当前位置:网站首页>gstreamer ffmpeg avdec解码数据流向分析
gstreamer ffmpeg avdec解码数据流向分析
2022-07-03 07:12:00 【HUI的技術筆記】
avdec_xxx是gst-libav中的解码插件,对应文件是gstavviddec.c。
avdec初始化的时候,decoder中初始化了下面这些函数,所以libav的avviddec插件中,主要的数据处理,关注几个函数的实现就可以了:
viddec_class->handle_frame = gst_ffmpegviddec_handle_frame;
viddec_class->start = gst_ffmpegviddec_start;
viddec_class->stop = gst_ffmpegviddec_stop;
viddec_class->flush = gst_ffmpegviddec_flush;
viddec_class->finish = gst_ffmpegviddec_finish;
viddec_class->handle_frame接收upstream数据进行处理,viddec_class->finish是在基类sink_event中,收到EOS之后会被调用。
ffmpeg中调用@gst_video_decoder_finish_frame将解码的数据push到downstream,经过以下过程处理:
gst_video_decoder_decode_frame:基类decoder frame
- gst_ffmpegviddec_handle_frame
- gst_ffmpegviddec_frame
- gst_ffmpegviddec_video_frame
- gst_video_decoder_finish_frame
gst_ffmpegviddec_handle_frame功能
- 将frame->input_buffer复制到ffmpeg的packet中
- avcodec_send_packet将上面的packet发给解码器
- 从gst_ffmpegviddec_frame中获取解码buffer并发送到downstream
gst_ffmpegviddec_video_frame功能
gst_ffmpegviddec_video_frame中做的工作列举出来如下,最后gst_video_decoder_finish_frame是最关键的一部,将解码后的buffer继续组合成GstBuffer,发给downstream进行处理。
gst_ffmpegviddec_video_frame
- gst_ffmpegviddec_do_qos
- avcodec_receive_frame
- gst_ffmpegviddec_negotiate
- update_video_context
- gst_ffmpeg_pixfmt_to_videoformat
- gst_video_decoder_set_output_state
- gst_video_decoder_negotiate
- gst_video_decoder_finish_frame(最后关键的一步,push到下游)
解码后的QOS
从上面的栈次序来看,解码后需要做QOS,用到了AVDiscard中定义,AVDiscard的类型定义如下,这个在gst_ffmpegviddec_do_qos函数中可以看到,解码器在在解码下一帧之前执行 qos 计算,设置 skip_frame 标志,如果情况非常糟糕,则跳到下一个关键帧。
enum AVDiscard{
/* We leave some space between them for extensions (drop some * keyframes for intra-only or drop just some bidir frames). */
AVDISCARD_NONE =-16, ///< discard nothing 什么都不丢弃
AVDISCARD_DEFAULT = 0, ///< discard useless packets like 0 size packets in avi 丢弃无用的数据包
AVDISCARD_NONREF = 8, ///< discard all non reference 丢弃所有非参考帧
AVDISCARD_BIDIR = 16, ///< discard all bidirectional frames 丢弃所有双向帧
AVDISCARD_NONINTRA= 24, ///< discard all non intra frames 丢弃所有非帧内帧
AVDISCARD_NONKEY = 32, ///< discard all frames except keyframes 丢弃除关键帧以外的所有帧
AVDISCARD_ALL = 48, ///< discard all 全部丢弃
};
gst_ffmpegviddec_negotiate
gst_ffmpegviddec_negotiate中将avcodec的AVCodecContext中的相关信息转换为gstreamer中的GstVideoInfo,然后调用gst_video_decoder_negotiate进行和downstream的协商。
这是获取caps信息的方法:
in_s = gst_caps_get_structure (ffmpegdec->input_state->caps, 0);
if (!gst_structure_has_field (in_s, "interlace-mode")) {
// ...
}
// ...
gst_video_decoder_negotiate
与下游元素协商当前配置的GstVideoCodecState,在任何情况下都取消flag GST_PAD_FLAG_NEED_RECONFIGURE。但如果协商失败,就需要标记上。
gst_ffmpegviddec_get_buffer2
在avviddec中,get_buffer2是ffmpeg解码的数据转换成gstreamer中的GstVideoCodecFrame类型,Fill avpicture的过程,就是将GstVideoCodecFrame对应的buffer地址转换到avpicture里面,后面用到picture的时候会往里面写数据。
// picture->reordered_opaque : system_frame_nunber;
frame = gst_video_decoder_get_frame (GST_VIDEO_DECODER (ffmpegdec), picture->reordered_opaque);
if (G_UNLIKELY (frame->output_buffer != NULL))
goto duplicate_frame;
if (picture->opaque) {
dframe = picture->opaque;
dframe->frame = frame;
} else {
picture->opaque = dframe =
gst_ffmpegviddec_video_frame_new (ffmpegdec, frame);
}
/* Fill avpicture */
if (!gst_video_frame_map (&dframe->vframe, &ffmpegdec->pool_info,
dframe->buffer, GST_MAP_READWRITE))
goto map_failed;
dframe->mapped = TRUE;
for (c = 0; c < AV_NUM_DATA_POINTERS; c++) {
if (c < GST_VIDEO_INFO_N_PLANES (&ffmpegdec->pool_info)) {
picture->data[c] = GST_VIDEO_FRAME_PLANE_DATA (&dframe->vframe, c);
picture->linesize[c] = GST_VIDEO_FRAME_PLANE_STRIDE (&dframe->vframe, c);
if (ffmpegdec->stride[c] == -1)
ffmpegdec->stride[c] = picture->linesize[c];
/* libav does not allow stride changes, decide allocation should check * before replacing the internal pool with a downstream pool. * https://bugzilla.gnome.org/show_bug.cgi?id=704769 * https://bugzilla.libav.org/show_bug.cgi?id=556 */
g_assert (picture->linesize[c] == ffmpegdec->stride[c]);
} else {
picture->data[c] = NULL;
picture->linesize[c] = 0;
}
GST_LOG_OBJECT (ffmpegdec, "linesize %d, data %p", picture->linesize[c],
picture->data[c]);
}
gst_ffmpegviddec_finish
gst_ffmpegviddec_finish是在结束的时候GST_EVENT_EOS事件后被调用,往下会调用avcodec_flush_buffers进行数据的flush操作。
gst_video_decoder_sink_event_default
- gst_ffmpegviddec_finish
- gst_ffmpegviddec_drain(drain:流走)
- gst_ffmpegviddec_frame
- gst_ffmpegviddec_video_frame
边栏推荐
- PHP install composer
- Software testing assignment - the next day
- Software testing assignment - day 1
- IC_ EDA_ All virtual machine (rich Edition): questasim, vivado, VCs, Verdi, DC, Pt, spyglass, icc2, synthesize, innovative, ic617, mmsim, process library
- IP home online query platform
- Software testing learning - day 3
- Split small interface
- instanceof
- [untitled]
- 10000小時定律不會讓你成為編程大師,但至少是個好的起點
猜你喜欢

