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

发布于:2024-09-18 ⋅ 阅读:(35) ⋅ 点赞:(0)

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

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

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

一、引言

本文讲解FFmpeg源码对WAV音频文件进行解复用(解封装)时,其AVStream的time_base是怎样被计算出来的。

二、FFmpeg源码中计算WAV音频文件AVStream的time_base的实现

从《音视频入门基础:WAV专题(5)——FFmpeg源码中解码WAV Header的实现》中可以知道,FFmpeg对WAV音频文件进行解复用(解封装)时,其源码内部会调用wav_read_header函数解码WAV音频文件的WAV Header。而该函数内部会调用wav_parse_fmt_tag函数解析“Format chunk”子区块:

​
 for (;;) {
  //...
        switch (tag) {
        case MKTAG('f', 'm', 't', ' '):
        /* only parse the first 'fmt ' tag found */
        if (!got_xma2 && !got_fmt && (ret = wav_parse_fmt_tag(s, size, st)) < 0) {
            return ret;
        } else if (got_fmt)
            av_log(s, AV_LOG_WARNING, "found more than one 'fmt ' tag\n");
 
        got_fmt = 1;
        break;
        }
	}
}
 
​

wav_parse_fmt_tag函数内部会调用avpriv_set_pts_info函数设置AVStream的time_base。关于avpriv_set_pts_info函数的用法可以参考:《FFmpeg源码:avpriv_set_pts_info函数分析》。可以看到,调用avpriv_set_pts_info函数后,st->time_base.num会被设置为1,st->time_base.den会被设置为st->codecpar->sample_rate。也就是说WAV音频文件AVStream的time_base为音频采样频率的倒数:

static int wav_parse_fmt_tag(AVFormatContext *s, int64_t size, AVStream *st)
{
    AVIOContext *pb = s->pb;
    WAVDemuxContext *wav = s->priv_data;
    int ret;

    /* parse fmt header */
    ret = ff_get_wav_header(s, pb, st->codecpar, size, wav->rifx);
    if (ret < 0)
        return ret;
    handle_stream_probing(st);

    ffstream(st)->need_parsing = AVSTREAM_PARSE_FULL_RAW;

    avpriv_set_pts_info(st, 64, 1, st->codecpar->sample_rate);

    return 0;
}

三、总结

WAV音频文件AVStream的time_base为音频采样频率的倒数。比如音频采样频率为44100Hz,其AVStream的time_base为1/44100(44100分之一)。这个计算方式跟AAC裸流是不一样的,各位同学可以把本文跟《音视频入门基础:AAC专题(8)——FFmpeg源码中计算AAC裸流AVStream的time_base的实现》进行对比,以加深对音频AVStream的time_base的理解。