aac编解码
2015-03-26 16:35:37 u010129251 阅读数 415

1.  AAC音频

Advanced Audio Coding。一种专为声音数据设计的文件压缩格式,与Mp3不同,它采用了全新的算法进行编码,更加高效,具有更高的“性价比”。利用AAC格式,可使人感觉声音质量没有明显降低的前提下,更加小巧。AAC格式可以用苹果iTunes转换或千千静听(六组件)。

苹果ipod、诺基亚手机也支持AAC格式的音频文件。

优点:相对于mp3,AAC格式的音质更佳,文件更小。

不足:AAC属于有损压缩的格式,与时下流行的APE、FLAC等无损格式相比音质存在“本质上”的差距。加之,传输速度更快的USB3.0和16G以上大容量MP3正在加速普及,也使得AAC头上“小巧”的光环不复存在了。

前景:以发展的眼光来看,正如“高清”正在被越来越多的人所接受一样,“无损”必定是未来音乐格式的绝对主流。AAC这种“有损”格式的前景不容乐观。


1.  测试压缩文件压缩比

 AAC:PCM  2:45

AAC:WVA   2:45

PCM:AAC:WVA  =  37:1:21

Pcm压缩成aac格式以及解压缩成WVA格式的压缩比分别为:37:1:21

2008-10-30 13:13:00 quickembed 阅读数 312

http://www.quickembed.com

ISO/IEC 13818-7, 14496-3,支持LC(Low Complexity), LD(Low Delay), PNS(Perceptual Noise Shaping) and LTP(Long Term Prediction). 单/双声道,采样率8-96kHz,码率16-576kbps.
支持TI TMS320 C54, ARM,Freescale iMX27和Intel PXA系列硬件平台。

2017-08-08 13:43:53 Joymine 阅读数 1666

这篇文章主要是对雷神关于AAC的分析,文章链接如下:
《视音频数据处理入门:AAC音频码流解析 》
http://blog.csdn.net/leixiaohua1020/article/details/50535042

简介:

AAC文件的解码,就是将AAC码流分解为AAC原始码流(裸流),将裸流作为编解码库的输入,进行编解码。
AAC原始码流就是我们所说的数据帧,主要有两种格式:ADTS帧,ADIF帧。这里主要分析ADTS帧。

ADTS帧分析

这个分析,很多文章都有详细介绍,如下文章:
《 AAC ADTS格式分析 》
http://blog.csdn.net/bsplover/article/details/7426476

每个ADTS帧包含一个header,占7个字节,主要是记录帧格式信息。

其中每个ADTS frame之间通过syncword(同步字)进行分隔。同步字为0xFFF(二进制“111111111111”)。AAC码流解析的步骤就是首先从码流中搜索0x0FFF,分离出ADTS frame;然后再分析ADTS frame的首部各个字段。(7个字节。)

ADTS内容及结构描述如下:
ADTS Header分为两个部分,可变头,不可变头。记录了采样率,声道数,帧长度等信息。共占有7个字节,也就是56bit
adts_fixed_header();
//高28bit 不可变头,信息,记录AAC级别,采样率,声道数

adts_variable_header();
//低28bit,可变头信息,记录帧长度等信息。码率可变等

vim ./libavformat/adtsenc.c 中间的操作可参考

雷神博客代码学习与分析:
以下代码段,从AAC码流中分析得到它的基本单元ADTS frame,并且简单解析ADTS frame首部的字段


int getADTSframe(unsigned char* buffer, int buf_size, unsigned char* data ,int* data_size){
    int size = 0;

    if(!buffer || !data || !data_size ){
        return -1;
    }

    while(1){
        if(buf_size  < 7 ){
            return -1;
        }
        //Sync words
        //此处的判断筛选是根据ADTS帧头部的同步字,以此来判断每一帧的开始,整个循环是处理每一帧的前7个字节(header),判断前遇到0xfff则表明则是新的一帧的开始。
        if((buffer[0] == 0xff) && ((buffer[1] & 0xf0) == 0xf0) ){
        //下面对size的赋值操作 ,实质是读取从遇到ADTS同步字开始计算,读取buffer[3]的低两位到buffer[5]的高3位,这11个bit记录着帧长度,这属于可变头部分。
            size |= ((buffer[3] & 0x03) <<11);     //high 2 bit
            size |= buffer[4]<<3;                //middle 8 bit
            size |= ((buffer[5] & 0xe0)>>5);        //low 3bit
            break;//找到一个新的adts帧,获取size之后就跳出循环
        }
        --buf_size;//可遍历的buf减少一个字节
        ++buffer;//查找下一个字节,寻找ADTS同步字,即新的一帧
    }

    if(buf_size < size){//当前这个帧是无效的帧,丢弃掉
        return 1;
    }

    memcpy(data, buffer, size);
    *data_size = size;

    return 0;
}