La loi des 10 000 heures ne fait pas de vous un maître de programmation, mais au moins un bon point de départ

深度学习参数初始化(一)Xavier初始化 含代码

Flask Foundation

JMeter JSON extractor extracts two parameters at the same time

JUC forkjoinpool branch merge framework - work theft

POI excel percentage

How to specify the execution order for multiple global exception handling classes

IC_ EDA_ All virtual machine (rich Edition): questasim, vivado, VCs, Verdi, DC, Pt, spyglass, icc2, synthesize, innovative, ic617, mmsim, process library

2022 - 06 - 23 vgmp - OSPF - Inter - Domain Security Policy - nat Policy (Update)

In depth analysis of reentrantlock fair lock and unfair lock source code implementation
随机推荐
691. Cube IV
The education of a value investor
Software testing learning - the next day
MySQL transaction rollback, error points record
Laravel Web Framework
Winter vacation work of software engineering practice
2021 year end summary
Upgrade CentOS php7.2.24 to php7.3
How can I split a string at the first occurrence of “-” (minus sign) into two $vars with PHP?
Inno Setup 制作安装包
20220319
Tool class static method calls @autowired injected service
[HCAI] learning summary OSI model
Pat grade a real problem 1166
Deep learning parameter initialization (I) Xavier initialization with code
Discussion on some problems of array
RestHighLevelClient获取某个索引的mapping
SecureCRT password to cancel session recording
[solved] win10 cannot find a solution to the local group policy editor
Inno setup production and installation package