AVIAACDecoder.cpp 5.3 KB

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