int simplest_aac_parser(char *url)
{
    int data_size = 0;
    int size = 0;
    int cnt=0;
    int offset=0;

    //FILE *myout=fopen("output_log.txt","wb+");
    FILE *myout=stdout;

    unsigned char *aacframe=(unsigned char *)malloc(1024*5);
    unsigned char *aacbuffer=(unsigned char *)malloc(1024*1024);

    FILE *ifile = fopen(url, "rb");
    if(!ifile){
        printf("Open file error");
        return -1;
    }

    printf("-----+- ADTS Frame Table -+------+\n");
    printf(" NUM | Profile | Frequency| Size |\n");
    printf("-----+---------+----------+------+\n");

    while(!feof(ifile)){
        data_size = fread(aacbuffer+offset, 1, 1024*1024-offset, ifile);//偏移设置,下面的分析
        unsigned char* input_data = aacbuffer;

        while(1)
        {
            int ret=getADTSframe(input_data, data_size, aacframe, &size);
            if(ret==-1){
                break;//参数不合法导致返回
            }else if(ret==1){
                memcpy(aacbuffer,input_data,data_size);
                offset=data_size;//此次的处理完成。重新从offset位置开始fread数据到指定地址,进行分析处理
                break;
            }

            char profile_str[10]={0};
            char frequence_str[10]={0};

            unsigned char profile=aacframe[2]&0xC0;//AAC 的级别,是16~17bit的值
            profile=profile>>6;
            switch(profile){
            case 0: sprintf(profile_str,"Main");break;
            case 1: sprintf(profile_str,"LC");break;
            case 2: sprintf(profile_str,"SSR");break;
            default:sprintf(profile_str,"unknown");break;
            }

            unsigned char sampling_frequency_index=aacframe[2]&0x3C;//采样率,18~21bit
            sampling_frequency_index=sampling_frequency_index>>2;
            switch(sampling_frequency_index){
            case 0: sprintf(frequence_str,"96000Hz");break;
            case 1: sprintf(frequence_str,"88200Hz");break;
            case 2: sprintf(frequence_str,"64000Hz");break;
            case 3: sprintf(frequence_str,"48000Hz");break;
            case 4: sprintf(frequence_str,"44100Hz");break;
            case 5: sprintf(frequence_str,"32000Hz");break;
            case 6: sprintf(frequence_str,"24000Hz");break;
            case 7: sprintf(frequence_str,"22050Hz");break;
            case 8: sprintf(frequence_str,"16000Hz");break;
            case 9: sprintf(frequence_str,"12000Hz");break;
            case 10: sprintf(frequence_str,"11025Hz");break;
            case 11: sprintf(frequence_str,"8000Hz");break;
            default:sprintf(frequence_str,"unknown");break;
            }


            fprintf(myout,"%5d| %8s|  %8s| %5d|\n",cnt,profile_str ,frequence_str,size);
            data_size -= size;
            input_data += size;
            cnt++;
        }   

    }
    fclose(ifile);
    free(aacbuffer);
    free(aacframe);

    return 0;
}
2015-08-03 18:18:53 xiaoyinghui 阅读数 417

   网上关于这两个库的介绍也比较多,但在项目中调试时遇到一些问题, 经过一翻调试, 终于成功, 并且把编解码做了封装, 这里把实现过程中的一些问题记录下来:

  1. FAAD 解码

    (1) 打开解码器

       NeAACDecOpen()

    (2) 修改配置

      NeAACDecConfigurationPtr cfg;

cfg = NeAACDecGetCurrentConfiguration(codec->decoder);

cfg->dontUpSampleImplicitSBR = 1;

NeAACDecSetConfiguration(codec->decoder, cfg);

注意: 这里设置cfg->dontUpSampleImplicitSBR 为1 是防止解码器修改参数, 真实的参数信息可以从 ADTS 流中获取.

(3) 解码器初始化

NeAACDecInit(codec->decoder, (unsigned char*)src, lsrc, &samplerate, &channels);

用一帧带 ADTS 的 AAC 数据初始化解码器, 获取参数

(4) 解码数据.

NeAACDecDecode(codec->decoder, &info, (unsigned char*)src, lsrc);


