cfaad.cpp

来自「faac-1.25.rar音频编解码器demo」· C++ 代码 · 共 808 行 · 第 1/2 页

CPP
808
字号

void Cfaad::setFaadCfg(faacDecHandle hDecoder, CMyDecCfg Cfg)
{
faacDecConfigurationPtr	config=faacDecGetCurrentConfiguration(hDecoder);

	if(!Cfg.DefaultCfg)
	{
		config->defObjectType=Cfg.DecCfg.defObjectType;
		config->outputFormat=Cfg.DecCfg.outputFormat;
		config->defSampleRate=Cfg.DecCfg.defSampleRate;
		config->downMatrix=Cfg.DecCfg.downMatrix;
		config->useOldADTSFormat=Cfg.DecCfg.useOldADTSFormat;
		config->dontUpSampleImplicitSBR=1;
	}
	else
	{
		config->defObjectType=LC;
		config->outputFormat=FAAD_FMT_16BIT;
		config->defSampleRate=44100;
		config->downMatrix=0;
		config->useOldADTSFormat=0;
		config->dontUpSampleImplicitSBR=1;
	}
	faacDecSetConfiguration(hDecoder, config);
}
// -----------------------------------------------------------------------------------------------

void Cfaad::setDefaultFaadCfg(faacDecHandle hDecoder, BOOL showDlg)
{
	if(showDlg && ShowDlg4RawAAC)
		ShowDlg4RawAAC();

CMyDecCfg Cfg(false);
	setFaadCfg(hDecoder,Cfg);
}
// -----------------------------------------------------------------------------------------------

void Cfaad::DisplayError(char *ProcName, char *str)
{
MYINPUT *mi;
char buf[100]="";

	GlobalUnlock(hInput); // it wasn't done in getInfos()
	GLOBALLOCK(mi,hInput,MYINPUT,return);

	if(ProcName && *ProcName)
		sprintf(buf,"%s: ", ProcName);
	if(str && *str)
		strcat(buf,str);
	if(*buf && str)
		MessageBox(0, buf, APP_NAME " plugin", MB_OK|MB_ICONSTOP);

	mi->bytes_into_buffer=-1;
	GlobalUnlock(hInput);
}
// *********************************************************************************************

