AAC ADTS格式分析与提取aac音频文件实战

news2024/11/16 15:25:58

1.AAC⾳频格式简介

AAC⾳频格式:Advanced Audio Coding(⾼级⾳频解码),是⼀种由MPEG-4 标准定义的有损⾳频压缩格式,由Fraunhofer发展,Dolby, Sony和AT&T是主 要的贡献者。

AAC 包含两种格式:ADIF和ADTS

2.ADIF和ADTS简介

  • ADIF:Audio Data Interchange Format ⾳频数据交换格式。这种格式的特 征是可以确定的找到这个⾳频数据的开始,不需进⾏在⾳频数据流中间开始 的解码,即它的解码必须在明确定义的开始处进⾏。故这种格式常⽤在磁盘 ⽂件中。
  • ADTS的全称是Audio Data Transport Stream。是AAC⾳频的传输流格 式。AAC⾳频格式在MPEG-2(ISO-13318-7 2003)中有定义。AAC后来 ⼜被采⽤到MPEG-4标准中。这种格式的特征是它是⼀个有同步字的⽐特 流,解码可以在这个流中任何位置开始。它的特征类似于mp3数据流格式。

简单说,ADTS可以在任意帧解码,也就是说它每⼀帧都有头信息。ADIF只有⼀ 个统⼀的头,所以必须得到所有的数据后解码。

且这两种的header的格式也是不同的,⽬前⼀般编码后的和抽取出的都是 ADTS格式的⾳频流。

AAC的ADIF格式:

在这里插入图片描述

AAC的ADTS的⼀般格式(空⽩处表示前后帧):
在这里插入图片描述

有的时候当你编码AAC裸流的时候,会遇到写出来的AAC⽂件并不能在PC和⼿ 机上播放,很⼤的可能就是AAC⽂件的每⼀帧⾥缺少了ADTS头信息⽂件的包装拼接。

只需要加⼊头⽂件ADTS即可,⼀个AAC原始数据块⻓度是可变的,对原始帧加 上ADTS头进⾏ADTS的封装,就形成了ADTS帧

3.ADTS解析

AAC⾳频⽂件的每⼀帧由ADTS Header和AAC Audio Data组成,结构体如下:

在这里插入图片描述

注意:ADTS Header的长度可能为7个字节或者9个字节,protection_absent=0时,9个字节,protection_absent=1,7个字节。

每⼀帧的ADTS的头⽂件都包含了⾳频的采样率,声道,帧⻓度等信息,这样解码器才能解析读取,⼀般情况下ADTS的头信息都是7个字节,分为2部分:

  • adts_fixed_header

  • adts_variable_header

其⼀为固定头信息,紧接着是可变头信息。固定头信息中的数据每⼀帧都相 同,⽽可变头信息则在帧与帧之间可变。

	/* adts_fixed_header */
    put_bits(&pb, 12, 0xfff);   /* syncword */
    put_bits(&pb, 1, 0);        /* ID */
    put_bits(&pb, 2, 0);        /* layer */
    put_bits(&pb, 1, 1);        /* protection_absent */
    put_bits(&pb, 2, ctx->objecttype); /* profile_objecttype */
    put_bits(&pb, 4, ctx->sample_rate_index);
    put_bits(&pb, 1, 0);        /* private_bit */
    put_bits(&pb, 3, ctx->channel_conf); /* channel_configuration */
    put_bits(&pb, 1, 0);        /* original_copy */
    put_bits(&pb, 1, 0);        /* home */

syncword :同步头 总是0xFFF, all bits must be 1,代表着⼀个ADTS帧的开 始

ID:MPEG标识符,0标识MPEG-4,1标识MPEG-2

Layer:always: ‘00’

protection_absent:表示是否误码校验。Warning, set to 1 if there is no CRC and 0 if there is CRC

profile:表示使⽤哪个级别的AAC,如01 Low Complexity(LC)— AAC

