ffmpeg H264转码为RGB24,并使用GDI进行播放

       最近在优化视频播放,原先使用.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的过程中,一定要小心内存泄漏,该释放的一定要释放。

你可能感兴趣的:(C++)