aac解码器之郁闷(二)

扫盲

       AAC实际上是高级音频编码的缩写,它是MPEG-2规范的一部分。但2000年,MPEG-4标准出台,AAC从新整合了其特性,故现又称 MPEG-4 AAC,即m4a。以上也就是说以.aac和.m4a结尾的都可以称为aac。

 

目前成熟的解码器

  • opencore的opencore-aacdec
  • ffmpeg 的aac解码器,当然还包括很多其他格式的音频视频解码器。
  • faad 解码器

目的:把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;

猜你喜欢

转载自yangzc106.iteye.com/blog/1646678