扫盲
AAC实际上是高级音频编码的缩写,它是MPEG-2规范的一部分。但2000年,MPEG-4标准出台,AAC从新整合了其特性,故现又称 MPEG-4 AAC,即m4a。以上也就是说以.aac和.m4a结尾的都可以称为aac。
目前成熟的解码器
目的:把faad的aac解码器移植到android平台上来。
方法:参考demo移植解码器。
实现方式:
附上部分代码
首先定义结构体:
#define MAX_BUFFER 20480 //20K
#define MIN_BUFFER 2048 /* FAAD file buffering routines */ typedef struct { long bytes_into_buffer; long bytes_consumed; long file_offset; long size; unsigned char *buffer; int at_eof; FILE *infile; } aac_buffer; struct AACFileHandle { FILE* file;//文件 int size;//文件长度 int bitrate;//比特率 int samplerate;//抽样率 float duration;//播放时长 int channelNum;//声道数 int fileType;//文件类型(1:ADTS,2: ADIF) int mp4file; int track; long sampleId; mp4ff_t *infile; mp4AudioSpecificConfig *mp4ASC; mp4ff_callback_t *mp4cb; aac_buffer buffer;//aac缓存信息 NeAACDecHandle hDecoder; };
打开文件操作:
int mp4file = 0;
int index = findFreeHandle( ); if( index == -1 ) return -1; //取得文件全路径 const char* fileString = env->GetStringUTFChars(file, NULL); FILE* fileHandle = fopen( fileString, "rb" );//以只读的方式打开文件 env->ReleaseStringUTFChars(file, fileString);//释放文件路径 if( fileHandle == 0 )//如果打开文件失败返回-1 return -1; //*********************以上打开文件完毕******************************** AACFileHandle* aacHandle = new AACFileHandle(); if(aacHandle == NULL){ return -1; } memset(aacHandle, 0, sizeof(AACFileHandle)); //读取文件头,判断是否是MP4 unsigned char header[8]; fread(header, 1, 8, fileHandle); rewind(fileHandle); if (header[4] == 'f' && header[5] == 't' && header[6] == 'y' && header[7] == 'p') mp4file = 1; aacHandle->mp4file = mp4file; if (!mp4file){ if(open_aac_file(fileHandle, aacHandle) < 0) { fclose(fileHandle); delete aacHandle; return -1; } }else{//mp4 aac if(open_mp4_file(fileHandle, aacHandle) < 0) { fclose(fileHandle); delete aacHandle; return -1; } } handles[index] = aacHandle; // AACD_TRACE("index :" + index); return index;
解码操作:
AACD_TRACE("start"); //加传入参数的判断 if(aacHandle == NULL || size <=0){ //这部分返回0是因为外部判断的是0 return 0; } // size = size >>1; // if(fp == NULL) // { // fp = fopen("sdcard/temp222.wav", "a+b"); // } int pos =0; AACD_TRACE("read_aac_samples, isSeeking %d",isSeeking); jshort * target = env->GetShortArrayElements(buffer, NULL); if(aacHandle->buffer.bytes_into_buffer == 0) { fill_buffer(&aacHandle->buffer, 1); } int times = 0; void *sample_buffer = NULL; while(pos < size && aacHandle->buffer.bytes_into_buffer != 0){ if(isSeeking)return -1; NeAACDecFrameInfo frameInfo; sample_buffer = NeAACDecDecode(aacHandle->hDecoder, &frameInfo, aacHandle->buffer.buffer, aacHandle->buffer.bytes_into_buffer); if((frameInfo.error == 0) && (frameInfo.samples >= 0) && sample_buffer != NULL) { times++; if((pos + frameInfo.samples) > size){ AACD_TRACE("samples: %d, pos: %d, size %d", frameInfo.samples, pos, size); break; } aacHandle->sampleId += 1; // if(pos + frameInfo.samples < size){ // AACD_TRACE("samples %d", frameInfo.samples); // aacHandle->buffer.bytes_consumed = 0; memmove((void *)(target + pos), (void *)sample_buffer, sizeof(short) * frameInfo.samples); // memset(sample_buffer, 0, sizeof(short) * frameInfo.samples); pos += frameInfo.samples; advance_buffer(&aacHandle->buffer, frameInfo.bytesconsumed); fill_buffer(&aacHandle->buffer, 1); // }else{ // int othersize = 0; // unsigned long bytesconsumed = 0; // if(frameInfo.samples < (size -pos)){ // othersize = frameInfo.samples; // }else{ // othersize = (size -pos); // } // AACD_TRACE( "othersize %d", othersize); // memcpy((void *)(target + pos), (void *)sample_buffer, sizeof(short) * othersize); // advance_buffer(&aacHandle->buffer, frameInfo.bytesconsumed*othersize/size); // pos += othersize; // fill_buffer(&aacHandle->buffer); // AACD_TRACE( "decodingothers %d", frameInfo.samples); // break; // } } else if(frameInfo.error != 0){ AACD_TRACE("read error %d, consumed bytes: %d", frameInfo.error, frameInfo.bytesconsumed); advance_buffer(&aacHandle->buffer, frameInfo.bytesconsumed); if (frameInfo.bytesconsumed == 0) { fseek(aacHandle->buffer.infile,aacHandle->buffer.file_offset,SEEK_SET); aacHandle->buffer.bytes_into_buffer = 0; break; } // if(aacHandle->mp4file){ // mp4ff_set_sample_position(aacHandle->infile, aacHandle->track, aacHandle->sampleId); // } } } AACD_TRACE("times : %d, pos %d, size %d", times, pos, size); env->ReleaseShortArrayElements(buffer, target, 0); return times > 0 ? pos: -1;