summaryrefslogtreecommitdiff
path: root/chromium/media/renderers/win
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/media/renderers/win')
-rw-r--r--chromium/media/renderers/win/media_engine_notify_impl.cc2
-rw-r--r--chromium/media/renderers/win/media_engine_notify_impl.h14
-rw-r--r--chromium/media/renderers/win/media_foundation_audio_stream.cc59
-rw-r--r--chromium/media/renderers/win/media_foundation_audio_stream.h2
-rw-r--r--chromium/media/renderers/win/media_foundation_protection_manager.cc2
-rw-r--r--chromium/media/renderers/win/media_foundation_renderer.cc52
-rw-r--r--chromium/media/renderers/win/media_foundation_renderer.h31
-rw-r--r--chromium/media/renderers/win/media_foundation_renderer_extension.h4
-rw-r--r--chromium/media/renderers/win/media_foundation_renderer_integration_test.cc13
-rw-r--r--chromium/media/renderers/win/media_foundation_renderer_unittest.cc4
-rw-r--r--chromium/media/renderers/win/media_foundation_source_wrapper.cc5
-rw-r--r--chromium/media/renderers/win/media_foundation_source_wrapper.h3
-rw-r--r--chromium/media/renderers/win/media_foundation_stream_wrapper.cc37
-rw-r--r--chromium/media/renderers/win/media_foundation_stream_wrapper.h13
-rw-r--r--chromium/media/renderers/win/media_foundation_video_stream.cc37
-rw-r--r--chromium/media/renderers/win/media_foundation_video_stream.h1
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;