123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152 |
- // Copyright 2019 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- // Ensures MFAudioFormat_Xxx symbols are defined in mfapi.h which is included
- // by media_foundation_audio_stream.h.
- #include <initguid.h> // NOLINT(build/include_order)
- #include "media/renderers/win/media_foundation_audio_stream.h"
- #include <mferror.h> // NOLINT(build/include_order)
- #include <mmreg.h> // NOLINT(build/include_order)
- #include <wrl.h> // NOLINT(build/include_order)
- #include "base/win/scoped_co_mem.h"
- #include "media/base/audio_codecs.h"
- #include "media/base/audio_decoder_config.h"
- #include "media/base/win/mf_helpers.h"
- namespace media {
- using Microsoft::WRL::ComPtr;
- using Microsoft::WRL::MakeAndInitialize;
- /*static*/
- HRESULT MediaFoundationAudioStream::Create(
- int stream_id,
- IMFMediaSource* parent_source,
- DemuxerStream* demuxer_stream,
- std::unique_ptr<MediaLog> media_log,
- MediaFoundationStreamWrapper** stream_out) {
- DVLOG(1) << __func__ << ": stream_id=" << stream_id;
- ComPtr<IMFMediaStream> audio_stream;
- AudioCodec codec = demuxer_stream->audio_decoder_config().codec();
- switch (codec) {
- #if BUILDFLAG(USE_PROPRIETARY_CODECS)
- case AudioCodec::kAAC:
- RETURN_IF_FAILED(MakeAndInitialize<MediaFoundationAACAudioStream>(
- &audio_stream, stream_id, parent_source, demuxer_stream,
- std::move(media_log)));
- break;
- #endif // BUILDFLAG(USE_PROPRIETARY_CODECS)
- default:
- RETURN_IF_FAILED(MakeAndInitialize<MediaFoundationAudioStream>(
- &audio_stream, stream_id, parent_source, demuxer_stream,
- std::move(media_log)));
- break;
- }
- *stream_out =
- static_cast<MediaFoundationStreamWrapper*>(audio_stream.Detach());
- return S_OK;
- }
- bool MediaFoundationAudioStream::IsEncrypted() const {
- AudioDecoderConfig audio_config = demuxer_stream_->audio_decoder_config();
- return audio_config.is_encrypted();
- }
- HRESULT MediaFoundationAudioStream::GetMediaType(
- IMFMediaType** media_type_out) {
- AudioDecoderConfig decoder_config = demuxer_stream_->audio_decoder_config();
- return GetDefaultAudioType(decoder_config, media_type_out);
- }
- #if BUILDFLAG(USE_PROPRIETARY_CODECS)
- HRESULT MediaFoundationAACAudioStream::GetMediaType(
- IMFMediaType** media_type_out) {
- AudioDecoderConfig decoder_config = demuxer_stream_->audio_decoder_config();
- enable_adts_header_removal_ = !decoder_config.should_discard_decoder_delay();
- return GetAacAudioType(decoder_config, media_type_out);
- }
- // This detects whether the given |sample| has an ADTS header in the clear. If
- // yes, it removes the ADTS header (and modifies the subsample mappings
- // accordingly).
- HRESULT MediaFoundationAACAudioStream::TransformSample(
- Microsoft::WRL::ComPtr<IMFSample>& sample) {
- DVLOG_FUNC(3);
- if (!enable_adts_header_removal_)
- return S_OK;
- ComPtr<IMFMediaBuffer> mf_buffer;
- ComPtr<IMFMediaBuffer> new_mf_buffer;
- DWORD buffer_count = 0;
- RETURN_IF_FAILED(sample->GetBufferCount(&buffer_count));
- if (buffer_count != 1) {
- DLOG(ERROR) << __func__ << ": buffer_count=" << buffer_count;
- return MF_E_UNEXPECTED;
- }
- RETURN_IF_FAILED(sample->GetBufferByIndex(0, &mf_buffer));
- BYTE* mf_buffer_data = nullptr;
- DWORD max_length = 0;
- DWORD current_length = 0;
- const int kADTSHeaderSize = 7;
- bool might_contain_adts_header = false;
- RETURN_IF_FAILED(
- mf_buffer->Lock(&mf_buffer_data, &max_length, ¤t_length));
- if (current_length >= kADTSHeaderSize && mf_buffer_data[0] == 0xff &&
- mf_buffer_data[1] == 0xf1 && mf_buffer_data[6] == 0xfc) {
- might_contain_adts_header = true;
- }
- RETURN_IF_FAILED(mf_buffer->Unlock());
- if (!might_contain_adts_header)
- return S_OK;
- bool contains_clear_adts_header = true;
- // If the stream is encrypted, ensure that the sub-sample mappings are
- // adjusted to account for the ADTS header removal.
- base::win::ScopedCoMem<MediaFoundationSubsampleEntry> subsample_mappings;
- uint32_t subsample_mappings_size = 0;
- // MFSampleExtension_Encryption_SubSample_Mapping is documented in "mfapi.h".
- // If the attribute doesn't exist, we should not fail the call.
- if (SUCCEEDED(sample->GetAllocatedBlob(
- MFSampleExtension_Encryption_SubSample_Mapping,
- reinterpret_cast<uint8_t**>(&subsample_mappings),
- &subsample_mappings_size)) &&
- subsample_mappings_size >= sizeof(MediaFoundationSubsampleEntry)) {
- uint32_t subsample_count =
- subsample_mappings_size / sizeof(MediaFoundationSubsampleEntry);
- if (subsample_count == 1 &&
- subsample_mappings.get()[0].clear_bytes == kADTSHeaderSize) {
- // When MFSampleExtension_Encryption_SubSample_Mapping attribute is
- // removed, the whole sample is considered as encrypted.
- RETURN_IF_FAILED(
- sample->DeleteItem(MFSampleExtension_Encryption_SubSample_Mapping));
- } else if (subsample_mappings.get()[0].clear_bytes >= kADTSHeaderSize) {
- subsample_mappings.get()[0].clear_bytes -= kADTSHeaderSize;
- RETURN_IF_FAILED(sample->SetBlob(
- MFSampleExtension_Encryption_SubSample_Mapping,
- reinterpret_cast<const uint8_t*>(subsample_mappings.get()),
- subsample_mappings_size));
- } else {
- // There is no ADTS header inserted by Demuxer, we don't need to remove
- // it.
- contains_clear_adts_header = false;
- }
- }
- if (contains_clear_adts_header) {
- // Remove ADTS header from |sample|.
- RETURN_IF_FAILED(MFCreateMediaBufferWrapper(
- mf_buffer.Get(), kADTSHeaderSize, current_length - kADTSHeaderSize,
- &new_mf_buffer));
- RETURN_IF_FAILED(sample->RemoveAllBuffers());
- RETURN_IF_FAILED(sample->AddBuffer(new_mf_buffer.Get()));
- }
- return S_OK;
- }
- #endif // BUILDFLAG(USE_PROPRIETARY_CODECS)
- } // namespace media
|