2. FAAC 编码

(1) 打开并初始编码器

faacEncOpen(codec->sample, codec->channels, &codec->sample_input, &codec->max_output_size);

(2) 修改编码器配置信息

这里我只修改了位宽.

cfg = faacEncGetCurrentConfiguration(codec->encoder);
switch (codec->bit_width)
{
case 16:
cfg->inputFormat = FAAC_INPUT_16BIT;
break;
case 24:
cfg->inputFormat = FAAC_INPUT_24BIT;
break;
case 32:
cfg->inputFormat = FAAC_INPUT_32BIT;
break;
}
if (!faacEncSetConfiguration(codec->encoder, cfg))

(3) 计算最大输入长度

max_input_size = codec->sample_input * codec->bit_width / 8;

(4) 编码

int len = faacEncEncode(codec->encoder, (int*)codec->encbuf, codec->sample_input,
(unsigned char*)dst, codec->max_output_size);

len 为编三后实际返回的数据长度, 可能为0

3. 封装

           

codec.h

#ifndef __AAC_CODEC_H__
#define __AAC_CODEC_H__

typedef void* HANDLE_CODEC;

HANDLE_CODEC codec_create();
void codec_release(HANDLE_CODEC handle);
void codec_init(HANDLE_CODEC handle, int sample, int bitwidth, int channel);
int codec_decode(HANDLE_CODEC handle, void* dst, int* ldst, const void* src, int lsrc);
int codec_encode(HANDLE_CODEC handle, void* dst, int* ldst, const void* src, int lsrc);

#endif

  

codec.c

#include "codec.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "faad.h"
#include "faac.h"

typedef struct _codec_t
{
	int sample;
	int bit_width;
	int channels;

	// decode
	NeAACDecHandle decoder;

	// encode
	faacEncHandle encoder;
	unsigned long sample_input;
	unsigned long max_output_size;
	int max_input_size;
	char* encbuf;
	int   write_pos;
}codec_t;

HANDLE_CODEC codec_create()
{
	codec_t* codec = (codec_t*)malloc(sizeof(codec_t));
	memset(codec, 0, sizeof(codec_t));

	return codec;
}

void codec_release(HANDLE_CODEC handle)
{
	if (handle)	{
		codec_t* codec = (codec_t*)handle;
		free(codec->encbuf);
		free(codec);
	}
}

void codec_init(HANDLE_CODEC handle, int sample, int bitwidth, int channel)
{
	if (handle)	{
		codec_t* codec = (codec_t*)handle;
		codec->sample = sample;
		codec->bit_width = bitwidth;
		codec->channels = channel;
	}
}

int codec_decode(HANDLE_CODEC handle, void* dst, int* ldst, const void* src, int lsrc)
{
	unsigned long samplerate;
	unsigned char channels;
	NeAACDecConfigurationPtr cfg;
	NeAACDecFrameInfo info;
	void* out_data;

	codec_t* codec = (codec_t*)handle;
	if (codec == 0)	{
		return -1;
	}

	if (codec->decoder == 0) {
		codec->decoder = NeAACDecOpen();
		cfg = NeAACDecGetCurrentConfiguration(codec->decoder);
		cfg->dontUpSampleImplicitSBR = 1;
		NeAACDecSetConfiguration(codec->decoder, cfg);
		NeAACDecInit(codec->decoder, (unsigned char*)src, lsrc, &samplerate, &channels);
	}

	out_data = NeAACDecDecode(codec->decoder, &info, (unsigned char*)src, lsrc);
	if (out_data && (info.samples > 0))	{
		*ldst = info.samples * info.channels;
		memcpy(dst, out_data, *ldst);
	} else {
		*ldst = 0;
	}

	return 0;
}

