diff options
Diffstat (limited to 'chromium/media/base')
74 files changed, 787 insertions, 700 deletions
diff --git a/chromium/media/base/BUILD.gn b/chromium/media/base/BUILD.gn index e5f3cb49ffd..e45cb89a96a 100644 --- a/chromium/media/base/BUILD.gn +++ b/chromium/media/base/BUILD.gn @@ -37,6 +37,7 @@ jumbo_source_set("base") { "android_overlay_config.cc", "android_overlay_config.h", "android_overlay_mojo_factory.h", + "async_destroy_video_decoder.h", "audio_block_fifo.cc", "audio_block_fifo.h", "audio_buffer.cc", @@ -345,6 +346,7 @@ jumbo_source_set("base") { ] deps = [ "//base/allocator:buildflags", + "//base/util/values:values_util", "//components/system_media_controls/linux/buildflags", "//gpu/command_buffer/common", "//gpu/ipc/common:common", @@ -411,7 +413,10 @@ jumbo_source_set("base") { } if (is_win) { - public_deps += [ "//media/base/win:d3d11" ] + public_deps += [ + "//media/base/win:d3d11", + "//media/base/win:mf_cdm_proxy", + ] } if (is_chromecast || is_fuchsia) { diff --git a/chromium/media/base/android/android_cdm_factory.cc b/chromium/media/base/android/android_cdm_factory.cc index a2c20394f23..faa670ffb1d 100644 --- a/chromium/media/base/android/android_cdm_factory.cc +++ b/chromium/media/base/android/android_cdm_factory.cc @@ -43,7 +43,6 @@ AndroidCdmFactory::~AndroidCdmFactory() { void AndroidCdmFactory::Create( const std::string& key_system, - const url::Origin& security_origin, const CdmConfig& cdm_config, const SessionMessageCB& session_message_cb, const SessionClosedCB& session_closed_cb, @@ -56,11 +55,6 @@ void AndroidCdmFactory::Create( CdmCreatedCB bound_cdm_created_cb = BindToCurrentLoop(std::move(cdm_created_cb)); - if (security_origin.opaque()) { - std::move(bound_cdm_created_cb).Run(nullptr, "Invalid origin."); - return; - } - // Create AesDecryptor here to support External Clear Key key system. // This is used for testing. if (base::FeatureList::IsEnabled(media::kExternalClearKeyForTesting) && @@ -92,9 +86,9 @@ void AndroidCdmFactory::Create( creation_id_, PendingCreation(std::move(factory), std::move(bound_cdm_created_cb))); - raw_factory->Create(key_system, security_origin, cdm_config, - session_message_cb, session_closed_cb, - session_keys_change_cb, session_expiration_update_cb, + raw_factory->Create(key_system, cdm_config, session_message_cb, + session_closed_cb, session_keys_change_cb, + session_expiration_update_cb, base::BindOnce(&AndroidCdmFactory::OnCdmCreated, weak_factory_.GetWeakPtr(), creation_id_)); } diff --git a/chromium/media/base/android/android_cdm_factory.h b/chromium/media/base/android/android_cdm_factory.h index b32b7935b77..ce241061eff 100644 --- a/chromium/media/base/android/android_cdm_factory.h +++ b/chromium/media/base/android/android_cdm_factory.h @@ -29,7 +29,6 @@ class MEDIA_EXPORT AndroidCdmFactory : public CdmFactory { // CdmFactory implementation. void Create(const std::string& key_system, - const url::Origin& security_origin, const CdmConfig& cdm_config, const SessionMessageCB& session_message_cb, const SessionClosedCB& session_closed_cb, diff --git a/chromium/media/base/android/media_drm_bridge.cc b/chromium/media/base/android/media_drm_bridge.cc index 6bdfc3a974d..e0695e964d3 100644 --- a/chromium/media/base/android/media_drm_bridge.cc +++ b/chromium/media/base/android/media_drm_bridge.cc @@ -32,6 +32,7 @@ #include "media/base/android/media_drm_bridge_delegate.h" #include "media/base/android/media_jni_headers/MediaDrmBridge_jni.h" #include "media/base/cdm_key_information.h" +#include "media/base/logging_override_if_enabled.h" #include "media/base/media_drm_key_type.h" #include "media/base/media_switches.h" #include "media/base/provision_fetcher.h" diff --git a/chromium/media/base/android/media_drm_bridge_factory.cc b/chromium/media/base/android/media_drm_bridge_factory.cc index 52b3e01c271..ee3e4dcdb86 100644 --- a/chromium/media/base/android/media_drm_bridge_factory.cc +++ b/chromium/media/base/android/media_drm_bridge_factory.cc @@ -9,7 +9,6 @@ #include "media/base/cdm_config.h" #include "media/base/content_decryption_module.h" #include "third_party/widevine/cdm/widevine_cdm_common.h" -#include "url/origin.h" namespace media { @@ -28,7 +27,6 @@ MediaDrmBridgeFactory::~MediaDrmBridgeFactory() { void MediaDrmBridgeFactory::Create( const std::string& key_system, - const url::Origin& security_origin, const CdmConfig& cdm_config, const SessionMessageCB& session_message_cb, const SessionClosedCB& session_closed_cb, @@ -37,7 +35,6 @@ void MediaDrmBridgeFactory::Create( CdmCreatedCB cdm_created_cb) { DCHECK(MediaDrmBridge::IsKeySystemSupported(key_system)); DCHECK(MediaDrmBridge::IsAvailable()); - DCHECK(!security_origin.opaque()); DCHECK(scheme_uuid_.empty()) << "This factory can only be used once."; scheme_uuid_ = MediaDrmBridge::GetUUID(key_system); diff --git a/chromium/media/base/android/media_drm_bridge_factory.h b/chromium/media/base/android/media_drm_bridge_factory.h index 4dfa133dcf2..6df430ad62f 100644 --- a/chromium/media/base/android/media_drm_bridge_factory.h +++ b/chromium/media/base/android/media_drm_bridge_factory.h @@ -32,7 +32,6 @@ class MEDIA_EXPORT MediaDrmBridgeFactory : public CdmFactory { // CdmFactory implementation. void Create(const std::string& key_system, - const url::Origin& security_origin, const CdmConfig& cdm_config, const SessionMessageCB& session_message_cb, const SessionClosedCB& session_closed_cb, diff --git a/chromium/media/base/android/media_player_bridge.cc b/chromium/media/base/android/media_player_bridge.cc index c0a10cef065..eeab111c274 100644 --- a/chromium/media/base/android/media_player_bridge.cc +++ b/chromium/media/base/android/media_player_bridge.cc @@ -74,6 +74,7 @@ MediaPlayerBridge::MediaPlayerBridge(const GURL& url, bool allow_credentials, bool is_hls) : prepared_(false), + playback_completed_(false), pending_play_(false), should_seek_on_prepare_(false), url_(url), @@ -122,7 +123,7 @@ void MediaPlayerBridge::Initialize() { return; } - if (allow_credentials_) { + if (allow_credentials_ && !url_.SchemeIsFile()) { media::MediaResourceGetter* resource_getter = client_->GetMediaResourceGetter(); @@ -415,7 +416,10 @@ void MediaPlayerBridge::OnMediaError(int error_type) { } void MediaPlayerBridge::OnPlaybackComplete() { - client_->OnPlaybackComplete(); + if (!playback_completed_) { + playback_completed_ = true; + client_->OnPlaybackComplete(); + } } void MediaPlayerBridge::OnMediaPrepared() { @@ -509,6 +513,8 @@ void MediaPlayerBridge::SeekInternal(base::TimeDelta time) { return; } + playback_completed_ = false; + // Note: we do not want to count changes in media time due to seeks as watch // time, but tracking pending seeks is not completely trivial. Instead seeks // larger than kWatchTimeReportingInterval * 2 will be discarded by the sanity diff --git a/chromium/media/base/android/media_player_bridge.h b/chromium/media/base/android/media_player_bridge.h index 8de59c2c59a..8757e09b24a 100644 --- a/chromium/media/base/android/media_player_bridge.h +++ b/chromium/media/base/android/media_player_bridge.h @@ -199,6 +199,9 @@ class MEDIA_EXPORT MediaPlayerBridge { // Whether the player is prepared for playback. bool prepared_; + // Whether the player completed playback. + bool playback_completed_; + // Pending play event while player is preparing. bool pending_play_; diff --git a/chromium/media/base/async_destroy_video_decoder.h b/chromium/media/base/async_destroy_video_decoder.h new file mode 100644 index 00000000000..921109b08f1 --- /dev/null +++ b/chromium/media/base/async_destroy_video_decoder.h @@ -0,0 +1,91 @@ +// Copyright (c) 2020 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. + +#ifndef MEDIA_BASE_ASYNC_DESTROY_VIDEO_DECODER_H_ +#define MEDIA_BASE_ASYNC_DESTROY_VIDEO_DECODER_H_ + +#include <memory> +#include <type_traits> +#include "media/base/video_decoder.h" + +namespace media { + +// Some VideoDecoder implementations must do non-synchronous cleanup before +// they are destroyed. This wrapper implementation allows a VideoDecoder +// to schedule its own cleanup tasks before its memory is released. +// The underlying type must implement a static +// `DestroyAsync(std::unique_ptr<T>)` function which fires any pending +// callbacks, stops and destroys the decoder. After this call, external +// resources (e.g. raw pointers) held by the decoder might be invalidated +// immediately. So if the decoder is destroyed asynchronously (e.g. DeleteSoon), +// external resources must be released in this call. +template <typename T> +class AsyncDestroyVideoDecoder final : public VideoDecoder { + public: + explicit AsyncDestroyVideoDecoder(std::unique_ptr<T> wrapped_decoder) + : wrapped_decoder_(std::move(wrapped_decoder)) { + static_assert(std::is_base_of<VideoDecoder, T>::value, + "T must implement 'media::VideoDecoder'"); + DCHECK(wrapped_decoder_); + } + + ~AsyncDestroyVideoDecoder() override { + if (wrapped_decoder_) + T::DestroyAsync(std::move(wrapped_decoder_)); + } + + std::string GetDisplayName() const override { + DCHECK(wrapped_decoder_); + return wrapped_decoder_->GetDisplayName(); + } + + bool IsPlatformDecoder() const override { + DCHECK(wrapped_decoder_); + return wrapped_decoder_->IsPlatformDecoder(); + } + + void Initialize(const VideoDecoderConfig& config, + bool low_delay, + CdmContext* cdm_context, + InitCB init_cb, + const OutputCB& output_cb, + const WaitingCB& waiting_cb) override { + DCHECK(wrapped_decoder_); + wrapped_decoder_->Initialize(config, low_delay, cdm_context, + std::move(init_cb), output_cb, waiting_cb); + } + + void Decode(scoped_refptr<DecoderBuffer> buffer, + DecodeCB decode_cb) override { + DCHECK(wrapped_decoder_); + wrapped_decoder_->Decode(std::move(buffer), std::move(decode_cb)); + } + + void Reset(base::OnceClosure closure) override { + DCHECK(wrapped_decoder_); + wrapped_decoder_->Reset(std::move(closure)); + } + + bool NeedsBitstreamConversion() const override { + DCHECK(wrapped_decoder_); + return wrapped_decoder_->NeedsBitstreamConversion(); + } + + bool CanReadWithoutStalling() const override { + DCHECK(wrapped_decoder_); + return wrapped_decoder_->CanReadWithoutStalling(); + } + + int GetMaxDecodeRequests() const override { + DCHECK(wrapped_decoder_); + return wrapped_decoder_->GetMaxDecodeRequests(); + } + + private: + std::unique_ptr<T> wrapped_decoder_; +}; + +} // namespace media + +#endif // MEDIA_BASE_ASYNC_DESTROY_VIDEO_DECODER_H_ diff --git a/chromium/media/base/audio_buffer.cc b/chromium/media/base/audio_buffer.cc index d0f34c51e5b..622c9154f4f 100644 --- a/chromium/media/base/audio_buffer.cc +++ b/chromium/media/base/audio_buffer.cc @@ -7,6 +7,7 @@ #include <cmath> #include "base/logging.h" +#include "base/notreached.h" #include "media/base/audio_bus.h" #include "media/base/limits.h" #include "media/base/timestamp_constants.h" @@ -249,9 +250,9 @@ void AudioBuffer::ReadFrames(int frames_to_copy, // |dest| must have the same number of channels, and the number of frames // specified must be in range. DCHECK(!end_of_stream()); - DCHECK_EQ(dest->channels(), channel_count_); - DCHECK_LE(source_frame_offset + frames_to_copy, adjusted_frame_count_); - DCHECK_LE(dest_frame_offset + frames_to_copy, dest->frames()); + CHECK_EQ(dest->channels(), channel_count_); + CHECK_LE(source_frame_offset + frames_to_copy, adjusted_frame_count_); + CHECK_LE(dest_frame_offset + frames_to_copy, dest->frames()); dest->set_is_bitstream_format(IsBitstreamFormat()); diff --git a/chromium/media/base/audio_converter.cc b/chromium/media/base/audio_converter.cc index e54ded8b8fc..8d56906b31f 100644 --- a/chromium/media/base/audio_converter.cc +++ b/chromium/media/base/audio_converter.cc @@ -14,6 +14,7 @@ #include "base/bind.h" #include "base/bind_helpers.h" +#include "base/logging.h" #include "base/trace_event/trace_event.h" #include "media/base/audio_bus.h" #include "media/base/audio_pull_fifo.h" diff --git a/chromium/media/base/audio_renderer.h b/chromium/media/base/audio_renderer.h index eac3c82ffea..533c46150d7 100644 --- a/chromium/media/base/audio_renderer.h +++ b/chromium/media/base/audio_renderer.h @@ -65,6 +65,10 @@ class MEDIA_EXPORT AudioRenderer { // (restore UA default). virtual void SetLatencyHint(base::Optional<base::TimeDelta> latency_hint) = 0; + // Sets a flag indicating that the AudioRenderer should use or avoid pitch + // preservation when playing back at speeds other than 1.0. + virtual void SetPreservesPitch(bool preserves_pitch) = 0; + private: DISALLOW_COPY_AND_ASSIGN(AudioRenderer); }; diff --git a/chromium/media/base/audio_renderer_mixer.cc b/chromium/media/base/audio_renderer_mixer.cc index d3c1bd8c7db..d7109300027 100644 --- a/chromium/media/base/audio_renderer_mixer.cc +++ b/chromium/media/base/audio_renderer_mixer.cc @@ -24,49 +24,15 @@ namespace media { enum { kPauseDelaySeconds = 10 }; -// Tracks the maximum value of a counter and logs it into a UMA histogram upon -// each increase of the maximum. NOT thread-safe, make sure it is used under -// lock. -class AudioRendererMixer::UMAMaxValueTracker { - public: - UMAMaxValueTracker(UmaLogCallback log_callback) - : log_callback_(std::move(log_callback)), count_(0), max_count_(0) {} - - ~UMAMaxValueTracker() = default; - - // Increments the counter, updates the maximum. - void Increment() { - ++count_; - if (max_count_ < count_) { - max_count_ = count_; - log_callback_.Run(max_count_); - } - } - - // Decrements the counter. - void Decrement() { - DCHECK_GE(count_, 0); - --count_; - } - - private: - const UmaLogCallback log_callback_; - int count_; - int max_count_; - DISALLOW_COPY_AND_ASSIGN(UMAMaxValueTracker); -}; - AudioRendererMixer::AudioRendererMixer(const AudioParameters& output_params, - scoped_refptr<AudioRendererSink> sink, - UmaLogCallback log_callback) + scoped_refptr<AudioRendererSink> sink) : output_params_(output_params), audio_sink_(std::move(sink)), master_converter_(output_params, output_params, true), pause_delay_(base::TimeDelta::FromSeconds(kPauseDelaySeconds)), last_play_time_(base::TimeTicks::Now()), // Initialize |playing_| to true since Start() results in an auto-play. - playing_(true), - input_count_tracker_(new UMAMaxValueTracker(std::move(log_callback))) { + playing_(true) { DCHECK(audio_sink_); // If enabled we will disable the real audio output stream for muted/silent @@ -126,8 +92,6 @@ void AudioRendererMixer::AddMixerInput(const AudioParameters& input_params, } converter->second->AddInput(input); } - - input_count_tracker_->Increment(); } void AudioRendererMixer::RemoveMixerInput( @@ -148,8 +112,6 @@ void AudioRendererMixer::RemoveMixerInput( converters_.erase(converter); } } - - input_count_tracker_->Decrement(); } void AudioRendererMixer::AddErrorCallback(AudioRendererMixerInput* input) { diff --git a/chromium/media/base/audio_renderer_mixer.h b/chromium/media/base/audio_renderer_mixer.h index b8917dcf532..db82cb3eaa8 100644 --- a/chromium/media/base/audio_renderer_mixer.h +++ b/chromium/media/base/audio_renderer_mixer.h @@ -35,11 +35,8 @@ class SilentSinkSuspender; class MEDIA_EXPORT AudioRendererMixer : public AudioRendererSink::RenderCallback { public: - using UmaLogCallback = base::RepeatingCallback<void(int)>; - AudioRendererMixer(const AudioParameters& output_params, - scoped_refptr<AudioRendererSink> sink, - UmaLogCallback log_callback); + scoped_refptr<AudioRendererSink> sink); ~AudioRendererMixer() override; // Add or remove a mixer input from mixing; called by AudioRendererMixerInput. @@ -62,8 +59,6 @@ class MEDIA_EXPORT AudioRendererMixer } private: - class UMAMaxValueTracker; - // AudioRendererSink::RenderCallback implementation. int Render(base::TimeDelta delay, base::TimeTicks delay_timestamp, @@ -115,10 +110,6 @@ class MEDIA_EXPORT AudioRendererMixer base::TimeTicks last_play_time_ GUARDED_BY(lock_); bool playing_ GUARDED_BY(lock_); - // Tracks the maximum number of simultaneous mixer inputs and logs it into - // UMA histogram upon the destruction. - std::unique_ptr<UMAMaxValueTracker> input_count_tracker_ GUARDED_BY(lock_); - DISALLOW_COPY_AND_ASSIGN(AudioRendererMixer); }; diff --git a/chromium/media/base/audio_renderer_mixer_input_unittest.cc b/chromium/media/base/audio_renderer_mixer_input_unittest.cc index c94d73b9ecd..39b9c758531 100644 --- a/chromium/media/base/audio_renderer_mixer_input_unittest.cc +++ b/chromium/media/base/audio_renderer_mixer_input_unittest.cc @@ -21,10 +21,6 @@ using testing::_; -namespace { -void LogUma(int value) {} -} - namespace media { static const int kSampleRate = 48000; @@ -67,8 +63,8 @@ class AudioRendererMixerInputTest : public testing::Test, EXPECT_CALL(*reinterpret_cast<MockAudioRendererSink*>(sink.get()), Start()); - mixers_[idx].reset(new AudioRendererMixer( - audio_parameters_, std::move(sink), base::BindRepeating(&LogUma))); + mixers_[idx] = std::make_unique<AudioRendererMixer>(audio_parameters_, + std::move(sink)); } EXPECT_CALL(*this, ReturnMixer(mixers_[idx].get())); return mixers_[idx].get(); diff --git a/chromium/media/base/audio_renderer_mixer_unittest.cc b/chromium/media/base/audio_renderer_mixer_unittest.cc index 14cdde6d460..d979c591c72 100644 --- a/chromium/media/base/audio_renderer_mixer_unittest.cc +++ b/chromium/media/base/audio_renderer_mixer_unittest.cc @@ -25,10 +25,6 @@ #include "testing/gmock/include/gmock/gmock.h" #include "testing/gtest/include/gtest/gtest.h" -namespace { -void LogUma(int value) {} -} - namespace media { // Parameters which control the many input case tests. @@ -77,8 +73,7 @@ class AudioRendererMixerTest EXPECT_CALL(*sink_.get(), Start()); EXPECT_CALL(*sink_.get(), Stop()); - mixer_.reset(new AudioRendererMixer(output_parameters_, sink_, - base::BindRepeating(&LogUma))); + mixer_ = std::make_unique<AudioRendererMixer>(output_parameters_, sink_); mixer_callback_ = sink_->callback(); audio_bus_ = AudioBus::Create(output_parameters_); diff --git a/chromium/media/base/audio_shifter.cc b/chromium/media/base/audio_shifter.cc index e6cb0459566..3b7ae5441fc 100644 --- a/chromium/media/base/audio_shifter.cc +++ b/chromium/media/base/audio_shifter.cc @@ -10,6 +10,7 @@ #include "base/bind.h" #include "base/containers/circular_deque.h" +#include "base/logging.h" #include "base/numerics/ranges.h" #include "base/trace_event/trace_event.h" #include "media/base/audio_bus.h" diff --git a/chromium/media/base/bit_reader_core.h b/chromium/media/base/bit_reader_core.h index 1ba856a6986..7a9f7497ec0 100644 --- a/chromium/media/base/bit_reader_core.h +++ b/chromium/media/base/bit_reader_core.h @@ -7,7 +7,7 @@ #include <stdint.h> -#include "base/logging.h" +#include "base/check_op.h" #include "base/macros.h" #include "media/base/media_export.h" diff --git a/chromium/media/base/cdm_context.cc b/chromium/media/base/cdm_context.cc index dac22fbd70f..cf298fef0e6 100644 --- a/chromium/media/base/cdm_context.cc +++ b/chromium/media/base/cdm_context.cc @@ -48,6 +48,4 @@ FuchsiaCdmContext* CdmContext::GetFuchsiaCdmContext() { } #endif -void IgnoreCdmAttached(bool /* success */) {} - } // namespace media diff --git a/chromium/media/base/cdm_context.h b/chromium/media/base/cdm_context.h index e346698746e..b3a0d19c149 100644 --- a/chromium/media/base/cdm_context.h +++ b/chromium/media/base/cdm_context.h @@ -12,6 +12,7 @@ #include "media/media_buildflags.h" #if defined(OS_WIN) +#include <wrl/client.h> struct IMFCdmProxy; #endif @@ -90,7 +91,8 @@ class MEDIA_EXPORT CdmContext { virtual int GetCdmId() const; #if defined(OS_WIN) - using GetMediaFoundationCdmProxyCB = base::OnceCallback<void(IMFCdmProxy*)>; + using GetMediaFoundationCdmProxyCB = + base::OnceCallback<void(Microsoft::WRL::ComPtr<IMFCdmProxy>)>; // This allows a CdmContext to expose an IMFTrustedInput instance for use in // a Media Foundation rendering pipeline. This method is asynchronous because // the underlying MF-based CDM might not have a native session created yet. @@ -120,13 +122,6 @@ class MEDIA_EXPORT CdmContext { DISALLOW_COPY_AND_ASSIGN(CdmContext); }; -// Callback to notify that the CdmContext has been completely attached to -// the media pipeline. Parameter indicates whether the operation succeeded. -typedef base::OnceCallback<void(bool)> CdmAttachedCB; - -// A dummy implementation of CdmAttachedCB. -MEDIA_EXPORT void IgnoreCdmAttached(bool success); - // A reference holder to make sure the CdmContext is always valid as long as // |this| is alive. Typically |this| will hold a reference (directly or // indirectly) to the host, e.g. a ContentDecryptionModule. diff --git a/chromium/media/base/cdm_factory.h b/chromium/media/base/cdm_factory.h index 29d764d8ae0..96fcf3a8678 100644 --- a/chromium/media/base/cdm_factory.h +++ b/chromium/media/base/cdm_factory.h @@ -34,7 +34,6 @@ class MEDIA_EXPORT CdmFactory { // asynchronously. virtual void Create( const std::string& key_system, - const url::Origin& security_origin, const CdmConfig& cdm_config, const SessionMessageCB& session_message_cb, const SessionClosedCB& session_closed_cb, diff --git a/chromium/media/base/cdm_promise.h b/chromium/media/base/cdm_promise.h index 771a6f025cc..5b3d05f5bc7 100644 --- a/chromium/media/base/cdm_promise.h +++ b/chromium/media/base/cdm_promise.h @@ -9,6 +9,7 @@ #include <string> +#include "base/check.h" #include "base/logging.h" #include "base/macros.h" #include "media/base/cdm_key_information.h" diff --git a/chromium/media/base/cdm_session_tracker.h b/chromium/media/base/cdm_session_tracker.h index 94dfa5e5f57..2d902640637 100644 --- a/chromium/media/base/cdm_session_tracker.h +++ b/chromium/media/base/cdm_session_tracker.h @@ -10,7 +10,6 @@ #include <string> #include <unordered_set> -#include "base/logging.h" #include "base/macros.h" #include "media/base/content_decryption_module.h" #include "media/base/media_export.h" diff --git a/chromium/media/base/channel_layout.cc b/chromium/media/base/channel_layout.cc index d7378d2619c..5a1738bbe85 100644 --- a/chromium/media/base/channel_layout.cc +++ b/chromium/media/base/channel_layout.cc @@ -6,7 +6,9 @@ #include <stddef.h> +#include "base/check_op.h" #include "base/logging.h" +#include "base/notreached.h" #include "base/stl_util.h" namespace media { diff --git a/chromium/media/base/data_buffer.h b/chromium/media/base/data_buffer.h index b7906b8ffd5..72a0398569c 100644 --- a/chromium/media/base/data_buffer.h +++ b/chromium/media/base/data_buffer.h @@ -9,7 +9,7 @@ #include <memory> -#include "base/logging.h" +#include "base/check_op.h" #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/time/time.h" diff --git a/chromium/media/base/decode_status.cc b/chromium/media/base/decode_status.cc index 97fda7276d0..de30ca7e306 100644 --- a/chromium/media/base/decode_status.cc +++ b/chromium/media/base/decode_status.cc @@ -51,7 +51,7 @@ ScopedDecodeTrace::ScopedDecodeTrace(const char* trace_name, : trace_name_(trace_name) { DCHECK(trace_name_); TRACE_EVENT_ASYNC_BEGIN1("media", trace_name_, this, "decoder_buffer", - buffer.AsHumanReadableString()); + buffer.AsHumanReadableString(/*verbose=*/true)); } ScopedDecodeTrace::~ScopedDecodeTrace() { diff --git a/chromium/media/base/decoder_buffer.cc b/chromium/media/base/decoder_buffer.cc index 0a593b8d6ef..995e1044db7 100644 --- a/chromium/media/base/decoder_buffer.cc +++ b/chromium/media/base/decoder_buffer.cc @@ -164,21 +164,27 @@ bool DecoderBuffer::MatchesForTesting(const DecoderBuffer& buffer) const { : true; } -std::string DecoderBuffer::AsHumanReadableString() const { +std::string DecoderBuffer::AsHumanReadableString(bool verbose) const { if (end_of_stream()) return "EOS"; std::ostringstream s; - s << "timestamp=" << timestamp_.InMicroseconds() + + s << "{timestamp=" << timestamp_.InMicroseconds() << " duration=" << duration_.InMicroseconds() << " size=" << size_ - << " side_data_size=" << side_data_size_ << " is_key_frame=" << is_key_frame_ - << " encrypted=" << (decrypt_config_ != NULL) << " discard_padding (us)=(" - << discard_padding_.first.InMicroseconds() << ", " - << discard_padding_.second.InMicroseconds() << ")"; + << " encrypted=" << (decrypt_config_ != nullptr); + + if (verbose) { + s << " side_data_size=" << side_data_size_ << " discard_padding (us)=(" + << discard_padding_.first.InMicroseconds() << ", " + << discard_padding_.second.InMicroseconds() << ")"; + + if (decrypt_config_) + s << " decrypt_config=" << (*decrypt_config_); + } - if (decrypt_config_) - s << " decrypt=" << (*decrypt_config_); + s << "}"; return s.str(); } diff --git a/chromium/media/base/decoder_buffer.h b/chromium/media/base/decoder_buffer.h index e1bd6297b47..ea64fa50d0b 100644 --- a/chromium/media/base/decoder_buffer.h +++ b/chromium/media/base/decoder_buffer.h @@ -12,7 +12,7 @@ #include <string> #include <utility> -#include "base/logging.h" +#include "base/check.h" #include "base/macros.h" #include "base/memory/aligned_memory.h" #include "base/memory/read_only_shared_memory_region.h" @@ -190,7 +190,7 @@ class MEDIA_EXPORT DecoderBuffer bool MatchesForTesting(const DecoderBuffer& buffer) const; // Returns a human-readable string describing |*this|. - std::string AsHumanReadableString() const; + std::string AsHumanReadableString(bool verbose = false) const; // Replaces any existing side data with data copied from |side_data|. void CopySideDataFrom(const uint8_t* side_data, size_t side_data_size); diff --git a/chromium/media/base/fake_audio_renderer_sink.cc b/chromium/media/base/fake_audio_renderer_sink.cc index bf5ca25b581..114aa95dcb1 100644 --- a/chromium/media/base/fake_audio_renderer_sink.cc +++ b/chromium/media/base/fake_audio_renderer_sink.cc @@ -47,7 +47,7 @@ void FakeAudioRendererSink::Start() { } void FakeAudioRendererSink::Stop() { - callback_ = NULL; + callback_ = nullptr; ChangeState(kStopped); } diff --git a/chromium/media/base/format_utils.cc b/chromium/media/base/format_utils.cc index b86350cea54..be5a8b9c411 100644 --- a/chromium/media/base/format_utils.cc +++ b/chromium/media/base/format_utils.cc @@ -34,6 +34,9 @@ base::Optional<VideoPixelFormat> GfxBufferFormatToVideoPixelFormat( case gfx::BufferFormat::YUV_420_BIPLANAR: return PIXEL_FORMAT_NV12; + case gfx::BufferFormat::P010: + return PIXEL_FORMAT_P016LE; + default: DLOG(WARNING) << "Unsupported BufferFormat: " << gfx::BufferFormatToString(format); @@ -62,6 +65,9 @@ base::Optional<gfx::BufferFormat> VideoPixelFormatToGfxBufferFormat( case PIXEL_FORMAT_XBGR: return gfx::BufferFormat::RGBX_8888; + case PIXEL_FORMAT_P016LE: + return gfx::BufferFormat::P010; + default: DLOG(WARNING) << "Unsupported VideoPixelFormat: " << pixel_format; return base::nullopt; diff --git a/chromium/media/base/key_systems.cc b/chromium/media/base/key_systems.cc index eabf9796a93..35dc6e348fe 100644 --- a/chromium/media/base/key_systems.cc +++ b/chromium/media/base/key_systems.cc @@ -11,6 +11,7 @@ #include "base/logging.h" #include "base/no_destructor.h" +#include "base/notreached.h" #include "base/stl_util.h" #include "base/strings/string_util.h" #include "base/threading/thread_checker.h" diff --git a/chromium/media/base/mac/video_frame_mac.cc b/chromium/media/base/mac/video_frame_mac.cc index e299bf2fadb..7d3eb1a48ed 100644 --- a/chromium/media/base/mac/video_frame_mac.cc +++ b/chromium/media/base/mac/video_frame_mac.cc @@ -9,6 +9,7 @@ #include <algorithm> +#include "base/logging.h" #include "media/base/video_frame.h" namespace media { diff --git a/chromium/media/base/mac/videotoolbox_helpers.cc b/chromium/media/base/mac/videotoolbox_helpers.cc index 1cd9c596e18..014cd2a05dd 100644 --- a/chromium/media/base/mac/videotoolbox_helpers.cc +++ b/chromium/media/base/mac/videotoolbox_helpers.cc @@ -8,6 +8,8 @@ #include <vector> #include "base/big_endian.h" +#include "base/logging.h" +#include "base/notreached.h" namespace media { diff --git a/chromium/media/base/media_observer.h b/chromium/media/base/media_observer.h index eb0e3969c58..533b60dd728 100644 --- a/chromium/media/base/media_observer.h +++ b/chromium/media/base/media_observer.h @@ -5,7 +5,6 @@ #ifndef MEDIA_BASE_MEDIA_OBSERVER_H_ #define MEDIA_BASE_MEDIA_OBSERVER_H_ -#include "media/base/cdm_context.h" #include "media/base/pipeline_metadata.h" #include "url/gurl.h" diff --git a/chromium/media/base/media_switches.cc b/chromium/media/base/media_switches.cc index e0d62061b43..162d2e2991a 100644 --- a/chromium/media/base/media_switches.cc +++ b/chromium/media/base/media_switches.cc @@ -239,6 +239,11 @@ const base::Feature kResumeBackgroundVideo { #endif }; +// When enabled, MediaCapabilities will check with GPU Video Accelerator +// Factories to determine isPowerEfficient = true/false. +const base::Feature kMediaCapabilitiesQueryGpuFactories{ + "MediaCapabilitiesQueryGpuFactories", base::FEATURE_DISABLED_BY_DEFAULT}; + // Enable Media Capabilities with finch-parameters. const base::Feature kMediaCapabilitiesWithParameters{ "MediaCapabilitiesWithParameters", base::FEATURE_ENABLED_BY_DEFAULT}; @@ -261,6 +266,12 @@ const base::Feature kBackgroundVideoPauseOptimization{ const base::Feature kCdmHostVerification{"CdmHostVerification", base::FEATURE_ENABLED_BY_DEFAULT}; +// Use per-CDM-type, per-user and per-site CDM processes (for library CDM). If +// disabled, the CDM processes are only per-CDM-type, meaning different sites +// using the same CDM type would share one CDM process. +const base::Feature kCdmProcessSiteIsolation{"CdmProcessSiteIsolation", + base::FEATURE_ENABLED_BY_DEFAULT}; + // Make MSE garbage collection algorithm more aggressive when we are under // moderate or critical memory pressure. This will relieve memory pressure by // releasing stale data from MSE buffers. @@ -365,7 +376,7 @@ const base::Feature kGlobalMediaControlsOverlayControls{ "GlobalMediaControlsOverlayControls", base::FEATURE_DISABLED_BY_DEFAULT}; // Show picture-in-picture button in Global Media Controls. -const base::Feature kGlobalMediaControlsPictureInPicture{ +const base::Feature kGlobalMediaControlsPictureInPicture { "GlobalMediaControlsPictureInPicture", #if defined(OS_WIN) || defined(OS_MACOSX) || \ (defined(OS_LINUX) && !defined(OS_CHROMEOS)) @@ -375,6 +386,10 @@ const base::Feature kGlobalMediaControlsPictureInPicture{ #endif }; +// Enable selection of audio output device in Global Media Controls. +const base::Feature kGlobalMediaControlsSeamlessTransfer { + "GlobalMediaControlsSeamlessTransfer", base::FEATURE_DISABLED_BY_DEFAULT}; + // Enable new cpu load estimator. Intended for evaluation in local // testing and origin-trial. // TODO(nisse): Delete once we have switched over to always using the @@ -408,13 +423,9 @@ const base::Feature kUseR16Texture{"use-r16-texture", const base::Feature kUnifiedAutoplay{"UnifiedAutoplay", base::FEATURE_ENABLED_BY_DEFAULT}; -// Enable VA-API hardware encode acceleration for H264 on AMD. -const base::Feature kVaapiH264AMDEncoder{"VaapiH264AMDEncoder", - base::FEATURE_ENABLED_BY_DEFAULT}; - -// Enable VA-API hardware low power encoder for all codecs. -const base::Feature kVaapiLowPowerEncoder{"VaapiLowPowerEncoder", - base::FEATURE_DISABLED_BY_DEFAULT}; +// Enable VA-API hardware low power encoder for all codecs on intel Gen9x gpu. +const base::Feature kVaapiLowPowerEncoderGen9x{ + "VaapiLowPowerEncoderGen9x", base::FEATURE_DISABLED_BY_DEFAULT}; // Enable VA-API hardware encode acceleration for VP8. const base::Feature kVaapiVP8Encoder{"VaapiVP8Encoder", @@ -475,7 +486,7 @@ const base::Feature kWidevineAv1ForceSupportForTesting{ "WidevineAv1ForceSupportForTesting", base::FEATURE_DISABLED_BY_DEFAULT}; // Enables handling of hardware media keys for controlling media. -const base::Feature kHardwareMediaKeyHandling{ +const base::Feature kHardwareMediaKeyHandling { "HardwareMediaKeyHandling", #if defined(OS_CHROMEOS) || defined(OS_WIN) || defined(OS_MACOSX) || \ BUILDFLAG(USE_MPRIS) @@ -505,6 +516,12 @@ const base::Feature kAutoplayWhitelistSettings{ "AutoplayWhitelistSettings", base::FEATURE_ENABLED_BY_DEFAULT}; #if defined(OS_ANDROID) +// Should we allow video playback to use an overlay if it's not needed for +// security? Normally, we'd always want to allow this, except as part of the +// power testing A/B experiment. https://crbug.com/1081346 . +const base::Feature kAllowNonSecureOverlays{"AllowNonSecureOverlays", + base::FEATURE_ENABLED_BY_DEFAULT}; + // Enable a gesture to make the media controls expaned into the display cutout. // TODO(beccahughes): Remove this. const base::Feature kMediaControlsExpandGesture{ @@ -584,7 +601,7 @@ const base::Feature kMediaFoundationAsyncH264Encoding{ // Enables AV1 decode acceleration for Windows. const base::Feature MEDIA_EXPORT kMediaFoundationAV1Decoding{ - "MediaFoundationAV1Decoding", base::FEATURE_DISABLED_BY_DEFAULT}; + "MediaFoundationAV1Decoding", base::FEATURE_ENABLED_BY_DEFAULT}; // Enables MediaFoundation based video capture const base::Feature kMediaFoundationVideoCapture{ @@ -653,6 +670,10 @@ const base::Feature kMediaEngagementHTTPSOnly{ const base::Feature kMediaFeeds{"MediaFeeds", base::FEATURE_DISABLED_BY_DEFAULT}; +// Enables fetching Media Feeds periodically in the background. +const base::Feature kMediaFeedsBackgroundFetching{ + "MediaFeedsBackgroundFetching", base::FEATURE_DISABLED_BY_DEFAULT}; + // Enables checking Media Feeds against safe search to prevent adult content. const base::Feature kMediaFeedsSafeSearch{"MediaFeedsSafeSearch", base::FEATURE_ENABLED_BY_DEFAULT}; @@ -710,7 +731,7 @@ const base::Feature kInternalMediaSession { }; const base::Feature kKaleidoscope{"Kaleidoscope", - base::FEATURE_DISABLED_BY_DEFAULT}; + base::FEATURE_ENABLED_BY_DEFAULT}; const base::Feature kUseFakeDeviceForMediaStream{ "use-fake-device-for-media-stream", base::FEATURE_DISABLED_BY_DEFAULT}; diff --git a/chromium/media/base/media_switches.h b/chromium/media/base/media_switches.h index 5add050c996..967d16fe80a 100644 --- a/chromium/media/base/media_switches.h +++ b/chromium/media/base/media_switches.h @@ -108,6 +108,7 @@ MEDIA_EXPORT extern const base::Feature kAutoplayWhitelistSettings; MEDIA_EXPORT extern const base::Feature kBackgroundVideoPauseOptimization; MEDIA_EXPORT extern const base::Feature kBresenhamCadence; MEDIA_EXPORT extern const base::Feature kCdmHostVerification; +MEDIA_EXPORT extern const base::Feature kCdmProcessSiteIsolation; MEDIA_EXPORT extern const base::Feature kD3D11PrintCodecOnCrash; MEDIA_EXPORT extern const base::Feature kD3D11VideoDecoder; MEDIA_EXPORT extern const base::Feature kD3D11VideoDecoderIgnoreWorkarounds; @@ -126,17 +127,20 @@ MEDIA_EXPORT extern const base::Feature kGlobalMediaControlsAutoDismiss; MEDIA_EXPORT extern const base::Feature kGlobalMediaControlsForCast; MEDIA_EXPORT extern const base::Feature kGlobalMediaControlsOverlayControls; MEDIA_EXPORT extern const base::Feature kGlobalMediaControlsPictureInPicture; +MEDIA_EXPORT extern const base::Feature kGlobalMediaControlsSeamlessTransfer; MEDIA_EXPORT extern const base::Feature kHardwareMediaKeyHandling; MEDIA_EXPORT extern const base::Feature kHardwareSecureDecryption; MEDIA_EXPORT extern const base::Feature kInternalMediaSession; MEDIA_EXPORT extern const base::Feature kKaleidoscope; MEDIA_EXPORT extern const base::Feature kLiveCaption; MEDIA_EXPORT extern const base::Feature kLowDelayVideoRenderingOnLiveStream; +MEDIA_EXPORT extern const base::Feature kMediaCapabilitiesQueryGpuFactories; MEDIA_EXPORT extern const base::Feature kMediaCapabilitiesWithParameters; MEDIA_EXPORT extern const base::Feature kMediaCastOverlayButton; MEDIA_EXPORT extern const base::Feature kMediaEngagementBypassAutoplayPolicies; MEDIA_EXPORT extern const base::Feature kMediaEngagementHTTPSOnly; MEDIA_EXPORT extern const base::Feature kMediaFeeds; +MEDIA_EXPORT extern const base::Feature kMediaFeedsBackgroundFetching; MEDIA_EXPORT extern const base::Feature kMediaFeedsSafeSearch; MEDIA_EXPORT extern const base::Feature kMediaInspectorLogging; MEDIA_EXPORT extern const base::Feature kMediaLearningExperiment; @@ -164,8 +168,7 @@ MEDIA_EXPORT extern const base::Feature kUseFakeDeviceForMediaStream; MEDIA_EXPORT extern const base::Feature kUseMediaHistoryStore; MEDIA_EXPORT extern const base::Feature kUseNewMediaCache; MEDIA_EXPORT extern const base::Feature kUseR16Texture; -MEDIA_EXPORT extern const base::Feature kVaapiH264AMDEncoder; -MEDIA_EXPORT extern const base::Feature kVaapiLowPowerEncoder; +MEDIA_EXPORT extern const base::Feature kVaapiLowPowerEncoderGen9x; MEDIA_EXPORT extern const base::Feature kVaapiVP8Encoder; MEDIA_EXPORT extern const base::Feature kVaapiVP9Encoder; MEDIA_EXPORT extern const base::Feature kVideoBlitColorAccuracy; @@ -178,6 +181,7 @@ MEDIA_EXPORT extern const base::Feature kVp9kSVCHWDecoding; #endif // defined(ARCH_CPU_X86_FAMILY) && defined(OS_CHROMEOS) #if defined(OS_ANDROID) +MEDIA_EXPORT extern const base::Feature kAllowNonSecureOverlays; MEDIA_EXPORT extern const base::Feature kMediaControlsExpandGesture; MEDIA_EXPORT extern const base::Feature kMediaDrmPersistentLicense; MEDIA_EXPORT extern const base::Feature kMediaDrmPreprovisioning; diff --git a/chromium/media/base/media_url_demuxer.cc b/chromium/media/base/media_url_demuxer.cc index ce7af50c5a8..cff132e69e2 100644 --- a/chromium/media/base/media_url_demuxer.cc +++ b/chromium/media/base/media_url_demuxer.cc @@ -5,6 +5,7 @@ #include "media/base/media_url_demuxer.h" #include "base/bind.h" +#include "base/logging.h" #include "base/single_thread_task_runner.h" namespace media { diff --git a/chromium/media/base/memory_dump_provider_proxy.h b/chromium/media/base/memory_dump_provider_proxy.h index 72767e003fe..0473c79403d 100644 --- a/chromium/media/base/memory_dump_provider_proxy.h +++ b/chromium/media/base/memory_dump_provider_proxy.h @@ -12,7 +12,6 @@ #include <string> #include <utility> -#include "base/logging.h" #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/single_thread_task_runner.h" diff --git a/chromium/media/base/mime_util_internal.cc b/chromium/media/base/mime_util_internal.cc index 30347811de0..bf57e184925 100644 --- a/chromium/media/base/mime_util_internal.cc +++ b/chromium/media/base/mime_util_internal.cc @@ -8,6 +8,7 @@ #include "base/feature_list.h" #include "base/logging.h" #include "base/no_destructor.h" +#include "base/notreached.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" #include "base/strings/string_util.h" @@ -285,11 +286,10 @@ void MimeUtil::AddSupportedMediaFormats() { const CodecSet wav_codecs{PCM}; const CodecSet ogg_audio_codecs{FLAC, OPUS, VORBIS}; -#if !defined(OS_ANDROID) - CodecSet ogg_video_codecs{THEORA, VP8}; -#else - CodecSet ogg_video_codecs; -#endif // !defined(OS_ANDROID) + CodecSet ogg_video_codecs{VP8}; +#if BUILDFLAG(ENABLE_FFMPEG_VIDEO_DECODERS) + ogg_video_codecs.emplace(THEORA); +#endif // BUILDFLAG(ENABLE_FFMPEG_VIDEO_DECODERS) CodecSet ogg_codecs(ogg_audio_codecs); ogg_codecs.insert(ogg_video_codecs.begin(), ogg_video_codecs.end()); diff --git a/chromium/media/base/mime_util_unittest.cc b/chromium/media/base/mime_util_unittest.cc index 31258457dc0..819390fe12a 100644 --- a/chromium/media/base/mime_util_unittest.cc +++ b/chromium/media/base/mime_util_unittest.cc @@ -148,11 +148,7 @@ TEST(MimeUtilTest, CommonMediaMimeType) { EXPECT_TRUE(IsSupportedMediaMimeType("audio/ogg")); EXPECT_TRUE(IsSupportedMediaMimeType("application/ogg")); -#if defined(OS_ANDROID) - EXPECT_FALSE(IsSupportedMediaMimeType("video/ogg")); -#else EXPECT_TRUE(IsSupportedMediaMimeType("video/ogg")); -#endif // OS_ANDROID EXPECT_EQ(kHlsSupported, IsSupportedMediaMimeType("application/x-mpegurl")); EXPECT_EQ(kHlsSupported, IsSupportedMediaMimeType("Application/X-MPEGURL")); diff --git a/chromium/media/base/mock_filters.cc b/chromium/media/base/mock_filters.cc index e16cd6a65a9..109903cbc54 100644 --- a/chromium/media/base/mock_filters.cc +++ b/chromium/media/base/mock_filters.cc @@ -172,13 +172,11 @@ MockCdmSessionPromise::~MockCdmSessionPromise() { } MockCdm::MockCdm(const std::string& key_system, - const url::Origin& security_origin, const SessionMessageCB& session_message_cb, const SessionClosedCB& session_closed_cb, const SessionKeysChangeCB& session_keys_change_cb, const SessionExpirationUpdateCB& session_expiration_update_cb) : key_system_(key_system), - security_origin_(security_origin), session_message_cb_(session_message_cb), session_closed_cb_(session_closed_cb), session_keys_change_cb_(session_keys_change_cb), @@ -214,7 +212,6 @@ MockCdmFactory::~MockCdmFactory() = default; void MockCdmFactory::Create( const std::string& key_system, - const url::Origin& security_origin, const CdmConfig& /* cdm_config */, const SessionMessageCB& session_message_cb, const SessionClosedCB& session_closed_cb, @@ -236,8 +233,8 @@ void MockCdmFactory::Create( // get the MockCdm via MockCdmFactory::GetCreatedCdm() and explicitly specify // expectations using EXPECT_CALL. scoped_refptr<MockCdm> cdm = new NiceMock<MockCdm>( - key_system, security_origin, session_message_cb, session_closed_cb, - session_keys_change_cb, session_expiration_update_cb); + key_system, session_message_cb, session_closed_cb, session_keys_change_cb, + session_expiration_update_cb); created_cdm_ = cdm.get(); std::move(cdm_created_cb).Run(std::move(cdm), ""); } diff --git a/chromium/media/base/mock_filters.h b/chromium/media/base/mock_filters.h index 1d900919416..8f012bd07d9 100644 --- a/chromium/media/base/mock_filters.h +++ b/chromium/media/base/mock_filters.h @@ -114,6 +114,7 @@ class MockPipeline : public Pipeline { MOCK_CONST_METHOD0(GetVolume, float()); MOCK_METHOD1(SetVolume, void(float)); MOCK_METHOD1(SetLatencyHint, void(base::Optional<base::TimeDelta>)); + MOCK_METHOD1(SetPreservesPitch, void(bool)); // TODO(sandersd): These should probably have setters too. MOCK_CONST_METHOD0(GetMediaTime, base::TimeDelta()); @@ -357,6 +358,7 @@ class MockAudioRenderer : public AudioRenderer { MOCK_METHOD1(SetVolume, void(float volume)); MOCK_METHOD1(SetLatencyHint, void(base::Optional<base::TimeDelta> latency_hint)); + MOCK_METHOD1(SetPreservesPitch, void(bool)); private: DISALLOW_COPY_AND_ASSIGN(MockAudioRenderer); @@ -378,7 +380,8 @@ class MockRenderer : public Renderer { RendererClient* client, PipelineStatusCallback& init_cb)); MOCK_METHOD1(SetLatencyHint, void(base::Optional<base::TimeDelta>)); - void Flush(base::OnceClosure flush_cb) { OnFlush(flush_cb); } + MOCK_METHOD1(SetPreservesPitch, void(bool)); + void Flush(base::OnceClosure flush_cb) override { OnFlush(flush_cb); } MOCK_METHOD1(OnFlush, void(base::OnceClosure& flush_cb)); MOCK_METHOD1(StartPlayingFrom, void(base::TimeDelta timestamp)); MOCK_METHOD1(SetPlaybackRate, void(double playback_rate)); @@ -575,7 +578,6 @@ class MockCdmSessionPromise : public NewSessionCdmPromise { class MockCdm : public ContentDecryptionModule { public: MockCdm(const std::string& key_system, - const url::Origin& security_origin, const SessionMessageCB& session_message_cb, const SessionClosedCB& session_closed_cb, const SessionKeysChangeCB& session_keys_change_cb, @@ -646,7 +648,6 @@ class MockCdmFactory : public CdmFactory { // created CDM is passed to |cdm_created_cb|, a copy is kept (and available // using Cdm()). If |key_system| is empty, no CDM will be created. void Create(const std::string& key_system, - const url::Origin& security_origin, const CdmConfig& cdm_config, const SessionMessageCB& session_message_cb, const SessionClosedCB& session_closed_cb, diff --git a/chromium/media/base/output_device_info.cc b/chromium/media/base/output_device_info.cc index 3bc4eaa1f8c..b1270471f08 100644 --- a/chromium/media/base/output_device_info.cc +++ b/chromium/media/base/output_device_info.cc @@ -4,6 +4,8 @@ #include "media/base/output_device_info.h" +#include <sstream> + namespace media { // Output device information returned by GetOutputDeviceInfo() methods of diff --git a/chromium/media/base/pipeline.h b/chromium/media/base/pipeline.h index fbd6575e3d0..72a22a031c9 100644 --- a/chromium/media/base/pipeline.h +++ b/chromium/media/base/pipeline.h @@ -12,7 +12,6 @@ #include "base/time/time.h" #include "media/base/audio_decoder_config.h" #include "media/base/buffering_state.h" -#include "media/base/cdm_context.h" #include "media/base/media_export.h" #include "media/base/media_status.h" #include "media/base/media_track.h" @@ -27,6 +26,7 @@ namespace media { +class CdmContext; class Demuxer; class MEDIA_EXPORT Pipeline { @@ -225,6 +225,10 @@ class MEDIA_EXPORT Pipeline { // can choose its own default. virtual void SetLatencyHint(base::Optional<base::TimeDelta> latency_hint) = 0; + // Sets whether pitch adjustment should be applied when the playback rate is + // different than 1.0. + virtual void SetPreservesPitch(bool preserves_pitch) = 0; + // Returns the current media playback time, which progresses from 0 until // GetMediaDuration(). virtual base::TimeDelta GetMediaTime() const = 0; @@ -243,6 +247,7 @@ class MEDIA_EXPORT Pipeline { // Gets the current pipeline statistics. virtual PipelineStatistics GetStatistics() const = 0; + using CdmAttachedCB = base::OnceCallback<void(bool)>; virtual void SetCdm(CdmContext* cdm_context, CdmAttachedCB cdm_attached_cb) = 0; }; diff --git a/chromium/media/base/pipeline_impl.cc b/chromium/media/base/pipeline_impl.cc index e1d7be53c5c..32bf075a0ec 100644 --- a/chromium/media/base/pipeline_impl.cc +++ b/chromium/media/base/pipeline_impl.cc @@ -20,6 +20,7 @@ #include "base/synchronization/waitable_event.h" #include "base/threading/thread_task_runner_handle.h" #include "media/base/bind_to_current_loop.h" +#include "media/base/cdm_context.h" #include "media/base/demuxer.h" #include "media/base/media_log.h" #include "media/base/media_switches.h" @@ -69,6 +70,7 @@ class PipelineImpl::RendererWrapper : public DemuxerHost, void SetPlaybackRate(double playback_rate); void SetVolume(float volume); void SetLatencyHint(base::Optional<base::TimeDelta> latency_hint); + void SetPreservesPitch(bool preserves_pitch); base::TimeDelta GetMediaTime() const; Ranges<base::TimeDelta> GetBufferedTimeRanges() const; bool DidLoadingProgress(); @@ -192,6 +194,9 @@ class PipelineImpl::RendererWrapper : public DemuxerHost, base::Optional<base::TimeDelta> latency_hint_; CdmContext* cdm_context_; + // By default, apply pitch adjustments. + bool preserves_pitch_ = true; + // Lock used to serialize |shared_state_|. // TODO(crbug.com/893739): Add GUARDED_BY annotations. mutable base::Lock shared_state_lock_; @@ -325,7 +330,7 @@ void PipelineImpl::RendererWrapper::Stop() { if (demuxer_) { demuxer_->Stop(); - demuxer_ = NULL; + demuxer_ = nullptr; } SetState(kStopped); @@ -481,6 +486,17 @@ void PipelineImpl::RendererWrapper::SetLatencyHint( shared_state_.renderer->SetLatencyHint(latency_hint_); } +void PipelineImpl::RendererWrapper::SetPreservesPitch(bool preserves_pitch) { + DCHECK(media_task_runner_->BelongsToCurrentThread()); + + if (preserves_pitch_ == preserves_pitch) + return; + + preserves_pitch_ = preserves_pitch; + if (shared_state_.renderer) + shared_state_.renderer->SetPreservesPitch(preserves_pitch_); +} + base::TimeDelta PipelineImpl::RendererWrapper::GetMediaTime() const { DCHECK(main_task_runner_->BelongsToCurrentThread()); @@ -1034,14 +1050,13 @@ void PipelineImpl::RendererWrapper::InitializeRenderer( break; } - if (cdm_context_) { - shared_state_.renderer->SetCdm(cdm_context_, - base::BindOnce(&IgnoreCdmAttached)); - } + if (cdm_context_) + shared_state_.renderer->SetCdm(cdm_context_, base::DoNothing()); - if (latency_hint_) { + if (latency_hint_) shared_state_.renderer->SetLatencyHint(latency_hint_); - } + + shared_state_.renderer->SetPreservesPitch(preserves_pitch_); shared_state_.renderer->Initialize(demuxer_, this, std::move(done_cb)); } @@ -1359,6 +1374,15 @@ void PipelineImpl::SetLatencyHint( base::Unretained(renderer_wrapper_.get()), latency_hint)); } +void PipelineImpl::SetPreservesPitch(bool preserves_pitch) { + DCHECK(thread_checker_.CalledOnValidThread()); + + media_task_runner_->PostTask( + FROM_HERE, base::BindOnce(&RendererWrapper::SetPreservesPitch, + base::Unretained(renderer_wrapper_.get()), + preserves_pitch)); +} + base::TimeDelta PipelineImpl::GetMediaTime() const { DCHECK(thread_checker_.CalledOnValidThread()); diff --git a/chromium/media/base/pipeline_impl.h b/chromium/media/base/pipeline_impl.h index 101de818805..d9444600f6f 100644 --- a/chromium/media/base/pipeline_impl.h +++ b/chromium/media/base/pipeline_impl.h @@ -104,6 +104,7 @@ class MEDIA_EXPORT PipelineImpl : public Pipeline { float GetVolume() const override; void SetVolume(float volume) override; void SetLatencyHint(base::Optional<base::TimeDelta> latency_hint) override; + void SetPreservesPitch(bool preserves_pitch) override; base::TimeDelta GetMediaTime() const override; Ranges<base::TimeDelta> GetBufferedTimeRanges() const override; base::TimeDelta GetMediaDuration() const override; diff --git a/chromium/media/base/pipeline_impl_unittest.cc b/chromium/media/base/pipeline_impl_unittest.cc index 444f22ca07c..01b1e8b39b3 100644 --- a/chromium/media/base/pipeline_impl_unittest.cc +++ b/chromium/media/base/pipeline_impl_unittest.cc @@ -128,6 +128,8 @@ class PipelineImplTest : public ::testing::Test { .WillRepeatedly(Return(base::TimeDelta())); EXPECT_CALL(*demuxer_, GetStartTime()).WillRepeatedly(Return(start_time_)); + + EXPECT_CALL(*renderer_, SetPreservesPitch(true)).Times(AnyNumber()); } ~PipelineImplTest() override { @@ -302,6 +304,7 @@ class PipelineImplTest : public ::testing::Test { // |renderer_| has been deleted, replace it. scoped_renderer_.reset(new StrictMock<MockRenderer>()); renderer_ = scoped_renderer_.get(); + EXPECT_CALL(*renderer_, SetPreservesPitch(_)).Times(AnyNumber()); } void ExpectResume(const base::TimeDelta& seek_time) { @@ -606,6 +609,10 @@ TEST_F(PipelineImplTest, SuspendResume) { EXPECT_EQ(stats.video_memory_usage, pipeline_->GetStatistics().video_memory_usage); + // Make sure the preserves pitch flag is preserved between after resuming. + EXPECT_CALL(*renderer_, SetPreservesPitch(false)).Times(1); + pipeline_->SetPreservesPitch(false); + ExpectSuspend(); DoSuspend(); @@ -614,6 +621,8 @@ TEST_F(PipelineImplTest, SuspendResume) { base::TimeDelta expected = base::TimeDelta::FromSeconds(2000); ExpectResume(expected); + EXPECT_CALL(*renderer_, SetPreservesPitch(false)).Times(1); + DoResume(expected); } @@ -631,6 +640,21 @@ TEST_F(PipelineImplTest, SetVolume) { base::RunLoop().RunUntilIdle(); } +TEST_F(PipelineImplTest, SetPreservesPitch) { + CreateAudioStream(); + SetDemuxerExpectations(); + + // The audio renderer preserve pitch by default. + EXPECT_CALL(*renderer_, SetPreservesPitch(true)); + StartPipelineAndExpect(PIPELINE_OK); + base::RunLoop().RunUntilIdle(); + + // Changes to the preservesPitch flag should be propagated. + EXPECT_CALL(*renderer_, SetPreservesPitch(false)); + pipeline_->SetPreservesPitch(false); + base::RunLoop().RunUntilIdle(); +} + TEST_F(PipelineImplTest, Properties) { CreateVideoStream(); const auto kDuration = base::TimeDelta::FromSeconds(100); diff --git a/chromium/media/base/ranges.h b/chromium/media/base/ranges.h index ca6d03546aa..d9aa4803d69 100644 --- a/chromium/media/base/ranges.h +++ b/chromium/media/base/ranges.h @@ -12,7 +12,7 @@ #include <ostream> #include <vector> -#include "base/logging.h" +#include "base/check_op.h" #include "base/time/time.h" #include "media/base/media_export.h" diff --git a/chromium/media/base/renderer.cc b/chromium/media/base/renderer.cc index c2e1736fdc0..c1970f95e89 100644 --- a/chromium/media/base/renderer.cc +++ b/chromium/media/base/renderer.cc @@ -3,6 +3,7 @@ // found in the LICENSE file. #include "media/base/renderer.h" +#include "base/logging.h" namespace media { @@ -10,18 +11,27 @@ Renderer::Renderer() = default; Renderer::~Renderer() = default; +void Renderer::SetCdm(CdmContext* cdm_context, CdmAttachedCB cdm_attached_cb) { + DLOG(WARNING) << "CdmContext is not supported."; + std::move(cdm_attached_cb).Run(false); +} + void Renderer::OnSelectedVideoTracksChanged( const std::vector<DemuxerStream*>& enabled_tracks, base::OnceClosure change_completed_cb) { - std::move(change_completed_cb).Run(); DLOG(WARNING) << "Track changes are not supported."; + std::move(change_completed_cb).Run(); } void Renderer::OnEnabledAudioTracksChanged( const std::vector<DemuxerStream*>& enabled_tracks, base::OnceClosure change_completed_cb) { - std::move(change_completed_cb).Run(); DLOG(WARNING) << "Track changes are not supported."; + std::move(change_completed_cb).Run(); +} + +void Renderer::SetPreservesPitch(bool preserves_pitch) { + // Not supported by most renderers. } } // namespace media diff --git a/chromium/media/base/renderer.h b/chromium/media/base/renderer.h index 7481d000bef..b6e1a73373b 100644 --- a/chromium/media/base/renderer.h +++ b/chromium/media/base/renderer.h @@ -11,13 +11,13 @@ #include "base/optional.h" #include "base/time/time.h" #include "media/base/buffering_state.h" -#include "media/base/cdm_context.h" #include "media/base/demuxer_stream.h" #include "media/base/media_export.h" #include "media/base/pipeline_status.h" namespace media { +class CdmContext; class MediaResource; class RendererClient; @@ -38,9 +38,10 @@ class MEDIA_EXPORT Renderer { PipelineStatusCallback init_cb) = 0; // Associates the |cdm_context| with this Renderer for decryption (and - // decoding) of media data, then fires |cdm_attached_cb| with the result. - virtual void SetCdm(CdmContext* cdm_context, - CdmAttachedCB cdm_attached_cb) = 0; + // decoding) of media data, then fires |cdm_attached_cb| with whether the + // operation succeeded. + using CdmAttachedCB = base::OnceCallback<void(bool)>; + virtual void SetCdm(CdmContext* cdm_context, CdmAttachedCB cdm_attached_cb); // Specifies a latency hint from the site. Renderers should clamp the hint // value to reasonable min and max and use the resulting value as a target @@ -50,6 +51,10 @@ class MEDIA_EXPORT Renderer { // thresholds. virtual void SetLatencyHint(base::Optional<base::TimeDelta> latency_hint) = 0; + // Sets whether pitch adjustment should be applied when the playback rate is + // different than 1.0. + virtual void SetPreservesPitch(bool preserves_pitch); + // The following functions must be called after Initialize(). // Discards any buffered data, executing |flush_cb| when completed. diff --git a/chromium/media/base/renderer_factory_selector.h b/chromium/media/base/renderer_factory_selector.h index b6dd257439c..c291fb35d20 100644 --- a/chromium/media/base/renderer_factory_selector.h +++ b/chromium/media/base/renderer_factory_selector.h @@ -46,7 +46,8 @@ enum class RendererFactoryType { kCast = 5, // CastRendererClientFactory kMediaFoundation = 6, // MediaFoundationRendererClientFactory kFuchsia = 7, // FuchsiaRendererFactory - kMaxValue = kFuchsia, + kRemoting = 8, // RemotingRendererFactory + kMaxValue = kRemoting, }; class MEDIA_EXPORT RendererFactorySelector { diff --git a/chromium/media/base/speech_recognition_client.h b/chromium/media/base/speech_recognition_client.h index 1290cd88c25..8103b6a6eca 100644 --- a/chromium/media/base/speech_recognition_client.h +++ b/chromium/media/base/speech_recognition_client.h @@ -7,7 +7,9 @@ #include <memory> +#include "base/callback.h" #include "media/base/audio_buffer.h" +#include "media/base/audio_bus.h" #include "media/base/media_export.h" namespace media { @@ -16,11 +18,19 @@ namespace media { // captions. class MEDIA_EXPORT SpeechRecognitionClient { public: + using OnReadyCallback = base::OnceCallback<void()>; + virtual ~SpeechRecognitionClient() = default; virtual void AddAudio(scoped_refptr<AudioBuffer> buffer) = 0; + virtual void AddAudio(std::unique_ptr<media::AudioBus> audio_bus, + int sample_rate, + media::ChannelLayout channel_layout) = 0; + virtual bool IsSpeechRecognitionAvailable() = 0; + + virtual void SetOnReadyCallback(OnReadyCallback callback) = 0; }; } // namespace media diff --git a/chromium/media/base/status.h b/chromium/media/base/status.h index c06635b27a8..0e81b54f06a 100644 --- a/chromium/media/base/status.h +++ b/chromium/media/base/status.h @@ -179,6 +179,10 @@ class ErrorOr { // the value in question. ErrorOr(Status&& error) : error_(std::move(error)) {} ErrorOr(const Status& error) : error_(error) {} + ErrorOr(StatusCode code, + const base::Location& location = base::Location::Current()) + : error_(Status(code, "", location)) {} + ErrorOr(T&& value) : value_(std::move(value)) {} ErrorOr(const T& value) : value_(value) {} diff --git a/chromium/media/base/status_codes.h b/chromium/media/base/status_codes.h index 468ff813946..84fd4d50274 100644 --- a/chromium/media/base/status_codes.h +++ b/chromium/media/base/status_codes.h @@ -53,6 +53,10 @@ enum class StatusCode : StatusCodeType { kCantCreateEglStream = 0x00000304, kCantCreateEglStreamConsumer = 0x00000305, kCantCreateEglStreamProducer = 0x00000306, + kCannotCreateTextureSelector = 0x00000307, + kCannotQueryID3D11Multithread = 0x00000308, + kCannotGetDecoderConfigCount = 0x00000309, + kCannotGetDecoderConfig = 0x0000030A, // MojoDecoder Errors: 0x04 kMojoDecoderNoWrappedDecoder = 0x00000401, @@ -69,8 +73,9 @@ enum class StatusCode : StatusCodeType { kV4l2FailedFileCapabilitiesCheck = 0x00000505, kV4l2FailedResourceAllocation = 0x00000506, kV4l2BadFormat = 0x00000507, - kVaapiReinitializedDuringDecode = 0x00000508, - kVaapiFailedAcceleratorCreation = 0x00000509, + kV4L2FailedToStartStreamQueue = 0x00000508, + kVaapiReinitializedDuringDecode = 0x00000509, + kVaapiFailedAcceleratorCreation = 0x00000510, // Encoder Error: 0x06 kEncoderInitializeNeverCompleted = 0x00000601, diff --git a/chromium/media/base/supported_types.cc b/chromium/media/base/supported_types.cc index c98ce24e557..f3ccd25f1c4 100644 --- a/chromium/media/base/supported_types.cc +++ b/chromium/media/base/supported_types.cc @@ -7,6 +7,7 @@ #include "base/feature_list.h" #include "base/logging.h" #include "base/no_destructor.h" +#include "base/notreached.h" #include "build/build_config.h" #include "media/base/media.h" #include "media/base/media_client.h" diff --git a/chromium/media/base/test_helpers.h b/chromium/media/base/test_helpers.h index bffe5960363..4fd250ca230 100644 --- a/chromium/media/base/test_helpers.h +++ b/chromium/media/base/test_helpers.h @@ -328,7 +328,14 @@ MATCHER_P2(AudioNonKeyframe, pts_microseconds, dts_microseconds, "") { base::NumberToString(pts_microseconds) + "us and DTS " + base::NumberToString(dts_microseconds) + "us indicated the frame is not a random access point (key " - "frame). All audio frames are expected to be key frames."); + "frame). All audio frames are expected to be key frames for " + "the current audio codec."); +} + +MATCHER(AudioNonKeyframeOutOfOrder, "") { + return CONTAINS_STRING(arg, + "Dependent audio frame with invalid decreasing " + "presentation timestamp detected."); } MATCHER_P2(SkippingSpliceAtOrBefore, @@ -451,6 +458,20 @@ MATCHER_P3(DroppedFrameCheckAppendWindow, base::NumberToString(append_window_end_us) + "us"); } +MATCHER_P3(DroppedAppendWindowUnusedPreroll, + pts_us, + delta_us, + next_pts_us, + "") { + return CONTAINS_STRING( + arg, + "Partial append window trimming dropping unused audio preroll buffer " + "with PTS " + + base::NumberToString(pts_us) + "us that ends too far (" + + base::NumberToString(delta_us) + "us) from next buffer with PTS " + + base::NumberToString(next_pts_us) + "us"); +} + } // namespace media #endif // MEDIA_BASE_TEST_HELPERS_H_ diff --git a/chromium/media/base/test_random.h b/chromium/media/base/test_random.h index f08c6f2cb12..6c5eb51392b 100644 --- a/chromium/media/base/test_random.h +++ b/chromium/media/base/test_random.h @@ -7,7 +7,7 @@ #include <stdint.h> -#include "base/logging.h" +#include "base/check_op.h" // Vastly simplified ACM random class meant to only be used for testing. // This class is meant to generate predictable sequences of pseudorandom diff --git a/chromium/media/base/user_input_monitor_linux.cc b/chromium/media/base/user_input_monitor_linux.cc index 00d818f1f68..4ac78970651 100644 --- a/chromium/media/base/user_input_monitor_linux.cc +++ b/chromium/media/base/user_input_monitor_linux.cc @@ -96,9 +96,9 @@ class UserInputMonitorLinux : public UserInputMonitorBase { UserInputMonitorLinuxCore::UserInputMonitorLinuxCore( const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner) : io_task_runner_(io_task_runner), - x_control_display_(NULL), - x_record_display_(NULL), - x_record_range_(NULL), + x_control_display_(nullptr), + x_record_display_(nullptr), + x_record_range_(nullptr), x_record_context_(0) {} UserInputMonitorLinuxCore::~UserInputMonitorLinuxCore() { @@ -138,8 +138,8 @@ void UserInputMonitorLinuxCore::StartMonitor() { } int xr_opcode, xr_event, xr_error; - if (!XQueryExtension( - x_control_display_, "RECORD", &xr_opcode, &xr_event, &xr_error)) { + if (!XQueryExtension(x_control_display_, "RECORD", &xr_opcode, &xr_event, + &xr_error)) { LOG(ERROR) << "X Record extension not available."; StopMonitor(); return; @@ -154,8 +154,8 @@ void UserInputMonitorLinuxCore::StartMonitor() { return; } - x_record_range_->device_events.first = KeyPress; - x_record_range_->device_events.last = KeyRelease; + x_record_range_->device_events.first = x11::KeyEvent::Press; + x_record_range_->device_events.last = x11::KeyEvent::Release; if (x_record_context_) { XRecordDisableContext(x_control_display_, x_record_context_); @@ -175,8 +175,7 @@ void UserInputMonitorLinuxCore::StartMonitor() { return; } - if (!XRecordEnableContextAsync(x_record_display_, - x_record_context_, + if (!XRecordEnableContextAsync(x_record_display_, x_record_context_, &UserInputMonitorLinuxCore::ProcessReply, reinterpret_cast<XPointer>(this))) { LOG(ERROR) << "XRecordEnableContextAsync failed."; @@ -210,7 +209,7 @@ void UserInputMonitorLinuxCore::StopMonitor() { if (x_record_range_) { XFree(x_record_range_); - x_record_range_ = NULL; + x_record_range_ = nullptr; } // Context must be disabled via the control channel because we can't send @@ -225,11 +224,11 @@ void UserInputMonitorLinuxCore::StopMonitor() { } if (x_record_display_) { XCloseDisplay(x_record_display_); - x_record_display_ = NULL; + x_record_display_ = nullptr; } if (x_control_display_) { XCloseDisplay(x_control_display_); - x_control_display_ = NULL; + x_control_display_ = nullptr; } key_press_count_mapping_.reset(); @@ -249,10 +248,12 @@ void UserInputMonitorLinuxCore::OnXEvent() { void UserInputMonitorLinuxCore::ProcessXEvent(xEvent* event) { DCHECK(io_task_runner_->BelongsToCurrentThread()); - DCHECK(event->u.u.type == KeyRelease || event->u.u.type == KeyPress); + DCHECK(event->u.u.type == x11::KeyEvent::Release || + event->u.u.type == x11::KeyEvent::Press); - ui::EventType type = - (event->u.u.type == KeyPress) ? ui::ET_KEY_PRESSED : ui::ET_KEY_RELEASED; + ui::EventType type = (event->u.u.type == x11::KeyEvent::Press) + ? ui::ET_KEY_PRESSED + : ui::ET_KEY_RELEASED; KeySym key_sym = XkbKeycodeToKeysym(x_control_display_, event->u.u.detail, 0, 0); diff --git a/chromium/media/base/vector_math.cc b/chromium/media/base/vector_math.cc index fabb796d324..a0333cb6885 100644 --- a/chromium/media/base/vector_math.cc +++ b/chromium/media/base/vector_math.cc @@ -8,6 +8,7 @@ #include <algorithm> #include "base/check_op.h" +#include "base/memory/aligned_memory.h" #include "build/build_config.h" // NaCl does not allow intrinsics. @@ -40,9 +41,8 @@ namespace media { namespace vector_math { void FMAC(const float src[], float scale, int len, float dest[]) { - // Ensure |src| and |dest| are 16-byte aligned. - DCHECK_EQ(0u, reinterpret_cast<uintptr_t>(src) & (kRequiredAlignment - 1)); - DCHECK_EQ(0u, reinterpret_cast<uintptr_t>(dest) & (kRequiredAlignment - 1)); + DCHECK(base::IsAligned(src, kRequiredAlignment)); + DCHECK(base::IsAligned(dest, kRequiredAlignment)); return FMAC_FUNC(src, scale, len, dest); } @@ -52,9 +52,8 @@ void FMAC_C(const float src[], float scale, int len, float dest[]) { } void FMUL(const float src[], float scale, int len, float dest[]) { - // Ensure |src| and |dest| are 16-byte aligned. - DCHECK_EQ(0u, reinterpret_cast<uintptr_t>(src) & (kRequiredAlignment - 1)); - DCHECK_EQ(0u, reinterpret_cast<uintptr_t>(dest) & (kRequiredAlignment - 1)); + DCHECK(base::IsAligned(src, kRequiredAlignment)); + DCHECK(base::IsAligned(dest, kRequiredAlignment)); return FMUL_FUNC(src, scale, len, dest); } @@ -65,8 +64,7 @@ void FMUL_C(const float src[], float scale, int len, float dest[]) { std::pair<float, float> EWMAAndMaxPower( float initial_value, const float src[], int len, float smoothing_factor) { - // Ensure |src| is 16-byte aligned. - DCHECK_EQ(0u, reinterpret_cast<uintptr_t>(src) & (kRequiredAlignment - 1)); + DCHECK(base::IsAligned(src, kRequiredAlignment)); return EWMAAndMaxPower_FUNC(initial_value, src, len, smoothing_factor); } diff --git a/chromium/media/base/video_codecs.cc b/chromium/media/base/video_codecs.cc index 4c04f29f6b2..fd84206a453 100644 --- a/chromium/media/base/video_codecs.cc +++ b/chromium/media/base/video_codecs.cc @@ -5,6 +5,7 @@ #include "media/base/video_codecs.h" #include "base/logging.h" +#include "base/notreached.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" #include "base/strings/string_util.h" diff --git a/chromium/media/base/video_decoder.cc b/chromium/media/base/video_decoder.cc index 3a7647313fb..626ca0f0182 100644 --- a/chromium/media/base/video_decoder.cc +++ b/chromium/media/base/video_decoder.cc @@ -15,10 +15,6 @@ namespace media { VideoDecoder::VideoDecoder() = default; -void VideoDecoder::Destroy() { - delete this; -} - VideoDecoder::~VideoDecoder() = default; bool VideoDecoder::IsPlatformDecoder() const { @@ -66,12 +62,3 @@ int VideoDecoder::GetRecommendedThreadCount(int desired_threads) { } } // namespace media - -namespace std { - -void default_delete<media::VideoDecoder>::operator()( - media::VideoDecoder* ptr) const { - ptr->Destroy(); -} - -} // namespace std diff --git a/chromium/media/base/video_decoder.h b/chromium/media/base/video_decoder.h index bbb0b11b151..06488700d0a 100644 --- a/chromium/media/base/video_decoder.h +++ b/chromium/media/base/video_decoder.h @@ -39,6 +39,7 @@ class MEDIA_EXPORT VideoDecoder { using DecodeCB = base::OnceCallback<void(DecodeStatus)>; VideoDecoder(); + virtual ~VideoDecoder(); // Returns the name of the decoder for logging and decoder selection purposes. // This name should be available immediately after construction (e.g. before @@ -134,39 +135,9 @@ class MEDIA_EXPORT VideoDecoder { // [|limits::kMinVideoDecodeThreads|, |limits::kMaxVideoDecodeThreads|]. static int GetRecommendedThreadCount(int desired_threads); - protected: - // Deletion is only allowed via Destroy(). - virtual ~VideoDecoder(); - - private: - friend struct std::default_delete<VideoDecoder>; - - // Fires any pending callbacks, stops and destroys the decoder. After this - // call, external resources (e.g. raw pointers) |this| holds might be - // invalidated immediately. So if the decoder is destroyed asynchronously - // (e.g. DeleteSoon), external resources must be released in this call. - virtual void Destroy(); - DISALLOW_COPY_AND_ASSIGN(VideoDecoder); }; } // namespace media -namespace std { - -// Specialize std::default_delete to call Destroy(). -template <> -struct MEDIA_EXPORT default_delete<media::VideoDecoder> { - constexpr default_delete() = default; - - template <typename U, - typename = typename std::enable_if< - std::is_convertible<U*, media::VideoDecoder*>::value>::type> - default_delete(const default_delete<U>& d) {} - - void operator()(media::VideoDecoder* ptr) const; -}; - -} // namespace std - #endif // MEDIA_BASE_VIDEO_DECODER_H_ diff --git a/chromium/media/base/video_decoder_config.h b/chromium/media/base/video_decoder_config.h index 405be9f8102..052adc4f6d6 100644 --- a/chromium/media/base/video_decoder_config.h +++ b/chromium/media/base/video_decoder_config.h @@ -95,6 +95,8 @@ class MEDIA_EXPORT VideoDecoderConfig { // in this region are valid. const gfx::Size& coded_size() const { return coded_size_; } + void set_coded_size(const gfx::Size& coded_size) { coded_size_ = coded_size; } + // Region of coded_size() that contains image data, also known as the clean // aperture. Usually, but not always, origin-aligned (top-left). const gfx::Rect& visible_rect() const { return visible_rect_; } diff --git a/chromium/media/base/video_frame.cc b/chromium/media/base/video_frame.cc index 0bb025a1d5f..a069012e49d 100644 --- a/chromium/media/base/video_frame.cc +++ b/chromium/media/base/video_frame.cc @@ -338,8 +338,7 @@ scoped_refptr<VideoFrame> VideoFrame::CreateVideoHoleFrame( scoped_refptr<VideoFrame> frame = new VideoFrame(*layout, StorageType::STORAGE_OPAQUE, gfx::Rect(natural_size), natural_size, timestamp); - frame->metadata()->SetUnguessableToken(VideoFrameMetadata::OVERLAY_PLANE_ID, - overlay_plane_id); + frame->metadata()->overlay_plane_id = overlay_plane_id; return frame; } @@ -366,7 +365,7 @@ scoped_refptr<VideoFrame> VideoFrame::WrapNativeTextures( if (format != PIXEL_FORMAT_ARGB && format != PIXEL_FORMAT_XRGB && format != PIXEL_FORMAT_NV12 && format != PIXEL_FORMAT_I420 && format != PIXEL_FORMAT_ABGR && format != PIXEL_FORMAT_XR30 && - format != PIXEL_FORMAT_XB30) { + format != PIXEL_FORMAT_XB30 && format != PIXEL_FORMAT_P016LE) { DLOG(ERROR) << "Unsupported pixel format: " << VideoPixelFormatToString(format); return nullptr; @@ -750,7 +749,7 @@ scoped_refptr<VideoFrame> VideoFrame::CreateEOSFrame() { } scoped_refptr<VideoFrame> frame = new VideoFrame( *layout, STORAGE_UNKNOWN, gfx::Rect(), gfx::Size(), kNoTimestamp); - frame->metadata()->SetBoolean(VideoFrameMetadata::END_OF_STREAM, true); + frame->metadata()->end_of_stream = true; return frame; } @@ -1119,7 +1118,7 @@ gpu::SyncToken VideoFrame::UpdateReleaseSyncToken(SyncTokenClient* client) { } std::string VideoFrame::AsHumanReadableString() const { - if (metadata()->IsTrue(VideoFrameMetadata::END_OF_STREAM)) + if (metadata()->end_of_stream) return "end of stream"; std::ostringstream s; diff --git a/chromium/media/base/video_frame.h b/chromium/media/base/video_frame.h index 271fcdf19fd..51515be694a 100644 --- a/chromium/media/base/video_frame.h +++ b/chromium/media/base/video_frame.h @@ -14,8 +14,8 @@ #include <vector> #include "base/callback.h" +#include "base/check_op.h" #include "base/hash/md5.h" -#include "base/logging.h" #include "base/macros.h" #include "base/memory/aligned_memory.h" #include "base/memory/ref_counted.h" @@ -535,8 +535,16 @@ class MEDIA_EXPORT VideoFrame : public base::RefCountedThreadSafe<VideoFrame> { // // TODO(miu): Move some of the "extra" members of VideoFrame (below) into // here as a later clean-up step. + // + // TODO(https://crbug.com/1096727): change the return type to const&. const VideoFrameMetadata* metadata() const { return &metadata_; } VideoFrameMetadata* metadata() { return &metadata_; } + void set_metadata(const VideoFrameMetadata& metadata) { + metadata_ = metadata; + } + + // Resets |metadata_|. + void clear_metadata() { set_metadata(VideoFrameMetadata()); } // The time span between the current frame and the first frame of the stream. // This is the media timestamp, and not the reference time. diff --git a/chromium/media/base/video_frame_metadata.cc b/chromium/media/base/video_frame_metadata.cc index ad45ea010c9..2c8475df48c 100644 --- a/chromium/media/base/video_frame_metadata.cc +++ b/chromium/media/base/video_frame_metadata.cc @@ -9,194 +9,56 @@ #include <vector> #include "base/check_op.h" -#include "base/no_destructor.h" #include "base/strings/string_number_conversions.h" -#include "base/value_conversions.h" +#include "base/util/values/values_util.h" #include "ui/gfx/geometry/rect.h" namespace media { -namespace { - -std::vector<std::string> CreateInternalKeys() { - std::vector<std::string> result(VideoFrameMetadata::NUM_KEYS); - for (size_t i = 0; i < result.size(); i++) - result[i] = base::NumberToString(i); - return result; -} - -// Map enum key to internal StringPiece key used by base::DictionaryValue. -inline base::StringPiece ToInternalKey(VideoFrameMetadata::Key key) { - DCHECK_LT(key, VideoFrameMetadata::NUM_KEYS); - static const base::NoDestructor<std::vector<std::string>> internal_keys( - CreateInternalKeys()); - return (*internal_keys)[int{key}]; -} - -} // namespace - VideoFrameMetadata::VideoFrameMetadata() = default; VideoFrameMetadata::~VideoFrameMetadata() = default; -bool VideoFrameMetadata::HasKey(Key key) const { - return dictionary_.HasKey(ToInternalKey(key)); -} - -void VideoFrameMetadata::SetBoolean(Key key, bool value) { - dictionary_.SetKey(ToInternalKey(key), base::Value(value)); -} - -void VideoFrameMetadata::SetInteger(Key key, int value) { - dictionary_.SetKey(ToInternalKey(key), base::Value(value)); -} - -void VideoFrameMetadata::SetDouble(Key key, double value) { - dictionary_.SetKey(ToInternalKey(key), base::Value(value)); -} - -void VideoFrameMetadata::SetRotation(Key key, VideoRotation value) { - DCHECK_EQ(ROTATION, key); - dictionary_.SetKey(ToInternalKey(key), base::Value(value)); -} - -void VideoFrameMetadata::SetString(Key key, const std::string& value) { - dictionary_.SetKey( - ToInternalKey(key), - - // Using BlobStorage since we don't want the |value| interpreted as having - // any particular character encoding (e.g., UTF-8) by - // base::DictionaryValue. - base::Value(base::Value::BlobStorage(value.begin(), value.end()))); -} - -void VideoFrameMetadata::SetTimeDelta(Key key, const base::TimeDelta& value) { - dictionary_.SetKey(ToInternalKey(key), base::CreateTimeDeltaValue(value)); -} - -void VideoFrameMetadata::SetTimeTicks(Key key, const base::TimeTicks& value) { - // Serialize TimeTicks as TimeDeltas. - dictionary_.SetKey(ToInternalKey(key), - base::CreateTimeDeltaValue(value - base::TimeTicks())); -} - -void VideoFrameMetadata::SetUnguessableToken( - Key key, - const base::UnguessableToken& value) { - dictionary_.SetKey(ToInternalKey(key), - base::CreateUnguessableTokenValue(value)); -} - -void VideoFrameMetadata::SetRect(Key key, const gfx::Rect& value) { - base::Value init[] = {base::Value(value.x()), base::Value(value.y()), - base::Value(value.width()), - base::Value(value.height())}; - dictionary_.SetKey(ToInternalKey(key), - base::Value(base::Value::ListStorage( - std::make_move_iterator(std::begin(init)), - std::make_move_iterator(std::end(init))))); -} - -bool VideoFrameMetadata::GetBoolean(Key key, bool* value) const { - DCHECK(value); - auto opt_bool = dictionary_.FindBoolKey(ToInternalKey(key)); - if (opt_bool) - *value = opt_bool.value(); +VideoFrameMetadata::VideoFrameMetadata(const VideoFrameMetadata& other) = + default; - return opt_bool.has_value(); -} - -bool VideoFrameMetadata::GetInteger(Key key, int* value) const { - DCHECK(value); - auto opt_int = dictionary_.FindIntKey(ToInternalKey(key)); - if (opt_int) - *value = opt_int.value(); - - return opt_int.has_value(); -} - -bool VideoFrameMetadata::GetDouble(Key key, double* value) const { - DCHECK(value); - auto opt_double = dictionary_.FindDoubleKey(ToInternalKey(key)); - if (opt_double) - *value = opt_double.value(); - - return opt_double.has_value(); -} - -bool VideoFrameMetadata::GetRotation(Key key, VideoRotation* value) const { - DCHECK_EQ(ROTATION, key); - DCHECK(value); - auto opt_int = dictionary_.FindIntKey(ToInternalKey(key)); - if (opt_int) - *value = static_cast<VideoRotation>(opt_int.value()); - return opt_int.has_value(); -} - -bool VideoFrameMetadata::GetString(Key key, std::string* value) const { - DCHECK(value); - const base::Value::BlobStorage* const binary_value = - dictionary_.FindBlobKey(ToInternalKey(key)); - - if (!!binary_value) - value->assign(binary_value->begin(), binary_value->end()); - - return !!binary_value; -} - -bool VideoFrameMetadata::GetTimeDelta(Key key, base::TimeDelta* value) const { - const base::Value* internal_value = dictionary_.FindKey(ToInternalKey(key)); - if (!internal_value) - return false; - return base::GetValueAsTimeDelta(*internal_value, value); -} - -bool VideoFrameMetadata::GetTimeTicks(Key key, base::TimeTicks* value) const { - // Deserialize TimeTicks from TimeDelta. - const base::Value* internal_value = dictionary_.FindKey(ToInternalKey(key)); - base::TimeDelta delta; - - if (!internal_value || !base::GetValueAsTimeDelta(*internal_value, &delta)) - return false; - - *value = base::TimeTicks() + delta; - return true; -} - -bool VideoFrameMetadata::GetUnguessableToken( - Key key, - base::UnguessableToken* value) const { - const base::Value* internal_value = dictionary_.FindKey(ToInternalKey(key)); - if (!internal_value) - return false; - return base::GetValueAsUnguessableToken(*internal_value, value); -} - -bool VideoFrameMetadata::GetRect(Key key, gfx::Rect* value) const { - const base::Value* internal_value = - dictionary_.FindListKey(ToInternalKey(key)); - if (!internal_value || internal_value->GetList().size() != 4) - return false; - *value = gfx::Rect(internal_value->GetList()[0].GetInt(), - internal_value->GetList()[1].GetInt(), - internal_value->GetList()[2].GetInt(), - internal_value->GetList()[3].GetInt()); - return true; -} - -bool VideoFrameMetadata::IsTrue(Key key) const { - bool value = false; - return GetBoolean(key, &value) && value; -} - -void VideoFrameMetadata::MergeInternalValuesFrom(const base::Value& in) { - // This function CHECKs if |in| is a dictionary. - dictionary_.MergeDictionary(&in); -} +#define MERGE_FIELD(a, source) \ + if (source->a) \ + this->a = source->a void VideoFrameMetadata::MergeMetadataFrom( const VideoFrameMetadata* metadata_source) { - dictionary_.MergeDictionary(&metadata_source->dictionary_); + MERGE_FIELD(allow_overlay, metadata_source); + MERGE_FIELD(capture_begin_time, metadata_source); + MERGE_FIELD(capture_end_time, metadata_source); + MERGE_FIELD(capture_counter, metadata_source); + MERGE_FIELD(capture_update_rect, metadata_source); + MERGE_FIELD(copy_required, metadata_source); + MERGE_FIELD(end_of_stream, metadata_source); + MERGE_FIELD(frame_duration, metadata_source); + MERGE_FIELD(frame_rate, metadata_source); + MERGE_FIELD(interactive_content, metadata_source); + MERGE_FIELD(reference_time, metadata_source); + MERGE_FIELD(resource_utilization, metadata_source); + MERGE_FIELD(read_lock_fences_enabled, metadata_source); + MERGE_FIELD(rotation, metadata_source); + MERGE_FIELD(texture_owner, metadata_source); + MERGE_FIELD(wants_promotion_hint, metadata_source); + MERGE_FIELD(protected_video, metadata_source); + MERGE_FIELD(hw_protected, metadata_source); + MERGE_FIELD(overlay_plane_id, metadata_source); + MERGE_FIELD(power_efficient, metadata_source); + MERGE_FIELD(device_scale_factor, metadata_source); + MERGE_FIELD(page_scale_factor, metadata_source); + MERGE_FIELD(root_scroll_offset_x, metadata_source); + MERGE_FIELD(root_scroll_offset_y, metadata_source); + MERGE_FIELD(top_controls_visible_height, metadata_source); + MERGE_FIELD(decode_begin_time, metadata_source); + MERGE_FIELD(decode_end_time, metadata_source); + MERGE_FIELD(processing_time, metadata_source); + MERGE_FIELD(rtp_timestamp, metadata_source); + MERGE_FIELD(receive_time, metadata_source); + MERGE_FIELD(wallclock_frame_duration, metadata_source); } } // namespace media diff --git a/chromium/media/base/video_frame_metadata.h b/chromium/media/base/video_frame_metadata.h index 4e873e4152d..9f16b7fce27 100644 --- a/chromium/media/base/video_frame_metadata.h +++ b/chromium/media/base/video_frame_metadata.h @@ -16,177 +16,43 @@ #include "build/build_config.h" #include "media/base/media_export.h" #include "media/base/video_transformation.h" - -namespace gfx { -class Rect; -} +#include "ui/gfx/geometry/rect.h" namespace media { class MEDIA_EXPORT VideoFrameMetadata { public: enum Key { - // Sources of VideoFrames use this marker to indicate that the associated - // VideoFrame can be overlayed, case in which its contents do not need to be - // further composited but displayed directly. Use Get/SetBoolean() for - // this Key. ALLOW_OVERLAY, - - // Video capture begin/end timestamps. Consumers can use these values for - // dynamic optimizations, logging stats, etc. Use Get/SetTimeTicks() for - // these keys. CAPTURE_BEGIN_TIME, CAPTURE_END_TIME, - - // A counter that is increased by the producer of video frames each time - // it pushes out a new frame. By looking for gaps in this counter, clients - // can determine whether or not any frames have been dropped on the way from - // the producer between two consecutively received frames. Note that the - // counter may start at arbitrary values, so the absolute value of it has no - // meaning. CAPTURE_COUNTER, - - // A base::ListValue containing 4 integers representing x, y, width, height - // of the rectangular region of the frame that has changed since the frame - // with the directly preceding CAPTURE_COUNTER. If that frame was not - // received, typically because it was dropped during transport from the - // producer, clients must assume that the entire frame has changed. - // The rectangle is relative to the full frame data, i.e. [0, 0, - // coded_size().width(), coded_size().height()]. It does not have to be - // fully contained within visible_rect(). CAPTURE_UPDATE_RECT, - - // Indicates that this frame must be copied to a new texture before use, - // rather than being used directly. Specifically this is required for - // WebView because of limitations about sharing surface textures between GL - // contexts. COPY_REQUIRED, - - // Indicates if the current frame is the End of its current Stream. Use - // Get/SetBoolean() for this Key. END_OF_STREAM, - - // The estimated duration of this frame (i.e., the amount of time between - // the media timestamp of this frame and the next). Note that this is not - // the same information provided by FRAME_RATE as the FRAME_DURATION can - // vary unpredictably for every frame. Consumers can use this to optimize - // playback scheduling, make encoding quality decisions, and/or compute - // frame-level resource utilization stats. Use Get/SetTimeDelta() for this - // key. FRAME_DURATION, - - // Represents either the fixed frame rate, or the maximum frame rate to - // expect from a variable-rate source. This value generally remains the - // same for all frames in the same session. Use Get/SetDouble() for this - // key. FRAME_RATE, - - // This is a boolean that signals that the video capture engine detects - // interactive content. One possible optimization that this signal can help - // with is remote content: adjusting end-to-end latency down to help the - // user better coordinate their actions. - // - // Use Get/SetBoolean for this key. INTERACTIVE_CONTENT, - - // This field represents the local time at which either: 1) the frame was - // generated, if it was done so locally; or 2) the targeted play-out time - // of the frame, if it was generated from a remote source. This value is NOT - // a high-resolution timestamp, and so it should not be used as a - // presentation time; but, instead, it should be used for buffering playback - // and for A/V synchronization purposes. - // Use Get/SetTimeTicks() for this key. REFERENCE_TIME, - - // A feedback signal that indicates the fraction of the tolerable maximum - // amount of resources that were utilized to process this frame. A producer - // can check this value after-the-fact, usually via a VideoFrame destruction - // observer, to determine whether the consumer can handle more or less data - // volume, and achieve the right quality versus performance trade-off. - // - // Use Get/SetDouble() for this key. Values are interpreted as follows: - // Less than 0.0 is meaningless and should be ignored. 1.0 indicates a - // maximum sustainable utilization. Greater than 1.0 indicates the consumer - // is likely to stall or drop frames if the data volume is not reduced. - // - // Example: In a system that encodes and transmits video frames over the - // network, this value can be used to indicate whether sufficient CPU - // is available for encoding and/or sufficient bandwidth is available for - // transmission over the network. The maximum of the two utilization - // measurements would be used as feedback. RESOURCE_UTILIZATION, - - // Sources of VideoFrames use this marker to indicate that an instance of - // VideoFrameExternalResources produced from the associated video frame - // should use read lock fences. READ_LOCK_FENCES_ENABLED, - - // Indicates that the frame is rotated. ROTATION, - - // Android only: if set, then this frame is not suitable for overlay, even - // if ALLOW_OVERLAY is set. However, it allows us to process the overlay - // to see if it would have been promoted, if it were backed by a SurfaceView - // instead. This lets us figure out when SurfaceViews are appropriate. TEXTURE_OWNER, - - // Android only: if set, then this frame's resource would like to be - // notified about its promotability to an overlay. WANTS_PROMOTION_HINT, - - // This video frame comes from protected content. PROTECTED_VIDEO, - - // This video frame is protected by hardware. This option is valid only if - // PROTECTED_VIDEO is also set to true. HW_PROTECTED, - - // An UnguessableToken that identifies VideoOverlayFactory that created - // this VideoFrame. It's used by Cast to help with video hole punch. - // Use Get/SetUnguessableToken() for this key. OVERLAY_PLANE_ID, - - // Whether this frame was decoded in a power efficient way. POWER_EFFICIENT, - - // CompositorFrameMetadata variables associated with this frame. Used for - // remote debugging. - // Use Get/SetDouble() for these keys. - // TODO(crbug.com/832220): Use a customized dictionary value instead of - // using these keys directly. DEVICE_SCALE_FACTOR, PAGE_SCALE_FACTOR, ROOT_SCROLL_OFFSET_X, ROOT_SCROLL_OFFSET_Y, TOP_CONTROLS_VISIBLE_HEIGHT, - - // If present, this field represents the local time at which the VideoFrame - // was decoded from whichever format it was encoded in. Sometimes only - // DECODE_END_TIME will be present. Use Get/SetTimeTicks() for this key. DECODE_BEGIN_TIME, DECODE_END_TIME, - - // If present, this field represents the elapsed time from the submission of - // the encoded packet with the same PTS as this frame to the decoder until - // the decoded frame was ready for presentation. Stored as base::TimeDelta. PROCESSING_TIME, - - // The RTP timestamp associated with this video frame. Stored as a double - // since base::DictionaryValue doesn't have a uint32_t type. - // - // https://w3c.github.io/webrtc-pc/#dom-rtcrtpcontributingsource RTP_TIMESTAMP, - - // For video frames coming from a remote source, this is the time the - // encoded frame was received by the platform, i.e., the time at - // which the last packet belonging to this frame was received over the - // network. RECEIVE_TIME, - - // If present, this field represents the duration this frame is ideally - // expected to spend on the screen during playback. Unlike FRAME_DURATION - // this field takes into account current playback rate. - // Use Get/SetTimeDelta() for this key. WALLCLOCK_FRAME_DURATION, NUM_KEYS @@ -195,47 +61,161 @@ class MEDIA_EXPORT VideoFrameMetadata { VideoFrameMetadata(); ~VideoFrameMetadata(); - bool HasKey(Key key) const; - - void Clear() { dictionary_.Clear(); } - - // Setters. Overwrites existing value, if present. - void SetBoolean(Key key, bool value); - void SetInteger(Key key, int value); - void SetDouble(Key key, double value); - void SetRotation(Key key, VideoRotation value); - void SetString(Key key, const std::string& value); - void SetTimeDelta(Key key, const base::TimeDelta& value); - void SetTimeTicks(Key key, const base::TimeTicks& value); - void SetUnguessableToken(Key key, const base::UnguessableToken& value); - void SetRect(Key key, const gfx::Rect& value); - - // Getters. Returns true if |key| is present, and its value has been set. - bool GetBoolean(Key key, bool* value) const WARN_UNUSED_RESULT; - bool GetInteger(Key key, int* value) const WARN_UNUSED_RESULT; - bool GetDouble(Key key, double* value) const WARN_UNUSED_RESULT; - bool GetRotation(Key key, VideoRotation* value) const WARN_UNUSED_RESULT; - bool GetString(Key key, std::string* value) const WARN_UNUSED_RESULT; - bool GetTimeDelta(Key key, base::TimeDelta* value) const WARN_UNUSED_RESULT; - bool GetTimeTicks(Key key, base::TimeTicks* value) const WARN_UNUSED_RESULT; - bool GetUnguessableToken(Key key, base::UnguessableToken* value) const - WARN_UNUSED_RESULT; - bool GetRect(Key key, gfx::Rect* value) const WARN_UNUSED_RESULT; - - // Convenience method that returns true if |key| exists and is set to true. - bool IsTrue(Key key) const WARN_UNUSED_RESULT; - - // For serialization. - void MergeInternalValuesFrom(const base::Value& in); - const base::Value& GetInternalValues() const { return dictionary_; } + VideoFrameMetadata(const VideoFrameMetadata& other); // Merges internal values from |metadata_source|. void MergeMetadataFrom(const VideoFrameMetadata* metadata_source); - private: - base::DictionaryValue dictionary_; - - DISALLOW_COPY_AND_ASSIGN(VideoFrameMetadata); + // Sources of VideoFrames use this marker to indicate that the associated + // VideoFrame can be overlaid, case in which its contents do not need to be + // further composited but displayed directly. + bool allow_overlay = false; + + // Video capture begin/end timestamps. Consumers can use these values for + // dynamic optimizations, logging stats, etc. + base::Optional<base::TimeTicks> capture_begin_time; + base::Optional<base::TimeTicks> capture_end_time; + + // A counter that is increased by the producer of video frames each time + // it pushes out a new frame. By looking for gaps in this counter, clients + // can determine whether or not any frames have been dropped on the way from + // the producer between two consecutively received frames. Note that the + // counter may start at arbitrary values, so the absolute value of it has no + // meaning. + base::Optional<int> capture_counter; + + // The rectangular region of the frame that has changed since the frame + // with the directly preceding CAPTURE_COUNTER. If that frame was not + // received, typically because it was dropped during transport from the + // producer, clients must assume that the entire frame has changed. + // The rectangle is relative to the full frame data, i.e. [0, 0, + // coded_size().width(), coded_size().height()]. It does not have to be + // fully contained within visible_rect(). + base::Optional<gfx::Rect> capture_update_rect; + + // Indicates that this frame must be copied to a new texture before use, + // rather than being used directly. Specifically this is required for + // WebView because of limitations about sharing surface textures between GL + // contexts. + bool copy_required = false; + + // Indicates if the current frame is the End of its current Stream. + bool end_of_stream = false; + + // The estimated duration of this frame (i.e., the amount of time between + // the media timestamp of this frame and the next). Note that this is not + // the same information provided by FRAME_RATE as the FRAME_DURATION can + // vary unpredictably for every frame. Consumers can use this to optimize + // playback scheduling, make encoding quality decisions, and/or compute + // frame-level resource utilization stats. + base::Optional<base::TimeDelta> frame_duration; + + // Represents either the fixed frame rate, or the maximum frame rate to + // expect from a variable-rate source. This value generally remains the + // same for all frames in the same session. + base::Optional<double> frame_rate; + + // This is a boolean that signals that the video capture engine detects + // interactive content. One possible optimization that this signal can help + // with is remote content: adjusting end-to-end latency down to help the + // user better coordinate their actions. + bool interactive_content = false; + + // This field represents the local time at which either: 1) the frame was + // generated, if it was done so locally; or 2) the targeted play-out time + // of the frame, if it was generated from a remote source. This value is NOT + // a high-resolution timestamp, and so it should not be used as a + // presentation time; but, instead, it should be used for buffering playback + // and for A/V synchronization purposes. + base::Optional<base::TimeTicks> reference_time; + + // A feedback signal that indicates the fraction of the tolerable maximum + // amount of resources that were utilized to process this frame. A producer + // can check this value after-the-fact, usually via a VideoFrame destruction + // observer, to determine whether the consumer can handle more or less data + // volume, and achieve the right quality versus performance trade-off. + // + // Values are interpreted as follows: + // Less than 0.0 is meaningless and should be ignored. 1.0 indicates a + // maximum sustainable utilization. Greater than 1.0 indicates the consumer + // is likely to stall or drop frames if the data volume is not reduced. + // + // Example: In a system that encodes and transmits video frames over the + // network, this value can be used to indicate whether sufficient CPU + // is available for encoding and/or sufficient bandwidth is available for + // transmission over the network. The maximum of the two utilization + // measurements would be used as feedback. + base::Optional<double> resource_utilization; + + // Sources of VideoFrames use this marker to indicate that an instance of + // VideoFrameExternalResources produced from the associated video frame + // should use read lock fences. + bool read_lock_fences_enabled = false; + + // Indicates that the frame is rotated. + base::Optional<VideoRotation> rotation; + + // Android only: if set, then this frame is not suitable for overlay, even + // if ALLOW_OVERLAY is set. However, it allows us to process the overlay + // to see if it would have been promoted, if it were backed by a SurfaceView + // instead. This lets us figure out when SurfaceViews are appropriate. + bool texture_owner = false; + + // Android only: if set, then this frame's resource would like to be + // notified about its promotability to an overlay. + bool wants_promotion_hint = false; + + // This video frame comes from protected content. + bool protected_video = false; + + // This video frame is protected by hardware. This option is valid only if + // PROTECTED_VIDEO is also set to true. + bool hw_protected = false; + + // An UnguessableToken that identifies VideoOverlayFactory that created + // this VideoFrame. It's used by Cast to help with video hole punch. + base::Optional<base::UnguessableToken> overlay_plane_id; + + // Whether this frame was decoded in a power efficient way. + bool power_efficient = false; + + // CompositorFrameMetadata variables associated with this frame. Used for + // remote debugging. + // TODO(crbug.com/832220): Use a customized dictionary value instead of + // using these keys directly. + base::Optional<double> device_scale_factor; + base::Optional<double> page_scale_factor; + base::Optional<double> root_scroll_offset_x; + base::Optional<double> root_scroll_offset_y; + base::Optional<double> top_controls_visible_height; + + // If present, this field represents the local time at which the VideoFrame + // was decoded from whichever format it was encoded in. Sometimes only + // DECODE_END_TIME will be present. + base::Optional<base::TimeTicks> decode_begin_time; + base::Optional<base::TimeTicks> decode_end_time; + + // If present, this field represents the elapsed time from the submission of + // the encoded packet with the same PTS as this frame to the decoder until + // the decoded frame was ready for presentation. + base::Optional<base::TimeDelta> processing_time; + + // The RTP timestamp associated with this video frame. Stored as a double + // since base::DictionaryValue doesn't have a uint32_t type. + // + // https://w3c.github.io/webrtc-pc/#dom-rtcrtpcontributingsource + base::Optional<double> rtp_timestamp; + + // For video frames coming from a remote source, this is the time the + // encoded frame was received by the platform, i.e., the time at + // which the last packet belonging to this frame was received over the + // network. + base::Optional<base::TimeTicks> receive_time; + + // If present, this field represents the duration this frame is ideally + // expected to spend on the screen during playback. Unlike FRAME_DURATION + // this field takes into account current playback rate. + base::Optional<base::TimeDelta> wallclock_frame_duration; }; } // namespace media diff --git a/chromium/media/base/video_frame_pool.cc b/chromium/media/base/video_frame_pool.cc index 1d029f054b6..4541324af7b 100644 --- a/chromium/media/base/video_frame_pool.cc +++ b/chromium/media/base/video_frame_pool.cc @@ -6,6 +6,7 @@ #include "base/bind.h" #include "base/containers/circular_deque.h" +#include "base/logging.h" #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/synchronization/lock.h" @@ -93,7 +94,7 @@ scoped_refptr<VideoFrame> VideoFramePool::PoolImpl::CreateFrame( natural_size)) { frame = pool_frame; frame->set_timestamp(timestamp); - frame->metadata()->Clear(); + frame->clear_metadata(); break; } } diff --git a/chromium/media/base/video_frame_unittest.cc b/chromium/media/base/video_frame_unittest.cc index 17a1b972c64..7f9b105990b 100644 --- a/chromium/media/base/video_frame_unittest.cc +++ b/chromium/media/base/video_frame_unittest.cc @@ -47,6 +47,99 @@ void CreateTestY16Frame(const gfx::Size& coded_size, } } } + +// Returns a VideoFrameMetadata object with a value for each field. +media::VideoFrameMetadata GetFullVideoFrameMetadata() { + // Assign a non-default, distinct (when possible), value to all fields, and + // make sure values are preserved across serialization. + media::VideoFrameMetadata metadata; + + // ints + metadata.capture_counter = 123; + + // gfx::Rects + metadata.capture_update_rect = gfx::Rect(12, 34, 360, 480); + + // media::VideoRotations + metadata.rotation = media::VideoRotation::VIDEO_ROTATION_90; + + // bools + metadata.allow_overlay = true; + metadata.copy_required = true; + metadata.end_of_stream = true; + metadata.texture_owner = true; + metadata.wants_promotion_hint = true; + metadata.protected_video = true; + metadata.hw_protected = true; + metadata.power_efficient = true; + metadata.read_lock_fences_enabled = true; + metadata.interactive_content = true; + + // base::UnguessableTokens + metadata.overlay_plane_id = base::UnguessableToken::Create(); + + // doubles + metadata.device_scale_factor = 2.0; + metadata.page_scale_factor = 2.1; + metadata.root_scroll_offset_x = 100.2; + metadata.root_scroll_offset_y = 200.1; + metadata.top_controls_visible_height = 25.5; + metadata.resource_utilization = 95.8; + metadata.frame_rate = 29.94; + metadata.rtp_timestamp = 1.0; + + // base::TimeTicks + base::TimeTicks now = base::TimeTicks::Now(); + metadata.receive_time = now + base::TimeDelta::FromMilliseconds(10); + metadata.capture_begin_time = now + base::TimeDelta::FromMilliseconds(20); + metadata.capture_end_time = now + base::TimeDelta::FromMilliseconds(30); + metadata.decode_begin_time = now + base::TimeDelta::FromMilliseconds(40); + metadata.decode_end_time = now + base::TimeDelta::FromMilliseconds(50); + metadata.reference_time = now + base::TimeDelta::FromMilliseconds(60); + + // base::TimeDeltas + metadata.processing_time = base::TimeDelta::FromMilliseconds(500); + metadata.frame_duration = base::TimeDelta::FromMilliseconds(16); + metadata.wallclock_frame_duration = base::TimeDelta::FromMilliseconds(17); + + return metadata; +} + +void VerifyVideoFrameMetadataEquality(const media::VideoFrameMetadata& a, + const media::VideoFrameMetadata& b) { + EXPECT_EQ(a.allow_overlay, b.allow_overlay); + EXPECT_EQ(a.capture_begin_time, b.capture_begin_time); + EXPECT_EQ(a.capture_end_time, b.capture_end_time); + EXPECT_EQ(a.capture_counter, b.capture_counter); + EXPECT_EQ(a.capture_update_rect, b.capture_update_rect); + EXPECT_EQ(a.copy_required, b.copy_required); + EXPECT_EQ(a.end_of_stream, b.end_of_stream); + EXPECT_EQ(a.frame_duration, b.frame_duration); + EXPECT_EQ(a.frame_rate, b.frame_rate); + EXPECT_EQ(a.interactive_content, b.interactive_content); + EXPECT_EQ(a.reference_time, b.reference_time); + EXPECT_EQ(a.resource_utilization, b.resource_utilization); + EXPECT_EQ(a.read_lock_fences_enabled, b.read_lock_fences_enabled); + EXPECT_EQ(a.rotation, b.rotation); + EXPECT_EQ(a.texture_owner, b.texture_owner); + EXPECT_EQ(a.wants_promotion_hint, b.wants_promotion_hint); + EXPECT_EQ(a.protected_video, b.protected_video); + EXPECT_EQ(a.hw_protected, b.hw_protected); + EXPECT_EQ(a.overlay_plane_id, b.overlay_plane_id); + EXPECT_EQ(a.power_efficient, b.power_efficient); + EXPECT_EQ(a.device_scale_factor, b.device_scale_factor); + EXPECT_EQ(a.page_scale_factor, b.page_scale_factor); + EXPECT_EQ(a.root_scroll_offset_x, b.root_scroll_offset_x); + EXPECT_EQ(a.root_scroll_offset_y, b.root_scroll_offset_y); + EXPECT_EQ(a.top_controls_visible_height, b.top_controls_visible_height); + EXPECT_EQ(a.decode_begin_time, b.decode_begin_time); + EXPECT_EQ(a.decode_end_time, b.decode_end_time); + EXPECT_EQ(a.processing_time, b.processing_time); + EXPECT_EQ(a.rtp_timestamp, b.rtp_timestamp); + EXPECT_EQ(a.receive_time, b.receive_time); + EXPECT_EQ(a.wallclock_frame_duration, b.wallclock_frame_duration); +} + } // namespace namespace media { @@ -198,8 +291,7 @@ TEST(VideoFrame, CreateFrame) { // Test an empty frame. frame = VideoFrame::CreateEOSFrame(); - EXPECT_TRUE( - frame->metadata()->IsTrue(VideoFrameMetadata::END_OF_STREAM)); + EXPECT_TRUE(frame->metadata()->end_of_stream); } TEST(VideoFrame, CreateZeroInitializedFrame) { @@ -235,8 +327,7 @@ TEST(VideoFrame, CreateBlackFrame) { // Test basic properties. EXPECT_EQ(0, frame->timestamp().InMicroseconds()); - EXPECT_FALSE( - frame->metadata()->IsTrue(VideoFrameMetadata::END_OF_STREAM)); + EXPECT_FALSE(frame->metadata()->end_of_stream); // Test |frame| properties. EXPECT_EQ(PIXEL_FORMAT_I420, frame->format()); @@ -278,8 +369,7 @@ TEST(VideoFrame, WrapVideoFrame) { gfx::Rect visible_rect(1, 1, 1, 1); gfx::Size natural_size = visible_rect.size(); - wrapped_frame->metadata()->SetTimeDelta( - media::VideoFrameMetadata::FRAME_DURATION, kFrameDuration); + wrapped_frame->metadata()->frame_duration = kFrameDuration; frame = media::VideoFrame::WrapVideoFrame( wrapped_frame, wrapped_frame->format(), visible_rect, natural_size); wrapped_frame->AddDestructionObserver( @@ -293,18 +383,12 @@ TEST(VideoFrame, WrapVideoFrame) { EXPECT_EQ(natural_size, frame->natural_size()); // Verify metadata was copied to the wrapped frame. - base::TimeDelta frame_duration; - ASSERT_TRUE(frame->metadata()->GetTimeDelta( - media::VideoFrameMetadata::FRAME_DURATION, &frame_duration)); - - EXPECT_EQ(frame_duration, kFrameDuration); + EXPECT_EQ(*frame->metadata()->frame_duration, kFrameDuration); // Verify the metadata copy was a deep copy. - wrapped_frame->metadata()->Clear(); - EXPECT_NE( - wrapped_frame->metadata()->HasKey( - media::VideoFrameMetadata::FRAME_DURATION), - frame->metadata()->HasKey(media::VideoFrameMetadata::FRAME_DURATION)); + wrapped_frame->clear_metadata(); + EXPECT_NE(wrapped_frame->metadata()->frame_duration.has_value(), + frame->metadata()->frame_duration.has_value()); } // Verify that |wrapped_frame| outlives |frame|. @@ -643,111 +727,44 @@ TEST(VideoFrame, AllocationSize_OddSize) { } } -TEST(VideoFrameMetadata, SetAndThenGetAllKeysForAllTypes) { - VideoFrameMetadata metadata; - - for (int i = 0; i < VideoFrameMetadata::NUM_KEYS; ++i) { - const VideoFrameMetadata::Key key = static_cast<VideoFrameMetadata::Key>(i); - - EXPECT_FALSE(metadata.HasKey(key)); - metadata.SetBoolean(key, true); - EXPECT_TRUE(metadata.HasKey(key)); - bool bool_value = false; - EXPECT_TRUE(metadata.GetBoolean(key, &bool_value)); - EXPECT_EQ(true, bool_value); - metadata.Clear(); - - EXPECT_FALSE(metadata.HasKey(key)); - metadata.SetInteger(key, i); - EXPECT_TRUE(metadata.HasKey(key)); - int int_value = -999; - EXPECT_TRUE(metadata.GetInteger(key, &int_value)); - EXPECT_EQ(i, int_value); - metadata.Clear(); - - EXPECT_FALSE(metadata.HasKey(key)); - metadata.SetDouble(key, 3.14 * i); - EXPECT_TRUE(metadata.HasKey(key)); - double double_value = -999.99; - EXPECT_TRUE(metadata.GetDouble(key, &double_value)); - EXPECT_EQ(3.14 * i, double_value); - metadata.Clear(); - - EXPECT_FALSE(metadata.HasKey(key)); - metadata.SetString(key, base::StringPrintf("\xfe%d\xff", i)); - EXPECT_TRUE(metadata.HasKey(key)); - std::string string_value; - EXPECT_TRUE(metadata.GetString(key, &string_value)); - EXPECT_EQ(base::StringPrintf("\xfe%d\xff", i), string_value); - metadata.Clear(); - - EXPECT_FALSE(metadata.HasKey(key)); - base::TimeDelta reference_delta = base::TimeDelta::FromMilliseconds(42 + i); - metadata.SetTimeDelta(key, reference_delta); - EXPECT_TRUE(metadata.HasKey(key)); - base::TimeDelta delta_value; - EXPECT_TRUE(metadata.GetTimeDelta(key, &delta_value)); - EXPECT_EQ(reference_delta, delta_value); - metadata.Clear(); - - EXPECT_FALSE(metadata.HasKey(key)); - base::TimeTicks reference_ticks = - base::TimeTicks() + base::TimeDelta::FromMilliseconds(1234 + i); - metadata.SetTimeTicks(key, reference_ticks); - EXPECT_TRUE(metadata.HasKey(key)); - base::TimeTicks ticks_value; - EXPECT_TRUE(metadata.GetTimeTicks(key, &ticks_value)); - EXPECT_EQ(reference_ticks, ticks_value); - metadata.Clear(); - - EXPECT_FALSE(metadata.HasKey(key)); - gfx::Rect reference_rect = gfx::Rect(3, 5, 240, 360); - metadata.SetRect(key, reference_rect); - EXPECT_TRUE(metadata.HasKey(key)); - gfx::Rect rect_value; - EXPECT_TRUE(metadata.GetRect(key, &rect_value)); - EXPECT_EQ(reference_rect, rect_value); - metadata.Clear(); - } +TEST(VideoFrameMetadata, MergeMetadata) { + VideoFrameMetadata reference_metadata = GetFullVideoFrameMetadata(); + VideoFrameMetadata full_metadata = reference_metadata; + VideoFrameMetadata empty_metadata; - // The Get/SetRotation methods only accept ROTATION as a key. - auto rot_key = VideoFrameMetadata::Key::ROTATION; - EXPECT_FALSE(metadata.HasKey(rot_key)); - VideoRotation reference_rot = VideoRotation::VIDEO_ROTATION_270; - metadata.SetRotation(rot_key, reference_rot); - EXPECT_TRUE(metadata.HasKey(rot_key)); - VideoRotation rot_value; - EXPECT_TRUE(metadata.GetRotation(rot_key, &rot_value)); - EXPECT_EQ(reference_rot, rot_value); - metadata.Clear(); -} + // Merging empty metadata into full metadata should be a no-op. + full_metadata.MergeMetadataFrom(&empty_metadata); + VerifyVideoFrameMetadataEquality(full_metadata, reference_metadata); -TEST(VideoFrameMetadata, PassMetadataViaIntermediary) { - VideoFrameMetadata expected; - for (int i = 0; i < VideoFrameMetadata::NUM_KEYS; ++i) { - const VideoFrameMetadata::Key key = static_cast<VideoFrameMetadata::Key>(i); - expected.SetInteger(key, i); - } - - VideoFrameMetadata result; - result.MergeMetadataFrom(&expected); - - for (int i = 0; i < VideoFrameMetadata::NUM_KEYS; ++i) { - const VideoFrameMetadata::Key key = static_cast<VideoFrameMetadata::Key>(i); - int value = -1; - EXPECT_TRUE(result.GetInteger(key, &value)); - EXPECT_EQ(i, value); - } - - result.Clear(); - result.MergeInternalValuesFrom(expected.GetInternalValues()); + // Merging full metadata into empty metadata should fill it up. + empty_metadata.MergeMetadataFrom(&full_metadata); + VerifyVideoFrameMetadataEquality(empty_metadata, reference_metadata); +} - for (int i = 0; i < VideoFrameMetadata::NUM_KEYS; ++i) { - const VideoFrameMetadata::Key key = static_cast<VideoFrameMetadata::Key>(i); - int value = -1; - EXPECT_TRUE(result.GetInteger(key, &value)); - EXPECT_EQ(i, value); - } +TEST(VideoFrameMetadata, PartialMergeMetadata) { + VideoFrameMetadata full_metadata = GetFullVideoFrameMetadata(); + + const gfx::Rect kTempRect{100, 200, 300, 400}; + const base::TimeTicks kTempTicks = + base::TimeTicks::Now() + base::TimeDelta::FromSeconds(2); + const base::TimeDelta kTempDelta = base::TimeDelta::FromMilliseconds(31415); + const double kTempDouble = 123.45; + + VideoFrameMetadata partial_metadata; + partial_metadata.capture_update_rect = kTempRect; + partial_metadata.reference_time = kTempTicks; + partial_metadata.processing_time = kTempDelta; + partial_metadata.resource_utilization = kTempDouble; + partial_metadata.allow_overlay = false; + + // Merging partial metadata into full metadata partially override it. + full_metadata.MergeMetadataFrom(&partial_metadata); + + EXPECT_EQ(partial_metadata.capture_update_rect, kTempRect); + EXPECT_EQ(partial_metadata.reference_time, kTempTicks); + EXPECT_EQ(partial_metadata.processing_time, kTempDelta); + EXPECT_EQ(partial_metadata.resource_utilization, kTempDouble); + EXPECT_EQ(partial_metadata.allow_overlay, false); } } // namespace media diff --git a/chromium/media/base/video_renderer_sink.h b/chromium/media/base/video_renderer_sink.h index 2598d0c3b0a..62442035a12 100644 --- a/chromium/media/base/video_renderer_sink.h +++ b/chromium/media/base/video_renderer_sink.h @@ -5,7 +5,6 @@ #ifndef MEDIA_BASE_VIDEO_RENDERER_SINK_H_ #define MEDIA_BASE_VIDEO_RENDERER_SINK_H_ -#include "base/logging.h" #include "base/memory/ref_counted.h" #include "base/time/time.h" #include "media/base/media_export.h" diff --git a/chromium/media/base/win/BUILD.gn b/chromium/media/base/win/BUILD.gn index b59888ffc6c..d30fdc1ef4c 100644 --- a/chromium/media/base/win/BUILD.gn +++ b/chromium/media/base/win/BUILD.gn @@ -57,6 +57,11 @@ source_set("hresult_status_helper") { deps = [ "//media" ] } +source_set("mf_cdm_proxy") { + sources = [ "mf_cdm_proxy.h" ] + deps = [ "//base" ] +} + source_set("d3d11_test_support") { testonly = true sources = [ diff --git a/chromium/media/base/win/mf_cdm_proxy.h b/chromium/media/base/win/mf_cdm_proxy.h new file mode 100644 index 00000000000..536cfa4cf58 --- /dev/null +++ b/chromium/media/base/win/mf_cdm_proxy.h @@ -0,0 +1,67 @@ +// 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. + +#ifndef MEDIA_BASE_WIN_MF_CDM_PROXY_H_ +#define MEDIA_BASE_WIN_MF_CDM_PROXY_H_ + +#include <stdint.h> +#include <unknwn.h> + +// Interface for clients to get information from MediaFoundationCdm to +// implements COM interfaces. +// COM interface is used because we are working with Media Foundation which uses +// COM extensively for object lifetime management. +MIDL_INTERFACE("565ab5c2-9923-44e0-997a-f93ccba5dcbf") +IMFCdmProxy : public IUnknown { + public: + // Used by MediaFoundationProtectionManager to get + // ABI::Windows::Media::Protection::IMediaProtectionPMPServer to implement + // ABI::Windows::Media::Protection::IMediaProtectionManager::get_Properties as + // in + // https://docs.microsoft.com/en-us/uwp/api/windows.media.protection.mediaprotectionmanager + virtual HRESULT STDMETHODCALLTYPE GetPMPServer( + /* [in] */ __RPC__in REFIID riid, + /* [iid_is][out] */ __RPC__deref_out_opt LPVOID * object_result) = 0; + + // Used by MediaFoundationSourceWrapper to implement + // IMFTrustedInput::GetInputTrustAuthority as in + // https://docs.microsoft.com/en-us/windows/win32/api/mfidl/nn-mfidl-imftrustedinput + // + // |content_init_data| is optional initialization data as in + // https://www.w3.org/TR/encrypted-media/#initialization-data + virtual HRESULT STDMETHODCALLTYPE GetInputTrustAuthority( + _In_ uint64_t playback_element_id, _In_ uint32_t stream_id, + _In_ uint32_t stream_count, + _In_reads_bytes_opt_(content_init_data_size) + const uint8_t* content_init_data, + _In_ uint32_t content_init_data_size, _In_ REFIID riid, + _COM_Outptr_ IUnknown** object_out) = 0; + + // MediaFoundationSourceWrapper provides its last set of key ids + // associated with a playback element id using SetLastKeyIds when it is + // destructed. + // Another instance of MediaFoundationSourceWrapper could then invoke + // RefreshTrustedInput to let implementation to reuse those key ids + // information when it happens to have the same playback element id. + // + // |playback_element_id| is an ID corresponding to a particular instance of + // video playback element. + virtual HRESULT STDMETHODCALLTYPE RefreshTrustedInput( + _In_ uint64_t playback_element_id) = 0; + + virtual HRESULT STDMETHODCALLTYPE SetLastKeyIds( + _In_ uint64_t playback_element_id, GUID * key_ids, + uint32_t key_ids_count) = 0; + + // Used by MediaFoundationProtectionManager to implement + // IMFContentProtectionManager::BeginEnableContent as in + // https://msdn.microsoft.com/en-us/windows/ms694217(v=vs.71) + // + // |result| is used to obtain the result of an asynchronous operation as in + // https://docs.microsoft.com/en-us/windows/win32/api/mfobjects/nn-mfobjects-imfasyncresult + virtual HRESULT STDMETHODCALLTYPE ProcessContentEnabler( + _In_ IUnknown * request, _In_ IMFAsyncResult * result) = 0; +}; + +#endif // MEDIA_BASE_WIN_MF_CDM_PROXY_H_ diff --git a/chromium/media/base/win/mf_helpers.cc b/chromium/media/base/win/mf_helpers.cc index fce7ada08e4..29837bb407b 100644 --- a/chromium/media/base/win/mf_helpers.cc +++ b/chromium/media/base/win/mf_helpers.cc @@ -4,6 +4,8 @@ #include "media/base/win/mf_helpers.h" +#include "base/check_op.h" + namespace media { Microsoft::WRL::ComPtr<IMFSample> CreateEmptySampleWithBuffer( diff --git a/chromium/media/base/win/mf_initializer.h b/chromium/media/base/win/mf_initializer.h index 2f8431b65bc..714cf3c4501 100644 --- a/chromium/media/base/win/mf_initializer.h +++ b/chromium/media/base/win/mf_initializer.h @@ -9,7 +9,7 @@ #include <memory> -#include "base/logging.h" +#include "base/compiler_specific.h" #include "media/base/win/mf_initializer_export.h" namespace media { |