HANDLE Cfaad::getInfos(LPSTR lpstrFilename)
{
MYINPUT *mi;

// test tags
//CMyDecCfg cfg;	cfg.Tag.ReadMp4Tag(lpstrFilename);
//CMyDecCfg cfg;	cfg.Tag.ReadAacTag(lpstrFilename);

	GLOBALLOCK(mi,hInput,MYINPUT,return NULL);

//	mi->IsAAC=strcmpi(lpstrFilename+lstrlen(lpstrFilename)-4,".aac")==0;
	if((mi->IsMP4=IsMP4(lpstrFilename))==-1)
		return ERROR_getInfos("Error opening file");

	if(mi->IsMP4) // MP4 file ---------------------------------------------------------------------
	{
	MP4Duration			length;
	unsigned __int32	buffer_size;
	DWORD				timeScale;
	BYTE				sf;
    mp4AudioSpecificConfig mp4ASC;

		if(!(mi->mp4File=MP4Read(lpstrFilename, 0)))
			return ERROR_getInfos("Error opening file");

		if((mi->track=GetAACTrack(mi->mp4File))<0)
			return ERROR_getInfos(0); //"Unable to find correct AAC sound track");

		if(!(mi->hDecoder=faacDecOpen()))
			return ERROR_getInfos("Error initializing decoder library");

		MP4GetTrackESConfiguration(mi->mp4File, mi->track, (unsigned __int8 **)&mi->buffer, &buffer_size);
		if(!mi->buffer)
			return ERROR_getInfos("MP4GetTrackESConfiguration()");
		AudioSpecificConfig(mi->buffer, buffer_size, &mp4ASC);

        timeScale = mp4ASC.samplingFrequency;
        mi->Channels=mp4ASC.channelsConfiguration;
        sf = mp4ASC.samplingFrequencyIndex;
        mi->type = mp4ASC.objectTypeIndex;
//        mi->SBR=mp4ASC.sbr_present_flag;

		if(faacDecInit2(mi->hDecoder, mi->buffer, buffer_size, &mi->Samprate, &mi->Channels) < 0)
			return ERROR_getInfos("Error initializing decoder library");
		FREE_ARRAY(mi->buffer);

		length=MP4GetTrackDuration(mi->mp4File, mi->track);
		mi->len_ms=(DWORD)MP4ConvertFromTrackDuration(mi->mp4File, mi->track, length, MP4_MSECS_TIME_SCALE);
		mi->file_info.bitrate=MP4GetTrackBitRate(mi->mp4File, mi->track);
		mi->file_info.version=MP4GetTrackAudioType(mi->mp4File, mi->track)==MP4_MPEG4_AUDIO_TYPE ? 4 : 2;
		mi->numSamples=MP4GetTrackNumberOfSamples(mi->mp4File, mi->track);
		mi->sampleId=1;

		mi->IsSeekable=true;
		mi->LockSeeking=!mi->IsSeekable;
	}
	else // AAC file ------------------------------------------------------------------------------
	{   
	DWORD			read,
					tmp;
	BYTE			Channels4Raw=0;

		if(!(mi->aacFile=fopen(lpstrFilename,"rb")))
			return ERROR_getInfos("Error opening file"); 

		// use bufferized stream
		setvbuf(mi->aacFile,NULL,_IOFBF,32767);

		// get size of file
		fseek(mi->aacFile, 0, SEEK_END);
		mi->src_size=ftell(mi->aacFile);
		fseek(mi->aacFile, 0, SEEK_SET);

		if(!(mi->buffer=(BYTE *)malloc(FAAD_STREAMSIZE)))
			return ERROR_getInfos("Memory allocation error: mi->buffer");

		tmp=mi->src_size<FAAD_STREAMSIZE ? mi->src_size : FAAD_STREAMSIZE;
		read=fread(mi->buffer, 1, tmp, mi->aacFile);
		if(read==tmp)
		{
			mi->bytes_read=read;
			mi->bytes_into_buffer=read;
		}
		else
			return ERROR_getInfos("Read failed!");

		// skip Tag
	long tagsize;
		if(tagsize=id3v2_TagSize(mi->buffer))
		{
			if(tagsize>(long)mi->src_size)
				ERROR_getInfos("Corrupt stream!");
			if(tagsize<mi->bytes_into_buffer)
			{
				mi->bytes_into_buffer-=tagsize;
				memcpy(mi->buffer,mi->buffer+tagsize,mi->bytes_into_buffer);
			}
			else
			{
				mi->bytes_read=tagsize;
				mi->bytes_into_buffer=0;
				if(tagsize>mi->bytes_into_buffer)
					fseek(mi->aacFile, tagsize, SEEK_SET);
			}
			if(mi->src_size<mi->bytes_read+FAAD_STREAMSIZE-mi->bytes_into_buffer)
				tmp=mi->src_size-mi->bytes_read;
			else
				tmp=FAAD_STREAMSIZE-mi->bytes_into_buffer;
			read=fread(mi->buffer+mi->bytes_into_buffer, 1, tmp, mi->aacFile);
			if(read==tmp)
			{
				mi->bytes_read+=read;
				mi->bytes_into_buffer+=read;
			}
			else
				ERROR_getInfos("Read failed!");
		}

		if(get_AAC_format(lpstrFilename, &mi->file_info, &mi->seek_table, &mi->seek_table_length, 0))
			ERROR_getInfos("get_AAC_format()");
		mi->IsSeekable=mi->file_info.headertype==ADTS && mi->seek_table && mi->seek_table_length>0;
		mi->LockSeeking=!mi->IsSeekable;
/*
	aac_buffer	b;
	float		fLength;
	DWORD		headertype;
		b.infile=mi->aacFile;
		b.buffer=mi->buffer;
	    b.bytes_into_buffer=read;
		b.bytes_consumed=mi->bytes_consumed;
		b.file_offset=0;
		b.at_eof=(read!=tmp) ? 1 : 0;
		GetAACInfos(&b,&headertype,&fLength,&mi->file_info.bitrate,mi->src_size);
		mi->file_info.bitrate*=1024;
		mi->file_info.headertype=headertype;
        mi->bytes_into_buffer=b.bytes_into_buffer;
        mi->bytes_consumed=b.bytes_consumed;
		IsSeekable=false; // only mp4 can be seeked
*/
		if(!mi->FindBitrate) // open a new instance to get info from decoder
		{
		MYINPUT *miTmp;
		Cfaad	*NewInst;
			if(!(NewInst=new Cfaad()))
				return ERROR_getInfos("Memory allocation error: NewInst");

			GLOBALLOCK(miTmp,NewInst->hInput,MYINPUT,return 0);
			miTmp->FindBitrate=TRUE;
			NewInst->ShowDlg4RawAAC=ShowDlg4RawAAC;
			NewInst->pCfg=pCfg;
			if(!NewInst->getInfos(lpstrFilename))
				return ERROR_getInfos(0);
			mi->Channels=miTmp->frameInfo.channels;
			if(mi->file_info.headertype==RAW)
				mi->file_info.bitrate=miTmp->file_info.bitrate;//*mi->Channels;
			mi->Samprate=miTmp->Samprate;
			mi->file_info.headertype=miTmp->file_info.headertype;
			mi->file_info.object_type=miTmp->file_info.object_type;
			mi->file_info.version=miTmp->file_info.version;
			GlobalUnlock(NewInst->hInput);
			delete NewInst;
		}

		if(!(mi->hDecoder=faacDecOpen()))
			return ERROR_getInfos("Can't open library");
		if(mi->file_info.headertype==RAW)
			if(pCfg)
				setFaadCfg(mi->hDecoder,*pCfg);
			else
				setDefaultFaadCfg(mi->hDecoder,mi->FindBitrate);
	BYTE Channels; // faacDecInit doesn't report correctly the number of channels in raw aac files
		if((mi->bytes_consumed=faacDecInit(mi->hDecoder, mi->buffer, mi->bytes_into_buffer, &mi->Samprate, &Channels))<0)
			return ERROR_getInfos("faacDecInit()");
		mi->bytes_into_buffer-=mi->bytes_consumed;

		if(mi->FindBitrate) // get info from decoder
		{
		DWORD	Samples,
				BytesConsumed;

			if(!processData(hInput,0,0))
				return ERROR_getInfos(0);
			Samples=mi->frameInfo.samples/sizeof(short);
			BytesConsumed=mi->frameInfo.bytesconsumed;
			if(mi->file_info.headertype==RAW || !mi->file_info.bitrate)
				mi->file_info.bitrate=(BytesConsumed*8*mi->Samprate)/(Samples*2);
			if(!mi->file_info.bitrate)
				return ERROR_getInfos("Can't determine the bitrate");
		}

		mi->len_ms=(DWORD)((mi->src_size<<3)/(mi->file_info.bitrate>>10));
//		mi->len_ms=(DWORD)((1000*((float)mi->src_size*8))/mi->file_info.bitrate);
	}

	if(mi->len_ms)
		mi->dst_size=(DWORD)(mi->len_ms*((float)mi->Samprate/1000)*mi->Channels*(mi->BitsPerSample/8));
	else
		return ERROR_getInfos("Can't determine the length");

	showInfo(mi);

	GlobalUnlock(hInput);
    return hInput;
}
// *********************************************************************************************