LC。有些芯⽚只⽀持AAC LC 。

   /* adts_variable_header */
    put_bits(&pb, 1, 0);        /* copyright_identification_bit */
    put_bits(&pb, 1, 0);        /* copyright_identification_start */
    put_bits(&pb, 13, full_frame_size); /* aac_frame_length */
    put_bits(&pb, 11, 0x7ff);   /* adts_buffer_fullness */
    put_bits(&pb, 2, 0);        /* number_of_raw_data_blocks_in_frame */

frame_length : ⼀个ADTS帧的⻓度包括ADTS头和AAC原始流. frame length, this value must include 7 or 9 bytes of header length:

aac_frame_length = (protection_absent == 1 ? 7 : 9) + size(AACFrame)

protection_absent=0时, header length=9bytes

protection_absent=1时, header length=7bytes

adts_buffer_fullness:0x7FF 说明是码率可变的码流。

number_of_raw_data_blocks_in_frame:表示ADTS帧中有

number_of_raw_data_blocks_in_frame + 1个AAC原始帧。

所以说number_of_raw_data_blocks_in_frame == 0 表示说ADTS帧中有⼀个 AAC数据块。

ADTS MediaInfo解析:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Hm3G5qY2-1672847932496)(C:\Users\56930\Pictures\ADTS.png)]

二进制文件:

在这里插入图片描述

ADTS头7个字节:0xFF、0xF1、0x4C、0x80、0x2B、0x9F、0xFC

0xFF---->11111111

0xF1------>11110001

0x4C------>1001100

0x80-------->10000000

0x2B------->101011

0x9F--------->10011111

0xFC--------> 11111100

4.从视频文件中提取aac音频文件实战

4.1定义采样率数组
const int sampling_frequencies[]={
    96000,  // 0x0
    88200,  // 0x1
    64000,  // 0x2
    48000,  // 0x3
    44100,  // 0x4
    32000,  // 0x5
    24000,  // 0x6
    22050,  // 0x7
    16000,  // 0x8
    12000,  // 0x9
    11025,  // 0xa
    8000   // 0xb
    // 0xc d e f是保留的
};

4.2添加ADTS文件头信息
int adts_header(char* const p_adts_header,const int data_length,const int profile,
                const int samplerate,const int channels){
    int sampling_frequency_index=3; //默认使用48000采样率
    int adtsLen=data_length+7;
    int frequencies_size=sizeof (sampling_frequencies)/sizeof (sampling_frequencies[0]);
    int i=0;
    for(i=0;i<frequencies_size;i++){
        if(sampling_frequencies[i]==samplerate){
            sampling_frequency_index=i;
            break;
        }
    }

    //采样率不支持
    if(i>=frequencies_size){
        printf("unsupport samplerate:%d\n", samplerate);
        return -1;
    }


    p_adts_header[0] = 0xff;         //syncword:0xfff                          高8bits
    p_adts_header[1] = 0xf0;         //syncword:0xfff                          低4bits
    p_adts_header[1] |= (0 << 3);    //MPEG Version:0 for MPEG-4,1 for MPEG-2  1bit
    p_adts_header[1] |= (0 << 1);    //Layer:0                                 2bits
    p_adts_header[1] |= 1;           //protection absent:1                     1bit

    p_adts_header[2] = (profile)<<6;            //profile:profile               2bits
    p_adts_header[2] |= (sampling_frequency_index & 0x0f)<<2; //sampling frequency index:sampling_frequency_index  4bits
    p_adts_header[2] |= (0 << 1);             //private bit:0                   1bit
    p_adts_header[2] |= (channels & 0x04)>>2; //channel configuration:channels  高1bit

    p_adts_header[3] = (channels & 0x03)<<6; //channel configuration:channels 低2bits
    p_adts_header[3] |= (0 << 5);               //original:0                1bit
    p_adts_header[3] |= (0 << 4);               //home:0                    1bit
    p_adts_header[3] |= (0 << 3);               //copyright id bit:0        1bit
    p_adts_header[3] |= (0 << 2);               //copyright id start:0      1bit
    p_adts_header[3] |= ((adtsLen & 0x1800) >> 11);           //frame length:value   高2bits

    p_adts_header[4] = (uint8_t)((adtsLen & 0x7f8) >> 3);     //frame length:value    中间8bits
    p_adts_header[5] = (uint8_t)((adtsLen & 0x7) << 5);       //frame length:value    低3bits
    p_adts_header[5] |= 0x1f;                                 //buffer fullness:0x7ff 高5bits
    p_adts_header[6] = 0xfc;      //‭11111100‬       //buffer fullness:0x7ff 低6bits
    // number_of_raw_data_blocks_in_frame:
    //    表示ADTS帧中有number_of_raw_data_blocks_in_frame + 1个AAC原始帧。

    return 0;
}

