栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

openh264解码数据流向分析

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

openh264解码数据流向分析

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的定义
struct _GstVideoFrame {
  GstVideoInfo info;
  GstVideoFrameFlags flags;

  GstBuffer *buffer;
  gpointer   meta;
  gint       id;

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

  
  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;
    }
}
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/1005914.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号