音视频入门基础: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:

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

打印出来的“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。这里的time_base指AVStream的time_base。比如pts为4096,time_base为44100分之一,则pts_time等于4096乘以44100分之一 ,等于0.092880秒。

你可能感兴趣的:(FFmpeg源码分析,音视频技术,音视频,ffmpeg)