對軟件客戶區進行視頻錄製,採用截圖+壓縮至avi的做法壓縮代碼

https://blog.csdn.net/immortal_mcl


壓縮代碼:
void CRobotAppView::OnTimer(UINT_PTR nIDEvent)
{
// TODO: 在此添加消息處理程序代碼和/或調用默認值

if(m_timer)//如果上一次的定時器程序已經運行完,才執行下面的代碼
{
m_timer=FALSE;//本次定時,正在運行,未結束前,不得進行下次運行
CView* pView;
CMDIFrameWnd *pFrame = (CMDIFrameWnd*)AfxGetApp()->GetMainWnd();
  CMDIChildWnd *pChild = (CMDIChildWnd*)pFrame->GetActiveFrame();
  pView = (CRobotAppView*)pChild->GetActiveView();
CRect rc;
pView->GetWindowRect(rc);
         CDC * pClientDC =pView->GetDC();
CDC  memDC;//定義一個內存畫布
memDC.CreateCompatibleDC(pClientDC);//創建一個兼容的畫布
CBitmap bmp;
bmp.CreateCompatibleBitmap(pClientDC,rc.Width(),rc.Height());//創建兼容位圖
memDC.SelectObject(&bmp);//選中位圖對象
BITMAP bitmap;
bmp.GetBitmap(&bitmap);
CDC* pDeskDC =GetDesktopWindow()->GetDC();//獲取桌面畫布對象  獲取桌面窗口上下文環境的指針(句柄)

memDC.BitBlt(0,0,bitmap.bmWidth,bitmap.bmHeight,pDeskDC,rc.left,rc.top,SRCCOPY);

DWORD size=bitmap.bmWidthBytes * bitmap.bmHeight;//屏幕圖像的總像素數
lpData = new BYTE[size];
int panelsize  = 0; //記錄調色板大小
if(bitmap.bmBitsPixel<16)//判斷是否爲真彩色位圖
panelsize = (int)pow((float)2,(int)(bitmap.bmBitsPixel*sizeof(RGBQUAD)));
//填充BITMAPFILEHEADER
BITMAPFILEHEADER bitmapFileHeader;
memset(&bitmapFileHeader,0,sizeof(BITMAPFILEHEADER));
bitmapFileHeader.bfSize = sizeof(BITMAPFILEHEADER);
bitmapFileHeader.bfType = 0x4d42; //BM

bitmapFileHeader.bfOffBits =sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER);


BITMAPINFOHEADER *pBInfo = new BITMAPINFOHEADER;//定義位圖信息頭結構體
//初始化位圖信息頭
pBInfo->biBitCount       = bitmap.bmBitsPixel;
pBInfo->biClrImportant   = 0;
pBInfo->biCompression    = 0;
pBInfo->biHeight         = bitmap.bmHeight;
pBInfo->biPlanes         = bitmap.bmPlanes;
pBInfo->biSize           = sizeof(BITMAPINFOHEADER);
pBInfo->biSizeImage      = bitmap.bmWidthBytes*bitmap.bmHeight;
pBInfo->biWidth          = bitmap.bmWidth;
pBInfo->biXPelsPerMeter  = 0;
pBInfo->biYPelsPerMeter  = 0;
BITMAPINFO bInfo;//定義位圖信息結構體
bInfo.bmiHeader = *pBInfo;//初始化

GetDIBits(memDC.m_hDC,bmp,0, pBInfo->biHeight,lpData,&bInfo,DIB_RGB_COLORS);// 獲取屏幕位圖的DIB數據(生成avi需要),保存到lpdata


if(nFrames == 0)//如果是第一幀
{
AVISTREAMINFO strhdr;//視頻數據流結構
AVIFileOpen(&pfile,m_VedioName,OF_WRITE | OF_CREATE,NULL);//打開或創建AVI文件
/////////////初始化AVI視頻流信息結構體
memset(&strhdr, 0, sizeof(strhdr));//初始化信息頭爲0
strhdr.fccType    = streamtypeVIDEO;
strhdr.fccHandler = mmioStringToFOURCC(_T("MSVC"), 0);  
strhdr.dwScale    = 1;
strhdr.dwRate     = m_VedioFrame;
strhdr.dwSuggestedBufferSize = pBInfo->biSizeImage;
SetRect(&strhdr.rcFrame,0,0,pBInfo->biWidth,pBInfo->biHeight);
AVIFileCreateStream(pfile,&pS,&strhdr);//創建AVI文件流

//設置壓縮選項,創建壓縮流 
AVICOMPRESSOPTIONS pCompressOption;   
AVICOMPRESSOPTIONS* opts[1] = {&pCompressOption}; 
memset(&pCompressOption,0,sizeof(pCompressOption));
opts[0]->fccType = streamtypeVIDEO;
opts[0]->fccHandler = mmioStringToFOURCC(_T("MSVC"), 0);
opts[0]->dwQuality = 10000;//original :7500
opts[0]->dwBytesPerSecond = 1000;//original :0
opts[0]->dwFlags = AVICOMPRESSF_VALID || AVICOMPRESSF_KEYFRAMES;
opts[0]->lpFormat = 0;
opts[0]->cbFormat = 0;
AVIMakeCompressedStream(&pComStream,pS,&pCompressOption,NULL); 
AVIStreamSetFormat(pComStream,0,pBInfo,sizeof(BITMAPINFOHEADER));
}
AVIStreamWrite(pComStream,nFrames ,1,(LPBYTE)lpData,pBInfo->biSizeImage,AVIIF_KEYFRAME,NULL,NULL);//將桌面圖像數據寫入文件
nFrames++;//增加一幀
delete []lpData;//釋放內存
delete pBInfo ; //釋放內存
ReleaseDC(pClientDC);
ReleaseDC(pDeskDC);
ReleaseDC(&memDC);
m_timer=TRUE;//定時器程序可以繼續響應

}
CBaseView::OnTimer(nIDEvent);
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章