ffmpeg源码分析-process_input_packet - 弦外之音

/ 0评 / 0

本系列 以 ffmpeg4.2 源码为准,下载地址:链接:百度网盘 提取码:g3k8

ffmpeg 源码分析系列以一条简单的命令开始,ffmpeg -i a.mp4 b.flv,分析其内部逻辑。

a.mp4下载链接:百度网盘,提取码:nl0s 。


本文主要分析 process_input_packet() 的内部逻辑,流程图如下:

process_input_packet()的逻辑并不是特别复杂,下面贴上代码图,重点已用红笔标记出来。

从图中可以看到,process_input_packet() 的主要逻辑主要有 5 点。

1,对 ist->dtsist->next_dtsist->ptsist->next_pts 进行赋值。

saw_first_ts 那里利用 has_b_frame 对第一个 dts 赋值,这里计算出的 dts 在本文的命令下,是等于 pkt->dts 的,我也不知道这块代码在什么场景下 有用,应该是兼容性处理,在当前命令下 计算出的 dts 等于 pkt->dts,第二个框框已经用了 pkt->dts 来赋值,所以第一个框框的代码是多余的。 这里的 next_dts 的计算,是根据上一个 pktdts 加上 pkt->duration 或者 帧率时间,推算得到的。

2,第二点主要就是调用了 decode_video() 跟 decode_audio() 来进行后续处理,这两个函数里面不单只会解码packet,还会把 解码出来的 farme 发送给 filter,如果 filter 还没有初始化,会初始化再发送。

3,第五个红色框框,如果解码出 第一个 frame ,ist->got_out 会设置成 1。

4,第六个红色框框,while 循环的最后,repeating = 1 ,这里主要是用来实现,发送一个 packet ,调用多次 avcodec_receive_frame()读取 frame,因为某个packet发给解码器之后,可能可以读取出多个Frame,这里 repeating 是控制多次读取,直到读不到。可以看到,decode_video() 函数的传参,如果repeating =1 ,就会传NULL。

5,最后一个 return !eof_reached ,这里 eof_reached 在什么情况会是 1?当文件读到末尾, av_read_frame() 已经 读不出 pakcet,读不出 packet,就会往 process_input_packet(),传递 NULL packet,就会导致 process_input_packet() 生成一个 packet.size = 0pkt,然后把这样一个pkt丢给解码器,告诉解码器冲刷数据,解码器冲刷完数据,已经没有 frame可以刷出来了,eof_reached 才会是1。

这里有一点需要注意,文件已经没有pakcet读出来,不代表解码器已经冲刷完数据,可能 packet.data = NULLpkt 发送给解码器之后,还要循环几次才能读完后面刷出来的 frame。



process_input_packet() 的流程图如下。


©版权所属:知识星球:弦外之音,QQ:2338195090。

由于笔者的水平有限, 加之编写的同时还要参与开发工作,文中难免会出现一些错误或者不准确的地方,恳请读者批评指正。如果读者有任何宝贵意见,可以加我微信 Loken1。

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注