1
0

MP4AACDecoder.cpp 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. #include "MP4AACDecoder.h"
  2. #include "api.h"
  3. #include <math.h>
  4. #include <bfc/platform/minmax.h>
  5. #include "../nsutil/pcm.h"
  6. // {B6CB4A7C-A8D0-4c55-8E60-9F7A7A23DA0F}
  7. static const GUID playbackConfigGroupGUID =
  8. { 0xb6cb4a7c, 0xa8d0, 0x4c55, { 0x8e, 0x60, 0x9f, 0x7a, 0x7a, 0x23, 0xda, 0xf } };
  9. MP4AACDecoder::MP4AACDecoder()
  10. {
  11. preDelay = 0;
  12. decoder = 0;
  13. access_unit = 0;
  14. composition_unit = 0;
  15. isFloat = false;
  16. gain=1.0f;
  17. // get bps
  18. bitsPerSample = AGAVE_API_CONFIG->GetUnsigned(playbackConfigGroupGUID, L"bits", 16);
  19. if (bitsPerSample >= 24) bitsPerSample = 24;
  20. else bitsPerSample = 16;
  21. // get max channels
  22. if (AGAVE_API_CONFIG->GetBool(playbackConfigGroupGUID, L"surround", true))
  23. maxChannels = 6;
  24. else if (AGAVE_API_CONFIG->GetBool(playbackConfigGroupGUID, L"mono", false))
  25. maxChannels = 1;
  26. else
  27. maxChannels = 2;
  28. }
  29. int MP4AACDecoder::Open()
  30. {
  31. /* with FhG's API, we can't actually create a decoder until we have the ASC.
  32. best we can do right now is create the access unit object */
  33. access_unit = CAccessUnit_Create(0, 0);
  34. if (access_unit)
  35. return MP4_SUCCESS;
  36. else
  37. return MP4_FAILURE;
  38. }
  39. int MP4AACDecoder::OpenEx(size_t _bits, size_t _maxChannels, bool useFloat)
  40. {
  41. isFloat = useFloat;
  42. if (isFloat)
  43. {
  44. bitsPerSample = 32;
  45. }
  46. else
  47. {
  48. if (_bits)
  49. bitsPerSample = _bits;
  50. if (bitsPerSample >= 24) bitsPerSample = 24;
  51. else bitsPerSample = 16;
  52. }
  53. if (_maxChannels)
  54. maxChannels = _maxChannels;
  55. return Open();
  56. }
  57. int MP4AACDecoder::GetOutputProperties(unsigned int *sampleRate, unsigned int *channels, unsigned int *_bitsPerSample)
  58. {
  59. bool dummy;
  60. return GetOutputPropertiesEx(sampleRate, channels, _bitsPerSample, &dummy);
  61. }
  62. int MP4AACDecoder::GetOutputPropertiesEx(unsigned int *sampleRate, unsigned int *channels, unsigned int *_bitsPerSample, bool *useFloat)
  63. {
  64. /* TODO: verify that it's safe to call these, e.g. one frame has been decoded successfully, otherwise call MKV_NEED_MORE_INPUT */
  65. CCompositionUnit_GetSamplingRate(composition_unit, sampleRate);
  66. CCompositionUnit_GetChannels(composition_unit, channels);
  67. *_bitsPerSample = bitsPerSample;
  68. *useFloat = isFloat;
  69. return MP4_SUCCESS;
  70. }
  71. void MP4AACDecoder::Flush()
  72. {
  73. mp4AudioDecoder_Reset(decoder, MP4AUDIODECPARAM_DEFAULT, 0);
  74. }
  75. int MP4AACDecoder::GetCurrentBitrate(unsigned int *bitrate)
  76. {
  77. int current_bitrate;
  78. if (CCompositionUnit_GetProperty(composition_unit, CUBUFFER_CURRENTBITRATE, &current_bitrate) == MP4AUDIODEC_OK)
  79. {
  80. *bitrate = current_bitrate/1000;
  81. return MP4_SUCCESS;
  82. }
  83. else
  84. return MP4_GETCURRENTBITRATE_UNKNOWN;
  85. }
  86. int MP4AACDecoder::DecodeSample(void *inputBuffer, size_t inputBufferBytes, void *outputBuffer, size_t *outputBufferBytes)
  87. {
  88. CAccessUnit_Reset(access_unit);
  89. CAccessUnit_Assign(access_unit, (const unsigned char *)inputBuffer, inputBufferBytes);
  90. CCompositionUnit_Reset(composition_unit);
  91. MP4_RESULT result = mp4AudioDecoder_DecodeFrame(decoder, &access_unit, composition_unit);
  92. if (result == MP4AUDIODEC_OK)
  93. {
  94. unsigned int channels;
  95. unsigned int samples_per_channel;
  96. if (CCompositionUnit_GetSamplesPerChannel(composition_unit, &samples_per_channel) != MP4AUDIODEC_OK
  97. || CCompositionUnit_GetChannels(composition_unit, &channels) != MP4AUDIODEC_OK)
  98. return MP4_FAILURE;
  99. const float *audio_output = 0;
  100. size_t num_samples = samples_per_channel * channels;
  101. size_t output_size = num_samples * (bitsPerSample/8);
  102. if (output_size > *outputBufferBytes)
  103. return MP4_FAILURE;
  104. *outputBufferBytes = output_size;
  105. CCompositionUnit_GetPcmPtr(composition_unit, &audio_output);
  106. if (!isFloat)
  107. {
  108. nsutil_pcm_FloatToInt_Interleaved_Gain(outputBuffer, audio_output, bitsPerSample, num_samples, gain/32768.0f);
  109. }
  110. else
  111. {
  112. for (size_t i = 0;i != num_samples;i++)
  113. ((float *)outputBuffer)[i] = audio_output[i] * gain / 32768.0f;
  114. }
  115. return MP4_SUCCESS;
  116. }
  117. else
  118. return MP4_FAILURE;
  119. }
  120. int MP4AACDecoder::OutputFrameSize(size_t *frameSize)
  121. {
  122. if (!decoder)
  123. return MP4_FAILURE;
  124. unsigned int samples_per_channel;
  125. unsigned int channels;
  126. if (CCompositionUnit_GetSamplesPerChannel(composition_unit, &samples_per_channel) != MP4AUDIODEC_OK
  127. || CCompositionUnit_GetChannels(composition_unit, &channels) != MP4AUDIODEC_OK)
  128. return MP4_FAILURE;
  129. *frameSize = samples_per_channel*channels;
  130. return MP4_SUCCESS;
  131. }
  132. int MP4AACDecoder::AudioSpecificConfiguration(void *buffer, size_t buffer_size) // reads ASC block from mp4 file
  133. {
  134. // TODO: error check
  135. if (buffer && buffer_size)
  136. {
  137. CSAudioSpecificConfig asc;
  138. memset(&asc, 0, sizeof(asc));
  139. if (mp4AudioDecoder_ascParse((const unsigned char *)buffer, buffer_size, &asc) == MP4AUDIODEC_OK)
  140. {
  141. CSAudioSpecificConfig *asc_array = &asc;;
  142. decoder = mp4AudioDecoder_Create(&asc_array, 1);
  143. if (decoder)
  144. {
  145. mp4AudioDecoder_SetParam(decoder, TDL_MODE, SWITCH_OFF);
  146. mp4AudioDecoder_SetParam(decoder, CONCEALMENT_ENERGYINTERPOLATION, SWITCH_OFF);
  147. composition_unit = CCompositionUnit_Create(max(asc.m_channels, 8), asc.m_samplesPerFrame * 2, asc.m_samplingFrequency, 6144, CUBUFFER_PCMTYPE_FLOAT);
  148. return MP4_SUCCESS;
  149. }
  150. }
  151. }
  152. return MP4_FAILURE;
  153. }
  154. void MP4AACDecoder::Close()
  155. {
  156. mp4AudioDecoder_Destroy(&decoder);
  157. CAccessUnit_Destroy(&access_unit);
  158. CCompositionUnit_Destroy(&composition_unit);
  159. }
  160. int MP4AACDecoder::CanHandleCodec(const char *codecName)
  161. {
  162. return !strcmp(codecName, "mp4a");
  163. }
  164. int MP4AACDecoder::CanHandleType(uint8_t type)
  165. {
  166. switch (type)
  167. {
  168. case MP4_TYPE_MPEG4_AUDIO:
  169. return 1;
  170. case MP4_TYPE_MPEG2_AAC_LC_AUDIO:
  171. return 1;
  172. default:
  173. return 0;
  174. }
  175. }
  176. int MP4AACDecoder::CanHandleMPEG4Type(uint8_t type)
  177. {
  178. switch (type)
  179. {
  180. case MP4_MPEG4_TYPE_AAC_LC_AUDIO:
  181. case MP4_MPEG4_TYPE_AAC_HE_AUDIO:
  182. case MP4_MPEG4_TYPE_PARAMETRIC_STEREO:
  183. return 1;
  184. default:
  185. return 0;
  186. }
  187. }
  188. #ifdef CBCLASS
  189. #undef CBCLASS
  190. #endif
  191. #define CBCLASS MP4AACDecoder
  192. START_DISPATCH;
  193. CB(MPEG4_AUDIO_OPEN, Open)
  194. CB(MPEG4_AUDIO_OPEN_EX, OpenEx)
  195. CB(MPEG4_AUDIO_ASC, AudioSpecificConfiguration)
  196. CB(MPEG4_AUDIO_BITRATE, GetCurrentBitrate)
  197. CB(MPEG4_AUDIO_FRAMESIZE, OutputFrameSize)
  198. CB(MPEG4_AUDIO_OUTPUTINFO, GetOutputProperties)
  199. CB(MPEG4_AUDIO_OUTPUTINFO_EX, GetOutputPropertiesEx)
  200. CB(MPEG4_AUDIO_DECODE, DecodeSample)
  201. VCB(MPEG4_AUDIO_FLUSH, Flush)
  202. VCB(MPEG4_AUDIO_CLOSE, Close)
  203. CB(MPEG4_AUDIO_HANDLES_CODEC, CanHandleCodec)
  204. CB(MPEG4_AUDIO_HANDLES_TYPE, CanHandleType)
  205. CB(MPEG4_AUDIO_HANDLES_MPEG4_TYPE, CanHandleMPEG4Type)
  206. CB(MPEG4_AUDIO_SET_GAIN, SetGain)
  207. END_DISPATCH;