4.3提取aac音频文件
 int ret=-1;
    char errors[1024];

    char* filename=NULL;
    char* aac_filename=NULL;

    int audio_index=-1;
    int len=0;

    FILE *aac_fd=NULL;

    AVFormatContext* av_format_context=NULL;
    AVPacket pkt;

    av_log_set_level(AV_LOG_DEBUG);

    if(argc<3){
        av_log(NULL, LOG_LEVEL, "the count of parameters should be more than three!\n");
        return -1;
    }

    filename=argv[1];  //输入文件名称
    aac_filename=argv[2]; //输出aac文件名

    if(filename == NULL||aac_filename==NULL){
        av_log(NULL,LOG_LEVEL,"输入文件或者输出文件名为null,请检查");
        return -1;
    }

    aac_fd=fopen(aac_filename,"wb");
    if(!aac_fd){
        av_log(NULL,LOG_LEVEL,"aac_file open fieled");
        return -1;
    }

    if(ret = avformat_open_input(&av_format_context,filename,NULL,NULL)<0){
        av_strerror(ret,errors,1024);
        av_log(NULL,LOG_LEVEL,"avformat_open_input failed :%s,%d(%s)\n",
               filename,
               ret,
               errors);
    }
    // 获取解码器信息
    if(ret=avformat_find_stream_info(av_format_context,NULL)<0){
        av_strerror(ret,errors,1024);
        av_log(NULL,LOG_LEVEL,"avformat_find_stream_info failed :%s,%d(%s)\n",
               filename,
               ret,
               errors);
    }

    av_dump_format(av_format_context,0,filename,0);

    av_init_packet(&pkt);

    audio_index= av_find_best_stream(av_format_context,AVMEDIA_TYPE_AUDIO,-1,-1,NULL,0);
    if(audio_index<0){
        av_log(NULL,LOG_LEVEL,"没找到%s 流信息 从%s视频文件中\n",
               av_get_media_type_string(AVMEDIA_TYPE_AUDIO),
               filename);
        return AVERROR(EINVAL);
    }

    //打印aac的级别
    printf("audio profile :%d , FF_PROFILE_AAC_LOW:%d\n",
           av_format_context->streams[audio_index]->codecpar->level,
           FF_PROFILE_AAC_LOW);

    if(av_format_context->streams[audio_index]->codecpar->codec_id != AV_CODEC_ID_AAC)
    {
        printf("the media file no contain AAC stream, it's codec_id is %d\n",
               av_format_context->streams[audio_index]->codecpar->codec_id);
        goto failed;
    }

    //读取媒体文件并把aac数据贞写法如到本地文件
    while(av_read_frame(av_format_context,&pkt)>=0){
        if(pkt.stream_index==audio_index){
            char adts_header_buf[7]={0};
            adts_header(adts_header_buf,pkt.size,
                        av_format_context->streams[audio_index]->codecpar->profile,
                        av_format_context->streams[audio_index]->codecpar->sample_rate,
                        av_format_context->streams[audio_index]->codecpar->channels);
            // 写adts header , ts流不适用,ts流分离出来的packet带了adts header
            //第二个参数:这是要被写入的每个元素的大小,以字节为单位  char 占一个字节所以写1
            fwrite(adts_header_buf,1,7,aac_fd);
            len=fwrite(pkt.data,1,pkt.size,aac_fd); //写adts data
            if(len!=pkt.size){
                av_log(NULL, AV_LOG_DEBUG, "warning, length of writed data isn't equal pkt.size(%d, %d)\n",
                       len,
                       pkt.size);
            }
        }
        av_packet_unref(&pkt);
    }

 failed:
     if(av_format_context){
         avformat_close_input(&av_format_context);
     }

     if(aac_fd){
         fclose(aac_fd);
     }

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/140472.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python基础(二十):面向对象基础

