ffmpeg: ff_hevc_set_new_ref :设置新的参考帧

22 阅读3分钟

在 FFmpeg 中的 ff_hevc_set_new_ref 函数是用于设置新的参考帧(reference frame)的函数,特别是在 HEVC(High Efficiency Video Coding)解码器中使用。这个函数的作用是将给定的帧(AVFrame)作为新的参考帧(reference frame)添加到 HEVC 解码器的参考帧列表中,并指定该帧的 POC(Picture Order Count)值。

作用和解决问题:

  1. 更新参考帧列表ff_hevc_set_new_ref 函数用于更新 HEVC 解码器内部的参考帧列表,以确保解码过程中正确地使用新的参考帧。
  2. 处理参考帧刷新:在视频编解码过程中,通常会定期刷新参考帧列表,以确保适当的帧可供后续帧进行参考。这个函数帮助管理参考帧的刷新和更新。
  3. 提高解码质量:通过正确管理参考帧列表,解码器可以更准确地重建视频帧,从而提高解码质量和视频播放效果。
  4. 确保正确的顺序:指定 POC 值有助于解码器正确地识别和排序帧,确保视频帧按正确的顺序进行解码和显示。
  5. 解决参考帧相关问题:通过设置新的参考帧,可以解决一些与参考帧管理和使用相关的问题,如视频质量下降、解码错误等。

伪代码

int poc = calculate_poc(); // 假设计算得到了新帧的 POC 值
AVFrame *newFrame = decode_new_frame(); // 假设解码了新的帧

// 在 HEVCContext 中设置新的参考帧
ff_hevc_set_new_ref(hevcContext, &newFrame, poc);
  • 通过调用 ff_hevc_set_new_ref 函数,您可以确保新的参考帧被正确地添加到 HEVC 解码器的参考帧列表中,并能够在解码过程中正确地使用这些参考帧。这有助于提高解码质量和确保视频的正确解码和播放。

ff_hevc_set_new_ref 函数

/**
 * 在 HEVC 解码器上设置新的参考帧。
 *
 * @param s     HEVC 解码器上下文
 * @param frame 指向要设置为参考帧的新帧的指针
 * @param poc   新帧的图片顺序计数(Picture Order Count)
 *
 * @return      成功返回 0,出错返回负值
 */
int ff_hevc_set_new_ref(HEVCContext *s, AVFrame **frame, int poc)
{
    HEVCFrame *ref;
    int i;

    /* 检查该 POC 值是否已经存在于解码图像缓冲区(DPB)中 */
    for (i = 0; i < FF_ARRAY_ELEMS(s->DPB); i++) {
        HEVCFrame *frame = &s->DPB[i];

        if (frame->frame->buf[0] && frame->sequence == s->seq_decode &&
            frame->poc == poc) {
            // 在序列中发现重复的 POC
            av_log(s->avctx, AV_LOG_ERROR, "Duplicate POC in a sequence:%d。\n",poc);
            return AVERROR_INVALIDDATA;
        }
    }

    /* 为新的参考帧分配内存 */
    ref = alloc_frame(s);
    if (!ref)
        return AVERROR(ENOMEM);

    *frame = ref->frame;
    s->ref = ref;

    /* 根据图片输出标志设置新的参考帧标志 */
    if (s->sh.pic_output_flag)
        ref->flags = HEVC_FRAME_FLAG_OUTPUT | HEVC_FRAME_FLAG_SHORT_REF;
    else
        ref->flags = HEVC_FRAME_FLAG_SHORT_REF;

    /* 设置新参考帧的 POC 和其他帧属性 */
    ref->poc      = poc;
    ref->sequence = s->seq_decode;
    ref->frame->crop_left   = s->ps.sps->output_window.left_offset;
    ref->frame->crop_right  = s->ps.sps->output_window.right_offset;
    ref->frame->crop_top    = s->ps.sps->output_window.top_offset;
    ref->frame->crop_bottom = s->ps.sps->output_window.bottom_offset;

    return 0;
}

出现bug:Duplicate POC in a sequence

参考