当前位置: 首页 > news >正文

音视频入门基础:FLV专题(21)——FFmpeg源码中,获取FLV文件音频信息的实现(上)

由于本文篇幅较长,分为上、中、下三篇。

一、引言

通过FFmpeg命令可以获取到FLV文件的音频压缩编码格式、音频采样率、通道数、音频码率信息:

./ffmpeg -i XXX.flv

而由《音视频入门基础:FLV专题(9)——Script Tag简介》和《音视频入门基础:FLV专题(18)——Audio Tag简介》可以知道:FLV文件中名称为“onMetadata”的Script Tag、每个Audio Tag的AudioTagHeader、AudioSpecificConfig都会包含音频信息。

名称为“onMetadata”的Script Tag:

每个Audio Tag的AudioTagHeader:

AudioSpecificConfig:

可以看到,FLV文件中的上述三个地方都会存在音频信息,有些信息比如:音频压缩编码格式、音频采样率、通道数甚至是重复的。所以FFmpeg到底获取的是哪个地方的音频信息呢,本文为大家揭开谜底。

二、音频压缩编码格式

FFmpeg获取FLV文件的音频压缩编码格式,获取的是Audio Tag的AudioTagHeader中的音频压缩编码格式。由《音视频入门基础:FLV专题(18)——Audio Tag简介》可以知道,AudioTagHeader存在一个占4位的SoundFormat属性,表示音频的压缩编码格式:

0:Linear PCM, platform endian
1:ADPCM
2:MP3
3:Linear PCM, little endian
4:Nellymoser 16 kHz mono
5:Nellymoser 8 kHz mono
6:Nellymoser
7:G.711 A-law logarithmic PCM
8:G.711 mu-law logarithmic PCM
9:reserved
10:AAC
11:Speex
14:MP3 8 kHz
15:Device-specific sound

由《音视频入门基础:FLV专题(19)——FFmpeg源码中,解码Audio Tag的AudioTagHeader,并提取AUDIODATA的实现》可以知道,FFmpeg源码中使用flv_read_packet函数来读取每个Tag的信息。如果判断出该Tag为Audio Tag,flv_read_packet函数中会通过下面代码块将AudioTagHeader的SoundFormat属性提取出来,转换得到音频压缩编码格式。将音频压缩编码格式赋值给st->codecpar->codec_id中。st->codecpar为指向一个AVCodecParameters类型变量的指针:

        if (!st->codecpar->codec_id) {flv_set_audio_codec(s, st, st->codecpar,flags & FLV_AUDIO_CODECID_MASK);//...}

然后在flv_read_packet函数外部,通过avcodec_parameters_to_context函数将AVCodecParameters的codec_id赋值给AVCodecContext的codec_id:

int avcodec_parameters_to_context(AVCodecContext *codec,const AVCodecParameters *par)
{
//...codec->codec_id   = par->codec_id;
//...
}

然后在dump_stream_format函数中,通过avcodec_string函数中的语句:codec_name = avcodec_get_name(enc->codec_id) 拿到AVCodecContext的codec_id对应的音频压缩编码格式名称。最后再在dump_stream_format函数中将音频压缩编码格式打印出来:

void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode)
{
//...codec_name = avcodec_get_name(enc->codec_id);
//...
}

所以FFmpeg获取FLV文件的音频压缩编码格式,获取的是Audio Tag的AudioTagHeader中的音频压缩编码格式:

三、音频压缩编码格式的profile

音频压缩编码格式还有附带的profile(规格)。比如音频压缩编码格式为AAC,根据《ISO14496-3-2009.pdf》第124页,还有AAC Main、AAC LC、AAC SSR、AAC LTP这几种规格:

FFmpeg获取FLV文件的音频压缩编码格式的profile,获取的是AudioSpecificConfig中的audioObjectType。由《音视频入门基础:AAC专题(11)——AudioSpecificConfig简介》可以知道,FLV文件中的音频为AAC时,正常情况下它必定存在一个Audio Tag包含Audio Specific Config,而Audio Specific Config中存在一个占5位或11位的audioObjectType属性,表示音频对象类型:

