2026-01-02 20:00:18 +01:00
|
|
|
|
// VideoDlg.cpp : 实现文件
|
2019-01-05 20:21:43 +08:00
|
|
|
|
//
|
|
|
|
|
|
|
|
|
|
|
|
#include "stdafx.h"
|
|
|
|
|
|
#include "2015Remote.h"
|
|
|
|
|
|
#include "VideoDlg.h"
|
|
|
|
|
|
#include "afxdialogex.h"
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-10-15 04:32:59 +08:00
|
|
|
|
enum {
|
2026-01-02 20:00:18 +01:00
|
|
|
|
IDM_ENABLECOMPRESS = 0x0010, // 视频压缩
|
|
|
|
|
|
IDM_SAVEAVI, // 保存录像
|
2019-01-05 20:21:43 +08:00
|
|
|
|
};
|
2026-01-02 20:00:18 +01:00
|
|
|
|
// CVideoDlg 对话框
|
2019-01-05 20:21:43 +08:00
|
|
|
|
|
|
|
|
|
|
IMPLEMENT_DYNAMIC(CVideoDlg, CDialog)
|
|
|
|
|
|
|
2019-01-26 10:35:10 +08:00
|
|
|
|
|
|
|
|
|
|
void CVideoDlg::SaveAvi(void)
|
|
|
|
|
|
{
|
2025-10-15 04:32:59 +08:00
|
|
|
|
CMenu *pSysMenu = GetSystemMenu(FALSE);
|
|
|
|
|
|
if (pSysMenu->GetMenuState(IDM_SAVEAVI, MF_BYCOMMAND) & MF_CHECKED) {
|
|
|
|
|
|
pSysMenu->CheckMenuItem(IDM_SAVEAVI, MF_UNCHECKED);
|
|
|
|
|
|
m_aviFile.Empty();
|
|
|
|
|
|
m_aviStream.Close();
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
CString strFileName = m_IPAddress + CTime::GetCurrentTime().Format("_%Y-%m-%d_%H-%M-%S.avi");
|
2026-01-02 20:00:18 +01:00
|
|
|
|
CFileDialog dlg(FALSE, "avi", strFileName, OFN_OVERWRITEPROMPT, "视频文件(*.avi)|*.avi|", this);
|
2025-10-15 04:32:59 +08:00
|
|
|
|
if(dlg.DoModal () != IDOK)
|
|
|
|
|
|
return;
|
|
|
|
|
|
m_aviFile = dlg.GetPathName();
|
2025-11-23 10:57:52 +01:00
|
|
|
|
int code;
|
|
|
|
|
|
if (code = m_aviStream.Open(m_aviFile, m_BitmapInfor_Full)) {
|
2026-01-02 20:00:18 +01:00
|
|
|
|
MessageBox("创建录像文件失败:"+m_aviFile + "\r\n错误代码: " + CBmpToAvi::GetErrMsg(code).c_str(), "提示");
|
2025-10-15 04:32:59 +08:00
|
|
|
|
m_aviFile.Empty();
|
|
|
|
|
|
} else {
|
|
|
|
|
|
pSysMenu->CheckMenuItem(IDM_SAVEAVI, MF_CHECKED);
|
|
|
|
|
|
}
|
2019-01-26 10:35:10 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-06-29 21:25:59 +08:00
|
|
|
|
CVideoDlg::CVideoDlg(CWnd* pParent, Server* IOCPServer, CONTEXT_OBJECT *ContextObject)
|
2025-10-15 04:32:59 +08:00
|
|
|
|
: DialogBase(CVideoDlg::IDD, pParent, IOCPServer, ContextObject, IDI_ICON_CAMERA)
|
2019-01-05 20:21:43 +08:00
|
|
|
|
{
|
2025-10-15 04:32:59 +08:00
|
|
|
|
m_nCount = 0;
|
|
|
|
|
|
m_aviFile.Empty();
|
|
|
|
|
|
m_BitmapInfor_Full = NULL;
|
|
|
|
|
|
m_pVideoCodec = NULL;
|
|
|
|
|
|
|
|
|
|
|
|
m_BitmapData_Full = NULL;
|
|
|
|
|
|
m_BitmapCompressedData_Full = NULL;
|
|
|
|
|
|
ResetScreen();
|
2019-01-05 20:21:43 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void CVideoDlg::ResetScreen(void)
|
|
|
|
|
|
{
|
2025-10-15 04:32:59 +08:00
|
|
|
|
if (m_BitmapInfor_Full) {
|
|
|
|
|
|
delete m_BitmapInfor_Full;
|
|
|
|
|
|
m_BitmapInfor_Full = NULL;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int iBitMapInforSize = m_ContextObject->InDeCompressedBuffer.GetBufferLength() - 1;
|
|
|
|
|
|
m_BitmapInfor_Full = (LPBITMAPINFO) new BYTE[iBitMapInforSize];
|
|
|
|
|
|
m_ContextObject->InDeCompressedBuffer.CopyBuffer(m_BitmapInfor_Full, iBitMapInforSize, 1);
|
|
|
|
|
|
m_BitmapData_Full = new BYTE[m_BitmapInfor_Full->bmiHeader.biSizeImage];
|
|
|
|
|
|
m_BitmapCompressedData_Full = new BYTE[m_BitmapInfor_Full->bmiHeader.biSizeImage];
|
2019-01-05 20:21:43 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
CVideoDlg::~CVideoDlg()
|
|
|
|
|
|
{
|
2025-10-15 04:32:59 +08:00
|
|
|
|
if (!m_aviFile.IsEmpty()) {
|
|
|
|
|
|
SaveAvi();
|
|
|
|
|
|
m_aviFile.Empty();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (m_pVideoCodec) {
|
|
|
|
|
|
delete m_pVideoCodec;
|
|
|
|
|
|
m_pVideoCodec = NULL;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (m_BitmapData_Full) {
|
|
|
|
|
|
delete m_BitmapData_Full;
|
|
|
|
|
|
m_BitmapData_Full = NULL;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (m_BitmapInfor_Full) {
|
|
|
|
|
|
delete m_BitmapInfor_Full;
|
|
|
|
|
|
m_BitmapInfor_Full = NULL;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (m_BitmapCompressedData_Full) {
|
|
|
|
|
|
delete m_BitmapCompressedData_Full;
|
|
|
|
|
|
m_BitmapCompressedData_Full = NULL;
|
|
|
|
|
|
}
|
2019-01-05 20:21:43 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CVideoDlg::DoDataExchange(CDataExchange* pDX)
|
|
|
|
|
|
{
|
2025-10-15 04:32:59 +08:00
|
|
|
|
CDialog::DoDataExchange(pDX);
|
2019-01-05 20:21:43 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BEGIN_MESSAGE_MAP(CVideoDlg, CDialog)
|
2025-10-15 04:32:59 +08:00
|
|
|
|
ON_WM_CLOSE()
|
|
|
|
|
|
ON_WM_SYSCOMMAND()
|
|
|
|
|
|
ON_WM_PAINT()
|
2019-01-05 20:21:43 +08:00
|
|
|
|
END_MESSAGE_MAP()
|
|
|
|
|
|
|
|
|
|
|
|
|
2026-01-02 20:00:18 +01:00
|
|
|
|
// CVideoDlg 消息处理程序
|
2019-01-05 20:21:43 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
BOOL CVideoDlg::OnInitDialog()
|
|
|
|
|
|
{
|
2025-10-15 04:32:59 +08:00
|
|
|
|
CDialog::OnInitDialog();
|
2019-01-05 20:21:43 +08:00
|
|
|
|
|
2025-10-15 04:32:59 +08:00
|
|
|
|
CMenu* SysMenu = GetSystemMenu(FALSE);
|
|
|
|
|
|
if (SysMenu != NULL) {
|
|
|
|
|
|
m_hDD = DrawDibOpen();
|
2019-01-05 20:21:43 +08:00
|
|
|
|
|
2025-10-15 04:32:59 +08:00
|
|
|
|
m_hDC = ::GetDC(m_hWnd);
|
2026-01-02 20:00:18 +01:00
|
|
|
|
SysMenu->AppendMenu(MF_STRING, IDM_ENABLECOMPRESS, "视频压缩(&C)");
|
|
|
|
|
|
SysMenu->AppendMenu(MF_STRING, IDM_SAVEAVI, "保存录像(&V)");
|
2025-10-15 04:32:59 +08:00
|
|
|
|
SysMenu->AppendMenu(MF_SEPARATOR);
|
2019-01-05 20:21:43 +08:00
|
|
|
|
|
2025-10-15 04:32:59 +08:00
|
|
|
|
CString strString;
|
2019-01-05 20:21:43 +08:00
|
|
|
|
|
2026-01-02 20:00:18 +01:00
|
|
|
|
strString.Format("%s - 视频管理 %d×%d", m_IPAddress, m_BitmapInfor_Full->bmiHeader.biWidth, m_BitmapInfor_Full->bmiHeader.biHeight);
|
2019-01-05 20:21:43 +08:00
|
|
|
|
|
2025-10-15 04:32:59 +08:00
|
|
|
|
SetWindowText(strString);
|
2019-01-05 20:21:43 +08:00
|
|
|
|
|
2025-10-15 04:32:59 +08:00
|
|
|
|
BYTE bToken = COMMAND_NEXT;
|
2019-01-05 20:21:43 +08:00
|
|
|
|
|
2025-10-15 04:32:59 +08:00
|
|
|
|
m_ContextObject->Send2Client(&bToken, sizeof(BYTE));
|
|
|
|
|
|
}
|
2019-01-05 20:21:43 +08:00
|
|
|
|
|
2025-10-15 04:32:59 +08:00
|
|
|
|
SetIcon(m_hIcon, TRUE);
|
|
|
|
|
|
SetIcon(m_hIcon, FALSE);
|
2019-01-26 14:05:37 +08:00
|
|
|
|
|
2025-10-15 04:32:59 +08:00
|
|
|
|
return TRUE;
|
2019-01-05 20:21:43 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CVideoDlg::OnClose()
|
|
|
|
|
|
{
|
2025-10-15 04:32:59 +08:00
|
|
|
|
CancelIO();
|
2026-01-02 20:00:18 +01:00
|
|
|
|
// 等待数据处理完毕
|
2025-10-15 04:32:59 +08:00
|
|
|
|
if (IsProcessing()) {
|
|
|
|
|
|
ShowWindow(SW_HIDE);
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (!m_aviFile.IsEmpty()) {
|
|
|
|
|
|
SaveAvi();
|
|
|
|
|
|
m_aviFile.Empty();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
DialogBase::OnClose();
|
2019-01-05 20:21:43 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CVideoDlg::OnReceiveComplete(void)
|
|
|
|
|
|
{
|
2025-10-15 04:32:59 +08:00
|
|
|
|
++m_nCount;
|
|
|
|
|
|
|
|
|
|
|
|
switch (m_ContextObject->InDeCompressedBuffer.GetBYTE(0)) {
|
|
|
|
|
|
case TOKEN_WEBCAM_DIB: {
|
2026-01-02 20:00:18 +01:00
|
|
|
|
DrawDIB();//这里是绘图函数,转到他的代码看一下
|
2025-10-15 04:32:59 +08:00
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
default:
|
2026-01-02 20:00:18 +01:00
|
|
|
|
// 传输发生异常数据
|
2025-10-15 04:32:59 +08:00
|
|
|
|
break;
|
|
|
|
|
|
}
|
2019-01-05 20:21:43 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void CVideoDlg::DrawDIB(void)
|
|
|
|
|
|
{
|
2025-10-15 04:32:59 +08:00
|
|
|
|
CMenu* SysMenu = GetSystemMenu(FALSE);
|
|
|
|
|
|
if (SysMenu == NULL)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
const int nHeadLen = 1 + 1 + 4;
|
|
|
|
|
|
|
|
|
|
|
|
Buffer tmp = m_ContextObject->InDeCompressedBuffer.GetMyBuffer(0);
|
|
|
|
|
|
LPBYTE szBuffer = tmp.Buf();
|
|
|
|
|
|
UINT ulBufferLen = m_ContextObject->InDeCompressedBuffer.GetBufferLength();
|
2026-01-02 20:00:18 +01:00
|
|
|
|
if (szBuffer[1] == 0) { // 没有经过H263压缩的原始数据,不需要解码
|
|
|
|
|
|
// 第一次,没有压缩,说明服务端不支持指定的解码器
|
2025-10-15 04:32:59 +08:00
|
|
|
|
if (m_nCount == 1) {
|
|
|
|
|
|
SysMenu->EnableMenuItem(IDM_ENABLECOMPRESS, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
|
|
|
|
|
|
}
|
|
|
|
|
|
SysMenu->CheckMenuItem(IDM_ENABLECOMPRESS, MF_UNCHECKED);
|
|
|
|
|
|
memcpy(m_BitmapData_Full, szBuffer + nHeadLen, ulBufferLen - nHeadLen);
|
2026-01-02 20:00:18 +01:00
|
|
|
|
} else { // 解码
|
|
|
|
|
|
////这里缓冲区里的的第二个字符正好是是否视频解码
|
|
|
|
|
|
InitCodec(*(LPDWORD)(szBuffer + 2)); //判断
|
2025-10-15 04:32:59 +08:00
|
|
|
|
if (m_pVideoCodec != NULL) {
|
|
|
|
|
|
SysMenu->CheckMenuItem(IDM_ENABLECOMPRESS, MF_CHECKED);
|
2026-01-02 20:00:18 +01:00
|
|
|
|
memcpy(m_BitmapCompressedData_Full, szBuffer + nHeadLen, ulBufferLen - nHeadLen); //视频没有解压
|
|
|
|
|
|
//这里开始解码,解码后就是同未压缩的一样了 显示到对话框上。 接下来开始视频保存成avi格式
|
2025-10-15 04:32:59 +08:00
|
|
|
|
m_pVideoCodec->DecodeVideoData(m_BitmapCompressedData_Full, ulBufferLen - nHeadLen,
|
2026-01-02 20:00:18 +01:00
|
|
|
|
(LPBYTE)m_BitmapData_Full, NULL, NULL); //将视频数据解压
|
2025-10-15 04:32:59 +08:00
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
PostMessage(WM_PAINT);
|
2019-01-05 20:21:43 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void CVideoDlg::InitCodec(DWORD fccHandler)
|
|
|
|
|
|
{
|
2025-10-15 04:32:59 +08:00
|
|
|
|
if (m_pVideoCodec != NULL)
|
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
m_pVideoCodec = new CVideoCodec;
|
|
|
|
|
|
if (!m_pVideoCodec->InitCompressor(m_BitmapInfor_Full, fccHandler)) {
|
|
|
|
|
|
Mprintf("======> InitCompressor failed \n");
|
|
|
|
|
|
delete m_pVideoCodec;
|
2026-01-02 20:00:18 +01:00
|
|
|
|
// 置NULL, 发送时判断是否为NULL来判断是否压缩
|
2025-10-15 04:32:59 +08:00
|
|
|
|
m_pVideoCodec = NULL;
|
2026-01-02 20:00:18 +01:00
|
|
|
|
// 通知服务端不启用压缩
|
2025-10-15 04:32:59 +08:00
|
|
|
|
BYTE bToken = COMMAND_WEBCAM_DISABLECOMPRESS;
|
|
|
|
|
|
m_ContextObject->Send2Client(&bToken, sizeof(BYTE));
|
|
|
|
|
|
GetSystemMenu(FALSE)->EnableMenuItem(IDM_ENABLECOMPRESS, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
|
|
|
|
|
|
}
|
2019-01-05 20:21:43 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void CVideoDlg::OnSysCommand(UINT nID, LPARAM lParam)
|
|
|
|
|
|
{
|
2026-01-02 20:00:18 +01:00
|
|
|
|
// TODO: 在此添加消息处理程序代码和/或调用默认值
|
2025-10-15 04:32:59 +08:00
|
|
|
|
switch (nID) {
|
|
|
|
|
|
case IDM_SAVEAVI: {
|
|
|
|
|
|
SaveAvi();
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
case IDM_ENABLECOMPRESS: {
|
|
|
|
|
|
CMenu *pSysMenu = GetSystemMenu(FALSE);
|
|
|
|
|
|
bool bIsChecked = pSysMenu->GetMenuState(IDM_ENABLECOMPRESS, MF_BYCOMMAND) & MF_CHECKED;
|
|
|
|
|
|
pSysMenu->CheckMenuItem(IDM_ENABLECOMPRESS, bIsChecked ? MF_UNCHECKED : MF_CHECKED);
|
|
|
|
|
|
bIsChecked = !bIsChecked;
|
|
|
|
|
|
BYTE bToken = COMMAND_WEBCAM_ENABLECOMPRESS;
|
|
|
|
|
|
if (!bIsChecked)
|
|
|
|
|
|
bToken = COMMAND_WEBCAM_DISABLECOMPRESS;
|
|
|
|
|
|
m_ContextObject->Send2Client(&bToken, sizeof(BYTE));
|
|
|
|
|
|
break;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
CDialog::OnSysCommand(nID, lParam);
|
2019-01-05 20:21:43 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void CVideoDlg::OnPaint()
|
|
|
|
|
|
{
|
2025-10-15 04:32:59 +08:00
|
|
|
|
CPaintDC dc(this); // device context for painting
|
|
|
|
|
|
|
|
|
|
|
|
if (m_BitmapData_Full==NULL) {
|
|
|
|
|
|
return;
|
|
|
|
|
|
}
|
|
|
|
|
|
RECT rect;
|
|
|
|
|
|
GetClientRect(&rect);
|
|
|
|
|
|
|
|
|
|
|
|
DrawDibDraw
|
|
|
|
|
|
(
|
|
|
|
|
|
m_hDD,
|
|
|
|
|
|
m_hDC,
|
|
|
|
|
|
0, 0,
|
|
|
|
|
|
rect.right, rect.bottom,
|
|
|
|
|
|
(LPBITMAPINFOHEADER)m_BitmapInfor_Full,
|
|
|
|
|
|
m_BitmapData_Full,
|
|
|
|
|
|
0, 0,
|
|
|
|
|
|
m_BitmapInfor_Full->bmiHeader.biWidth, m_BitmapInfor_Full->bmiHeader.biHeight,
|
|
|
|
|
|
DDF_SAME_HDC
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
if (!m_aviFile.IsEmpty()) {
|
|
|
|
|
|
m_aviStream.Write(m_BitmapData_Full);
|
2026-01-02 20:00:18 +01:00
|
|
|
|
// 提示正在录像
|
2025-10-15 04:32:59 +08:00
|
|
|
|
SetBkMode(m_hDC, TRANSPARENT);
|
|
|
|
|
|
SetTextColor(m_hDC, RGB(0xff,0x00,0x00));
|
|
|
|
|
|
const LPCTSTR lpTipsString = "Recording";
|
|
|
|
|
|
TextOut(m_hDC, 0, 0, lpTipsString, lstrlen(lpTipsString));
|
|
|
|
|
|
}
|
2019-01-05 20:21:43 +08:00
|
|
|
|
}
|