傲渊山岳 发表于 2024-9-8 07:03:51

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

一、引言

本文讲解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分之一)。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。
页: [1]
查看完整版本: 音视频入门基础:WAV专题(8)——FFmpeg源码中盘算WAV音频文件AVStream的t