int codec_encode(HANDLE_CODEC handle, void* dst, int* ldst, const void* src, int lsrc)
{
	faacEncConfigurationPtr cfg;
	codec_t* codec = (codec_t*)handle;
	if (codec == 0)	{
		return -1;
	}

	if (codec->encoder == 0) {
		codec->encoder = faacEncOpen(codec->sample, codec->channels, &codec->sample_input, &codec->max_output_size);
		if (codec->encoder == 0) {  					
			return -1;
		}
		cfg = faacEncGetCurrentConfiguration(codec->encoder);
		switch (codec->bit_width)
		{
		case 16:
			cfg->inputFormat = FAAC_INPUT_16BIT;
			break;
		case 24:
			cfg->inputFormat = FAAC_INPUT_24BIT;
			break;
		case 32:
			cfg->inputFormat = FAAC_INPUT_32BIT;
			break;
		}
		
		if (!faacEncSetConfiguration(codec->encoder, cfg)) {  
			return -1;
		}
		codec->max_input_size = codec->sample_input * codec->bit_width / 8;
		if (codec->max_input_size > 0) {
			codec->encbuf = malloc(codec->max_input_size);
			codec->write_pos = 0;
		}

		if (codec->encbuf == 0) {
			return -1;
		}
	}
	
	if ((codec->write_pos + lsrc) >= codec->max_input_size)	{
		int retlen;
		int difflen = codec->max_input_size - codec->write_pos;
		memcpy(codec->encbuf + codec->write_pos, src, difflen);
		memset(dst, 0, codec->max_output_size);

		retlen = faacEncEncode(codec->encoder, (int*)codec->encbuf, codec->sample_input,
			(unsigned char*)dst, codec->max_output_size);
		*ldst = retlen;

		if ((lsrc - (codec->max_input_size - codec->write_pos)) > 0) {
			memcpy((char*)codec->encbuf, (char*)src + (codec->max_input_size - codec->write_pos), 
				lsrc - (codec->max_input_size - codec->write_pos));
			codec->write_pos = lsrc - (codec->max_input_size - codec->write_pos);
		} 
		else {
			codec->write_pos = 0;
		}
	} else {
		if ((lsrc == 0)) {
			int retlen;
			if (codec->write_pos > 0) {
				retlen = faacEncEncode(codec->encoder, (int*)codec->encbuf, codec->sample_input,
					(unsigned char*)dst, codec->max_output_size);
				codec->write_pos = 0;
			} else {
				retlen = faacEncEncode(codec->encoder, NULL, 0, (unsigned char*)dst, codec->max_output_size);
			}
			*ldst = retlen;
		} else {
			memcpy(codec->encbuf + codec->write_pos, src, lsrc);
			codec->write_pos += lsrc;
			*ldst = 0;
		}		
	}

	return 0;
}


完整源码下载地址: http://download.csdn.net/detail/xiaoyinghui/8957809


2012-02-25 20:08:29 syouhappy 阅读数 496
              AAC音频压缩已广泛应用网络视频网站、视频聊天及通信、视频监控等,关键技术上包含:aac文件封装(adts、adif),aac编解码、aac数据网络传输(rtp、hls),如下图:

AAC编解码(一)

阅读数 986

一、ADTS格式:ADTS的全称是AudioDataTransportStream。是AAC音频的传输流格式。1.adts_sequence(){ while(nextbits()==syncword){ adts_frame(); }}2.adts_frame(){ adts_fixed_header(); adts_variable_header(); if(number_...

博文 来自: audio_algorithm

AAC编解码简介

阅读数 1683

AAC代表AdvancedAudioCoding(高级音频编码),是一种由MPEG-4标准定义的有损音频压缩格式,由Fraunhofer发展,Dolby,Sony和AT&T是主要的贡献者。在使用MP4作为各种内容的容器格式的新多媒体MPEG-4标准中,它是MPEGLayerIII/MP3的天然后继者。AAC能够在一条音轨中包括48条全带宽(直到96khz)音频声道,加上15条低频增强(

博文 来自: audio_algorithm

AAC编解码原理概述

阅读数 1017

一引言 本文对AAC(AdvancedAudioCoding)音频编码算法进行总结。首先简要介绍MPEG音频(包括AAC)的发展历程及AAC概况,然后结合FAAC(FreeAAC)的代码对AAC编码算法的各个模块进行比较详尽的分析。 二AAC概况 1MPEG及其AAC音频的发展历程 1988年ISO/IEC标准化组织成立了运动图像专家组(MPEG)(正式名称ISO/IECJTC1/S...

博文 来自: qinglongzhan

一些常见的AAC编解码库

阅读数 2597

一些AAC编解码库

博文 来自: mandagod

Android音视频之使用MediaCodec编解码AAC

阅读数 2

现在的短视频、音视频通话都离不开编码和解码,今天就来聊一下音频的编解码。1.音频的基本概念在音频开发中,有些基本概念是需要了解的。采样率(SampleRate):每秒采集声音的数量,它用赫兹(Hz)来表示。采样频率越高,音频质量越好。常用的音频采样频率有:8kHz、16kHz、44.1kHz、48kHz等。声道数(Channel):一般表示声音录制时的...

博文 来自: weixin_33872566
没有更多推荐了,返回首页