文章目录 面向对象基础 一、理解面向对象 二、类和对象 1、理解类和对象

已知Retangle2的中心点坐标,角度,半长,半宽,计算四个顶点坐标和四个线段中点坐标

Halcon可以通过最小外接矩型算子获取Retangle2的中心点坐标&#xff0c;角度&#xff0c;半长&#xff0c;半宽。但是却没有四个顶点坐标和四个线段中点坐标。下面的代码是获取四个顶点坐标和四个线段中点坐标的方法。 gen_rectangle2 (Rectangle, 300, 200, 0.39, 100, 50) C…

E5071C网络分析仪

18320918653 E5071C 安捷伦E5071CAgilent 8.5G网络分析仪二手E5071C 频率范围&#xff1a;300 kHz至8.5GHz 在测试端口处保持125 dB动态范围&#xff08;典型值&#xff09; 宽动态范围&#xff1a;在测试端口上的动态范围> 123 dB&#xff08;典型值&#xff09; 极快的…

GDB调试技巧实战--找到打开某个文件的地方

问题&#xff1a; 本系列期望用一个简单的实例来展示一些调试技巧。不时更新。 本期问题是&#xff1a;如何才能快速定位到打开某个文件的代码&#xff1f;&#xff08;对应open/fopen, 读者可举一反三到其它系统函数&#xff09;。当面对屎山代码时&#xff0c;GDB的条件断点…

基于R的Bilibili视频数据建模及分析——变量相关性分析篇

基于R的Bilibili视频数据建模及分析——变量相关性分析篇 文章目录基于R的Bilibili视频数据建模及分析——变量相关性分析篇0、写在前面1、数据分析1.1 变量相关性分析1.2 单元数据直观展示1.3 多元数据直观展示2、多元数据与回归分析2.1 简单相关分析2.2 简单线性回归分析2.3 …

从0到1搭建大数据平台之调度系统

大家好&#xff0c;我是脚丫先生 (o^^o) 大数据平台核心之一在于数据计算&#xff0c;分为离线计算和实时计算任务。 然而任务是离不开调度的。比如&#xff1a;我们要进行定时抽取业务数据库 的数据&#xff0c;定时跑hive/spark任务&#xff0c;定时推送日报、月报指标数据…

数字档案馆系统测试前准备工作(“指标表”和“具体要求”可下载)

数字档案馆系统测试是国家档案局组织开展的一项针对县级以上国家综合档案馆数字档案馆建设情况的绩效评价工作。数字档案馆系统测试的评分依据是《数字档案馆系统测试指标表》&#xff08;后台回复“指标表”可下载&#xff09;&#xff0c;测试采用百分制。测试结果达到80分以…

华脉智联电力行业技术解决方案

一、前言 所谓电力应急&#xff0c;就是快速处理突发紧急事件尽量减少因供电中断造成的损失&#xff0c;快速修复故障设备或线路&#xff0c;使电力生产和运营恢复正常。重大施工事故、公共紧急事件、性质恶劣的违章操作、蓄意破坏、自然灾害等&#xff0c;都极易引发大规模停…

论文浅尝 | Future Event Prediction Based on Temporal KG Embedding

笔记整理&#xff1a;杨露露&#xff0c;天津大学硕士链接&#xff1a;https://www.techscience.com/csse/v44n3/49146/html动机对未来事件的准确预测在许多领域为社会带来巨大利益&#xff0c;减少损失&#xff0c;如内乱、流行病和犯罪。知识图谱是描述和建模复杂系统的通用语…

