You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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,提问作者심상원

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:36:46