FFmpeg解码H.264后AVFrame在MFC中显示黑屏求助
在MFC中显示FFmpeg解码后的AVFrame数据(黑屏问题排查与解决)
问题背景
你已经成功通过FFmpeg接收摄像头的H.264数据包并完成解码,保存为PPM、Bitmap文件时内容显示正常,但将解码数据输出到MFC界面时,却只显示黑屏,代码运行无报错。
问题分析与修复方案
从你提供的代码来看,核心问题出在像素数据缓冲区的绑定逻辑和消息传递的类型错误上,以下是具体的问题点和解决思路:
1. 像素缓冲区未正确绑定到位图内存
这是导致黑屏的最关键原因:你最初的代码使用av_malloc分配了独立的buffer作为av_image_fill_arrays的数据源,但sws_scale转换后的像素数据会被写入这个独立缓冲区,而不是CreateDIBSection创建的位图内存,导致位图始终为空。
修改后的正确写法是直接绑定CreateDIBSection返回的pbmpdata,让缩放后的BGR数据直接写入位图内存:
int err = av_image_fill_arrays( frameRGB->data, frameRGB->linesize, (uint8_t*)pbmpdata, // 直接绑定位图的内存地址 AV_PIX_FMT_BGR24, this->m_VideoCondecContext->width, this->m_VideoCondecContext->height, 1);
2. 消息传递的句柄类型错误
子线程发送消息时传递的是HBITMAP句柄本身,但消息处理函数错误地将其当作指针处理,导致无法正确获取位图信息:
// 子线程发送消息(正确传递句柄) ((CNetworkVideoViewerView*)(m_View))->SendMessage( UM_DISPLAYBITMAP, (WPARAM)hbmp); // 主线程消息处理(修正类型转换) afx_msg LRESULT CNetworkVideoViewerView::OnUmDisplaybitmap(WPARAM wParam, LPARAM lParam) { HBITMAP hBmp = (HBITMAP)wParam; // 直接转为HBITMAP,而非指针 CDC *dc = GetDC(); CDC memDC; memDC.CreateCompatibleDC(dc); BITMAP bmpInfo; GetObject(hBmp, sizeof(BITMAP), &bmpInfo); memDC.SelectObject(hBmp); dc->BitBlt(0, 0, bmpInfo.bmWidth, bmpInfo.bmHeight, &memDC, 0, 0, SRCCOPY); DeleteObject(hBmp); ReleaseDC(dc); return 0; }
3. 额外优化建议
- 避免子线程操作DC:MFC的CDC对象不是线程安全的,所有界面绘制操作都应该放在主线程的消息处理函数中完成,子线程只负责解码和数据传递。
- 资源复用:
SwsContext、AVFrame等资源可以提前初始化并复用,不需要每次解码循环都创建和销毁,能显著提升性能。 - 线程同步:确保
m_IsStreamAlive等线程共享变量的访问是线程安全的,避免竞态条件导致的异常。
解决结果
[2018.01.10 已解决] 按建议修改源码后,FFmpeg将缓冲空间替换为位图地址,画面显示正常。虽仍有部分待优化处,但已能正常显示。
内容的提问来源于stack exchange,提问作者심상원
相关产品推荐
相关产品推荐