【状态估计】将变压器和LSTM与卡尔曼滤波器结合到EM算法中进行状态估计(Python代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

讨教大学|六西格玛之属性值数据一致性分析

相信大家在日常的工作中肯定会遇到这样一种情况&#xff1a;产品的质量特性属于外观特性&#xff0c;即 需要靠人工判断产品是不是符合标准。当遇到客户投诉&#xff0c;或者内部报废率比较高的时候&#xff0c;经 常会遇到客户和领导的挑战&#xff1a; 如何保证员工清楚的知…

IO、NIO、BIO傻傻分不清吗,让我对象告诉你~~

1、Stream 与 Channel stream 不会自动缓冲数据&#xff0c;channel 会利用系统提供的发送缓冲区、接收缓冲区&#xff08;更为底层&#xff09;stream 仅支持阻塞 API&#xff0c;channel 同时支持阻塞、非阻塞 API&#xff0c;网络 channel 可配合 selector 实现多路复用二者…

电商系统概要设计

设计一个最小化的电商系统&#xff0c;理清楚电商系统的架构。目前唯一能确定的是&#xff0c;老板要做一个电商系统。具体做成什么样&#xff0c;还不清楚。你需要和老板讨论需求。 你&#xff1a;“咱们要做的业务模式是C2C、B2C还是B2B呢&#xff1f;” 老板&#xff1a;“…

CES 2023:NVIDIA发力元宇宙与汽车市场

作为全球规模最大、影响最为广泛的国际消费电子展&#xff0c;2023年的CES&#xff08;Consumer Electronics Show&#xff09;在美国拉斯维加斯如约而至。众所周知&#xff0c;作为全球消费电子产业发展的风向标&#xff0c;每年的CES都汇聚了各大科技企业最先进的技术与产品。…

Renesas setting-文件导入

导入工程 1.1, 文件\从文件系统选中打开项目… 1.2, 打开xpg_app文件 链接文件 2.1&#xff0c;选中项目\右键\属性 2.2&#xff0c;删除文件&#xff08;在不同电脑中绝对路径不同&#xff09; 属性\路径和符号&#xff0c; 源位置&#xff08;delete C 文件&#xff09;&…

在未联网的计算机中部署 yum 源和 EPICS 环境

1. 基本背景 EPICS 软件仓库&#xff1a;192.168.206.234:8888 安装方式&#xff1a;yum 2. 配置跳板机 跳板机功能&#xff1a;借助ssh 隧道服务进行端口转发&#xff0c;使未联网的计算机能够访问软件仓库。 将未联网的计算机与一台申请了无线校园网的笔记本电脑进行有线…

PCB结构和谐振(一)

本文构建了包括不同的旋转角度、不同的叠层和两种不同布线方法&#xff08;W 形和蛇形线&#xff09;的测试手段&#xff0c;对应于这些设计的谐振是通过 VNA 测量获得的。然后&#xff0c;使用仿真方法来帮助我们理解这些实验结果。为了消除仿真与实验之间的差异&#xff0c;研…

【chatGPT】一位聊天永远秒回的朋友

目录一、chatGPT介绍二、通过猿如意体验三、在openAI官网体验2.1注册openAI2.2使用和问题说明一、chatGPT介绍 ChatGPT是由人工智能研究实验室OpenAI在2022年11月30日发布的全新聊天机器人模型&#xff0c;一款人工智能技术驱动的自然语言处理工具。它能够通过学习和理解人类的…

债务豁免,只是中昌数据的一次“回光返照”?

‍‍数据智能产业创新服务媒体——聚焦数智 改变商业因为经营不善&#xff0c;中昌大数据股份有限公司&#xff08;以下简称“中昌数据”&#xff09;已被实施退市风险警示&#xff0c;1月3日&#xff0c;中昌数据发布公告称收到两位债权人的《债务豁免函》&#xff0c;对中昌…

线程安全中的原子性,有序性和可见性

对于Java并发编程&#xff0c;一般来说有以下的关注点&#xff1a; 线程安全性&#xff0c;正确性。 线程的活跃性(死锁&#xff0c;活锁) 性能 其中线程的安全性问题是首要解决的问题&#xff0c;线程不安全&#xff0c;运行出来的结果和预期不一致&#xff0c;那就连基本要…