| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159 | #include "MKVAACDecoder.h"#include <math.h>#include "../nsutil/pcm.h"MKVAACDecoder::MKVAACDecoder(mp4AudioDecoderHandle decoder, CAccessUnitPtr access_unit, CCompositionUnitPtr composition_unit, unsigned int bps, bool floating_point): decoder(decoder), access_unit(access_unit), composition_unit(composition_unit), bps(bps), floating_point(floating_point){	}MKVAACDecoder *MKVAACDecoder::Create(const nsmkv::TrackEntryData *track_entry_data, const nsmkv::AudioData *audio_data, unsigned int preferred_bits, unsigned int max_channels, bool floating_point){	if (!floating_point)	{		if (preferred_bits >= 24) 			preferred_bits=24;		else			preferred_bits=16;	}	/*if (!max_channels)		max_channels = 8;*/	if (track_entry_data->codec_private && track_entry_data->codec_private_len)	{		CSAudioSpecificConfig asc;				memset(&asc, 0, sizeof(asc));		if (mp4AudioDecoder_ascParse((const unsigned char *)track_entry_data->codec_private, track_entry_data->codec_private_len, &asc) == MP4AUDIODEC_OK)		{			CSAudioSpecificConfig *asc_array = &asc;;			mp4AudioDecoderHandle decoder = mp4AudioDecoder_Create(&asc_array, 1);			if (decoder)			{				mp4AudioDecoder_SetParam(decoder, TDL_MODE, SWITCH_OFF);				mp4AudioDecoder_SetParam(decoder, CONCEALMENT_ENERGYINTERPOLATION, SWITCH_OFF);				CCompositionUnitPtr composition_unit = CCompositionUnit_Create(max(asc.m_channels, 8), asc.m_samplesPerFrame * 2, asc.m_samplingFrequency, 6144, CUBUFFER_PCMTYPE_FLOAT);				if (composition_unit)				{					CAccessUnitPtr access_unit = CAccessUnit_Create(0, 0);					if (access_unit)					{						return new MKVAACDecoder(decoder, access_unit, composition_unit, preferred_bits, floating_point);					}					CCompositionUnit_Destroy(&composition_unit);				}				mp4AudioDecoder_Destroy(&decoder);			}		}	}	return 0;}int MKVAACDecoder::GetOutputProperties(unsigned int *sampleRate, unsigned int *channels, unsigned int *bitsPerSample, bool *isFloat){		/* TODO: verify that it's safe to call these, e.g. one frame has been decoded successfully, otherwise call MKV_NEED_MORE_INPUT */	CCompositionUnit_GetSamplingRate(composition_unit, sampleRate);	CCompositionUnit_GetChannels(composition_unit, channels);	*bitsPerSample = bps;	*isFloat = floating_point;	return MKV_SUCCESS;}void MKVAACDecoder::Flush(){	mp4AudioDecoder_Reset(decoder, MP4AUDIODECPARAM_DEFAULT, 0);}int MKVAACDecoder::OutputFrameSize(size_t *frame_size){		if (!decoder)		return MKV_FAILURE;	unsigned int samples_per_channel;	unsigned int channels;	if (CCompositionUnit_GetSamplesPerChannel(composition_unit, &samples_per_channel) != MP4AUDIODEC_OK		|| 	CCompositionUnit_GetChannels(composition_unit, &channels) != MP4AUDIODEC_OK)		return MKV_FAILURE;	*frame_size = samples_per_channel*channels;	return MKV_SUCCESS;	}void MKVAACDecoder::Close(){	mp4AudioDecoder_Destroy(&decoder);	CAccessUnit_Destroy(&access_unit);	CCompositionUnit_Destroy(&composition_unit);	delete this;}int MKVAACDecoder::DecodeBlock(void *inputBuffer, size_t inputBufferBytes, void *outputBuffer, size_t *outputBufferBytes){	CAccessUnit_Reset(access_unit);	CAccessUnit_Assign(access_unit, (const unsigned char *)inputBuffer, inputBufferBytes);	CCompositionUnit_Reset(composition_unit);	MP4_RESULT result = mp4AudioDecoder_DecodeFrame(decoder, &access_unit, composition_unit);	if (result == MP4AUDIODEC_OK)	{		unsigned int channels;		unsigned int samples_per_channel;		CCompositionUnit_GetSamplesPerChannel(composition_unit, &samples_per_channel);		CCompositionUnit_GetChannels(composition_unit, &channels);		const float *audio_output = 0;		size_t num_samples = samples_per_channel * channels;		size_t output_size = num_samples * (bps/8);		if (output_size > *outputBufferBytes)			return MKV_FAILURE;		*outputBufferBytes = output_size;		CCompositionUnit_GetPcmPtr(composition_unit, &audio_output);		if (!floating_point)		{			nsutil_pcm_FloatToInt_Interleaved_Gain(outputBuffer, audio_output, bps, num_samples, 1.0f/32768.0f);		}		else		{			for (size_t i = 0;i != num_samples;i++)				((float *)outputBuffer)[i] = audio_output[i] / 32768.0f;		}		return MKV_SUCCESS;	}	else		return MKV_FAILURE;}#define CBCLASS MKVAACDecoderSTART_DISPATCH;CB(OUTPUT_FRAME_SIZE, OutputFrameSize)CB(GET_OUTPUT_PROPERTIES, GetOutputProperties)CB(DECODE_BLOCK, DecodeBlock)VCB(FLUSH, Flush)VCB(CLOSE, Close)END_DISPATCH;#undef CBCLASSint MKVDecoder::CreateAudioDecoder(const char *codec_id, const nsmkv::TrackEntryData *track_entry_data, const nsmkv::AudioData *audio_data, unsigned int preferred_bits, unsigned int max_channels,bool floating_point, ifc_mkvaudiodecoder **decoder){	if (!strcmp(codec_id, "A_AAC"))	{		MKVAACDecoder *aac_decoder = MKVAACDecoder::Create(track_entry_data, audio_data, preferred_bits, max_channels, floating_point);		if (aac_decoder)		{			*decoder = aac_decoder;			return CREATEDECODER_SUCCESS;		}		return CREATEDECODER_FAILURE;	}	return CREATEDECODER_NOT_MINE;}#define CBCLASS MKVDecoderSTART_DISPATCH;CB(CREATE_AUDIO_DECODER, CreateAudioDecoder)END_DISPATCH;#undef CBCLASS
 |