int Cfaad::processData(HANDLE hInput, unsigned char far *bufout, long lBytes)
{
BYTE	*buffer;
DWORD	BytesDecoded=0;
char	*sample_buffer=0;
int		read;
MYINPUT	*mi;

	GLOBALLOCK(mi,hInput,MYINPUT,return 0);

	if(mi->LockSeeking)
	{
		NoSeek();
		mi->LockSeeking=false;
	}

	if(mi->IsMP4) // MP4 file --------------------------------------------------------------------------
	{   
	unsigned __int32 buffer_size=0;
    int rc;

		if(newpos_ms>-1)
		{
		MP4Duration duration=MP4ConvertToTrackDuration(mi->mp4File,mi->track,newpos_ms,MP4_MSECS_TIME_SCALE);
		MP4SampleId sampleId=MP4GetSampleIdFromTime(mi->mp4File,mi->track,duration,0);
			mi->bytes_read=(DWORD)(((float)newpos_ms*mi->file_info.bitrate)/(8*1000));
			if(seek(mi->bytes_read))  // update the slider
				return ERROR_processData(0);
			newpos_ms=-1;
		}
		do
		{
			buffer=NULL;
			if(mi->sampleId>=mi->numSamples)
				return ERROR_processData(0);

			rc=MP4ReadSample(mi->mp4File, mi->track, mi->sampleId++, (unsigned __int8 **)&buffer, &buffer_size, NULL, NULL, NULL, NULL);
			if(rc==0 || buffer==NULL)
			{
				FREE_ARRAY(buffer);
				return ERROR_processData("MP4ReadSample()");
			}

			sample_buffer=(char *)faacDecDecode(mi->hDecoder,&mi->frameInfo,buffer,buffer_size);
			BytesDecoded=mi->frameInfo.samples*sizeof(short);
			if(BytesDecoded>(DWORD)lBytes)
				BytesDecoded=lBytes;
			memmove(bufout,sample_buffer,BytesDecoded);
			FREE_ARRAY(buffer);
			// to update the slider
			mi->bytes_read+=buffer_size;
			if(seek(mi->bytes_read))
				return ERROR_processData(0);
		}while(!BytesDecoded && !mi->frameInfo.error);
	}
	else // AAC file --------------------------------------------------------------------------
	{   
		if(newpos_ms>-1)
		{
			if(mi->IsSeekable)
			{
			DWORD normalized=mi->len_ms/(mi->seek_table_length-1);
				if(normalized<1000)
					normalized=1000;
				mi->bytes_read=mi->seek_table[newpos_ms/normalized];
				fseek(mi->aacFile, mi->bytes_read, SEEK_SET);
				if(seek(mi->bytes_read))  // update the slider
					return ERROR_processData(0);
				mi->bytes_into_buffer=0;
				mi->bytes_consumed=FAAD_STREAMSIZE;
			}
			newpos_ms=-1;
		}
		buffer=mi->buffer;
		do
		{
			if(mi->bytes_consumed>0)
			{
				if(mi->bytes_into_buffer)
					memmove(buffer,buffer+mi->bytes_consumed,mi->bytes_into_buffer);

				if(mi->bytes_read<mi->src_size)
				{
				int tmp;
					if(mi->bytes_read+mi->bytes_consumed<mi->src_size)
						tmp=mi->bytes_consumed;
					else
						tmp=mi->src_size-mi->bytes_read;
					read=fread(buffer+mi->bytes_into_buffer, 1, tmp, mi->aacFile);
					if(read==tmp)
					{
						mi->bytes_read+=read;
						mi->bytes_into_buffer+=read;
					}
				}
				else
					if(mi->bytes_into_buffer)
						memset(buffer+mi->bytes_into_buffer, 0, mi->bytes_consumed);

				mi->bytes_consumed=0;

				if(	(mi->bytes_into_buffer>3 && !memcmp(mi->buffer, "TAG", 3)) ||
					(mi->bytes_into_buffer>11 && !memcmp(mi->buffer, "LYRICSBEGIN", 11)) ||
					(mi->bytes_into_buffer>8 && !memcmp(mi->buffer, "APETAGEX", 8)))
					return ERROR_processData(0);
			}

			if(mi->bytes_into_buffer<1)
				if(mi->bytes_read<mi->src_size)
					return ERROR_processData("Buffer empty!");
				else
					return ERROR_processData(0);

			sample_buffer=(char *)faacDecDecode(mi->hDecoder,&mi->frameInfo,buffer,mi->bytes_into_buffer);
			BytesDecoded=mi->frameInfo.samples*sizeof(short);
			if(bufout)
			{
				if(BytesDecoded>(DWORD)lBytes)
					BytesDecoded=lBytes;
				if(sample_buffer && BytesDecoded && !mi->frameInfo.error)
					memmove(bufout,sample_buffer,BytesDecoded);
			}
			else // Data needed to decode Raw files
			{
				mi->Channels=mi->frameInfo.channels;
				mi->file_info.object_type=mi->frameInfo.object_type;
			}
		    mi->bytes_consumed+=mi->frameInfo.bytesconsumed;
			mi->bytes_into_buffer-=mi->bytes_consumed;
		}while(!BytesDecoded && !mi->frameInfo.error);
	} // END AAC file --------------------------------------------------------------------------

	if(mi->frameInfo.error)
		return ERROR_processData((char *)faacDecGetErrorMessage(mi->frameInfo.error));

	showProgress(mi);

	GlobalUnlock(hInput);
    return BytesDecoded;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?