0: Null
1: AAC Main
2: AAC LC (Low Complexity)
3: AAC SSR (Scalable Sample Rate)
4: AAC LTP (Long Term Prediction)
5: SBR (Spectral Band Replication)
6: AAC Scalable
7: TwinVQ
8: CELP (Code Excited Linear Prediction)
9: HXVC (Harmonic Vector eXcitation Coding)
10: Reserved
11: Reserved
12: TTSI (Text-To-Speech Interface)
13: Main Synthesis
14: Wavetable Synthesis
15: General MIDI
16: Algorithmic Synthesis and Audio Effects
17: ER (Error Resilient) AAC LC
18: Reserved
19: ER AAC LTP
20: ER AAC Scalable
21: ER TwinVQ
22: ER BSAC (Bit-Sliced Arithmetic Coding)
23: ER AAC LD (Low Delay)
24: ER CELP
25: ER HVXC
26: ER HILN (Harmonic and Individual Lines plus Noise)
27: ER Parametric
28: SSC (SinuSoidal Coding)
29: PS (Parametric Stereo)
30: MPEG Surround
31: (Escape value)
32: Layer-1
33: Layer-2
34: Layer-3
35: DST (Direct Stream Transfer)
36: ALS (Audio Lossless)
37: SLS (Scalable LosslesS)
38: SLS non-core
39: ER AAC ELD (Enhanced Low Delay)
40: SMR (Symbolic Music Representation) Simple
41: SMR Main
42: USAC (Unified Speech and Audio Coding) (no SBR)
43: SAOC (Spatial Audio Object Coding)
44: LD MPEG Surround
45: USAC

由《音视频入门基础:AAC专题(12)——FFmpeg源码中,解码AudioSpecificConfig的实现》可以知道,FFmpeg源码中使用decode_audio_specific_config_gb函数来读取AudioSpecificConfig的信息。decode_audio_specific_config_gb函数中会调用ff_mpeg4audio_get_config_gb函数,而ff_mpeg4audio_get_config_gb函数中,通过语句:c->object_type = get_object_type(gb) 获取AudioSpecificConfig的audioObjectType属性。执行decode_audio_specific_config_gb函数后,m4ac指向的变量会得到从AudioSpecificConfig中解码出来的属性:

static inline int get_object_type(GetBitContext *gb)
{int object_type = get_bits(gb, 5);if (object_type == AOT_ESCAPE)object_type = 32 + get_bits(gb, 6);return object_type;
}

然后在decode_audio_specific_config_gb函数外部,通过aac_decode_frame_int函数将上一步得到的audioObjectType属性赋值给AVCodecContext的profile:

static int aac_decode_frame_int(AVCodecContext *avctx, AVFrame *frame,int *got_frame_ptr, GetBitContext *gb,const AVPacket *avpkt)
{
//...// The AV_PROFILE_AAC_* defines are all object_type - 1// This may lead to an undefined profile being signaledac->avctx->profile = ac->oc[1].m4ac.object_type - 1;
//...
}

然后在dump_stream_format函数中,通过avcodec_string函数中的语句:profile = avcodec_profile_name(enc->codec_id, enc->profile)拿到上一步中得到的AVCodecContext的profile。最后再在dump_stream_format函数中将profile打印出来:

void avcodec_string(char *buf, int buf_size, AVCodecContext *enc, int encode)
{
//...profile = avcodec_profile_name(enc->codec_id, enc->profile);
//...
}

所以FFmpeg获取FLV文件的音频压缩编码格式的profile,获取的是AudioSpecificConfig中的audioObjectType:


http://www.mrgr.cn/news/63171.html

相关文章:

  • flask websocket服务搭建,flask-sock 和 flask-socketio
  • 中文NLP地址要素解析【阿里云:天池比赛】
  • 【JS学习】04. JS基础语法-函数
  • AIGC 浪潮下,R 语言奏响数据分析新乐
  • 创建多维数组的全部元素的索引np.indices
  • JDBC分页查询操作
  • 开放式耳机品牌排行榜 ,如何挑选开放式耳机
  • Puppeteer点击系统:解锁百度流量点击率提升的解决案例
  • Android OpenGL ES详解——模板Stencil
  • 数智税务 | 数电票:带来税务管理五大新挑战、绘就智慧税务征管新蓝图
  • js、vue、angular中的函数声明方式及特点
  • JVM性能优化实战手册:从监控到调优策略
  • Vatee万腾平台:让企业数字化转型更轻松、更高效
  • 博客搭建之路:hexo博客显示阅读时间和字数
  • lanqiaoOJ 315:寻找3个数的最大乘积
  • 构建安全的用户登录API:从请求验证到JWT令牌生成
  • 呼吁中兴向全国免费开放专利许可,支持国产创新,你支持吗?
  • VS2022 远程调式
  • Strongly Connected City
  • FlinkCDC-MYSQL批量写入
  • 第三百零七节 Log4j教程 - Log4j日志格式、Log4j日志到文件
  • Android开发教程viewpager2点击指示标也能切换
  • (C#面向初学者的 .NET 的生成 AI) 第 2 部分-什么是 AI 和 ML?
  • 解读!中国人工智能大模型技术白皮书!
  • 基于SSM医药进出口交易系统的设计
  • 大语言模型(LLMs)在安全芯片设计中应用