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

使用FFmpeg 4.0的avcodec_decode_video2解码RTSP H264视频出错求助

解决FFmpeg 4.0中avcodec_decode_video2解码RTSP H264高清视频的错误问题

结合你提供的代码和FFmpeg 4.0的特性,我整理了几个针对性的排查和修复方向,帮你解决高清H264解码出错的问题:

一、补全解码上下文的关键配置

高清H264(如1080P/4K)解码对上下文配置有更高要求,你当前仅复制原始Codec上下文,可能漏掉了关键设置:

  • 启用多线程解码:高清流单线程解码容易出现性能瓶颈或错误,根据CPU核心数设置线程数
  • 启用帧引用计数:避免内存异常导致的解码失败
  • 实时流低延迟配置:适配RTSP实时传输特性

修改代码中复制上下文后的逻辑:

if(avcodec_copy_context(pCodecCtx, pCodecCtxOrig) != 0) {
    fGrabb=-5; // Error copying codec context
} else {
    // 添加高清解码必备配置
    pCodecCtx->thread_count = av_cpu_count(); // 自动匹配CPU核心数
    pCodecCtx->refcounted_frames = 1; // 启用帧引用计数,避免内存问题
    pCodecCtx->flags |= AV_CODEC_FLAG_LOW_DELAY; // 适配RTSP实时流的低延迟需求
    
    // Open codec
    if(avcodec_open2(pCodecCtx, pCodec, NULL)<0) {
        fGrabb=-6; // Could not open codec
    }
    // ... 后续帧分配等代码
}

二、修复RTSP流的数据包处理问题

RTSP实时流存在数据包乱序、丢包或时间戳缺失的可能,会直接导致解码失败:

  • 让FFmpeg自动生成缺失的时间戳,避免时序错误
  • 不要跳过任何视频数据包,哪怕看起来无效

在打开输入流后添加配置:

if(avformat_open_input(&pFormatCtx, nameVideoStream, NULL, NULL)!=0) {
    fGrabb=-1; // Couldn't open file
} else {
    // 让FFmpeg自动生成缺失的时间戳,适配RTSP流
    pFormatCtx->flags |= AVFMT_FLAG_GENPTS;
    // Retrieve stream information
    if(avformat_find_stream_info(pFormatCtx, NULL)<0) {
        fGrabb=-2; // Couldn't find stream information
    }
    // ... 后续找视频流等代码
}

三、完善解码错误的检测与处理

你的代码未检查avcodec_decode_video2的返回值,无法及时捕获解码错误并处理:

int len = avcodec_decode_video2(pCodecCtx, pFrame, &frameFinished, &packet);
if (len < 0) {
    // 打印错误信息,方便定位问题
    char errbuf[1024];
    av_strerror(len, errbuf, sizeof(errbuf));
    // 这里可以加入日志记录逻辑
    av_free_packet(&packet);
    continue; // 跳过错误包,继续处理下一个
}
nPacket++;
// Did we get a video frame?
if(frameFinished) {
    // ... 格式转换与窗口显示代码
}

四、修复过时API与资源泄漏问题

FFmpeg 4.0中部分API已过时,不正确的资源释放会间接导致解码不稳定:

  • 用av_packet_unref(&packet)替代过时的av_free_packet(&packet)
  • 确保所有分配的资源在退出时完全释放

在函数末尾补充资源释放逻辑:

// 释放缩放上下文
sws_freeContext(sws_ctx_to_RGB);
sws_freeContext(sws_ctx_to_YUV);
// 释放缓冲区
av_free(buffer);
av_free(bufferRGB);
av_free(bufferYUV);
// 释放格式上下文与解码上下文
avformat_close_input(&pFormatCtx);
avcodec_free_context(&pCodecCtx);

五、推荐替换为更稳定的新解码API

FFmpeg 4.0中avcodec_decode_video2已被标记为过时,新的avcodec_send_packet+avcodec_receive_frameAPI对高清流的兼容性更好,替换解码循环逻辑:

while ((fGrabb==1)||(fGrabb==100)) {
    if (av_read_frame(pFormatCtx, &packet) >= 0) {
        if(packet.stream_index==videoStream) {
            int ret = avcodec_send_packet(pCodecCtx, &packet);
            if (ret == AVERROR(EAGAIN)) {
                // 需要更多数据,继续等待
            } else if (ret < 0) {
                char errbuf[1024];
                av_strerror(ret, errbuf, sizeof(errbuf));
                // 记录错误信息
                av_packet_unref(&packet);
                continue;
            }
            // 循环接收解码后的帧(可能一次解码多帧)
            while (ret >= 0) {
                ret = avcodec_receive_frame(pCodecCtx, pFrame);
                if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
                    break;
                } else if (ret < 0) {
                    char errbuf[1024];
                    av_strerror(ret, errbuf, sizeof(errbuf));
                    // 记录错误信息
                    break;
                }
                // 解码成功,执行格式转换与显示逻辑
                sws_scale(sws_ctx_to_YUV, (uint8_t const * const *)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameYUV->data, pFrameYUV->linesize);
                sws_scale(sws_ctx_to_RGB, (uint8_t const * const *)pFrame->data, pFrame->linesize, 0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize);
                
                HDC hdc=GetDC(hWndM);
                SetDIBitsToDevice(hdc, 0, 0, pCodecCtx->width, pCodecCtx->height, 0, 0, 0, pCodecCtx->height,pFrameRGB->data[0], (LPBITMAPINFO)&RealBsqHdr, DIB_RGB_COLORS);
                ReleaseDC(hWndM,hdc);
                
                av_frame_unref(pFrame);
            }
        }
        av_packet_unref(&packet);
    }
}

建议你先添加错误日志打印,用av_strerror把错误码转换为可读信息,这样能更精准定位是解码失败、数据包问题还是资源不足导致的错误。

内容的提问来源于stack exchange,提问作者Nguyen Ba Thi

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:48:31