赞
踩
前言
本demo是使用的开源项目faad2将aac数据解码成pcm数据。
faad2的编译:(faad2下载地址:https://sourceforge.net/projects/faac/files/faad2-src/faad2-2.8.0/)
tar xzf faad2-2.8.8.tar.gz
cd faad2-2.8.8/
./configure --prefix=$PWD/_install
make
make install
demo的编译使用:
$ make clean && make
$
$ ./aac2pcm
Usage:
./aac2pcm <in aac file> <out pcm file>
Examples:
./aac2pcm ./audio/test1_44100_stereo.aac out1_44100_16bit_stereo.pcm
./aac2pcm ./audio/test2_8000_mono.aac out2_16000_16bit_stereo.pcm # output [samplerate] and [channels] will be auto configured.
$ tree . ├── aac_adts.c ├── aac_adts.h ├── audio │ ├── out1_44100_16bit_stereo.pcm │ ├── out2_16000_16bit_stereo.pcm │ ├── test1_44100_stereo.aac │ └── test2_8000_mono.aac ├── docs │ └── 用faad解码AAC(ADTS封装)_gavinr的博客-CSDN博客_faad解码aac.mhtml ├── include │ ├── faad.h │ └── neaacdec.h ├── lib │ └── libfaad.a ├── main.c ├── Makefile └── README.md
#include "aac_adts.h" int getAdtsFrame(FILE *fp, uint8_t *pAdtsFrameData, T_AdtsHeader *ptAdtsHeaderInfo) { uint32_t readBytes = 0; if(!fp || !pAdtsFrameData || !ptAdtsHeaderInfo) return -1; // ADTS header size is AAC_ADTS_HEADER_SIZE(=7) bytes readBytes = fread(pAdtsFrameData, 1, AAC_ADTS_HEADER_SIZE, fp); if(readBytes <= 0) return -2; ptAdtsHeaderInfo->syncword = (pAdtsFrameData[0] << 4 ) | (pAdtsFrameData[1] >> 4); ptAdtsHeaderInfo->id = (pAdtsFrameData[1] & 0x08) >> 3; ptAdtsHeaderInfo->layer = (pAdtsFrameData[1] & 0x06) >> 1; ptAdtsHeaderInfo->protection_absent = pAdtsFrameData[1] & 0x01; ptAdtsHeaderInfo->profile = (pAdtsFrameData[2] & 0xc0) >> 6; ptAdtsHeaderInfo->sampling_freq_index = (pAdtsFrameData[2] & 0x3c) >> 2; ptAdtsHeaderInfo->private_bit = (pAdtsFrameData[2] & 0x02) >> 1; ptAdtsHeaderInfo->channel_configuration = (((pAdtsFrameData[2] & 0x01) << 2) | ((pAdtsFrameData[3] & 0xc0) >> 6)); ptAdtsHeaderInfo->original_copy = (pAdtsFrameData[3] & 0x20) >> 5; ptAdtsHeaderInfo->home = (pAdtsFrameData[3] & 0x10) >> 4; ptAdtsHeaderInfo->copyright_identification_bit = (pAdtsFrameData[3] & 0x08) >> 3; ptAdtsHeaderInfo->copyright_identification_start = (pAdtsFrameData[3] & 0x04) >> 2; ptAdtsHeaderInfo->aac_frame_length = ((pAdtsFrameData[3] & 0x03) << 11) | ((pAdtsFrameData[4] & 0xFF) << 3) | ((pAdtsFrameData[5] & 0xE0) >> 5); ptAdtsHeaderInfo->adts_buffer_fullness = ((pAdtsFrameData[5] & 0x1f) << 6 | (pAdtsFrameData[6] & 0xfc) >> 2); ptAdtsHeaderInfo->number_of_raw_data_blocks_in_frame = (pAdtsFrameData[6] & 0x03); if (ptAdtsHeaderInfo->syncword != 0xFFF) return -3; /* read the remaining frame of ADTS data outside the AAC_ADTS_HEADER_SIZE(=7) bytes header, * and it should be written after offsetting the header by AAC_ADTS_HEADER_SIZE(=7) bytes */ readBytes = fread(pAdtsFrameData + AAC_ADTS_HEADER_SIZE, 1, ptAdtsHeaderInfo->aac_frame_length - AAC_ADTS_HEADER_SIZE, fp); if(readBytes <= 0) return -4; return 0; }
#ifndef __AAC_ADTS_H__ #define __AAC_ADTS_H__ #include <stdio.h> #include <stdint.h> #define AAC_ADTS_HEADER_SIZE (7) #define MAX_ADTS_SIZE (1024) /* 1K Bytes */ typedef enum{ MPEG_4 = 0x0, MPEG_2 = 0x1, }aac_id_t; typedef enum{ SFI_96000 = 0x0, SFI_88200 = 0x1, SFI_64000 = 0x2, SFI_48000 = 0x3, SFI_44100 = 0x4, SFI_32000 = 0x5, SFI_24000 = 0x6, SFI_22050 = 0x7, SFI_16000 = 0x8, SFI_12000 = 0x9, SFI_11025 = 0xa, SFI_8000 = 0xb, SFI_7350 = 0xc, SFI_ERROR = 0xd, }sampling_freq_index_t; /* AAC(ADTS) Header element member. * [Note: It is not stored as defined type size!!!] */ typedef struct{ /* fixed header */ uint32_t syncword; // 12bit '1111 1111 1111' is stand by ADTS frame uint32_t id; // 1 bit 0 for MPEG-4, 1 for MPEG-2 uint32_t layer; // 2 bit always '00' uint32_t protection_absent; // 1 bit 1 not crc, 0 have crc 1 uint32_t profile; // 2 bit AAC profile, '01' for AAC-LC uint32_t sampling_freq_index; // 4 bit reference to 'sampling_freq_index_t' uint32_t private_bit; // 1 bit always '0' uint32_t channel_configuration; // 3 bit channels count uint32_t original_copy; // 1 bit always '0' uint32_t home; // 1 bit /* varible header */ uint32_t copyright_identification_bit; // 1 bit always '0' uint32_t copyright_identification_start; // 1 bit always '0' uint32_t aac_frame_length; // 13bit length of [adts header] + [adts data] uint32_t adts_buffer_fullness; // 11bit 0x7FF stand by varible bit rate uint32_t number_of_raw_data_blocks_in_frame; // 2 bit always '00', number of AAC Frames(RDBs) in ADTS frame minus 1 }T_AdtsHeader, *PT_AdtsHeader; /************************************************************************ * function describe: get one frame aac(adts, include adts header) from * aac file. * params: * [fp]: aac file handler.(in) * [pAdtsFrameData]: the function will fill the aac data in it, must be * alloced memory before call this function.(out) * [ptAdtsHeaderInfo]: AAC-ADTS header information in this frame.(out) * return: 0-success other-error ************************************************************************/ int getAdtsFrame(FILE *fp, uint8_t *pAdtsFrameData, T_AdtsHeader *ptAdtsHeaderInfo); #endif /* __AAC_ADTS_H__ */
#include <stdio.h> #include <stdlib.h> #include "aac_adts.h" #include "faad.h" #define MAX_DEC_SIZE (128 * 1024) int main(int argc, char *argv[]) { int ret = -1; FILE *fpAAC = NULL; FILE *fpPCM = NULL; unsigned char *aacBuf = NULL; unsigned char *pcmPtr = NULL; unsigned char channels = 0; unsigned long sampleRate = 0; T_AdtsHeader adtsHeader = {}; NeAACDecHandle aacDecHandler = 0; NeAACDecFrameInfo aacDecFrameInfo = {}; uint32_t audioSampleRate = -1; if(argc != 3) { printf("Usage:\n" " %s <in aac file> <out pcm file>\n" "Examples:\n" " %s ./audio/test1_44100_stereo.aac out1_44100_16bit_stereo.pcm\n" " %s ./audio/test2_8000_mono.aac out2_16000_16bit_stereo.pcm # output [samplerate] and [channels] will be auto configured.\n", argv[0], argv[0], argv[0]); return -1; } /* open file */ fpAAC = fopen(argv[1], "rb"); fpPCM = fopen(argv[2], "wb"); if(!fpAAC || !fpPCM) { printf("[%s:%d] open <%s> or <%s> file failed!\n", __FUNCTION__, __LINE__, argv[1], argv[2]); goto exit; } /* alloc memory */ aacBuf = (unsigned char *)malloc(MAX_DEC_SIZE); if(!aacBuf) { printf("[%s:%d] alloc memory for aacBuf failed!\n", __FUNCTION__, __LINE__); goto exit; } /* aac decode 1/4: open aac decoder */ aacDecHandler = NeAACDecOpen(); /* use to configure decoder params */ ret = getAdtsFrame(fpAAC, aacBuf, &adtsHeader); if(ret < 0) { if(ret == -2) { printf("aac file end!\n"); goto exit; } else { printf("[%s:%d] get adts frame failed with %d!\n", __FUNCTION__, __LINE__, ret); goto exit; } } else { fseek(fpAAC, 0, SEEK_SET); // reset /* aac decode 2/4: init aac decoder params */ NeAACDecInit(aacDecHandler, aacBuf, adtsHeader.aac_frame_length, &sampleRate, &channels); printf("\e[32m>>> will be decoded output with [samplerate: %lu], [channels: %d]<<<\e[0m\n", sampleRate, channels); } while(1) { ret = getAdtsFrame(fpAAC, aacBuf, &adtsHeader); if(ret < 0) { if(ret == -2) { printf("aac file end!\n"); break; } else { printf("[%s:%d] get adts frame failed with %d!\n", __FUNCTION__, __LINE__, ret); goto exit; } } //printf("get one adts frame with size: %d\n", adtsHeader.aac_frame_length); /* aac decode 3/4: decode */ pcmPtr = (unsigned char*)NeAACDecDecode(aacDecHandler, &aacDecFrameInfo, aacBuf, adtsHeader.aac_frame_length/* include header */); if(aacDecFrameInfo.error > 0) { printf("[%s:%d] %s\n", __FUNCTION__, __LINE__, NeAACDecGetErrorMessage(aacDecFrameInfo.error)); goto exit; } else if(pcmPtr && aacDecFrameInfo.samples > 0) { printf("<in> [aac frame size: %lu] [header type: %s] " "[profile: %s] | <out> [samplerate: %lu] [samples cnt: %lu] [channels: %d] \n", aacDecFrameInfo.bytesconsumed, aacDecFrameInfo.header_type == 2 ? "ADTS" : "Other", aacDecFrameInfo.object_type == 2 ? "LC" : "Other", aacDecFrameInfo.samplerate, aacDecFrameInfo.samples, aacDecFrameInfo.channels); fwrite(pcmPtr, 1, aacDecFrameInfo.samples * aacDecFrameInfo.channels, fpPCM); } else { printf("[%s:%d] Unknown decode error!\n", __FUNCTION__, __LINE__); } } /* aac decode 1/4: close aac decoder */ NeAACDecClose(aacDecHandler); printf("\e[32mSuccess!\e[0m\n"); exit: if(fpAAC) fclose(fpAAC); if(fpPCM) {fflush(fpPCM); fclose(fpPCM);} if(aacBuf) free(aacBuf); return 0; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。