最近在优化视频播放,原先使用.net+ocx(DirectX)进行接收视频流并展示到前端界面,在使用的过程中发现视频窗口多的话,容易分配内存失败并占用内存、GPU、CPU过高,不能满足客户的需要;
后来在优化的过程中,发现是使用DirextX导致的,在使用下面语句创建设备时经常创建失败,并且发现内存增长跟使用DirextX有关 。
- d3d9->CreateDevice(D3DADAPTER_DEFAULT,deviceType,hwnd,vp,&d3dpp,device);
采取了第二种方案进行优化,就想到了使用GDI进行播放,并且操作也比使用DirectX更加简单。
- if (m_pSwsContext == NULL)
- {
- m_pSwsContext = sws_getContext(w,h,m_pCodecContext->pix_fmt,w, h,AV_PIX_FMT_BGR24, SWS_FAST_BILINEAR,NULL, NULL, NULL);
- av_image_alloc(m_pFrameRGB->data, m_pFrameRGB->linesize,w, h, AV_PIX_FMT_BGR24,1);
- }
-
- sws_scale(m_pSwsContext,(uint8_t const * const *)m_pSrcFrame->data,
- m_pSrcFrame->linesize, 0, h, m_pFrameRGB->data,m_pFrameRGB->linesize);
-
- GetClientRect(m_hWnd, &recWindow);//获取窗口大小
- int width = recWindow.right - recWindow.left; //窗口的宽度
- int height = recWindow.bottom - recWindow.top; //窗口的高度
- HDC hdc = GetDC(m_hWnd);
- //转换成RGB24
- BITMAPINFO m_bmphdr = { 0 };
- DWORD dwBmpHdr = sizeof(BITMAPINFO);
- //24bit
- m_bmphdr.bmiHeader.biBitCount = 24;
- m_bmphdr.bmiHeader.biClrImportant = 0;
- m_bmphdr.bmiHeader.biSize = dwBmpHdr;
- m_bmphdr.bmiHeader.biSizeImage = 0;
- m_bmphdr.bmiHeader.biWidth = w;
- //Notice: BMP storage pixel data in opposite direction of Y-axis (from bottom to top).
- //So we must set reverse biHeight to show image correctly.m_bmphdr.bmiHeader.biHeight = -h;
- m_bmphdr.bmiHeader.biXPelsPerMeter = 0;
- m_bmphdr.bmiHeader.biYPelsPerMeter = 0;
- m_bmphdr.bmiHeader.biClrUsed = 0;
- m_bmphdr.bmiHeader.biPlanes = 1;
- m_bmphdr.bmiHeader.biCompression = BI_RGB;
- //Draw data
- //YUV420P data convert to another buffer
- SetStretchBltMode(hdc, STRETCH_HALFTONE);
- int nResult = StretchDIBits(hdc,
- 0, 0,
- width, height,
- 0, 0,
- w, h,
- m_pFrameRGB->data[0],
- &m_bmphdr,
- DIB_RGB_COLORS,
- SRCCOPY);
-
- //DeleteDC(hdc);
- ReleaseDC(m_hWnd, hdc);
- av_frame_unref(m_pSrcFrame);
- sws_freeContext(m_pSwsContext);
使用上述代码展示视频后,内存占用没有原来的的多了,并且使用到的GPU很少(一般客户那里的电脑没有GPU),视频十分流畅;上述代码中 SetStretchBltMode(hdc, STRETCH_HALFTONE);这一句非常重要,在测试阶段发现视频失真非常严重,导致画面十分难看,加上了这段代码后,视频质量提升了不少,播放效果大大提升。在使用ffmpeg的过程中,一定要小心内存泄漏,该释放的一定要释放。