FFplay源码分析-RTMP的PTS - 弦外之音

/ 0评 / 0

本系列 以 ffmpeg4.4 源码为准,主要讲解 ffplay 的 RTMP 协议解析,播放。本文使用的命令如下:

ffplay -loglevel quiet -fflags nobuffer -i rtmp://192.168.0.122/live/livestream

播放音视频流最重要的是同步,同步需要用到各个帧的pts,下面就来分析一下 ffplay 从 RTMP 地面读取到的帧的 pts 是从哪个字段提取出来的。

前面几篇文章《FFplay源码分析-rtmp入口》《FFplay源码分析-rtmp_open》《FFplay源码分析-avformat_open_input》已经讲解了 RTMP 的建立,以及部分的数据读取。本文是基于之前的基础进行讲解的。

从之前的文章知道,所有的 RTMP 音视频帧都是通过 append_flv_data() 函数丢进去 RTMPContext 做临时存储,但是播放不是从这里拿数据,播放是从 ic->internal->packet_buffer 拿数据, append_flv_data() 函数函数里面有个 pkt 变量,里面有个 timestamp 字段,如下如:

这个 timestamp 字段应该就是音频帧的pts,时间是微妙。只需要对照一个这个时间戳跟 data字段的数据,就能知道 pts 是不是从这里取的。

由于我知道 find_stream_info() 会读取一部分的视频数据,探测之后丢弃。所以 av_read_frame() 拿到的第一个 数据包的 pts 是 1689 ,如下图:

所以我在 append_flv_data() 函数加个判断,如下:

上图我打印了一下 pts 跟 头 4个字节的内存,然后,我在 ffplay.c 文件的 av_read_frame() 后面打一个断点,查看 AVPacket 的内容,如下图:

最后,两个断点处 的 变量 pkt 的 pts 跟 timestamp 字段值都是 1696,时间戳一直,然后 data 截图如下:

所以 AVPacket 的 pts 就是从 RTMPPacket 的 timestamp 拿出来的,data 也是基本相同,只是 RTMPPacket 的data 头两个字节是 0xaf 0x01。至此我们已经找到 AVPacket 的 pts 的来源,RTMPPacket 的 timestamp 就是 RTMP 格式中的 timestamp,封装 RTMP 包的时候,要把时间戳往这个字段上填。如下图:

纠正,上面那个应该是 dts 不是 pts,然后 pts 应该是通过这个 CompositionTime 计算出来的,如下:

这个 CompositionTime 应该是在 RTMP body 里面的,可能是 H264 的一些东西。后面研究H264编码再做分析。


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

发表回复

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