media_foundation_audio_stream.cc 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. // Copyright 2019 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/renderers/win/media_foundation_audio_stream.h"
  8. #include <mferror.h> // NOLINT(build/include_order)
  9. #include <mmreg.h> // NOLINT(build/include_order)
  10. #include <wrl.h> // NOLINT(build/include_order)
  11. #include "base/win/scoped_co_mem.h"
  12. #include "media/base/audio_codecs.h"
  13. #include "media/base/audio_decoder_config.h"
  14. #include "media/base/win/mf_helpers.h"
  15. namespace media {
  16. using Microsoft::WRL::ComPtr;
  17. using Microsoft::WRL::MakeAndInitialize;
  18. /*static*/
  19. HRESULT MediaFoundationAudioStream::Create(
  20. int stream_id,
  21. IMFMediaSource* parent_source,
  22. DemuxerStream* demuxer_stream,
  23. std::unique_ptr<MediaLog> media_log,
  24. MediaFoundationStreamWrapper** stream_out) {
  25. DVLOG(1) << __func__ << ": stream_id=" << stream_id;
  26. ComPtr<IMFMediaStream> audio_stream;
  27. AudioCodec codec = demuxer_stream->audio_decoder_config().codec();
  28. switch (codec) {
  29. #if BUILDFLAG(USE_PROPRIETARY_CODECS)
  30. case AudioCodec::kAAC:
  31. RETURN_IF_FAILED(MakeAndInitialize<MediaFoundationAACAudioStream>(
  32. &audio_stream, stream_id, parent_source, demuxer_stream,
  33. std::move(media_log)));
  34. break;
  35. #endif // BUILDFLAG(USE_PROPRIETARY_CODECS)
  36. default:
  37. RETURN_IF_FAILED(MakeAndInitialize<MediaFoundationAudioStream>(
  38. &audio_stream, stream_id, parent_source, demuxer_stream,
  39. std::move(media_log)));
  40. break;
  41. }
  42. *stream_out =
  43. static_cast<MediaFoundationStreamWrapper*>(audio_stream.Detach());
  44. return S_OK;
  45. }
  46. bool MediaFoundationAudioStream::IsEncrypted() const {
  47. AudioDecoderConfig audio_config = demuxer_stream_->audio_decoder_config();
  48. return audio_config.is_encrypted();
  49. }
  50. HRESULT MediaFoundationAudioStream::GetMediaType(
  51. IMFMediaType** media_type_out) {
  52. AudioDecoderConfig decoder_config = demuxer_stream_->audio_decoder_config();
  53. return GetDefaultAudioType(decoder_config, media_type_out);
  54. }
  55. #if BUILDFLAG(USE_PROPRIETARY_CODECS)
  56. HRESULT MediaFoundationAACAudioStream::GetMediaType(
  57. IMFMediaType** media_type_out) {
  58. AudioDecoderConfig decoder_config = demuxer_stream_->audio_decoder_config();
  59. enable_adts_header_removal_ = !decoder_config.should_discard_decoder_delay();
  60. return GetAacAudioType(decoder_config, media_type_out);
  61. }
  62. // This detects whether the given |sample| has an ADTS header in the clear. If
  63. // yes, it removes the ADTS header (and modifies the subsample mappings
  64. // accordingly).
  65. HRESULT MediaFoundationAACAudioStream::TransformSample(
  66. Microsoft::WRL::ComPtr<IMFSample>& sample) {
  67. DVLOG_FUNC(3);
  68. if (!enable_adts_header_removal_)
  69. return S_OK;
  70. ComPtr<IMFMediaBuffer> mf_buffer;
  71. ComPtr<IMFMediaBuffer> new_mf_buffer;
  72. DWORD buffer_count = 0;
  73. RETURN_IF_FAILED(sample->GetBufferCount(&buffer_count));
  74. if (buffer_count != 1) {
  75. DLOG(ERROR) << __func__ << ": buffer_count=" << buffer_count;
  76. return MF_E_UNEXPECTED;
  77. }
  78. RETURN_IF_FAILED(sample->GetBufferByIndex(0, &mf_buffer));
  79. BYTE* mf_buffer_data = nullptr;
  80. DWORD max_length = 0;
  81. DWORD current_length = 0;
  82. const int kADTSHeaderSize = 7;
  83. bool might_contain_adts_header = false;
  84. RETURN_IF_FAILED(
  85. mf_buffer->Lock(&mf_buffer_data, &max_length, &current_length));
  86. if (current_length >= kADTSHeaderSize && mf_buffer_data[0] == 0xff &&
  87. mf_buffer_data[1] == 0xf1 && mf_buffer_data[6] == 0xfc) {
  88. might_contain_adts_header = true;
  89. }
  90. RETURN_IF_FAILED(mf_buffer->Unlock());
  91. if (!might_contain_adts_header)
  92. return S_OK;
  93. bool contains_clear_adts_header = true;
  94. // If the stream is encrypted, ensure that the sub-sample mappings are
  95. // adjusted to account for the ADTS header removal.
  96. base::win::ScopedCoMem<MediaFoundationSubsampleEntry> subsample_mappings;
  97. uint32_t subsample_mappings_size = 0;
  98. // MFSampleExtension_Encryption_SubSample_Mapping is documented in "mfapi.h".
  99. // If the attribute doesn't exist, we should not fail the call.
  100. if (SUCCEEDED(sample->GetAllocatedBlob(
  101. MFSampleExtension_Encryption_SubSample_Mapping,
  102. reinterpret_cast<uint8_t**>(&subsample_mappings),
  103. &subsample_mappings_size)) &&
  104. subsample_mappings_size >= sizeof(MediaFoundationSubsampleEntry)) {
  105. uint32_t subsample_count =
  106. subsample_mappings_size / sizeof(MediaFoundationSubsampleEntry);
  107. if (subsample_count == 1 &&
  108. subsample_mappings.get()[0].clear_bytes == kADTSHeaderSize) {
  109. // When MFSampleExtension_Encryption_SubSample_Mapping attribute is
  110. // removed, the whole sample is considered as encrypted.
  111. RETURN_IF_FAILED(
  112. sample->DeleteItem(MFSampleExtension_Encryption_SubSample_Mapping));
  113. } else if (subsample_mappings.get()[0].clear_bytes >= kADTSHeaderSize) {
  114. subsample_mappings.get()[0].clear_bytes -= kADTSHeaderSize;
  115. RETURN_IF_FAILED(sample->SetBlob(
  116. MFSampleExtension_Encryption_SubSample_Mapping,
  117. reinterpret_cast<const uint8_t*>(subsample_mappings.get()),
  118. subsample_mappings_size));
  119. } else {
  120. // There is no ADTS header inserted by Demuxer, we don't need to remove
  121. // it.
  122. contains_clear_adts_header = false;
  123. }
  124. }
  125. if (contains_clear_adts_header) {
  126. // Remove ADTS header from |sample|.
  127. RETURN_IF_FAILED(MFCreateMediaBufferWrapper(
  128. mf_buffer.Get(), kADTSHeaderSize, current_length - kADTSHeaderSize,
  129. &new_mf_buffer));
  130. RETURN_IF_FAILED(sample->RemoveAllBuffers());
  131. RETURN_IF_FAILED(sample->AddBuffer(new_mf_buffer.Get()));
  132. }
  133. return S_OK;
  134. }
  135. #endif // BUILDFLAG(USE_PROPRIETARY_CODECS)
  136. } // namespace media