剑痴乎

  • 首页
  • 文章分类
    • 音视频
    • WebRTC
    • 编程之美
    • Linux
    • Windows
    • 生活点滴
    • 校园生活
  • 参考
    • API参考
    • 实用工具
    • 测试音视频
    • 文档
  • 留言板
  • 关于
剑痴乎
代码为剑,如痴如醉
  1. 首页
  2. 音视频
  3. 正文

flv文件adts头计算

2016年4月29日 2848点热度 3人点赞 0条评论

常见flv文件封装的音频用的都是aac编码,aac文件有两种格式,一个是AIDS,一个是ADTS(Audio Data Transport Stream 音频数据传输流)。其中ADTS格式用于流式传输,因为每一帧都包含头信息,可以从任一帧开始解码,故用于流式传输。本文主要讲下flv文件中的adts。

adts的头部结构

adts头部大小7个字节或者9个字节(决定于是否包含CRC)。结构定义如下图所示:
adts结构

MPEG-4 Audio Object Type

  • 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

······

MPEG-4 Sampling Frequency Index

  • 0: 96000 Hz
  • 1: 88200 Hz
  • 2: 64000 Hz
  • 3: 48000 Hz
  • 4: 44100 Hz
  • 5: 32000 Hz
  • 6: 24000 Hz
  • 7: 22050 Hz
  • 8: 16000 Hz
  • 9: 12000 Hz
  • 10: 11025 Hz
  • 11: 8000 Hz
  • 12: 7350 Hz
  • 13: Reserved
  • 14: Reserved
  • 15: frequency is written explictly

MPEG-4 Channel Configuration

  • 0: Defined in AOT Specifc Config
  • 1: 1 channel: front-center
  • 2: 2 channels: front-left, front-right
  • 3: 3 channels: front-center, front-left, front-right
  • 4: 4 channels: front-center, front-left, front-right, back-center
  • 5: 5 channels: front-center, front-left, front-right, back-left, back-right
  • 6: 6 channels: front-center, front-left, front-right, back-left, back-right, LFE-channel
  • 7: 8 channels: front-center, front-left, front-right, side-left, side-right, back-left, back-right, LFE-channel
  • 8-15: Reserved

flv文件获取AudioSpecificConfig

在flv文件中,上述Audio Object Type,Channel Configrartion等信息存储在AudioSpecificConfig结构中,该AudioSpecificConfig结构一般存储在第一个Audio Tag数据中。在ISO 14496-3中AudioSpecificConfig结构按如下定义:
audiospecificconfig
也就是:

1
2
3
4
5
6
5 bits: audio object type
4 bits: sampling frequency index
if (frequency index == 15)
    24 bits: frequency index
4 bits: channel configuration
other bits: audio object type specific config

如下图所示,我们打开一个音频为aac编码的flv视频文件(本文讨论的都是aac编码的),红色框处是tag data部分数据:
audio_tag_data

由flv标准文档AudioData定义可知,Audio Tag data部分第一个字节(0xAF)结构如下:
audio_tag_data

接着一个字节为AACPacketType(0x00):
auido_tag_data

第一个Audio Tag只包含头信息,不包含具体音频数据,所以AACPacketType值为0。Audio Tag data剩余的才是真正adts帧数据,也就是要把Audio Tag data除去前两个字节。到这里,我们得到了AudioSpecificConfig数据为:0x13 0x88 0x56 0xE5 0xA5 0x48 0x80。在程序中我们先构造一个字符数组,用于存储该数据:

C++
1
char szAudioSpecificConfig[64] = {0};

从flv文件中读取Audio Tag data除去前两个字节的数据:

C++
1
2
//第一个auido tag数据包含AudioSpecificConfig,解析后用于生成adts头
fread(szAudioSpecificConfig, 1, tagheader_datasize - 2, m_pFlvFile);

解析AudioSpecificConfig

由前一部分得知AudioSpecificConfig按如下解析:

C++
1
2
3
4
5
6
5 bits: audio object type
4 bits: sampling frequency index
if (frequency index == 15)
    24 bits: frequency index
4 bits: channel configuration
other bits: audio object type specific config

通过位操作得到相应信息,代码如下:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
uint8_t audio_object_type = 0;
uint8_t sampling_frequency_index = 0;
uint8_t channel_config = 0;
 
//audio object type:5bit
audio_object_type = szAudioSpecificConfig[0] & 0xf8;
audio_object_type >>= 3;
 
//sampling frequency index:4bit
//高3bits
sampling_frequency_index = szAudioSpecificConfig[0] & 0x07;
sampling_frequency_index <<= 1;
//低1bit
uint8_t tmp = szAudioSpecificConfig[1] & 0x80;
tmp >>= 7;
sampling_frequency_index |= tmp;
 
//channel config:4bits
channel_config = szAudioSpecificConfig[1] & 0x78;
channel_config >>= 3;

程序中得到的3个数据我们将在下一部分使用。

计算adts头部

这里我们只讨论adts头部为7个字节的,首先构造一个字符数组存储adts头部:

C++
1
char szAdtsheader[7] = {0};

接着计算得到flv文件所有adts帧头部相同部分:

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
szAdtsHeader[0] = 0xff;         //syncword:0xfff                          高8bits
szAdtsHeader[1] = 0xf0;         //syncword:0xfff                          低4bits
szAdtsHeader[1] |= (0 << 3);    //MPEG Version:0 for MPEG-4,1 for MPEG-2  1bit
szAdtsHeader[1] |= (0 << 1);    //Layer:0                                 2bits
szAdtsHeader[1] |= 1;           //protection absent:1                     1bit
 
szAdtsHeader[2] = (audio_object_type - 1)<<6;            //profile:audio_object_type - 1                      2bits
szAdtsHeader[2] |= (sampling_frequency_index & 0x0f)<<2; //sampling frequency index:sampling_frequency_index  4bits
szAdtsHeader[2] |= (0 << 1);                             //private bit:0                                      1bit
szAdtsHeader[2] |= (channel_config & 0x04)>>2;           //channel configuration:channel_config               高1bit
 
szAdtsHeader[3] = (channel_config & 0x03)<<6;     //channel configuration:channel_config      低2bits
szAdtsHeader[3] |= (0 << 5);                      //original:0                               1bit
szAdtsHeader[3] |= (0 << 4);                      //home:0                                   1bit
szAdtsHeader[3] |= (0 << 3);                      //copyright id bit:0                       1bit  
szAdtsHeader[3] |= (0 << 2);                      //copyright id start:0                     1bit

接下来要计算的数据跟每一个adts帧长度有关,是变化的。如下所示是flv tag的结构,在flv每个tag中,数据部分长度为datasize(tagheader_datasize)。
flv tag

由前面可知flv中Audio Tag存储的真实adts帧数据长度为tagheader_datasize - 2,此时还要加上7个字节adts头部长度才是完整一帧 adts长度,我们设置该长度为:

C++
1
int AdtsLen = tagheader_datasize - 2 + 7;

然后根据该AdtsLen计算得到头部剩下几位:

C++
1
2
3
4
5
szAdtsHeader[3] |= ((AdtsLen & 0x1800) >> 11);           //frame length:value   高2bits
szAdtsHeader[4] = (uint8_t)((AdtsLen & 0x7f8) >> 3);     //frame length:value    中间8bits
szAdtsHeader[5] = (uint8_t)((AdtsLen & 0x7) << 5);       //frame length:value    低3bits
szAdtsHeader[5] |= 0x1f;                                 //buffer fullness:0x7ff 高5bits
szAdtsHeader[6] = 0xfc;

至此我们可以得到了每一帧7个字节的adts头部,加上每一个adts帧的数据,可以得到完整的adts文件。

参考文档

1.flv标准说明video_file_format_spec_v10.pdf:https://pan.baidu.com/s/1z8RSGdQ_wzeXf8J50JMEQA
2.ISO/IEC 14496-3ISO_IEC_14496-3.PDF:https://pan.baidu.com/s/1TNrwlSshmDM3ZcglPHlHCA

本作品采用 知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议 进行许可
标签: 音视频
最后更新:2018年12月23日

Jeff

管理员——代码为剑,如痴如醉

打赏 点赞
< 上一篇
下一篇 >

文章评论

razz evil exclaim smile redface biggrin eek confused idea lol mad twisted rolleyes wink cool arrow neutral cry mrgreen drooling persevering
取消回复

这个站点使用 Akismet 来减少垃圾评论。了解你的评论数据如何被处理。

版权声明

为支持原创,创作更好的文章,未经许可,禁止任何形式的转载与抄袭,如需转载请邮件私信!本人保留所有法定权利。违者必究!

文章目录
  • adts的头部结构
    • MPEG-4 Audio Object Type
    • MPEG-4 Sampling Frequency Index
    • MPEG-4 Channel Configuration
  • flv文件获取AudioSpecificConfig
  • 解析AudioSpecificConfig
  • 计算adts头部
    • 参考文档
最近评论
ztt 发布于 3 周前(04月05日) 你好,想看里面的视频和图片为什么没有显示呢?需要下flash吗还是什么。
huowa222 发布于 1 个月前(03月26日) 同问
邱国禄 发布于 2 个月前(02月17日) Receive Delta以0.25ms为单位,reference time以64ms为单位,kDe...
啊非 发布于 4 个月前(12月30日) 大神,请教一个问题: constexpr int kBaseScaleFactor = Tran...
啊非 发布于 4 个月前(12月30日) reference time:3字节,表示参考时间,以64ms为单位,但是 代码里面是 Trans...
相关文章
  • 音视频开发入门:视频基础
  • 大话WebRTC
  • WebRTC音视频传输基础:NAT穿透
  • Intel平台硬件加速视频编解码开发
  • 音视频开发入门:音频基础

COPYRIGHT © 2024 jianchihu.net. ALL RIGHTS RESERVED.

Theme Kratos Made By Seaton Jiang