📄 videoiomgr.cpp
字号:
// VideoIOMgr.cpp: implementation of the CVideoIOMgr class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "MonClient.h"
#include "VideoIOMgr.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
class CMonClientDlg;
CVideoIOMgr* CVideoIOMgr::m_pInstance = NULL;
CVideoIOMgr* CVideoIOMgr::getInstance()
{
if(m_pInstance==NULL)
m_pInstance = new CVideoIOMgr();
return m_pInstance;
}
void CVideoIOMgr::releaseInstance()
{
if(m_pInstance)
{
delete m_pInstance;
m_pInstance = NULL;
}
}
CVideoIOMgr::CVideoIOMgr()
{
for(int i=0;i<SIZE_BUFFER_NUM;i++)
{
m_VBuff[i].id = 0;
m_VBuff[i].data_size=0;
m_VBuff[i].data_size_total=0;
}
m_pDlg = NULL;
for(i=0;i<4;i++)
m_IPArr[i]=0;
m_iport = 0;
m_pSocket= NULL;
}
CVideoIOMgr::~CVideoIOMgr()
{
}
void CVideoIOMgr::SetShowDlg(CMonClientDlg* pDlg)
{
m_pDlg = pDlg;
}
void CVideoIOMgr::InputVideoPack(AVIO_VIDEO *pVPack)
{
if(pVPack->flag != FLAG_VIDEO)
return;
//得到可用缓冲区
int itarbuf = GetReadyBuf(pVPack->id);
AVIO_VIDEO_BUFFER* pbuf = (AVIO_VIDEO_BUFFER*)&m_VBuff[itarbuf];
//把数据导入缓冲区
pbuf->id = pVPack->id;
pbuf->data_size_total = pVPack->data_size_total;
pbuf->data_size += pVPack->data_size;
BYTE* pdst = (BYTE*)&(pbuf->data[pVPack->subid*SIZE_VIDEO_PACKED]);
BYTE* psrc = (BYTE*)&(pVPack->data[0]);
memcpy(pdst,psrc,pVPack->data_size);
//输出调试信息
TRACE("目前缓冲区ID:%d 图像帧ID:%d SUBID:%d \n 当前帧中数据:%d 已接收数据大小:%d 总数据大小%d \n\n",itarbuf,pbuf->id,pVPack->subid,pVPack->data_size,pbuf->data_size,pbuf->data_size_total);
//判断已经接受到完整的图像帧,就显示,然后清空该缓冲区
if(pbuf->data_size == pbuf->data_size_total)
{
TRACE("\n**************************\n");
//发送并显示图像帧
if(m_pDlg)
{
BYTE* pdate = (BYTE*)&(pbuf->data[0]);
int ilen = pbuf->data_size_total;
m_pDlg->RcvPicData(pdate,ilen);
/*
int ifile = 0;
if(ifile<20)
ifile=0;
else
ifile++;
CString strFile;
strFile.Format("c:\\%d.jpg",ifile);
CFile file(strFile,CFile::modeCreate|CFile::modeWrite);
file.Write(pdate,ilen);
*/
pbuf->id = 0;
pbuf->data_size = 0;
pbuf->data_size_total = 0;
}
//清空缓冲区
pbuf->id = 0;
pbuf->data_size = 0;
pbuf->data_size_total = 0;
}
}
int CVideoIOMgr::GetReadyBuf(BYTE rcvid)
{
//**************判断该报应该放在那个缓冲区中*************
int itarbuf=-1;
//1.首先判断是否已经有该ID的帧缓冲区存在
for(int i=0;i<SIZE_BUFFER_NUM;i++)
{
if(m_VBuff[i].id==rcvid)
{
itarbuf=i;
break;
}
}
if(itarbuf>=0)
return itarbuf;
//2.如果判断该帧报为新报,则寻找新的空缓冲区.
//如果有空的缓冲区,则放置在该空缓冲区中
for(i=0;i<SIZE_BUFFER_NUM;i++)
{
if(m_VBuff[i].id==0)
{
itarbuf=i;
break;
}
}
if(itarbuf>=0)
{
m_VBuff[itarbuf].data_size = 0;
m_VBuff[itarbuf].data_size_total = 0;
return itarbuf;
}
//3.如果没有空缓冲区,则认为最老的缓冲区中保存了无效的数据,
//清空该缓冲区,并把数据放置在该缓冲区中
if(itarbuf==-1)
{
//得到最小的ID帧和最大的ID帧编号
BYTE imaxid = 0;
BYTE imaxbufid = 0;
BYTE iminid = 255;
BYTE iminbufid = 0;
for(i=0;i<SIZE_BUFFER_NUM;i++)
{
if(m_VBuff[i].id > imaxid)
{
imaxid = m_VBuff[i].id;
imaxbufid = i;
}
if(m_VBuff[i].id < iminid)
{
iminid = m_VBuff[i].id;
iminbufid = i;
}
}
//由最大最小帧ID判断当前最老的帧
if(imaxid - iminid > 128) //有环绕,则最大的ID代表最老的帧
{
itarbuf = imaxbufid;
}
else
{
itarbuf = iminbufid;
}
m_VBuff[itarbuf].data_size = 0;
m_VBuff[itarbuf].data_size_total = 0;
}
if(itarbuf<0)
itarbuf = 0;
return itarbuf;
}
void CVideoIOMgr::InitSocket(BYTE* IPArr,USHORT iport)
{
if(m_pSocket==NULL)
{
m_pSocket = new CSocket();
m_pSocket->Create(PORT_SOCKET_CLIENT,SOCK_DGRAM,"192.168.1.126");
m_pSocket->Bind(PORT_SOCKET_CLIENT,"192.168.1.126");
}
for(int i=0;i<4;i++)
{
m_IPArr[i] = *(IPArr+i);
}
m_iport = iport;
}
void CVideoIOMgr::RcvSocketData()
{
if(m_pSocket==NULL)
return;
CString strIP;
strIP.Format("%d.%d.%d.%d",m_IPArr[0],m_IPArr[1],m_IPArr[2],m_IPArr[3]);
UINT iport = m_iport;
AVIO_VIDEO videopack;
memset(&videopack,0,sizeof(AVIO_VIDEO));
int ilen = sizeof(videopack);
int iRecv = m_pSocket->ReceiveFrom((BYTE*)&videopack,ilen,strIP,iport,0);
if(iRecv>0)
{
//TRACE("接收到数据ID: %d 数据subID:%d 大小:%d \n",videopack.id,videopack.subid,videopack.data_size);
InputVideoPack(&videopack); //192.168.1.121
}
}
void CVideoIOMgr::Test()
{
typedef struct tagBITMAPFILEHEADER
{
WORD bfType; // 位图文件的类型,必须为BM
DWORD bfSize; // 位图文件的大小,以字节为单位
WORD bfReserved1; // 位图文件保留字,必须为0
WORD bfReserved2; // 位图文件保留字,必须为0
DWORD bfOffBits; // 位图数据的起始位置,以相对于位图
// 文件头的偏移量表示,以字节为单位
} BITMAPFILEHEADER;
// BMP位图信息头数据用于说明位图的尺寸等信息。
typedef struct tagBITMAPINFOHEADER{
DWORD biSize; // 本结构所占用字节数
LONG biWidth; // 位图的宽度,以像素为单位
LONG biHeight; // 位图的高度,以像素为单位
WORD biPlanes; // 目标设备的级别,必须为1
WORD biBitCount;// 每个像素所需的位数,必须是1(双色),
// 4(16色),8(256色)或24(真彩色)之一
DWORD biCompression; // 位图压缩类型,必须是 0(不压缩),
// 1(BI_RLE8压缩类型)或2(BI_RLE4压缩类型)之一
DWORD biSizeImage; // 位图的大小,以字节为单位
LONG biXPelsPerMeter; // 位图水平分辨率,每米像素数
LONG biYPelsPerMeter; // 位图垂直分辨率,每米像素数
DWORD biClrUsed;// 位图实际使用的颜色表中的颜色数
DWORD biClrImportant;// 位图显示过程中重要的颜色数
} BITMAPINFOHEADER;
int iwidth = 640;
int iheight = 480;
BITMAPFILEHEADER filehead;
filehead.bfType=19778;
filehead.bfReserved1=0;
filehead.bfReserved2=0;
filehead.bfOffBits=54;
filehead.bfSize=iwidth*iheight*3+54;
BITMAPINFOHEADER bmiHeader;
bmiHeader.biSize = 40;
bmiHeader.biWidth=iwidth;
bmiHeader.biHeight=iheight;
bmiHeader.biPlanes=1;
bmiHeader.biBitCount=8*3;
bmiHeader.biCompression=0;
bmiHeader.biSizeImage=iwidth*iheight*3;
bmiHeader.biXPelsPerMeter=3780;
bmiHeader.biYPelsPerMeter=3780;
bmiHeader.biClrImportant=0;
bmiHeader.biClrUsed=0;
WORD header[27] ;
memcpy(header,&filehead,sizeof(filehead));
memcpy(header+sizeof(filehead),&bmiHeader,sizeof(bmiHeader));
int ss = sizeof(bmiHeader) + sizeof(filehead);
int i=0;
i++;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -