Linux31:FFMPEG时间戳、时间基、时间转换的讲解

目录

[1. 时间基(time_base)](#1. 时间基(time_base))

[2. 时间戳(PTS、DTS)](#2. 时间戳(PTS、DTS))

3.时间转换的原理


1. 时间基(time_base)

时间基也称之为时间基准,它代表的是每个刻度是多少秒。比方说:视频帧率是**25FPS,**那它的时间刻度是{1,25}。相当于1s内划分出25个等分,也就是每隔1/25秒后显示一帧视频数据。具体的如下图所示:

在FFMPEG中时间基准都是用AVRational结构体来表示:

  • num:它是numerator的缩小,代表的是分子
  • den:它是denominator的缩小,代表的是分母

在视频时间基都是以帧率为单位,比方说25帧。FFMPEG就以AVRational video_timebase = {1, 25}来表示。

在音频时间基都是以采样率为单位,比方说音频采样率是48000HZ。FFMPEG就以AVRationalaudio_timebase = {1, 48000}来表示。

对于封装格式来说:flv 封装格式的 time_base 为{1,1000},ts 封装格式的 time_base 为{1,90000}

从上图ffplay的信息我们可以看到有很多关于时间基的信息:

  • tbr:表示帧率,该帧率是一个基准,通常来说tbr和fps是一致的
  • tbn:表示视频流timebase(时间基数值),容器时间基,比方说:TS格式的数据timebase是90000,fv格式的视频流timebase为1000
  • tbc:表示视频流编解码器时间基codec timebase,它用于在解码或编码过程中,标记帧的显示顺序或解码顺序。这个值一般为帧率的两倍。比方说:帧率是25fps,则tbc是50

在 MPEG 编码标准(如 H.264)中,视频编码后的帧通常分为三种类型:I帧、P帧、B帧。

  • B帧(双向预测帧) 有一个关键特性:它需要参考前后的帧才能解码。
  • 这就导致在数据流的组织上,帧的存储顺序(解码顺序) 和显示顺序是不一致的。

举个例子:

假设一个视频的显示顺序是:I1 B2 B3 P4。

  • 显示顺序: 先显示 I1,然后 B2,然后 B3,然后 P4。
  • 解码顺序(因为 B 帧依赖 P 帧): 必须先解码 I1,然后必须解码 P4(因为 B2 和 B3 需要 P4 的信息),然后才能解码 B2 和 B3。所以实际存储顺序可能是:I1 P4 B2 B3。

这就产生了一个问题:如何同时标记解码时间和显示时间?

编码器需要两套时间戳:

  1. DTS(解码时间戳): 告诉解码器什么时候解码这个数据包(通常基于 tbc)。
  2. PTS(显示时间戳): 告诉播放器什么时候显示这个解码后的画面(通常基于 tbn)。

为了在时间基上精确区分 DTS 和 PTS,并且为了在半个帧间隔(比如处理场模式视频或 B 帧的精细偏移)时依然能精确标记,编解码器内部需要一个更细粒度的时间刻度。

  • tbn(容器): 只需要精确到显示每一帧就够了,所以通常是帧率的倒数(例如 1/90000 或 1/1000)。
  • tbc(编解码器): 因为需要标记"解码"和"显示"之间的偏移,为了操作整数方便,很多编码器(特别是 MPEG 系列)会将时间基设为帧率的两倍。这样,两个相邻显示帧之间的刻度就是 2,中间可以插入一个解码偏移值。

2. 时间戳(PTS、DTS)

时间戳它指的是在时间轴里面占了多少个格子,时间戳的单位不是具体的秒数,而是时间刻度。只有当时间基和时间戳结合在一起的时候,才能够真正表达出来时间是多少。

比方说:

有一把尺子pts = 25个刻度,time_base = {1,25} 每一个刻度是1/25厘米

所以这把尺子的长度 = pts * time_base = 25* 1/25= 1厘米

PTS

全称是Presentation Time Stamp(显示时间戳),它主要的作用是度量解码后的视频帧什么时候显示出来。

视频PTS计算:n为第n帧视频帧,timebase是{1,framerate},fps是framerate

timebase = 1/framerate

pts = (n-1) *(( 1 / timebase) / fps) = (n-1) *(timerate/fps) = n

pts = pts++;

举例子:

n = 0, pts = 0

n = 1, pts = 1

n = 2, pts = 2

n = 3, pts = 3
音频PTS计算:n为第n帧音频帧,nb_samples指的是采样个数(AAC默认1024),timebase是{1,samplerate},samplerate是采样率

Samplerate = 48000, nb_sample=1024, timebase = {1,48000}

num_pkt = samplerate/nb_samples // 每秒多少个音频包

pts = (n-1) * ( ( 1/ timebase) / num_pkt) = n *1024

pts = pts+1024

举例子:

n = 0, pts = 0

n = 1, pts = 1024

n = 2, pts = 2048

n = 3, pts = 3072

DTS

表示的是压缩解码的时间戳,在没有B帧的情况下PTS 等于 DTS。假设编码的里面引入了B帧,则还要计算B帧的时间。

没有B帧:dts = pts

存在B帧:dts = pts + b_time

3.时间转换的原理

在FFMPEG中由于不同的复合流,时间基是不同的,比方说:flv的时间基time_base= {1,1000 },假设一个视频time_base = {1,25 },我们需要合成mpegts文件,它就需要把time_base = {1,25} 占的格子转换成time_base = {1,1000}占的格子。

在FFMPEG中用以下的API进行时间基转换:

void av_packet_rescale_ts(AVPacket *pkt, AVRational tb_src, AVRational tb_dst);

**第一个参数:**AVPacket结构体指针

**第二个参数:**源时间基

**第三个参数:**目的时间基

上面这个api的用法是,把AVPacket的时间基tb_src 转换成时间基tb_dst

下面我们用H264和AAC时间基TS转换的例子来说明这个转换时间基的用法:

视频H264时间基转换成MPEGTS时间基:

DST_VIDEO_PTS = VIDEO_PTS * VIDEO_TIME_BASE / DST_TIME_BASE

本质:视频播放的时间相同,即

DST_VIDEO_PTS * DST_TIME_BASE = VIDEO_PTS * VIDEO_TIME_BASE

H264 {1,25} flv{1,1000}

pts = 1 pts = 40

pts = 2 av_packet_rescale_ts pts = 80

pts = 3 pts = 120

pts = 4 pts = 160

音频AAC时间基转换成FLV时间基:

DST_AUDIO_PTS = AUDIO_PTS * AUDIO_TIME_BASE / DST_TIME_BASE

AAC {1,48000} FLV{1,1000}

pts =1024 pts ~= 21.3

pts =2048 av_packet_rescale_ts pts ~= 42.6

pts =3072 pts ~= 64

pts =4096 pts ~= 85.3

从上述推导的结果可以看出来,如果使用av_packet_rescale_ts 的API对视频时间基进行转换,实际上是使用DST_VIDEO_PTS = VIDEO_PTS * VIDEO_TIME_BASE / DST_TIME_BASE去计算推流的视频时间戳。

同理用av_packet_rescale_ts 对音频时间基进行转换,实际上是使用DST_AUDIO_PTS = AUDIO_PTS * AUDIO_TIME_BASE / DST_TIME_BASE去计算我们真实推流的音频时间戳。

相关推荐
智能工业品检测-奇妙智能2 小时前
linux 安装 FFmpeg 和windows安装 FFmpeg
linux·windows·ffmpeg
xmRao10 小时前
Qt+FFmpeg 实现摄像头采集并录制 YUV 格式视频
qt·ffmpeg·音视频
软件架构师-叶秋10 小时前
FFMPEG之完整编译指南
ffmpeg
食指Shaye10 小时前
免费视频编辑软件FFmpeg 在windows上使用CMD命令行的操作说明
windows·ffmpeg
活捉一个坏小孩15 天前
Nvidia FFmpeg安装说明
ffmpeg
WF_YL15 天前
如何删除 Oracle 过期 key / 数据,删除目的的key
ffmpeg
浩瀚之水_csdn15 天前
avcodec_find_decoder函数详解
ffmpeg
浩瀚之水_csdn18 天前
avcodec_parameters_copy详解
linux·人工智能·ffmpeg
不吃鱼的猫74822 天前
【ffplay 源码解析系列】02-核心数据结构详解
c++·ffmpeg·音视频