MKVAACDecoder.cpp 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. #include "MKVAACDecoder.h"
  2. #include <math.h>
  3. #include "../nsutil/pcm.h"
  4. MKVAACDecoder::MKVAACDecoder(mp4AudioDecoderHandle decoder, CAccessUnitPtr access_unit, CCompositionUnitPtr composition_unit, unsigned int bps, bool floating_point)
  5. : decoder(decoder), access_unit(access_unit), composition_unit(composition_unit), bps(bps), floating_point(floating_point)
  6. {
  7. }
  8. 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)
  9. {
  10. if (!floating_point)
  11. {
  12. if (preferred_bits >= 24)
  13. preferred_bits=24;
  14. else
  15. preferred_bits=16;
  16. }
  17. /*if (!max_channels)
  18. max_channels = 8;*/
  19. if (track_entry_data->codec_private && track_entry_data->codec_private_len)
  20. {
  21. CSAudioSpecificConfig asc;
  22. memset(&asc, 0, sizeof(asc));
  23. if (mp4AudioDecoder_ascParse((const unsigned char *)track_entry_data->codec_private, track_entry_data->codec_private_len, &asc) == MP4AUDIODEC_OK)
  24. {
  25. CSAudioSpecificConfig *asc_array = &asc;;
  26. mp4AudioDecoderHandle decoder = mp4AudioDecoder_Create(&asc_array, 1);
  27. if (decoder)
  28. {
  29. mp4AudioDecoder_SetParam(decoder, TDL_MODE, SWITCH_OFF);
  30. mp4AudioDecoder_SetParam(decoder, CONCEALMENT_ENERGYINTERPOLATION, SWITCH_OFF);
  31. CCompositionUnitPtr composition_unit = CCompositionUnit_Create(max(asc.m_channels, 8), asc.m_samplesPerFrame * 2, asc.m_samplingFrequency, 6144, CUBUFFER_PCMTYPE_FLOAT);
  32. if (composition_unit)
  33. {
  34. CAccessUnitPtr access_unit = CAccessUnit_Create(0, 0);
  35. if (access_unit)
  36. {
  37. return new MKVAACDecoder(decoder, access_unit, composition_unit, preferred_bits, floating_point);
  38. }
  39. CCompositionUnit_Destroy(&composition_unit);
  40. }
  41. mp4AudioDecoder_Destroy(&decoder);
  42. }
  43. }
  44. }
  45. return 0;
  46. }
  47. int MKVAACDecoder::GetOutputProperties(unsigned int *sampleRate, unsigned int *channels, unsigned int *bitsPerSample, bool *isFloat)
  48. {
  49. /* TODO: verify that it's safe to call these, e.g. one frame has been decoded successfully, otherwise call MKV_NEED_MORE_INPUT */
  50. CCompositionUnit_GetSamplingRate(composition_unit, sampleRate);
  51. CCompositionUnit_GetChannels(composition_unit, channels);
  52. *bitsPerSample = bps;
  53. *isFloat = floating_point;
  54. return MKV_SUCCESS;
  55. }
  56. void MKVAACDecoder::Flush()
  57. {
  58. mp4AudioDecoder_Reset(decoder, MP4AUDIODECPARAM_DEFAULT, 0);
  59. }
  60. int MKVAACDecoder::OutputFrameSize(size_t *frame_size)
  61. {
  62. if (!decoder)
  63. return MKV_FAILURE;
  64. unsigned int samples_per_channel;
  65. unsigned int channels;
  66. if (CCompositionUnit_GetSamplesPerChannel(composition_unit, &samples_per_channel) != MP4AUDIODEC_OK
  67. || CCompositionUnit_GetChannels(composition_unit, &channels) != MP4AUDIODEC_OK)
  68. return MKV_FAILURE;
  69. *frame_size = samples_per_channel*channels;
  70. return MKV_SUCCESS;
  71. }
  72. void MKVAACDecoder::Close()
  73. {
  74. mp4AudioDecoder_Destroy(&decoder);
  75. CAccessUnit_Destroy(&access_unit);
  76. CCompositionUnit_Destroy(&composition_unit);
  77. delete this;
  78. }
  79. int MKVAACDecoder::DecodeBlock(void *inputBuffer, size_t inputBufferBytes, void *outputBuffer, size_t *outputBufferBytes)
  80. {
  81. CAccessUnit_Reset(access_unit);
  82. CAccessUnit_Assign(access_unit, (const unsigned char *)inputBuffer, inputBufferBytes);
  83. CCompositionUnit_Reset(composition_unit);
  84. MP4_RESULT result = mp4AudioDecoder_DecodeFrame(decoder, &access_unit, composition_unit);
  85. if (result == MP4AUDIODEC_OK)
  86. {
  87. unsigned int channels;
  88. unsigned int samples_per_channel;
  89. CCompositionUnit_GetSamplesPerChannel(composition_unit, &samples_per_channel);
  90. CCompositionUnit_GetChannels(composition_unit, &channels);
  91. const float *audio_output = 0;
  92. size_t num_samples = samples_per_channel * channels;
  93. size_t output_size = num_samples * (bps/8);
  94. if (output_size > *outputBufferBytes)
  95. return MKV_FAILURE;
  96. *outputBufferBytes = output_size;
  97. CCompositionUnit_GetPcmPtr(composition_unit, &audio_output);
  98. if (!floating_point)
  99. {
  100. nsutil_pcm_FloatToInt_Interleaved_Gain(outputBuffer, audio_output, bps, num_samples, 1.0f/32768.0f);
  101. }
  102. else
  103. {
  104. for (size_t i = 0;i != num_samples;i++)
  105. ((float *)outputBuffer)[i] = audio_output[i] / 32768.0f;
  106. }
  107. return MKV_SUCCESS;
  108. }
  109. else
  110. return MKV_FAILURE;
  111. }
  112. #define CBCLASS MKVAACDecoder
  113. START_DISPATCH;
  114. CB(OUTPUT_FRAME_SIZE, OutputFrameSize)
  115. CB(GET_OUTPUT_PROPERTIES, GetOutputProperties)
  116. CB(DECODE_BLOCK, DecodeBlock)
  117. VCB(FLUSH, Flush)
  118. VCB(CLOSE, Close)
  119. END_DISPATCH;
  120. #undef CBCLASS
  121. int 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)
  122. {
  123. if (!strcmp(codec_id, "A_AAC"))
  124. {
  125. MKVAACDecoder *aac_decoder = MKVAACDecoder::Create(track_entry_data, audio_data, preferred_bits, max_channels, floating_point);
  126. if (aac_decoder)
  127. {
  128. *decoder = aac_decoder;
  129. return CREATEDECODER_SUCCESS;
  130. }
  131. return CREATEDECODER_FAILURE;
  132. }
  133. return CREATEDECODER_NOT_MINE;
  134. }
  135. #define CBCLASS MKVDecoder
  136. START_DISPATCH;
  137. CB(CREATE_AUDIO_DECODER, CreateAudioDecoder)
  138. END_DISPATCH;
  139. #undef CBCLASS