diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2022-02-02 12:21:57 +0100 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2022-02-12 08:13:00 +0000 |
commit | 606d85f2a5386472314d39923da28c70c60dc8e7 (patch) | |
tree | a8f4d7bf997f349f45605e6058259fba0630e4d7 /chromium/media/renderers/win | |
parent | 5786336dda477d04fb98483dca1a5426eebde2d7 (diff) | |
download | qtwebengine-chromium-606d85f2a5386472314d39923da28c70c60dc8e7.tar.gz |
BASELINE: Update Chromium to 96.0.4664.181
Change-Id: I762cd1da89d73aa6313b4a753fe126c34833f046
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/media/renderers/win')
16 files changed, 191 insertions, 88 deletions
diff --git a/chromium/media/renderers/win/media_engine_notify_impl.cc b/chromium/media/renderers/win/media_engine_notify_impl.cc index da71066f543..18220d53015 100644 --- a/chromium/media/renderers/win/media_engine_notify_impl.cc +++ b/chromium/media/renderers/win/media_engine_notify_impl.cc @@ -132,7 +132,7 @@ HRESULT MediaEngineNotifyImpl::EventNotify(DWORD event_code, MF_MEDIA_ENGINE_ERR error = static_cast<MF_MEDIA_ENGINE_ERR>(param1); HRESULT hr = param2; LOG(ERROR) << __func__ << ": error=" << error << ", hr=" << PrintHr(hr); - error_cb_.Run(MediaEngineErrorToPipelineStatus(error, hr)); + error_cb_.Run(MediaEngineErrorToPipelineStatus(error, hr), hr); break; } case MF_MEDIA_ENGINE_EVENT_ENDED: diff --git a/chromium/media/renderers/win/media_engine_notify_impl.h b/chromium/media/renderers/win/media_engine_notify_impl.h index cf3cafc6045..fd03064be03 100644 --- a/chromium/media/renderers/win/media_engine_notify_impl.h +++ b/chromium/media/renderers/win/media_engine_notify_impl.h @@ -15,13 +15,6 @@ namespace media { -using ErrorCB = base::RepeatingCallback<void(PipelineStatus)>; -using EndedCB = base::RepeatingClosure; -using BufferingStateChangedCB = - base::RepeatingCallback<void(BufferingState, BufferingStateChangeReason)>; -using VideoNaturalSizeChangedCB = base::RepeatingClosure; -using TimeUpdateCB = base::RepeatingClosure; - // Implements IMFMediaEngineNotify required by IMFMediaEngine // (https://docs.microsoft.com/en-us/windows/win32/api/mfmediaengine/nn-mfmediaengine-imfmediaengine). // @@ -34,6 +27,13 @@ class MediaEngineNotifyImpl MediaEngineNotifyImpl(); ~MediaEngineNotifyImpl() override; + using ErrorCB = base::RepeatingCallback<void(PipelineStatus, HRESULT)>; + using EndedCB = base::RepeatingClosure; + using BufferingStateChangedCB = + base::RepeatingCallback<void(BufferingState, BufferingStateChangeReason)>; + using VideoNaturalSizeChangedCB = base::RepeatingClosure; + using TimeUpdateCB = base::RepeatingClosure; + HRESULT RuntimeClassInitialize( ErrorCB error_cb, EndedCB ended_cb, diff --git a/chromium/media/renderers/win/media_foundation_audio_stream.cc b/chromium/media/renderers/win/media_foundation_audio_stream.cc index 5a211ae8b41..c3fca8cf272 100644 --- a/chromium/media/renderers/win/media_foundation_audio_stream.cc +++ b/chromium/media/renderers/win/media_foundation_audio_stream.cc @@ -37,37 +37,37 @@ GUID AudioCodecToMediaFoundationSubtype(AudioCodec codec) { DVLOG(1) << __func__ << ": codec=" << codec; switch (codec) { - case kCodecAAC: + case AudioCodec::kAAC: return MFAudioFormat_AAC; - case kCodecMP3: + case AudioCodec::kMP3: return MFAudioFormat_MP3; - case kCodecPCM: + case AudioCodec::kPCM: return MFAudioFormat_PCM; - case kCodecVorbis: + case AudioCodec::kVorbis: return MFAudioFormat_Vorbis; - case kCodecFLAC: + case AudioCodec::kFLAC: return MFAudioFormat_FLAC; - case kCodecAMR_NB: + case AudioCodec::kAMR_NB: return MFAudioFormat_AMR_NB; - case kCodecAMR_WB: + case AudioCodec::kAMR_WB: return MFAudioFormat_AMR_WB; - case kCodecPCM_MULAW: + case AudioCodec::kPCM_MULAW: return MediaFoundationSubTypeFromWaveFormat(WAVE_FORMAT_MULAW); - case kCodecGSM_MS: + case AudioCodec::kGSM_MS: return MediaFoundationSubTypeFromWaveFormat(WAVE_FORMAT_GSM610); - case kCodecPCM_S16BE: + case AudioCodec::kPCM_S16BE: return MFAudioFormat_PCM; - case kCodecPCM_S24BE: + case AudioCodec::kPCM_S24BE: return MFAudioFormat_PCM; - case kCodecOpus: + case AudioCodec::kOpus: return MFAudioFormat_Opus; - case kCodecEAC3: + case AudioCodec::kEAC3: return MFAudioFormat_Dolby_DDPlus; - case kCodecPCM_ALAW: + case AudioCodec::kPCM_ALAW: return MediaFoundationSubTypeFromWaveFormat(WAVE_FORMAT_ALAW); - case kCodecALAC: + case AudioCodec::kALAC: return MFAudioFormat_ALAC; - case kCodecAC3: + case AudioCodec::kAC3: return MFAudioFormat_Dolby_AC3; default: return GUID_NULL; @@ -76,9 +76,9 @@ GUID AudioCodecToMediaFoundationSubtype(AudioCodec codec) { bool IsUncompressedAudio(AudioCodec codec) { switch (codec) { - case kCodecPCM: - case kCodecPCM_S16BE: - case kCodecPCM_S24BE: + case AudioCodec::kPCM: + case AudioCodec::kPCM_S16BE: + case AudioCodec::kPCM_S24BE: return true; default: return false; @@ -155,8 +155,11 @@ HRESULT GetAacAudioType(const AudioDecoderConfig decoder_config, ComPtr<IMFMediaType> media_type; RETURN_IF_FAILED(GetDefaultAudioType(decoder_config, &media_type)); - size_t wave_format_size = - sizeof(HEAACWAVEINFO) + decoder_config.extra_data().size(); + // On Windows `extra_data` is not populated for AAC in `decoder_config`. Use + // `aac_extra_data` instead. See crbug.com/1245123. + const auto& extra_data = decoder_config.aac_extra_data(); + + size_t wave_format_size = sizeof(HEAACWAVEINFO) + extra_data.size(); std::vector<uint8_t> wave_format_buffer(wave_format_size); HEAACWAVEINFO* aac_wave_format = reinterpret_cast<HEAACWAVEINFO*>(wave_format_buffer.data()); @@ -178,10 +181,9 @@ HRESULT GetAacAudioType(const AudioDecoderConfig decoder_config, aac_wave_format->wReserved1 = 0; aac_wave_format->dwReserved2 = 0; - if (decoder_config.extra_data().size() > 0) { + if (!extra_data.empty()) { memcpy(reinterpret_cast<uint8_t*>(aac_wave_format) + sizeof(HEAACWAVEINFO), - decoder_config.extra_data().data(), - decoder_config.extra_data().size()); + extra_data.data(), extra_data.size()); } RETURN_IF_FAILED(MFInitMediaTypeFromWaveFormatEx( @@ -199,6 +201,7 @@ 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; @@ -206,14 +209,16 @@ HRESULT MediaFoundationAudioStream::Create( AudioCodec codec = demuxer_stream->audio_decoder_config().codec(); switch (codec) { #if BUILDFLAG(USE_PROPRIETARY_CODECS) - case kCodecAAC: + case AudioCodec::kAAC: RETURN_IF_FAILED(MakeAndInitialize<MediaFoundationAACAudioStream>( - &audio_stream, stream_id, parent_source, demuxer_stream)); + &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)); + &audio_stream, stream_id, parent_source, demuxer_stream, + std::move(media_log))); break; } *stream_out = diff --git a/chromium/media/renderers/win/media_foundation_audio_stream.h b/chromium/media/renderers/win/media_foundation_audio_stream.h index ebac24d07fb..1d281a3f862 100644 --- a/chromium/media/renderers/win/media_foundation_audio_stream.h +++ b/chromium/media/renderers/win/media_foundation_audio_stream.h @@ -10,6 +10,7 @@ #include "media/renderers/win/media_foundation_stream_wrapper.h" +#include "media/base/media_log.h" #include "media/media_buildflags.h" namespace media { @@ -20,6 +21,7 @@ class MediaFoundationAudioStream : public MediaFoundationStreamWrapper { static HRESULT Create(int stream_id, IMFMediaSource* parent_source, DemuxerStream* demuxer_stream, + std::unique_ptr<MediaLog> media_log, MediaFoundationStreamWrapper** stream_out); bool IsEncrypted() const override; HRESULT GetMediaType(IMFMediaType** media_type_out) override; diff --git a/chromium/media/renderers/win/media_foundation_protection_manager.cc b/chromium/media/renderers/win/media_foundation_protection_manager.cc index e19382e57e6..d9c7b087745 100644 --- a/chromium/media/renderers/win/media_foundation_protection_manager.cc +++ b/chromium/media/renderers/win/media_foundation_protection_manager.cc @@ -203,7 +203,7 @@ void MediaFoundationProtectionManager::OnBeginEnableContent() { // If EnableContent takes too long, report waiting for key status. Choose a // timeout of 500ms to be on the safe side, e.g. on slower machines. - const auto kWaitingForKeyTimeOut = base::TimeDelta::FromMilliseconds(500); + const auto kWaitingForKeyTimeOut = base::Milliseconds(500); waiting_for_key_time_out_cb_.Reset( base::BindOnce(&MediaFoundationProtectionManager::OnWaitingForKeyTimeOut, diff --git a/chromium/media/renderers/win/media_foundation_renderer.cc b/chromium/media/renderers/win/media_foundation_renderer.cc index 196d161dfa7..5a7c89ac2df 100644 --- a/chromium/media/renderers/win/media_foundation_renderer.cc +++ b/chromium/media/renderers/win/media_foundation_renderer.cc @@ -11,6 +11,7 @@ #include "base/callback_helpers.h" #include "base/guid.h" +#include "base/metrics/histogram_functions.h" #include "base/numerics/safe_conversions.h" #include "base/process/process_handle.h" #include "base/strings/string_number_conversions.h" @@ -22,6 +23,7 @@ #include "base/win/wrapped_window_proc.h" #include "media/base/bind_to_current_loop.h" #include "media/base/cdm_context.h" +#include "media/base/media_log.h" #include "media/base/timestamp_constants.h" #include "media/base/win/mf_helpers.h" #include "media/base/win/mf_initializer.h" @@ -72,8 +74,10 @@ bool MediaFoundationRenderer::IsSupported() { MediaFoundationRenderer::MediaFoundationRenderer( scoped_refptr<base::SequencedTaskRunner> task_runner, + std::unique_ptr<MediaLog> media_log, bool force_dcomp_mode_for_testing) : task_runner_(std::move(task_runner)), + media_log_(std::move(media_log)), force_dcomp_mode_for_testing_(force_dcomp_mode_for_testing) { DVLOG_FUNC(1); } @@ -191,7 +195,7 @@ HRESULT MediaFoundationRenderer::CreateMediaEngine( } RETURN_IF_FAILED(MakeAndInitialize<MediaFoundationSourceWrapper>( - &mf_source_, media_resource, task_runner_)); + &mf_source_, media_resource, media_log_.get(), task_runner_)); if (force_dcomp_mode_for_testing_) ignore_result(SetDCompModeInternal()); @@ -268,6 +272,7 @@ HRESULT MediaFoundationRenderer::InitializeDXGIDeviceManager() { D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, 0, creation_flags, feature_levels, base::size(feature_levels), D3D11_SDK_VERSION, &d3d11_device, nullptr, nullptr)); + RETURN_IF_FAILED(media::SetDebugName(d3d11_device.Get(), "Media_MFRenderer")); ComPtr<ID3D10Multithread> multithreaded_device; RETURN_IF_FAILED(d3d11_device.As(&multithreaded_device)); @@ -452,27 +457,32 @@ void MediaFoundationRenderer::SetVideoStreamEnabled(bool enabled) { } } -void MediaFoundationRenderer::SetOutputParams(const gfx::Rect& output_rect) { +void MediaFoundationRenderer::SetOutputRect(const gfx::Rect& output_rect, + SetOutputRectCB callback) { DVLOG_FUNC(2); - output_rect_ = output_rect; - if (virtual_video_window_ && !::SetWindowPos(virtual_video_window_, HWND_BOTTOM, output_rect.x(), output_rect.y(), output_rect.width(), output_rect.height(), SWP_NOACTIVATE)) { DLOG(ERROR) << "Failed to SetWindowPos: " << PrintHr(HRESULT_FROM_WIN32(GetLastError())); + std::move(callback).Run(false); + return; + } + + if (FAILED(UpdateVideoStream(output_rect))) { + std::move(callback).Run(false); return; } - ignore_result(UpdateVideoStream(output_rect)); + std::move(callback).Run(true); } HRESULT MediaFoundationRenderer::UpdateVideoStream(const gfx::Rect& rect) { ComPtr<IMFMediaEngineEx> mf_media_engine_ex; RETURN_IF_FAILED(mf_media_engine_.As(&mf_media_engine_ex)); - RECT dest_rect = rect.ToRECT(); + RECT dest_rect = {0, 0, rect.width(), rect.height()}; RETURN_IF_FAILED(mf_media_engine_ex->UpdateVideoStream( /*pSrc=*/nullptr, &dest_rect, /*pBorderClr=*/nullptr)); return S_OK; @@ -518,7 +528,8 @@ void MediaFoundationRenderer::SendStatistics() { PipelineStatistics new_stats = {}; HRESULT hr = PopulateStatistics(new_stats); if (FAILED(hr)) { - DVLOG_FUNC(3) << "Unable to populate pipeline stats: " << PrintHr(hr); + LIMITED_MEDIA_LOG(INFO, media_log_, populate_statistics_failure_count_, 3) + << "MediaFoundationRenderer failed to populate stats: " + PrintHr(hr); return; } @@ -530,8 +541,7 @@ void MediaFoundationRenderer::SendStatistics() { void MediaFoundationRenderer::StartSendingStatistics() { DVLOG_FUNC(2); - const auto kPipelineStatsPollingPeriod = - base::TimeDelta::FromMilliseconds(500); + const auto kPipelineStatsPollingPeriod = base::Milliseconds(500); statistics_timer_.Start(FROM_HERE, kPipelineStatsPollingPeriod, this, &MediaFoundationRenderer::SendStatistics); } @@ -557,18 +567,25 @@ base::TimeDelta MediaFoundationRenderer::GetMediaTime() { double current_time = mf_media_engine_->GetCurrentTime(); // Restore macro definition. #define GetCurrentTime() GetTickCount() - auto media_time = base::TimeDelta::FromSecondsD(current_time); + auto media_time = base::Seconds(current_time); DVLOG_FUNC(3) << "media_time=" << media_time; return media_time; } -void MediaFoundationRenderer::OnPlaybackError(PipelineStatus status) { - DVLOG_FUNC(1) << "status=" << status; +void MediaFoundationRenderer::OnPlaybackError(PipelineStatus status, + HRESULT hr) { + DVLOG_FUNC(1) << "status=" << status << ", hr=" << hr; DCHECK(task_runner_->RunsTasksInCurrentSequence()); + base::UmaHistogramSparse("Media.MediaFoundationRenderer.PlaybackError", hr); + if (status == PIPELINE_ERROR_HARDWARE_CONTEXT_RESET && cdm_proxy_) cdm_proxy_->OnHardwareContextReset(); + MEDIA_LOG(ERROR, media_log_) + << "MediaFoundationRenderer OnPlaybackError: " << status << ", " + << PrintHr(hr); + renderer_client_->OnError(status); StopSendingStatistics(); } @@ -628,9 +645,14 @@ void MediaFoundationRenderer::OnVideoNaturalSizeChange() { base::checked_cast<int>(native_height)}; } - // If `output_rect_` is not available yet, use `native_video_size_` for now. - if (output_rect_.IsEmpty()) - ignore_result(UpdateVideoStream(gfx::Rect(native_video_size_))); + // TODO(frankli): Let test code to call `UpdateVideoStream()`. + if (force_dcomp_mode_for_testing_) { + const gfx::Rect test_rect(/*x=*/0, /*y=*/0, /*width=*/640, /*height=*/320); + // This invokes IMFMediaEngineEx::UpdateVideoStream() for video frames to + // be presented. Otherwise, the Media Foundation video renderer will not + // request video samples from our source. + ignore_result(UpdateVideoStream(test_rect)); + } renderer_client_->OnVideoNaturalSizeChange(native_video_size_); } diff --git a/chromium/media/renderers/win/media_foundation_renderer.h b/chromium/media/renderers/win/media_foundation_renderer.h index 95d4d0499ed..5b34e30dc51 100644 --- a/chromium/media/renderers/win/media_foundation_renderer.h +++ b/chromium/media/renderers/win/media_foundation_renderer.h @@ -11,7 +11,6 @@ #include <wrl.h> #include "base/callback.h" -#include "base/macros.h" #include "base/memory/scoped_refptr.h" #include "base/memory/weak_ptr.h" #include "base/sequenced_task_runner.h" @@ -32,6 +31,8 @@ namespace media { +class MediaLog; + // MediaFoundationRenderer bridges the Renderer and Windows MFMediaEngine // interfaces. class MEDIA_EXPORT MediaFoundationRenderer @@ -42,13 +43,12 @@ class MEDIA_EXPORT MediaFoundationRenderer static bool IsSupported(); MediaFoundationRenderer(scoped_refptr<base::SequencedTaskRunner> task_runner, + std::unique_ptr<MediaLog> media_log, bool force_dcomp_mode_for_testing = false); - + MediaFoundationRenderer(const MediaFoundationRenderer&) = delete; + MediaFoundationRenderer& operator=(const MediaFoundationRenderer&) = delete; ~MediaFoundationRenderer() override; - // TODO(frankli): naming: Change DComp into DirectComposition for interface - // method names in a separate CL. - // Renderer implementation. void Initialize(MediaResource* media_resource, RendererClient* client, @@ -64,7 +64,8 @@ class MEDIA_EXPORT MediaFoundationRenderer // MediaFoundationRendererExtension implementation. void GetDCompSurface(GetDCompSurfaceCB callback) override; void SetVideoStreamEnabled(bool enabled) override; - void SetOutputParams(const gfx::Rect& output_rect) override; + void SetOutputRect(const gfx::Rect& output_rect, + SetOutputRectCB callback) override; private: HRESULT CreateMediaEngine(MediaResource* media_resource); @@ -77,8 +78,8 @@ class MEDIA_EXPORT MediaFoundationRenderer void StartSendingStatistics(); void StopSendingStatistics(); - // Callbacks for |mf_media_engine_notify_|. - void OnPlaybackError(PipelineStatus status); + // Callbacks for `mf_media_engine_notify_`. + void OnPlaybackError(PipelineStatus status, HRESULT hr); void OnPlaybackEnded(); void OnBufferingStateChange(BufferingState state, BufferingStateChangeReason reason); @@ -98,7 +99,10 @@ class MEDIA_EXPORT MediaFoundationRenderer // Renderer methods are running in the same sequence. scoped_refptr<base::SequencedTaskRunner> task_runner_; - // Once set, will force |mf_media_engine_| to use DirectComposition mode. + // Used to report media logs. Can be called on any thread. + std::unique_ptr<MediaLog> media_log_; + + // Once set, will force `mf_media_engine_` to use DirectComposition mode. // This is used for testing. const bool force_dcomp_mode_for_testing_; @@ -118,9 +122,6 @@ class MEDIA_EXPORT MediaFoundationRenderer // This is the same as "natural_size" in Chromium. gfx::Size native_video_size_; - // The actual output Rect for video. - gfx::Rect output_rect_; - // Keep the last volume value being set. float volume_ = 1.0; @@ -131,6 +132,10 @@ class MEDIA_EXPORT MediaFoundationRenderer PipelineStatistics statistics_ = {}; base::RepeatingTimer statistics_timer_; + // Tracks the number of MEDIA_LOGs emitted for failure to populate statistics. + // Useful to prevent log spam. + int populate_statistics_failure_count_ = 0; + // A fake window handle passed to MF-based rendering pipeline for OPM. HWND virtual_video_window_ = nullptr; @@ -143,8 +148,6 @@ class MEDIA_EXPORT MediaFoundationRenderer // NOTE: Weak pointers must be invalidated before all other member variables. base::WeakPtrFactory<MediaFoundationRenderer> weak_factory_{this}; - - DISALLOW_COPY_AND_ASSIGN(MediaFoundationRenderer); }; } // namespace media diff --git a/chromium/media/renderers/win/media_foundation_renderer_extension.h b/chromium/media/renderers/win/media_foundation_renderer_extension.h index 5162dc6a934..1f48b40c59f 100644 --- a/chromium/media/renderers/win/media_foundation_renderer_extension.h +++ b/chromium/media/renderers/win/media_foundation_renderer_extension.h @@ -32,7 +32,9 @@ class MEDIA_EXPORT MediaFoundationRendererExtension { virtual void SetVideoStreamEnabled(bool enabled) = 0; // Notifies renderer of output composition parameters. - virtual void SetOutputParams(const ::gfx::Rect& rect) = 0; + using SetOutputRectCB = base::OnceCallback<void(bool)>; + virtual void SetOutputRect(const ::gfx::Rect& rect, + SetOutputRectCB callback) = 0; }; } // namespace media diff --git a/chromium/media/renderers/win/media_foundation_renderer_integration_test.cc b/chromium/media/renderers/win/media_foundation_renderer_integration_test.cc index 6d0bedb8577..257042270a0 100644 --- a/chromium/media/renderers/win/media_foundation_renderer_integration_test.cc +++ b/chromium/media/renderers/win/media_foundation_renderer_integration_test.cc @@ -8,6 +8,8 @@ #include <mfapi.h> +#include "base/win/windows_version.h" +#include "media/base/media_util.h" #include "media/test/pipeline_integration_test_base.h" #include "media/test/test_media_source.h" @@ -64,6 +66,7 @@ class MediaFoundationRendererIntegrationTest absl::optional<RendererType> /*renderer_type*/) { auto renderer = std::make_unique<MediaFoundationRenderer>( task_environment_.GetMainThreadTaskRunner(), + std::make_unique<NullMediaLog>(), /*force_dcomp_mode_for_testing=*/true); return renderer; } @@ -72,6 +75,11 @@ class MediaFoundationRendererIntegrationTest }; TEST_F(MediaFoundationRendererIntegrationTest, BasicPlayback) { + // TODO(crbug.com/1240681): This test is very flaky on win10-20h2. + if (base::win::OSInfo::GetInstance()->version() >= + base::win::Version::WIN10_20H2) { + GTEST_SKIP() << "Skipping test for WIN10_20H2 and greater"; + } if (!CanDecodeVp9()) return; @@ -81,6 +89,11 @@ TEST_F(MediaFoundationRendererIntegrationTest, BasicPlayback) { } TEST_F(MediaFoundationRendererIntegrationTest, BasicPlayback_MediaSource) { + // TODO(crbug.com/1240681): This test is very flaky on win10-20h2. + if (base::win::OSInfo::GetInstance()->version() >= + base::win::Version::WIN10_20H2) { + GTEST_SKIP() << "Skipping test for WIN10_20H2 and greater"; + } if (!CanDecodeVp9()) return; diff --git a/chromium/media/renderers/win/media_foundation_renderer_unittest.cc b/chromium/media/renderers/win/media_foundation_renderer_unittest.cc index 8678ae691f6..07b7f19dd25 100644 --- a/chromium/media/renderers/win/media_foundation_renderer_unittest.cc +++ b/chromium/media/renderers/win/media_foundation_renderer_unittest.cc @@ -15,6 +15,7 @@ #include "base/win/scoped_com_initializer.h" #include "media/base/bind_to_current_loop.h" #include "media/base/demuxer_stream.h" +#include "media/base/media_util.h" #include "media/base/mock_filters.h" #include "media/base/test_helpers.h" #include "media/base/win/test_utils.h" @@ -103,7 +104,8 @@ class MediaFoundationRendererTest : public testing::Test { &pmp_server_); mf_renderer_ = std::make_unique<MediaFoundationRenderer>( - task_environment_.GetMainThreadTaskRunner()); + task_environment_.GetMainThreadTaskRunner(), + std::make_unique<NullMediaLog>()); // Some default actions. ON_CALL(cdm_context_, GetMediaFoundationCdmProxy(_)) diff --git a/chromium/media/renderers/win/media_foundation_source_wrapper.cc b/chromium/media/renderers/win/media_foundation_source_wrapper.cc index 3a41567f5c4..a6b2cc8279a 100644 --- a/chromium/media/renderers/win/media_foundation_source_wrapper.cc +++ b/chromium/media/renderers/win/media_foundation_source_wrapper.cc @@ -8,6 +8,7 @@ #include "media/base/audio_decoder_config.h" #include "media/base/demuxer_stream.h" +#include "media/base/media_log.h" #include "media/base/video_decoder_config.h" #include "media/base/win/mf_helpers.h" @@ -34,6 +35,7 @@ MediaFoundationSourceWrapper::~MediaFoundationSourceWrapper() { HRESULT MediaFoundationSourceWrapper::RuntimeClassInitialize( MediaResource* media_resource, + MediaLog* media_log, scoped_refptr<base::SequencedTaskRunner> task_runner) { DVLOG_FUNC(1); @@ -50,7 +52,8 @@ HRESULT MediaFoundationSourceWrapper::RuntimeClassInitialize( for (DemuxerStream* demuxer_stream : demuxer_streams) { ComPtr<MediaFoundationStreamWrapper> mf_stream; RETURN_IF_FAILED(MediaFoundationStreamWrapper::Create( - stream_id++, this, demuxer_stream, task_runner, &mf_stream)); + stream_id++, this, demuxer_stream, media_log->Clone(), task_runner, + &mf_stream)); media_streams_.push_back(mf_stream); } diff --git a/chromium/media/renderers/win/media_foundation_source_wrapper.h b/chromium/media/renderers/win/media_foundation_source_wrapper.h index 88ca8f96b44..de77dac3555 100644 --- a/chromium/media/renderers/win/media_foundation_source_wrapper.h +++ b/chromium/media/renderers/win/media_foundation_source_wrapper.h @@ -20,6 +20,8 @@ namespace media { +class MediaLog; + // IMFMediaSource implementation // (https://docs.microsoft.com/en-us/windows/win32/api/mfidl/nn-mfidl-imfmediasource) // based on the given |media_resource|. @@ -47,6 +49,7 @@ class MediaFoundationSourceWrapper HRESULT RuntimeClassInitialize( MediaResource* media_resource, + MediaLog* media_log, scoped_refptr<base::SequencedTaskRunner> task_runner); // Note: All COM interface (IMFXxx) methods are called on the MF threadpool diff --git a/chromium/media/renderers/win/media_foundation_stream_wrapper.cc b/chromium/media/renderers/win/media_foundation_stream_wrapper.cc index 7eb15906d5c..0d7783695af 100644 --- a/chromium/media/renderers/win/media_foundation_stream_wrapper.cc +++ b/chromium/media/renderers/win/media_foundation_stream_wrapper.cc @@ -122,6 +122,7 @@ HRESULT MediaFoundationStreamWrapper::Create( int stream_id, IMFMediaSource* parent_source, DemuxerStream* demuxer_stream, + std::unique_ptr<MediaLog> media_log, scoped_refptr<base::SequencedTaskRunner> task_runner, MediaFoundationStreamWrapper** stream_out) { DVLOG(1) << __func__ << ": stream_id=" << stream_id; @@ -130,11 +131,13 @@ HRESULT MediaFoundationStreamWrapper::Create( switch (demuxer_stream->type()) { case DemuxerStream::Type::VIDEO: RETURN_IF_FAILED(MediaFoundationVideoStream::Create( - stream_id, parent_source, demuxer_stream, &stream)); + stream_id, parent_source, demuxer_stream, std::move(media_log), + &stream)); break; case DemuxerStream::Type::AUDIO: RETURN_IF_FAILED(MediaFoundationAudioStream::Create( - stream_id, parent_source, demuxer_stream, &stream)); + stream_id, parent_source, demuxer_stream, std::move(media_log), + &stream)); break; default: DLOG(ERROR) << "Unsupported demuxer stream type: " @@ -149,7 +152,8 @@ HRESULT MediaFoundationStreamWrapper::Create( HRESULT MediaFoundationStreamWrapper::RuntimeClassInitialize( int stream_id, IMFMediaSource* parent_source, - DemuxerStream* demuxer_stream) { + DemuxerStream* demuxer_stream, + std::unique_ptr<MediaLog> media_log) { { base::AutoLock auto_lock(lock_); parent_source_ = parent_source; @@ -161,6 +165,8 @@ HRESULT MediaFoundationStreamWrapper::RuntimeClassInitialize( DVLOG_FUNC(1) << "stream_id=" << stream_id << ", stream_type=" << DemuxerStream::GetTypeName(stream_type_); + media_log_ = std::move(media_log); + RETURN_IF_FAILED(GenerateStreamDescriptor()); RETURN_IF_FAILED(MFCreateEventQueue(&mf_media_event_queue_)); return S_OK; @@ -394,6 +400,11 @@ void MediaFoundationStreamWrapper::OnDemuxerStreamRead( HRESULT hr = S_OK; if (status == DemuxerStream::Status::kOk) { + if (!encryption_type_reported_) { + encryption_type_reported_ = true; + ReportEncryptionType(buffer); + } + // Push |buffer| to process later if needed. Otherwise, process it // immediately. if (flushed_ || !post_flush_buffers_.empty()) { @@ -601,4 +612,24 @@ GUID MediaFoundationStreamWrapper::GetLastKeyId() const { return last_key_id_; } +void MediaFoundationStreamWrapper::ReportEncryptionType( + const scoped_refptr<DecoderBuffer>& buffer) { + auto encryption_type = EncryptionType::kClear; + if (IsEncrypted()) { + bool is_buffer_encrypted = buffer->decrypt_config(); + encryption_type = !is_buffer_encrypted + ? EncryptionType::kEncryptedWithClearLead + : EncryptionType::kEncrypted; + } + + if (encryption_type == EncryptionType::kEncryptedWithClearLead) { + MEDIA_LOG(INFO, media_log_) << "MediaFoundationStreamWrapper: " + << DemuxerStream::GetTypeName(stream_type_) + << " stream is encrypted with clear lead"; + } + + // TODO(xhwang): Report `encryption_type` to `PipelineStatistics` so it's + // also reported to UKM. +} + } // namespace media diff --git a/chromium/media/renderers/win/media_foundation_stream_wrapper.h b/chromium/media/renderers/win/media_foundation_stream_wrapper.h index 6e9cd79fe06..521cb4683a8 100644 --- a/chromium/media/renderers/win/media_foundation_stream_wrapper.h +++ b/chromium/media/renderers/win/media_foundation_stream_wrapper.h @@ -8,6 +8,8 @@ #include <mfapi.h> #include <mfidl.h> #include <wrl.h> + +#include <memory> #include <queue> #include "base/memory/scoped_refptr.h" @@ -16,6 +18,7 @@ #include "base/synchronization/lock.h" #include "media/base/decoder_buffer.h" #include "media/base/demuxer_stream.h" +#include "media/base/media_log.h" namespace media { @@ -47,12 +50,14 @@ class MediaFoundationStreamWrapper static HRESULT Create(int stream_id, IMFMediaSource* parent_source, DemuxerStream* demuxer_stream, + std::unique_ptr<MediaLog> media_log, scoped_refptr<base::SequencedTaskRunner> task_runner, MediaFoundationStreamWrapper** stream_out); HRESULT RuntimeClassInitialize(int stream_id, IMFMediaSource* parent_source, - DemuxerStream* demuxer_stream); + DemuxerStream* demuxer_stream, + std::unique_ptr<MediaLog> media_log); void SetTaskRunner(scoped_refptr<base::SequencedTaskRunner> task_runner); void DetachParent(); void DetachDemuxerStream(); @@ -116,6 +121,8 @@ class MediaFoundationStreamWrapper bool ServicePostFlushSampleRequest(); virtual HRESULT GetMediaType(IMFMediaType** media_type_out) = 0; + void ReportEncryptionType(const scoped_refptr<DecoderBuffer>& buffer); + scoped_refptr<base::SequencedTaskRunner> task_runner_; enum class State { kInitialized, @@ -126,6 +133,8 @@ class MediaFoundationStreamWrapper DemuxerStream* demuxer_stream_ = nullptr; DemuxerStream::Type stream_type_ = DemuxerStream::Type::UNKNOWN; + std::unique_ptr<MediaLog> media_log_; + // Need exclusive access to some members between calls from MF threadpool // thread and calling thread from Chromium media stack. base::Lock lock_; @@ -166,6 +175,8 @@ class MediaFoundationStreamWrapper std::queue<scoped_refptr<DecoderBuffer>> post_flush_buffers_ GUARDED_BY(lock_); + bool encryption_type_reported_ = false; + // NOTE: Weak pointers must be invalidated before all other member variables. base::WeakPtrFactory<MediaFoundationStreamWrapper> weak_factory_{this}; }; diff --git a/chromium/media/renderers/win/media_foundation_video_stream.cc b/chromium/media/renderers/win/media_foundation_video_stream.cc index 1ef146a6f04..6d623bf3d8d 100644 --- a/chromium/media/renderers/win/media_foundation_video_stream.cc +++ b/chromium/media/renderers/win/media_foundation_video_stream.cc @@ -26,27 +26,27 @@ DEFINE_MEDIATYPE_GUID(MFVideoFormat_THEORA, FCC('theo')) GUID VideoCodecToMFSubtype(VideoCodec codec) { switch (codec) { - case kCodecH264: + case VideoCodec::kH264: return MFVideoFormat_H264; - case kCodecVC1: + case VideoCodec::kVC1: return MFVideoFormat_WVC1; - case kCodecMPEG2: + case VideoCodec::kMPEG2: return MFVideoFormat_MPEG2; - case kCodecMPEG4: + case VideoCodec::kMPEG4: return MFVideoFormat_MP4V; - case kCodecTheora: + case VideoCodec::kTheora: return MFVideoFormat_THEORA; - case kCodecVP8: + case VideoCodec::kVP8: return MFVideoFormat_VP80; - case kCodecVP9: + case VideoCodec::kVP9: return MFVideoFormat_VP90; - case kCodecHEVC: + case VideoCodec::kHEVC: return MFVideoFormat_HEVC; - case kCodecDolbyVision: + case VideoCodec::kDolbyVision: // TODO(frankli): DolbyVision also supports H264 when the profile ID is 9 // (DOLBYVISION_PROFILE9). Will it be fine to use HEVC? return MFVideoFormat_HEVC; - case kCodecAV1: + case VideoCodec::kAV1: return MFVideoFormat_AV1; default: return GUID_NULL; @@ -234,6 +234,7 @@ HRESULT MediaFoundationVideoStream::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; @@ -241,28 +242,32 @@ HRESULT MediaFoundationVideoStream::Create( VideoCodec codec = demuxer_stream->video_decoder_config().codec(); switch (codec) { #if BUILDFLAG(USE_PROPRIETARY_CODECS) - case kCodecH264: + case VideoCodec::kH264: RETURN_IF_FAILED(MakeAndInitialize<MediaFoundationH264VideoStream>( - &video_stream, stream_id, parent_source, demuxer_stream)); + &video_stream, stream_id, parent_source, demuxer_stream, + std::move(media_log))); break; #endif // BUILDFLAG(USE_PROPRIETARY_CODECS) #if BUILDFLAG(ENABLE_PLATFORM_HEVC) - case kCodecHEVC: + case VideoCodec::kHEVC: #endif #if BUILDFLAG(ENABLE_PLATFORM_DOLBY_VISION) - case kCodecDolbyVision: + case VideoCodec::kDolbyVision: #endif #if BUILDFLAG(ENABLE_PLATFORM_HEVC) || BUILDFLAG(ENABLE_PLATFORM_DOLBY_VISION) RETURN_IF_FAILED(MakeAndInitialize<MediaFoundationHEVCVideoStream>( - &video_stream, stream_id, parent_source, demuxer_stream)); + &video_stream, stream_id, parent_source, demuxer_stream, + std::move(media_log))); break; #endif // BUILDFLAG(ENABLE_PLATFORM_HEVC) || // BUILDFLAG(ENABLE_PLATFORM_DOLBY_VISION) default: RETURN_IF_FAILED(MakeAndInitialize<MediaFoundationVideoStream>( - &video_stream, stream_id, parent_source, demuxer_stream)); + &video_stream, stream_id, parent_source, demuxer_stream, + std::move(media_log))); break; } + *stream_out = static_cast<MediaFoundationStreamWrapper*>(video_stream.Detach()); return S_OK; diff --git a/chromium/media/renderers/win/media_foundation_video_stream.h b/chromium/media/renderers/win/media_foundation_video_stream.h index 230df187d44..33e43def6c6 100644 --- a/chromium/media/renderers/win/media_foundation_video_stream.h +++ b/chromium/media/renderers/win/media_foundation_video_stream.h @@ -20,6 +20,7 @@ class MediaFoundationVideoStream : public MediaFoundationStreamWrapper { static HRESULT Create(int stream_id, IMFMediaSource* parent_source, DemuxerStream* demuxer_stream, + std::unique_ptr<MediaLog> media_log, MediaFoundationStreamWrapper** stream_out); bool IsEncrypted() const override; |