media_foundation_utils.cc 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209
  1. // Copyright 2022 The Chromium Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style license that can be
  3. // found in the LICENSE file.
  4. // Ensures MFAudioFormat_Xxx symbols are defined in mfapi.h which is included
  5. // by media_foundation_audio_stream.h.
  6. #include <initguid.h> // NOLINT(build/include_order)
  7. #include "media/filters/win/media_foundation_utils.h"
  8. #include <mfapi.h>
  9. #include <mferror.h> // NOLINT(build/include_order)
  10. #include <mfidl.h>
  11. #include <mmreg.h> // NOLINT(build/include_order)
  12. #include <wrl.h> // NOLINT(build/include_order)
  13. #include "base/win/scoped_co_mem.h"
  14. #include "media/base/audio_codecs.h"
  15. #include "media/base/audio_decoder_config.h"
  16. #include "media/base/win/mf_helpers.h"
  17. #include "media/media_buildflags.h"
  18. namespace media {
  19. using Microsoft::WRL::ComPtr;
  20. using Microsoft::WRL::MakeAndInitialize;
  21. namespace {
  22. // Given an audio format tag |wave_format|, it returns an audio subtype GUID per
  23. // https://docs.microsoft.com/en-us/windows/win32/medfound/audio-subtype-guids
  24. // |wave_format| must be one of the WAVE_FORMAT_* constants defined in mmreg.h.
  25. GUID MediaFoundationSubTypeFromWaveFormat(uint32_t wave_format) {
  26. GUID format_base = MFAudioFormat_Base;
  27. format_base.Data1 = wave_format;
  28. return format_base;
  29. }
  30. GUID AudioCodecToMediaFoundationSubtype(AudioCodec codec) {
  31. DVLOG(1) << __func__ << ": codec=" << codec;
  32. switch (codec) {
  33. case AudioCodec::kAAC:
  34. return MFAudioFormat_AAC;
  35. case AudioCodec::kMP3:
  36. return MFAudioFormat_MP3;
  37. case AudioCodec::kPCM:
  38. return MFAudioFormat_PCM;
  39. case AudioCodec::kVorbis:
  40. return MFAudioFormat_Vorbis;
  41. case AudioCodec::kFLAC:
  42. return MFAudioFormat_FLAC;
  43. case AudioCodec::kAMR_NB:
  44. return MFAudioFormat_AMR_NB;
  45. case AudioCodec::kAMR_WB:
  46. return MFAudioFormat_AMR_WB;
  47. case AudioCodec::kPCM_MULAW:
  48. return MediaFoundationSubTypeFromWaveFormat(WAVE_FORMAT_MULAW);
  49. case AudioCodec::kGSM_MS:
  50. return MediaFoundationSubTypeFromWaveFormat(WAVE_FORMAT_GSM610);
  51. case AudioCodec::kPCM_S16BE:
  52. return MFAudioFormat_PCM;
  53. case AudioCodec::kPCM_S24BE:
  54. return MFAudioFormat_PCM;
  55. case AudioCodec::kOpus:
  56. return MFAudioFormat_Opus;
  57. case AudioCodec::kEAC3:
  58. return MFAudioFormat_Dolby_DDPlus;
  59. case AudioCodec::kPCM_ALAW:
  60. return MediaFoundationSubTypeFromWaveFormat(WAVE_FORMAT_ALAW);
  61. case AudioCodec::kALAC:
  62. return MFAudioFormat_ALAC;
  63. case AudioCodec::kAC3:
  64. return MFAudioFormat_Dolby_AC3;
  65. #if BUILDFLAG(USE_PROPRIETARY_CODECS) && BUILDFLAG(ENABLE_PLATFORM_DTS_AUDIO)
  66. case AudioCodec::kDTS:
  67. return MFAudioFormat_DTS_RAW;
  68. case AudioCodec::kDTSXP2:
  69. return MFAudioFormat_DTS_UHD;
  70. #endif // BUILDFLAG(USE_PROPRIETARY_CODECS) &&
  71. // BUILDFLAG(ENABLE_PLATFORM_DTS_AUDIO)
  72. default:
  73. return GUID_NULL;
  74. }
  75. }
  76. bool IsUncompressedAudio(AudioCodec codec) {
  77. switch (codec) {
  78. case AudioCodec::kPCM:
  79. case AudioCodec::kPCM_S16BE:
  80. case AudioCodec::kPCM_S24BE:
  81. return true;
  82. default:
  83. return false;
  84. }
  85. }
  86. } // namespace
  87. // Given an AudioDecoderConfig, get its corresponding IMFMediaType format.
  88. // Note:
  89. // IMFMediaType is derived from IMFAttributes and hence all the of information
  90. // in a media type is store as attributes.
  91. // https://docs.microsoft.com/en-us/windows/win32/medfound/media-type-attributes
  92. // has a list of media type attributes.
  93. HRESULT GetDefaultAudioType(const AudioDecoderConfig decoder_config,
  94. IMFMediaType** media_type_out) {
  95. DVLOG(1) << __func__;
  96. ComPtr<IMFMediaType> media_type;
  97. RETURN_IF_FAILED(MFCreateMediaType(&media_type));
  98. RETURN_IF_FAILED(media_type->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Audio));
  99. GUID mf_subtype = AudioCodecToMediaFoundationSubtype(decoder_config.codec());
  100. if (mf_subtype == GUID_NULL) {
  101. DLOG(ERROR) << "Unsupported codec type: " << decoder_config.codec();
  102. return MF_E_TOPO_CODEC_NOT_FOUND;
  103. }
  104. RETURN_IF_FAILED(media_type->SetGUID(MF_MT_SUBTYPE, mf_subtype));
  105. bool uncompressed = IsUncompressedAudio(decoder_config.codec());
  106. if (uncompressed) {
  107. RETURN_IF_FAILED(media_type->SetUINT32(MF_MT_ALL_SAMPLES_INDEPENDENT, 1));
  108. } else {
  109. RETURN_IF_FAILED(media_type->SetUINT32(MF_MT_COMPRESSED, 1));
  110. }
  111. int channels = decoder_config.channels();
  112. if (channels > 0) {
  113. RETURN_IF_FAILED(media_type->SetUINT32(MF_MT_AUDIO_NUM_CHANNELS, channels));
  114. }
  115. int samples_per_second = decoder_config.samples_per_second();
  116. if (samples_per_second > 0) {
  117. RETURN_IF_FAILED(media_type->SetUINT32(MF_MT_AUDIO_SAMPLES_PER_SECOND,
  118. samples_per_second));
  119. }
  120. int bits_per_sample = decoder_config.bytes_per_frame() * 8;
  121. if (bits_per_sample > 0) {
  122. RETURN_IF_FAILED(
  123. media_type->SetUINT32(MF_MT_AUDIO_BITS_PER_SAMPLE, bits_per_sample));
  124. }
  125. if (uncompressed) {
  126. unsigned long block_alignment = channels * (bits_per_sample / 8);
  127. if (block_alignment > 0) {
  128. RETURN_IF_FAILED(
  129. media_type->SetUINT32(MF_MT_AUDIO_BLOCK_ALIGNMENT, block_alignment));
  130. }
  131. unsigned long average_bps = samples_per_second * (bits_per_sample / 8);
  132. if (average_bps > 0) {
  133. RETURN_IF_FAILED(
  134. media_type->SetUINT32(MF_MT_AUDIO_AVG_BYTES_PER_SECOND, average_bps));
  135. }
  136. }
  137. *media_type_out = media_type.Detach();
  138. return S_OK;
  139. }
  140. #if BUILDFLAG(USE_PROPRIETARY_CODECS)
  141. HRESULT GetAacAudioType(const AudioDecoderConfig decoder_config,
  142. IMFMediaType** media_type_out) {
  143. DVLOG(1) << __func__;
  144. ComPtr<IMFMediaType> media_type;
  145. RETURN_IF_FAILED(GetDefaultAudioType(decoder_config, &media_type));
  146. // On Windows `extra_data` is not populated for AAC in `decoder_config`. Use
  147. // `aac_extra_data` instead. See crbug.com/1245123.
  148. const auto& extra_data = decoder_config.aac_extra_data();
  149. size_t wave_format_size = sizeof(HEAACWAVEINFO) + extra_data.size();
  150. std::vector<uint8_t> wave_format_buffer(wave_format_size);
  151. HEAACWAVEINFO* aac_wave_format =
  152. reinterpret_cast<HEAACWAVEINFO*>(wave_format_buffer.data());
  153. aac_wave_format->wfx.wFormatTag = WAVE_FORMAT_MPEG_HEAAC;
  154. aac_wave_format->wfx.nChannels = decoder_config.channels();
  155. aac_wave_format->wfx.wBitsPerSample = decoder_config.bytes_per_channel() * 8;
  156. aac_wave_format->wfx.nSamplesPerSec = decoder_config.samples_per_second();
  157. aac_wave_format->wfx.nAvgBytesPerSec =
  158. decoder_config.samples_per_second() * decoder_config.bytes_per_frame();
  159. aac_wave_format->wfx.nBlockAlign = 1;
  160. size_t extra_size = wave_format_size - sizeof(WAVEFORMATEX);
  161. aac_wave_format->wfx.cbSize = static_cast<WORD>(extra_size);
  162. aac_wave_format->wPayloadType = 0; // RAW AAC
  163. aac_wave_format->wAudioProfileLevelIndication =
  164. 0xFE; // no audio profile specified
  165. aac_wave_format->wStructType = 0; // audio specific config follows
  166. aac_wave_format->wReserved1 = 0;
  167. aac_wave_format->dwReserved2 = 0;
  168. if (!extra_data.empty()) {
  169. memcpy(reinterpret_cast<uint8_t*>(aac_wave_format) + sizeof(HEAACWAVEINFO),
  170. extra_data.data(), extra_data.size());
  171. }
  172. RETURN_IF_FAILED(MFInitMediaTypeFromWaveFormatEx(
  173. media_type.Get(), reinterpret_cast<const WAVEFORMATEX*>(aac_wave_format),
  174. wave_format_size));
  175. *media_type_out = media_type.Detach();
  176. return S_OK;
  177. }
  178. #endif // BUILDFLAG(USE_PROPRIETARY_CODECS)
  179. } // namespace media