diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2022-05-17 17:24:03 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2022-06-22 07:51:41 +0000 |
commit | 774f54339e5db91f785733232d3950366db65d07 (patch) | |
tree | 068e1b47bd1af94d77094ed12b604a6b83d9c22a /chromium/media/base | |
parent | f7eaed5286974984ba5f9e3189d8f49d03e99f81 (diff) | |
download | qtwebengine-chromium-774f54339e5db91f785733232d3950366db65d07.tar.gz |
BASELINE: Update Chromium to 102.0.5005.57
Change-Id: I885f714bb40ee724c28f94ca6bd8dbdb39915158
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/media/base')
106 files changed, 1324 insertions, 539 deletions
diff --git a/chromium/media/base/BUILD.gn b/chromium/media/base/BUILD.gn index 4ebdb112b14..619c3bf1995 100644 --- a/chromium/media/base/BUILD.gn +++ b/chromium/media/base/BUILD.gn @@ -73,6 +73,7 @@ source_set("base") { "audio_power_monitor.h", "audio_processing.cc", "audio_processing.h", + "audio_processor_controls.h", "audio_pull_fifo.cc", "audio_pull_fifo.h", "audio_push_fifo.cc", @@ -573,6 +574,7 @@ source_set("unit_tests") { "audio_shifter_unittest.cc", "audio_timestamp_helper_unittest.cc", "bit_reader_unittest.cc", + "bitrate_unittest.cc", "callback_holder_unittest.cc", "callback_registry_unittest.cc", "channel_mixer_unittest.cc", @@ -627,6 +629,7 @@ source_set("unit_tests") { "video_frame_pool_unittest.cc", "video_frame_unittest.cc", "video_thumbnail_decoder_unittest.cc", + "video_transformation_unittest.cc", "video_types_unittest.cc", "video_util_unittest.cc", "wall_clock_time_source_unittest.cc", diff --git a/chromium/media/base/android/media_codec_bridge_impl.cc b/chromium/media/base/android/media_codec_bridge_impl.cc index be63bd3653f..aac199d9b32 100644 --- a/chromium/media/base/android/media_codec_bridge_impl.cc +++ b/chromium/media/base/android/media_codec_bridge_impl.cc @@ -183,8 +183,9 @@ std::unique_ptr<MediaCodecBridge> MediaCodecBridgeImpl::CreateAudioDecoder( DVLOG(2) << __func__ << ": " << config.AsHumanReadableString() << " media_crypto:" << media_crypto.obj(); - const std::string mime = - MediaCodecUtil::CodecToAndroidMimeType(config.codec()); + const std::string mime = MediaCodecUtil::CodecToAndroidMimeType( + config.codec(), config.target_output_sample_format()); + if (mime.empty()) return nullptr; @@ -280,12 +281,6 @@ std::unique_ptr<MediaCodecBridge> MediaCodecBridgeImpl::CreateVideoEncoder( // static void MediaCodecBridgeImpl::SetupCallbackHandlerForTesting() { - // Callback APIs are only available on M+, so do nothing if below that. - if (base::android::BuildInfo::GetInstance()->sdk_int() < - base::android::SDK_VERSION_MARSHMALLOW) { - return; - } - JNIEnv* env = AttachCurrentThread(); Java_MediaCodecBridge_createCallbackHandlerForTesting(env); } @@ -304,9 +299,6 @@ MediaCodecBridgeImpl::MediaCodecBridgeImpl( if (!on_buffers_available_cb_) return; - DCHECK_GE(base::android::BuildInfo::GetInstance()->sdk_int(), - base::android::SDK_VERSION_MARSHMALLOW); - // Note this should be done last since setBuffersAvailableListener() may // immediately invoke the callback if buffers came in during construction. Java_MediaCodecBridge_setBuffersAvailableListener( @@ -673,8 +665,6 @@ std::string MediaCodecBridgeImpl::GetName() { } bool MediaCodecBridgeImpl::SetSurface(const JavaRef<jobject>& surface) { - DCHECK_GE(base::android::BuildInfo::GetInstance()->sdk_int(), - base::android::SDK_VERSION_MARSHMALLOW); JNIEnv* env = AttachCurrentThread(); return Java_MediaCodecBridge_setSurface(env, j_bridge_, surface); } diff --git a/chromium/media/base/android/media_codec_bridge_impl.h b/chromium/media/base/android/media_codec_bridge_impl.h index c0874748d0d..5e64ddd20ff 100644 --- a/chromium/media/base/android/media_codec_bridge_impl.h +++ b/chromium/media/base/android/media_codec_bridge_impl.h @@ -62,8 +62,6 @@ class MEDIA_EXPORT VideoCodecConfig { // Enables the async MediaCodec.Callback API. |on_buffers_available_cb| // will be called when input or output buffers are available. This will be // called on an arbitrary thread, so use BindToCurrentLoop if needed. - // - // May only be used on API level 23 and higher. base::RepeatingClosure on_buffers_available_cb; }; diff --git a/chromium/media/base/android/media_codec_bridge_impl_unittest.cc b/chromium/media/base/android/media_codec_bridge_impl_unittest.cc index 322eb3d5cbe..d1010650e7e 100644 --- a/chromium/media/base/android/media_codec_bridge_impl_unittest.cc +++ b/chromium/media/base/android/media_codec_bridge_impl_unittest.cc @@ -11,6 +11,7 @@ #include "base/files/file_util.h" #include "base/logging.h" #include "base/memory/ptr_util.h" +#include "base/time/time.h" #include "media/base/android/media_codec_bridge_impl.h" #include "media/base/android/media_codec_util.h" #include "media/base/decoder_buffer.h" diff --git a/chromium/media/base/android/media_codec_util.cc b/chromium/media/base/android/media_codec_util.cc index 34bcdbd310a..3b53e0125d9 100644 --- a/chromium/media/base/android/media_codec_util.cc +++ b/chromium/media/base/android/media_codec_util.cc @@ -118,7 +118,20 @@ static bool HasVp9Profile23Decoder() { // static std::string MediaCodecUtil::CodecToAndroidMimeType(AudioCodec codec) { - if (IsPassthroughAudioFormat(codec)) + return CodecToAndroidMimeType(codec, kUnknownSampleFormat); +} + +// static +std::string MediaCodecUtil::CodecToAndroidMimeType(AudioCodec codec, + SampleFormat sample_format) { + // Passthrough is possible for some bitstream formats. + const bool is_passthrough = sample_format == kSampleFormatDts || + sample_format == kSampleFormatDtsxP2 || + sample_format == kSampleFormatAc3 || + sample_format == kSampleFormatEac3 || + sample_format == kSampleFormatMpegHAudio; + + if (IsPassthroughAudioFormat(codec) || is_passthrough) return kBitstreamAudioMimeType; switch (codec) { @@ -278,8 +291,6 @@ bool MediaCodecUtil::IsPassthroughAudioFormat(AudioCodec codec) { switch (codec) { case AudioCodec::kAC3: case AudioCodec::kEAC3: - case AudioCodec::kDTS: - case AudioCodec::kDTSXP2: case AudioCodec::kMpegHAudio: return true; default: diff --git a/chromium/media/base/android/media_codec_util.h b/chromium/media/base/android/media_codec_util.h index 2825a7c8e54..1933e9c174b 100644 --- a/chromium/media/base/android/media_codec_util.h +++ b/chromium/media/base/android/media_codec_util.h @@ -14,6 +14,7 @@ #include "media/base/android/media_codec_direction.h" #include "media/base/audio_codecs.h" #include "media/base/media_export.h" +#include "media/base/sample_format.h" #include "media/base/video_codecs.h" namespace media { @@ -26,6 +27,8 @@ namespace media { class MEDIA_EXPORT MediaCodecUtil { public: static std::string CodecToAndroidMimeType(AudioCodec codec); + static std::string CodecToAndroidMimeType(AudioCodec codec, + SampleFormat sample_format); static std::string CodecToAndroidMimeType(VideoCodec codec); // Returns true if MediaCodec supports CBCS Encryption. diff --git a/chromium/media/base/android/media_drm_bridge.cc b/chromium/media/base/android/media_drm_bridge.cc index 6bc445c0515..0c38fc73c66 100644 --- a/chromium/media/base/android/media_drm_bridge.cc +++ b/chromium/media/base/android/media_drm_bridge.cc @@ -6,6 +6,7 @@ #include <stddef.h> #include <sys/system_properties.h> + #include <algorithm> #include <memory> #include <utility> @@ -15,7 +16,6 @@ #include "base/android/jni_string.h" #include "base/bind.h" #include "base/callback_helpers.h" -#include "base/cxx17_backports.h" #include "base/feature_list.h" #include "base/location.h" #include "base/logging.h" @@ -181,7 +181,7 @@ class KeySystemManager { KeySystemManager::KeySystemManager() { // Widevine is always supported in Android. key_system_uuid_map_[kWidevineKeySystem] = - UUID(kWidevineUuid, kWidevineUuid + base::size(kWidevineUuid)); + UUID(kWidevineUuid, kWidevineUuid + std::size(kWidevineUuid)); MediaDrmBridgeClient* client = GetMediaDrmBridgeClient(); if (client) client->AddKeySystemUUIDMappings(&key_system_uuid_map_); diff --git a/chromium/media/base/android/media_player_bridge.cc b/chromium/media/base/android/media_player_bridge.cc index 723837a9350..6a7eacdd39e 100644 --- a/chromium/media/base/android/media_player_bridge.cc +++ b/chromium/media/base/android/media_player_bridge.cc @@ -121,7 +121,7 @@ MediaPlayerBridge::~MediaPlayerBridge() { void MediaPlayerBridge::Initialize() { cookies_.clear(); - if (url_.SchemeIsBlob()) { + if (url_.SchemeIsBlob() || url_.SchemeIsFileSystem()) { NOTREACHED(); return; } @@ -182,20 +182,13 @@ void MediaPlayerBridge::SetPlaybackRate(double playback_rate) { void MediaPlayerBridge::Prepare() { DCHECK(j_media_player_bridge_.is_null()); - if (url_.SchemeIsBlob()) { + if (url_.SchemeIsBlob() || url_.SchemeIsFileSystem()) { NOTREACHED(); return; } CreateJavaMediaPlayerBridge(); - if (url_.SchemeIsFileSystem()) { - client_->GetMediaResourceGetter()->GetPlatformPathFromURL( - url_, base::BindOnce(&MediaPlayerBridge::SetDataSource, - weak_factory_.GetWeakPtr())); - return; - } - SetDataSource(url_.spec()); } diff --git a/chromium/media/base/android/media_resource_getter.h b/chromium/media/base/android/media_resource_getter.h index 714e5f1d05d..b0b822261fa 100644 --- a/chromium/media/base/android/media_resource_getter.h +++ b/chromium/media/base/android/media_resource_getter.h @@ -31,9 +31,6 @@ class MEDIA_EXPORT MediaResourceGetter { // Callback to get the cookies. Args: cookies string. typedef base::OnceCallback<void(const std::string&)> GetCookieCB; - // Callback to get the platform path. Args: platform path. - typedef base::OnceCallback<void(const std::string&)> GetPlatformPathCB; - // Callback to get the auth credentials. Args: username and password. typedef base::OnceCallback<void(const std::u16string&, const std::u16string&)> GetAuthCredentialsCB; @@ -53,10 +50,6 @@ class MEDIA_EXPORT MediaResourceGetter { const net::SiteForCookies& site_for_cookies, const url::Origin& top_frame_origin, GetCookieCB callback) = 0; - - // Method for getting the platform path from a file system URL. - virtual void GetPlatformPathFromURL(const GURL& url, - GetPlatformPathCB callback) = 0; }; } // namespace media diff --git a/chromium/media/base/android/media_service_throttler_unittest.cc b/chromium/media/base/android/media_service_throttler_unittest.cc index 0e3928f0bfd..7b12f8aef9b 100644 --- a/chromium/media/base/android/media_service_throttler_unittest.cc +++ b/chromium/media/base/android/media_service_throttler_unittest.cc @@ -8,6 +8,7 @@ #include "base/numerics/safe_conversions.h" #include "base/test/simple_test_tick_clock.h" #include "base/test/task_environment.h" +#include "base/time/time.h" #include "media/base/android/media_server_crash_listener.h" #include "media/base/fake_single_thread_task_runner.h" #include "testing/gmock/include/gmock/gmock.h" diff --git a/chromium/media/base/audio_buffer_unittest.cc b/chromium/media/base/audio_buffer_unittest.cc index 7a11dcf12c5..e20fff84008 100644 --- a/chromium/media/base/audio_buffer_unittest.cc +++ b/chromium/media/base/audio_buffer_unittest.cc @@ -8,6 +8,7 @@ #include <memory> #include "base/test/gtest_util.h" +#include "base/time/time.h" #include "media/base/audio_buffer.h" #include "media/base/audio_bus.h" #include "media/base/test_helpers.h" diff --git a/chromium/media/base/audio_bus_unittest.cc b/chromium/media/base/audio_bus_unittest.cc index 7b2f328582b..753b407d92f 100644 --- a/chromium/media/base/audio_bus_unittest.cc +++ b/chromium/media/base/audio_bus_unittest.cc @@ -2,19 +2,19 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "media/base/audio_bus.h" + #include <stddef.h> #include <stdint.h> #include <limits> #include <memory> -#include "base/cxx17_backports.h" #include "base/memory/aligned_memory.h" #include "base/strings/stringprintf.h" #include "base/test/bind.h" #include "base/time/time.h" #include "build/build_config.h" -#include "media/base/audio_bus.h" #include "media/base/audio_parameters.h" #include "media/base/audio_sample_types.h" #include "media/base/channel_layout.h" @@ -333,7 +333,7 @@ static const int kTestVectorFrameCount = kTestVectorSize / 2; static const float kTestVectorResult[][kTestVectorFrameCount] = { {-1.0f, 1.0f, 0.5f, 0.0f, 0.0f}, {0.0f, -1.0f, -0.5f, 1.0f, 0.0f}}; -static const int kTestVectorChannelCount = base::size(kTestVectorResult); +static const int kTestVectorChannelCount = std::size(kTestVectorResult); // Verify FromInterleaved() deinterleaves audio in supported formats correctly. TEST_F(AudioBusTest, FromInterleaved) { @@ -424,26 +424,26 @@ TEST_F(AudioBusTest, ToInterleaved) { { SCOPED_TRACE("UnsignedInt8SampleTypeTraits"); - uint8_t test_array[base::size(kTestVectorUint8)]; + uint8_t test_array[std::size(kTestVectorUint8)]; bus->ToInterleaved<UnsignedInt8SampleTypeTraits>(bus->frames(), test_array); ASSERT_EQ(0, memcmp(test_array, kTestVectorUint8, sizeof(kTestVectorUint8))); } { SCOPED_TRACE("SignedInt16SampleTypeTraits"); - int16_t test_array[base::size(kTestVectorInt16)]; + int16_t test_array[std::size(kTestVectorInt16)]; bus->ToInterleaved<SignedInt16SampleTypeTraits>(bus->frames(), test_array); ASSERT_EQ(0, memcmp(test_array, kTestVectorInt16, sizeof(kTestVectorInt16))); } { SCOPED_TRACE("SignedInt32SampleTypeTraits"); - int32_t test_array[base::size(kTestVectorInt32)]; + int32_t test_array[std::size(kTestVectorInt32)]; bus->ToInterleaved<SignedInt32SampleTypeTraits>(bus->frames(), test_array); // Some compilers get better precision than others on the half-max test, so // let the test pass with an off by one check on the half-max. - int32_t alternative_acceptable_result[base::size(kTestVectorInt32)]; + int32_t alternative_acceptable_result[std::size(kTestVectorInt32)]; memcpy(alternative_acceptable_result, kTestVectorInt32, sizeof(kTestVectorInt32)); ASSERT_EQ(alternative_acceptable_result[4], @@ -457,7 +457,7 @@ TEST_F(AudioBusTest, ToInterleaved) { } { SCOPED_TRACE("Float32SampleTypeTraits"); - float test_array[base::size(kTestVectorFloat32)]; + float test_array[std::size(kTestVectorFloat32)]; bus->ToInterleaved<Float32SampleTypeTraits>(bus->frames(), test_array); ASSERT_EQ( 0, memcmp(test_array, kTestVectorFloat32, sizeof(kTestVectorFloat32))); @@ -471,9 +471,9 @@ TEST_F(AudioBusTest, ToInterleavedSanitized) { bus->frames()); // Verify FromInterleaved applied no sanity. ASSERT_EQ(bus->channel(0)[0], kTestVectorFloat32Invalid[0]); - float test_array[base::size(kTestVectorFloat32Sanitized)]; + float test_array[std::size(kTestVectorFloat32Sanitized)]; bus->ToInterleaved<Float32SampleTypeTraits>(bus->frames(), test_array); - for (size_t i = 0; i < base::size(kTestVectorFloat32Sanitized); ++i) + for (size_t i = 0; i < std::size(kTestVectorFloat32Sanitized); ++i) ASSERT_EQ(kTestVectorFloat32Sanitized[i], test_array[i]); // Verify that Float32SampleTypeTraitsNoClip applied no sanity. Note: We don't @@ -531,7 +531,7 @@ TEST_F(AudioBusTest, ToInterleavedPartial) { { SCOPED_TRACE("Float32SampleTypeTraits"); - float test_array[base::size(kTestVectorFloat32)]; + float test_array[std::size(kTestVectorFloat32)]; expected->ToInterleavedPartial<Float32SampleTypeTraits>( kPartialStart, kPartialFrames, test_array); ASSERT_EQ(0, memcmp(test_array, kTestVectorFloat32 + diff --git a/chromium/media/base/audio_decoder_config.cc b/chromium/media/base/audio_decoder_config.cc index 5bbd6f7a73c..1285f096f83 100644 --- a/chromium/media/base/audio_decoder_config.cc +++ b/chromium/media/base/audio_decoder_config.cc @@ -65,21 +65,23 @@ bool AudioDecoderConfig::IsValidConfig() const { } bool AudioDecoderConfig::Matches(const AudioDecoderConfig& config) const { - return ((codec() == config.codec()) && - (bytes_per_channel() == config.bytes_per_channel()) && - (channel_layout() == config.channel_layout()) && - (samples_per_second() == config.samples_per_second()) && - (extra_data() == config.extra_data()) && - (encryption_scheme() == config.encryption_scheme()) && - (sample_format() == config.sample_format()) && - (seek_preroll() == config.seek_preroll()) && - (codec_delay() == config.codec_delay()) && - (profile() == config.profile()) && - (should_discard_decoder_delay() == - config.should_discard_decoder_delay()) && - (target_output_channel_layout() == - config.target_output_channel_layout()) && - (aac_extra_data() == config.aac_extra_data())); + return ( + (codec() == config.codec()) && + (bytes_per_channel() == config.bytes_per_channel()) && + (channel_layout() == config.channel_layout()) && + (samples_per_second() == config.samples_per_second()) && + (extra_data() == config.extra_data()) && + (encryption_scheme() == config.encryption_scheme()) && + (sample_format() == config.sample_format()) && + (seek_preroll() == config.seek_preroll()) && + (codec_delay() == config.codec_delay()) && + (profile() == config.profile()) && + (should_discard_decoder_delay() == + config.should_discard_decoder_delay()) && + (target_output_channel_layout() == + config.target_output_channel_layout()) && + (target_output_sample_format() == config.target_output_sample_format()) && + (aac_extra_data() == config.aac_extra_data())); } std::string AudioDecoderConfig::AsHumanReadableString() const { @@ -100,6 +102,8 @@ std::string AudioDecoderConfig::AsHumanReadableString() const { << (should_discard_decoder_delay() ? "true" : "false") << ", target_output_channel_layout: " << ChannelLayoutToString(target_output_channel_layout()) + << ", target_output_sample_format: " + << SampleFormatToString(target_output_sample_format()) << ", has aac extra data: " << (aac_extra_data().empty() ? "false" : "true"); return s.str(); diff --git a/chromium/media/base/audio_decoder_config.h b/chromium/media/base/audio_decoder_config.h index 6e1077dca89..63379a2c1e1 100644 --- a/chromium/media/base/audio_decoder_config.h +++ b/chromium/media/base/audio_decoder_config.h @@ -115,6 +115,14 @@ class MEDIA_EXPORT AudioDecoderConfig { return target_output_channel_layout_; } + // Optionally set by renderer to signal desired bitstream-passthru format. + void set_target_output_sample_format(SampleFormat sample_format) { + target_output_sample_format_ = sample_format; + } + SampleFormat target_output_sample_format() const { + return target_output_sample_format_; + } + void set_aac_extra_data(std::vector<uint8_t> aac_extra_data) { aac_extra_data_ = std::move(aac_extra_data); } @@ -152,6 +160,9 @@ class MEDIA_EXPORT AudioDecoderConfig { // Layout of the output hardware. Optionally set. See setter comments. ChannelLayout target_output_channel_layout_ = CHANNEL_LAYOUT_NONE; + // Desired output format of bitstream. Optionally set. See setter comments. + SampleFormat target_output_sample_format_ = kUnknownSampleFormat; + // This is a hack for backward compatibility. For AAC, to preserve existing // behavior, we set `aac_extra_data_` on all platforms but only set // `extra_data` on Android. diff --git a/chromium/media/base/audio_discard_helper.h b/chromium/media/base/audio_discard_helper.h index 50ed4bff504..20e8d54ec81 100644 --- a/chromium/media/base/audio_discard_helper.h +++ b/chromium/media/base/audio_discard_helper.h @@ -73,6 +73,8 @@ class MEDIA_EXPORT AudioDiscardHelper { return timestamp_helper_.base_timestamp() != kNoTimestamp; } + size_t decoder_delay() const { return decoder_delay_; } + private: // The sample rate of the decoded audio samples. Used by TimeDeltaToFrames() // and the timestamp helper. diff --git a/chromium/media/base/audio_hash.cc b/chromium/media/base/audio_hash.cc index bf2c7baf0cd..236d92d8920 100644 --- a/chromium/media/base/audio_hash.cc +++ b/chromium/media/base/audio_hash.cc @@ -2,12 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "media/base/audio_hash.h" + #include <cmath> #include <sstream> -#include "media/base/audio_hash.h" - -#include "base/cxx17_backports.h" #include "base/numerics/math_constants.h" #include "base/strings/stringprintf.h" #include "media/base/audio_bus.h" @@ -29,7 +28,7 @@ void AudioHash::Update(const AudioBus* audio_bus, int frames) { for (uint32_t i = 0; i < static_cast<uint32_t>(frames); ++i) { const uint32_t kSampleIndex = sample_count_ + i; const uint32_t kHashIndex = - (kSampleIndex * (ch + 1)) % base::size(audio_hash_); + (kSampleIndex * (ch + 1)) % std::size(audio_hash_); // Mix in a sine wave with the result so we ensure that sequences of empty // buffers don't result in an empty hash. @@ -48,7 +47,7 @@ void AudioHash::Update(const AudioBus* audio_bus, int frames) { std::string AudioHash::ToString() const { std::string result; - for (size_t i = 0; i < base::size(audio_hash_); ++i) + for (size_t i = 0; i < std::size(audio_hash_); ++i) result += base::StringPrintf("%.2f,", audio_hash_[i]); return result; } @@ -58,7 +57,7 @@ bool AudioHash::IsEquivalent(const std::string& other, double tolerance) const { char comma; std::stringstream is(other); - for (size_t i = 0; i < base::size(audio_hash_); ++i) { + for (size_t i = 0; i < std::size(audio_hash_); ++i) { is >> other_hash >> comma; if (std::fabs(audio_hash_[i] - other_hash) > tolerance) return false; diff --git a/chromium/media/base/audio_parameters.cc b/chromium/media/base/audio_parameters.cc index 401d8034b67..ded8e403c9b 100644 --- a/chromium/media/base/audio_parameters.cc +++ b/chromium/media/base/audio_parameters.cc @@ -6,10 +6,22 @@ #include <sstream> +#include "media/base/audio_bus.h" #include "media/base/limits.h" namespace media { +static_assert(AudioBus::kChannelAlignment == kParametersAlignment, + "Audio buffer parameters struct alignment not same as AudioBus"); +static_assert(sizeof(AudioInputBufferParameters) % + AudioBus::kChannelAlignment == + 0, + "AudioInputBufferParameters not aligned"); +static_assert(sizeof(AudioOutputBufferParameters) % + AudioBus::kChannelAlignment == + 0, + "AudioOutputBufferParameters not aligned"); + const char* FormatToString(AudioParameters::Format format) { switch (format) { case AudioParameters::AUDIO_PCM_LINEAR: @@ -134,6 +146,7 @@ bool AudioParameters::IsValid() const { (hardware_capabilities_->max_frames_per_buffer >= hardware_capabilities_->min_frames_per_buffer))) && (channel_layout_ == CHANNEL_LAYOUT_DISCRETE || + channel_layout_ == CHANNEL_LAYOUT_5_1_4_DOWNMIX || channels_ == ChannelLayoutToChannelCount(channel_layout_)); } @@ -194,6 +207,11 @@ bool AudioParameters::IsBitstreamFormat() const { } } +bool AudioParameters::IsFormatSupportedByHardware(Format format) const { + return hardware_capabilities_.has_value() && + (hardware_capabilities_->bitstream_formats & format); +} + // static AudioParameters AudioParameters::UnavailableDeviceParams() { // Using 10 ms buffer since WebAudioMediaStreamSource::DeliverRebufferedAudio diff --git a/chromium/media/base/audio_parameters.h b/chromium/media/base/audio_parameters.h index 17643d804c8..4293aeeb1c7 100644 --- a/chromium/media/base/audio_parameters.h +++ b/chromium/media/base/audio_parameters.h @@ -13,7 +13,6 @@ #include "base/numerics/checked_math.h" #include "base/time/time.h" #include "build/build_config.h" -#include "media/base/audio_bus.h" #include "media/base/audio_latency.h" #include "media/base/audio_point.h" #include "media/base/channel_layout.h" @@ -27,19 +26,18 @@ namespace media { // size as sizeof(Audio{Input,Output}BufferParameters) + #(bytes in audio // buffer) without using packing. Also align Audio{Input,Output}BufferParameters // instead of in Audio{Input,Output}Buffer to be able to calculate size like so. -// Use a macro for the alignment value that's the same as +// Use a constexpr for the alignment value that's the same as // AudioBus::kChannelAlignment, since MSVC doesn't accept the latter to be used. #if BUILDFLAG(IS_WIN) #pragma warning(push) #pragma warning(disable : 4324) // Disable warning for added padding. #endif -#define PARAMETERS_ALIGNMENT 16 -static_assert(AudioBus::kChannelAlignment == PARAMETERS_ALIGNMENT, - "Audio buffer parameters struct alignment not same as AudioBus"); +constexpr int kParametersAlignment = 16; + // ****WARNING****: Do not change the field types or ordering of these fields // without checking that alignment is correct. The structs may be concurrently // accessed by both 32bit and 64bit process in shmem. http://crbug.com/781095. -struct MEDIA_SHMEM_EXPORT ALIGNAS(PARAMETERS_ALIGNMENT) +struct MEDIA_SHMEM_EXPORT ALIGNAS(kParametersAlignment) AudioInputBufferParameters { double volume; int64_t capture_time_us; // base::TimeTicks in microseconds. @@ -47,7 +45,7 @@ struct MEDIA_SHMEM_EXPORT ALIGNAS(PARAMETERS_ALIGNMENT) uint32_t id; bool key_pressed; }; -struct MEDIA_SHMEM_EXPORT ALIGNAS(PARAMETERS_ALIGNMENT) +struct MEDIA_SHMEM_EXPORT ALIGNAS(kParametersAlignment) AudioOutputBufferParameters { int64_t delay_us; // base::TimeDelta in microseconds. int64_t delay_timestamp_us; // base::TimeTicks in microseconds. @@ -55,20 +53,10 @@ struct MEDIA_SHMEM_EXPORT ALIGNAS(PARAMETERS_ALIGNMENT) uint32_t bitstream_data_size; uint32_t bitstream_frames; }; -#undef PARAMETERS_ALIGNMENT #if BUILDFLAG(IS_WIN) #pragma warning(pop) #endif -static_assert(sizeof(AudioInputBufferParameters) % - AudioBus::kChannelAlignment == - 0, - "AudioInputBufferParameters not aligned"); -static_assert(sizeof(AudioOutputBufferParameters) % - AudioBus::kChannelAlignment == - 0, - "AudioOutputBufferParameters not aligned"); - struct MEDIA_SHMEM_EXPORT AudioInputBuffer { AudioInputBufferParameters params; int8_t audio[1]; @@ -94,6 +82,8 @@ struct MEDIA_SHMEM_EXPORT AudioRendererAlgorithmParameters { base::TimeDelta starting_capacity_for_encrypted; }; +class AudioParameters; + // These convenience function safely computes the size required for // |shared_memory_count| AudioInputBuffers, with enough memory for AudioBus // data, using |paremeters| (or alternatively |channels| and |frames|). The @@ -124,8 +114,6 @@ MEDIA_SHMEM_EXPORT uint32_t ComputeAudioOutputBufferSize(int channels, class MEDIA_SHMEM_EXPORT AudioParameters { public: - // TODO(miu): Rename this enum to something that correctly reflects its - // semantics, such as "TransportScheme." // GENERATED_JAVA_ENUM_PACKAGE: org.chromium.media // GENERATED_JAVA_CLASS_NAME_OVERRIDE: AudioEncodingFormat // GENERATED_JAVA_PREFIX_TO_STRIP: AUDIO_ @@ -170,6 +158,9 @@ class MEDIA_SHMEM_EXPORT AudioParameters { // experimentally be enabled. MULTIZONE = 1 << 7, AUDIO_PREFETCH = 1 << 8, + ALLOW_DSP_ECHO_CANCELLER = 1 << 9, + ALLOW_DSP_NOISE_SUPPRESSION = 1 << 10, + ALLOW_DSP_AUTOMATIC_GAIN_CONTROL = 1 << 11, }; struct HardwareCapabilities { @@ -177,7 +168,7 @@ class MEDIA_SHMEM_EXPORT AudioParameters { : min_frames_per_buffer(min_frames_per_buffer), max_frames_per_buffer(max_frames_per_buffer), bitstream_formats(0) {} - HardwareCapabilities(int bitstream_formats) + explicit HardwareCapabilities(int bitstream_formats) : min_frames_per_buffer(0), max_frames_per_buffer(0), bitstream_formats(bitstream_formats) {} @@ -246,6 +237,8 @@ class MEDIA_SHMEM_EXPORT AudioParameters { // Return true if |format_| is compressed bitstream. bool IsBitstreamFormat() const; + bool IsFormatSupportedByHardware(Format format) const; + void set_format(Format format) { format_ = format; } Format format() const { return format_; } @@ -256,6 +249,7 @@ class MEDIA_SHMEM_EXPORT AudioParameters { // this explicitly is only required with CHANNEL_LAYOUT_DISCRETE. void set_channels_for_discrete(int channels) { DCHECK(channel_layout_ == CHANNEL_LAYOUT_DISCRETE || + channel_layout_ == CHANNEL_LAYOUT_5_1_4_DOWNMIX || channels == ChannelLayoutToChannelCount(channel_layout_)); channels_ = channels; } diff --git a/chromium/media/base/audio_parameters_unittest.cc b/chromium/media/base/audio_parameters_unittest.cc index 28bac4e0002..021f044991e 100644 --- a/chromium/media/base/audio_parameters_unittest.cc +++ b/chromium/media/base/audio_parameters_unittest.cc @@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "media/base/audio_parameters.h" + #include <stddef.h> -#include "base/cxx17_backports.h" #include "base/strings/string_number_conversions.h" -#include "media/base/audio_parameters.h" #include "testing/gtest/include/gtest/gtest.h" namespace media { @@ -107,8 +107,8 @@ TEST(AudioParameters, Compare) { CHANNEL_LAYOUT_STEREO, 2000, 200), }; - for (size_t i = 0; i < base::size(values); ++i) { - for (size_t j = 0; j < base::size(values); ++j) { + for (size_t i = 0; i < std::size(values); ++i) { + for (size_t j = 0; j < std::size(values); ++j) { SCOPED_TRACE("i=" + base::NumberToString(i) + " j=" + base::NumberToString(j)); EXPECT_EQ(i < j, values[i] < values[j]); diff --git a/chromium/media/base/audio_processor_controls.h b/chromium/media/base/audio_processor_controls.h new file mode 100644 index 00000000000..b429f8035a6 --- /dev/null +++ b/chromium/media/base/audio_processor_controls.h @@ -0,0 +1,40 @@ +// Copyright 2022 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_AUDIO_PROCESSOR_CONTROLS_H_ +#define MEDIA_BASE_AUDIO_PROCESSOR_CONTROLS_H_ + +#include "base/callback.h" +#include "media/base/media_export.h" +#include "third_party/abseil-cpp/absl/types/optional.h" + +namespace media { + +// Audio processing metrics that are reported by the audio service. +struct MEDIA_EXPORT AudioProcessingStats { + absl::optional<double> echo_return_loss; + absl::optional<double> echo_return_loss_enhancement; +}; + +// Interactions with the audio service. +class MEDIA_EXPORT AudioProcessorControls { + public: + using GetStatsCB = + base::OnceCallback<void(const media::AudioProcessingStats& stats)>; + + // Request the latest stats from the audio processor. Stats are returned + // asynchronously through |callback|. + virtual void GetStats(GetStatsCB callback) = 0; + + // Set preferred number of microphone channels. + virtual void SetPreferredNumCaptureChannels( + int32_t num_preferred_channels) = 0; + + protected: + virtual ~AudioProcessorControls() = default; +}; + +} // namespace media + +#endif // MEDIA_BASE_AUDIO_PROCESSOR_CONTROLS_H_ diff --git a/chromium/media/base/audio_renderer_mixer_unittest.cc b/chromium/media/base/audio_renderer_mixer_unittest.cc index 3151b3153d6..d094586e7ab 100644 --- a/chromium/media/base/audio_renderer_mixer_unittest.cc +++ b/chromium/media/base/audio_renderer_mixer_unittest.cc @@ -14,11 +14,11 @@ #include "base/bind.h" #include "base/callback_helpers.h" -#include "base/cxx17_backports.h" #include "base/memory/raw_ptr.h" #include "base/synchronization/waitable_event.h" #include "base/test/task_environment.h" #include "base/threading/platform_thread.h" +#include "base/time/time.h" #include "media/base/audio_renderer_mixer_input.h" #include "media/base/audio_renderer_mixer_pool.h" #include "media/base/fake_audio_render_callback.h" @@ -536,19 +536,19 @@ INSTANTIATE_TEST_SUITE_P( // Downsampling, multuple input sample rates. std::make_tuple(static_cast<const int* const>(kTestInput3Rates), - base::size(kTestInput3Rates), + std::size(kTestInput3Rates), kTestInput3Rates[0], 0.01), // Upsampling, multiple sinput sample rates. std::make_tuple(static_cast<const int* const>(kTestInput3Rates), - base::size(kTestInput3Rates), + std::size(kTestInput3Rates), kTestInput3Rates[2], 0.01), // Both downsampling and upsampling, multiple input sample rates std::make_tuple(static_cast<const int* const>(kTestInput3Rates), - base::size(kTestInput3Rates), + std::size(kTestInput3Rates), kTestInput3Rates[1], 0.01))); diff --git a/chromium/media/base/audio_shifter_unittest.cc b/chromium/media/base/audio_shifter_unittest.cc index 206048ac445..4d99ceac4f7 100644 --- a/chromium/media/base/audio_shifter_unittest.cc +++ b/chromium/media/base/audio_shifter_unittest.cc @@ -8,6 +8,7 @@ #include <memory> #include <vector> +#include "base/time/time.h" #include "media/base/audio_bus.h" #include "media/base/audio_shifter.h" #include "testing/gtest/include/gtest/gtest.h" diff --git a/chromium/media/base/audio_timestamp_helper.h b/chromium/media/base/audio_timestamp_helper.h index 8ec5be76604..116826d800e 100644 --- a/chromium/media/base/audio_timestamp_helper.h +++ b/chromium/media/base/audio_timestamp_helper.h @@ -59,10 +59,9 @@ class MEDIA_EXPORT AudioTimestampHelper { // and the number of sample frames that have been added so far. base::TimeDelta GetTimestamp() const; - // Gets the duration if |frame_count| frames were added to the current - // timestamp reported by GetTimestamp(). This method ensures that - // (GetTimestamp() + GetFrameDuration(n)) will equal the timestamp that - // GetTimestamp() will return if AddFrames(n) is called. + // Gets the duration of |frame_count| frames by calculating the difference + // between the current timestamp and what the timestamp would be if + // |frame_count| frames were added. base::TimeDelta GetFrameDuration(int frame_count) const; // Returns the number of frames needed to reach the target timestamp. diff --git a/chromium/media/base/audio_timestamp_helper_unittest.cc b/chromium/media/base/audio_timestamp_helper_unittest.cc index af4144cebc9..2beb9414f11 100644 --- a/chromium/media/base/audio_timestamp_helper_unittest.cc +++ b/chromium/media/base/audio_timestamp_helper_unittest.cc @@ -2,11 +2,11 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "media/base/audio_timestamp_helper.h" + #include <stddef.h> #include <stdint.h> -#include "base/cxx17_backports.h" -#include "media/base/audio_timestamp_helper.h" #include "media/base/timestamp_constants.h" #include "testing/gtest/include/gtest/gtest.h" @@ -132,7 +132,7 @@ TEST_F(AudioTimestampHelperTest, GetDuration) { int frame_count = 5; int64_t expected_durations[] = {113, 113, 114, 113, 113, 114}; - for (size_t i = 0; i < base::size(expected_durations); ++i) { + for (size_t i = 0; i < std::size(expected_durations); ++i) { base::TimeDelta duration = helper_.GetFrameDuration(frame_count); EXPECT_EQ(expected_durations[i], duration.InMicroseconds()); diff --git a/chromium/media/base/bit_reader_unittest.cc b/chromium/media/base/bit_reader_unittest.cc index ee04e3603d5..e8ba51c12f7 100644 --- a/chromium/media/base/bit_reader_unittest.cc +++ b/chromium/media/base/bit_reader_unittest.cc @@ -7,7 +7,6 @@ #include <stddef.h> #include <stdint.h> -#include "base/cxx17_backports.h" #include "testing/gtest/include/gtest/gtest.h" namespace media { @@ -97,7 +96,7 @@ TEST(BitReaderTest, VariableSkipBitsTest) { // Set bits to one only for the first and last bit of each read // in the pattern. size_t pos = 0; - for (size_t k = 0; k < base::size(pattern_read_skip); ++k) { + for (size_t k = 0; k < std::size(pattern_read_skip); ++k) { const size_t read_bit_count = pattern_read_skip[k][0]; if (read_bit_count > 0) { SetBit(buffer, sizeof(buffer), pos); @@ -110,7 +109,7 @@ TEST(BitReaderTest, VariableSkipBitsTest) { // Run the test. BitReader bit_reader(buffer, sizeof(buffer)); EXPECT_EQ(bit_reader.bits_available(), static_cast<int>(sizeof(buffer) * 8)); - for (size_t k = 0; k < base::size(pattern_read_skip); ++k) { + for (size_t k = 0; k < std::size(pattern_read_skip); ++k) { const size_t read_bit_count = pattern_read_skip[k][0]; if (read_bit_count > 0) { int value; diff --git a/chromium/media/base/bitrate.cc b/chromium/media/base/bitrate.cc index bc904dfe388..b265cc90d1e 100644 --- a/chromium/media/base/bitrate.cc +++ b/chromium/media/base/bitrate.cc @@ -9,33 +9,33 @@ namespace media { // static -Bitrate Bitrate::VariableBitrate(uint32_t target_bitrate, - uint32_t peak_bitrate) { - DCHECK_GE(peak_bitrate, target_bitrate); - return Bitrate(Mode::kVariable, target_bitrate, peak_bitrate); +Bitrate Bitrate::VariableBitrate(uint32_t target_bps, uint32_t peak_bps) { + DCHECK_GE(peak_bps, target_bps); + return Bitrate(Mode::kVariable, target_bps, peak_bps); } bool Bitrate::operator==(const Bitrate& right) const { - return (this->mode_ == right.mode_) && (this->target_ == right.target_) && - (this->peak_ == right.peak_); + return (this->mode_ == right.mode_) && + (this->target_bps_ == right.target_bps_) && + (this->peak_bps_ == right.peak_bps_); } bool Bitrate::operator!=(const Bitrate& right) const { return !(*this == right); } -uint32_t Bitrate::peak() const { - DCHECK_EQ(mode_ == Mode::kConstant, peak_ == 0u); - return peak_; +uint32_t Bitrate::peak_bps() const { + DCHECK_EQ(mode_ == Mode::kConstant, peak_bps_ == 0u); + return peak_bps_; } std::string Bitrate::ToString() const { switch (mode_) { case Mode::kConstant: - return base::StringPrintf("CBR: %d bps", target_); + return base::StringPrintf("CBR: %d bps", target_bps_); case Mode::kVariable: - return base::StringPrintf("VBR: target %d bps, peak %d bps", target_, - peak_); + return base::StringPrintf("VBR: target %d bps, peak %d bps", target_bps_, + peak_bps_); } } diff --git a/chromium/media/base/bitrate.h b/chromium/media/base/bitrate.h index 1d189621908..f72692b5b8f 100644 --- a/chromium/media/base/bitrate.h +++ b/chromium/media/base/bitrate.h @@ -30,28 +30,25 @@ class MEDIA_EXPORT Bitrate { // or 64-bit value you want to use as input, you must explicitly convert to // uint32_t before calling. This is intended to prevent implicit and unsafe // type conversion. - static constexpr Bitrate ConstantBitrate(uint32_t target_bitrate) { - return Bitrate(Mode::kConstant, target_bitrate, 0); + static constexpr Bitrate ConstantBitrate(uint32_t target_bps) { + return Bitrate(Mode::kConstant, target_bps, 0); } - static Bitrate VariableBitrate(uint32_t target_bitrate, - uint32_t peak_bitrate); + static Bitrate VariableBitrate(uint32_t target_bps, uint32_t peak_bps); // Deleted variants: you must SAFELY convert to uint32_t before calling. // See base/numerics/safe_conversions.h for functions to safely convert // between types. - static Bitrate ConstantBitrate(int target_bitrate) = delete; - static Bitrate VariableBitrate(int target_bitrate, int peak_bitrate) = delete; - static Bitrate VariableBitrate(int target_bitrate, - uint32_t peak_bitrate) = delete; - static Bitrate VariableBitrate(uint32_t target_bitrate, - int peak_bitrate) = delete; - static Bitrate ConstantBitrate(uint64_t target_bitrate) = delete; - static Bitrate VariableBitrate(uint64_t target_bitrate, - uint64_t peak_bitrate) = delete; - static Bitrate VariableBitrate(uint64_t target_bitrate, - uint32_t peak_bitrate) = delete; - static Bitrate VariableBitrate(uint32_t target_bitrate, - uint64_t peak_bitrate) = delete; + static Bitrate ConstantBitrate(int target_bps) = delete; + static Bitrate VariableBitrate(int target_bps, int peak_bps) = delete; + static Bitrate VariableBitrate(int target_bps, uint32_t peak_bps) = delete; + static Bitrate VariableBitrate(uint32_t target_bps, int peak_bps) = delete; + static Bitrate ConstantBitrate(uint64_t target_bps) = delete; + static Bitrate VariableBitrate(uint64_t target_bps, + uint64_t peak_bps) = delete; + static Bitrate VariableBitrate(uint64_t target_bps, + uint32_t peak_bps) = delete; + static Bitrate VariableBitrate(uint32_t target_bps, + uint64_t peak_bps) = delete; bool operator==(const Bitrate& right) const; bool operator!=(const Bitrate& right) const; @@ -60,17 +57,17 @@ class MEDIA_EXPORT Bitrate { constexpr Mode mode() const { return mode_; } // Accessor for |target_|. - constexpr uint32_t target() const { return target_; } + constexpr uint32_t target_bps() const { return target_bps_; } // Accessor for |peak_|. Returns 0 if |mode_| is // Mode::kConstantBitrate. - uint32_t peak() const; + uint32_t peak_bps() const; std::string ToString() const; private: - constexpr Bitrate(Mode mode, uint32_t target_bitrate, uint32_t peak_bitrate) - : mode_(mode), target_(target_bitrate), peak_(peak_bitrate) {} + constexpr Bitrate(Mode mode, uint32_t target_bps, uint32_t peak_bps) + : mode_(mode), target_bps_(target_bps), peak_bps_(peak_bps) {} // These member variables cannot be const (despite the intent that we do not // change them after creation) because we must have an assignment operator for @@ -81,10 +78,10 @@ class MEDIA_EXPORT Bitrate { Mode mode_ = Mode::kConstant; // Target bitrate for the stream in bits per second. - uint32_t target_ = 0u; + uint32_t target_bps_ = 0u; // For use with Mode::kVariable. Peak bitrate in bits per second. - uint32_t peak_ = 0u; + uint32_t peak_bps_ = 0u; }; } // namespace media diff --git a/chromium/media/base/bitrate_unittest.cc b/chromium/media/base/bitrate_unittest.cc new file mode 100644 index 00000000000..0e385b2c3b7 --- /dev/null +++ b/chromium/media/base/bitrate_unittest.cc @@ -0,0 +1,25 @@ +// Copyright 2022 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. + +#include "media/base/bitrate.h" + +#include <string> + +#include "testing/gtest/include/gtest/gtest.h" + +namespace media { + +TEST(BitrateTest, ConstantBitrate_ToString) { + Bitrate bitrate = Bitrate::ConstantBitrate(1234u); + + EXPECT_EQ("CBR: 1234 bps", bitrate.ToString()); +} + +TEST(BitrateTest, VariableBitrate_ToString) { + Bitrate bitrate = Bitrate::VariableBitrate(0u, 123456u); + + EXPECT_EQ("VBR: target 0 bps, peak 123456 bps", bitrate.ToString()); +} + +} // namespace media diff --git a/chromium/media/base/cdm_context.cc b/chromium/media/base/cdm_context.cc index 3742b25f881..0a3ee1a1414 100644 --- a/chromium/media/base/cdm_context.cc +++ b/chromium/media/base/cdm_context.cc @@ -35,9 +35,9 @@ bool CdmContext::RequiresMediaFoundationRenderer() { return false; } -bool CdmContext::GetMediaFoundationCdmProxy( - GetMediaFoundationCdmProxyCB get_mf_cdm_proxy_cb) { - return false; +scoped_refptr<MediaFoundationCdmProxy> +CdmContext::GetMediaFoundationCdmProxy() { + return nullptr; } #endif diff --git a/chromium/media/base/cdm_context.h b/chromium/media/base/cdm_context.h index c48d2a47d0e..2e206d2c022 100644 --- a/chromium/media/base/cdm_context.h +++ b/chromium/media/base/cdm_context.h @@ -13,6 +13,10 @@ #include "media/media_buildflags.h" #include "third_party/abseil-cpp/absl/types/optional.h" +#if BUILDFLAG(IS_WIN) +#include "media/base/win/media_foundation_cdm_proxy.h" +#endif + #if BUILDFLAG(IS_CHROMEOS) namespace chromeos { class ChromeOsCdmContext; @@ -29,10 +33,6 @@ class MediaCryptoContext; class FuchsiaCdmContext; #endif -#if BUILDFLAG(IS_WIN) -class MediaFoundationCdmProxy; -#endif - // An interface representing the context that a media player needs from a // content decryption module (CDM) to decrypt (and decode) encrypted buffers. // Typically this will be passed to the media player (e.g. using SetCdm()). @@ -101,17 +101,10 @@ class MEDIA_EXPORT CdmContext { // a sync call called in the render process to setup the media pipeline. virtual bool RequiresMediaFoundationRenderer(); - using GetMediaFoundationCdmProxyCB = - base::OnceCallback<void(scoped_refptr<MediaFoundationCdmProxy>)>; - // 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. - // When the return value is true, the callback might also not be invoked - // if the application has never caused the MF-based CDM to create its - // native session. - // NOTE: the callback should always be fired asynchronously. - virtual bool GetMediaFoundationCdmProxy( - GetMediaFoundationCdmProxyCB get_mf_cdm_proxy_cb); + // Returns a MediaFoundationCdmProxy to expose an IMFTrustedInput instance for + // use in a Media Foundation rendering pipeline. Returns nullptr if the CDM is + // in an invalid state or if MediaFoundationCdmProxy is not available. + virtual scoped_refptr<MediaFoundationCdmProxy> GetMediaFoundationCdmProxy(); #endif #if BUILDFLAG(IS_ANDROID) diff --git a/chromium/media/base/channel_layout.cc b/chromium/media/base/channel_layout.cc index 07546f3ae32..b1be4cb5162 100644 --- a/chromium/media/base/channel_layout.cc +++ b/chromium/media/base/channel_layout.cc @@ -7,7 +7,6 @@ #include <stddef.h> #include "base/check_op.h" -#include "base/cxx17_backports.h" #include "base/logging.h" #include "base/notreached.h" @@ -47,6 +46,7 @@ static const int kLayoutToChannels[] = { 3, // CHANNEL_LAYOUT_STEREO_AND_KEYBOARD_MIC, deprecated 5, // CHANNEL_LAYOUT_4_1_QUAD_SIDE 0, // CHANNEL_LAYOUT_BITSTREAM + 6, // CHANNEL_LAYOUT_5_1_4 (downmixed to 5.1) }; // The channel orderings for each layout as specified by FFmpeg. Each value @@ -162,10 +162,13 @@ static const int kChannelOrderings[CHANNEL_LAYOUT_MAX + 1][CHANNELS_MAX + 1] = { { -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 , -1 }, // FL | FR | FC | LFE | BL | BR | FLofC | FRofC | BC | SL | SR + + // CHANNEL_LAYOUT_5_1_4, downmixed to six channels (5.1) + { 0 , 1 , 2 , 3 , -1 , -1 , -1 , -1 , -1 , 4 , 5 }, }; int ChannelLayoutToChannelCount(ChannelLayout layout) { - DCHECK_LT(static_cast<size_t>(layout), base::size(kLayoutToChannels)); + DCHECK_LT(static_cast<size_t>(layout), std::size(kLayoutToChannels)); DCHECK_LE(kLayoutToChannels[layout], kMaxConcurrentChannels); return kLayoutToChannels[layout]; } @@ -189,6 +192,8 @@ ChannelLayout GuessChannelLayout(int channels) { return CHANNEL_LAYOUT_6_1; case 8: return CHANNEL_LAYOUT_7_1; + case 10: + return CHANNEL_LAYOUT_5_1_4_DOWNMIX; default: DVLOG(1) << "Unsupported channel count: " << channels; } @@ -196,8 +201,8 @@ ChannelLayout GuessChannelLayout(int channels) { } int ChannelOrder(ChannelLayout layout, Channels channel) { - DCHECK_LT(static_cast<size_t>(layout), base::size(kChannelOrderings)); - DCHECK_LT(static_cast<size_t>(channel), base::size(kChannelOrderings[0])); + DCHECK_LT(static_cast<size_t>(layout), std::size(kChannelOrderings)); + DCHECK_LT(static_cast<size_t>(channel), std::size(kChannelOrderings[0])); return kChannelOrderings[layout][channel]; } @@ -269,6 +274,8 @@ const char* ChannelLayoutToString(ChannelLayout layout) { return "4.1_QUAD_SIDE"; case CHANNEL_LAYOUT_BITSTREAM: return "BITSTREAM"; + case CHANNEL_LAYOUT_5_1_4_DOWNMIX: + return "5.1.4 DOWNMIX"; } NOTREACHED() << "Invalid channel layout provided: " << layout; return ""; diff --git a/chromium/media/base/channel_layout.h b/chromium/media/base/channel_layout.h index c208eb6f4f9..2bf24ef8b1f 100644 --- a/chromium/media/base/channel_layout.h +++ b/chromium/media/base/channel_layout.h @@ -114,8 +114,14 @@ enum ChannelLayout { // pass-through mode). CHANNEL_LAYOUT_BITSTREAM = 32, + // Front L, Front R, Front C, LFE, Side L, Side R, + // Front Height L, Front Height R, Rear Height L, Rear Height R + // Will be represented as six channels (5.1) due to eight channel limit + // kMaxConcurrentChannels + CHANNEL_LAYOUT_5_1_4_DOWNMIX = 33, + // Max value, must always equal the largest entry ever logged. - CHANNEL_LAYOUT_MAX = CHANNEL_LAYOUT_BITSTREAM + CHANNEL_LAYOUT_MAX = CHANNEL_LAYOUT_5_1_4_DOWNMIX }; // Note: Do not reorder or reassign these values; other code depends on their diff --git a/chromium/media/base/channel_mixer_unittest.cc b/chromium/media/base/channel_mixer_unittest.cc index f89cc7954c3..56facff6325 100644 --- a/chromium/media/base/channel_mixer_unittest.cc +++ b/chromium/media/base/channel_mixer_unittest.cc @@ -2,13 +2,13 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "media/base/channel_mixer.h" + #include <memory> -#include "base/cxx17_backports.h" #include "base/strings/stringprintf.h" #include "media/base/audio_bus.h" #include "media/base/audio_parameters.h" -#include "media/base/channel_mixer.h" #include "testing/gtest/include/gtest/gtest.h" namespace media { @@ -166,35 +166,35 @@ INSTANTIATE_TEST_SUITE_P( testing::Values(ChannelMixerTestData(CHANNEL_LAYOUT_STEREO, CHANNEL_LAYOUT_MONO, kStereoToMonoValues, - base::size(kStereoToMonoValues), + std::size(kStereoToMonoValues), 0.5f), ChannelMixerTestData(CHANNEL_LAYOUT_MONO, CHANNEL_LAYOUT_STEREO, kMonoToStereoValues, - base::size(kMonoToStereoValues), + std::size(kMonoToStereoValues), 1.0f), ChannelMixerTestData(CHANNEL_LAYOUT_5_1, CHANNEL_LAYOUT_MONO, kFiveOneToMonoValues, - base::size(kFiveOneToMonoValues), + std::size(kFiveOneToMonoValues), ChannelMixer::kHalfPower), ChannelMixerTestData(CHANNEL_LAYOUT_DISCRETE, 2, CHANNEL_LAYOUT_DISCRETE, 2, kStereoToMonoValues, - base::size(kStereoToMonoValues)), + std::size(kStereoToMonoValues)), ChannelMixerTestData(CHANNEL_LAYOUT_DISCRETE, 2, CHANNEL_LAYOUT_DISCRETE, 5, kStereoToMonoValues, - base::size(kStereoToMonoValues)), + std::size(kStereoToMonoValues)), ChannelMixerTestData(CHANNEL_LAYOUT_DISCRETE, 5, CHANNEL_LAYOUT_DISCRETE, 2, kFiveDiscreteValues, - base::size(kFiveDiscreteValues)))); + std::size(kFiveDiscreteValues)))); } // namespace media diff --git a/chromium/media/base/channel_mixing_matrix_unittest.cc b/chromium/media/base/channel_mixing_matrix_unittest.cc index 7da150e258d..3bee28210a7 100644 --- a/chromium/media/base/channel_mixing_matrix_unittest.cc +++ b/chromium/media/base/channel_mixing_matrix_unittest.cc @@ -6,7 +6,6 @@ #include <stddef.h> -#include "base/cxx17_backports.h" #include "base/strings/stringprintf.h" #include "media/base/channel_mixer.h" #include "testing/gtest/include/gtest/gtest.h" @@ -161,7 +160,7 @@ TEST(ChannelMixingMatrixTest, DiscreteToDiscrete) { {2, 2}, {2, 5}, {5, 2}, }; - for (size_t n = 0; n < base::size(test_case); n++) { + for (size_t n = 0; n < std::size(test_case); n++) { int input_channels = test_case[n].input_channels; int output_channels = test_case[n].output_channels; ChannelMixingMatrix matrix_builder(CHANNEL_LAYOUT_DISCRETE, diff --git a/chromium/media/base/container_names.cc b/chromium/media/base/container_names.cc index 75816aaab82..08315dcdb55 100644 --- a/chromium/media/base/container_names.cc +++ b/chromium/media/base/container_names.cc @@ -11,7 +11,6 @@ #include <limits> #include "base/check_op.h" -#include "base/cxx17_backports.h" #include "base/numerics/safe_conversions.h" #include "media/base/bit_reader.h" @@ -312,7 +311,7 @@ static bool CheckDts(const uint8_t* buffer, int buffer_size) { // Verify core audio sampling frequency is an allowed value. size_t sampling_freq_index = ReadBits(&reader, 4); - RCHECK(sampling_freq_index < base::size(kSamplingFrequencyValid)); + RCHECK(sampling_freq_index < std::size(kSamplingFrequencyValid)); RCHECK(kSamplingFrequencyValid[sampling_freq_index]); // Verify transmission bit rate is valid. @@ -326,7 +325,7 @@ static bool CheckDts(const uint8_t* buffer, int buffer_size) { // Verify extension audio descriptor flag is an allowed value. size_t audio_id_index = ReadBits(&reader, 3); - RCHECK(audio_id_index < base::size(kExtAudioIdValid)); + RCHECK(audio_id_index < std::size(kExtAudioIdValid)); RCHECK(kExtAudioIdValid[audio_id_index]); // Skip extended coding flag and audio sync word insertion flag. @@ -386,7 +385,7 @@ static bool CheckDV(const uint8_t* buffer, int buffer_size) { reader.SkipBits(3); RCHECK(ReadBits(&reader, 24) == 0xffffff); current_sequence_number = sequence_number; - for (size_t i = 0; i < base::size(last_block_number); ++i) + for (size_t i = 0; i < std::size(last_block_number); ++i) last_block_number[i] = -1; } else { // Sequence number must match (this will also fail if no header seen). diff --git a/chromium/media/base/data_buffer_unittest.cc b/chromium/media/base/data_buffer_unittest.cc index e4f53040b00..0faaecd8b48 100644 --- a/chromium/media/base/data_buffer_unittest.cc +++ b/chromium/media/base/data_buffer_unittest.cc @@ -5,11 +5,12 @@ #include "media/base/data_buffer.h" #include <stdint.h> + #include <memory> #include <utility> -#include "base/cxx17_backports.h" #include "base/strings/string_util.h" +#include "base/time/time.h" #include "testing/gtest/include/gtest/gtest.h" namespace media { @@ -49,7 +50,7 @@ TEST(DataBufferTest, Constructor_ScopedArray) { TEST(DataBufferTest, CopyFrom) { const uint8_t kTestData[] = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77}; - const int kTestDataSize = base::size(kTestData); + const int kTestDataSize = std::size(kTestData); scoped_refptr<DataBuffer> buffer = DataBuffer::CopyFrom(kTestData, kTestDataSize); @@ -99,9 +100,9 @@ TEST(DataBufferTest, Duration) { TEST(DataBufferTest, ReadingWriting) { const char kData[] = "hello"; - const int kDataSize = base::size(kData); + const int kDataSize = std::size(kData); const char kNewData[] = "chromium"; - const int kNewDataSize = base::size(kNewData); + const int kNewDataSize = std::size(kNewData); // Create a DataBuffer. scoped_refptr<DataBuffer> buffer(new DataBuffer(kDataSize)); diff --git a/chromium/media/base/decoder.cc b/chromium/media/base/decoder.cc index 738c6856442..24a73f3dcb2 100644 --- a/chromium/media/base/decoder.cc +++ b/chromium/media/base/decoder.cc @@ -54,9 +54,6 @@ std::string GetDecoderName(VideoDecoderType type) { return "V4L2VideoDecoder"; case VideoDecoderType::kTesting: return "Testing or Mock Video decoder"; - default: - NOTREACHED(); - return "VideoDecoderType created through invalid static_cast"; } } @@ -76,9 +73,8 @@ std::string GetDecoderName(AudioDecoderType type) { return "AudioDecoderBroker"; case AudioDecoderType::kTesting: return "Testing or Mock Audio decoder"; - default: - NOTREACHED(); - return "VideoDecoderType created through invalid static_cast"; + case AudioDecoderType::kAudioToolbox: + return "AudioToolbox"; } } diff --git a/chromium/media/base/decoder.h b/chromium/media/base/decoder.h index b0705fe9c6c..f4370b12226 100644 --- a/chromium/media/base/decoder.h +++ b/chromium/media/base/decoder.h @@ -16,16 +16,17 @@ namespace media { // List of known AudioDecoder implementations; recorded to UKM, always add new // values to the end and do not reorder or delete values from this list. enum class AudioDecoderType : int { - kUnknown = 0, // Decoder name string is not recognized or n/a. - kFFmpeg = 1, // FFmpegAudioDecoder - kMojo = 2, // MojoAudioDecoder - kDecrypting = 3, // DecryptingAudioDecoder - kMediaCodec = 4, // MediaCodecAudioDecoder (Android) - kBroker = 5, // AudioDecoderBroker - kTesting = 6, // Never send this to UKM, for tests only. + kUnknown = 0, // Decoder name string is not recognized or n/a. + kFFmpeg = 1, // FFmpegAudioDecoder + kMojo = 2, // MojoAudioDecoder + kDecrypting = 3, // DecryptingAudioDecoder + kMediaCodec = 4, // MediaCodecAudioDecoder (Android) + kBroker = 5, // AudioDecoderBroker + kTesting = 6, // Never send this to UKM, for tests only. + kAudioToolbox = 7, // AudioToolbox (macOS) // Keep this at the end and equal to the last entry. - kMaxValue = kTesting, + kMaxValue = kAudioToolbox, }; // List of known VideoDecoder implementations; recorded to UKM, always add new diff --git a/chromium/media/base/decoder_buffer.cc b/chromium/media/base/decoder_buffer.cc index 2cf6d59bb2e..4d98e2c4bd1 100644 --- a/chromium/media/base/decoder_buffer.cc +++ b/chromium/media/base/decoder_buffer.cc @@ -142,7 +142,8 @@ scoped_refptr<DecoderBuffer> DecoderBuffer::CreateEOSBuffer() { return base::WrapRefCounted(new DecoderBuffer(NULL, 0, NULL, 0)); } -bool DecoderBuffer::MatchesForTesting(const DecoderBuffer& buffer) const { +bool DecoderBuffer::MatchesMetadataForTesting( + const DecoderBuffer& buffer) const { if (end_of_stream() != buffer.end_of_stream()) return false; @@ -152,14 +153,7 @@ bool DecoderBuffer::MatchesForTesting(const DecoderBuffer& buffer) const { if (timestamp() != buffer.timestamp() || duration() != buffer.duration() || is_key_frame() != buffer.is_key_frame() || - discard_padding() != buffer.discard_padding() || - data_size() != buffer.data_size() || - side_data_size() != buffer.side_data_size()) { - return false; - } - - if (memcmp(data(), buffer.data(), data_size()) != 0 || - memcmp(side_data(), buffer.side_data(), side_data_size()) != 0) { + discard_padding() != buffer.discard_padding()) { return false; } @@ -170,6 +164,21 @@ bool DecoderBuffer::MatchesForTesting(const DecoderBuffer& buffer) const { : true; } +bool DecoderBuffer::MatchesForTesting(const DecoderBuffer& buffer) const { + if (!MatchesMetadataForTesting(buffer)) // IN-TEST + return false; + + // It is illegal to call any member function if eos is true. + if (end_of_stream()) + return true; + + DCHECK(!buffer.end_of_stream()); + return data_size() == buffer.data_size() && + side_data_size() == buffer.side_data_size() && + memcmp(data(), buffer.data(), data_size()) == 0 && + memcmp(side_data(), buffer.side_data(), side_data_size()) == 0; +} + std::string DecoderBuffer::AsHumanReadableString(bool verbose) const { if (end_of_stream()) return "EOS"; diff --git a/chromium/media/base/decoder_buffer.h b/chromium/media/base/decoder_buffer.h index 852f5943f3c..f44b8792d2b 100644 --- a/chromium/media/base/decoder_buffer.h +++ b/chromium/media/base/decoder_buffer.h @@ -215,6 +215,9 @@ class MEDIA_EXPORT DecoderBuffer // including |data_| and |side_data_|. bool MatchesForTesting(const DecoderBuffer& buffer) const; + // As above, except that |data_| and |side_data_| are not compared. + bool MatchesMetadataForTesting(const DecoderBuffer& buffer) const; + // Returns a human-readable string describing |*this|. std::string AsHumanReadableString(bool verbose = false) const; diff --git a/chromium/media/base/decoder_buffer_unittest.cc b/chromium/media/base/decoder_buffer_unittest.cc index 2d6c257b923..2f80d5e92d8 100644 --- a/chromium/media/base/decoder_buffer_unittest.cc +++ b/chromium/media/base/decoder_buffer_unittest.cc @@ -9,7 +9,6 @@ #include <memory> -#include "base/cxx17_backports.h" #include "base/memory/read_only_shared_memory_region.h" #include "base/memory/unsafe_shared_memory_region.h" #include "base/strings/string_util.h" @@ -38,7 +37,7 @@ TEST(DecoderBufferTest, CreateEOSBuffer) { TEST(DecoderBufferTest, CopyFrom) { const uint8_t kData[] = "hello"; - const size_t kDataSize = base::size(kData); + const size_t kDataSize = std::size(kData); scoped_refptr<DecoderBuffer> buffer2(DecoderBuffer::CopyFrom( reinterpret_cast<const uint8_t*>(&kData), kDataSize)); @@ -65,7 +64,7 @@ TEST(DecoderBufferTest, CopyFrom) { TEST(DecoderBufferTest, FromArray) { const uint8_t kData[] = "hello"; - const size_t kDataSize = base::size(kData); + const size_t kDataSize = std::size(kData); std::unique_ptr<uint8_t[]> ptr(new uint8_t[kDataSize]); memcpy(ptr.get(), kData, kDataSize); @@ -80,7 +79,7 @@ TEST(DecoderBufferTest, FromArray) { TEST(DecoderBufferTest, FromPlatformSharedMemoryRegion) { const uint8_t kData[] = "hello"; - const size_t kDataSize = base::size(kData); + const size_t kDataSize = std::size(kData); auto region = base::UnsafeSharedMemoryRegion::Create(kDataSize); auto mapping = region.Map(); @@ -100,7 +99,7 @@ TEST(DecoderBufferTest, FromPlatformSharedMemoryRegion) { TEST(DecoderBufferTest, FromPlatformSharedMemoryRegion_Unaligned) { const uint8_t kData[] = "XXXhello"; - const size_t kDataSize = base::size(kData); + const size_t kDataSize = std::size(kData); const off_t kDataOffset = 3; auto region = base::UnsafeSharedMemoryRegion::Create(kDataSize); @@ -122,7 +121,7 @@ TEST(DecoderBufferTest, FromPlatformSharedMemoryRegion_Unaligned) { TEST(DecoderBufferTest, FromPlatformSharedMemoryRegion_ZeroSize) { const uint8_t kData[] = "hello"; - const size_t kDataSize = base::size(kData); + const size_t kDataSize = std::size(kData); auto region = base::UnsafeSharedMemoryRegion::Create(kDataSize); auto mapping = region.Map(); @@ -138,7 +137,7 @@ TEST(DecoderBufferTest, FromPlatformSharedMemoryRegion_ZeroSize) { TEST(DecoderBufferTest, FromSharedMemoryRegion) { const uint8_t kData[] = "hello"; - const size_t kDataSize = base::size(kData); + const size_t kDataSize = std::size(kData); auto mapping_region = base::ReadOnlySharedMemoryRegion::Create(kDataSize); ASSERT_TRUE(mapping_region.IsValid()); @@ -155,7 +154,7 @@ TEST(DecoderBufferTest, FromSharedMemoryRegion) { TEST(DecoderBufferTest, FromSharedMemoryRegion_Unaligned) { const uint8_t kData[] = "XXXhello"; - const size_t kDataSize = base::size(kData); + const size_t kDataSize = std::size(kData); const off_t kDataOffset = 3; auto mapping_region = base::ReadOnlySharedMemoryRegion::Create(kDataSize); @@ -175,7 +174,7 @@ TEST(DecoderBufferTest, FromSharedMemoryRegion_Unaligned) { TEST(DecoderBufferTest, FromSharedMemoryRegion_ZeroSize) { const uint8_t kData[] = "hello"; - const size_t kDataSize = base::size(kData); + const size_t kDataSize = std::size(kData); auto mapping_region = base::ReadOnlySharedMemoryRegion::Create(kDataSize); memcpy(mapping_region.mapping.GetMemoryAs<uint8_t>(), kData, kDataSize); @@ -188,7 +187,7 @@ TEST(DecoderBufferTest, FromSharedMemoryRegion_ZeroSize) { TEST(DecoderBufferTest, ReadingWriting) { const char kData[] = "hello"; - const size_t kDataSize = base::size(kData); + const size_t kDataSize = std::size(kData); scoped_refptr<DecoderBuffer> buffer(new DecoderBuffer(kDataSize)); ASSERT_TRUE(buffer.get()); diff --git a/chromium/media/base/decoder_status.cc b/chromium/media/base/decoder_status.cc index 9fffd5fe5ee..44d0aaf1351 100644 --- a/chromium/media/base/decoder_status.cc +++ b/chromium/media/base/decoder_status.cc @@ -39,6 +39,7 @@ const std::string GetDecodeStatusString(const DecoderStatus& status) { STRINGIFY(DecoderStatus::Codes::kCantChangeCodec); STRINGIFY(DecoderStatus::Codes::kFailedToCreateDecoder); STRINGIFY(DecoderStatus::Codes::kKeyFrameRequired); + STRINGIFY(DecoderStatus::Codes::kMissingTimestamp); } #undef STRINGIFY } diff --git a/chromium/media/base/decoder_status.h b/chromium/media/base/decoder_status.h index 209d4b20309..dd2a0c6548a 100644 --- a/chromium/media/base/decoder_status.h +++ b/chromium/media/base/decoder_status.h @@ -31,6 +31,7 @@ struct DecoderStatusTraits { kDecoderStreamReinitFailed = 109, kDecoderStreamDemuxerError = 110, kKeyFrameRequired = 111, + kMissingTimestamp = 112, // Reasons for failing to initialize kUnsupportedProfile = 200, diff --git a/chromium/media/base/demuxer_stream.cc b/chromium/media/base/demuxer_stream.cc index 9fad473f2db..ccc922440e5 100644 --- a/chromium/media/base/demuxer_stream.cc +++ b/chromium/media/base/demuxer_stream.cc @@ -6,6 +6,17 @@ namespace media { +std::string GetStreamLivenessName(StreamLiveness liveness) { + switch (liveness) { + case StreamLiveness::kUnknown: + return "unknown"; + case StreamLiveness::kRecorded: + return "recorded"; + case StreamLiveness::kLive: + return "live"; + } +} + // static const char* DemuxerStream::GetTypeName(Type type) { switch (type) { @@ -38,8 +49,8 @@ DemuxerStream::~DemuxerStream() = default; // Most DemuxerStream implementations don't specify liveness. Returns unknown // liveness by default. -DemuxerStream::Liveness DemuxerStream::liveness() const { - return DemuxerStream::LIVENESS_UNKNOWN; +StreamLiveness DemuxerStream::liveness() const { + return StreamLiveness::kUnknown; } // Most DemuxerStream implementations don't need to convert bit stream. diff --git a/chromium/media/base/demuxer_stream.h b/chromium/media/base/demuxer_stream.h index 3b10523f7fb..f866d62c0cb 100644 --- a/chromium/media/base/demuxer_stream.h +++ b/chromium/media/base/demuxer_stream.h @@ -16,6 +16,15 @@ class AudioDecoderConfig; class DecoderBuffer; class VideoDecoderConfig; +enum class StreamLiveness { + kUnknown, + kRecorded, + kLive, + kMaxValue = kLive, +}; + +MEDIA_EXPORT std::string GetStreamLivenessName(StreamLiveness liveness); + class MEDIA_EXPORT DemuxerStream { public: enum Type { @@ -29,13 +38,6 @@ class MEDIA_EXPORT DemuxerStream { // Returns a string representation of |type|. static const char* GetTypeName(Type type); - enum Liveness { - LIVENESS_UNKNOWN, - LIVENESS_RECORDED, - LIVENESS_LIVE, - LIVENESS_MAX = LIVENESS_LIVE, - }; - // Status returned in the Read() callback. // kOk : Indicates the second parameter is Non-NULL and contains media data // or the end of the stream. @@ -83,7 +85,7 @@ class MEDIA_EXPORT DemuxerStream { virtual Type type() const = 0; // Returns liveness of the streams provided, i.e. whether recorded or live. - virtual Liveness liveness() const; + virtual StreamLiveness liveness() const; virtual void EnableBitstreamConverter(); diff --git a/chromium/media/base/fake_audio_render_callback.h b/chromium/media/base/fake_audio_render_callback.h index 3fe33f202e6..1f5e39bf7e0 100644 --- a/chromium/media/base/fake_audio_render_callback.h +++ b/chromium/media/base/fake_audio_render_callback.h @@ -7,6 +7,7 @@ #include <stdint.h> +#include "base/time/time.h" #include "media/base/audio_converter.h" #include "media/base/audio_renderer_sink.h" #include "testing/gmock/include/gmock/gmock.h" diff --git a/chromium/media/base/fake_demuxer_stream.cc b/chromium/media/base/fake_demuxer_stream.cc index 771795dea62..d6020caddc1 100644 --- a/chromium/media/base/fake_demuxer_stream.cc +++ b/chromium/media/base/fake_demuxer_stream.cc @@ -5,14 +5,13 @@ #include "media/base/fake_demuxer_stream.h" #include <stdint.h> -#include <memory> +#include <memory> #include <vector> #include "base/bind.h" #include "base/callback_helpers.h" #include "base/check_op.h" -#include "base/cxx17_backports.h" #include "base/location.h" #include "base/notreached.h" #include "base/task/single_thread_task_runner.h" @@ -206,9 +205,8 @@ void FakeDemuxerStream::DoRead() { // TODO(xhwang): Output out-of-order buffers if needed. if (is_encrypted_) { buffer->set_decrypt_config(DecryptConfig::CreateCencConfig( - std::string(kKeyId, kKeyId + base::size(kKeyId)), - std::string(kIv, kIv + base::size(kIv)), - std::vector<SubsampleEntry>())); + std::string(kKeyId, kKeyId + std::size(kKeyId)), + std::string(kIv, kIv + std::size(kIv)), std::vector<SubsampleEntry>())); } buffer->set_timestamp(current_timestamp_); buffer->set_duration(duration_); diff --git a/chromium/media/base/fake_demuxer_stream.h b/chromium/media/base/fake_demuxer_stream.h index c0a19a31891..1a2251e0515 100644 --- a/chromium/media/base/fake_demuxer_stream.h +++ b/chromium/media/base/fake_demuxer_stream.h @@ -6,6 +6,7 @@ #define MEDIA_BASE_FAKE_DEMUXER_STREAM_H_ #include "base/memory/ref_counted.h" +#include "base/time/time.h" #include "media/base/audio_decoder_config.h" #include "media/base/demuxer_stream.h" #include "media/base/media_resource.h" diff --git a/chromium/media/base/fake_demuxer_stream_unittest.cc b/chromium/media/base/fake_demuxer_stream_unittest.cc index ccfc880150c..04437210db9 100644 --- a/chromium/media/base/fake_demuxer_stream_unittest.cc +++ b/chromium/media/base/fake_demuxer_stream_unittest.cc @@ -326,4 +326,36 @@ TEST_F(FakeDemuxerStreamTest, SeekToStart_AfterEOS) { ReadAllBuffers(3, 5); } +TEST_F(FakeDemuxerStreamTest, DemuxerStream_GetTypeName) { + EXPECT_TRUE(DemuxerStream::GetTypeName(DemuxerStream::Type::AUDIO) == + std::string("audio")); + EXPECT_TRUE(DemuxerStream::GetTypeName(DemuxerStream::Type::VIDEO) == + std::string("video")); + EXPECT_TRUE(DemuxerStream::GetTypeName(DemuxerStream::Type::TEXT) == + std::string("text")); + EXPECT_TRUE(DemuxerStream::GetTypeName(DemuxerStream::Type::UNKNOWN) == + std::string("unknown")); +} + +TEST_F(FakeDemuxerStreamTest, DemuxerStream_GetStatusName) { + EXPECT_TRUE(DemuxerStream::GetStatusName(DemuxerStream::Status::kOk) == + std::string("okay")); + EXPECT_TRUE(DemuxerStream::GetStatusName(DemuxerStream::Status::kAborted) == + std::string("aborted")); + EXPECT_TRUE( + DemuxerStream::GetStatusName(DemuxerStream::Status::kConfigChanged) == + std::string("config_changed")); + EXPECT_TRUE(DemuxerStream::GetStatusName(DemuxerStream::Status::kError) == + std::string("error")); +} + +TEST_F(FakeDemuxerStreamTest, DemuxerStream_GetLivenessName) { + EXPECT_TRUE(GetStreamLivenessName(StreamLiveness::kUnknown) == + std::string("unknown")); + EXPECT_TRUE(GetStreamLivenessName(StreamLiveness::kRecorded) == + std::string("recorded")); + EXPECT_TRUE(GetStreamLivenessName(StreamLiveness::kLive) == + std::string("live")); +} + } // namespace media diff --git a/chromium/media/base/fake_single_thread_task_runner.h b/chromium/media/base/fake_single_thread_task_runner.h index 84e302f87e3..fd61d665b0b 100644 --- a/chromium/media/base/fake_single_thread_task_runner.h +++ b/chromium/media/base/fake_single_thread_task_runner.h @@ -11,6 +11,7 @@ #include "base/memory/raw_ptr.h" #include "base/task/single_thread_task_runner.h" #include "base/test/simple_test_tick_clock.h" +#include "base/time/time.h" namespace media { diff --git a/chromium/media/base/feedback_signal_accumulator_unittest.cc b/chromium/media/base/feedback_signal_accumulator_unittest.cc index d6c11a91673..f1d09baa765 100644 --- a/chromium/media/base/feedback_signal_accumulator_unittest.cc +++ b/chromium/media/base/feedback_signal_accumulator_unittest.cc @@ -4,6 +4,7 @@ #include "media/base/feedback_signal_accumulator.h" +#include "base/time/time.h" #include "testing/gtest/include/gtest/gtest.h" namespace media { diff --git a/chromium/media/base/key_system_properties.h b/chromium/media/base/key_system_properties.h index 6eeb8775875..f80ba87203a 100644 --- a/chromium/media/base/key_system_properties.h +++ b/chromium/media/base/key_system_properties.h @@ -82,7 +82,7 @@ using KeySystemPropertiesVector = std::vector<std::unique_ptr<KeySystemProperties>>; using GetSupportedKeySystemsCB = - base::OnceCallback<void(KeySystemPropertiesVector)>; + base::RepeatingCallback<void(KeySystemPropertiesVector)>; } // namespace media diff --git a/chromium/media/base/key_systems.cc b/chromium/media/base/key_systems.cc index adf33338922..744b47f7078 100644 --- a/chromium/media/base/key_systems.cc +++ b/chromium/media/base/key_systems.cc @@ -18,7 +18,6 @@ #include "base/notreached.h" #include "base/strings/string_util.h" #include "base/threading/thread_checker.h" -#include "base/time/time.h" #include "build/build_config.h" #include "media/base/key_system_names.h" #include "media/base/key_system_properties.h" @@ -276,7 +275,6 @@ class KeySystemsImpl : public KeySystems { // Implementation of KeySystems interface. void UpdateIfNeeded(base::OnceClosure done_cb) override; - bool IsUpToDate() override; std::string GetBaseKeySystemName( const std::string& key_system) const override; bool IsSupportedKeySystem(const std::string& key_system) const override; @@ -323,7 +321,6 @@ class KeySystemsImpl : public KeySystems { KeySystemsImpl(); ~KeySystemsImpl() override; - bool IsUpdateNeeded(); void UpdateSupportedKeySystems(); void OnSupportedKeySystemsUpdated(KeySystemPropertiesVector key_systems); void ProcessSupportedKeySystems(KeySystemPropertiesVector key_systems); @@ -387,10 +384,6 @@ KeySystemsImpl::~KeySystemsImpl() { update_callbacks_.Notify(); } -bool KeySystemsImpl::IsUpdateNeeded() { - return GetMediaClient() && GetMediaClient()->IsKeySystemsUpdateNeeded(); -} - void KeySystemsImpl::UpdateSupportedKeySystems() { DCHECK(!is_updating_); is_updating_ = true; @@ -401,28 +394,18 @@ void KeySystemsImpl::UpdateSupportedKeySystems() { } GetMediaClient()->GetSupportedKeySystems( - base::BindOnce(&KeySystemsImpl::OnSupportedKeySystemsUpdated, - weak_factory_.GetWeakPtr())); + base::BindRepeating(&KeySystemsImpl::OnSupportedKeySystemsUpdated, + weak_factory_.GetWeakPtr())); } void KeySystemsImpl::UpdateIfNeeded(base::OnceClosure done_cb) { if (is_updating_) { + // The callback will be resolved in OnSupportedKeySystemsUpdated(). update_callbacks_.AddUnsafe(std::move(done_cb)); return; } - DCHECK(update_callbacks_.empty()); - if (!IsUpdateNeeded()) { - std::move(done_cb).Run(); - return; - } - - update_callbacks_.AddUnsafe(std::move(done_cb)); - UpdateSupportedKeySystems(); -} - -bool KeySystemsImpl::IsUpToDate() { - return !is_updating_ && !IsUpdateNeeded(); + std::move(done_cb).Run(); } SupportedCodecs KeySystemsImpl::GetCodecMaskForMimeType( @@ -483,7 +466,6 @@ void KeySystemsImpl::OnSupportedKeySystemsUpdated( KeySystemPropertiesVector key_systems) { DVLOG(1) << __func__; - DCHECK(is_updating_); is_updating_ = false; // Clear Key is always supported. @@ -550,6 +532,7 @@ void KeySystemsImpl::ProcessSupportedKeySystems( const KeySystemProperties* KeySystemsImpl::GetKeySystemProperties( const std::string& key_system) const { + DCHECK(!is_updating_); for (const auto& entry : key_system_properties_map_) { const auto& base_key_system = entry.first; const auto* properties = entry.second.get(); diff --git a/chromium/media/base/key_systems.h b/chromium/media/base/key_systems.h index b13bf6d9a49..7165a179c82 100644 --- a/chromium/media/base/key_systems.h +++ b/chromium/media/base/key_systems.h @@ -35,9 +35,6 @@ class MEDIA_EXPORT KeySystems { // out of date. Calls the `done_cb` when done. virtual void UpdateIfNeeded(base::OnceClosure done_cb) = 0; - // Whether the list of available key systems is up to date. - virtual bool IsUpToDate() = 0; - // Gets the base key system name, e.g. "org.chromium.foo". virtual std::string GetBaseKeySystemName( const std::string& key_system) const = 0; diff --git a/chromium/media/base/key_systems_unittest.cc b/chromium/media/base/key_systems_unittest.cc index cd4b7924d7f..7a9b977589f 100644 --- a/chromium/media/base/key_systems_unittest.cc +++ b/chromium/media/base/key_systems_unittest.cc @@ -247,16 +247,11 @@ class TestMediaClient : public MediaClient { ~TestMediaClient() override; // MediaClient implementation. - bool IsKeySystemsUpdateNeeded() final; void GetSupportedKeySystems(GetSupportedKeySystemsCB cb) final; bool IsSupportedAudioType(const media::AudioType& type) final; bool IsSupportedVideoType(const media::VideoType& type) final; bool IsSupportedBitstreamAudioCodec(AudioCodec codec) final; - // Helper function to test the case where IsKeySystemsUpdateNeeded() is true - // after GetSupportedKeySystems() is called. - void SetKeySystemsUpdateNeeded(); - // Helper function to disable "kExternal" key system support so that we can // test the key system update case. void DisableExternalKeySystemSupport(); @@ -265,28 +260,21 @@ class TestMediaClient : public MediaClient { GetAudioRendererAlgorithmParameters(AudioParameters audio_parameters) final; private: - bool is_update_needed_ = true; + KeySystemPropertiesVector GetSupportedKeySystemsInternal(); + + GetSupportedKeySystemsCB get_supported_key_systems_cb_; bool supports_external_key_system_ = true; }; TestMediaClient::TestMediaClient() = default; TestMediaClient::~TestMediaClient() = default; -bool TestMediaClient::IsKeySystemsUpdateNeeded() { - return is_update_needed_; -} - void TestMediaClient::GetSupportedKeySystems(GetSupportedKeySystemsCB cb) { - DCHECK(is_update_needed_); - KeySystemPropertiesVector key_systems; + // Save the callback for future updates. + DCHECK(!get_supported_key_systems_cb_); + get_supported_key_systems_cb_ = cb; - key_systems.emplace_back(new AesKeySystemProperties(kUsesAes)); - - if (supports_external_key_system_) - key_systems.emplace_back(new ExternalKeySystemProperties()); - - is_update_needed_ = false; - std::move(cb).Run(std::move(key_systems)); + get_supported_key_systems_cb_.Run(GetSupportedKeySystemsInternal()); } bool TestMediaClient::IsSupportedAudioType(const media::AudioType& type) { @@ -301,12 +289,9 @@ bool TestMediaClient::IsSupportedBitstreamAudioCodec(AudioCodec codec) { return false; } -void TestMediaClient::SetKeySystemsUpdateNeeded() { - is_update_needed_ = true; -} - void TestMediaClient::DisableExternalKeySystemSupport() { supports_external_key_system_ = false; + get_supported_key_systems_cb_.Run(GetSupportedKeySystemsInternal()); } absl::optional<::media::AudioRendererAlgorithmParameters> @@ -315,6 +300,17 @@ TestMediaClient::GetAudioRendererAlgorithmParameters( return absl::nullopt; } +KeySystemPropertiesVector TestMediaClient::GetSupportedKeySystemsInternal() { + KeySystemPropertiesVector key_systems; + + key_systems.emplace_back(new AesKeySystemProperties(kUsesAes)); + + if (supports_external_key_system_) + key_systems.emplace_back(new ExternalKeySystemProperties()); + + return key_systems; +} + } // namespace class KeySystemsTest : public testing::Test { @@ -365,7 +361,6 @@ class KeySystemsTest : public testing::Test { base::RunLoop run_loop; KeySystems::GetInstance()->UpdateIfNeeded(run_loop.QuitClosure()); run_loop.Run(); - ASSERT_TRUE(KeySystems::GetInstance()->IsUpToDate()); } ~KeySystemsTest() override { @@ -376,13 +371,11 @@ class KeySystemsTest : public testing::Test { } void UpdateClientKeySystems() { - test_media_client_.SetKeySystemsUpdateNeeded(); test_media_client_.DisableExternalKeySystemSupport(); base::RunLoop run_loop; KeySystems::GetInstance()->UpdateIfNeeded(run_loop.QuitClosure()); run_loop.Run(); - ASSERT_TRUE(KeySystems::GetInstance()->IsUpToDate()); } typedef std::vector<std::string> CodecVector; diff --git a/chromium/media/base/media_client.h b/chromium/media/base/media_client.h index 7fc3ddf6112..5e8ac795f72 100644 --- a/chromium/media/base/media_client.h +++ b/chromium/media/base/media_client.h @@ -43,11 +43,6 @@ class MEDIA_EXPORT MediaClient { // Adds properties for supported key systems. virtual void GetSupportedKeySystems(GetSupportedKeySystemsCB cb) = 0; - // Returns whether client key systems properties should be updated. - // TODO(xhwang): Refactor this to a proper change "observer" API that is - // less fragile (don't assume GetSupportedKeySystems has just one caller). - virtual bool IsKeySystemsUpdateNeeded() = 0; - // Returns true if the given audio config is supported. virtual bool IsSupportedAudioType(const AudioType& type) = 0; diff --git a/chromium/media/base/media_log_events.cc b/chromium/media/base/media_log_events.cc index f6b3b1e97ec..c628a511c1b 100644 --- a/chromium/media/base/media_log_events.cc +++ b/chromium/media/base/media_log_events.cc @@ -10,37 +10,6 @@ namespace media { -std::string MediaLogEventToString(MediaLogEvent level) { - switch (level) { - case MediaLogEvent::kPlay: - return "PLAY"; - case MediaLogEvent::kPause: - return "PAUSE"; - case MediaLogEvent::kSeek: - return "SEEK"; - case MediaLogEvent::kPipelineStateChange: - return "PIPELINE_STATE_CHANGED"; - case MediaLogEvent::kWebMediaPlayerCreated: - return "WEBMEDIAPLAYER_CREATED"; - case MediaLogEvent::kWebMediaPlayerDestroyed: - return "WEBMEDIAPLAYER_DESTROYED"; - case MediaLogEvent::kLoad: - return "LOAD"; - case MediaLogEvent::kVideoSizeChanged: - return "VIDEO_SIZE_SET"; - case MediaLogEvent::kDurationChanged: - return "DURATION_SET"; - case MediaLogEvent::kEnded: - return "ENDED"; - case MediaLogEvent::kBufferingStateChanged: - return "BUFFERING_STATE_CHANGE"; - case MediaLogEvent::kSuspended: - return "SUSPENDED"; - } - NOTREACHED(); - return ""; -} - std::string TruncateUrlString(const std::string& url) { if (url.length() > kMaxUrlLength) { // Take substring and _then_ replace, to avoid copying unused data. diff --git a/chromium/media/base/media_log_events.h b/chromium/media/base/media_log_events.h index c61ff4676f6..ddf71e1f5a2 100644 --- a/chromium/media/base/media_log_events.h +++ b/chromium/media/base/media_log_events.h @@ -63,12 +63,11 @@ enum class MediaLogEvent { // The player has been suspended to save resources. kSuspended, -}; -// This has to be declared before the macros use it - Some infra code relies on -// the enum names to be UPPER_CASE, so this will convert them manually -// instead of using macro stringification. -MEDIA_EXPORT std::string MediaLogEventToString(MediaLogEvent level); + // An internal-only event that the media log sends when it is created, and + // includes a wall-clock timestamp. + kMediaLogCreated, +}; // Sometimes URLs can have encoded data that can be exteremly large. MEDIA_EXPORT std::string TruncateUrlString(const std::string& url); @@ -92,6 +91,7 @@ MEDIA_LOG_EVENT_NAMED_DATA_OP(kWebMediaPlayerCreated, std::string, "origin_url", TruncateUrlString); +MEDIA_LOG_EVENT_NAMED_DATA(kMediaLogCreated, base::Time, "created"); // Each type of buffering state gets a different name. MEDIA_LOG_EVENT_NAMED_DATA( diff --git a/chromium/media/base/media_log_properties.h b/chromium/media/base/media_log_properties.h index 3bca8a08869..ddd20e971d6 100644 --- a/chromium/media/base/media_log_properties.h +++ b/chromium/media/base/media_log_properties.h @@ -8,6 +8,7 @@ #include <string> #include <vector> +#include "base/time/time.h" #include "media/base/audio_decoder_config.h" #include "media/base/media_export.h" #include "media/base/media_log_type_enforcement.h" diff --git a/chromium/media/base/media_serializers.h b/chromium/media/base/media_serializers.h index f20a307899a..401acac1114 100644 --- a/chromium/media/base/media_serializers.h +++ b/chromium/media/base/media_serializers.h @@ -156,6 +156,16 @@ struct MediaSerializer<base::TimeDelta> { } }; +// enum (simple) +template <> +struct MediaSerializer<base::Time> { + static inline base::Value Serialize(const base::Time value) { + std::stringstream formatted; + formatted << value; + return MediaSerializer<std::string>::Serialize(formatted.str()); + } +}; + // Enum (simple) template <> struct MediaSerializer<RendererType> { diff --git a/chromium/media/base/media_switches.cc b/chromium/media/base/media_switches.cc index 71b1563c8f8..ebd93cf54a2 100644 --- a/chromium/media/base/media_switches.cc +++ b/chromium/media/base/media_switches.cc @@ -8,15 +8,12 @@ #include "build/build_config.h" #include "build/chromeos_buildflags.h" #include "components/system_media_controls/linux/buildflags/buildflags.h" +#include "media/media_buildflags.h" #if BUILDFLAG(IS_LINUX) #include "base/cpu.h" #endif -#if BUILDFLAG(IS_CHROMEOS_ASH) -#include "ash/constants/ash_features.h" -#endif - namespace switches { // Allow users to specify a custom buffer size for debugging purpose. @@ -256,10 +253,6 @@ const base::Feature kFFmpegDecodeOpaqueVP8{"FFmpegDecodeOpaqueVP8", const base::Feature kOverlayFullscreenVideo{"overlay-fullscreen-video", base::FEATURE_ENABLED_BY_DEFAULT}; -// TODO(crbug.com/1146594): Flip this to disabled in M92. -const base::Feature kEnableMediaInternals{"enable-media-internals", - base::FEATURE_ENABLED_BY_DEFAULT}; - // Enables user control over muting tab audio from the tab strip. const base::Feature kEnableTabMuting{"EnableTabMuting", base::FEATURE_DISABLED_BY_DEFAULT}; @@ -348,6 +341,27 @@ const base::Feature kCdmHostVerification{"CdmHostVerification", const base::Feature kCdmProcessSiteIsolation{"CdmProcessSiteIsolation", base::FEATURE_ENABLED_BY_DEFAULT}; +#if BUILDFLAG(CHROME_WIDE_ECHO_CANCELLATION) +// If echo cancellation for a mic signal is requested, mix and cancel all audio +// playback going to a specific output device in the audio service. +const base::Feature kChromeWideEchoCancellation{ + "ChromeWideEchoCancellation", base::FEATURE_DISABLED_BY_DEFAULT}; + +// If non-zero, audio processing is done on a dedicated processing thread which +// receives audio from the audio capture thread via a fifo of a specified size. +// Zero fifo size means the usage of such processing thread is disabled and +// processing is done on the audio capture thread itself. +const base::FeatureParam<int> kChromeWideEchoCancellationProcessingFifoSize{ + &kChromeWideEchoCancellation, "processing_fifo_size", 0}; + +// When audio processing is done in the audio process, at the renderer side IPC +// is set up to receive audio at the processing sample rate. This is a +// kill-switch to fallback to receiving audio at the default sample rate of the +// audio capture device. +const base::FeatureParam<bool> kChromeWideEchoCancellationMinimizeResampling{ + &kChromeWideEchoCancellation, "minimize_resampling", true}; +#endif + // 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. @@ -575,6 +589,17 @@ const base::Feature kLiveCaption{"LiveCaption", // tab instead" button is shown for chrome.desktopCapture captures. const base::Feature kShareThisTabInsteadButtonGetDisplayMedia{ "ShareThisTabInsteadButtonGetDisplayMedia", + base::FEATURE_DISABLED_BY_DEFAULT}; + +// If kShareThisTabInsteadButtonGetDisplayMedia is ENABLED, this flag controls +// whether a "Share this tab instead" button should be enabled for +// getDisplayMedia captures with audio. +// If kShareThisTabInsteadButtonGetDisplayMedia is DISABLED, this flag has no +// effect. +// Note: This flag does not control if the "Share this tab instead" button is +// shown for chrome.desktopCapture captures. +const base::Feature kShareThisTabInsteadButtonGetDisplayMediaAudio{ + "ShareThisTabInsteadButtonGetDisplayMediaAudio", base::FEATURE_ENABLED_BY_DEFAULT}; // Enable the Speaker Change Detection feature, which inserts a line break when @@ -609,6 +634,13 @@ const base::Feature kHardwareSecureDecryption{ const base::Feature kHardwareSecureDecryptionExperiment{ "HardwareSecureDecryptionExperiment", base::FEATURE_DISABLED_BY_DEFAULT}; +// Allows automatically disabling hardware secure Content Decryption Module +// (CDM) after failures or crashes to fallback to software secure CDMs. If this +// feature is disabled, the fallback will never happen and users could be stuck +// in playback failures. +const base::Feature kHardwareSecureDecryptionFallback{ + "HardwareSecureDecryptionFallback", base::FEATURE_ENABLED_BY_DEFAULT}; + const base::Feature kWakeLockOptimisationHiddenMuted{ "kWakeLockOptimisationHiddenMuted", base::FEATURE_ENABLED_BY_DEFAULT}; @@ -729,6 +761,14 @@ const base::Feature kUseRealColorSpaceForAndroidVideo{ const base::Feature kUseChromeOSDirectVideoDecoder{ "UseChromeOSDirectVideoDecoder", base::FEATURE_ENABLED_BY_DEFAULT}; +#if defined(ARCH_CPU_ARM_FAMILY) +// Some architectures have separate image processor hardware that +// can be used by Chromium's ImageProcessor to color convert/crop/etc. +// video buffers. Sometimes it is more efficient/performant/correct +// to use libYUV instead of the hardware to do this processing. +const base::Feature kPreferLibYuvImageProcessor{ + "prefer-libyuv-image-processor", base::FEATURE_DISABLED_BY_DEFAULT}; +#endif // defined(ARCH_CPU_ARM_FAMILY) #if BUILDFLAG(IS_CHROMEOS) // ChromeOS has one of two VideoDecoder implementations active based on // SoC/board specific configurations that are sent via command line flags. This @@ -741,11 +781,17 @@ const base::Feature kUseAlternateVideoDecoderImplementation{ #endif // BUILDFLAG(USE_CHROMEOS_MEDIA_ACCELERATION) #if BUILDFLAG(IS_MAC) + +#if BUILDFLAG(ENABLE_PLATFORM_HEVC_DECODING) +const base::Feature kVideoToolboxHEVCDecoding{ + "VideoToolboxHEVCDecoding", base::FEATURE_DISABLED_BY_DEFAULT}; +#endif // BUILDFLAG(ENABLE_PLATFORM_HEVC_DECODING) + // Enable binding multiple shared images to a single GpuMemoryBuffer for // accelerated video decode using VideoToolbox. const base::Feature kMultiPlaneVideoToolboxSharedImages{ "MultiPlaneVideoToolboxSharedImages", base::FEATURE_ENABLED_BY_DEFAULT}; -#endif +#endif // BUILDFLAG(IS_MAC) #if BUILDFLAG(IS_WIN) // Does NV12->NV12 video copy on the main thread right before the texture's @@ -768,11 +814,19 @@ const base::Feature kIncludeIRCamerasInDeviceEnumeration{ const base::Feature MEDIA_EXPORT kMediaFoundationAV1Encoding{ "MediaFoundationAV1Encoding", base::FEATURE_DISABLED_BY_DEFAULT}; +// Enables H.264 CBP encode acceleration for Windows. +// For feature check of kMediaFoundationH264CbpEncoding at runtime, +// please use IsMediaFoundationH264CbpEncodingEnabled() instead. +const base::Feature MEDIA_EXPORT kMediaFoundationH264CbpEncoding{ + "MediaFoundationH264CbpEncoding", base::FEATURE_DISABLED_BY_DEFAULT}; + // Enables MediaFoundation based video capture const base::Feature kMediaFoundationVideoCapture{ "MediaFoundationVideoCapture", base::FEATURE_ENABLED_BY_DEFAULT}; // Enables MediaFoundation based video capture with D3D11 +// For feature check of kMediaFoundationD3D11VideoCapture at runtime, +// please use IsMediaFoundationD3D11VideoCaptureEnabled() instead. const base::Feature kMediaFoundationD3D11VideoCapture{ "MediaFoundationD3D11VideoCapture", base::FEATURE_DISABLED_BY_DEFAULT}; @@ -809,6 +863,13 @@ const base::Feature MEDIA_EXPORT kDeprecateLowUsageCodecs{ "DeprecateLowUsageCodecs", base::FEATURE_ENABLED_BY_DEFAULT}; #endif // BUILDFLAG(IS_CHROMEOS) +#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) +// Spawn utility processes to perform hardware decode acceleration instead of +// using the GPU process. +const base::Feature MEDIA_EXPORT kUseOutOfProcessVideoDecoding{ + "UseOutOfProcessVideoDecoding", base::FEATURE_DISABLED_BY_DEFAULT}; +#endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) + std::string GetEffectiveAutoplayPolicy(const base::CommandLine& command_line) { // Return the autoplay policy set in the command line, if any. if (command_line.HasSwitch(switches::kAutoplayPolicy)) @@ -931,38 +992,19 @@ const base::Feature kBresenhamCadence{"BresenhamCadence", const base::Feature kPlaybackSpeedButton{"PlaybackSpeedButton", base::FEATURE_ENABLED_BY_DEFAULT}; +bool IsChromeWideEchoCancellationEnabled() { +#if BUILDFLAG(CHROME_WIDE_ECHO_CANCELLATION) + return base::FeatureList::IsEnabled(kChromeWideEchoCancellation); +#else + return false; +#endif +} + bool IsHardwareSecureDecryptionEnabled() { return base::FeatureList::IsEnabled(kHardwareSecureDecryption) || base::FeatureList::IsEnabled(kHardwareSecureDecryptionExperiment); } -bool IsLiveCaptionFeatureEnabled() { - if (!base::FeatureList::IsEnabled(media::kLiveCaption)) - return false; - -#if BUILDFLAG(IS_CHROMEOS_ASH) - // Some Chrome OS devices do not support on-device speech. - if (!base::FeatureList::IsEnabled(ash::features::kOnDeviceSpeechRecognition)) - return false; -#endif - -#if BUILDFLAG(IS_LINUX) - // Check if the CPU has the required instruction set to run the Speech - // On-Device API (SODA) library. - static bool has_sse41 = base::CPU().has_sse41(); - if (!has_sse41) - return false; -#endif - -#if BUILDFLAG(IS_WIN) && defined(ARCH_CPU_ARM64) - // The Speech On-Device API (SODA) component does not support Windows on - // arm64. - return false; -#else - return true; -#endif -} - bool IsVideoCaptureAcceleratedJpegDecodingEnabled() { if (base::CommandLine::ForCurrentProcess()->HasSwitch( switches::kDisableAcceleratedMjpegDecode)) { @@ -979,4 +1021,14 @@ bool IsVideoCaptureAcceleratedJpegDecodingEnabled() { #endif } +#if BUILDFLAG(IS_WIN) +bool IsMediaFoundationH264CbpEncodingEnabled() { + return base::FeatureList::IsEnabled(kMediaFoundationH264CbpEncoding); +} + +bool IsMediaFoundationD3D11VideoCaptureEnabled() { + return base::FeatureList::IsEnabled(kMediaFoundationD3D11VideoCapture); +} +#endif + } // namespace media diff --git a/chromium/media/base/media_switches.h b/chromium/media/base/media_switches.h index 92087150b55..c6715ac3cec 100644 --- a/chromium/media/base/media_switches.h +++ b/chromium/media/base/media_switches.h @@ -125,8 +125,14 @@ 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; +#if BUILDFLAG(CHROME_WIDE_ECHO_CANCELLATION) +MEDIA_EXPORT extern const base::Feature kChromeWideEchoCancellation; +MEDIA_EXPORT extern const base::FeatureParam<int> + kChromeWideEchoCancellationProcessingFifoSize; +MEDIA_EXPORT extern const base::FeatureParam<bool> + kChromeWideEchoCancellationMinimizeResampling; +#endif MEDIA_EXPORT extern const base::Feature kD3D11VideoDecoderUseSharedHandle; -MEDIA_EXPORT extern const base::Feature kEnableMediaInternals; MEDIA_EXPORT extern const base::Feature kEnableTabMuting; MEDIA_EXPORT extern const base::Feature kExposeSwDecodersToWebRTC; MEDIA_EXPORT extern const base::Feature kExternalClearKeyForTesting; @@ -143,6 +149,7 @@ MEDIA_EXPORT extern const base::Feature kGlobalMediaControlsModernUI; MEDIA_EXPORT extern const base::Feature kHardwareMediaKeyHandling; MEDIA_EXPORT extern const base::Feature kHardwareSecureDecryption; MEDIA_EXPORT extern const base::Feature kHardwareSecureDecryptionExperiment; +MEDIA_EXPORT extern const base::Feature kHardwareSecureDecryptionFallback; MEDIA_EXPORT extern const base::Feature kInternalMediaSession; MEDIA_EXPORT extern const base::Feature kKeepRvfcFrameAlive; MEDIA_EXPORT extern const base::Feature kKeyPressMonitoring; @@ -176,6 +183,8 @@ MEDIA_EXPORT extern const base::Feature kReuseMediaPlayer; MEDIA_EXPORT extern const base::Feature kRevokeMediaSourceObjectURLOnAttach; MEDIA_EXPORT extern const base::Feature kShareThisTabInsteadButtonGetDisplayMedia; +MEDIA_EXPORT extern const base::Feature + kShareThisTabInsteadButtonGetDisplayMediaAudio; MEDIA_EXPORT extern const base::Feature kSpeakerChangeDetection; MEDIA_EXPORT extern const base::Feature kSpecCompliantCanPlayThrough; MEDIA_EXPORT extern const base::Feature kSurfaceLayerForMediaStreams; @@ -227,24 +236,38 @@ MEDIA_EXPORT extern const base::Feature kUseRealColorSpaceForAndroidVideo; #if BUILDFLAG(USE_CHROMEOS_MEDIA_ACCELERATION) MEDIA_EXPORT extern const base::Feature kUseChromeOSDirectVideoDecoder; - +#if defined(ARCH_CPU_ARM_FAMILY) +MEDIA_EXPORT extern const base::Feature kPreferLibYuvImageProcessor; +#endif // defined(ARCH_CPU_ARM_FAMILY) #if BUILDFLAG(IS_CHROMEOS) MEDIA_EXPORT extern const base::Feature kUseAlternateVideoDecoderImplementation; #endif // BUILDFLAG(IS_CHROMEOS) #endif // BUILDFLAG(USE_CHROMEOS_MEDIA_ACCELERATION) #if BUILDFLAG(IS_MAC) +#if BUILDFLAG(ENABLE_PLATFORM_HEVC_DECODING) +MEDIA_EXPORT extern const base::Feature kVideoToolboxHEVCDecoding; +#endif // BUILDFLAG(ENABLE_PLATFORM_HEVC_DECODING) MEDIA_EXPORT extern const base::Feature kMultiPlaneVideoToolboxSharedImages; -#endif +#endif // BUILDFLAG(IS_MAC) #if BUILDFLAG(IS_WIN) MEDIA_EXPORT extern const base::Feature kDelayCopyNV12Textures; MEDIA_EXPORT extern const base::Feature kDirectShowGetPhotoState; MEDIA_EXPORT extern const base::Feature kIncludeIRCamerasInDeviceEnumeration; MEDIA_EXPORT extern const base::Feature kMediaFoundationAV1Encoding; + +// For feature check of kMediaFoundationH264CbpEncoding at runtime, +// please use IsMediaFoundationH264CbpEncodingEnabled() instead. +MEDIA_EXPORT extern const base::Feature kMediaFoundationH264CbpEncoding; + MEDIA_EXPORT extern const base::Feature kMediaFoundationVideoCapture; MEDIA_EXPORT extern const base::Feature kMediaFoundationVP8Decoding; + +// For feature check of kMediaFoundationD3D11VideoCapture at runtime, +// please use IsMediaFoundationD3D11VideoCaptureEnabled() instead. MEDIA_EXPORT extern const base::Feature kMediaFoundationD3D11VideoCapture; + MEDIA_EXPORT extern const base::Feature kMediaFoundationClearPlayback; MEDIA_EXPORT extern const base::Feature kWasapiRawAudioCapture; MEDIA_EXPORT extern const base::Feature kD3D11HEVCDecoding; @@ -255,6 +278,10 @@ MEDIA_EXPORT extern const base::Feature kD3D11Vp9kSVCHWDecoding; MEDIA_EXPORT extern const base::Feature kDeprecateLowUsageCodecs; #endif +#if BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) +MEDIA_EXPORT extern const base::Feature kUseOutOfProcessVideoDecoding; +#endif // BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) + // Based on a |command_line| and the current platform, returns the effective // autoplay policy. In other words, it will take into account the default policy // if none is specified via the command line and options passed for testing. @@ -263,10 +290,15 @@ MEDIA_EXPORT extern const base::Feature kDeprecateLowUsageCodecs; MEDIA_EXPORT std::string GetEffectiveAutoplayPolicy( const base::CommandLine& command_line); +MEDIA_EXPORT bool IsChromeWideEchoCancellationEnabled(); MEDIA_EXPORT bool IsHardwareSecureDecryptionEnabled(); -MEDIA_EXPORT bool IsLiveCaptionFeatureEnabled(); MEDIA_EXPORT bool IsVideoCaptureAcceleratedJpegDecodingEnabled(); +#if BUILDFLAG(IS_WIN) +MEDIA_EXPORT bool IsMediaFoundationH264CbpEncodingEnabled(); +MEDIA_EXPORT bool IsMediaFoundationD3D11VideoCaptureEnabled(); +#endif + enum class kCrosGlobalMediaControlsPinOptions { kPin, kNotPin, diff --git a/chromium/media/base/mime_util_unittest.cc b/chromium/media/base/mime_util_unittest.cc index 7ebc35762e0..8137fbc7d5b 100644 --- a/chromium/media/base/mime_util_unittest.cc +++ b/chromium/media/base/mime_util_unittest.cc @@ -2,9 +2,10 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +#include "media/base/mime_util.h" + #include <stddef.h> -#include "base/cxx17_backports.h" #include "base/strings/string_split.h" #include "base/strings/stringprintf.h" #include "base/test/scoped_command_line.h" @@ -12,7 +13,6 @@ #include "media/base/audio_codecs.h" #include "media/base/media.h" #include "media/base/media_switches.h" -#include "media/base/mime_util.h" #include "media/base/mime_util_internal.h" #include "media/base/video_codecs.h" #include "media/base/video_color_space.h" @@ -53,8 +53,7 @@ static std::vector<bool> CreateTestVector(bool test_all_values, bool single_value) { const bool kTestStates[] = {true, false}; if (test_all_values) - return std::vector<bool>(kTestStates, - kTestStates + base::size(kTestStates)); + return std::vector<bool>(kTestStates, kTestStates + std::size(kTestStates)); return std::vector<bool>(1, single_value); } @@ -212,7 +211,7 @@ TEST(MimeUtilTest, SplitAndStripCodecs) { {",", 2, {"", ""}, {"", ""}}, }; - for (size_t i = 0; i < base::size(tests); ++i) { + for (size_t i = 0; i < std::size(tests); ++i) { std::vector<std::string> codecs_out; SplitCodecs(tests[i].original, &codecs_out); diff --git a/chromium/media/base/mock_filters.cc b/chromium/media/base/mock_filters.cc index e1658c63468..3ab836a646c 100644 --- a/chromium/media/base/mock_filters.cc +++ b/chromium/media/base/mock_filters.cc @@ -33,8 +33,7 @@ std::string MockDemuxer::GetDisplayName() const { return "MockDemuxer"; } -MockDemuxerStream::MockDemuxerStream(DemuxerStream::Type type) - : type_(type), liveness_(LIVENESS_UNKNOWN) {} +MockDemuxerStream::MockDemuxerStream(DemuxerStream::Type type) : type_(type) {} MockDemuxerStream::~MockDemuxerStream() = default; @@ -42,7 +41,7 @@ DemuxerStream::Type MockDemuxerStream::type() const { return type_; } -DemuxerStream::Liveness MockDemuxerStream::liveness() const { +StreamLiveness MockDemuxerStream::liveness() const { return liveness_; } @@ -68,7 +67,7 @@ void MockDemuxerStream::set_video_decoder_config( video_decoder_config_ = config; } -void MockDemuxerStream::set_liveness(DemuxerStream::Liveness liveness) { +void MockDemuxerStream::set_liveness(StreamLiveness liveness) { liveness_ = liveness; } diff --git a/chromium/media/base/mock_filters.h b/chromium/media/base/mock_filters.h index dbc853ccced..31f3dbe4948 100644 --- a/chromium/media/base/mock_filters.h +++ b/chromium/media/base/mock_filters.h @@ -202,8 +202,8 @@ class MockDemuxerStream : public DemuxerStream { // DemuxerStream implementation. Type type() const override; - Liveness liveness() const override; - void Read(ReadCB read_cb) { OnRead(read_cb); } + StreamLiveness liveness() const override; + void Read(ReadCB read_cb) override { OnRead(read_cb); } MOCK_METHOD1(OnRead, void(ReadCB& read_cb)); AudioDecoderConfig audio_decoder_config() override; VideoDecoderConfig video_decoder_config() override; @@ -212,11 +212,11 @@ class MockDemuxerStream : public DemuxerStream { void set_audio_decoder_config(const AudioDecoderConfig& config); void set_video_decoder_config(const VideoDecoderConfig& config); - void set_liveness(Liveness liveness); + void set_liveness(StreamLiveness liveness); private: Type type_; - Liveness liveness_; + StreamLiveness liveness_ = StreamLiveness::kUnknown; AudioDecoderConfig audio_decoder_config_; VideoDecoderConfig video_decoder_config_; }; @@ -658,8 +658,8 @@ class MockCdmContext : public CdmContext { #if BUILDFLAG(IS_WIN) MOCK_METHOD0(RequiresMediaFoundationRenderer, bool()); - MOCK_METHOD1(GetMediaFoundationCdmProxy, - bool(GetMediaFoundationCdmProxyCB get_mf_cdm_proxy_cb)); + MOCK_METHOD0(GetMediaFoundationCdmProxy, + scoped_refptr<MediaFoundationCdmProxy>()); #endif #if BUILDFLAG(IS_CHROMEOS_ASH) MOCK_METHOD0(GetChromeOsCdmContext, chromeos::ChromeOsCdmContext*()); @@ -858,7 +858,6 @@ class MockMediaClient : public media::MediaClient { // MediaClient implementation. MOCK_METHOD1(GetSupportedKeySystems, void(GetSupportedKeySystemsCB cb)); - MOCK_METHOD0(IsKeySystemsUpdateNeeded, bool()); MOCK_METHOD1(IsSupportedAudioType, bool(const media::AudioType& type)); MOCK_METHOD1(IsSupportedVideoType, bool(const media::VideoType& type)); MOCK_METHOD1(IsSupportedBitstreamAudioCodec, bool(media::AudioCodec codec)); diff --git a/chromium/media/base/null_video_sink.h b/chromium/media/base/null_video_sink.h index f113e09286a..28ddf2a6043 100644 --- a/chromium/media/base/null_video_sink.h +++ b/chromium/media/base/null_video_sink.h @@ -9,6 +9,7 @@ #include "base/memory/raw_ptr.h" #include "base/time/default_tick_clock.h" #include "base/time/tick_clock.h" +#include "base/time/time.h" #include "media/base/media_export.h" #include "media/base/video_renderer_sink.h" diff --git a/chromium/media/base/null_video_sink_unittest.cc b/chromium/media/base/null_video_sink_unittest.cc index cbb954f27ac..cc89d6fa45e 100644 --- a/chromium/media/base/null_video_sink_unittest.cc +++ b/chromium/media/base/null_video_sink_unittest.cc @@ -9,6 +9,7 @@ #include "base/test/gmock_callback_support.h" #include "base/test/simple_test_tick_clock.h" #include "base/test/task_environment.h" +#include "base/time/time.h" #include "components/viz/common/frame_sinks/begin_frame_args.h" #include "media/base/null_video_sink.h" #include "media/base/test_helpers.h" diff --git a/chromium/media/base/offloading_audio_encoder_unittest.cc b/chromium/media/base/offloading_audio_encoder_unittest.cc index 467ce4174e7..39c2719ac85 100644 --- a/chromium/media/base/offloading_audio_encoder_unittest.cc +++ b/chromium/media/base/offloading_audio_encoder_unittest.cc @@ -14,6 +14,7 @@ #include "base/test/bind.h" #include "base/test/gmock_callback_support.h" #include "base/test/task_environment.h" +#include "base/time/time.h" #include "media/base/media_util.h" #include "media/base/mock_filters.h" #include "media/base/offloading_audio_encoder.h" diff --git a/chromium/media/base/pipeline_impl.h b/chromium/media/base/pipeline_impl.h index d88da084f35..6262fa9bbcc 100644 --- a/chromium/media/base/pipeline_impl.h +++ b/chromium/media/base/pipeline_impl.h @@ -11,6 +11,7 @@ #include "base/memory/ref_counted.h" #include "base/memory/weak_ptr.h" #include "base/threading/thread_checker.h" +#include "base/time/time.h" #include "media/base/media_export.h" #include "media/base/pipeline.h" #include "media/base/renderer.h" diff --git a/chromium/media/base/pipeline_impl_unittest.cc b/chromium/media/base/pipeline_impl_unittest.cc index 07c95300f21..c9f047b0cb8 100644 --- a/chromium/media/base/pipeline_impl_unittest.cc +++ b/chromium/media/base/pipeline_impl_unittest.cc @@ -20,6 +20,7 @@ #include "base/threading/simple_thread.h" #include "base/threading/thread_task_runner_handle.h" #include "base/time/clock.h" +#include "base/time/time.h" #include "media/base/fake_text_track_stream.h" #include "media/base/media_util.h" #include "media/base/mock_filters.h" diff --git a/chromium/media/base/renderer_factory_selector.h b/chromium/media/base/renderer_factory_selector.h index bc83cf8260c..8be6f06500e 100644 --- a/chromium/media/base/renderer_factory_selector.h +++ b/chromium/media/base/renderer_factory_selector.h @@ -66,7 +66,7 @@ class MEDIA_EXPORT RendererFactorySelector { RendererFactorySelector(const RendererFactorySelector&) = delete; RendererFactorySelector& operator=(const RendererFactorySelector&) = delete; - ~RendererFactorySelector(); + virtual ~RendererFactorySelector(); // See file level comments above. void AddBaseFactory(RendererType type, @@ -85,11 +85,11 @@ class MEDIA_EXPORT RendererFactorySelector { // Returns the type of the Renderer for what GetCurrentFactory() would return. // NOTE: SetBaseRendererType() must be called before calling this method. - RendererType GetCurrentRendererType(); + virtual RendererType GetCurrentRendererType(); // Updates |current_factory_| if necessary, and returns its value. // NOTE: SetBaseRendererType() must be called before calling this method. - RendererFactory* GetCurrentFactory(); + virtual RendererFactory* GetCurrentFactory(); #if BUILDFLAG(IS_ANDROID) // Starts a request to receive a RemotePlayStateChangeCB, to be fulfilled diff --git a/chromium/media/base/seekable_buffer_unittest.cc b/chromium/media/base/seekable_buffer_unittest.cc index d1df6a3ca9b..df18af5d516 100644 --- a/chromium/media/base/seekable_buffer_unittest.cc +++ b/chromium/media/base/seekable_buffer_unittest.cc @@ -9,7 +9,6 @@ #include <cstdlib> -#include "base/cxx17_backports.h" #include "base/time/time.h" #include "media/base/data_buffer.h" #include "media/base/timestamp_constants.h" @@ -337,7 +336,7 @@ TEST_F(SeekableBufferTest, GetTime) { scoped_refptr<DataBuffer> buffer = DataBuffer::CopyFrom(data_, kWriteSize); - for (size_t i = 0; i < base::size(tests); ++i) { + for (size_t i = 0; i < std::size(tests); ++i) { buffer->set_timestamp(base::Microseconds(tests[i].first_time_useconds)); buffer->set_duration(base::Microseconds(tests[i].duration_useconds)); buffer_.Append(buffer.get()); diff --git a/chromium/media/base/status.h b/chromium/media/base/status.h index 155db110a04..abcffbc394b 100644 --- a/chromium/media/base/status.h +++ b/chromium/media/base/status.h @@ -50,6 +50,14 @@ using UKMPackedType = uint64_t; namespace internal { +template <typename T> +struct SecondArgType {}; + +template <typename R, typename A1, typename A2> +struct SecondArgType<R(A1, A2)> { + using Type = A2; +}; + union UKMPackHelper { struct bits { uint16_t group; @@ -224,20 +232,70 @@ class MEDIA_EXPORT TypedStatus { using Traits = T; using Codes = typename T::Codes; - // default constructor to please the Mojo Gods. - TypedStatus() = default; + // See media/base/status.md for the ways that an instantiation of TypedStatus + // can be constructed, since there are a few. + + // Default constructor to please the Mojo Gods. + TypedStatus() : data_(nullptr) {} + + // Copy constructor (also as a sacrifice to Lord Mojo) + TypedStatus(const TypedStatus<T>& copy) { *this = copy; } - // For TypedStatus(OkStatus()) + // Special constructor use by OkStatus() to implicitly be cast to any required + // status type. TypedStatus(const internal::OkStatusImplicitConstructionHelper&) : TypedStatus(Codes::kOk) {} + // Used to implicitly create a TypedStatus from a TypedStatus::Codes value. + TypedStatus(Codes code, + const base::Location& location = base::Location::Current()) + : TypedStatus(code, "", location) {} + + TypedStatus(std::tuple<Codes, base::StringPiece> pack, + const base::Location& location = base::Location::Current()) + : TypedStatus(std::get<0>(pack), std::get<1>(pack), location) {} + + // Used to allow returning {TypedStatus::Codes::kValue, CastFrom} implicitly + // iff TypedStatus::Traits::OnCreateFrom is implemented. + template < + typename _T = Traits, + typename = std::enable_if<std::is_pointer_v<decltype(&_T::OnCreateFrom)>>> + TypedStatus( + Codes code, + const typename internal::SecondArgType<decltype(_T::OnCreateFrom)>::Type& + data, + const base::Location& location = base::Location::Current()) + : TypedStatus(code, "", location) { + // TODO(tmathmeyer) I think we can make this dcheck a static assert. + DCHECK(data_); + Traits::OnCreateFrom(this, data); + } + + // Used to allow returning {TypedStatus::Codes::kValue, "message", CastFrom} + // implicitly iff TypedStatus::Traits::OnCreateFrom is implemented. + template < + typename _T = Traits, + typename = std::enable_if<std::is_pointer_v<decltype(&_T::OnCreateFrom)>>> + TypedStatus( + Codes code, + base::StringPiece message, + const typename internal::SecondArgType<decltype(_T::OnCreateFrom)>::Type& + data, + const base::Location& location = base::Location::Current()) + : TypedStatus(code, message, location) { + DCHECK(data_); + Traits::OnCreateFrom(this, data); + } + // Constructor to create a new TypedStatus from a numeric code & message. // These are immutable; if you'd like to change them, then you likely should // create a new TypedStatus. // NOTE: This should never be given a location parameter when called - It is // defaulted in order to grab the caller location. + // Also used to allow returning {TypedStatus::Codes::kValue, "message"} + // implicitly as a typed status. TypedStatus(Codes code, - base::StringPiece message = "", + base::StringPiece message, const base::Location& location = base::Location::Current()) { // Note that |message| would be dropped when code is the default value, // so DCHECK that it is not set. @@ -251,8 +309,6 @@ class MEDIA_EXPORT TypedStatus { data_->AddLocation(location); } - TypedStatus(const TypedStatus<T>& copy) { *this = copy; } - TypedStatus<T>& operator=(const TypedStatus<T>& copy) { if (!copy.data_) { data_.reset(); @@ -384,24 +440,38 @@ class MEDIA_EXPORT TypedStatus { ~Or() = default; - // Implicit constructors allow returning |OtherType| or |TypedStatus| - // directly. + // Create an Or type implicitly from a TypedStatus Or(TypedStatus<T>&& error) : error_(std::move(error)) { // `error_` must not be `kOk`, if there is such a value. DCHECK(!error_->is_ok()); } + Or(const TypedStatus<T>& error) : error_(error) { DCHECK(!error_->is_ok()); } + // Create an Or type implicitly from the alternate OtherType. Or(OtherType&& value) : value_(std::move(value)) {} Or(const OtherType& value) : value_(value) {} + + // Create an Or type explicitly from a code Or(typename T::Codes code, const base::Location& location = base::Location::Current()) : error_(TypedStatus<T>(code, "", location)) { DCHECK(!error_->is_ok()); } + // Create an Or type implicitly from any brace-initializer list that could + // have been used to create the typed status + template <typename First, typename... Rest> + Or(typename T::Codes code, + const First& first, + const Rest&... rest, + const base::Location& location = base::Location::Current()) + : error_(TypedStatus<T>(code, first, rest..., location)) { + DCHECK(!error_->is_ok()); + } + // Move- and copy- construction and assignment are okay. Or(const Or&) = default; Or(Or&&) = default; diff --git a/chromium/media/base/status.md b/chromium/media/base/status.md index deb5b06ee2c..288e9d5791d 100644 --- a/chromium/media/base/status.md +++ b/chromium/media/base/status.md @@ -5,32 +5,52 @@ enums that support causality tracking, data attachment, and general assistance with debugging, without adding slowdowns due to returning large structs, pointers, or more complicated types. -TypedStatus<T> should be instantiated with a traits struct that defines: - - Codes - enum (usually enum class) that would be the return type, if we weren't - using TypedStatus. - static constexpr StatusGroupType Group() { return "NameOfStatus"; } - - // If DefaultEnumValue is present, then it returns the code that should be - // treated as the common, optimized case. Generally, this is the "success" - // case, unless you are unlucky. This function can be omitted if you do not - // want any of the codes to be optimized. - static constexpr Codes DefaultEnumValue() { - return Codes::kCodeThatShouldBeSuperOptimized; +A use-every-feature example: +```c++ +struct MyExampleStatusTraits { + // [REQUIRED] Declare your enum + enum class Codes : StatusCodeType { + kSomething = 9090, + kAnotherThing = 92, + kAThirdThing = 458, + kAFinalThing = 438, + }; + + // [REQUIRED] Declare your group name + static constexpr StatusGroupType Group() { return "MyExampleStatus"; } + + // [OPTIONAL] Declare your "default" code. If this method is defined, + // then the function OkStatus() can be used to return a status with this + // code. Statuses created with this default code can not have any data, + // causes, or a message attached. + static constexpr Codes DefaultEnumValue() { return Codes::kSomething; } + + // [OPTIONAL] If |OnCreateFrom| is declared, then TypedStatus<T> can be + // created with {T::Codes, SomeOtherType} or {T::Codes, string, SomeOtherType} + // The pre-created TypedStatus is passed into this method for additional + // manipulation. + static void OnCreateFrom(TypedStatus<MyExampleStatusTraits>* impl, + const SomeOtherType& t) { + impl->WithData("key", SomeOtherTypeToString(t)); } -Typically one would: + // [OPTIONAL] If you'd like to be able to send your status to UKM, declare + // this method in your traits. This allows you to pack any part of the + // status internal data into a single ukm-ready uint32. + static uint32_t PackExtraData(const internal::StatusData& data) { + return 0; + } +}; - struct MyStatusTraits { ... }; - using MyStatus = TypedStatus<MyStatusTraits>; +// Typically, you'd want to redefine your template instantiation, like this. +using MyExampleStatus = TypedStatus<MyExampleStatusTraits>; -## Using an existing `TypedStatus<T>` +``` -The current canonical TypedStatus is called `Status` for historical reasons, -though that will soon change. -All TypedStatus specializations have the following common API: +## Using an existing `TypedStatus<T>` +All TypedStatus specializations have the following common API: ```c++ // The underlying code value. T::Codes code() const; @@ -78,8 +98,6 @@ Define an |TypedStatusTraits|, picking a name for the group of codes: ```c++ struct MyExampleStatusTraits { - // If you do not have an existing enum, you can `enum class Codes { ... };` - // here, instead of `using`. using Codes = MyExampleEnum; static constexpr StatusGroupType Group() { return "MyExampleStatus"; } static constexpr Codes DefaultEnumValue() { return Codes::kDefaultValue; } @@ -107,6 +125,9 @@ int main() { } ``` + +## TypedStatus<T>::Or<D> + For the common case where you'd like to return some constructed thing OR an error type, we've also created `TypedStatus<T>::Or<D>`. diff --git a/chromium/media/base/status_unittest.cc b/chromium/media/base/status_unittest.cc index 60eba31436b..f49bbb66c17 100644 --- a/chromium/media/base/status_unittest.cc +++ b/chromium/media/base/status_unittest.cc @@ -68,6 +68,22 @@ struct TraitsWithCustomUKMSerializer { } }; +struct TraitsWithDataPacking { + enum class Codes { kOk, kFail }; + struct PackThis { + int a; + int b; + std::string c; + }; + static constexpr StatusGroupType Group() { return "GroupWithDataPacking"; } + static void OnCreateFrom(TypedStatus<TraitsWithDataPacking>* status, + const PackThis& data) { + status->WithData("DataA", data.a); + status->WithData("DataB", data.b); + status->WithData("DataC", data.c); + } +}; + class StatusTest : public testing::Test { public: using NormalStatus = TypedStatus<ZeroValueOkTypeTraits>; @@ -149,6 +165,57 @@ class StatusTest : public testing::Test { } }; +TEST_F(StatusTest, DifferentModesOfConstruction) { + // Can construct any type with OkStatus + NormalStatus ok = OkStatus(); + ASSERT_TRUE(ok.is_ok()); + + // Can construct implicitly from a code + NormalStatus ok2 = NormalStatus::Codes::kOk; + ASSERT_TRUE(ok.is_ok()); + + // Can construct implicitly from a {code, message} braced initializer. + NormalStatus foo = {NormalStatus::Codes::kFoo, "msg"}; + ASSERT_EQ(foo.code(), NormalStatus::Codes::kFoo); + ASSERT_EQ(foo.message(), "msg"); + + // Can construct explicitly from a code and message + NormalStatus foo2 = NormalStatus(NormalStatus::Codes::kFoo, "msg2"); + ASSERT_EQ(foo2.code(), NormalStatus::Codes::kFoo); + ASSERT_EQ(foo2.message(), "msg2"); + + using PackingStatus = TypedStatus<TraitsWithDataPacking>; + TraitsWithDataPacking::PackThis data = {7, 3, "apple pie"}; + + // Can construct implicitly from a {code, data} for a type with OnCreateFrom + // in it's traits + PackingStatus packed = {PackingStatus::Codes::kFail, data}; + ASSERT_EQ(packed.code(), PackingStatus::Codes::kFail); + ASSERT_EQ(packed.message(), ""); + // Keep serialized around, accessing |data| from it inline causes it + // to be destructed and |unpacked| to be used after being freed. + auto serialized = MediaSerialize(packed); + auto* unpacked = serialized.FindDictPath("data"); + ASSERT_NE(unpacked, nullptr); + ASSERT_EQ(unpacked->DictSize(), 3ul); + ASSERT_EQ(unpacked->FindIntPath("DataA"), 7); + ASSERT_EQ(unpacked->FindIntPath("DataB"), 3); + ASSERT_EQ(*unpacked->FindStringPath("DataC"), "apple pie"); + + // Can construct implicitly from a {code, "message", data} for a type with + // OnCreateFrom in it's traits + PackingStatus packed2 = {PackingStatus::Codes::kFail, "*explosion*", data}; + ASSERT_EQ(packed2.code(), PackingStatus::Codes::kFail); + ASSERT_EQ(packed2.message(), "*explosion*"); + serialized = MediaSerialize(packed); + unpacked = serialized.FindDictPath("data"); + ASSERT_NE(unpacked, nullptr); + ASSERT_EQ(unpacked->DictSize(), 3ul); + ASSERT_EQ(unpacked->FindIntPath("DataA"), 7); + ASSERT_EQ(unpacked->FindIntPath("DataB"), 3); + ASSERT_EQ(*unpacked->FindStringPath("DataC"), "apple pie"); +} + TEST_F(StatusTest, StaticOKMethodGivesCorrectSerialization) { NormalStatus ok = DontFail(); base::Value actual = MediaSerialize(ok); diff --git a/chromium/media/base/stream_parser.cc b/chromium/media/base/stream_parser.cc index eeaf07616f0..904e16fe32d 100644 --- a/chromium/media/base/stream_parser.cc +++ b/chromium/media/base/stream_parser.cc @@ -10,7 +10,6 @@ namespace media { StreamParser::InitParameters::InitParameters(base::TimeDelta duration) : duration(duration), - liveness(DemuxerStream::LIVENESS_UNKNOWN), detected_audio_track_count(0), detected_video_track_count(0), detected_text_track_count(0) {} diff --git a/chromium/media/base/stream_parser.h b/chromium/media/base/stream_parser.h index 63a81d98ee4..4a0b0cae194 100644 --- a/chromium/media/base/stream_parser.h +++ b/chromium/media/base/stream_parser.h @@ -60,7 +60,7 @@ class MEDIA_EXPORT StreamParser { base::Time timeline_offset; // Indicates live stream. - DemuxerStream::Liveness liveness; + StreamLiveness liveness = StreamLiveness::kUnknown; // Counts of tracks detected by type within this stream. Not all of these // tracks may be selected for use by the parser. diff --git a/chromium/media/base/supported_types.cc b/chromium/media/base/supported_types.cc index e45abab5c2d..41a4609a2a7 100644 --- a/chromium/media/base/supported_types.cc +++ b/chromium/media/base/supported_types.cc @@ -7,6 +7,7 @@ #include "base/command_line.h" #include "base/feature_list.h" #include "base/logging.h" +#include "base/no_destructor.h" #include "base/notreached.h" #include "build/build_config.h" #include "build/chromeos_buildflags.h" @@ -36,6 +37,28 @@ namespace media { namespace { +class SupplementalProfileCache { + public: + void UpdateCache(const base::flat_set<media::VideoCodecProfile>& profiles) { + base::AutoLock lock(profiles_lock_); + DCHECK_EQ(profiles_.size(), 0u); + profiles_ = profiles; + } + bool IsProfileSupported(media::VideoCodecProfile profile) { + base::AutoLock lock(profiles_lock_); + return profiles_.find(profile) != profiles_.end(); + } + + private: + base::Lock profiles_lock_; + base::flat_set<media::VideoCodecProfile> profiles_ GUARDED_BY(profiles_lock_); +}; + +SupplementalProfileCache* GetSupplementalProfileCache() { + static base::NoDestructor<SupplementalProfileCache> cache; + return cache.get(); +} + bool IsSupportedHdrMetadata(const gfx::HdrMetadataType& hdr_metadata_type) { switch (hdr_metadata_type) { case gfx::HdrMetadataType::kNone: @@ -179,7 +202,16 @@ bool IsAudioCodecProprietary(AudioCodec codec) { #endif // !BUILDFLAG(USE_PROPRIETARY_CODECS) bool IsHevcProfileSupported(const VideoType& type) { -#if BUILDFLAG(ENABLE_PLATFORM_ENCRYPTED_HEVC) + if (!IsColorSpaceSupported(type.color_space)) + return false; + +#if BUILDFLAG(ENABLE_PLATFORM_HEVC) +#if BUILDFLAG(IS_WIN) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_LINUX) + return GetSupplementalProfileCache()->IsProfileSupported(type.profile); +#else + return true; +#endif // BUILDFLAG(IS_WIN) || BUILDFLAG(IS_CHROMEOS) || BUILDFLAG(IS_LINUX) +#elif BUILDFLAG(ENABLE_PLATFORM_ENCRYPTED_HEVC) // Only encrypted HEVC content is supported, and normally MSE.isTypeSupported // returns false for HEVC. The kEnableClearHevcForTesting flag allows it to // return true to enable a wider array of test scenarios to function properly. @@ -187,22 +219,10 @@ bool IsHevcProfileSupported(const VideoType& type) { switches::kEnableClearHevcForTesting)) { return false; } - - // Color management required for HDR to not look terrible. - if (!IsColorSpaceSupported(type.color_space)) - return false; - - switch (type.profile) { - case HEVCPROFILE_MAIN: - case HEVCPROFILE_MAIN10: - return true; - case HEVCPROFILE_MAIN_STILL_PICTURE: - return false; - default: - NOTREACHED(); - } -#endif // BUILDFLAG(ENABLE_PLATFORM_ENCRYPTED_HEVC) + return type.profile == HEVCPROFILE_MAIN || type.profile == HEVCPROFILE_MAIN10; +#else return false; +#endif } bool IsVp9ProfileSupported(const VideoType& type) { @@ -266,6 +286,10 @@ bool IsAACSupported(const AudioType& type) { #if BUILDFLAG(IS_ANDROID) return base::android::BuildInfo::GetInstance()->sdk_int() >= base::android::SDK_VERSION_P; +#elif BUILDFLAG(IS_MAC) + if (__builtin_available(macOS 10.15, *)) + return true; + return false; #else return false; #endif @@ -355,11 +379,21 @@ bool IsDefaultSupportedAudioType(const AudioType& type) { case AudioCodec::kALAC: case AudioCodec::kAC3: case AudioCodec::kMpegHAudio: + case AudioCodec::kUnknown: + return false; case AudioCodec::kDTS: case AudioCodec::kDTSXP2: - case AudioCodec::kUnknown: +#if BUILDFLAG(ENABLE_PLATFORM_DTS_AUDIO) + return true; +#else return false; +#endif } } +void UpdateDefaultSupportedVideoProfiles( + const base::flat_set<media::VideoCodecProfile>& profiles) { + GetSupplementalProfileCache()->UpdateCache(profiles); +} + } // namespace media diff --git a/chromium/media/base/supported_types.h b/chromium/media/base/supported_types.h index ba4ab01c37e..0bbb6e6cc3f 100644 --- a/chromium/media/base/supported_types.h +++ b/chromium/media/base/supported_types.h @@ -5,6 +5,7 @@ #ifndef MEDIA_BASE_SUPPORTED_TYPES_H_ #define MEDIA_BASE_SUPPORTED_TYPES_H_ +#include "base/containers/flat_set.h" #include "media/base/media_types.h" namespace media { @@ -21,6 +22,12 @@ MEDIA_EXPORT bool IsSupportedVideoType(const VideoType& type); MEDIA_EXPORT bool IsDefaultSupportedAudioType(const AudioType& type); MEDIA_EXPORT bool IsDefaultSupportedVideoType(const VideoType& type); +// This function lets the caller add additional codec profiles to those +// supported by default. Used primarily to add hardware codec profiles once +// support is known. +MEDIA_EXPORT void UpdateDefaultSupportedVideoProfiles( + const base::flat_set<VideoCodecProfile>& profiles); + } // namespace media #endif // MEDIA_BASE_SUPPORTED_TYPES_H_ diff --git a/chromium/media/base/supported_types_unittest.cc b/chromium/media/base/supported_types_unittest.cc index e0ad0925416..1d0f12e0bfa 100644 --- a/chromium/media/base/supported_types_unittest.cc +++ b/chromium/media/base/supported_types_unittest.cc @@ -249,21 +249,21 @@ TEST(SupportedTypesTest, IsSupportedAudioTypeWithSpatialRenderingBasics) { is_spatial_rendering})); } -TEST(SupportedTypesTest, XHE_AACSupportedOnAndroidOnly) { - // TODO(dalecurtis): Update this test if we ever have support elsewhere. +TEST(SupportedTypesTest, XHE_AACSupported) { + bool is_supported = false; + #if BUILDFLAG(IS_ANDROID) - const bool is_supported = - kPropCodecsEnabled && - base::android::BuildInfo::GetInstance()->sdk_int() >= - base::android::SDK_VERSION_P; + is_supported = kPropCodecsEnabled && + base::android::BuildInfo::GetInstance()->sdk_int() >= + base::android::SDK_VERSION_P; +#elif BUILDFLAG(IS_MAC) && BUILDFLAG(USE_PROPRIETARY_CODECS) + if (__builtin_available(macOS 10.15, *)) + is_supported = true; +#endif EXPECT_EQ(is_supported, IsSupportedAudioType( {AudioCodec::kAAC, AudioCodecProfile::kXHE_AAC, false})); -#else - EXPECT_FALSE(IsSupportedAudioType( - {AudioCodec::kAAC, AudioCodecProfile::kXHE_AAC, false})); -#endif } TEST(SupportedTypesTest, IsSupportedVideoTypeWithHdrMetadataBasics) { diff --git a/chromium/media/base/test_data_util.cc b/chromium/media/base/test_data_util.cc index 4940d4c4adc..0858b67d0dc 100644 --- a/chromium/media/base/test_data_util.cc +++ b/chromium/media/base/test_data_util.cc @@ -8,7 +8,6 @@ #include "base/check_op.h" #include "base/containers/flat_map.h" -#include "base/cxx17_backports.h" #include "base/files/file_util.h" #include "base/no_destructor.h" #include "base/numerics/safe_conversions.h" @@ -227,13 +226,13 @@ scoped_refptr<DecoderBuffer> ReadTestDataFile(const std::string& name) { bool LookupTestKeyVector(const std::vector<uint8_t>& key_id, bool allow_rotation, std::vector<uint8_t>* key) { - std::vector<uint8_t> starting_key_id(kKeyId, kKeyId + base::size(kKeyId)); + std::vector<uint8_t> starting_key_id(kKeyId, kKeyId + std::size(kKeyId)); size_t rotate_limit = allow_rotation ? starting_key_id.size() : 1; for (size_t pos = 0; pos < rotate_limit; ++pos) { std::rotate(starting_key_id.begin(), starting_key_id.begin() + pos, starting_key_id.end()); if (key_id == starting_key_id) { - key->assign(kSecretKey, kSecretKey + base::size(kSecretKey)); + key->assign(kSecretKey, kSecretKey + std::size(kSecretKey)); std::rotate(key->begin(), key->begin() + pos, key->end()); return true; } diff --git a/chromium/media/base/text_renderer_unittest.cc b/chromium/media/base/text_renderer_unittest.cc index 40c14d262f4..68e805b7234 100644 --- a/chromium/media/base/text_renderer_unittest.cc +++ b/chromium/media/base/text_renderer_unittest.cc @@ -13,6 +13,7 @@ #include "base/callback_helpers.h" #include "base/run_loop.h" #include "base/test/task_environment.h" +#include "base/time/time.h" #include "media/base/audio_decoder_config.h" #include "media/base/decoder_buffer.h" #include "media/base/demuxer_stream.h" diff --git a/chromium/media/base/time_delta_interpolator_unittest.cc b/chromium/media/base/time_delta_interpolator_unittest.cc index ed8b35c5291..c1c7935ea31 100644 --- a/chromium/media/base/time_delta_interpolator_unittest.cc +++ b/chromium/media/base/time_delta_interpolator_unittest.cc @@ -2,8 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "base/test/simple_test_tick_clock.h" #include "media/base/time_delta_interpolator.h" +#include "base/test/simple_test_tick_clock.h" +#include "base/time/time.h" #include "testing/gtest/include/gtest/gtest.h" namespace media { diff --git a/chromium/media/base/tuneable.cc b/chromium/media/base/tuneable.cc index c3b6d4221db..d018fd6eee1 100644 --- a/chromium/media/base/tuneable.cc +++ b/chromium/media/base/tuneable.cc @@ -10,6 +10,7 @@ #include "base/hash/hash.h" #include "base/metrics/field_trial_params.h" #include "base/strings/string_number_conversions.h" +#include "base/time/time.h" #include "media/base/media_switches.h" namespace { diff --git a/chromium/media/base/unaligned_shared_memory_unittest.cc b/chromium/media/base/unaligned_shared_memory_unittest.cc index 1e79bb29179..9d553cbc63f 100644 --- a/chromium/media/base/unaligned_shared_memory_unittest.cc +++ b/chromium/media/base/unaligned_shared_memory_unittest.cc @@ -9,7 +9,6 @@ #include <limits> -#include "base/cxx17_backports.h" #include "testing/gtest/include/gtest/gtest.h" namespace media { @@ -17,11 +16,11 @@ namespace media { namespace { const uint8_t kUnalignedData[] = "XXXhello"; -const size_t kUnalignedDataSize = base::size(kUnalignedData); +const size_t kUnalignedDataSize = std::size(kUnalignedData); const off_t kUnalignedOffset = 3; const uint8_t kData[] = "hello"; -const size_t kDataSize = base::size(kData); +const size_t kDataSize = std::size(kData); base::UnsafeSharedMemoryRegion CreateRegion(const uint8_t* data, size_t size) { auto region = base::UnsafeSharedMemoryRegion::Create(size); diff --git a/chromium/media/base/video_bitrate_allocation.cc b/chromium/media/base/video_bitrate_allocation.cc index a988be2f126..cf01aa25da4 100644 --- a/chromium/media/base/video_bitrate_allocation.cc +++ b/chromium/media/base/video_bitrate_allocation.cc @@ -11,26 +11,74 @@ #include "base/check_op.h" #include "base/numerics/checked_math.h" +#include "media/base/bitrate.h" + +namespace { + +static media::Bitrate MakeReplacementBitrate(const media::Bitrate& old, + uint32_t target_bps, + uint32_t peak_bps) { + switch (old.mode()) { + case media::Bitrate::Mode::kConstant: + return media::Bitrate::ConstantBitrate(target_bps); + case media::Bitrate::Mode::kVariable: + return media::Bitrate::VariableBitrate(target_bps, peak_bps); + } +} + +} // namespace namespace media { constexpr size_t VideoBitrateAllocation::kMaxSpatialLayers; constexpr size_t VideoBitrateAllocation::kMaxTemporalLayers; +VideoBitrateAllocation::VideoBitrateAllocation(Bitrate::Mode mode) { + switch (mode) { + case Bitrate::Mode::kConstant: + sum_bitrate_ = Bitrate::ConstantBitrate(0u); + break; + case Bitrate::Mode::kVariable: + // For variable bitrates, the peak must not be zero as enforced by + // Bitrate. + sum_bitrate_ = Bitrate::VariableBitrate(0u, 1u); + break; + } +} + +bool VideoBitrateAllocation::SetPeakBps(uint32_t peak_bps) { + if (sum_bitrate_.mode() != Bitrate::Mode::kVariable) + return false; + + if (peak_bps == 0u) + return false; + + if (sum_bitrate_.target_bps() > peak_bps) + return false; + + Bitrate old = sum_bitrate_; + sum_bitrate_ = MakeReplacementBitrate(old, old.target_bps(), peak_bps); + return true; +} + bool VideoBitrateAllocation::SetBitrate(size_t spatial_index, size_t temporal_index, uint32_t bitrate_bps) { CHECK_LT(spatial_index, kMaxSpatialLayers); CHECK_LT(temporal_index, kMaxTemporalLayers); - base::CheckedNumeric<uint32_t> checked_sum = sum_; - checked_sum -= bitrates_[spatial_index][temporal_index]; + base::CheckedNumeric<uint32_t> checked_sum = sum_bitrate_.target_bps(); + uint32_t old_bitrate_bps = bitrates_[spatial_index][temporal_index]; + checked_sum -= old_bitrate_bps; checked_sum += bitrate_bps; if (!checked_sum.IsValid()) { return false; // Would cause overflow of the sum. } - sum_ = checked_sum.ValueOrDie(); + const uint32_t new_sum_bps = checked_sum.ValueOrDefault(0u); + const uint32_t new_peak_bps = std::max(sum_bitrate_.peak_bps(), new_sum_bps); + sum_bitrate_ = + MakeReplacementBitrate(sum_bitrate_, new_sum_bps, new_peak_bps); bitrates_[spatial_index][temporal_index] = bitrate_bps; return true; } @@ -43,7 +91,11 @@ uint32_t VideoBitrateAllocation::GetBitrateBps(size_t spatial_index, } uint32_t VideoBitrateAllocation::GetSumBps() const { - return sum_; + return sum_bitrate_.target_bps(); +} + +const Bitrate VideoBitrateAllocation::GetSumBitrate() const { + return sum_bitrate_; } std::string VideoBitrateAllocation::ToString() const { @@ -83,13 +135,21 @@ std::string VideoBitrateAllocation::ToString() const { } ss << "}"; } - ss << "}"; + ss << "}, mode "; + switch (sum_bitrate_.mode()) { + case Bitrate::Mode::kConstant: + ss << "CBR"; + break; + case Bitrate::Mode::kVariable: + ss << "VBR with peak bps " << sum_bitrate_.peak_bps(); + break; + } return ss.str(); } bool VideoBitrateAllocation::operator==( const VideoBitrateAllocation& other) const { - if (sum_ != other.sum_) { + if (sum_bitrate_ != other.sum_bitrate_) { return false; } return memcmp(bitrates_, other.bitrates_, sizeof(bitrates_)) == 0; diff --git a/chromium/media/base/video_bitrate_allocation.h b/chromium/media/base/video_bitrate_allocation.h index 5b4e6a29a41..62a3cc49a47 100644 --- a/chromium/media/base/video_bitrate_allocation.h +++ b/chromium/media/base/video_bitrate_allocation.h @@ -9,6 +9,7 @@ #include <stdint.h> #include <string> +#include "media/base/bitrate.h" #include "media/base/media_export.h" namespace media { @@ -21,14 +22,16 @@ class MEDIA_EXPORT VideoBitrateAllocation { static constexpr size_t kMaxSpatialLayers = 5; static constexpr size_t kMaxTemporalLayers = 4; - VideoBitrateAllocation() = default; + explicit VideoBitrateAllocation( + Bitrate::Mode mode = Bitrate::Mode::kConstant); ~VideoBitrateAllocation() = default; - // Returns if this bitrate can't be set (sum exceeds uint32_t max value). Do - // not use an integer or uint64_t version of this. If you have a signed or - // 64-bit value you want to use as input, you must explicitly convert to - // uint32_t before calling. This is intended to prevent implicit and unsafe - // type conversion. + // Returns true iff. the bitrate was set (sum within uint32_t max value). If + // a variable bitrate is used and the previous peak bitrate was below the new + // sum of bitrates across layers, this will automatically set the new peak to + // equal the new sum. If you have a signed or 64-bit value you want to use as + // input, you must explicitly convert to uint32_t before calling. This is + // intended to prevent implicit and unsafe type conversion. bool SetBitrate(size_t spatial_index, size_t temporal_index, uint32_t bitrate_bps); @@ -46,12 +49,21 @@ class MEDIA_EXPORT VideoBitrateAllocation { size_t temporal_index, uint64_t bitrate_bps) = delete; + // True iff. this bitrate allocation can have its peak set to |peak_bps| (the + // peak must be greater than the sum of the layers' bitrates, and the bitrate + // mode must be variable bitrate). + bool SetPeakBps(uint32_t peak_bps); + // Returns the bitrate for specified spatial/temporal index, or 0 if not set. uint32_t GetBitrateBps(size_t spatial_index, size_t temporal_index) const; // Sum of all bitrates. uint32_t GetSumBps() const; + // Non-layered bitrate allocation. If there are layers, this bitrate's target + // bps equals the sum of the layers' bitrates. + const Bitrate GetSumBitrate() const; + std::string ToString() const; bool operator==(const VideoBitrateAllocation& other) const; @@ -60,8 +72,9 @@ class MEDIA_EXPORT VideoBitrateAllocation { } private: - // Cached sum of all elements of |bitrates_|, for performance. - uint32_t sum_ = 0u; + // A bitrate representing a cached sum of the elements of |bitrates_|, for + // performance. + Bitrate sum_bitrate_; uint32_t bitrates_[kMaxSpatialLayers][kMaxTemporalLayers] = {}; }; diff --git a/chromium/media/base/video_bitrate_allocation_unittest.cc b/chromium/media/base/video_bitrate_allocation_unittest.cc index 9794a819054..7ab8fdf07d7 100644 --- a/chromium/media/base/video_bitrate_allocation_unittest.cc +++ b/chromium/media/base/video_bitrate_allocation_unittest.cc @@ -9,6 +9,38 @@ namespace media { +TEST(VideoBitrateAllocationTest, Constructor_DefaultsModeConstant) { + VideoBitrateAllocation allocation; + + ASSERT_EQ(allocation.GetSumBitrate().mode(), Bitrate::Mode::kConstant); +} + +TEST(VideoBitrateAllocationTest, Constructor_ConstantBitrate_CorrectMode) { + VideoBitrateAllocation allocation(Bitrate::Mode::kConstant); + + ASSERT_EQ(allocation.GetSumBitrate().mode(), Bitrate::Mode::kConstant); +} + +TEST(VideoBitrateAllocationTest, Constructor_VariableBitrate_CorrectMode) { + VideoBitrateAllocation allocation(Bitrate::Mode::kVariable); + + ASSERT_EQ(allocation.GetSumBitrate().mode(), Bitrate::Mode::kVariable); +} + +TEST(VideoBitrateAllocationTest, + Constructor_ConstantBitrate_InitializesTargetZero) { + VideoBitrateAllocation allocation; + + ASSERT_EQ(allocation.GetSumBitrate().target_bps(), 0u); +} + +TEST(VideoBitrateAllocationTest, + Constructor_VariableBitrate_InitializesTargetZero) { + VideoBitrateAllocation allocation(Bitrate::Mode::kVariable); + + ASSERT_EQ(allocation.GetSumBitrate().target_bps(), 0u); +} + TEST(VideoBitrateAllocationTest, SetAndGet) { uint32_t sum = 0u; uint32_t layer_rate = 0u; @@ -39,6 +71,66 @@ TEST(VideoBitrateAllocationTest, SetAndGet) { } } +TEST(VideoBitrateAllocationTest, SetBitrate_VariableBitrate_CorrectSum) { + VideoBitrateAllocation allocation(Bitrate::Mode::kVariable); + allocation.SetBitrate(0, 0, 1u); + allocation.SetBitrate(1, 0, 2u); + allocation.SetBitrate(0, 1, 3u); + allocation.SetBitrate(2, 2, 4u); + allocation.SetBitrate(1, 2, 5u); + + ASSERT_EQ(15u, allocation.GetSumBps()); +} + +TEST(VideoBitrateAllocationTest, SetBitrate_PeakTooLow_IncreasesPeak) { + VideoBitrateAllocation allocation(Bitrate::Mode::kVariable); + allocation.SetPeakBps(50u); + + ASSERT_TRUE(allocation.SetBitrate(0, 0, 1000u)); + ASSERT_EQ(allocation.GetSumBitrate().peak_bps(), 1000u); +} + +TEST(VideoBitrateAllocationTest, SetPeakBps_GreaterThanSum_Succeeds) { + VideoBitrateAllocation allocation(Bitrate::Mode::kVariable); + allocation.SetBitrate(0, 0, 500u); + allocation.SetBitrate(0, 1, 500u); + allocation.SetBitrate(1, 0, 500u); + + ASSERT_TRUE(allocation.SetPeakBps(2000u)); + ASSERT_EQ(allocation.GetSumBitrate().peak_bps(), 2000u); +} + +TEST(VideoBitrateAllocationTest, SetPeakBps_EqualToSum_Succeeds) { + VideoBitrateAllocation allocation(Bitrate::Mode::kVariable); + allocation.SetBitrate(0, 0, 400u); + allocation.SetBitrate(0, 1, 300u); + allocation.SetBitrate(1, 0, 300u); + + EXPECT_EQ(allocation.GetSumBps(), 1000u); + + ASSERT_TRUE(allocation.SetPeakBps(1000u)); + ASSERT_EQ(allocation.GetSumBitrate().peak_bps(), 1000u); +} + +TEST(VideoBitrateAllocationTest, SetPeakBps_ImplicitConstantBitrate_Fails) { + VideoBitrateAllocation allocation; + + ASSERT_FALSE(allocation.SetPeakBps(1u)); +} + +TEST(VideoBitrateAllocationTest, SetPeakBps_ConstantBitrate_Fails) { + VideoBitrateAllocation allocation(Bitrate::Mode::kConstant); + + ASSERT_FALSE(allocation.SetPeakBps(1u)); +} + +TEST(VideoBitrateAllocationTest, SetPeakBps_PeakLessThanSum_Fails) { + VideoBitrateAllocation allocation(Bitrate::Mode::kVariable); + allocation.SetBitrate(0, 0, 1000u); + + ASSERT_FALSE(allocation.SetPeakBps(999u)); +} + TEST(VideoBitrateAllocationTest, CanSetMaxValue) { VideoBitrateAllocation allocation; // Single cell containing max value. @@ -87,26 +179,27 @@ TEST(VideoBitrateAllocationTest, ToString) { EXPECT_TRUE(allocation.SetBitrate(0, 1, 456u)); EXPECT_TRUE(allocation.SetBitrate(0, 2, 789u)); EXPECT_EQ(allocation.ToString(), - "active spatial layers: 1, {SL#0: {123, 456, 789}}"); + "active spatial layers: 1, {SL#0: {123, 456, 789}}, mode CBR"); // Add spatial layer. EXPECT_TRUE(allocation.SetBitrate(1, 0, 789u)); EXPECT_TRUE(allocation.SetBitrate(1, 1, 456u)); - EXPECT_EQ( - allocation.ToString(), - "active spatial layers: 2, {SL#0: {123, 456, 789}, SL#1: {789, 456}}"); + EXPECT_EQ(allocation.ToString(), + "active spatial layers: 2, {SL#0: {123, 456, 789}, SL#1: {789, " + "456}}, mode CBR"); // Reset the bottom spatial layer. EXPECT_TRUE(allocation.SetBitrate(0, 0, 0u)); EXPECT_TRUE(allocation.SetBitrate(0, 1, 0u)); EXPECT_TRUE(allocation.SetBitrate(0, 2, 0u)); EXPECT_EQ(allocation.ToString(), - "active spatial layers: 1, {SL#1: {789, 456}}"); + "active spatial layers: 1, {SL#1: {789, 456}}, mode CBR"); // Add one more spatial layer. EXPECT_TRUE(allocation.SetBitrate(2, 0, 123u)); - EXPECT_EQ(allocation.ToString(), - "active spatial layers: 2, {SL#1: {789, 456}, SL#2: {123}}"); + EXPECT_EQ( + allocation.ToString(), + "active spatial layers: 2, {SL#1: {789, 456}, SL#2: {123}}, mode CBR"); // Reset all the spatial layers. EXPECT_TRUE(allocation.SetBitrate(1, 0, 0u)); @@ -115,4 +208,27 @@ TEST(VideoBitrateAllocationTest, ToString) { EXPECT_EQ(allocation.ToString(), "Empty VideoBitrateAllocation"); } +TEST(VideoBitrateAllocationTest, ToString_VariableBitrateAndSingleLayer) { + VideoBitrateAllocation allocation(Bitrate::Mode::kVariable); + allocation.SetBitrate(0, 0, 1u); + + EXPECT_EQ(allocation.ToString(), + "active spatial layers: 1, {SL#0: {1}}, mode VBR with peak bps 1"); +} + +TEST(VideoBitrateAllocationTest, ToString_VariableBitrateAndMultiLayer) { + VideoBitrateAllocation allocation(Bitrate::Mode::kVariable); + allocation.SetBitrate(0, 0, 1u); + allocation.SetBitrate(0, 1, 2u); + allocation.SetBitrate(0, 2, 3u); + allocation.SetBitrate(1, 0, 4u); + allocation.SetBitrate(1, 1, 5u); + allocation.SetBitrate(1, 2, 6u); + allocation.SetPeakBps(100u); + + EXPECT_EQ(allocation.ToString(), + "active spatial layers: 2, {SL#0: {1, 2, 3}, SL#1: {4, 5, 6}}, " + "mode VBR with peak bps 100"); +} + } // namespace media diff --git a/chromium/media/base/video_frame.cc b/chromium/media/base/video_frame.cc index 9a4dab2a266..8e906c86f82 100644 --- a/chromium/media/base/video_frame.cc +++ b/chromium/media/base/video_frame.cc @@ -12,7 +12,6 @@ #include "base/atomic_sequence_num.h" #include "base/bind.h" #include "base/bits.h" -#include "base/cxx17_backports.h" #include "base/logging.h" #include "base/process/memory.h" #include "base/strings/string_piece.h" @@ -128,12 +127,16 @@ gfx::Size VideoFrame::SampleSize(VideoPixelFormat format, size_t plane) { case PIXEL_FORMAT_YUV444P10: case PIXEL_FORMAT_YUV444P12: case PIXEL_FORMAT_Y16: + case PIXEL_FORMAT_I444A: + case PIXEL_FORMAT_YUV444AP10: return gfx::Size(1, 1); case PIXEL_FORMAT_I422: case PIXEL_FORMAT_YUV422P9: case PIXEL_FORMAT_YUV422P10: case PIXEL_FORMAT_YUV422P12: + case PIXEL_FORMAT_I422A: + case PIXEL_FORMAT_YUV422AP10: return gfx::Size(2, 1); case PIXEL_FORMAT_YV12: @@ -145,6 +148,7 @@ gfx::Size VideoFrame::SampleSize(VideoPixelFormat format, size_t plane) { case PIXEL_FORMAT_YUV420P10: case PIXEL_FORMAT_YUV420P12: case PIXEL_FORMAT_P016LE: + case PIXEL_FORMAT_YUV420AP10: return gfx::Size(2, 2); case PIXEL_FORMAT_UYVY: @@ -214,6 +218,11 @@ static bool RequiresEvenSizeAllocation(VideoPixelFormat format) { case PIXEL_FORMAT_I420A: case PIXEL_FORMAT_UYVY: case PIXEL_FORMAT_P016LE: + case PIXEL_FORMAT_I422A: + case PIXEL_FORMAT_I444A: + case PIXEL_FORMAT_YUV420AP10: + case PIXEL_FORMAT_YUV422AP10: + case PIXEL_FORMAT_YUV444AP10: return true; case PIXEL_FORMAT_UNKNOWN: break; @@ -268,8 +277,6 @@ static absl::optional<VideoFrameLayout> GetDefaultLayout( } default: - // TODO(miu): This function should support any pixel format. - // http://crbug.com/555909 . DLOG(ERROR) << "Unsupported pixel format" << VideoPixelFormatToString(format); return absl::nullopt; @@ -1060,16 +1067,19 @@ int VideoFrame::BytesPerElement(VideoPixelFormat format, size_t plane) { case PIXEL_FORMAT_YUV420P12: case PIXEL_FORMAT_YUV422P12: case PIXEL_FORMAT_YUV444P12: + case PIXEL_FORMAT_YUV420AP10: + case PIXEL_FORMAT_YUV422AP10: + case PIXEL_FORMAT_YUV444AP10: return 2; case PIXEL_FORMAT_NV12: case PIXEL_FORMAT_NV21: { static const int bytes_per_element[] = {1, 2}; - DCHECK_LT(plane, base::size(bytes_per_element)); + DCHECK_LT(plane, std::size(bytes_per_element)); return bytes_per_element[plane]; } case PIXEL_FORMAT_P016LE: { static const int bytes_per_element[] = {1, 2}; - DCHECK_LT(plane, base::size(bytes_per_element)); + DCHECK_LT(plane, std::size(bytes_per_element)); return bytes_per_element[plane] * 2; } case PIXEL_FORMAT_YV12: @@ -1077,6 +1087,8 @@ int VideoFrame::BytesPerElement(VideoPixelFormat format, size_t plane) { case PIXEL_FORMAT_I422: case PIXEL_FORMAT_I420A: case PIXEL_FORMAT_I444: + case PIXEL_FORMAT_I422A: + case PIXEL_FORMAT_I444A: return 1; case PIXEL_FORMAT_MJPEG: return 0; @@ -1451,9 +1463,6 @@ bool VideoFrame::IsValidConfigInternal(VideoPixelFormat format, return false; } - // Make sure new formats are properly accounted for in the method. - static_assert(PIXEL_FORMAT_MAX == 33, - "Added pixel format, please review AreSizesValid()"); switch (frame_control_type) { case FrameControlType::kNone: // Check that software-allocated buffer formats are not empty. diff --git a/chromium/media/base/video_frame.h b/chromium/media/base/video_frame.h index 0bc150669e5..edf74296fd3 100644 --- a/chromium/media/base/video_frame.h +++ b/chromium/media/base/video_frame.h @@ -22,6 +22,7 @@ #include "base/memory/unsafe_shared_memory_region.h" #include "base/synchronization/lock.h" #include "base/thread_annotations.h" +#include "base/time/time.h" #include "base/unguessable_token.h" #include "build/build_config.h" #include "gpu/command_buffer/common/mailbox_holder.h" @@ -588,9 +589,6 @@ class MEDIA_EXPORT VideoFrame : public base::RefCountedThreadSafe<VideoFrame> { // Returns a dictionary of optional metadata. This contains information // associated with the frame that downstream clients might use for frame-level // logging, quality/performance optimizations, signaling, etc. - // - // TODO(miu): Move some of the "extra" members of VideoFrame (below) into - // here as a later clean-up step. const VideoFrameMetadata& metadata() const { return metadata_; } VideoFrameMetadata& metadata() { return metadata_; } void set_metadata(const VideoFrameMetadata& metadata) { diff --git a/chromium/media/base/video_frame_layout.cc b/chromium/media/base/video_frame_layout.cc index 3eef408656d..b3d666289e4 100644 --- a/chromium/media/base/video_frame_layout.cc +++ b/chromium/media/base/video_frame_layout.cc @@ -76,6 +76,11 @@ size_t VideoFrameLayout::NumPlanes(VideoPixelFormat format) { case PIXEL_FORMAT_YUV444P12: return 3; case PIXEL_FORMAT_I420A: + case PIXEL_FORMAT_I422A: + case PIXEL_FORMAT_I444A: + case PIXEL_FORMAT_YUV420AP10: + case PIXEL_FORMAT_YUV422AP10: + case PIXEL_FORMAT_YUV444AP10: return 4; case PIXEL_FORMAT_UNKNOWN: // Note: PIXEL_FORMAT_UNKNOWN is used for end-of-stream frame. diff --git a/chromium/media/base/video_frame_metadata.cc b/chromium/media/base/video_frame_metadata.cc index 47d0cd1166a..3a95860569e 100644 --- a/chromium/media/base/video_frame_metadata.cc +++ b/chromium/media/base/video_frame_metadata.cc @@ -50,6 +50,7 @@ void VideoFrameMetadata::MergeMetadataFrom( MERGE_VALUE_FIELD(dcomp_surface, metadata_source); MERGE_VALUE_FIELD(protected_video, metadata_source); MERGE_VALUE_FIELD(hw_protected, metadata_source); + MERGE_VALUE_FIELD(is_webgpu_compatible, metadata_source); #if BUILDFLAG(USE_VAAPI) MERGE_OPTIONAL_FIELD(hw_va_protected_session_id, metadata_source); #endif diff --git a/chromium/media/base/video_frame_metadata.h b/chromium/media/base/video_frame_metadata.h index e74c575399b..0f7560a4855 100644 --- a/chromium/media/base/video_frame_metadata.h +++ b/chromium/media/base/video_frame_metadata.h @@ -148,6 +148,10 @@ struct MEDIA_EXPORT VideoFrameMetadata { // PROTECTED_VIDEO is also set to true. bool hw_protected = false; + // This video frame's shared image backing can support zero-copy WebGPU + // import. + bool is_webgpu_compatible = false; + #if BUILDFLAG(USE_VAAPI) // The ID of the VA-API protected session used to decode this frame, if // applicable. The proper type is VAProtectedSessionID. However, in order to diff --git a/chromium/media/base/video_frame_pool.cc b/chromium/media/base/video_frame_pool.cc index e5aa15c28f8..8f6a0489fde 100644 --- a/chromium/media/base/video_frame_pool.cc +++ b/chromium/media/base/video_frame_pool.cc @@ -12,6 +12,7 @@ #include "base/synchronization/lock.h" #include "base/thread_annotations.h" #include "base/time/default_tick_clock.h" +#include "base/time/time.h" namespace media { diff --git a/chromium/media/base/video_frame_unittest.cc b/chromium/media/base/video_frame_unittest.cc index bf5ba94cddd..5db228c01b1 100644 --- a/chromium/media/base/video_frame_unittest.cc +++ b/chromium/media/base/video_frame_unittest.cc @@ -6,11 +6,11 @@ #include <stddef.h> #include <stdint.h> + #include <memory> #include "base/bind.h" #include "base/callback_helpers.h" -#include "base/cxx17_backports.h" #include "base/format_macros.h" #include "base/memory/aligned_memory.h" #include "base/memory/unsafe_shared_memory_region.h" @@ -340,15 +340,15 @@ TEST(VideoFrame, CreateBlackFrame) { // Test frames themselves. uint8_t* y_plane = frame->data(VideoFrame::kYPlane); for (int y = 0; y < frame->coded_size().height(); ++y) { - EXPECT_EQ(0, memcmp(kExpectedYRow, y_plane, base::size(kExpectedYRow))); + EXPECT_EQ(0, memcmp(kExpectedYRow, y_plane, std::size(kExpectedYRow))); y_plane += frame->stride(VideoFrame::kYPlane); } uint8_t* u_plane = frame->data(VideoFrame::kUPlane); uint8_t* v_plane = frame->data(VideoFrame::kVPlane); for (int y = 0; y < frame->coded_size().height() / 2; ++y) { - EXPECT_EQ(0, memcmp(kExpectedUVRow, u_plane, base::size(kExpectedUVRow))); - EXPECT_EQ(0, memcmp(kExpectedUVRow, v_plane, base::size(kExpectedUVRow))); + EXPECT_EQ(0, memcmp(kExpectedUVRow, u_plane, std::size(kExpectedUVRow))); + EXPECT_EQ(0, memcmp(kExpectedUVRow, v_plane, std::size(kExpectedUVRow))); u_plane += frame->stride(VideoFrame::kUPlane); v_plane += frame->stride(VideoFrame::kVPlane); } @@ -703,12 +703,14 @@ TEST(VideoFrame, AllocationSize_OddSize) { case PIXEL_FORMAT_YUV444P9: case PIXEL_FORMAT_YUV444P10: case PIXEL_FORMAT_YUV444P12: + case PIXEL_FORMAT_YUV422AP10: EXPECT_EQ(144u, VideoFrame::AllocationSize(format, size)) << VideoPixelFormatToString(format); break; case PIXEL_FORMAT_YUV422P9: case PIXEL_FORMAT_YUV422P10: case PIXEL_FORMAT_YUV422P12: + case PIXEL_FORMAT_I444A: EXPECT_EQ(96u, VideoFrame::AllocationSize(format, size)) << VideoPixelFormatToString(format); break; @@ -717,6 +719,7 @@ TEST(VideoFrame, AllocationSize_OddSize) { case PIXEL_FORMAT_YUV420P10: case PIXEL_FORMAT_YUV420P12: case PIXEL_FORMAT_P016LE: + case PIXEL_FORMAT_I422A: EXPECT_EQ(72u, VideoFrame::AllocationSize(format, size)) << VideoPixelFormatToString(format); break; @@ -753,9 +756,14 @@ TEST(VideoFrame, AllocationSize_OddSize) { << VideoPixelFormatToString(format); break; case PIXEL_FORMAT_RGBAF16: + case PIXEL_FORMAT_YUV420AP10: EXPECT_EQ(120u, VideoFrame::AllocationSize(format, size)) << VideoPixelFormatToString(format); break; + case PIXEL_FORMAT_YUV444AP10: + EXPECT_EQ(192u, VideoFrame::AllocationSize(format, size)) + << VideoPixelFormatToString(format); + break; case PIXEL_FORMAT_MJPEG: case PIXEL_FORMAT_UNKNOWN: continue; diff --git a/chromium/media/base/video_transformation.cc b/chromium/media/base/video_transformation.cc index 043ae2d0397..a293bb2ed09 100644 --- a/chromium/media/base/video_transformation.cc +++ b/chromium/media/base/video_transformation.cc @@ -14,8 +14,9 @@ namespace media { namespace { +template <size_t decimal_bits> double FixedToFloatingPoint(int32_t i) { - return static_cast<double>(i >> 16); + return i / static_cast<double>(1 << decimal_bits); } } // namespace @@ -58,7 +59,6 @@ VideoTransformation::VideoTransformation(int32_t matrix[4]) { // [ sin(Θ), cos(Θ)] // A vertical flip is represented by the cosine's having opposite signs // and a horizontal flip is represented by the sine's having the same sign. - // Check the matrix for validity if (abs(matrix[0]) != abs(matrix[3]) || abs(matrix[1]) != abs(matrix[2])) { rotation = VIDEO_ROTATION_0; @@ -66,7 +66,19 @@ VideoTransformation::VideoTransformation(int32_t matrix[4]) { return; } - double angle = acos(FixedToFloatingPoint(matrix[0])) * 180 / base::kPiDouble; + double angle = + acos(FixedToFloatingPoint<16>(matrix[0])) * 180 / base::kPiDouble; + double check_angle = + asin(FixedToFloatingPoint<16>(matrix[1])) * 180 / base::kPiDouble; + double offset = abs(abs(angle) - abs(check_angle)); + while (offset >= 180.0) + offset -= 180.0; + + if (offset > 1e-3) { + rotation = VIDEO_ROTATION_0; + mirrored = false; + return; + } // Calculate angle offsets for rotation - rotating about the X axis // can be expressed as a 180 degree rotation and a Y axis rotation @@ -98,8 +110,7 @@ VideoTransformation::VideoTransformation(int32_t matrix[4]) { } else if (abs(angle - 180) < 1e-4) { rotation = VIDEO_ROTATION_180; } else if (abs(angle - 90) < 1e-4) { - bool quadrant = asin(FixedToFloatingPoint(matrix[2])) < 0; - rotation = quadrant ? VIDEO_ROTATION_90 : VIDEO_ROTATION_270; + rotation = (check_angle > 0) ? VIDEO_ROTATION_90 : VIDEO_ROTATION_270; } else { rotation = VIDEO_ROTATION_0; mirrored = false; diff --git a/chromium/media/base/video_transformation_unittest.cc b/chromium/media/base/video_transformation_unittest.cc new file mode 100644 index 00000000000..d0435e72f70 --- /dev/null +++ b/chromium/media/base/video_transformation_unittest.cc @@ -0,0 +1,92 @@ +// Copyright 2022 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. +#include "media/base/video_transformation.h" +#include <math.h> +#include "testing/gtest/include/gtest/gtest.h" + +namespace media { + +namespace { + +enum class Flip { kNone, kVertical, kHorizontal, kBoth }; + +// Rotation by angle Θ is represented in the matrix as: +// [ cos(Θ), -sin(Θ)] +// [ sin(Θ), cos(Θ)] +// a vertical flip is represented by the cosine's having opposite signs +// and a horizontal flip is represented by the sine's having the same sign. +constexpr void FromAngle(double angle_degrees, int32_t* matrix, Flip flip) { + double f_matrix[4] = {0, 0, 0, 0}; + f_matrix[0] = f_matrix[3] = cos(angle_degrees * 3.1415926535 / 180.0); + f_matrix[1] = f_matrix[2] = sin(angle_degrees * 3.1415926535 / 180.0); + if (flip == Flip::kVertical || flip == Flip::kBoth) + f_matrix[3] *= -1; + if (flip == Flip::kVertical || flip == Flip::kNone) + f_matrix[2] *= -1; + + matrix[0] = static_cast<int32_t>(round(f_matrix[0] * (1 << 16))); + matrix[1] = static_cast<int32_t>(round(f_matrix[1] * (1 << 16))); + matrix[3] = static_cast<int32_t>(round(f_matrix[2] * (1 << 16))); + matrix[4] = static_cast<int32_t>(round(f_matrix[3] * (1 << 16))); +} + +} // namespace + +class VideoTransformationTest : public testing::Test { + public: + VideoTransformationTest() = default; + VideoTransformationTest(const VideoTransformationTest&) = delete; + VideoTransformationTest& operator=(const VideoTransformationTest&) = delete; + ~VideoTransformationTest() override = default; +}; + +TEST_F(VideoTransformationTest, ComputeRotationAngles) { + int32_t matrix[9]; + + // Standard 90 degree increments with no rotation all end up rotated normally + FromAngle(0.0, matrix, Flip::kNone); + ASSERT_EQ(VideoTransformation::FromFFmpegDisplayMatrix(matrix), + VideoTransformation(VIDEO_ROTATION_0, false)); + + FromAngle(90.0, matrix, Flip::kNone); + ASSERT_EQ(VideoTransformation::FromFFmpegDisplayMatrix(matrix), + VideoTransformation(VIDEO_ROTATION_90, false)); + + FromAngle(180.0, matrix, Flip::kNone); + ASSERT_EQ(VideoTransformation::FromFFmpegDisplayMatrix(matrix), + VideoTransformation(VIDEO_ROTATION_180, false)); + + FromAngle(270.0, matrix, Flip::kNone); + ASSERT_EQ(VideoTransformation::FromFFmpegDisplayMatrix(matrix), + VideoTransformation(VIDEO_ROTATION_270, false)); + + // Non-right-angle rotations all get set to 0, since we can't render those + // properly anyway. + FromAngle(60.0, matrix, Flip::kNone); + ASSERT_EQ(VideoTransformation::FromFFmpegDisplayMatrix(matrix), + VideoTransformation(VIDEO_ROTATION_0, false)); + + FromAngle(45.0, matrix, Flip::kNone); + ASSERT_EQ(VideoTransformation::FromFFmpegDisplayMatrix(matrix), + VideoTransformation(VIDEO_ROTATION_0, false)); + + // Flips can cause weird things - ie a vertical flip + 180 rotation + // is the same thing as a horizontal flip + no rotation! + FromAngle(180.0, matrix, Flip::kVertical); + ASSERT_EQ(VideoTransformation::FromFFmpegDisplayMatrix(matrix), + VideoTransformation(VIDEO_ROTATION_0, true)); + + // Vertical and horizontal flipping is the same as a 180 degree rotation + FromAngle(0.0, matrix, Flip::kBoth); + ASSERT_EQ(VideoTransformation::FromFFmpegDisplayMatrix(matrix), + VideoTransformation(VIDEO_ROTATION_180, true)); + + // An invalid matrix is always going to give no rotation or mirroring. + for (int i = 0; i < 9; i++) + matrix[i] = 78123; + ASSERT_EQ(VideoTransformation::FromFFmpegDisplayMatrix(matrix), + VideoTransformation(VIDEO_ROTATION_0, false)); +} + +} // namespace media diff --git a/chromium/media/base/video_types.cc b/chromium/media/base/video_types.cc index 00b263dd050..d909bf5a2a5 100644 --- a/chromium/media/base/video_types.cc +++ b/chromium/media/base/video_types.cc @@ -75,6 +75,16 @@ std::string VideoPixelFormatToString(VideoPixelFormat format) { return "PIXEL_FORMAT_BGRA"; case PIXEL_FORMAT_RGBAF16: return "PIXEL_FORMAT_RGBAF16"; + case PIXEL_FORMAT_I422A: + return "PIXEL_FORMAT_I422A"; + case PIXEL_FORMAT_I444A: + return "PIXEL_FORMAT_I444A"; + case PIXEL_FORMAT_YUV420AP10: + return "PIXEL_FORMAT_YUV420AP10"; + case PIXEL_FORMAT_YUV422AP10: + return "PIXEL_FORMAT_YUV422AP10"; + case PIXEL_FORMAT_YUV444AP10: + return "PIXEL_FORMAT_YUV444AP10"; } NOTREACHED() << "Invalid VideoPixelFormat provided: " << format; return ""; @@ -115,6 +125,11 @@ bool IsYuvPlanar(VideoPixelFormat format) { case PIXEL_FORMAT_YUV422P12: case PIXEL_FORMAT_YUV444P12: case PIXEL_FORMAT_P016LE: + case PIXEL_FORMAT_I422A: + case PIXEL_FORMAT_I444A: + case PIXEL_FORMAT_YUV420AP10: + case PIXEL_FORMAT_YUV422AP10: + case PIXEL_FORMAT_YUV444AP10: return true; case PIXEL_FORMAT_UNKNOWN: @@ -170,6 +185,11 @@ bool IsOpaque(VideoPixelFormat format) { case PIXEL_FORMAT_ABGR: case PIXEL_FORMAT_BGRA: case PIXEL_FORMAT_RGBAF16: + case PIXEL_FORMAT_I422A: + case PIXEL_FORMAT_I444A: + case PIXEL_FORMAT_YUV420AP10: + case PIXEL_FORMAT_YUV422AP10: + case PIXEL_FORMAT_YUV444AP10: break; } return false; @@ -196,6 +216,8 @@ size_t BitDepth(VideoPixelFormat format) { case PIXEL_FORMAT_ABGR: case PIXEL_FORMAT_XBGR: case PIXEL_FORMAT_BGRA: + case PIXEL_FORMAT_I422A: + case PIXEL_FORMAT_I444A: return 8; case PIXEL_FORMAT_YUV420P9: case PIXEL_FORMAT_YUV422P9: @@ -206,6 +228,9 @@ size_t BitDepth(VideoPixelFormat format) { case PIXEL_FORMAT_YUV444P10: case PIXEL_FORMAT_XR30: case PIXEL_FORMAT_XB30: + case PIXEL_FORMAT_YUV420AP10: + case PIXEL_FORMAT_YUV422AP10: + case PIXEL_FORMAT_YUV444AP10: return 10; case PIXEL_FORMAT_YUV420P12: case PIXEL_FORMAT_YUV422P12: diff --git a/chromium/media/base/video_types.h b/chromium/media/base/video_types.h index b0ce5ceeebf..dca783b768f 100644 --- a/chromium/media/base/video_types.h +++ b/chromium/media/base/video_types.h @@ -79,9 +79,18 @@ enum VideoPixelFormat { PIXEL_FORMAT_RGBAF16 = 33, // Half float RGBA, 1 plane. + PIXEL_FORMAT_I422A = 34, // 24bpp YUVA planar 1x1 Y, 2x1 UV, 1x1 A samples. + + PIXEL_FORMAT_I444A = 35, // 32bpp YUVA planar, no subsampling. + + // YUVA planar, 10 bits per pixel component. + PIXEL_FORMAT_YUV420AP10 = 36, + PIXEL_FORMAT_YUV422AP10 = 37, + PIXEL_FORMAT_YUV444AP10 = 38, + // Please update UMA histogram enumeration when adding new formats here. PIXEL_FORMAT_MAX = - PIXEL_FORMAT_RGBAF16, // Must always be equal to largest entry logged. + PIXEL_FORMAT_YUV444AP10, // Must always be equal to largest entry logged. }; // Returns the name of a Format as a string. diff --git a/chromium/media/base/video_util.cc b/chromium/media/base/video_util.cc index 0e4cb7fa468..a786d60496a 100644 --- a/chromium/media/base/video_util.cc +++ b/chromium/media/base/video_util.cc @@ -17,9 +17,12 @@ #include "base/time/time.h" #include "gpu/GLES2/gl2extchromium.h" #include "gpu/command_buffer/client/raster_interface.h" +#include "media/base/limits.h" #include "media/base/video_frame.h" #include "media/base/video_frame_pool.h" +#include "media/base/video_types.h" #include "third_party/libyuv/include/libyuv.h" +#include "third_party/skia/include/core/SkColorSpace.h" #include "third_party/skia/include/core/SkImage.h" #include "third_party/skia/include/core/SkRefCnt.h" #include "third_party/skia/include/core/SkSurface.h" @@ -61,7 +64,7 @@ void FillRegionOutsideVisibleRect(uint8_t* data, } } -VideoPixelFormat ReadbackFormat(const media::VideoFrame& frame) { +VideoPixelFormat ReadbackFormat(const VideoFrame& frame) { switch (frame.format()) { case PIXEL_FORMAT_I420: case PIXEL_FORMAT_I420A: @@ -94,8 +97,8 @@ SkColorType SkColorTypeForPlane(VideoPixelFormat format, size_t plane) { // kGray_8_SkColorType would make more sense but doesn't work on Windows. return kAlpha_8_SkColorType; case PIXEL_FORMAT_NV12: - return plane == media::VideoFrame::kYPlane ? kAlpha_8_SkColorType - : kR8G8_unorm_SkColorType; + return plane == VideoFrame::kYPlane ? kAlpha_8_SkColorType + : kR8G8_unorm_SkColorType; case PIXEL_FORMAT_XBGR: case PIXEL_FORMAT_ABGR: return kRGBA_8888_SkColorType; @@ -212,8 +215,8 @@ bool ReadbackTexturePlaneToMemorySyncOOP(const VideoFrame& src_frame, sk_color_type, sk_alpha_type); ri->ReadbackImagePixels(holder.mailbox, info, dest_stride, src_rect.x(), src_rect.y(), dest_pixels); - DCHECK_EQ(ri->GetError(), static_cast<GLenum>(GL_NO_ERROR)); - return true; + return ri->GetGraphicsResetStatusKHR() == GL_NO_ERROR && + ri->GetError() == GL_NO_ERROR; } void LetterboxPlane(const gfx::Rect& view_area_in_bytes, @@ -541,6 +544,23 @@ gfx::Rect ComputeLetterboxRegionForI420(const gfx::Rect& bounds, return result; } +gfx::Rect MinimallyShrinkRectForI420(const gfx::Rect& rect) { + constexpr int kMinDimension = -1 * limits::kMaxDimension; + DCHECK(gfx::Rect(kMinDimension, kMinDimension, limits::kMaxDimension * 2, + limits::kMaxDimension * 2) + .Contains(rect)); + + const auto positive_mod = [](int a, int b) { return (a % b + b) % b; }; + + const int left = rect.x() + positive_mod(rect.x(), 2); + const int top = rect.y() + positive_mod(rect.y(), 2); + const int right = rect.right() - (rect.right() % 2); + const int bottom = rect.bottom() - (rect.bottom() % 2); + + return gfx::Rect(left, top, std::max(0, right - left), + std::max(0, bottom - top)); +} + gfx::Size ScaleSizeToFitWithinTarget(const gfx::Size& size, const gfx::Size& target) { return ScaleSizeToTarget(size, target, true); @@ -828,14 +848,13 @@ EncoderStatus ConvertAndScaleFrame(const VideoFrame& src_frame, (src_frame.format() == PIXEL_FORMAT_I420 || src_frame.format() == PIXEL_FORMAT_I420A)) { if (dst_frame.format() == PIXEL_FORMAT_I420A) { - libyuv::ScalePlane(src_frame.visible_data(media::VideoFrame::kAPlane), - src_frame.stride(media::VideoFrame::kAPlane), - src_frame.visible_rect().width(), - src_frame.visible_rect().height(), - dst_frame.data(media::VideoFrame::kAPlane), - dst_frame.stride(media::VideoFrame::kAPlane), - dst_frame.coded_size().width(), - dst_frame.coded_size().height(), kDefaultFiltering); + libyuv::ScalePlane( + src_frame.visible_data(VideoFrame::kAPlane), + src_frame.stride(VideoFrame::kAPlane), + src_frame.visible_rect().width(), src_frame.visible_rect().height(), + dst_frame.data(VideoFrame::kAPlane), + dst_frame.stride(VideoFrame::kAPlane), dst_frame.coded_size().width(), + dst_frame.coded_size().height(), kDefaultFiltering); } int error = libyuv::I420Scale( src_frame.visible_data(VideoFrame::kYPlane), @@ -879,7 +898,7 @@ EncoderStatus ConvertAndScaleFrame(const VideoFrame& src_frame, if (dst_frame.format() == PIXEL_FORMAT_I420 && src_frame.format() == PIXEL_FORMAT_NV12) { - if (src_frame.visible_rect() == dst_frame.visible_rect()) { + if (src_frame.visible_rect().size() == dst_frame.visible_rect().size()) { // Both frames have the same size, only NV12-to-I420 conversion is // required. int error = libyuv::NV12ToI420( @@ -940,7 +959,7 @@ EncoderStatus ConvertAndScaleFrame(const VideoFrame& src_frame, if (dst_frame.format() == PIXEL_FORMAT_NV12 && src_frame.format() == PIXEL_FORMAT_I420) { - if (src_frame.visible_rect() == dst_frame.visible_rect()) { + if (src_frame.visible_rect().size() == dst_frame.visible_rect().size()) { // Both frames have the same size, only I420-to-NV12 conversion is // required. int error = libyuv::I420ToNV12( @@ -1005,12 +1024,12 @@ MEDIA_EXPORT VideoPixelFormat VideoPixelFormatFromSkColorType(SkColorType sk_color_type, bool is_opaque) { switch (sk_color_type) { case kRGBA_8888_SkColorType: - return is_opaque ? media::PIXEL_FORMAT_XBGR : media::PIXEL_FORMAT_ABGR; + return is_opaque ? PIXEL_FORMAT_XBGR : PIXEL_FORMAT_ABGR; case kBGRA_8888_SkColorType: - return is_opaque ? media::PIXEL_FORMAT_XRGB : media::PIXEL_FORMAT_ARGB; + return is_opaque ? PIXEL_FORMAT_XRGB : PIXEL_FORMAT_ARGB; default: // TODO(crbug.com/1073995): Add F16 support. - return media::PIXEL_FORMAT_UNKNOWN; + return PIXEL_FORMAT_UNKNOWN; } } diff --git a/chromium/media/base/video_util.h b/chromium/media/base/video_util.h index c778f5ef916..5e09b2c0e1e 100644 --- a/chromium/media/base/video_util.h +++ b/chromium/media/base/video_util.h @@ -87,6 +87,11 @@ MEDIA_EXPORT gfx::Rect ComputeLetterboxRegion(const gfx::Rect& bounds, MEDIA_EXPORT gfx::Rect ComputeLetterboxRegionForI420(const gfx::Rect& bounds, const gfx::Size& content); +// Shrinks the given |rect| by the minimum amount necessary to align its corners +// to even-numbered coordinates. |rect| is assumed to have bounded limit values, +// and may have negative bounds. +MEDIA_EXPORT gfx::Rect MinimallyShrinkRectForI420(const gfx::Rect& rect); + // Return a scaled |size| whose area is less than or equal to |target|, where // one of its dimensions is equal to |target|'s. The aspect ratio of |size| is // preserved as closely as possible. If |size| is empty, the result will be diff --git a/chromium/media/base/video_util_unittest.cc b/chromium/media/base/video_util_unittest.cc index e82e3caccbd..01eaf7626e6 100644 --- a/chromium/media/base/video_util_unittest.cc +++ b/chromium/media/base/video_util_unittest.cc @@ -9,8 +9,10 @@ #include <cmath> #include <memory> +#include "media/base/limits.h" #include "media/base/video_frame.h" #include "testing/gtest/include/gtest/gtest.h" +#include "ui/gfx/geometry/rect.h" namespace { @@ -410,6 +412,58 @@ TEST_F(VideoUtilTest, ComputeLetterboxRegionForI420) { .IsEmpty()); } +// Tests the MinimallyShrinkRectForI420 function. +TEST_F(VideoUtilTest, MinimallyShrinkRectForI420) { + // A few no-ops: + EXPECT_EQ(gfx::Rect(2, 2, 100, 100), + MinimallyShrinkRectForI420(gfx::Rect(2, 2, 100, 100))); + EXPECT_EQ(gfx::Rect(2, -2, 100, 100), + MinimallyShrinkRectForI420(gfx::Rect(2, -2, 100, 100))); + EXPECT_EQ(gfx::Rect(-2, 2, 100, 100), + MinimallyShrinkRectForI420(gfx::Rect(-2, 2, 100, 100))); + + // Origin has odd coordinates: + EXPECT_EQ(gfx::Rect(2, 2, 98, 98), + MinimallyShrinkRectForI420(gfx::Rect(1, 1, 100, 100))); + EXPECT_EQ(gfx::Rect(0, 2, 98, 98), + MinimallyShrinkRectForI420(gfx::Rect(-1, 1, 100, 100))); + EXPECT_EQ(gfx::Rect(2, 0, 98, 98), + MinimallyShrinkRectForI420(gfx::Rect(1, -1, 100, 100))); + + // Size is odd: + EXPECT_EQ(gfx::Rect(2, 2, 98, 98), + MinimallyShrinkRectForI420(gfx::Rect(2, 2, 99, 99))); + EXPECT_EQ(gfx::Rect(-2, 2, 98, 98), + MinimallyShrinkRectForI420(gfx::Rect(-2, 2, 99, 99))); + EXPECT_EQ(gfx::Rect(2, -2, 98, 98), + MinimallyShrinkRectForI420(gfx::Rect(2, -2, 99, 99))); + + // Both are odd: + EXPECT_EQ(gfx::Rect(2, 2, 98, 98), + MinimallyShrinkRectForI420(gfx::Rect(1, 1, 99, 99))); + EXPECT_EQ(gfx::Rect(0, 2, 98, 98), + MinimallyShrinkRectForI420(gfx::Rect(-1, 1, 99, 99))); + EXPECT_EQ(gfx::Rect(2, 0, 98, 98), + MinimallyShrinkRectForI420(gfx::Rect(1, -1, 99, 99))); + + // Check the biggest rectangle that the function will accept: + constexpr int kMinDimension = -1 * limits::kMaxDimension; + if (limits::kMaxDimension % 2 == 0) { + EXPECT_EQ(gfx::Rect(kMinDimension, kMinDimension, 2 * limits::kMaxDimension, + 2 * limits::kMaxDimension), + MinimallyShrinkRectForI420(gfx::Rect(kMinDimension, kMinDimension, + 2 * limits::kMaxDimension, + 2 * limits::kMaxDimension))); + } else { + EXPECT_EQ( + gfx::Rect(kMinDimension + 1, kMinDimension + 1, + 2 * limits::kMaxDimension - 2, 2 * limits::kMaxDimension - 2), + MinimallyShrinkRectForI420(gfx::Rect(kMinDimension, kMinDimension, + 2 * limits::kMaxDimension, + 2 * limits::kMaxDimension))); + } +} + TEST_F(VideoUtilTest, ScaleSizeToEncompassTarget) { EXPECT_EQ(gfx::Size(1000, 750), ScaleSizeToEncompassTarget(gfx::Size(640, 480), diff --git a/chromium/media/base/wall_clock_time_source_unittest.cc b/chromium/media/base/wall_clock_time_source_unittest.cc index 05c7718f63d..20b701a336a 100644 --- a/chromium/media/base/wall_clock_time_source_unittest.cc +++ b/chromium/media/base/wall_clock_time_source_unittest.cc @@ -5,6 +5,7 @@ #include <memory> #include "base/test/simple_test_tick_clock.h" +#include "base/time/time.h" #include "media/base/wall_clock_time_source.h" #include "testing/gtest/include/gtest/gtest.h" diff --git a/chromium/media/base/win/dcomp_texture_wrapper.h b/chromium/media/base/win/dcomp_texture_wrapper.h index 93eee07749a..2974ea75cb2 100644 --- a/chromium/media/base/win/dcomp_texture_wrapper.h +++ b/chromium/media/base/win/dcomp_texture_wrapper.h @@ -45,11 +45,9 @@ class DCOMPTextureWrapper { CreateVideoFrameCB create_video_frame_cb) = 0; using CreateDXVideoFrameCB = - base::OnceCallback<void(scoped_refptr<VideoFrame>, - const base::UnguessableToken& token)>; + base::OnceCallback<void(scoped_refptr<VideoFrame>)>; virtual void CreateVideoFrame(const gfx::Size& natural_size, gfx::GpuMemoryBufferHandle dx_handle, - const base::UnguessableToken& token, CreateDXVideoFrameCB create_video_frame_cb) = 0; }; diff --git a/chromium/media/base/win/hresult_status_helper.cc b/chromium/media/base/win/hresult_status_helper.cc deleted file mode 100644 index b8218fa94a4..00000000000 --- a/chromium/media/base/win/hresult_status_helper.cc +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 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. - -#include "media/base/win/hresult_status_helper.h" - -#include "base/logging.h" -#include "base/strings/string_util.h" - -namespace media { - -D3D11Status HresultToStatus(HRESULT hresult, - D3D11Status::Codes code, - const char* message, - const base::Location& location) { - if (SUCCEEDED(hresult)) - return D3D11Status::Codes::kOk; - - std::string sys_err = logging::SystemErrorCodeToString(hresult); - if (!base::IsStringUTF8AllowingNoncharacters(sys_err)) - sys_err = "System error string is invalid"; - - return D3D11Status(code, message == nullptr ? "HRESULT" : message, location) - .WithData("value", sys_err); -} - -} // namespace media diff --git a/chromium/media/base/win/media_foundation_cdm_proxy.h b/chromium/media/base/win/media_foundation_cdm_proxy.h index 8ba852ad61d..36831e9a331 100644 --- a/chromium/media/base/win/media_foundation_cdm_proxy.h +++ b/chromium/media/base/win/media_foundation_cdm_proxy.h @@ -60,6 +60,12 @@ class MediaFoundationCdmProxy // because they are in bad state. virtual void OnHardwareContextReset() = 0; + // Notify the CDM that significant playback (e.g. >1 minutes) has happened. + virtual void OnSignificantPlayback() = 0; + + // Notify the CDM that playback error happened. + virtual void OnPlaybackError() = 0; + protected: friend base::RefCountedThreadSafe<MediaFoundationCdmProxy>; virtual ~MediaFoundationCdmProxy() = default; |