加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

aac的格式, 以及faad解码

(2014-02-28 10:27:59)
一. ADTS 格式
ADTS全称是(Audio Data Transport Stream),是AAC的一种十分常见的传输格式。
一般的AAC解码器都需要把AAC的ES流打包成ADTS的格式,一般是在AAC ES流前添加7个字节的ADTS header。也就是说你可以吧ADTS这个头看作是AAC的frameheader。

 

ADTS AAC
ADTS_header AAC ES ADTS_header AAC ES
...
ADTS_header AAC ES


ADTS内容及结构

ADTS 头中相对有用的信息 采样率、声道数、帧长度。想想也是,我要是解码器的话,你给我一堆得AAC音频ES流我也解不出来。每一个带ADTS头信息的AAC流会清晰的告送解码器他需要的这些信息。

一般情况下ADTS的头信息都是7个字节,分为2部分:

adts_fixed_header();

adts_variable_header();

http://my.csdn.net/uploads/201203/31/1333164211_8586.jpg以及faad解码" />


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

ID:MPEG Version: 0 for MPEG-4, 1 for MPEG-2

Layer:always: '00'

profile:表示使用哪个级别的AAC,有些芯片只支持AAC LC 。在MPEG-2 AAC中定义了3种:

http://my.csdn.net/uploads/201203/31/1333165759_1644.jpg以及faad解码" />

sampling_frequency_index:表示使用的采样率下标,通过这个下标在 Sampling Frequencies[ ]数组中查找得知采样率的值。

 

There are 13 supported frequencies:

  • 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
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
http://my.csdn.net/uploads/201203/31/1333171714_8159.jpg以及faad解码" />

frame_length : 一个ADTS帧的长度包括ADTS头和AAC原始流.

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

将AAC打包成ADTS格式

通过对ADTS格式的了解,很容易就能把AAC打包成ADTS。我们只需得到封装格式里面关于音频采样率、声道数、元数据长度、aac格式类型等信息。然后在每个AAC原始流前面加上个ADTS头就OK了。

附上ffmpeg添加ADTS头的代码:

static int adts_write_packet(AVFormatContext *s, AVPacket *pkt)

{

    ADTSContext *adts = s->priv_data;

    AVIOContext *pb = s->pb;

    uint8_t buf[ADTS_HEADER_SIZE];


    if (!pkt->size)

        return 0;

    if (adts->write_adts) {

        ff_adts_write_frame_header(adts, buf, pkt->size, adts->pce_size);

        avio_write(pb, buf, ADTS_HEADER_SIZE);

        if (adts->pce_size) {

            avio_write(pb, adts->pce_data, adts->pce_size);

            adts->pce_size = 0;

        }

    }

    avio_write(pb, pkt->data, pkt->size);

    avio_flush(pb);


    return 0;

}

int ff_adts_write_frame_header(ADTSContext *ctx,

                               uint8_t *buf, int size, int pce_size)

{

    PutBitContext pb;


    init_put_bits(&pb, buf, ADTS_HEADER_SIZE);


   

    put_bits(&pb, 12, 0xfff);  

    put_bits(&pb, 1, 0);        

    put_bits(&pb, 2, 0);        

    put_bits(&pb, 1, 1);        

    put_bits(&pb, 2, ctx->objecttype);

    put_bits(&pb, 4, ctx->sample_rate_index);

    put_bits(&pb, 1, 0);        

    put_bits(&pb, 3, ctx->channel_conf);

    put_bits(&pb, 1, 0);        

    put_bits(&pb, 1, 0);        


   

    put_bits(&pb, 1, 0);        

    put_bits(&pb, 1, 0);        

    put_bits(&pb, 13, ADTS_HEADER_SIZE + size + pce_size);

    put_bits(&pb, 11, 0x7ff);  

    put_bits(&pb, 2, 0);        


    flush_put_bits(&pb);


    return 0;

 

}



二. ADIF

Audio Data Interchange Format 音频数据交换格式。这种格式的特征是可以确定的找到这个音频数据的开始,不需进行在音频数据流中间开始的解码,即它的解码必须在明确定义的开始处进行。故这种格式常用在磁盘文件中。

AACADIF格式见下图:

      http://hi.csdn.net/attachment/201009/10/0_1284105267YFfk.gif以及faad解码" />


三. faad解码aac

 iRet = pcmRender.init(2, 44100, 16, NULL);

static unsigned char frame[FRAME_MAX_LEN];

 

unsigned long samplerate;

unsigned char channels;

NeAACDecHandle decoder = 0;


size_t data_size = 0;

size_t size = 0;


NeAACDecFrameInfo frame_info;

unsigned char* input_data = buffer;

unsigned char* pcm_data = NULL;

static int iFlag = 0;

int iRead = 0;


while (m_iThreadFlag && (data_size = ReadData(NULL, buffer+iRead, BUFFER_MAX_LEN-iRead)))

{

#if 1

data_size += iRead;

if (0 == iFlag)

{

if(get_one_ADTS_frame(buffer, data_size, frame, &size, &iRead) < 0)

{

continue ;

}


decoder = NeAACDecOpen();    

//initialize decoder

NeAACDecInit(decoder, frame, size, &samplerate, &channels);

printf("samplerate %d, channels %d\n", samplerate, channels);

iFlag = 1;


}

input_data = buffer;

while(m_iThreadFlag && get_one_ADTS_frame(input_data, data_size, frame, &size, &iRead) == 0)

{

//decode ADTS frame

pcm_data = (unsigned char*)NeAACDecDecode(decoder, &frame_info, frame, size); 


if(frame_info.error > 0)

{

printf("%s\n",NeAACDecGetErrorMessage(frame_info.error));            


}

else if(pcm_data && frame_info.samples > 0)

{

static FILE *fp1 = NULL;

if (NULL == fp1)

{

fp1 = fopen("F:\\6.pcm", "wb");

}

if (fp1)

{

fwrite(pcm_data, 1, frame_info.samples * frame_info.channels,fp1);

fflush(fp1);

}

Player((char*)pcm_data, frame_info.samples * frame_info.channels);

}        

data_size -= size;

input_data += size;

#endif

}

NeAACDecClose(decoder);

0

阅读 收藏 喜欢 打印举报/Report
前一篇:ffmpeg 学生
后一篇:MP3文件
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有