openh264解码数据流向分析

本文详细介绍了openh264dec解码器的工作流程,包括如何使用DecodeFrameNoDelay解码视频帧,以及如何利用gst_video_frame_map映射和处理解码后的数据。此外还介绍了gst_video_decoder_finish_frame如何将解码后的数据推送至下游。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

openh264dec中finish_frame的逻辑和avviddec比起来比较简单,在handle_frame中,buffer先送给解码器解码(DecodeFrameNoDelay),然后调用gst_video_decoder_finish_frame将解码后的buffer发到downstream。

DecodeFrameNoDelay解码,返回yuvdata,完成后unmap input_buffer:

openh264dec->decoder->DecodeFrameNoDelay (map_info.data, map_info.size,
                                          yuvdata, &dst_buf_info);
gst_buffer_unmap (frame->input_buffer, &map_info);
gst_video_frame_map的功能

gst_video_frame_map()将在GstVideoFrame结构中填入buffer的像素以及所需的各种视频信息。

gboolean
gst_video_frame_map (GstVideoFrame * frame, GstVideoInfo * info, GstBuffer * buffer, GstMapFlags flags)

使用@info和@buffer来填入到@frame,地址会被传给分配在堆栈中的#GstVideoFrame结构。

可以使用访问器宏访问,如:

 GST_VIDEO_FRAME_COMP_DATA()
 GST_VIDEO_FRAME_PLANE_DATA()
 GST_VIDEO_FRAME_COMP_STRIDE()
 GST_VIDEO_FRAME_PLANE_STRIDE()

这个功能的目的是使你能够很容易地获得视频像素,而不需要担心太多细节问题。

比如视频数据是被分配在一个连续的内存块中还是多个内存块(例如,对于每一个plane都有一个内存块),或者是否使用自定义strides和自定义plane偏移(由每个缓冲区上的GstVideoMeta记录)。

这个函数只是用正确的值填充#GstVideoFrame结构,使用访问器宏,可以很容易地访问数据。它还会为你映射底层的内存块。

gst_video_frame_map的使用从ffmpeg avviddec和openh264dec的实现也可以看到,能方便的把解码器解码的数据放到plane内存块中。

GstVideoFrame的定义
/**
 * GstVideoFrame:
 * @info: the #GstVideoInfo
 * @flags: #GstVideoFrameFlags for the frame
 * @buffer: the mapped GstBuffer's buffer
 * @meta: pointer to metadata if any
 * @id: id of the mapped frame. the id can for example be used to
 *   identify the frame in case of multiview video.
 * @data: pointers to the plane data
 * @map: mappings of the planes
 *
 * A video frame obtained from gst_video_frame_map()
 */
struct _GstVideoFrame {
  GstVideoInfo info;
  GstVideoFrameFlags flags;

  GstBuffer *buffer;
  gpointer   meta;
  gint       id;

  gpointer   data[GST_VIDEO_MAX_PLANES];
  GstMapInfo map[GST_VIDEO_MAX_PLANES];

  /*< private >*/
  gpointer _gst_reserved[GST_PADDING];
};
gst_video_decoder_allocate_output_frame

辅助函数,为@decoder当前的#GstVideoCodecState分配一个缓冲区来容纳一个视频帧。子类应该已经配置了视频状态并设置了src pad caps。从openH264dec和avdec_h264中都可以看到,最后解码的数据要先allocate_output_frame,然后copy数据到这个里面,avviddec里面的处理需要看get_output_buffer函数的实现。

gst_video_decoder_finish_frame

在openh264dec中,通过gst_video_decoder_finish_frame将解码后的数据push到downstream,如果没有提供输出数据,frame被视为skipped。在任何情况下,frame都被视为finished和released。

gst_openh264dec_handle_frame
  • 收到frame后先交给openh264dec解码->DecodeFrameNoDelay
  • gst_video_frame_map:映射frame->output_buffer,将解码的yuvdata填进去。
  • gst_video_decoder_set_output_state:在srcpad上创建新的codec state作为解码器的输出状态
  • gst_video_decoder_finish_frame发送给downstream

因为output state部分配置的是I420,所以在进行数据copy的时候,是yuv依次copy:

// i = 0; Y plane
// i = 1; U plane
// i = 2; V plane
for (i = 0; i < 3; i++) {
    p = GST_VIDEO_FRAME_COMP_DATA (&video_frame, i);
    row_stride = GST_VIDEO_FRAME_COMP_STRIDE (&video_frame, i);
    component_width = GST_VIDEO_FRAME_COMP_WIDTH (&video_frame, i);
    component_height = GST_VIDEO_FRAME_COMP_HEIGHT (&video_frame, i);
    src_width =
        i <
        1 ? dst_buf_info.UsrData.sSystemBuffer.
        iStride[0] : dst_buf_info.UsrData.sSystemBuffer.iStride[1];
    for (row = 0; row < component_height; row++) {
        memcpy (p, yuvdata[i], component_width);
        p += row_stride;
        yuvdata[i] += src_width;
    }
}
OpenH264 是思科公司发布的一个开源的 H.264 编码和解码器。编码器特性Constrained Baseline Profile up to Level 5.2 (4096x2304)Arbitrary resolution, not constrained to multiples of 16x16Rate control with adaptive quantization, or constant quantizationSlice options: 1 slice per frame, N slices per frame, N macroblocks per slice, or N bytes per sliceMultiple threads automatically used for multiple slicesTemporal scalability up to 4 layers in a dyadic hierarchySpatial simulcast up to 4 resolutions from a single inputLong Term Reference (LTR) framesMemory Management Control Operation (MMCO)Reference picture list modificationSingle reference frame for inter predictionMultiple reference frames when using LTR and/or 3-4 temporal layersPeriodic and on-demand Instantaneous Decoder Refresh (IDR) frame insertionDynamic changes to bit rate, frame rate, and resolutionAnnex B byte stream outputYUV 4:2:0 planar input解码器特性Constrained Baseline Profile up to Level 5.2 (4096x2304)Arbitrary resolution, not constrained to multiples of 16x16Single thread for all slicesLong Term Reference (LTR) framesMemory Management Control Operation (MMCO)Reference picture list modificationMultiple reference frames when specified in Sequence Parameter Set (SPS)Annex B byte stream inputYUV 4:2:0 planar output支持的操作系统Windows 64-bit and 32-bit (initial release is only 32-bit, 64-bit will follow soon)Mac OS X 64-bit (initial release does not include this target, will follow soon)Linux 64-bit and 32-bit (initial release is only 32-bit, 64-bit will follow soon)Android 32-bit (initial release does not include this target, will follow soon)iOS 64-bit and 32-bit (not supported yet, may be added in the future)支持的处理器Intel x86 optionally with MMX/SSE (no AVX yet, help is welcome)ARMv7 optionally with NEON (initial release does not include this target, will follow later)Any architecture using C/C fallback functions 标签:OpenH264
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值