您的位置:首页 > 游戏 > 游戏 > 音视频入门基础:WAV专题(11)——FFmpeg源码中计算WAV音频文件每个packet的pts_time、dts_time的实现

音视频入门基础:WAV专题(11)——FFmpeg源码中计算WAV音频文件每个packet的pts_time、dts_time的实现

2024/12/21 19:55:48 来源:https://blog.csdn.net/u014552102/article/details/142046147  浏览:    关键词:音视频入门基础:WAV专题(11)——FFmpeg源码中计算WAV音频文件每个packet的pts_time、dts_time的实现

=================================================================

音视频入门基础:WAV专题系列文章:

音视频入门基础:WAV专题(1)——使用FFmpeg命令生成WAV音频文件

音视频入门基础:WAV专题(2)——WAV格式简介

音视频入门基础:WAV专题(3)——FFmpeg源码中,判断某文件是否为WAV音频文件的实现

音视频入门基础:WAV专题(4)——FFmpeg源码中获取WAV文件音频压缩编码格式、采样频率、声道数量、采样位数、码率的实现

音视频入门基础:WAV专题(5)——FFmpeg源码中解码WAV Header的实现

音视频入门基础:WAV专题(6)——通过FFprobe显示WAV音频文件每个数据包的信息

音视频入门基础:WAV专题(7)——FFmpeg源码中计算WAV音频文件每个packet的size值的实现

音视频入门基础:WAV专题(8)——FFmpeg源码中计算WAV音频文件AVStream的time_base的实现

音视频入门基础:WAV专题(9)——FFmpeg源码中计算WAV音频文件每个packet的duration和duration_time的实现

音视频入门基础:WAV专题(10)——FFmpeg源码中计算WAV音频文件每个packet的pts、dts的实现

音视频入门基础:WAV专题(11)——FFmpeg源码中计算WAV音频文件每个packet的pts_time、dts_time的实现

=================================================================

一、引言

从文章《音视频入门基础:WAV专题(6)——通过FFprobe显示WAV音频文件每个数据包的信息》中我们可以知道,通过FFprobe命令可以打印WAV音频文件每个packet(也称为数据包或多媒体包)的信息,这些信息包含该packet的pts_time、dts_time:

打印出来的“pts_time”是以秒为单位的显示时间戳;“dts_time”是以秒为单位的解码时间戳。这两个值都是通过fftools/ffprobe.c中的show_packet函数打印出来的:

static void show_packet(WriterContext *w, InputFile *ifile, AVPacket *pkt, int packet_idx)
{
//...print_time("pts_time",        pkt->pts, &st->time_base);
//...print_time("dts_time",        pkt->dts, &st->time_base);
//...
}

本文讲述上述pts_time、dts_time的值是怎样被计算出来的。如果想直接看结论,可以跳到本文的最后,直接看“总结”。

二、FFmpeg源码中计算WAV音频文件每个packet的pts_time、dts_time的实现

从《音视频入门基础:WAV专题(10)——FFmpeg源码中计算WAV音频文件每个packet的pts、dts的实现》中可以知道,pts是以AVStream->time_base为单位的显示时间戳;dts是以AVStream->time_base为单位的解码时间戳。

show_packet函数是通过print_time宏定义将pts和dts转换为pts_time和dts_time,并打印出来的:

​static void show_packet(WriterContext *w, InputFile *ifile, AVPacket *pkt, int packet_idx)
{
//...print_time("pts_time",        pkt->pts, &st->time_base);
//...print_time("dts_time",        pkt->dts, &st->time_base);
//...
}​

print_time宏定义如下,可以看到其实质是调用writer_print_time函数:

#define print_time(k, v, tb)    writer_print_time(w, k, v, tb, 0)

而writer_print_time函数的定义为:

static void writer_print_time(WriterContext *wctx, const char *key,int64_t ts, const AVRational *time_base, int is_duration)
{char buf[128];if ((!is_duration && ts == AV_NOPTS_VALUE) || (is_duration && ts == 0)) {writer_print_string(wctx, key, "N/A", PRINT_STRING_OPT);} else {double d = ts * av_q2d(*time_base);struct unit_value uv;uv.val.d = d;uv.unit = unit_second_str;value_string(buf, sizeof(buf), uv);writer_print_string(wctx, key, buf, 0);}
}

表达式writer_print_time(w, k, v, tb, 0)中,“v”为pts或dts,“tb”为AVStream的time_base。

关于av_q2d函数的用法可以参考:《FFmpeg有理数相关的源码:AVRational结构体和其相关的函数分析》。pts_time和dts_time是由writer_print_time函数中的下面语句计算出来的:

double d = ts * av_q2d(*time_base);

简单点来讲:

pts_time = pts × time_base,

dts_time = dts × time_base。

三、总结

“pts_time”是以秒为单位的显示时间戳;“dts_time”是以秒为单位的解码时间戳。

pts_time = pts × time_base,dts_time = dts × time_base。比如pts为4096,time_base为44100分之一,则pts_time等于4096乘以44100分之一 ,等于0.092880秒。

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com