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

H.265摄像头流解析异常:解码后画面半绿如何解决?

问题描述

我正在解析H.265摄像头流,通过live555的afterGettingFrame()获取帧数据,通过起始码0x00 0x00 0x00 0x01拆分NALU,并用以下代码判断I帧:

auto t = (buf[0] >> 1) & 0x3f;
return t == 19 || t == 20;

得到的NALU流日志如下(存在同时间戳帧):

log info Frame: time=1691746190593, key=true, duration=25230, size=50338
log info Frame: time=1691746190593, key=true, duration=3163, size=3464
log info Frame: time=1691746190713, key=false, duration=37765, size=480
log info Frame: time=1691746190713, key=false, duration=998, size=3274
log info Frame: time=1691746190713, key=false, duration=711, size=420
log info Frame: time=1691746190793, key=false, duration=115679, size=322
log info Frame: time=1691746190793, key=false, duration=1533, size=2437
log info Frame: time=1691746190793, key=false, duration=842, size=286
log info Frame: time=1691746190913, key=false, duration=77556, size=287
log info Frame: time=1691746190913, key=false, duration=1322, size=2693
log info Frame: time=1691746190913, key=false, duration=2059, size=216
log info Frame: time=1691746190993, key=false, duration=117100, size=258
log info Frame: time=1691746190993, key=false, duration=3076, size=2486
log info Frame: time=1691746190993, key=false, duration=396, size=211
log info Frame: time=1691746191113, key=false, duration=81118, size=23
log info Frame: time=1691746191113, key=false, duration=377, size=64
log info Frame: time=1691746191113, key=false, duration=3962, size=10
log info Frame: time=1691746191113, key=true, duration=5140, size=5069
log info Frame: time=1691746191113, key=true, duration=2797, size=49916
log info Frame: time=1691746191113, key=true, duration=1949, size=3493
log info Frame: time=1691746191193, key=false, duration=101536, size=429
log info Frame: time=1691746191193, key=false, duration=1158, size=3186
log info Frame: time=1691746191193, key=false, duration=1146, size=350
log info Frame: time=1691746191313, key=false, duration=77701, size=332

尝试过按时间戳拼接或单独解析,均未成功。使用原H.264解码代码:

AVPacket avpkt;
av_init_packet(&avpkt);
avpkt.pts = 0;
avpkt.dts = 0;
avpkt.data = data;
avpkt.size = size;

int gotFrame = false;

while (avpkt.size > 0)
{
  // We must use positive result to move through the data buffer
  auto len = avcodec_decode_video2(av_context_, av_frame_, &gotFrame, &avpkt);
  if (len < 0)
  {
    break;
  }

  avpkt.data += len;
  avpkt.size -= len;
}

代码返回gotFrame=true,但生成的JPEG画面出现半绿情况,求正确的H.265流解析方式。

正确的H.265流解析及解码方案

1. 优先处理关键参数集(VPS/SPS/PPS)

H.265解码必须先获取并送入**VPS(视频参数集)、SPS(序列参数集)、PPS(图像参数集)**三类NALU,否则解码器无法完成初始化,直接导致画面异常(如半绿):

  • 三类NALU的类型标识分别为:VPS=32,SPS=33,PPS=34
  • 通过(buf[0] >> 1) & 0x3f判断类型,在解码前先将这些参数集送入解码器。

2. 正确处理同时间戳的NALU

同时间戳的帧是同一编码帧的分片NALU,必须按顺序拼接成完整帧数据后再送入解码器,不能单独解析:

  • 拼接时保留每个NALU的起始码0x00 0x00 0x00 0x01,或直接拼接起始码后的payload部分,解码器两种方式均支持,保留起始码兼容性更好。

3. 替换为H.265专用解码器

原代码针对H.264设计,必须修改解码器初始化逻辑:

  • 指定codec_id为AV_CODEC_ID_HEVC
  • 示例初始化代码:
AVCodec* codec = avcodec_find_decoder(AV_CODEC_ID_HEVC);
AVCodecContext* av_context_ = avcodec_alloc_context3(codec);
av_context_->thread_count = 4; // 根据CPU核心数调整
if (avcodec_open2(av_context_, codec, nullptr) < 0) {
    // 初始化失败处理逻辑
}

4. 使用新版解码API替代废弃接口

avcodec_decode_video2已被废弃,H.265解码建议使用avcodec_send_packet和avcodec_receive_frame,流程更稳定:

AVPacket avpkt;
av_init_packet(&avpkt);
// 将live555时间戳转换为FFmpeg时间基准单位
avpkt.pts = av_rescale_q(live555_timestamp, AV_TIME_BASE_Q, av_context_->time_base);
avpkt.dts = avpkt.pts; // 无B帧场景下dts与pts一致
avpkt.data = data;
avpkt.size = size;

int ret = avcodec_send_packet(av_context_, &avpkt);
if (ret == 0) {
    while (ret >= 0) {
        ret = avcodec_receive_frame(av_context_, av_frame_);
        if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF) {
            break;
        } else if (ret < 0) {
            // 解码错误处理逻辑
            break;
        }
        // 处理解码后的帧(如转换为JPEG)
        convert_frame_to_jpeg(av_frame_);
    }
}
av_packet_unref(&avpkt);

5. 禁止硬设时间戳为0

必须使用live555获取的原始时间戳,转换为FFmpeg的时间基准(AV_TIME_BASE),否则解码器时序逻辑异常,会导致画面问题。

内容的提问来源于stack exchange,提问作者denn

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 23:45:56