diff options
author | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2021-03-12 09:13:00 +0100 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@qt.io> | 2021-03-16 09:58:26 +0000 |
commit | 03561cae90f1d99b5c54b1ef3be69f10e882b25e (patch) | |
tree | cc5f0958e823c044e7ae51cc0117fe51432abe5e /chromium/media/base | |
parent | fa98118a45f7e169f8846086dc2c22c49a8ba310 (diff) | |
download | qtwebengine-chromium-03561cae90f1d99b5c54b1ef3be69f10e882b25e.tar.gz |
BASELINE: Update Chromium to 88.0.4324.208
Change-Id: I3ae87d23e4eff4b4a469685658740a213600c667
Reviewed-by: Allan Sandfeld Jensen <allan.jensen@qt.io>
Diffstat (limited to 'chromium/media/base')
92 files changed, 1865 insertions, 703 deletions
diff --git a/chromium/media/base/BUILD.gn b/chromium/media/base/BUILD.gn index 676eb651405..f3ec9d91fd9 100644 --- a/chromium/media/base/BUILD.gn +++ b/chromium/media/base/BUILD.gn @@ -6,6 +6,7 @@ import("//build/config/android/config.gni") import("//build/config/arm.gni") import("//build/config/features.gni") import("//build/config/linux/pkg_config.gni") +import("//build/config/ozone.gni") import("//build/config/ui.gni") import("//media/media_options.gni") import("//testing/libfuzzer/fuzzer_test.gni") @@ -229,6 +230,8 @@ source_set("base") { "multi_channel_resampler.h", "null_video_sink.cc", "null_video_sink.h", + "offloading_video_encoder.cc", + "offloading_video_encoder.h", "output_device_info.cc", "output_device_info.h", "overlay_info.cc", @@ -355,6 +358,7 @@ source_set("base") { deps = [ "//base/allocator:buildflags", "//base/util/values:values_util", + "//build:chromeos_buildflags", "//components/system_media_controls/linux/buildflags", "//gpu/command_buffer/client:interface_base", "//gpu/command_buffer/common", @@ -362,6 +366,7 @@ source_set("base") { "//third_party/libyuv", "//third_party/widevine/cdm:headers", "//ui/display:display", + "//ui/events:events", "//ui/events:events_base", "//url:url", ] @@ -387,7 +392,7 @@ source_set("base") { deps += [ "//third_party/libvpx" ] } - if (use_x11) { + if (use_x11 || ozone_platform_x11) { sources += [ "user_input_monitor_linux.cc" ] deps += [ "//ui/base:features", @@ -408,12 +413,11 @@ source_set("base") { } else { defines += [ "DISABLE_USER_INPUT_MONITOR" ] } - - if (is_linux || is_chromeos || is_win) { - sources += [ - "keyboard_event_counter.cc", - "keyboard_event_counter.h", - ] + if (use_x11) { + deps += [ "//ui/base/x" ] + } + if (use_ozone) { + deps += [ "//ui/ozone" ] } # Note: should also work on is_posix || is_fuchsia @@ -428,10 +432,14 @@ source_set("base") { public_deps += [ "//media/base/win:mf_cdm_proxy" ] } - if (is_chromecast || is_fuchsia) { - sources += [ "demuxer_memory_limit_low.cc" ] - } else if (is_android) { + # TODO(ziyangch): Check |is_chromecast| first when using cast media pipeline + # on Android cast devices. + if (is_android) { sources += [ "demuxer_memory_limit_android.cc" ] + } else if (is_chromecast) { + sources += [ "demuxer_memory_limit_cast.cc" ] + } else if (is_fuchsia) { + sources += [ "demuxer_memory_limit_low.cc" ] } else { sources += [ "demuxer_memory_limit_default.cc" ] } @@ -570,6 +578,7 @@ source_set("unit_tests") { "moving_average_unittest.cc", "multi_channel_resampler_unittest.cc", "null_video_sink_unittest.cc", + "offloading_video_encoder_unittest.cc", "pipeline_impl_unittest.cc", "ranges_unittest.cc", "reentrancy_checker_unittest.cc", @@ -608,6 +617,7 @@ source_set("unit_tests") { ] deps = [ "//base/test:test_support", + "//build:chromeos_buildflags", "//components/viz/common", "//gpu/command_buffer/common", "//media:test_support", @@ -622,9 +632,6 @@ source_set("unit_tests") { deps += [ "//media/base/mac:unit_tests" ] } - if (is_linux || is_chromeos || is_win) { - sources += [ "keyboard_event_counter_unittest.cc" ] - } if (is_win) { sources += [ "win/dxgi_device_scope_handle_unittest.cc" ] deps += [ "//media/base/win:media_foundation_util" ] @@ -633,6 +640,10 @@ source_set("unit_tests") { "mfplat.lib", ] } + + if (is_chromecast && !is_android) { + sources += [ "demuxer_memory_limit_cast_unittest.cc" ] + } } source_set("perftests") { diff --git a/chromium/media/base/android/jni_hdr_metadata.cc b/chromium/media/base/android/jni_hdr_metadata.cc index 939577a88c8..de677849648 100644 --- a/chromium/media/base/android/jni_hdr_metadata.cc +++ b/chromium/media/base/android/jni_hdr_metadata.cc @@ -6,12 +6,12 @@ #include "media/base/android/media_jni_headers/HdrMetadata_jni.h" #include "media/base/video_color_space.h" -#include "ui/gl/hdr_metadata.h" +#include "ui/gfx/hdr_metadata.h" namespace media { JniHdrMetadata::JniHdrMetadata(const VideoColorSpace& color_space, - const gl::HDRMetadata& hdr_metadata) + const gfx::HDRMetadata& hdr_metadata) : color_space_(color_space), hdr_metadata_(hdr_metadata) { JNIEnv* env = base::android::AttachCurrentThread(); jobject_ = Java_HdrMetadata_create(env, reinterpret_cast<jlong>(this)); diff --git a/chromium/media/base/android/jni_hdr_metadata.h b/chromium/media/base/android/jni_hdr_metadata.h index af3510f3bf8..f7ea00533c2 100644 --- a/chromium/media/base/android/jni_hdr_metadata.h +++ b/chromium/media/base/android/jni_hdr_metadata.h @@ -7,7 +7,7 @@ #include "base/android/jni_android.h" #include "base/macros.h" -#include "ui/gl/hdr_metadata.h" +#include "ui/gfx/hdr_metadata.h" namespace media { @@ -16,7 +16,7 @@ class VideoColorSpace; class JniHdrMetadata { public: JniHdrMetadata(const VideoColorSpace& color_space, - const gl::HDRMetadata& hdr_metadata); + const gfx::HDRMetadata& hdr_metadata); ~JniHdrMetadata(); base::android::ScopedJavaLocalRef<jobject> obj() { return jobject_; } @@ -58,7 +58,7 @@ class JniHdrMetadata { private: const VideoColorSpace& color_space_; - const gl::HDRMetadata& hdr_metadata_; + const gfx::HDRMetadata& hdr_metadata_; base::android::ScopedJavaLocalRef<jobject> jobject_; DISALLOW_COPY_AND_ASSIGN(JniHdrMetadata); diff --git a/chromium/media/base/android/media_codec_bridge_impl.h b/chromium/media/base/android/media_codec_bridge_impl.h index c21ec38bab6..1d4ce6da9d8 100644 --- a/chromium/media/base/android/media_codec_bridge_impl.h +++ b/chromium/media/base/android/media_codec_bridge_impl.h @@ -20,7 +20,7 @@ #include "media/base/media_export.h" #include "media/base/video_decoder_config.h" #include "ui/gfx/geometry/size.h" -#include "ui/gl/hdr_metadata.h" +#include "ui/gfx/hdr_metadata.h" namespace media { @@ -54,7 +54,7 @@ class MEDIA_EXPORT VideoCodecConfig { // VP9 HDR metadata is only embedded in the container. HDR10 metadata is // embedded in the video stream. - base::Optional<gl::HDRMetadata> hdr_metadata; + base::Optional<gfx::HDRMetadata> hdr_metadata; // Enables the async MediaCodec.Callback API. |on_buffers_available_cb| // will be called when input or output buffers are available. This will be diff --git a/chromium/media/base/android/media_drm_bridge.cc b/chromium/media/base/android/media_drm_bridge.cc index d71a30826da..e5d7978a28f 100644 --- a/chromium/media/base/android/media_drm_bridge.cc +++ b/chromium/media/base/android/media_drm_bridge.cc @@ -689,10 +689,11 @@ void MediaDrmBridge::OnProvisionRequest( std::string request_data; JavaByteArrayToString(env, j_request_data, &request_data); + std::string default_url; + ConvertJavaStringToUTF8(env, j_default_url, &default_url); task_runner_->PostTask( FROM_HERE, base::BindOnce(&MediaDrmBridge::SendProvisioningRequest, - weak_factory_.GetWeakPtr(), - ConvertJavaStringToUTF8(env, j_default_url), + weak_factory_.GetWeakPtr(), GURL(default_url), std::move(request_data))); } @@ -944,7 +945,7 @@ void MediaDrmBridge::NotifyMediaCryptoReady(JavaObjectPtr j_media_crypto) { IsSecureCodecRequired()); } -void MediaDrmBridge::SendProvisioningRequest(const std::string& default_url, +void MediaDrmBridge::SendProvisioningRequest(const GURL& default_url, const std::string& request_data) { DCHECK(task_runner_->BelongsToCurrentThread()); DVLOG(1) << __func__; diff --git a/chromium/media/base/android/media_drm_bridge.h b/chromium/media/base/android/media_drm_bridge.h index 56104ea9748..abbbf7a6d61 100644 --- a/chromium/media/base/android/media_drm_bridge.h +++ b/chromium/media/base/android/media_drm_bridge.h @@ -287,7 +287,7 @@ class MEDIA_EXPORT MediaDrmBridge : public ContentDecryptionModule, void NotifyMediaCryptoReady(JavaObjectPtr j_media_crypto); // Sends HTTP provisioning request to a provisioning server. - void SendProvisioningRequest(const std::string& default_url, + void SendProvisioningRequest(const GURL& default_url, const std::string& request_data); // Process the data received by provisioning server. diff --git a/chromium/media/base/android/media_drm_bridge_unittest.cc b/chromium/media/base/android/media_drm_bridge_unittest.cc index 81243581abe..40c31575c49 100644 --- a/chromium/media/base/android/media_drm_bridge_unittest.cc +++ b/chromium/media/base/android/media_drm_bridge_unittest.cc @@ -6,7 +6,7 @@ #include "base/android/build_info.h" #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/logging.h" #include "base/memory/ptr_util.h" #include "base/run_loop.h" @@ -66,7 +66,7 @@ class ProvisionFetcherWrapper : public ProvisionFetcher { : provision_fetcher_(provision_fetcher) {} // ProvisionFetcher implementation. - void Retrieve(const std::string& default_url, + void Retrieve(const GURL& default_url, const std::string& request_data, ResponseCB response_cb) override { provision_fetcher_->Retrieve(default_url, request_data, @@ -96,7 +96,7 @@ class MediaDrmBridgeTest : public ProvisionFetcher, public testing::Test { // ProvisionFetcher implementation. Done as a mock method so we can properly // check if |media_drm_bridge_| invokes it or not. MOCK_METHOD3(Retrieve, - void(const std::string& default_url, + void(const GURL& default_url, const std::string& request_data, ResponseCB response_cb)); diff --git a/chromium/media/base/android/media_service_throttler.cc b/chromium/media/base/android/media_service_throttler.cc index ca54bb24204..d950218eebd 100644 --- a/chromium/media/base/android/media_service_throttler.cc +++ b/chromium/media/base/android/media_service_throttler.cc @@ -7,7 +7,7 @@ #include <memory> #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/threading/thread_task_runner_handle.h" #include "base/time/default_tick_clock.h" #include "media/base/android/media_server_crash_listener.h" diff --git a/chromium/media/base/async_destroy_video_encoder.h b/chromium/media/base/async_destroy_video_encoder.h index 8576205af49..1a94cf5b339 100644 --- a/chromium/media/base/async_destroy_video_encoder.h +++ b/chromium/media/base/async_destroy_video_encoder.h @@ -52,9 +52,12 @@ class AsyncDestroyVideoEncoder final : public VideoEncoder { wrapped_encoder_->Encode(std::move(frame), key_frame, std::move(done_cb)); } - void ChangeOptions(const Options& options, StatusCB done_cb) override { + void ChangeOptions(const Options& options, + OutputCB output_cb, + StatusCB done_cb) override { DCHECK(wrapped_encoder_); - wrapped_encoder_->ChangeOptions(options, std::move(done_cb)); + wrapped_encoder_->ChangeOptions(options, std::move(output_cb), + std::move(done_cb)); } void Flush(StatusCB done_cb) override { diff --git a/chromium/media/base/audio_buffer.cc b/chromium/media/base/audio_buffer.cc index 622c9154f4f..ad6bd58c9c7 100644 --- a/chromium/media/base/audio_buffer.cc +++ b/chromium/media/base/audio_buffer.cc @@ -39,8 +39,12 @@ AudioBufferMemoryPool::AudioMemory AudioBufferMemoryPool::CreateBuffer( return std::move(entry.first); } - return AudioMemory(static_cast<uint8_t*>( + // FFmpeg may not always initialize the entire output memory, so just like + // for VideoFrames we need to zero out the memory. https://crbug.com/1144070. + auto memory = AudioMemory(static_cast<uint8_t*>( base::AlignedAlloc(size, AudioBuffer::kChannelAlignment))); + memset(memory.get(), 0, size); + return memory; } void AudioBufferMemoryPool::ReturnBuffer(AudioMemory memory, size_t size) { @@ -228,12 +232,6 @@ scoped_refptr<AudioBuffer> AudioBuffer::CreateEOSBuffer() { nullptr, 0, kNoTimestamp, nullptr)); } -// Convert int16_t values in the range [INT16_MIN, INT16_MAX] to [-1.0, 1.0]. -inline float ConvertSample(int16_t value) { - return value * (value < 0 ? -1.0f / std::numeric_limits<int16_t>::min() - : 1.0f / std::numeric_limits<int16_t>::max()); -} - void AudioBuffer::AdjustSampleRate(int sample_rate) { DCHECK(!end_of_stream_); sample_rate_ = sample_rate; @@ -281,14 +279,16 @@ void AudioBuffer::ReadFrames(int frames_to_copy, return; } + // Note: The conversion steps below will clip values to [1.0, -1.0f]. + if (sample_format_ == kSampleFormatPlanarF32) { - // Format is planar float32. Copy the data from each channel as a block. for (int ch = 0; ch < channel_count_; ++ch) { + float* dest_data = dest->channel(ch) + dest_frame_offset; const float* source_data = reinterpret_cast<const float*>(channel_data_[ch]) + source_frame_offset; - memcpy(dest->channel(ch) + dest_frame_offset, source_data, - sizeof(float) * frames_to_copy); + for (int i = 0; i < frames_to_copy; ++i) + dest_data[i] = Float32SampleTypeTraits::FromFloat(source_data[i]); } return; } @@ -301,37 +301,35 @@ void AudioBuffer::ReadFrames(int frames_to_copy, reinterpret_cast<const int16_t*>(channel_data_[ch]) + source_frame_offset; float* dest_data = dest->channel(ch) + dest_frame_offset; - for (int i = 0; i < frames_to_copy; ++i) { - dest_data[i] = ConvertSample(source_data[i]); - } + for (int i = 0; i < frames_to_copy; ++i) + dest_data[i] = SignedInt16SampleTypeTraits::ToFloat(source_data[i]); } return; } + const int bytes_per_channel = SampleFormatToBytesPerChannel(sample_format_); + const int frame_size = channel_count_ * bytes_per_channel; + const uint8_t* source_data = data_.get() + source_frame_offset * frame_size; + if (sample_format_ == kSampleFormatF32) { - // Format is interleaved float32. Copy the data into each channel. - const float* source_data = reinterpret_cast<const float*>(data_.get()) + - source_frame_offset * channel_count_; - for (int ch = 0; ch < channel_count_; ++ch) { - float* dest_data = dest->channel(ch) + dest_frame_offset; - for (int i = 0, offset = ch; i < frames_to_copy; - ++i, offset += channel_count_) { - dest_data[i] = source_data[offset]; - } - } - return; + dest->FromInterleavedPartial<Float32SampleTypeTraits>( + reinterpret_cast<const float*>(source_data), dest_frame_offset, + frames_to_copy); + } else if (sample_format_ == kSampleFormatU8) { + dest->FromInterleavedPartial<UnsignedInt8SampleTypeTraits>( + source_data, dest_frame_offset, frames_to_copy); + } else if (sample_format_ == kSampleFormatS16) { + dest->FromInterleavedPartial<SignedInt16SampleTypeTraits>( + reinterpret_cast<const int16_t*>(source_data), dest_frame_offset, + frames_to_copy); + } else if (sample_format_ == kSampleFormatS24 || + sample_format_ == kSampleFormatS32) { + dest->FromInterleavedPartial<SignedInt32SampleTypeTraits>( + reinterpret_cast<const int32_t*>(source_data), dest_frame_offset, + frames_to_copy); + } else { + NOTREACHED() << "Unsupported audio sample type: " << sample_format_; } - - // Remaining formats are integer interleaved data. Use the deinterleaving code - // in AudioBus to copy the data. - DCHECK( - sample_format_ == kSampleFormatU8 || sample_format_ == kSampleFormatS16 || - sample_format_ == kSampleFormatS24 || sample_format_ == kSampleFormatS32); - int bytes_per_channel = SampleFormatToBytesPerChannel(sample_format_); - int frame_size = channel_count_ * bytes_per_channel; - const uint8_t* source_data = data_.get() + source_frame_offset * frame_size; - dest->FromInterleavedPartial(source_data, dest_frame_offset, frames_to_copy, - bytes_per_channel); } void AudioBuffer::TrimStart(int frames_to_trim) { diff --git a/chromium/media/base/audio_buffer.h b/chromium/media/base/audio_buffer.h index 71f5c87e8b7..55adc82837f 100644 --- a/chromium/media/base/audio_buffer.h +++ b/chromium/media/base/audio_buffer.h @@ -124,8 +124,8 @@ class MEDIA_EXPORT AudioBuffer // Copy frames into |dest|. |frames_to_copy| is the number of frames to copy. // |source_frame_offset| specifies how many frames in the buffer to skip // first. |dest_frame_offset| is the frame offset in |dest|. The frames are - // converted from their source format into planar float32 data (which is all - // that AudioBus handles). + // converted and clipped from their source format into planar float32 data + // (which is all that AudioBus handles). void ReadFrames(int frames_to_copy, int source_frame_offset, int dest_frame_offset, diff --git a/chromium/media/base/audio_buffer_queue_unittest.cc b/chromium/media/base/audio_buffer_queue_unittest.cc index 3cf5e120c56..94e20d581a5 100644 --- a/chromium/media/base/audio_buffer_queue_unittest.cc +++ b/chromium/media/base/audio_buffer_queue_unittest.cc @@ -18,18 +18,24 @@ namespace media { -const int kSampleRate = 44100; +constexpr int kSampleRate = 44100; +enum class ValueType { kNormal, kFloat }; static void VerifyBus(AudioBus* bus, int offset, int frames, int buffer_size, float start, - float increment) { + float increment, + ValueType type = ValueType::kNormal) { for (int ch = 0; ch < bus->channels(); ++ch) { const float v = start + ch * buffer_size * increment; for (int i = offset; i < offset + frames; ++i) { - ASSERT_FLOAT_EQ(v + (i - offset) * increment, bus->channel(ch)[i]) + float expected_value = v + (i - offset) * increment; + if (type == ValueType::kFloat) + expected_value /= std::numeric_limits<uint16_t>::max(); + + ASSERT_FLOAT_EQ(expected_value, bus->channel(ch)[i]) << "i=" << i << ", ch=" << ch; } } @@ -94,7 +100,7 @@ TEST(AudioBufferQueueTest, IteratorCheck) { EXPECT_EQ(4, buffer.ReadFrames(4, 0, bus.get())); EXPECT_EQ(4, buffer.frames()); - VerifyBus(bus.get(), 0, 4, bus->frames(), 10, 1); + VerifyBus(bus.get(), 0, 4, bus->frames(), 10, 1, ValueType::kFloat); buffer.Append(MakeTestBuffer<float>( kSampleFormatF32, channel_layout, 20.0f, 1.0f, 8)); @@ -106,7 +112,7 @@ TEST(AudioBufferQueueTest, IteratorCheck) { buffer.SeekFrames(16); EXPECT_EQ(4, buffer.ReadFrames(4, 0, bus.get())); EXPECT_EQ(0, buffer.frames()); - VerifyBus(bus.get(), 0, 4, bus->frames(), 34, 1); + VerifyBus(bus.get(), 0, 4, bus->frames(), 34, 1, ValueType::kFloat); buffer.Append(MakeTestBuffer<float>( kSampleFormatF32, channel_layout, 40.0f, 1.0f, 8)); @@ -116,13 +122,13 @@ TEST(AudioBufferQueueTest, IteratorCheck) { EXPECT_EQ(16, buffer.frames()); EXPECT_EQ(4, buffer.ReadFrames(4, 0, bus.get())); - VerifyBus(bus.get(), 0, 4, bus->frames(), 40, 1); + VerifyBus(bus.get(), 0, 4, bus->frames(), 40, 1, ValueType::kFloat); // Read off the end of the buffer. EXPECT_EQ(12, buffer.frames()); buffer.SeekFrames(8); EXPECT_EQ(4, buffer.ReadFrames(100, 0, bus.get())); - VerifyBus(bus.get(), 0, 4, bus->frames(), 54, 1); + VerifyBus(bus.get(), 0, 4, bus->frames(), 54, 1, ValueType::kFloat); } TEST(AudioBufferQueueTest, Seek) { @@ -188,13 +194,13 @@ TEST(AudioBufferQueueTest, ReadF32) { std::unique_ptr<AudioBus> bus = AudioBus::Create(channels, 100); EXPECT_EQ(3, buffer.ReadFrames(3, 0, bus.get())); EXPECT_EQ(73, buffer.frames()); - VerifyBus(bus.get(), 0, 3, 6, 1, 1); + VerifyBus(bus.get(), 0, 3, 6, 1, 1, ValueType::kFloat); // Now read 5 frames, which will span buffers. Append the data into AudioBus. EXPECT_EQ(5, buffer.ReadFrames(5, 3, bus.get())); EXPECT_EQ(68, buffer.frames()); - VerifyBus(bus.get(), 0, 6, 6, 1, 1); - VerifyBus(bus.get(), 6, 2, 10, 13, 1); + VerifyBus(bus.get(), 0, 6, 6, 1, 1, ValueType::kFloat); + VerifyBus(bus.get(), 6, 2, 10, 13, 1, ValueType::kFloat); // Now skip into the third buffer. buffer.SeekFrames(20); @@ -202,7 +208,7 @@ TEST(AudioBufferQueueTest, ReadF32) { // Now read 2 frames, which are in the third buffer. EXPECT_EQ(2, buffer.ReadFrames(2, 0, bus.get())); - VerifyBus(bus.get(), 0, 2, 60, 45, 1); + VerifyBus(bus.get(), 0, 2, 60, 45, 1, ValueType::kFloat); } TEST(AudioBufferQueueTest, ReadU8) { @@ -289,8 +295,8 @@ TEST(AudioBufferQueueTest, ReadF32Planar) { std::unique_ptr<AudioBus> bus = AudioBus::Create(channels, 100); EXPECT_EQ(6, buffer.ReadFrames(6, 0, bus.get())); EXPECT_EQ(8, buffer.frames()); - VerifyBus(bus.get(), 0, 4, 4, 1, 1); - VerifyBus(bus.get(), 4, 2, 10, 50, 1); + VerifyBus(bus.get(), 0, 4, 4, 1, 1, ValueType::kFloat); + VerifyBus(bus.get(), 4, 2, 10, 50, 1, ValueType::kFloat); } TEST(AudioBufferQueueTest, ReadS16Planar) { @@ -333,9 +339,9 @@ TEST(AudioBufferQueueTest, ReadManyChannels) { std::unique_ptr<AudioBus> bus = AudioBus::Create(channels, 100); EXPECT_EQ(30, buffer.ReadFrames(30, 0, bus.get())); EXPECT_EQ(46, buffer.frames()); - VerifyBus(bus.get(), 0, 6, 6, 0, 1); - VerifyBus(bus.get(), 6, 10, 10, 6 * channels, 1); - VerifyBus(bus.get(), 16, 14, 60, 16 * channels, 1); + VerifyBus(bus.get(), 0, 6, 6, 0, 1, ValueType::kFloat); + VerifyBus(bus.get(), 6, 10, 10, 6 * channels, 1, ValueType::kFloat); + VerifyBus(bus.get(), 16, 14, 60, 16 * channels, 1, ValueType::kFloat); } TEST(AudioBufferQueueTest, Peek) { @@ -355,17 +361,17 @@ TEST(AudioBufferQueueTest, Peek) { EXPECT_EQ(frames, buffer.PeekFrames(60, 0, 0, bus1.get())); EXPECT_EQ(30, buffer.PeekFrames(30, 0, 0, bus1.get())); EXPECT_EQ(frames, buffer.frames()); - VerifyBus(bus1.get(), 0, 30, bus1->frames(), 0, 1); + VerifyBus(bus1.get(), 0, 30, bus1->frames(), 0, 1, ValueType::kFloat); // Now read the next 30 frames (which should be the same as those peeked at). std::unique_ptr<AudioBus> bus2 = AudioBus::Create(channels, frames); EXPECT_EQ(30, buffer.ReadFrames(30, 0, bus2.get())); - VerifyBus(bus2.get(), 0, 30, bus2->frames(), 0, 1); + VerifyBus(bus2.get(), 0, 30, bus2->frames(), 0, 1, ValueType::kFloat); // Peek 10 frames forward bus1->Zero(); EXPECT_EQ(5, buffer.PeekFrames(5, 10, 0, bus1.get())); - VerifyBus(bus1.get(), 0, 5, bus1->frames(), 40, 1); + VerifyBus(bus1.get(), 0, 5, bus1->frames(), 40, 1, ValueType::kFloat); // Peek to the end of the buffer. EXPECT_EQ(30, buffer.frames()); diff --git a/chromium/media/base/audio_buffer_unittest.cc b/chromium/media/base/audio_buffer_unittest.cc index 31b5f4d0470..c769bd5adc2 100644 --- a/chromium/media/base/audio_buffer_unittest.cc +++ b/chromium/media/base/audio_buffer_unittest.cc @@ -14,25 +14,34 @@ namespace media { -static const int kSampleRate = 4800; +constexpr int kSampleRate = 4800; +enum class ValueType { kNormal, kFloat }; static void VerifyBusWithOffset(AudioBus* bus, int offset, int frames, float start, float start_offset, - float increment) { + float increment, + ValueType type = ValueType::kNormal) { for (int ch = 0; ch < bus->channels(); ++ch) { const float v = start_offset + start + ch * bus->frames() * increment; for (int i = offset; i < offset + frames; ++i) { - ASSERT_FLOAT_EQ(v + i * increment, bus->channel(ch)[i]) << "i=" << i - << ", ch=" << ch; + float expected_value = v + i * increment; + if (type == ValueType::kFloat) + expected_value /= std::numeric_limits<uint16_t>::max(); + ASSERT_FLOAT_EQ(expected_value, bus->channel(ch)[i]) + << "i=" << i << ", ch=" << ch; } } } -static void VerifyBus(AudioBus* bus, int frames, float start, float increment) { - VerifyBusWithOffset(bus, 0, frames, start, 0, increment); +static void VerifyBus(AudioBus* bus, + int frames, + float start, + float increment, + ValueType type = ValueType::kNormal) { + VerifyBusWithOffset(bus, 0, frames, start, 0, increment, type); } static void TrimRangeTest(SampleFormat sample_format) { @@ -57,7 +66,7 @@ static void TrimRangeTest(SampleFormat sample_format) { // Verify all frames before trimming. buffer->ReadFrames(frames, 0, 0, bus.get()); - VerifyBus(bus.get(), frames, 0, 1); + VerifyBus(bus.get(), frames, 0, 1, ValueType::kFloat); // Trim 10ms of frames from the middle of the buffer. int trim_start = frames / 2; @@ -69,13 +78,9 @@ static void TrimRangeTest(SampleFormat sample_format) { EXPECT_EQ(duration - trim_duration, buffer->duration()); bus->Zero(); buffer->ReadFrames(buffer->frame_count(), 0, 0, bus.get()); - VerifyBus(bus.get(), trim_start, 0, 1); - VerifyBusWithOffset(bus.get(), - trim_start, - buffer->frame_count() - trim_start, - 0, - trim_length, - 1); + VerifyBus(bus.get(), trim_start, 0, 1, ValueType::kFloat); + VerifyBusWithOffset(bus.get(), trim_start, buffer->frame_count() - trim_start, + 0, trim_length, 1, ValueType::kFloat); // Trim 10ms of frames from the start, which just adjusts the buffer's // internal start offset. @@ -86,13 +91,9 @@ static void TrimRangeTest(SampleFormat sample_format) { EXPECT_EQ(duration - 2 * trim_duration, buffer->duration()); bus->Zero(); buffer->ReadFrames(buffer->frame_count(), 0, 0, bus.get()); - VerifyBus(bus.get(), trim_start, trim_length, 1); - VerifyBusWithOffset(bus.get(), - trim_start, - buffer->frame_count() - trim_start, - trim_length, - trim_length, - 1); + VerifyBus(bus.get(), trim_start, trim_length, 1, ValueType::kFloat); + VerifyBusWithOffset(bus.get(), trim_start, buffer->frame_count() - trim_start, + trim_length, trim_length, 1, ValueType::kFloat); // Trim 10ms of frames from the end, which just adjusts the buffer's frame // count. @@ -102,13 +103,9 @@ static void TrimRangeTest(SampleFormat sample_format) { EXPECT_EQ(duration - 3 * trim_duration, buffer->duration()); bus->Zero(); buffer->ReadFrames(buffer->frame_count(), 0, 0, bus.get()); - VerifyBus(bus.get(), trim_start, trim_length, 1); - VerifyBusWithOffset(bus.get(), - trim_start, - buffer->frame_count() - trim_start, - trim_length, - trim_length, - 1); + VerifyBus(bus.get(), trim_start, trim_length, 1, ValueType::kFloat); + VerifyBusWithOffset(bus.get(), trim_start, buffer->frame_count() - trim_start, + trim_length, trim_length, 1, ValueType::kFloat); // Trim another 10ms from the inner portion of the buffer. buffer->TrimRange(trim_start, trim_start + trim_length); @@ -117,13 +114,9 @@ static void TrimRangeTest(SampleFormat sample_format) { EXPECT_EQ(duration - 4 * trim_duration, buffer->duration()); bus->Zero(); buffer->ReadFrames(buffer->frame_count(), 0, 0, bus.get()); - VerifyBus(bus.get(), trim_start, trim_length, 1); - VerifyBusWithOffset(bus.get(), - trim_start, - buffer->frame_count() - trim_start, - trim_length, - trim_length * 2, - 1); + VerifyBus(bus.get(), trim_start, trim_length, 1, ValueType::kFloat); + VerifyBusWithOffset(bus.get(), trim_start, buffer->frame_count() - trim_start, + trim_length, trim_length * 2, 1, ValueType::kFloat); // Trim off the end using TrimRange() to ensure end index is exclusive. buffer->TrimRange(buffer->frame_count() - trim_length, buffer->frame_count()); @@ -132,13 +125,9 @@ static void TrimRangeTest(SampleFormat sample_format) { EXPECT_EQ(duration - 5 * trim_duration, buffer->duration()); bus->Zero(); buffer->ReadFrames(buffer->frame_count(), 0, 0, bus.get()); - VerifyBus(bus.get(), trim_start, trim_length, 1); - VerifyBusWithOffset(bus.get(), - trim_start, - buffer->frame_count() - trim_start, - trim_length, - trim_length * 2, - 1); + VerifyBus(bus.get(), trim_start, trim_length, 1, ValueType::kFloat); + VerifyBusWithOffset(bus.get(), trim_start, buffer->frame_count() - trim_start, + trim_length, trim_length * 2, 1, ValueType::kFloat); // Trim off the start using TrimRange() to ensure start index is inclusive. buffer->TrimRange(0, trim_length); @@ -148,13 +137,9 @@ static void TrimRangeTest(SampleFormat sample_format) { EXPECT_EQ(duration - 6 * trim_duration, buffer->duration()); bus->Zero(); buffer->ReadFrames(buffer->frame_count(), 0, 0, bus.get()); - VerifyBus(bus.get(), trim_start, 2 * trim_length, 1); - VerifyBusWithOffset(bus.get(), - trim_start, - buffer->frame_count() - trim_start, - trim_length * 2, - trim_length * 2, - 1); + VerifyBus(bus.get(), trim_start, 2 * trim_length, 1, ValueType::kFloat); + VerifyBusWithOffset(bus.get(), trim_start, buffer->frame_count() - trim_start, + trim_length * 2, trim_length * 2, 1, ValueType::kFloat); } TEST(AudioBufferTest, CopyFrom) { @@ -345,12 +330,12 @@ TEST(AudioBufferTest, ReadF32) { start_time); std::unique_ptr<AudioBus> bus = AudioBus::Create(channels, frames); buffer->ReadFrames(10, 0, 0, bus.get()); - VerifyBus(bus.get(), 10, 1, 1); + VerifyBus(bus.get(), 10, 1, 1, ValueType::kFloat); // Read second 10 frames. bus->Zero(); buffer->ReadFrames(10, 10, 0, bus.get()); - VerifyBus(bus.get(), 10, 11, 1); + VerifyBus(bus.get(), 10, 11, 1, ValueType::kFloat); } TEST(AudioBufferTest, ReadS16Planar) { @@ -406,12 +391,12 @@ TEST(AudioBufferTest, ReadF32Planar) { // channels. std::unique_ptr<AudioBus> bus = AudioBus::Create(channels, 100); buffer->ReadFrames(frames, 0, 0, bus.get()); - VerifyBus(bus.get(), frames, 1, 1); + VerifyBus(bus.get(), frames, 1, 1, ValueType::kFloat); // Now read 20 frames from the middle of the buffer. bus->Zero(); buffer->ReadFrames(20, 50, 0, bus.get()); - VerifyBus(bus.get(), 20, 51, 1); + VerifyBus(bus.get(), 20, 51, 1, ValueType::kFloat); } TEST(AudioBufferTest, EmptyBuffer) { @@ -487,7 +472,7 @@ TEST(AudioBufferTest, Trim) { std::unique_ptr<AudioBus> bus = AudioBus::Create(channels, frames); buffer->ReadFrames(buffer->frame_count(), 0, 0, bus.get()); - VerifyBus(bus.get(), buffer->frame_count(), 0.0f, 1.0f); + VerifyBus(bus.get(), buffer->frame_count(), 0.0f, 1.0f, ValueType::kFloat); // Trim off 10ms of frames from the start. buffer->TrimStart(ten_ms_of_frames); @@ -495,7 +480,8 @@ TEST(AudioBufferTest, Trim) { EXPECT_EQ(frames - ten_ms_of_frames, buffer->frame_count()); EXPECT_EQ(duration - ten_ms, buffer->duration()); buffer->ReadFrames(buffer->frame_count(), 0, 0, bus.get()); - VerifyBus(bus.get(), buffer->frame_count(), ten_ms_of_frames, 1.0f); + VerifyBus(bus.get(), buffer->frame_count(), ten_ms_of_frames, 1.0f, + ValueType::kFloat); // Trim off 10ms of frames from the end. buffer->TrimEnd(ten_ms_of_frames); @@ -503,7 +489,8 @@ TEST(AudioBufferTest, Trim) { EXPECT_EQ(frames - 2 * ten_ms_of_frames, buffer->frame_count()); EXPECT_EQ(duration - 2 * ten_ms, buffer->duration()); buffer->ReadFrames(buffer->frame_count(), 0, 0, bus.get()); - VerifyBus(bus.get(), buffer->frame_count(), ten_ms_of_frames, 1.0f); + VerifyBus(bus.get(), buffer->frame_count(), ten_ms_of_frames, 1.0f, + ValueType::kFloat); // Trim off 40ms more from the start. buffer->TrimStart(4 * ten_ms_of_frames); @@ -511,7 +498,8 @@ TEST(AudioBufferTest, Trim) { EXPECT_EQ(frames - 6 * ten_ms_of_frames, buffer->frame_count()); EXPECT_EQ(duration - 6 * ten_ms, buffer->duration()); buffer->ReadFrames(buffer->frame_count(), 0, 0, bus.get()); - VerifyBus(bus.get(), buffer->frame_count(), 5 * ten_ms_of_frames, 1.0f); + VerifyBus(bus.get(), buffer->frame_count(), 5 * ten_ms_of_frames, 1.0f, + ValueType::kFloat); // Trim off the final 40ms from the end. buffer->TrimEnd(4 * ten_ms_of_frames); diff --git a/chromium/media/base/audio_converter.cc b/chromium/media/base/audio_converter.cc index 8d56906b31f..5b000656c3d 100644 --- a/chromium/media/base/audio_converter.cc +++ b/chromium/media/base/audio_converter.cc @@ -13,7 +13,7 @@ #include <algorithm> #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/logging.h" #include "base/trace_event/trace_event.h" #include "media/base/audio_bus.h" diff --git a/chromium/media/base/audio_discard_helper_unittest.cc b/chromium/media/base/audio_discard_helper_unittest.cc index 324439d5f82..9300fea296c 100644 --- a/chromium/media/base/audio_discard_helper_unittest.cc +++ b/chromium/media/base/audio_discard_helper_unittest.cc @@ -40,7 +40,7 @@ static float ExtractDecodedData(const AudioBuffer& buffer, int index) { std::unique_ptr<AudioBus> temp_bus = AudioBus::Create(buffer.channel_count(), 1); buffer.ReadFrames(1, index, 0, temp_bus.get()); - return temp_bus->channel(0)[0]; + return temp_bus->channel(0)[0] * std::numeric_limits<uint16_t>::max(); } TEST(AudioDiscardHelperTest, TimeDeltaToFrames) { diff --git a/chromium/media/base/audio_encoder.cc b/chromium/media/base/audio_encoder.cc index 0a9ca22e96f..64b5cab9f0a 100644 --- a/chromium/media/base/audio_encoder.cc +++ b/chromium/media/base/audio_encoder.cc @@ -38,14 +38,16 @@ AudioEncoder::AudioEncoder(const AudioParameters& input_params, DCHECK(audio_input_params_.IsValid()); DCHECK(!encode_callback_.is_null()); DCHECK(!status_callback_.is_null()); - DETACH_FROM_THREAD(thread_checker_); + DETACH_FROM_SEQUENCE(sequence_checker_); } -AudioEncoder::~AudioEncoder() = default; +AudioEncoder::~AudioEncoder() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); +} void AudioEncoder::EncodeAudio(const AudioBus& audio_bus, base::TimeTicks capture_time) { - DCHECK_CALLED_ON_VALID_THREAD(thread_checker_); + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_EQ(audio_bus.channels(), audio_input_params_.channels()); DCHECK(!capture_time.is_null()); @@ -61,6 +63,12 @@ void AudioEncoder::EncodeAudio(const AudioBus& audio_bus, EncodeAudioImpl(audio_bus, capture_time); } +void AudioEncoder::Flush() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + + FlushImpl(); +} + base::TimeTicks AudioEncoder::ComputeTimestamp( int num_frames, base::TimeTicks capture_time) const { diff --git a/chromium/media/base/audio_encoder.h b/chromium/media/base/audio_encoder.h index e7ad866fcb0..c25218c9ee8 100644 --- a/chromium/media/base/audio_encoder.h +++ b/chromium/media/base/audio_encoder.h @@ -8,7 +8,7 @@ #include <memory> #include "base/callback.h" -#include "base/threading/thread_checker.h" +#include "base/sequence_checker.h" #include "base/time/time.h" #include "media/base/audio_bus.h" #include "media/base/audio_parameters.h" @@ -41,7 +41,8 @@ struct MEDIA_EXPORT EncodedAudioBuffer { // number of encoded bytes may not be known in advance. const size_t encoded_data_size; - // The capture time of the first sample of the current AudioBus. + // The capture time of the first sample of the current AudioBus, or a previous + // AudioBus If this output was generated because of a call to Flush(). const base::TimeTicks timestamp; }; @@ -50,9 +51,9 @@ struct MEDIA_EXPORT EncodedAudioBuffer { class MEDIA_EXPORT AudioEncoder { public: // Signature of the callback invoked to provide the encoded audio data. It is - // invoked on the same thread on which EncodeAudio() is called. The utility + // invoked on the same sequence on which EncodeAudio() is called. The utility // media::BindToCurrentLoop() can be used to create a callback that will be - // invoked on the same thread it is constructed on. + // invoked on the same sequence it is constructed on. using EncodeCB = base::RepeatingCallback<void(EncodedAudioBuffer output)>; // Signature of the callback to report errors. @@ -62,8 +63,8 @@ class MEDIA_EXPORT AudioEncoder { // encoder, and a callback to trigger to provide the encoded audio data. // |input_params| must be valid, and |encode_callback| and |status_callback| // must not be null callbacks. All calls to EncodeAudio() must happen on the - // same thread (usually an encoder thread), but the encoder itself can be - // constructed on any thread. + // same sequence (usually an encoder blocking pool sequence), but the encoder + // itself can be constructed on any sequence. AudioEncoder(const AudioParameters& input_params, EncodeCB encode_callback, StatusCB status_callback); @@ -79,6 +80,11 @@ class MEDIA_EXPORT AudioEncoder { // actual encoding. void EncodeAudio(const AudioBus& audio_bus, base::TimeTicks capture_time); + // Some encoders may choose to buffer audio frames before they encode them. + // This function provides a mechanism to drain and encode any buffered frames + // (if any). Must be called on the encoder sequence. + void Flush(); + protected: const EncodeCB& encode_callback() const { return encode_callback_; } const StatusCB& status_callback() const { return status_callback_; } @@ -87,6 +93,8 @@ class MEDIA_EXPORT AudioEncoder { virtual void EncodeAudioImpl(const AudioBus& audio_bus, base::TimeTicks capture_time) = 0; + virtual void FlushImpl() = 0; + // Computes the timestamp of an AudioBus which has |num_frames| and was // captured at |capture_time|. This timestamp is the capture time of the first // sample in that AudioBus. @@ -104,7 +112,7 @@ class MEDIA_EXPORT AudioEncoder { // EncodeAudio(). base::TimeTicks last_capture_time_; - THREAD_CHECKER(thread_checker_); + SEQUENCE_CHECKER(sequence_checker_); }; } // namespace media diff --git a/chromium/media/base/audio_latency.cc b/chromium/media/base/audio_latency.cc index c181ec49343..b55a2da37e1 100644 --- a/chromium/media/base/audio_latency.cc +++ b/chromium/media/base/audio_latency.cc @@ -11,6 +11,7 @@ #include "base/logging.h" #include "base/time/time.h" #include "build/build_config.h" +#include "build/chromeos_buildflags.h" #include "media/base/limits.h" #if defined(OS_ANDROID) @@ -42,7 +43,7 @@ uint32_t RoundUpToPowerOfTwo(uint32_t v) { // static bool AudioLatency::IsResamplingPassthroughSupported(LatencyType type) { -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) return true; #elif defined(OS_ANDROID) // Only N MR1+ has support for OpenSLES performance modes which allow for diff --git a/chromium/media/base/audio_pull_fifo_unittest.cc b/chromium/media/base/audio_pull_fifo_unittest.cc index 2a83e3fb68f..358485a1831 100644 --- a/chromium/media/base/audio_pull_fifo_unittest.cc +++ b/chromium/media/base/audio_pull_fifo_unittest.cc @@ -5,7 +5,7 @@ #include <memory> #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/macros.h" #include "base/strings/stringprintf.h" #include "media/base/audio_bus.h" diff --git a/chromium/media/base/audio_push_fifo.h b/chromium/media/base/audio_push_fifo.h index 2eb6bfc467a..fb9c615c397 100644 --- a/chromium/media/base/audio_push_fifo.h +++ b/chromium/media/base/audio_push_fifo.h @@ -42,6 +42,9 @@ class MEDIA_EXPORT AudioPushFifo final { // OutputCallback. int frames_per_buffer() const { return frames_per_buffer_; } + // The number of frames currently queued in this FIFO. + int queued_frames() const { return queued_frames_; } + // Must be called at least once before the first call to Push(). May be // called later (e.g., to support an audio format change). void Reset(int frames_per_buffer); diff --git a/chromium/media/base/audio_push_fifo_unittest.cc b/chromium/media/base/audio_push_fifo_unittest.cc index 5ee4a186489..2adf285f37e 100644 --- a/chromium/media/base/audio_push_fifo_unittest.cc +++ b/chromium/media/base/audio_push_fifo_unittest.cc @@ -7,7 +7,7 @@ #include <vector> #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/macros.h" #include "media/base/audio_bus.h" #include "media/base/audio_push_fifo.h" diff --git a/chromium/media/base/audio_renderer_mixer_input_unittest.cc b/chromium/media/base/audio_renderer_mixer_input_unittest.cc index 3cfb45f9de6..01f4491e66b 100644 --- a/chromium/media/base/audio_renderer_mixer_input_unittest.cc +++ b/chromium/media/base/audio_renderer_mixer_input_unittest.cc @@ -6,7 +6,7 @@ #include <memory> #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/macros.h" #include "base/run_loop.h" #include "base/test/task_environment.h" diff --git a/chromium/media/base/audio_renderer_mixer_unittest.cc b/chromium/media/base/audio_renderer_mixer_unittest.cc index 7b195f599dd..60ddd9df47a 100644 --- a/chromium/media/base/audio_renderer_mixer_unittest.cc +++ b/chromium/media/base/audio_renderer_mixer_unittest.cc @@ -13,7 +13,7 @@ #include <vector> #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/stl_util.h" #include "base/synchronization/waitable_event.h" #include "base/test/task_environment.h" diff --git a/chromium/media/base/cdm_context.cc b/chromium/media/base/cdm_context.cc index cbc0c9d7ddf..8f8cd843f64 100644 --- a/chromium/media/base/cdm_context.cc +++ b/chromium/media/base/cdm_context.cc @@ -3,6 +3,7 @@ // found in the LICENSE file. #include "media/base/cdm_context.h" +#include "build/chromeos_buildflags.h" #include "media/base/callback_registry.h" @@ -52,4 +53,10 @@ FuchsiaCdmContext* CdmContext::GetFuchsiaCdmContext() { } #endif +#if BUILDFLAG(IS_ASH) +chromeos::ChromeOsCdmContext* CdmContext::GetChromeOsCdmContext() { + return nullptr; +} +#endif + } // namespace media diff --git a/chromium/media/base/cdm_context.h b/chromium/media/base/cdm_context.h index d2d6965592f..d555e21e360 100644 --- a/chromium/media/base/cdm_context.h +++ b/chromium/media/base/cdm_context.h @@ -10,6 +10,7 @@ #include "base/optional.h" #include "base/unguessable_token.h" #include "build/build_config.h" +#include "build/chromeos_buildflags.h" #include "media/base/media_export.h" #include "media/media_buildflags.h" @@ -18,6 +19,12 @@ struct IMFCdmProxy; #endif +#if BUILDFLAG(IS_ASH) +namespace chromeos { +class ChromeOsCdmContext; +} +#endif + namespace media { class CallbackRegistration; @@ -115,6 +122,12 @@ class MEDIA_EXPORT CdmContext { virtual FuchsiaCdmContext* GetFuchsiaCdmContext(); #endif +#if BUILDFLAG(IS_ASH) + // Returns a ChromeOsCdmContext interface when the context is backed by the + // ChromeOS CdmFactoryDaemon. Otherwise return nullptr. + virtual chromeos::ChromeOsCdmContext* GetChromeOsCdmContext(); +#endif + protected: CdmContext(); diff --git a/chromium/media/base/decoder_factory.cc b/chromium/media/base/decoder_factory.cc index 47aa49bab02..52028b6901c 100644 --- a/chromium/media/base/decoder_factory.cc +++ b/chromium/media/base/decoder_factory.cc @@ -13,12 +13,12 @@ DecoderFactory::DecoderFactory() = default; DecoderFactory::~DecoderFactory() = default; void DecoderFactory::CreateAudioDecoders( - scoped_refptr<base::SingleThreadTaskRunner> task_runner, + scoped_refptr<base::SequencedTaskRunner> task_runner, MediaLog* media_log, std::vector<std::unique_ptr<AudioDecoder>>* audio_decoders) {} void DecoderFactory::CreateVideoDecoders( - scoped_refptr<base::SingleThreadTaskRunner> task_runner, + scoped_refptr<base::SequencedTaskRunner> task_runner, GpuVideoAcceleratorFactories* gpu_factories, MediaLog* media_log, RequestOverlayInfoCB request_overlay_info_cb, diff --git a/chromium/media/base/decoder_factory.h b/chromium/media/base/decoder_factory.h index d01d55e6e56..2af1af58f9d 100644 --- a/chromium/media/base/decoder_factory.h +++ b/chromium/media/base/decoder_factory.h @@ -14,7 +14,7 @@ #include "media/base/overlay_info.h" namespace base { -class SingleThreadTaskRunner; +class SequencedTaskRunner; } // namespace base namespace gfx { @@ -37,14 +37,14 @@ class MEDIA_EXPORT DecoderFactory { // Creates audio decoders and append them to the end of |audio_decoders|. // Decoders are single-threaded, each decoder should run on |task_runner|. virtual void CreateAudioDecoders( - scoped_refptr<base::SingleThreadTaskRunner> task_runner, + scoped_refptr<base::SequencedTaskRunner> task_runner, MediaLog* media_log, std::vector<std::unique_ptr<AudioDecoder>>* audio_decoders); // Creates video decoders and append them to the end of |video_decoders|. // Decoders are single-threaded, each decoder should run on |task_runner|. virtual void CreateVideoDecoders( - scoped_refptr<base::SingleThreadTaskRunner> task_runner, + scoped_refptr<base::SequencedTaskRunner> task_runner, GpuVideoAcceleratorFactories* gpu_factories, MediaLog* media_log, RequestOverlayInfoCB request_overlay_info_cb, diff --git a/chromium/media/base/demuxer.h b/chromium/media/base/demuxer.h index a06793ab07a..c9a4ebbd6b8 100644 --- a/chromium/media/base/demuxer.h +++ b/chromium/media/base/demuxer.h @@ -73,6 +73,12 @@ class MEDIA_EXPORT Demuxer : public MediaResource { base::OnceCallback<void(DemuxerStream::Type type, const std::vector<DemuxerStream*>&)>; + enum DemuxerTypes { + kChunkDemuxer, + kFFmpegDemuxer, + kMediaUrlDemuxer, + }; + Demuxer(); ~Demuxer() override; diff --git a/chromium/media/base/demuxer_memory_limit.h b/chromium/media/base/demuxer_memory_limit.h index 6fac9409f7c..2492eca1dd4 100644 --- a/chromium/media/base/demuxer_memory_limit.h +++ b/chromium/media/base/demuxer_memory_limit.h @@ -8,17 +8,23 @@ #include <stddef.h> #include "build/build_config.h" +#include "media/base/audio_decoder_config.h" +#include "media/base/demuxer.h" #include "media/base/media_export.h" +#include "media/base/video_decoder_config.h" namespace media { // The maximum amount of data (in bytes) a demuxer can keep in memory, for a // particular type of stream. -MEDIA_EXPORT size_t GetDemuxerStreamAudioMemoryLimit(); -MEDIA_EXPORT size_t GetDemuxerStreamVideoMemoryLimit(); +MEDIA_EXPORT size_t +GetDemuxerStreamAudioMemoryLimit(const AudioDecoderConfig* audio_config); +MEDIA_EXPORT size_t +GetDemuxerStreamVideoMemoryLimit(Demuxer::DemuxerTypes demuxer_type, + const VideoDecoderConfig* video_config); // The maximum amount of data (in bytes) a demuxer can keep in memory overall. -MEDIA_EXPORT size_t GetDemuxerMemoryLimit(); +MEDIA_EXPORT size_t GetDemuxerMemoryLimit(Demuxer::DemuxerTypes demuxer_type); namespace internal { @@ -26,13 +32,17 @@ namespace internal { // above based on platform capabilities. // Default audio memory limit: 12MB (5 minutes of 320Kbps content). +// Medium audio memory limit: 5MB. // Low audio memory limit: 2MB (1 minute of 256Kbps content). constexpr size_t kDemuxerStreamAudioMemoryLimitDefault = 12 * 1024 * 1024; +constexpr size_t kDemuxerStreamAudioMemoryLimitMedium = 5 * 1024 * 1024; constexpr size_t kDemuxerStreamAudioMemoryLimitLow = 2 * 1024 * 1024; // Default video memory limit: 150MB (5 minutes of 4Mbps content). +// Medium video memory limit: 80MB. // Low video memory limit: 30MB (1 minute of 4Mbps content). constexpr size_t kDemuxerStreamVideoMemoryLimitDefault = 150 * 1024 * 1024; +constexpr size_t kDemuxerStreamVideoMemoryLimitMedium = 80 * 1024 * 1024; constexpr size_t kDemuxerStreamVideoMemoryLimitLow = 30 * 1024 * 1024; #if defined(OS_ANDROID) diff --git a/chromium/media/base/demuxer_memory_limit_android.cc b/chromium/media/base/demuxer_memory_limit_android.cc index b2f35ecd0d8..3ea849942e2 100644 --- a/chromium/media/base/demuxer_memory_limit_android.cc +++ b/chromium/media/base/demuxer_memory_limit_android.cc @@ -28,7 +28,8 @@ size_t SelectLimit(size_t default_limit, } // namespace -size_t GetDemuxerStreamAudioMemoryLimit() { +size_t GetDemuxerStreamAudioMemoryLimit( + const AudioDecoderConfig* /*audio_config*/) { static const size_t limit = SelectLimit(internal::kDemuxerStreamAudioMemoryLimitDefault, internal::kDemuxerStreamAudioMemoryLimitLow, @@ -36,7 +37,9 @@ size_t GetDemuxerStreamAudioMemoryLimit() { return limit; } -size_t GetDemuxerStreamVideoMemoryLimit() { +size_t GetDemuxerStreamVideoMemoryLimit( + Demuxer::DemuxerTypes /*demuxer_type*/, + const VideoDecoderConfig* /*video_config*/) { static const size_t limit = SelectLimit(internal::kDemuxerStreamVideoMemoryLimitDefault, internal::kDemuxerStreamVideoMemoryLimitLow, @@ -44,9 +47,9 @@ size_t GetDemuxerStreamVideoMemoryLimit() { return limit; } -size_t GetDemuxerMemoryLimit() { - return GetDemuxerStreamAudioMemoryLimit() + - GetDemuxerStreamVideoMemoryLimit(); +size_t GetDemuxerMemoryLimit(Demuxer::DemuxerTypes demuxer_type) { + return GetDemuxerStreamAudioMemoryLimit(nullptr) + + GetDemuxerStreamVideoMemoryLimit(demuxer_type, nullptr); } } // namespace media diff --git a/chromium/media/base/demuxer_memory_limit_cast.cc b/chromium/media/base/demuxer_memory_limit_cast.cc new file mode 100644 index 00000000000..a4c2775c686 --- /dev/null +++ b/chromium/media/base/demuxer_memory_limit_cast.cc @@ -0,0 +1,62 @@ +// 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/demuxer_memory_limit.h" + +#include "base/check.h" +#include "media/base/channel_layout.h" + +namespace media { + +size_t GetDemuxerStreamAudioMemoryLimit( + const AudioDecoderConfig* audio_config) { + if (!audio_config) { + return internal::kDemuxerStreamAudioMemoryLimitLow; + } + + DCHECK(audio_config->IsValidConfig()); + switch (audio_config->codec()) { + case kCodecEAC3: + case kCodecAC3: + return internal::kDemuxerStreamAudioMemoryLimitMedium; + case kCodecAAC: + if (ChannelLayoutToChannelCount(audio_config->channel_layout()) >= 5) { + return internal::kDemuxerStreamAudioMemoryLimitMedium; + } + return internal::kDemuxerStreamAudioMemoryLimitLow; + default: + return internal::kDemuxerStreamAudioMemoryLimitLow; + } +} + +size_t GetDemuxerStreamVideoMemoryLimit( + Demuxer::DemuxerTypes demuxer_type, + const VideoDecoderConfig* video_config) { + switch (demuxer_type) { + case Demuxer::DemuxerTypes::kFFmpegDemuxer: + return internal::kDemuxerStreamVideoMemoryLimitDefault; + case Demuxer::DemuxerTypes::kChunkDemuxer: + if (!video_config) { + return internal::kDemuxerStreamVideoMemoryLimitLow; + } + DCHECK(video_config->IsValidConfig()); + switch (video_config->codec()) { + case kCodecVP9: + case kCodecHEVC: + case kCodecDolbyVision: + return internal::kDemuxerStreamVideoMemoryLimitMedium; + default: + return internal::kDemuxerStreamVideoMemoryLimitLow; + } + case Demuxer::DemuxerTypes::kMediaUrlDemuxer: + return internal::kDemuxerStreamVideoMemoryLimitLow; + } +} + +size_t GetDemuxerMemoryLimit(Demuxer::DemuxerTypes demuxer_type) { + return GetDemuxerStreamAudioMemoryLimit(nullptr) + + GetDemuxerStreamVideoMemoryLimit(demuxer_type, nullptr); +} + +} // namespace media diff --git a/chromium/media/base/demuxer_memory_limit_cast_unittest.cc b/chromium/media/base/demuxer_memory_limit_cast_unittest.cc new file mode 100644 index 00000000000..41b68a20aed --- /dev/null +++ b/chromium/media/base/demuxer_memory_limit_cast_unittest.cc @@ -0,0 +1,106 @@ +// 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 "base/optional.h" +#include "media/base/audio_decoder_config.h" +#include "media/base/demuxer.h" +#include "media/base/demuxer_memory_limit.h" +#include "media/base/media_util.h" +#include "media/base/video_decoder_config.h" +#include "testing/gtest/include/gtest/gtest.h" + +namespace media { + +static const gfx::Size kCodedSize(320, 240); +static const gfx::Rect kVisibleRect(320, 240); +static const gfx::Size kNaturalSize(320, 240); + +TEST(DemuxerMemoryLimitCastTest, GetDemuxerStreamAudioMemoryLimit) { + EXPECT_EQ(GetDemuxerStreamAudioMemoryLimit(nullptr), + internal::kDemuxerStreamAudioMemoryLimitLow); + + AudioDecoderConfig audio_config_opus( + AudioCodec::kCodecOpus, SampleFormat::kSampleFormatS16, + ChannelLayout::CHANNEL_LAYOUT_STEREO, 5000 /* samples_per_second */, + EmptyExtraData(), EncryptionScheme::kUnencrypted); + EXPECT_EQ(GetDemuxerStreamAudioMemoryLimit(&audio_config_opus), + internal::kDemuxerStreamAudioMemoryLimitLow); + + AudioDecoderConfig audio_config_ac3( + AudioCodec::kCodecAC3, SampleFormat::kSampleFormatS16, + ChannelLayout::CHANNEL_LAYOUT_STEREO, 5000 /* samples_per_second */, + EmptyExtraData(), EncryptionScheme::kUnencrypted); + EXPECT_EQ(GetDemuxerStreamAudioMemoryLimit(&audio_config_ac3), + internal::kDemuxerStreamAudioMemoryLimitMedium); + + AudioDecoderConfig audio_config_aac_1( + AudioCodec::kCodecAAC, SampleFormat::kSampleFormatS16, + ChannelLayout::CHANNEL_LAYOUT_5_0, 5000 /* samples_per_second */, + EmptyExtraData(), EncryptionScheme::kUnencrypted); + EXPECT_EQ(GetDemuxerStreamAudioMemoryLimit(&audio_config_aac_1), + internal::kDemuxerStreamAudioMemoryLimitMedium); + + AudioDecoderConfig audio_config_aac_2( + AudioCodec::kCodecAAC, SampleFormat::kSampleFormatS16, + ChannelLayout::CHANNEL_LAYOUT_STEREO, 5000 /* samples_per_second */, + EmptyExtraData(), EncryptionScheme::kUnencrypted); + EXPECT_EQ(GetDemuxerStreamAudioMemoryLimit(&audio_config_aac_2), + internal::kDemuxerStreamAudioMemoryLimitLow); +} + +TEST(DemuxerMemoryLimitCastTest, GetDemuxerStreamVideoMemoryLimit) { + EXPECT_EQ(GetDemuxerStreamVideoMemoryLimit( + Demuxer::DemuxerTypes::kFFmpegDemuxer, nullptr), + internal::kDemuxerStreamVideoMemoryLimitDefault); + EXPECT_EQ(GetDemuxerStreamVideoMemoryLimit( + Demuxer::DemuxerTypes::kChunkDemuxer, nullptr), + internal::kDemuxerStreamVideoMemoryLimitLow); + EXPECT_EQ(GetDemuxerStreamVideoMemoryLimit( + Demuxer::DemuxerTypes::kMediaUrlDemuxer, nullptr), + internal::kDemuxerStreamVideoMemoryLimitLow); + + VideoDecoderConfig video_config( + kCodecVP8, VIDEO_CODEC_PROFILE_UNKNOWN, + VideoDecoderConfig::AlphaMode::kIsOpaque, VideoColorSpace(), + kNoTransformation, kCodedSize, kVisibleRect, kNaturalSize, + EmptyExtraData(), EncryptionScheme::kUnencrypted); + EXPECT_EQ(GetDemuxerStreamVideoMemoryLimit( + Demuxer::DemuxerTypes::kFFmpegDemuxer, &video_config), + internal::kDemuxerStreamVideoMemoryLimitDefault); + EXPECT_EQ(GetDemuxerStreamVideoMemoryLimit( + Demuxer::DemuxerTypes::kChunkDemuxer, &video_config), + internal::kDemuxerStreamVideoMemoryLimitLow); + EXPECT_EQ(GetDemuxerStreamVideoMemoryLimit( + Demuxer::DemuxerTypes::kMediaUrlDemuxer, &video_config), + internal::kDemuxerStreamVideoMemoryLimitLow); + + video_config.Initialize(kCodecVP9, VIDEO_CODEC_PROFILE_UNKNOWN, + VideoDecoderConfig::AlphaMode::kIsOpaque, + VideoColorSpace(), kNoTransformation, kCodedSize, + kVisibleRect, kNaturalSize, EmptyExtraData(), + EncryptionScheme::kUnencrypted); + EXPECT_EQ(GetDemuxerStreamVideoMemoryLimit( + Demuxer::DemuxerTypes::kFFmpegDemuxer, &video_config), + internal::kDemuxerStreamVideoMemoryLimitDefault); + EXPECT_EQ(GetDemuxerStreamVideoMemoryLimit( + Demuxer::DemuxerTypes::kChunkDemuxer, &video_config), + internal::kDemuxerStreamVideoMemoryLimitMedium); + EXPECT_EQ(GetDemuxerStreamVideoMemoryLimit( + Demuxer::DemuxerTypes::kMediaUrlDemuxer, &video_config), + internal::kDemuxerStreamVideoMemoryLimitLow); +} + +TEST(DemuxerMemoryLimitCastTest, GetDemuxerMemoryLimit) { + EXPECT_EQ(GetDemuxerMemoryLimit(Demuxer::DemuxerTypes::kFFmpegDemuxer), + internal::kDemuxerStreamAudioMemoryLimitLow + + internal::kDemuxerStreamVideoMemoryLimitDefault); + EXPECT_EQ(GetDemuxerMemoryLimit(Demuxer::DemuxerTypes::kChunkDemuxer), + internal::kDemuxerStreamAudioMemoryLimitLow + + internal::kDemuxerStreamVideoMemoryLimitLow); + EXPECT_EQ(GetDemuxerMemoryLimit(Demuxer::DemuxerTypes::kMediaUrlDemuxer), + internal::kDemuxerStreamAudioMemoryLimitLow + + internal::kDemuxerStreamVideoMemoryLimitLow); +} + +} // namespace media diff --git a/chromium/media/base/demuxer_memory_limit_default.cc b/chromium/media/base/demuxer_memory_limit_default.cc index 4fb4551e60b..896d534098a 100644 --- a/chromium/media/base/demuxer_memory_limit_default.cc +++ b/chromium/media/base/demuxer_memory_limit_default.cc @@ -6,17 +6,20 @@ namespace media { -size_t GetDemuxerStreamAudioMemoryLimit() { +size_t GetDemuxerStreamAudioMemoryLimit( + const AudioDecoderConfig* /*audio_config*/) { return internal::kDemuxerStreamAudioMemoryLimitDefault; } -size_t GetDemuxerStreamVideoMemoryLimit() { +size_t GetDemuxerStreamVideoMemoryLimit( + Demuxer::DemuxerTypes /*demuxer_type*/, + const VideoDecoderConfig* /*video_config*/) { return internal::kDemuxerStreamVideoMemoryLimitDefault; } -size_t GetDemuxerMemoryLimit() { - return GetDemuxerStreamAudioMemoryLimit() + - GetDemuxerStreamVideoMemoryLimit(); +size_t GetDemuxerMemoryLimit(Demuxer::DemuxerTypes demuxer_type) { + return GetDemuxerStreamAudioMemoryLimit(nullptr) + + GetDemuxerStreamVideoMemoryLimit(demuxer_type, nullptr); } } // namespace media diff --git a/chromium/media/base/demuxer_memory_limit_low.cc b/chromium/media/base/demuxer_memory_limit_low.cc index 054fafe2081..71dc442d42a 100644 --- a/chromium/media/base/demuxer_memory_limit_low.cc +++ b/chromium/media/base/demuxer_memory_limit_low.cc @@ -8,17 +8,20 @@ namespace media { -size_t GetDemuxerStreamAudioMemoryLimit() { +size_t GetDemuxerStreamAudioMemoryLimit( + const AudioDecoderConfig* /*audio_config*/) { return internal::kDemuxerStreamAudioMemoryLimitLow; } -size_t GetDemuxerStreamVideoMemoryLimit() { +size_t GetDemuxerStreamVideoMemoryLimit( + Demuxer::DemuxerTypes /*demuxer_type*/, + const VideoDecoderConfig* /*video_config*/) { return internal::kDemuxerStreamVideoMemoryLimitLow; } -size_t GetDemuxerMemoryLimit() { - return GetDemuxerStreamAudioMemoryLimit() + - GetDemuxerStreamVideoMemoryLimit(); +size_t GetDemuxerMemoryLimit(Demuxer::DemuxerTypes demuxer_type) { + return GetDemuxerStreamAudioMemoryLimit(nullptr) + + GetDemuxerStreamVideoMemoryLimit(demuxer_type, nullptr); } } // namespace media diff --git a/chromium/media/base/fake_audio_worker.cc b/chromium/media/base/fake_audio_worker.cc index bcaf73ebef5..2d0bbefd537 100644 --- a/chromium/media/base/fake_audio_worker.cc +++ b/chromium/media/base/fake_audio_worker.cc @@ -7,7 +7,7 @@ #include <utility> #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/cancelable_callback.h" #include "base/check_op.h" #include "base/location.h" diff --git a/chromium/media/base/fake_single_thread_task_runner.h b/chromium/media/base/fake_single_thread_task_runner.h index a56ac6f2b1f..68c8e45f62c 100644 --- a/chromium/media/base/fake_single_thread_task_runner.h +++ b/chromium/media/base/fake_single_thread_task_runner.h @@ -14,7 +14,7 @@ namespace media { -class FakeSingleThreadTaskRunner : public base::SingleThreadTaskRunner { +class FakeSingleThreadTaskRunner final : public base::SingleThreadTaskRunner { public: explicit FakeSingleThreadTaskRunner(base::SimpleTestTickClock* clock); diff --git a/chromium/media/base/fallback_video_decoder.cc b/chromium/media/base/fallback_video_decoder.cc index a4796c2ef4e..a10ac08bec8 100644 --- a/chromium/media/base/fallback_video_decoder.cc +++ b/chromium/media/base/fallback_video_decoder.cc @@ -5,7 +5,7 @@ #include <utility> #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/threading/sequenced_task_runner_handle.h" #include "media/base/decoder_buffer.h" #include "media/base/fallback_video_decoder.h" diff --git a/chromium/media/base/fallback_video_decoder_unittest.cc b/chromium/media/base/fallback_video_decoder_unittest.cc index ecf80f36b23..e996eb5b50c 100644 --- a/chromium/media/base/fallback_video_decoder_unittest.cc +++ b/chromium/media/base/fallback_video_decoder_unittest.cc @@ -5,7 +5,7 @@ #include <tuple> #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/run_loop.h" #include "base/test/gmock_callback_support.h" #include "base/test/task_environment.h" diff --git a/chromium/media/base/ipc/media_param_traits.cc b/chromium/media/base/ipc/media_param_traits.cc index 46c977a708f..271754aff43 100644 --- a/chromium/media/base/ipc/media_param_traits.cc +++ b/chromium/media/base/ipc/media_param_traits.cc @@ -13,7 +13,6 @@ #include "media/base/limits.h" #include "ui/gfx/ipc/geometry/gfx_param_traits.h" #include "ui/gfx/ipc/gfx_param_traits.h" -#include "ui/gfx/ipc/skia/gfx_skia_param_traits.h" using media::AudioParameters; using media::AudioLatency; diff --git a/chromium/media/base/ipc/media_param_traits_macros.h b/chromium/media/base/ipc/media_param_traits_macros.h index 9379933883f..ecebc25c85b 100644 --- a/chromium/media/base/ipc/media_param_traits_macros.h +++ b/chromium/media/base/ipc/media_param_traits_macros.h @@ -38,8 +38,8 @@ #include "media/base/watch_time_keys.h" #include "media/media_buildflags.h" #include "media/video/supported_video_decoder_config.h" +#include "ui/gfx/hdr_metadata.h" #include "ui/gfx/ipc/color/gfx_param_traits_macros.h" -#include "ui/gl/hdr_metadata.h" #if BUILDFLAG(ENABLE_MEDIA_DRM_STORAGE) #include "media/base/media_drm_key_type.h" @@ -183,7 +183,7 @@ IPC_STRUCT_TRAITS_BEGIN(media::VideoColorSpace) IPC_STRUCT_TRAITS_MEMBER(range) IPC_STRUCT_TRAITS_END() -IPC_STRUCT_TRAITS_BEGIN(gl::MasteringMetadata) +IPC_STRUCT_TRAITS_BEGIN(gfx::MasteringMetadata) IPC_STRUCT_TRAITS_MEMBER(primary_r) IPC_STRUCT_TRAITS_MEMBER(primary_g) IPC_STRUCT_TRAITS_MEMBER(primary_b) @@ -192,7 +192,7 @@ IPC_STRUCT_TRAITS_BEGIN(gl::MasteringMetadata) IPC_STRUCT_TRAITS_MEMBER(luminance_min) IPC_STRUCT_TRAITS_END() -IPC_STRUCT_TRAITS_BEGIN(gl::HDRMetadata) +IPC_STRUCT_TRAITS_BEGIN(gfx::HDRMetadata) IPC_STRUCT_TRAITS_MEMBER(mastering_metadata) IPC_STRUCT_TRAITS_MEMBER(max_content_light_level) IPC_STRUCT_TRAITS_MEMBER(max_frame_average_light_level) diff --git a/chromium/media/base/keyboard_event_counter.cc b/chromium/media/base/keyboard_event_counter.cc deleted file mode 100644 index 6c17f676e8c..00000000000 --- a/chromium/media/base/keyboard_event_counter.cc +++ /dev/null @@ -1,33 +0,0 @@ -// Copyright 2013 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/keyboard_event_counter.h" - -#include "base/check_op.h" - -namespace media { - -KeyboardEventCounter::KeyboardEventCounter() : total_key_presses_(0) {} - -KeyboardEventCounter::~KeyboardEventCounter() = default; - -void KeyboardEventCounter::OnKeyboardEvent(ui::EventType event, - ui::KeyboardCode key_code) { - // Updates the pressed keys and the total count of key presses. - if (event == ui::ET_KEY_PRESSED) { - if (pressed_keys_.find(key_code) != pressed_keys_.end()) - return; - pressed_keys_.insert(key_code); - ++total_key_presses_; - } else { - DCHECK_EQ(ui::ET_KEY_RELEASED, event); - pressed_keys_.erase(key_code); - } -} - -uint32_t KeyboardEventCounter::GetKeyPressCount() const { - return total_key_presses_.load(); -} - -} // namespace media diff --git a/chromium/media/base/keyboard_event_counter.h b/chromium/media/base/keyboard_event_counter.h deleted file mode 100644 index d9f4e56d24f..00000000000 --- a/chromium/media/base/keyboard_event_counter.h +++ /dev/null @@ -1,48 +0,0 @@ -// Copyright 2013 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_KEYBOARD_EVENT_COUNTER_H_ -#define MEDIA_BASE_KEYBOARD_EVENT_COUNTER_H_ - -#include <stddef.h> - -#include <atomic> -#include <set> - -#include "base/macros.h" -#include "media/base/media_export.h" -#include "ui/events/keycodes/keyboard_codes.h" -#include "ui/events/types/event_type.h" - -namespace media { - -// This class tracks the total number of keypresses based on the OnKeyboardEvent -// calls it receives from the client. -// Multiple key down events for the same key are counted as one keypress until -// the same key is released. -class MEDIA_EXPORT KeyboardEventCounter { - public: - KeyboardEventCounter(); - ~KeyboardEventCounter(); - - // Returns the total number of keypresses since its creation or last Reset() - // call. Can be called on any thread. - uint32_t GetKeyPressCount() const; - - // The client should call this method on key down or key up events. - // Must be called on a single thread. - void OnKeyboardEvent(ui::EventType event, ui::KeyboardCode key_code); - - private: - // The set of keys currently held down. - std::set<ui::KeyboardCode> pressed_keys_; - - std::atomic<uint32_t> total_key_presses_; - - DISALLOW_COPY_AND_ASSIGN(KeyboardEventCounter); -}; - -} // namespace media - -#endif // MEDIA_BASE_KEYBOARD_EVENT_COUNTER_H_ diff --git a/chromium/media/base/keyboard_event_counter_unittest.cc b/chromium/media/base/keyboard_event_counter_unittest.cc deleted file mode 100644 index 7d104dc76c8..00000000000 --- a/chromium/media/base/keyboard_event_counter_unittest.cc +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright 2016 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/keyboard_event_counter.h" - -#include <memory> - -#include "base/run_loop.h" -#include "build/build_config.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" -#include "third_party/skia/include/core/SkPoint.h" - -namespace media { - -TEST(KeyboardEventCounterTest, KeyPressCounter) { - KeyboardEventCounter counter; - - EXPECT_EQ(0u, counter.GetKeyPressCount()); - - counter.OnKeyboardEvent(ui::ET_KEY_PRESSED, ui::VKEY_0); - EXPECT_EQ(1u, counter.GetKeyPressCount()); - - // Holding the same key without releasing it does not increase the count. - counter.OnKeyboardEvent(ui::ET_KEY_PRESSED, ui::VKEY_0); - EXPECT_EQ(1u, counter.GetKeyPressCount()); - - // Releasing the key does not affect the total count. - counter.OnKeyboardEvent(ui::ET_KEY_RELEASED, ui::VKEY_0); - EXPECT_EQ(1u, counter.GetKeyPressCount()); - - counter.OnKeyboardEvent(ui::ET_KEY_PRESSED, ui::VKEY_0); - counter.OnKeyboardEvent(ui::ET_KEY_RELEASED, ui::VKEY_0); - EXPECT_EQ(2u, counter.GetKeyPressCount()); -} - -} // namespace media diff --git a/chromium/media/base/logging_override_if_enabled.h b/chromium/media/base/logging_override_if_enabled.h index 302a5f0ea20..ee274e79f9f 100644 --- a/chromium/media/base/logging_override_if_enabled.h +++ b/chromium/media/base/logging_override_if_enabled.h @@ -15,8 +15,17 @@ #if !defined(DVLOG) #error This file must be included after base/logging.h. #endif + +#define __DVLOG_0 LOG(INFO) +#define __DVLOG_1 LOG(INFO) +#define __DVLOG_2 LOG(INFO) +#define __DVLOG_3 EAT_STREAM_PARAMETERS +#define __DVLOG_4 EAT_STREAM_PARAMETERS +#define __DVLOG_5 EAT_STREAM_PARAMETERS + #undef DVLOG -#define DVLOG(verboselevel) LOG(INFO) +#define DVLOG(verboselevel) __DVLOG_##verboselevel + #endif // BUILDFLAG(ENABLE_LOGGING_OVERRIDE) #endif // MEDIA_BASE_LOGGING_OVERRIDE_IF_ENABLED_H_ diff --git a/chromium/media/base/mac/BUILD.gn b/chromium/media/base/mac/BUILD.gn index 7b16b9833cd..9dd95bbc171 100644 --- a/chromium/media/base/mac/BUILD.gn +++ b/chromium/media/base/mac/BUILD.gn @@ -2,13 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -# This file depends on the legacy global sources assignment filter. It should -# be converted to check target platform before assigning source files to the -# sources variable. Remove this import and set_sources_assignment_filter call -# when the file has been converted. See https://crbug.com/1018739 for details. -import("//build/config/deprecated_default_sources_assignment_filter.gni") -set_sources_assignment_filter(deprecated_default_sources_assignment_filter) - assert(is_apple) source_set("mac") { @@ -18,8 +11,9 @@ source_set("mac") { # run-time. visibility = [ "//media" ] - set_sources_assignment_filter([]) sources = [ + "color_space_util_mac.h", + "color_space_util_mac.mm", "video_frame_mac.cc", "video_frame_mac.h", "videotoolbox_helpers.cc", @@ -33,7 +27,6 @@ source_set("mac") { "VideoToolbox.framework", ] } - set_sources_assignment_filter(deprecated_default_sources_assignment_filter) configs += [ "//media:subcomponent_config" ] deps = [ diff --git a/chromium/media/base/mac/color_space_util_mac.h b/chromium/media/base/mac/color_space_util_mac.h new file mode 100644 index 00000000000..938b7fd46ab --- /dev/null +++ b/chromium/media/base/mac/color_space_util_mac.h @@ -0,0 +1,24 @@ +// 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. + +#ifndef MEDIA_BASE_MAC_COLOR_SPACE_UTIL_MAC_H_ +#define MEDIA_BASE_MAC_COLOR_SPACE_UTIL_MAC_H_ + +#include <CoreMedia/CoreMedia.h> +#include <CoreVideo/CoreVideo.h> + +#include "media/base/media_export.h" +#include "ui/gfx/color_space.h" + +namespace media { + +MEDIA_EXPORT gfx::ColorSpace GetImageBufferColorSpace( + CVImageBufferRef image_buffer); + +MEDIA_EXPORT gfx::ColorSpace GetFormatDescriptionColorSpace( + CMFormatDescriptionRef format_description) API_AVAILABLE(macos(10.11)); + +} // namespace media + +#endif // MEDIA_BASE_MAC_COLOR_SPACE_UTIL_MAC_H_ diff --git a/chromium/media/base/mac/color_space_util_mac.mm b/chromium/media/base/mac/color_space_util_mac.mm new file mode 100644 index 00000000000..8e76a7ef56d --- /dev/null +++ b/chromium/media/base/mac/color_space_util_mac.mm @@ -0,0 +1,285 @@ +// 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/mac/color_space_util_mac.h" + +#include <vector> + +#include "base/mac/foundation_util.h" +#include "base/no_destructor.h" + +namespace media { + +namespace { + +// Read the value for the key in |key| to CFString and convert it to IdType. +// Use the list of pairs in |cfstr_id_pairs| to do the conversion (by doing a +// linear lookup). +template <typename IdType, typename StringIdPair> +bool GetImageBufferProperty(CFTypeRef value_untyped, + const std::vector<StringIdPair>& cfstr_id_pairs, + IdType* value_as_id) { + CFStringRef value_as_string = base::mac::CFCast<CFStringRef>(value_untyped); + if (!value_as_string) + return false; + + for (const auto& p : cfstr_id_pairs) { + if (p.cfstr_cm) + DCHECK(!CFStringCompare(p.cfstr_cv, p.cfstr_cm, 0)); + if (!CFStringCompare(value_as_string, p.cfstr_cv, 0)) { + *value_as_id = p.id; + return true; + } + } + + return false; +} + +gfx::ColorSpace::PrimaryID GetCoreVideoPrimary(CFTypeRef primaries_untyped) { + struct CVImagePrimary { + const CFStringRef cfstr_cv; + const CFStringRef cfstr_cm; + const gfx::ColorSpace::PrimaryID id; + }; + static const base::NoDestructor<std::vector<CVImagePrimary>> + kSupportedPrimaries([] { + std::vector<CVImagePrimary> supported_primaries; + supported_primaries.push_back( + {kCVImageBufferColorPrimaries_ITU_R_709_2, + kCMFormatDescriptionColorPrimaries_ITU_R_709_2, + gfx::ColorSpace::PrimaryID::BT709}); + supported_primaries.push_back( + {kCVImageBufferColorPrimaries_EBU_3213, + kCMFormatDescriptionColorPrimaries_EBU_3213, + gfx::ColorSpace::PrimaryID::BT470BG}); + supported_primaries.push_back( + {kCVImageBufferColorPrimaries_SMPTE_C, + kCMFormatDescriptionColorPrimaries_SMPTE_C, + + gfx::ColorSpace::PrimaryID::SMPTE240M}); + if (@available(macos 10.11, *)) { + supported_primaries.push_back( + {kCVImageBufferColorPrimaries_ITU_R_2020, + kCMFormatDescriptionColorPrimaries_ITU_R_2020, + gfx::ColorSpace::PrimaryID::BT2020}); + } + return supported_primaries; + }()); + + // The named primaries. Default to BT709. + auto primary_id = gfx::ColorSpace::PrimaryID::BT709; + if (!GetImageBufferProperty(primaries_untyped, *kSupportedPrimaries, + &primary_id)) { + DLOG(ERROR) << "Failed to find CVImageBufferRef primaries."; + } + return primary_id; +} + +gfx::ColorSpace::TransferID GetCoreVideoTransferFn(CFTypeRef transfer_untyped, + CFTypeRef gamma_untyped, + double* gamma) { + struct CVImageTransferFn { + const CFStringRef cfstr_cv; + const CFStringRef cfstr_cm; + const gfx::ColorSpace::TransferID id; + }; + static const base::NoDestructor<std::vector<CVImageTransferFn>> + kSupportedTransferFuncs([] { + std::vector<CVImageTransferFn> supported_transfer_funcs; + // The constants kCMFormatDescriptionTransferFunction_ITU_R_709_2, + // SMPTE_240M_1995, and UseGamma will compile against macOS 10.10 + // because they are #defined to their kCVImageBufferTransferFunction + // equivalents. They are technically not present until macOS 10.11. + supported_transfer_funcs.push_back( + {kCVImageBufferTransferFunction_ITU_R_709_2, + kCMFormatDescriptionTransferFunction_ITU_R_709_2, + gfx::ColorSpace::TransferID::BT709_APPLE}); + supported_transfer_funcs.push_back( + {kCVImageBufferTransferFunction_SMPTE_240M_1995, + kCMFormatDescriptionTransferFunction_SMPTE_240M_1995, + gfx::ColorSpace::TransferID::SMPTE240M}); + supported_transfer_funcs.push_back( + {kCVImageBufferTransferFunction_UseGamma, + kCMFormatDescriptionTransferFunction_UseGamma, + gfx::ColorSpace::TransferID::CUSTOM}); + if (@available(macos 10.11, *)) { + supported_transfer_funcs.push_back( + {kCVImageBufferTransferFunction_ITU_R_2020, + kCMFormatDescriptionTransferFunction_ITU_R_2020, + gfx::ColorSpace::TransferID::BT2020_10}); + } + if (@available(macos 10.12, *)) { + supported_transfer_funcs.push_back( + {kCVImageBufferTransferFunction_SMPTE_ST_428_1, + kCMFormatDescriptionTransferFunction_SMPTE_ST_428_1, + gfx::ColorSpace::TransferID::SMPTEST428_1}); + } + if (@available(macos 10.13, *)) { + supported_transfer_funcs.push_back( + {kCVImageBufferTransferFunction_SMPTE_ST_2084_PQ, + kCMFormatDescriptionTransferFunction_SMPTE_ST_2084_PQ, + gfx::ColorSpace::TransferID::SMPTEST2084}); + supported_transfer_funcs.push_back( + {kCVImageBufferTransferFunction_ITU_R_2100_HLG, + kCMFormatDescriptionTransferFunction_ITU_R_2100_HLG, + gfx::ColorSpace::TransferID::ARIB_STD_B67}); + supported_transfer_funcs.push_back( + {kCVImageBufferTransferFunction_sRGB, nullptr, + gfx::ColorSpace::TransferID::IEC61966_2_1}); + } + if (@available(macos 10.14, *)) { + supported_transfer_funcs.push_back( + {kCVImageBufferTransferFunction_Linear, + kCMFormatDescriptionTransferFunction_Linear, + gfx::ColorSpace::TransferID::LINEAR}); + } + if (@available(macos 10.15, *)) { + supported_transfer_funcs.push_back( + {kCVImageBufferTransferFunction_sRGB, + kCMFormatDescriptionTransferFunction_sRGB, + gfx::ColorSpace::TransferID::IEC61966_2_1}); + } + + return supported_transfer_funcs; + }()); + + // The named transfer function. + auto transfer_id = gfx::ColorSpace::TransferID::BT709; + if (!GetImageBufferProperty(transfer_untyped, *kSupportedTransferFuncs, + &transfer_id)) { + DLOG(ERROR) << "Failed to find CVImageBufferRef transfer."; + } + + if (transfer_id != gfx::ColorSpace::TransferID::CUSTOM) + return transfer_id; + + // If we fail to retrieve the gamma parameter, fall back to BT709. + constexpr auto kDefaultTransferFn = gfx::ColorSpace::TransferID::BT709; + CFNumberRef gamma_number = base::mac::CFCast<CFNumberRef>(gamma_untyped); + if (!gamma_number) { + DLOG(ERROR) << "Failed to get gamma level."; + return kDefaultTransferFn; + } + + // CGFloat is a double on 64-bit systems. + CGFloat gamma_double = 0; + if (!CFNumberGetValue(gamma_number, kCFNumberCGFloatType, &gamma_double)) { + DLOG(ERROR) << "Failed to get CVImageBufferRef gamma level as float."; + return kDefaultTransferFn; + } + + if (gamma_double == 2.2) + return gfx::ColorSpace::TransferID::GAMMA22; + if (gamma_double == 2.8) + return gfx::ColorSpace::TransferID::GAMMA28; + + *gamma = gamma_double; + return transfer_id; +} + +gfx::ColorSpace::MatrixID GetCoreVideoMatrix(CFTypeRef matrix_untyped) { + struct CVImageMatrix { + const CFStringRef cfstr_cv; + const CFStringRef cfstr_cm; + gfx::ColorSpace::MatrixID id; + }; + static const base::NoDestructor<std::vector<CVImageMatrix>> + kSupportedMatrices([] { + std::vector<CVImageMatrix> supported_matrices; + supported_matrices.push_back( + {kCVImageBufferYCbCrMatrix_ITU_R_709_2, + kCMFormatDescriptionYCbCrMatrix_ITU_R_709_2, + gfx::ColorSpace::MatrixID::BT709}); + supported_matrices.push_back( + {kCVImageBufferYCbCrMatrix_ITU_R_601_4, + kCMFormatDescriptionYCbCrMatrix_ITU_R_601_4, + gfx::ColorSpace::MatrixID::SMPTE170M}); + supported_matrices.push_back( + {kCVImageBufferYCbCrMatrix_SMPTE_240M_1995, + kCMFormatDescriptionYCbCrMatrix_SMPTE_240M_1995, + gfx::ColorSpace::MatrixID::SMPTE240M}); + if (@available(macos 10.11, *)) { + supported_matrices.push_back( + {kCVImageBufferYCbCrMatrix_ITU_R_2020, + kCMFormatDescriptionYCbCrMatrix_ITU_R_2020, + gfx::ColorSpace::MatrixID::BT2020_NCL}); + } + return supported_matrices; + }()); + + auto matrix_id = gfx::ColorSpace::MatrixID::INVALID; + if (!GetImageBufferProperty(matrix_untyped, *kSupportedMatrices, + &matrix_id)) { + DLOG(ERROR) << "Failed to find CVImageBufferRef YUV matrix."; + } + return matrix_id; +} + +gfx::ColorSpace GetCoreVideoColorSpaceInternal(CFTypeRef primaries_untyped, + CFTypeRef transfer_untyped, + CFTypeRef gamma_untyped, + CFTypeRef matrix_untyped) { + double gamma; + auto primary_id = GetCoreVideoPrimary(primaries_untyped); + auto matrix_id = GetCoreVideoMatrix(matrix_untyped); + auto transfer_id = + GetCoreVideoTransferFn(transfer_untyped, gamma_untyped, &gamma); + + // Use a matrix id that is coherent with a primary id. Useful when we fail to + // parse the matrix. Previously it was always defaulting to MatrixID::BT709 + // See http://crbug.com/788236. + if (matrix_id == gfx::ColorSpace::MatrixID::INVALID) { + if (primary_id == gfx::ColorSpace::PrimaryID::BT470BG) + matrix_id = gfx::ColorSpace::MatrixID::BT470BG; + else + matrix_id = gfx::ColorSpace::MatrixID::BT709; + } + + // It is specified to the decoder to use luma=[16,235] chroma=[16,240] via + // the kCVPixelFormatType_420YpCbCr8BiPlanarVideoRange. + // + // TODO(crbug.com/1103432): We'll probably need support for more than limited + // range content if we want this to be used for more than video sites. + auto range_id = gfx::ColorSpace::RangeID::LIMITED; + + if (transfer_id == gfx::ColorSpace::TransferID::CUSTOM) { + // Transfer functions can also be specified as a gamma value. + skcms_TransferFunction custom_tr_fn = {2.2f, 1, 0, 1, 0, 0, 0}; + if (transfer_id == gfx::ColorSpace::TransferID::CUSTOM) + custom_tr_fn.g = gamma; + + return gfx::ColorSpace(primary_id, gfx::ColorSpace::TransferID::CUSTOM, + matrix_id, range_id, nullptr, &custom_tr_fn); + } + + return gfx::ColorSpace(primary_id, transfer_id, matrix_id, range_id); +} + +} // anonymous namespace + +gfx::ColorSpace GetImageBufferColorSpace(CVImageBufferRef image_buffer) { + return GetCoreVideoColorSpaceInternal( + CVBufferGetAttachment(image_buffer, kCVImageBufferColorPrimariesKey, + nullptr), + CVBufferGetAttachment(image_buffer, kCVImageBufferTransferFunctionKey, + nullptr), + CVBufferGetAttachment(image_buffer, kCVImageBufferGammaLevelKey, nullptr), + CVBufferGetAttachment(image_buffer, kCVImageBufferYCbCrMatrixKey, + nullptr)); +} + +gfx::ColorSpace GetFormatDescriptionColorSpace( + CMFormatDescriptionRef format_description) { + return GetCoreVideoColorSpaceInternal( + CMFormatDescriptionGetExtension( + format_description, kCMFormatDescriptionExtension_ColorPrimaries), + CMFormatDescriptionGetExtension( + format_description, kCMFormatDescriptionExtension_TransferFunction), + CMFormatDescriptionGetExtension(format_description, + kCMFormatDescriptionExtension_GammaLevel), + CMFormatDescriptionGetExtension( + format_description, kCMFormatDescriptionExtension_YCbCrMatrix)); +} + +} // namespace media diff --git a/chromium/media/base/mac/video_frame_mac.cc b/chromium/media/base/mac/video_frame_mac.cc index 458f0274bdb..ced632c600e 100644 --- a/chromium/media/base/mac/video_frame_mac.cc +++ b/chromium/media/base/mac/video_frame_mac.cc @@ -48,8 +48,7 @@ WrapVideoFrameInCVPixelBuffer(const VideoFrame& frame) { gfx::GpuMemoryBufferHandle handle = frame.GetGpuMemoryBuffer()->CloneHandle(); if (handle.type == gfx::GpuMemoryBufferType::IO_SURFACE_BUFFER) { - base::ScopedCFTypeRef<IOSurfaceRef> io_surface = - gfx::IOSurfaceMachPortToIOSurface(std::move(handle.mach_port)); + gfx::ScopedIOSurface io_surface = handle.io_surface; if (io_surface) { const CVReturn cv_return = CVPixelBufferCreateWithIOSurface( nullptr, io_surface, nullptr, pixel_buffer.InitializeInto()); diff --git a/chromium/media/base/media_log.h b/chromium/media/base/media_log.h index 48879f26e69..dc3ea25be66 100644 --- a/chromium/media/base/media_log.h +++ b/chromium/media/base/media_log.h @@ -17,6 +17,7 @@ #include "base/macros.h" #include "base/memory/ref_counted.h" #include "base/thread_annotations.h" +#include "build/build_config.h" #include "media/base/buffering_state.h" #include "media/base/media_export.h" #include "media/base/media_log_events.h" @@ -43,6 +44,15 @@ class MEDIA_EXPORT MediaLog { static const char kEventKey[]; static const char kStatusText[]; +// Maximum limit for the total number of logs kept per renderer. At the time of +// writing, 512 events of the kind: { "property": value } together consume ~88kb +// of memory on linux. +#if defined(OS_ANDROID) + static constexpr size_t kLogLimit = 128; +#else + static constexpr size_t kLogLimit = 512; +#endif + // Constructor is protected, see below. virtual ~MediaLog(); diff --git a/chromium/media/base/media_serializers.h b/chromium/media/base/media_serializers.h index 1a2a6bd5856..42f89c07122 100644 --- a/chromium/media/base/media_serializers.h +++ b/chromium/media/base/media_serializers.h @@ -18,7 +18,7 @@ #include "media/base/text_track_config.h" #include "media/base/video_decoder_config.h" #include "ui/gfx/geometry/size.h" -#include "ui/gl/hdr_metadata.h" +#include "ui/gfx/hdr_metadata.h" namespace media { @@ -212,8 +212,8 @@ struct MediaSerializer<VideoColorSpace> { // Class (complex) template <> -struct MediaSerializer<gl::HDRMetadata> { - static base::Value Serialize(const gl::HDRMetadata& value) { +struct MediaSerializer<gfx::HDRMetadata> { + static base::Value Serialize(const gfx::HDRMetadata& value) { // TODO(tmathmeyer) serialize more fields here potentially. base::Value result(base::Value::Type::DICTIONARY); FIELD_SERIALIZE("luminance range", diff --git a/chromium/media/base/media_switches.cc b/chromium/media/base/media_switches.cc index 0c20d23e273..07419d183fc 100644 --- a/chromium/media/base/media_switches.cc +++ b/chromium/media/base/media_switches.cc @@ -6,6 +6,7 @@ #include "base/command_line.h" #include "build/build_config.h" +#include "build/chromeos_buildflags.h" #include "components/system_media_controls/linux/buildflags/buildflags.h" namespace switches { @@ -191,14 +192,6 @@ const char kOverrideHardwareSecureCodecsForTesting[] = const char kEnableLiveCaptionPrefForTesting[] = "enable-live-caption-pref-for-testing"; -#if defined(OS_CHROMEOS) -// ChromeOS uses one of two VideoDecoder implementations based on SoC/board -// specific configurations that are signalled via this command line flag. -// TODO(b/159825227): remove when the "old" video decoder is fully launched. -const char kPlatformDisallowsChromeOSDirectVideoDecoder[] = - "platform-disallows-chromeos-direct-video-decoder"; -#endif - namespace autoplay { // Autoplay policy that requires a document user activation. @@ -326,11 +319,6 @@ const base::Feature kD3D11VideoDecoderIgnoreWorkarounds{ const base::Feature kD3D11VideoDecoderVP9Profile2{ "D3D11VideoDecoderEnableVP9Profile2", base::FEATURE_DISABLED_BY_DEFAULT}; -// Enable D3D11VideoDecoder to copy pictures based on workarounds, rather -// than binding them. -const base::Feature kD3D11VideoDecoderCopyPictures{ - "D3D11VideoDecoderCopyPictures", base::FEATURE_DISABLED_BY_DEFAULT}; - // Tell D3D11VideoDecoder not to switch the D3D11 device to multi-threaded mode. // This is to help us track down IGD crashes. const base::Feature kD3D11VideoDecoderSkipMultithreaded{ @@ -360,8 +348,8 @@ const base::Feature kGav1VideoDecoder{"Gav1VideoDecoder", // Show toolbar button that opens dialog for controlling media sessions. const base::Feature kGlobalMediaControls { "GlobalMediaControls", -#if defined(OS_WIN) || defined(OS_MAC) || \ - (defined(OS_LINUX) && !defined(OS_CHROMEOS)) +#if defined(OS_WIN) || defined(OS_MAC) || defined(OS_LINUX) || \ + BUILDFLAG(IS_LACROS) base::FEATURE_ENABLED_BY_DEFAULT #else base::FEATURE_DISABLED_BY_DEFAULT @@ -381,6 +369,19 @@ const base::Feature kGlobalMediaControlsForCast{ const base::Feature kGlobalMediaControlsForChromeOS{ "GlobalMediaControlsForChromeOS", base::FEATURE_DISABLED_BY_DEFAULT}; +constexpr base::FeatureParam<kCrosGlobalMediaControlsPinOptions>::Option + kCrosGlobalMediaControlsParamOptions[] = { + {kCrosGlobalMediaControlsPinOptions::kPin, "default-pinned"}, + {kCrosGlobalMediaControlsPinOptions::kNotPin, "default-unpinned"}, + {kCrosGlobalMediaControlsPinOptions::kHeuristic, "heuristic"}}; + +constexpr base::FeatureParam<kCrosGlobalMediaControlsPinOptions> + kCrosGlobalMediaControlsPinParam( + &kGlobalMediaControlsForChromeOS, + "CrosGlobalMediaControlsPinParam", + kCrosGlobalMediaControlsPinOptions::kHeuristic, + &kCrosGlobalMediaControlsParamOptions); + // Allow global media controls notifications to be dragged out into overlay // notifications. It is no-op if kGlobalMediaControls is not enabled. const base::Feature kGlobalMediaControlsOverlayControls{ @@ -389,8 +390,8 @@ const base::Feature kGlobalMediaControlsOverlayControls{ // Show picture-in-picture button in Global Media Controls. const base::Feature kGlobalMediaControlsPictureInPicture { "GlobalMediaControlsPictureInPicture", -#if defined(OS_WIN) || defined(OS_MAC) || \ - (defined(OS_LINUX) && !defined(OS_CHROMEOS)) +#if defined(OS_WIN) || defined(OS_MAC) || defined(OS_LINUX) || \ + BUILDFLAG(IS_LACROS) base::FEATURE_ENABLED_BY_DEFAULT #else base::FEATURE_DISABLED_BY_DEFAULT @@ -427,6 +428,10 @@ const base::Feature kUseR16Texture{"use-r16-texture", const base::Feature kUnifiedAutoplay{"UnifiedAutoplay", base::FEATURE_ENABLED_BY_DEFAULT}; +// Enable VA-API hardware decode acceleration for AV1. +const base::Feature kVaapiAV1Decoder{"VaapiAV1Decoder", + base::FEATURE_DISABLED_BY_DEFAULT}; + // Enable VA-API hardware low power encoder for all codecs on intel Gen9x gpu. const base::Feature kVaapiLowPowerEncoderGen9x{ "VaapiLowPowerEncoderGen9x", base::FEATURE_DISABLED_BY_DEFAULT}; @@ -439,11 +444,11 @@ const base::Feature kVaapiVP8Encoder{"VaapiVP8Encoder", const base::Feature kVaapiVP9Encoder{"VaapiVP9Encoder", base::FEATURE_ENABLED_BY_DEFAULT}; -#if defined(ARCH_CPU_X86_FAMILY) && defined(OS_CHROMEOS) +#if defined(ARCH_CPU_X86_FAMILY) && BUILDFLAG(IS_ASH) // Enable VP9 k-SVC decoding with HW decoder for webrtc use case on ChromeOS. const base::Feature kVp9kSVCHWDecoding{"Vp9kSVCHWDecoding", base::FEATURE_ENABLED_BY_DEFAULT}; -#endif // defined(ARCH_CPU_X86_FAMILY) && defined(OS_CHROMEOS) +#endif // defined(ARCH_CPU_X86_FAMILY) && BUILDFLAG(IS_ASH) // Inform video blitter of video color space. const base::Feature kVideoBlitColorAccuracy{"video-blit-color-accuracy", @@ -497,7 +502,7 @@ const base::Feature kWidevineAv1ForceSupportForTesting{ // Enables handling of hardware media keys for controlling media. const base::Feature kHardwareMediaKeyHandling { "HardwareMediaKeyHandling", -#if defined(OS_CHROMEOS) || defined(OS_WIN) || defined(OS_MAC) || \ +#if BUILDFLAG(IS_ASH) || defined(OS_WIN) || defined(OS_MAC) || \ BUILDFLAG(USE_MPRIS) base::FEATURE_ENABLED_BY_DEFAULT #else @@ -603,13 +608,9 @@ const base::Feature kUseAudioLatencyFromHAL{"UseAudioLatencyFromHAL", // the GPU main thread during VideoFrame construction. const base::Feature kUsePooledSharedImageVideoProvider{ "UsePooledSharedImageVideoProvider", base::FEATURE_ENABLED_BY_DEFAULT}; - -// Used to enable/disable zero copy video path on webview for MCVD. -const base::Feature kWebViewZeroCopyVideo{"WebViewZeroCopyVideo", - base::FEATURE_DISABLED_BY_DEFAULT}; #endif // defined(OS_ANDROID) -#if defined(OS_CHROMEOS) && BUILDFLAG(USE_CHROMEOS_MEDIA_ACCELERATION) +#if BUILDFLAG(IS_ASH) && BUILDFLAG(USE_CHROMEOS_MEDIA_ACCELERATION) // Enable the hardware-accelerated direct video decoder instead of the one // needing the VdaVideoDecoder adapter. This flag is used mainly as a // chrome:flag for developers debugging issues. TODO(b/159825227): remove when @@ -624,7 +625,7 @@ const base::Feature kUseChromeOSDirectVideoDecoder{ const base::Feature kUseAlternateVideoDecoderImplementation{ "UseAlternateVideoDecoderImplementation", base::FEATURE_DISABLED_BY_DEFAULT}; -#endif // defined(OS_CHROMEOS) && BUILDFLAG(USE_CHROMEOS_MEDIA_ACCELERATION) +#endif // BUILDFLAG(IS_ASH) && BUILDFLAG(USE_CHROMEOS_MEDIA_ACCELERATION) #if defined(OS_WIN) // Does NV12->NV12 video copy on the main thread right before the texture's @@ -675,7 +676,7 @@ const base::Feature MEDIA_EXPORT kAVFoundationCaptureV2{ // Controls whether or not the V2 capturer exports IOSurfaces for zero-copy. // This feature only has any effect if kAVFoundationCaptureV2 is also enabled. const base::Feature MEDIA_EXPORT kAVFoundationCaptureV2ZeroCopy{ - "AVFoundationCaptureV2ZeroCopy", base::FEATURE_DISABLED_BY_DEFAULT}; + "AVFoundationCaptureV2ZeroCopy", base::FEATURE_ENABLED_BY_DEFAULT}; const base::Feature MEDIA_EXPORT kVideoToolboxVp9Decoding{ "VideoToolboxVp9Decoding", base::FEATURE_DISABLED_BY_DEFAULT}; @@ -740,10 +741,6 @@ const base::Feature kMediaFeedsBackgroundFetching{ const base::Feature kMediaFeedsSafeSearch{"MediaFeedsSafeSearch", base::FEATURE_ENABLED_BY_DEFAULT}; -// Send events to devtools rather than to chrome://media-internals -const base::Feature kMediaInspectorLogging{"MediaInspectorLogging", - base::FEATURE_ENABLED_BY_DEFAULT}; - // Enables experimental local learning for media. Used in the context of media // capabilities only. Adds reporting only; does not change media behavior. const base::Feature kMediaLearningExperiment{"MediaLearningExperiment", @@ -772,7 +769,7 @@ const base::Feature kMediaPowerExperiment{"MediaPowerExperiment", // has audio focus enabled. const base::Feature kAudioFocusDuckFlash { "AudioFocusDuckFlash", -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) base::FEATURE_ENABLED_BY_DEFAULT #else base::FEATURE_DISABLED_BY_DEFAULT @@ -827,7 +824,7 @@ bool IsVideoCaptureAcceleratedJpegDecodingEnabled() { switches::kUseFakeMjpegDecodeAccelerator)) { return true; } -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) return true; #endif return false; diff --git a/chromium/media/base/media_switches.h b/chromium/media/base/media_switches.h index 0f47b38a949..e08ba0324d0 100644 --- a/chromium/media/base/media_switches.h +++ b/chromium/media/base/media_switches.h @@ -11,6 +11,7 @@ #include "base/feature_list.h" #include "build/build_config.h" +#include "build/chromeos_buildflags.h" #include "media/base/media_export.h" #include "media/media_buildflags.h" @@ -55,10 +56,6 @@ MEDIA_EXPORT extern const char kDisableAudioInput[]; MEDIA_EXPORT extern const char kUseOverlaysForVideo[]; #endif -#if defined(OS_CHROMEOS) -MEDIA_EXPORT extern const char kPlatformDisallowsChromeOSDirectVideoDecoder[]; -#endif - #if defined(USE_CRAS) MEDIA_EXPORT extern const char kUseCras[]; #endif @@ -117,7 +114,6 @@ MEDIA_EXPORT extern const base::Feature kD3D11PrintCodecOnCrash; MEDIA_EXPORT extern const base::Feature kD3D11VideoDecoder; MEDIA_EXPORT extern const base::Feature kD3D11VideoDecoderIgnoreWorkarounds; MEDIA_EXPORT extern const base::Feature kD3D11VideoDecoderVP9Profile2; -MEDIA_EXPORT extern const base::Feature kD3D11VideoDecoderCopyPictures; MEDIA_EXPORT extern const base::Feature kD3D11VideoDecoderSkipMultithreaded; MEDIA_EXPORT extern const base::Feature kD3D11VideoDecoderAlwaysCopy; MEDIA_EXPORT extern const base::Feature kD3D11VideoDecoderAllowOverlay; @@ -153,7 +149,6 @@ MEDIA_EXPORT extern const base::Feature kMediaEngagementHTTPSOnly; MEDIA_EXPORT extern const base::Feature kMediaFeeds; MEDIA_EXPORT extern const base::Feature kMediaFeedsBackgroundFetching; MEDIA_EXPORT extern const base::Feature kMediaFeedsSafeSearch; -MEDIA_EXPORT extern const base::Feature kMediaInspectorLogging; MEDIA_EXPORT extern const base::Feature kMediaLearningExperiment; MEDIA_EXPORT extern const base::Feature kMediaLearningFramework; MEDIA_EXPORT extern const base::Feature kMediaLearningSmoothnessExperiment; @@ -177,6 +172,7 @@ MEDIA_EXPORT extern const base::Feature kUseFakeDeviceForMediaStream; MEDIA_EXPORT extern const base::Feature kUseMediaHistoryStore; MEDIA_EXPORT extern const base::Feature kUseR16Texture; MEDIA_EXPORT extern const base::Feature kUseSodaForLiveCaption; +MEDIA_EXPORT extern const base::Feature kVaapiAV1Decoder; MEDIA_EXPORT extern const base::Feature kVaapiLowPowerEncoderGen9x; MEDIA_EXPORT extern const base::Feature kVaapiVP8Encoder; MEDIA_EXPORT extern const base::Feature kVaapiVP9Encoder; @@ -188,9 +184,9 @@ MEDIA_EXPORT extern const base::Feature kResolutionBasedDecoderPriority; MEDIA_EXPORT extern const base::Feature kForceHardwareVideoDecoders; MEDIA_EXPORT extern const base::Feature kForceHardwareAudioDecoders; -#if defined(ARCH_CPU_X86_FAMILY) && defined(OS_CHROMEOS) +#if defined(ARCH_CPU_X86_FAMILY) && BUILDFLAG(IS_ASH) MEDIA_EXPORT extern const base::Feature kVp9kSVCHWDecoding; -#endif // defined(ARCH_CPU_X86_FAMILY) && defined(OS_CHROMEOS) +#endif // defined(ARCH_CPU_X86_FAMILY) && BUILDFLAG(IS_ASH) #if defined(OS_ANDROID) MEDIA_EXPORT extern const base::Feature kAllowNonSecureOverlays; @@ -205,14 +201,13 @@ MEDIA_EXPORT extern const base::Feature kHlsPlayer; MEDIA_EXPORT extern const base::Feature kRequestSystemAudioFocus; MEDIA_EXPORT extern const base::Feature kUseAudioLatencyFromHAL; MEDIA_EXPORT extern const base::Feature kUsePooledSharedImageVideoProvider; -MEDIA_EXPORT extern const base::Feature kWebViewZeroCopyVideo; #endif // defined(OS_ANDROID) -#if defined(OS_CHROMEOS) && BUILDFLAG(USE_CHROMEOS_MEDIA_ACCELERATION) +#if BUILDFLAG(IS_ASH) && BUILDFLAG(USE_CHROMEOS_MEDIA_ACCELERATION) MEDIA_EXPORT extern const base::Feature kUseChromeOSDirectVideoDecoder; MEDIA_EXPORT extern const base::Feature kUseAlternateVideoDecoderImplementation; -#endif // defined(OS_CHROMEOS) && BUILDFLAG(USE_CHROMEOS_MEDIA_ACCELERATION) +#endif // BUILDFLAG(IS_ASH) && BUILDFLAG(USE_CHROMEOS_MEDIA_ACCELERATION) #if defined(OS_WIN) MEDIA_EXPORT extern const base::Feature kDelayCopyNV12Textures; @@ -240,6 +235,17 @@ MEDIA_EXPORT std::string GetEffectiveAutoplayPolicy( MEDIA_EXPORT bool IsVideoCaptureAcceleratedJpegDecodingEnabled(); +enum class kCrosGlobalMediaControlsPinOptions { + kPin, + kNotPin, + kHeuristic, +}; + +// Feature param used to force default pin/unpin for global media controls in +// CrOS. +MEDIA_EXPORT extern const base::FeatureParam<kCrosGlobalMediaControlsPinOptions> + kCrosGlobalMediaControlsPinParam; + } // namespace media #endif // MEDIA_BASE_MEDIA_SWITCHES_H_ diff --git a/chromium/media/base/media_types.h b/chromium/media/base/media_types.h index b96ee7bb4f4..f0b910ab1a9 100644 --- a/chromium/media/base/media_types.h +++ b/chromium/media/base/media_types.h @@ -33,7 +33,7 @@ struct MEDIA_EXPORT VideoType { VideoCodecProfile profile; int level; VideoColorSpace color_space; - gl::HdrMetadataType hdr_metadata_type; + gfx::HdrMetadataType hdr_metadata_type; }; MEDIA_EXPORT bool operator==(const AudioType& x, const AudioType& y); diff --git a/chromium/media/base/media_url_demuxer_unittest.cc b/chromium/media/base/media_url_demuxer_unittest.cc index 65869054e4e..136f0ac4794 100644 --- a/chromium/media/base/media_url_demuxer_unittest.cc +++ b/chromium/media/base/media_url_demuxer_unittest.cc @@ -5,7 +5,7 @@ #include "media/base/media_url_demuxer.h" #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/macros.h" #include "base/run_loop.h" #include "base/test/task_environment.h" diff --git a/chromium/media/base/mock_filters.cc b/chromium/media/base/mock_filters.cc index 34821e901da..f7fc5c0cf91 100644 --- a/chromium/media/base/mock_filters.cc +++ b/chromium/media/base/mock_filters.cc @@ -100,6 +100,11 @@ std::string MockVideoDecoder::GetDisplayName() const { return decoder_name_; } +MockVideoEncoder::MockVideoEncoder() = default; +MockVideoEncoder::~MockVideoEncoder() { + Dtor(); +} + MockAudioDecoder::MockAudioDecoder() : MockAudioDecoder("MockAudioDecoder") {} MockAudioDecoder::MockAudioDecoder(std::string decoder_name) diff --git a/chromium/media/base/mock_filters.h b/chromium/media/base/mock_filters.h index 25a78b098af..832c7b4650d 100644 --- a/chromium/media/base/mock_filters.h +++ b/chromium/media/base/mock_filters.h @@ -42,6 +42,7 @@ #include "media/base/time_source.h" #include "media/base/video_decoder.h" #include "media/base/video_decoder_config.h" +#include "media/base/video_encoder.h" #include "media/base/video_frame.h" #include "media/base/video_renderer.h" #include "testing/gmock/include/gmock/gmock.h" @@ -261,6 +262,43 @@ class MockVideoDecoder : public VideoDecoder { DISALLOW_COPY_AND_ASSIGN(MockVideoDecoder); }; +class MockVideoEncoder : public VideoEncoder { + public: + MockVideoEncoder(); + ~MockVideoEncoder() override; + + // VideoEncoder implementation. + MOCK_METHOD(void, + Initialize, + (VideoCodecProfile profile, + const VideoEncoder::Options& options, + VideoEncoder::OutputCB output_cb, + VideoEncoder::StatusCB done_cb), + (override)); + + MOCK_METHOD(void, + Encode, + (scoped_refptr<VideoFrame> frame, + bool key_frame, + VideoEncoder::StatusCB done_cb), + (override)); + + MOCK_METHOD(void, + ChangeOptions, + (const VideoEncoder::Options& options, + VideoEncoder::OutputCB output_cb, + VideoEncoder::StatusCB done_cb), + (override)); + + MOCK_METHOD(void, Flush, (VideoEncoder::StatusCB done_cb), (override)); + + // A function for mocking destructor calls + MOCK_METHOD(void, Dtor, ()); + + private: + DISALLOW_COPY_AND_ASSIGN(MockVideoEncoder); +}; + class MockAudioDecoder : public AudioDecoder { public: MockAudioDecoder(); diff --git a/chromium/media/base/multi_channel_resampler.cc b/chromium/media/base/multi_channel_resampler.cc index f7e52a70278..b37b72632a0 100644 --- a/chromium/media/base/multi_channel_resampler.cc +++ b/chromium/media/base/multi_channel_resampler.cc @@ -8,7 +8,7 @@ #include <memory> #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/check_op.h" #include "media/base/audio_bus.h" diff --git a/chromium/media/base/multi_channel_resampler_unittest.cc b/chromium/media/base/multi_channel_resampler_unittest.cc index dae0c72a805..1741286ad4f 100644 --- a/chromium/media/base/multi_channel_resampler_unittest.cc +++ b/chromium/media/base/multi_channel_resampler_unittest.cc @@ -8,7 +8,7 @@ #include <memory> #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/macros.h" #include "media/base/audio_bus.h" #include "testing/gtest/include/gtest/gtest.h" diff --git a/chromium/media/base/offloading_video_encoder.cc b/chromium/media/base/offloading_video_encoder.cc new file mode 100644 index 00000000000..02acf7135fe --- /dev/null +++ b/chromium/media/base/offloading_video_encoder.cc @@ -0,0 +1,89 @@ +// 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/offloading_video_encoder.h" + +#include "base/sequenced_task_runner.h" +#include "base/task/task_traits.h" +#include "base/task/thread_pool.h" +#include "media/base/bind_to_current_loop.h" +#include "media/base/video_frame.h" + +namespace media { + +OffloadingVideoEncoder::OffloadingVideoEncoder( + std::unique_ptr<VideoEncoder> wrapped_encoder, + const scoped_refptr<base::SequencedTaskRunner> work_runner, + const scoped_refptr<base::SequencedTaskRunner> callback_runner) + : wrapped_encoder_(std::move(wrapped_encoder)), + work_runner_(std::move(work_runner)), + callback_runner_(std::move(callback_runner)) { + DCHECK(wrapped_encoder_); + DCHECK(work_runner_); + DCHECK(callback_runner_); + DCHECK_NE(callback_runner_, work_runner_); +} + +OffloadingVideoEncoder::OffloadingVideoEncoder( + std::unique_ptr<VideoEncoder> wrapped_encoder) + : OffloadingVideoEncoder(std::move(wrapped_encoder), + base::ThreadPool::CreateSequencedTaskRunner( + {base::TaskPriority::USER_BLOCKING}), + base::SequencedTaskRunnerHandle::Get()) {} + +void OffloadingVideoEncoder::Initialize(VideoCodecProfile profile, + const Options& options, + OutputCB output_cb, + StatusCB done_cb) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + work_runner_->PostTask( + FROM_HERE, + base::BindOnce(&VideoEncoder::Initialize, + base::Unretained(wrapped_encoder_.get()), profile, options, + WrapCallback(std::move(output_cb)), + WrapCallback(std::move(done_cb)))); +} + +void OffloadingVideoEncoder::Encode(scoped_refptr<VideoFrame> frame, + bool key_frame, + StatusCB done_cb) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + work_runner_->PostTask( + FROM_HERE, + base::BindOnce(&VideoEncoder::Encode, + base::Unretained(wrapped_encoder_.get()), std::move(frame), + key_frame, WrapCallback(std::move(done_cb)))); +} + +void OffloadingVideoEncoder::ChangeOptions(const Options& options, + OutputCB output_cb, + StatusCB done_cb) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + work_runner_->PostTask( + FROM_HERE, base::BindOnce(&VideoEncoder::ChangeOptions, + base::Unretained(wrapped_encoder_.get()), + options, WrapCallback(std::move(output_cb)), + WrapCallback(std::move(done_cb)))); +} + +void OffloadingVideoEncoder::Flush(StatusCB done_cb) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + work_runner_->PostTask( + FROM_HERE, base::BindOnce(&VideoEncoder::Flush, + base::Unretained(wrapped_encoder_.get()), + WrapCallback(std::move(done_cb)))); +} + +OffloadingVideoEncoder::~OffloadingVideoEncoder() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + work_runner_->DeleteSoon(FROM_HERE, std::move(wrapped_encoder_)); +} + +template <class T> +T OffloadingVideoEncoder::WrapCallback(T cb) { + DCHECK(callback_runner_); + return media::BindToLoop(callback_runner_.get(), std::move(cb)); +} + +} // namespace media
\ No newline at end of file diff --git a/chromium/media/base/offloading_video_encoder.h b/chromium/media/base/offloading_video_encoder.h new file mode 100644 index 00000000000..6000c4ccb09 --- /dev/null +++ b/chromium/media/base/offloading_video_encoder.h @@ -0,0 +1,67 @@ +// 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. + +#ifndef MEDIA_BASE_OFFLOADING_VIDEO_ENCODER_H_ +#define MEDIA_BASE_OFFLOADING_VIDEO_ENCODER_H_ + +#include <memory> +#include <type_traits> + +#include "base/sequence_checker.h" +#include "media/base/video_encoder.h" + +namespace base { +class SequencedTaskRunner; +} + +namespace media { + +// A wrapper around video encoder that offloads all the calls to a dedicated +// task runner. It's used to move synchronous software encoding work off the +// current (main) thread. +class MEDIA_EXPORT OffloadingVideoEncoder final : public VideoEncoder { + public: + // |work_runner| - task runner for encoding work + // |callback_runner| - all encoder's callbacks will be executed on this task + // runner. + OffloadingVideoEncoder( + std::unique_ptr<VideoEncoder> wrapped_encoder, + const scoped_refptr<base::SequencedTaskRunner> work_runner, + const scoped_refptr<base::SequencedTaskRunner> callback_runner); + + // Uses current task runner for callbacks and asks thread pool for a new task + // runner to do actual encoding work. + explicit OffloadingVideoEncoder( + std::unique_ptr<VideoEncoder> wrapped_encoder); + + ~OffloadingVideoEncoder() override; + + void Initialize(VideoCodecProfile profile, + const Options& options, + OutputCB output_cb, + StatusCB done_cb) override; + + void Encode(scoped_refptr<VideoFrame> frame, + bool key_frame, + StatusCB done_cb) override; + + void ChangeOptions(const Options& options, + OutputCB output_cb, + StatusCB done_cb) override; + + void Flush(StatusCB done_cb) override; + + private: + template <class T> + T WrapCallback(T cb); + + std::unique_ptr<VideoEncoder> wrapped_encoder_; + const scoped_refptr<base::SequencedTaskRunner> work_runner_; + const scoped_refptr<base::SequencedTaskRunner> callback_runner_; + SEQUENCE_CHECKER(sequence_checker_); +}; + +} // namespace media + +#endif // MEDIA_BASE_OFFLOADING_VIDEO_ENCODER_H_ diff --git a/chromium/media/base/offloading_video_encoder_unittest.cc b/chromium/media/base/offloading_video_encoder_unittest.cc new file mode 100644 index 00000000000..3bccecf3552 --- /dev/null +++ b/chromium/media/base/offloading_video_encoder_unittest.cc @@ -0,0 +1,148 @@ +// 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 <memory> +#include <vector> + +#include "base/bind.h" +#include "base/callback_helpers.h" +#include "base/run_loop.h" +#include "base/sequenced_task_runner.h" +#include "base/test/bind.h" +#include "base/test/gmock_callback_support.h" +#include "base/test/task_environment.h" +#include "media/base/media_util.h" +#include "media/base/mock_filters.h" +#include "media/base/offloading_video_encoder.h" +#include "media/base/video_types.h" +#include "testing/gtest/include/gtest/gtest.h" + +using ::base::test::RunCallback; +using ::base::test::RunOnceCallback; +using ::testing::_; +using ::testing::DoAll; +using ::testing::Invoke; +using ::testing::Return; + +namespace media { + +class OffloadingVideoEncoderTest : public testing::Test { + protected: + void SetUp() override { + auto mock_video_encoder = std::make_unique<MockVideoEncoder>(); + mock_video_encoder_ = mock_video_encoder.get(); + work_runner_ = base::ThreadPool::CreateSequencedTaskRunner({}); + callback_runner_ = base::SequencedTaskRunnerHandle::Get(); + offloading_encoder_ = std::make_unique<OffloadingVideoEncoder>( + std::move(mock_video_encoder), work_runner_, callback_runner_); + EXPECT_CALL(*mock_video_encoder_, Dtor()).WillOnce(Invoke([this]() { + EXPECT_TRUE(work_runner_->RunsTasksInCurrentSequence()); + })); + } + + void RunLoop() { task_environment_.RunUntilIdle(); } + + base::test::TaskEnvironment task_environment_; + scoped_refptr<base::SequencedTaskRunner> work_runner_; + scoped_refptr<base::SequencedTaskRunner> callback_runner_; + MockVideoEncoder* mock_video_encoder_; + std::unique_ptr<OffloadingVideoEncoder> offloading_encoder_; +}; + +TEST_F(OffloadingVideoEncoderTest, Initialize) { + bool called_done = false; + bool called_output = false; + VideoEncoder::Options options; + VideoCodecProfile profile = VIDEO_CODEC_PROFILE_UNKNOWN; + VideoEncoder::OutputCB output_cb = base::BindLambdaForTesting( + [&](VideoEncoderOutput, base::Optional<VideoEncoder::CodecDescription>) { + EXPECT_TRUE(callback_runner_->RunsTasksInCurrentSequence()); + called_output = true; + }); + VideoEncoder::StatusCB done_cb = base::BindLambdaForTesting([&](Status s) { + EXPECT_TRUE(callback_runner_->RunsTasksInCurrentSequence()); + called_done = true; + }); + + EXPECT_CALL(*mock_video_encoder_, Initialize(_, _, _, _)) + .WillOnce(Invoke([this](VideoCodecProfile profile, + const VideoEncoder::Options& options, + VideoEncoder::OutputCB output_cb, + VideoEncoder::StatusCB done_cb) { + EXPECT_TRUE(work_runner_->RunsTasksInCurrentSequence()); + std::move(done_cb).Run(Status()); + std::move(output_cb).Run(VideoEncoderOutput(), {}); + })); + + offloading_encoder_->Initialize(profile, options, std::move(output_cb), + std::move(done_cb)); + RunLoop(); + EXPECT_TRUE(called_done); + EXPECT_TRUE(called_output); +} + +TEST_F(OffloadingVideoEncoderTest, Encode) { + bool called_done = false; + VideoEncoder::StatusCB done_cb = base::BindLambdaForTesting([&](Status s) { + EXPECT_TRUE(callback_runner_->RunsTasksInCurrentSequence()); + called_done = true; + }); + + EXPECT_CALL(*mock_video_encoder_, Encode(_, _, _)) + .WillOnce(Invoke([this](scoped_refptr<VideoFrame> frame, bool key_frame, + VideoEncoder::StatusCB done_cb) { + EXPECT_TRUE(work_runner_->RunsTasksInCurrentSequence()); + std::move(done_cb).Run(Status()); + })); + + offloading_encoder_->Encode(nullptr, false, std::move(done_cb)); + RunLoop(); + EXPECT_TRUE(called_done); +} + +TEST_F(OffloadingVideoEncoderTest, ChangeOptions) { + bool called_done = false; + VideoEncoder::Options options; + VideoEncoder::StatusCB done_cb = base::BindLambdaForTesting([&](Status s) { + EXPECT_TRUE(callback_runner_->RunsTasksInCurrentSequence()); + called_done = true; + }); + + VideoEncoder::OutputCB output_cb = base::BindRepeating( + [](VideoEncoderOutput, base::Optional<VideoEncoder::CodecDescription>) { + }); + + EXPECT_CALL(*mock_video_encoder_, ChangeOptions(_, _, _)) + .WillOnce(Invoke([this](const VideoEncoder::Options& options, + VideoEncoder::OutputCB output_cb, + VideoEncoder::StatusCB done_cb) { + EXPECT_TRUE(work_runner_->RunsTasksInCurrentSequence()); + std::move(done_cb).Run(Status()); + })); + + offloading_encoder_->ChangeOptions(options, std::move(output_cb), + std::move(done_cb)); + RunLoop(); + EXPECT_TRUE(called_done); +} + +TEST_F(OffloadingVideoEncoderTest, Flush) { + bool called_done = false; + VideoEncoder::StatusCB done_cb = base::BindLambdaForTesting([&](Status s) { + EXPECT_TRUE(callback_runner_->RunsTasksInCurrentSequence()); + called_done = true; + }); + + EXPECT_CALL(*mock_video_encoder_, Flush(_)) + .WillOnce(Invoke([this](VideoEncoder::StatusCB done_cb) { + EXPECT_TRUE(work_runner_->RunsTasksInCurrentSequence()); + std::move(done_cb).Run(Status()); + })); + + offloading_encoder_->Flush(std::move(done_cb)); + RunLoop(); + EXPECT_TRUE(called_done); +} + +} // namespace media diff --git a/chromium/media/base/pipeline_impl.cc b/chromium/media/base/pipeline_impl.cc index 8104646400b..67f988b9dde 100644 --- a/chromium/media/base/pipeline_impl.cc +++ b/chromium/media/base/pipeline_impl.cc @@ -8,7 +8,6 @@ #include <utility> #include "base/bind.h" -#include "base/bind_helpers.h" #include "base/callback.h" #include "base/callback_helpers.h" #include "base/command_line.h" @@ -51,8 +50,8 @@ gfx::Size GetRotatedVideoSize(VideoRotation rotation, gfx::Size natural_size) { // |default_renderer| in Start() and Resume() helps avoid a round trip to the // render main task runner for Renderer creation in most cases which could add // latency to start-to-play time. -class PipelineImpl::RendererWrapper : public DemuxerHost, - public RendererClient { +class PipelineImpl::RendererWrapper final : public DemuxerHost, + public RendererClient { public: RendererWrapper(scoped_refptr<base::SingleThreadTaskRunner> media_task_runner, scoped_refptr<base::SingleThreadTaskRunner> main_task_runner, diff --git a/chromium/media/base/provision_fetcher.h b/chromium/media/base/provision_fetcher.h index e63b4786be2..48135306722 100644 --- a/chromium/media/base/provision_fetcher.h +++ b/chromium/media/base/provision_fetcher.h @@ -9,6 +9,7 @@ #include <string> #include "base/callback.h" +#include "url/gurl.h" namespace media { @@ -29,7 +30,7 @@ class ProvisionFetcher { // MediaDrm.ProvisionRequest. // The implementation must call |response_cb| asynchronously on the same // thread that this method is called. - virtual void Retrieve(const std::string& default_url, + virtual void Retrieve(const GURL& default_url, const std::string& request_data, ResponseCB response_cb) = 0; }; diff --git a/chromium/media/base/sinc_resampler_perftest.cc b/chromium/media/base/sinc_resampler_perftest.cc index 70436975874..905d8b98c2e 100644 --- a/chromium/media/base/sinc_resampler_perftest.cc +++ b/chromium/media/base/sinc_resampler_perftest.cc @@ -3,7 +3,7 @@ // found in the LICENSE file. #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/time/time.h" #include "build/build_config.h" #include "media/base/sinc_resampler.h" diff --git a/chromium/media/base/sinc_resampler_unittest.cc b/chromium/media/base/sinc_resampler_unittest.cc index 0197ffdec6d..195da5d1f9e 100644 --- a/chromium/media/base/sinc_resampler_unittest.cc +++ b/chromium/media/base/sinc_resampler_unittest.cc @@ -5,7 +5,7 @@ #include <memory> #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/macros.h" #include "base/numerics/math_constants.h" #include "base/strings/string_number_conversions.h" diff --git a/chromium/media/base/status.h b/chromium/media/base/status.h index 96e26e6e421..ef49cc32781 100644 --- a/chromium/media/base/status.h +++ b/chromium/media/base/status.h @@ -152,9 +152,14 @@ MEDIA_EXPORT Status OkStatus(); // TODO(liberato): Add more helper functions for common error returns. -// Helper class to allow returning a |T| or a Status. Typical usage: +// Helper class to allow returning a `T` or a Status. // -// ErrorOr<std::unique_ptr<MyObject>> FactoryFn() { +// It is not okay to send a StatusOr with a status code of `kOk`. `kOk` is +// reserved for cases where there is a `T` rather than a Status. +// +// Typical usage: +// +// StatusOr<std::unique_ptr<MyObject>> FactoryFn() { // if (success) // return std::make_unique<MyObject>(); // return Status(StatusCodes::kSomethingBadHappened); @@ -164,12 +169,24 @@ MEDIA_EXPORT Status OkStatus(); // if (result.has_error()) return std::move(result.error()); // my_object_ = std::move(result.value()); // +// Can also be combined into a single switch using `code()`: +// +// switch (result.code()) { +// case StatusCode::kOk: +// // `kOk` is special; it means the StatusOr has a `T`. +// // Do something with result.value() +// break; +// // Maybe switch on specific non-kOk codes for special processing. +// default: // Send unknown errors upwards. +// return std::move(result.error()); +// } +// // Also useful if one would like to get an enum class return value, unless an // error occurs: // // enum class ResultType { kNeedMoreInput, kOutputIsReady, kFormatChanged }; // -// ErrorOr<ResultType> Foo() { ... } +// StatusOr<ResultType> Foo() { ... } // // auto result = Foo(); // if (result.has_error()) return std::move(result.error()); @@ -178,26 +195,32 @@ MEDIA_EXPORT Status OkStatus(); // ... // } template <typename T> -class ErrorOr { +class StatusOr { public: // All of these may be implicit, so that one may just return Status or // the value in question. - ErrorOr(Status&& error) : error_(std::move(error)) {} - ErrorOr(const Status& error) : error_(error) {} - ErrorOr(StatusCode code, - const base::Location& location = base::Location::Current()) - : error_(Status(code, "", location)) {} + StatusOr(Status&& error) : error_(std::move(error)) { + DCHECK(!this->error().is_ok()); + } + StatusOr(const Status& error) : error_(error) { + DCHECK(!this->error().is_ok()); + } + StatusOr(StatusCode code, + const base::Location& location = base::Location::Current()) + : error_(Status(code, "", location)) { + DCHECK(!error().is_ok()); + } - ErrorOr(T&& value) : value_(std::move(value)) {} - ErrorOr(const T& value) : value_(value) {} + StatusOr(T&& value) : value_(std::move(value)) {} + StatusOr(const T& value) : value_(value) {} - ~ErrorOr() = default; + ~StatusOr() = default; // Move- and copy- construction and assignment are okay. - ErrorOr(const ErrorOr&) = default; - ErrorOr(ErrorOr&&) = default; - ErrorOr& operator=(ErrorOr&) = default; - ErrorOr& operator=(ErrorOr&&) = default; + StatusOr(const StatusOr&) = default; + StatusOr(StatusOr&&) = default; + StatusOr& operator=(StatusOr&) = default; + StatusOr& operator=(StatusOr&&) = default; // Do we have a value? bool has_value() const { return value_.has_value(); } @@ -209,10 +232,18 @@ class ErrorOr { // have one via |!has_value()|. Status& error() { return *error_; } + const Status& error() const { return *error_; } + // Return a ref to the value. It's up to the caller to verify that we have a // value before calling this. T& value() { return std::get<0>(*value_); } + // Returns the error code we have, if any, or `kOk` if we have a value. If + // this returns `kOk`, then it is equivalent to has_value(). + StatusCode code() const { + return has_error() ? error().code() : StatusCode::kOk; + } + private: base::Optional<Status> error_; // We wrap |T| in a container so that windows COM wrappers work. They diff --git a/chromium/media/base/status_unittest.cc b/chromium/media/base/status_unittest.cc index b9e6604c7ac..0a2f7cc5e21 100644 --- a/chromium/media/base/status_unittest.cc +++ b/chromium/media/base/status_unittest.cc @@ -65,8 +65,8 @@ class StatusTest : public testing::Test { return me; } - // Make sure that the typical usage of ErrorOr actually compiles. - ErrorOr<std::unique_ptr<int>> TypicalErrorOrUsage(bool succeed) { + // Make sure that the typical usage of StatusOr actually compiles. + StatusOr<std::unique_ptr<int>> TypicalStatusOrUsage(bool succeed) { if (succeed) return std::make_unique<int>(123); return Status(StatusCode::kCodeOnlyForTesting); @@ -192,16 +192,16 @@ TEST_F(StatusTest, CanCopyEasily) { ASSERT_EQ(actual.FindDictPath("data")->DictSize(), 1ul); } -TEST_F(StatusTest, ErrorOrTypicalUsage) { +TEST_F(StatusTest, StatusOrTypicalUsage) { // Mostly so we have some code coverage on the default usage. - EXPECT_TRUE(TypicalErrorOrUsage(true).has_value()); - EXPECT_FALSE(TypicalErrorOrUsage(true).has_error()); - EXPECT_FALSE(TypicalErrorOrUsage(false).has_value()); - EXPECT_TRUE(TypicalErrorOrUsage(false).has_error()); + EXPECT_TRUE(TypicalStatusOrUsage(true).has_value()); + EXPECT_FALSE(TypicalStatusOrUsage(true).has_error()); + EXPECT_FALSE(TypicalStatusOrUsage(false).has_value()); + EXPECT_TRUE(TypicalStatusOrUsage(false).has_error()); } -TEST_F(StatusTest, ErrorOrWithMoveOnlyType) { - ErrorOr<std::unique_ptr<int>> error_or(std::make_unique<int>(123)); +TEST_F(StatusTest, StatusOrWithMoveOnlyType) { + StatusOr<std::unique_ptr<int>> error_or(std::make_unique<int>(123)); EXPECT_TRUE(error_or.has_value()); EXPECT_FALSE(error_or.has_error()); std::unique_ptr<int> result = std::move(error_or.value()); @@ -210,8 +210,8 @@ TEST_F(StatusTest, ErrorOrWithMoveOnlyType) { EXPECT_EQ(*result, 123); } -TEST_F(StatusTest, ErrorOrWithCopyableType) { - ErrorOr<int> error_or(123); +TEST_F(StatusTest, StatusOrWithCopyableType) { + StatusOr<int> error_or(123); EXPECT_TRUE(error_or.has_value()); EXPECT_FALSE(error_or.has_error()); int result = std::move(error_or.value()); @@ -220,14 +220,14 @@ TEST_F(StatusTest, ErrorOrWithCopyableType) { EXPECT_EQ(error_or.value(), 123); } -TEST_F(StatusTest, ErrorOrMoveConstructionAndAssignment) { +TEST_F(StatusTest, StatusOrMoveConstructionAndAssignment) { // Make sure that we can move-construct and move-assign a move-only value. - ErrorOr<std::unique_ptr<int>> error_or_0(std::make_unique<int>(123)); + StatusOr<std::unique_ptr<int>> error_or_0(std::make_unique<int>(123)); - ErrorOr<std::unique_ptr<int>> error_or_1(std::move(error_or_0)); + StatusOr<std::unique_ptr<int>> error_or_1(std::move(error_or_0)); EXPECT_EQ(error_or_0.value(), nullptr); - ErrorOr<std::unique_ptr<int>> error_or_2 = std::move(error_or_1); + StatusOr<std::unique_ptr<int>> error_or_2 = std::move(error_or_1); EXPECT_EQ(error_or_1.value(), nullptr); // |error_or_2| should have gotten the original. @@ -235,12 +235,22 @@ TEST_F(StatusTest, ErrorOrMoveConstructionAndAssignment) { EXPECT_EQ(*value, 123); } -TEST_F(StatusTest, ErrorOrCopyWorks) { +TEST_F(StatusTest, StatusOrCopyWorks) { // Make sure that we can move-construct and move-assign a move-only value. - ErrorOr<int> error_or_0(123); - ErrorOr<int> error_or_1(std::move(error_or_0)); - ErrorOr<int> error_or_2 = std::move(error_or_1); + StatusOr<int> error_or_0(123); + StatusOr<int> error_or_1(std::move(error_or_0)); + StatusOr<int> error_or_2 = std::move(error_or_1); EXPECT_EQ(error_or_2.value(), 123); } +TEST_F(StatusTest, StatusOrCodeIsOkWithValue) { + StatusOr<int> error_or(123); + EXPECT_EQ(error_or.code(), StatusCode::kOk); +} + +TEST_F(StatusTest, StatusOrCodeIsNotOkWithoutValue) { + StatusOr<int> error_or(StatusCode::kCodeOnlyForTesting); + EXPECT_EQ(error_or.code(), StatusCode::kCodeOnlyForTesting); +} + } // namespace media diff --git a/chromium/media/base/supported_types.cc b/chromium/media/base/supported_types.cc index 2047bb52af4..05de5ab4464 100644 --- a/chromium/media/base/supported_types.cc +++ b/chromium/media/base/supported_types.cc @@ -9,6 +9,7 @@ #include "base/no_destructor.h" #include "base/notreached.h" #include "build/build_config.h" +#include "build/chromeos_buildflags.h" #include "media/base/media.h" #include "media/base/media_client.h" #include "media/base/media_switches.h" @@ -35,14 +36,14 @@ namespace media { namespace { -bool IsSupportedHdrMetadata(const gl::HdrMetadataType& hdr_metadata_type) { +bool IsSupportedHdrMetadata(const gfx::HdrMetadataType& hdr_metadata_type) { switch (hdr_metadata_type) { - case gl::HdrMetadataType::kNone: + case gfx::HdrMetadataType::kNone: return true; - case gl::HdrMetadataType::kSmpteSt2086: - case gl::HdrMetadataType::kSmpteSt2094_10: - case gl::HdrMetadataType::kSmpteSt2094_40: + case gfx::HdrMetadataType::kSmpteSt2086: + case gfx::HdrMetadataType::kSmpteSt2094_10: + case gfx::HdrMetadataType::kSmpteSt2094_40: return false; } @@ -242,7 +243,7 @@ bool IsDefaultSupportedAudioType(const AudioType& type) { case kCodecAMR_NB: case kCodecAMR_WB: case kCodecGSM_MS: -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) return true; #else return false; @@ -324,7 +325,7 @@ bool IsDefaultSupportedVideoType(const VideoType& type) { return false; case kCodecMPEG4: -#if defined(OS_CHROMEOS) +#if BUILDFLAG(IS_ASH) return true; #else return false; diff --git a/chromium/media/base/supported_types_unittest.cc b/chromium/media/base/supported_types_unittest.cc index 15232a77bb2..f7e04b945c7 100644 --- a/chromium/media/base/supported_types_unittest.cc +++ b/chromium/media/base/supported_types_unittest.cc @@ -5,6 +5,7 @@ #include "media/base/supported_types.h" #include "build/build_config.h" +#include "build/chromeos_buildflags.h" #include "testing/gtest/include/gtest/gtest.h" #if defined(OS_ANDROID) @@ -19,7 +20,7 @@ const bool kPropCodecsEnabled = true; const bool kPropCodecsEnabled = false; #endif -#if defined(OS_CHROMEOS) && BUILDFLAG(USE_PROPRIETARY_CODECS) +#if BUILDFLAG(IS_ASH) && BUILDFLAG(USE_PROPRIETARY_CODECS) const bool kMpeg4Supported = true; #else const bool kMpeg4Supported = false; @@ -170,8 +171,8 @@ TEST(SupportedTypesTest, IsSupportedVideoType_VP9Profiles) { // VP9 Profile2 are supported on x86, ChromeOS on ARM and Mac/Win on ARM64. // See third_party/libvpx/BUILD.gn. -#if defined(ARCH_CPU_X86_FAMILY) || \ - (defined(ARCH_CPU_ARM_FAMILY) && defined(OS_CHROMEOS)) || \ +#if defined(ARCH_CPU_X86_FAMILY) || \ + (defined(ARCH_CPU_ARM_FAMILY) && BUILDFLAG(IS_ASH)) || \ (defined(ARCH_CPU_ARM64) && (defined(OS_MAC) || defined(OS_WIN))) EXPECT_TRUE(IsSupportedVideoType( {kCodecVP9, VP9PROFILE_PROFILE2, kUnspecifiedLevel, kColorSpace})); @@ -276,14 +277,14 @@ TEST(SupportedTypesTest, IsSupportedVideoTypeWithHdrMetadataBasics) { // No HDR metadata types are supported. EXPECT_FALSE( IsSupportedVideoType({kCodecVP8, VP8PROFILE_ANY, kUnspecifiedLevel, - color_space, gl::HdrMetadataType::kSmpteSt2086})); + color_space, gfx::HdrMetadataType::kSmpteSt2086})); EXPECT_FALSE(IsSupportedVideoType({kCodecVP8, VP8PROFILE_ANY, kUnspecifiedLevel, color_space, - gl::HdrMetadataType::kSmpteSt2094_10})); + gfx::HdrMetadataType::kSmpteSt2094_10})); EXPECT_FALSE(IsSupportedVideoType({kCodecVP8, VP8PROFILE_ANY, kUnspecifiedLevel, color_space, - gl::HdrMetadataType::kSmpteSt2094_40})); + gfx::HdrMetadataType::kSmpteSt2094_40})); } } // namespace media diff --git a/chromium/media/base/test_helpers.cc b/chromium/media/base/test_helpers.cc index 73ac060dc52..84f8a2047cf 100644 --- a/chromium/media/base/test_helpers.cc +++ b/chromium/media/base/test_helpers.cc @@ -350,6 +350,45 @@ scoped_refptr<AudioBuffer> MakeAudioBuffer(SampleFormat format, return output; } +template <> +scoped_refptr<AudioBuffer> MakeAudioBuffer<float>(SampleFormat format, + ChannelLayout channel_layout, + size_t channel_count, + int sample_rate, + float start, + float increment, + size_t frames, + base::TimeDelta timestamp) { + const size_t channels = ChannelLayoutToChannelCount(channel_layout); + scoped_refptr<AudioBuffer> output = AudioBuffer::CreateBuffer( + format, channel_layout, static_cast<int>(channel_count), sample_rate, + static_cast<int>(frames)); + output->set_timestamp(timestamp); + + const bool is_planar = + format == kSampleFormatPlanarS16 || format == kSampleFormatPlanarF32; + + // Values in channel 0 will be: + // (start) / max_value + // (start + increment) / max_value + // (start + 2 * increment) / max_value, ... + // While, values in channel 1 will be: + // (start + frames * increment) / max_value + // (start + (frames + 1) * increment) / max_value + // (start + (frames + 2) * increment) / max_value, ... + for (size_t ch = 0; ch < channels; ++ch) { + float* buffer = + reinterpret_cast<float*>(output->channel_data()[is_planar ? ch : 0]); + const float v = static_cast<float>(start + ch * frames * increment); + for (size_t i = 0; i < frames; ++i) { + buffer[is_planar ? i : ch + i * channels] = + static_cast<float>(v + i * increment) / + std::numeric_limits<uint16_t>::max(); + } + } + return output; +} + scoped_refptr<AudioBuffer> MakeBitstreamAudioBuffer( SampleFormat format, ChannelLayout channel_layout, @@ -408,7 +447,6 @@ void VerifyBitstreamAudioBus(AudioBus* bus, DEFINE_MAKE_AUDIO_BUFFER_INSTANCE(uint8_t); DEFINE_MAKE_AUDIO_BUFFER_INSTANCE(int16_t); DEFINE_MAKE_AUDIO_BUFFER_INSTANCE(int32_t); -DEFINE_MAKE_AUDIO_BUFFER_INSTANCE(float); static const char kFakeVideoBufferHeader[] = "FakeVideoBufferForTest"; diff --git a/chromium/media/base/test_helpers.h b/chromium/media/base/test_helpers.h index 3a0df8eda59..d7bcf89cfc8 100644 --- a/chromium/media/base/test_helpers.h +++ b/chromium/media/base/test_helpers.h @@ -177,6 +177,18 @@ scoped_refptr<AudioBuffer> MakeAudioBuffer(SampleFormat format, size_t frames, base::TimeDelta timestamp); +// Similar to above, but for float types where the maximum range is limited to +// [-1.0f, 1.0f]. Here the stored values will be divided by 65536. +template <> +scoped_refptr<AudioBuffer> MakeAudioBuffer<float>(SampleFormat format, + ChannelLayout channel_layout, + size_t channel_count, + int sample_rate, + float start, + float increment, + size_t frames, + base::TimeDelta timestamp); + // Create an AudioBuffer containing bitstream data. |start| and |increment| are // used to specify the values for the data. The value is determined by: // start + frames * increment diff --git a/chromium/media/base/user_input_monitor_linux.cc b/chromium/media/base/user_input_monitor_linux.cc index 13c373fadfd..58b7d3033fe 100644 --- a/chromium/media/base/user_input_monitor_linux.cc +++ b/chromium/media/base/user_input_monitor_linux.cc @@ -19,57 +19,84 @@ #include "base/single_thread_task_runner.h" #include "base/synchronization/lock.h" #include "base/task/current_thread.h" -#include "media/base/keyboard_event_counter.h" #include "third_party/skia/include/core/SkPoint.h" -#include "ui/base/ui_base_features.h" #include "ui/events/devices/x11/xinput_util.h" +#include "ui/events/keyboard_event_counter.h" #include "ui/events/keycodes/keyboard_code_conversion_x.h" -#include "ui/gfx/x/x11.h" -#include "ui/gfx/x/x11_types.h" #include "ui/gfx/x/xinput.h" +#if defined(USE_X11) +#include "ui/base/x/x11_user_input_monitor.h" // nogncheck +#endif + +#if defined(USE_OZONE) +#include "ui/base/ui_base_features.h" // nogncheck +#include "ui/ozone/public/ozone_platform.h" // nogncheck +#include "ui/ozone/public/platform_user_input_monitor.h" // nogncheck +#endif + namespace media { namespace { -// This is the actual implementation of event monitoring. It's separated from -// UserInputMonitorLinux since it needs to be deleted on the IO thread. -class UserInputMonitorLinuxCore - : public base::SupportsWeakPtr<UserInputMonitorLinuxCore>, - public base::CurrentThread::DestructionObserver, - public x11::Connection::Delegate { - public: - explicit UserInputMonitorLinuxCore( - const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner); - ~UserInputMonitorLinuxCore() override; - - // base::CurrentThread::DestructionObserver: - void WillDestroyCurrentMessageLoop() override; +using WriteKeyPressCallback = + base::RepeatingCallback<void(const base::WritableSharedMemoryMapping& shmem, + uint32_t count)>; - // x11::Connection::Delegate: - bool ShouldContinueStream() const override; - void DispatchXEvent(x11::Event* event) override; +// Provides a unified interface for using user input monitors of unrelated +// classes. +// TODO(crbug.com/1096425): remove this when non-Ozone path is deprecated. +class UserInputMonitorAdapter + : public base::SupportsWeakPtr<UserInputMonitorAdapter> { + public: + UserInputMonitorAdapter() = default; + UserInputMonitorAdapter(const UserInputMonitorAdapter&) = delete; + UserInputMonitorAdapter& operator=(const UserInputMonitorAdapter&) = delete; + virtual ~UserInputMonitorAdapter() = default; + + virtual uint32_t GetKeyPressCount() const = 0; + virtual void StartMonitor(WriteKeyPressCallback callback) = 0; + virtual void StartMonitorWithMapping( + WriteKeyPressCallback callback, + base::WritableSharedMemoryMapping mapping) = 0; + virtual void StopMonitor() = 0; +}; - uint32_t GetKeyPressCount() const; - void StartMonitor(); - void StartMonitorWithMapping(base::WritableSharedMemoryMapping mapping); - void StopMonitor(); +// Wraps a specific user input monitor into UserInputMonitorAdapter interface. +template <typename Impl> +class UserInputMonitorLinuxCore : public UserInputMonitorAdapter { + public: + explicit UserInputMonitorLinuxCore(std::unique_ptr<Impl> user_input_monitor) + : user_input_monitor_(std::move(user_input_monitor)) {} + UserInputMonitorLinuxCore(const UserInputMonitorLinuxCore&) = delete; + UserInputMonitorLinuxCore operator=(const UserInputMonitorLinuxCore&) = + delete; + ~UserInputMonitorLinuxCore() override = default; + + uint32_t GetKeyPressCount() const override { + if (!user_input_monitor_) + return 0; + return user_input_monitor_->GetKeyPressCount(); + } + void StartMonitor(WriteKeyPressCallback callback) override { + if (!user_input_monitor_) + return; + user_input_monitor_->StartMonitor(callback); + } + void StartMonitorWithMapping( + WriteKeyPressCallback callback, + base::WritableSharedMemoryMapping mapping) override { + if (!user_input_monitor_) + return; + user_input_monitor_->StartMonitorWithMapping(callback, std::move(mapping)); + } + void StopMonitor() override { + if (!user_input_monitor_) + return; + user_input_monitor_->StopMonitor(); + } private: - void OnConnectionData(); - - scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_; - - // Used for sharing key press count value. - std::unique_ptr<base::WritableSharedMemoryMapping> key_press_count_mapping_; - - // - // The following members should only be accessed on the IO thread. - // - std::unique_ptr<base::FileDescriptorWatcher::Controller> watch_controller_; - std::unique_ptr<x11::Connection> connection_; - KeyboardEventCounter counter_; - - DISALLOW_COPY_AND_ASSIGN(UserInputMonitorLinuxCore); + std::unique_ptr<Impl> user_input_monitor_; }; class UserInputMonitorLinux : public UserInputMonitorBase { @@ -89,130 +116,27 @@ class UserInputMonitorLinux : public UserInputMonitorBase { void StopKeyboardMonitoring() override; scoped_refptr<base::SingleThreadTaskRunner> io_task_runner_; - UserInputMonitorLinuxCore* core_; + UserInputMonitorAdapter* core_; DISALLOW_COPY_AND_ASSIGN(UserInputMonitorLinux); }; -UserInputMonitorLinuxCore::UserInputMonitorLinuxCore( - const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner) - : io_task_runner_(io_task_runner) {} - -UserInputMonitorLinuxCore::~UserInputMonitorLinuxCore() { - DCHECK(!connection_); -} - -void UserInputMonitorLinuxCore::WillDestroyCurrentMessageLoop() { - DCHECK(io_task_runner_->BelongsToCurrentThread()); - StopMonitor(); -} - -bool UserInputMonitorLinuxCore::ShouldContinueStream() const { - return true; -} - -void UserInputMonitorLinuxCore::DispatchXEvent(x11::Event* event) { - DCHECK(io_task_runner_->BelongsToCurrentThread()); - - auto* raw = event->As<x11::Input::RawDeviceEvent>(); - if (!raw || (raw->opcode != x11::Input::RawDeviceEvent::RawKeyPress && - raw->opcode != x11::Input::RawDeviceEvent::RawKeyRelease)) { - return; - } - - ui::EventType type = raw->opcode == x11::Input::RawDeviceEvent::RawKeyPress - ? ui::ET_KEY_PRESSED - : ui::ET_KEY_RELEASED; - - auto key_sym = connection_->KeycodeToKeysym(raw->detail, 0); - ui::KeyboardCode key_code = - ui::KeyboardCodeFromXKeysym(static_cast<uint32_t>(key_sym)); - counter_.OnKeyboardEvent(type, key_code); - - // Update count value in shared memory. - if (key_press_count_mapping_) - WriteKeyPressMonitorCount(*key_press_count_mapping_, GetKeyPressCount()); -} - -uint32_t UserInputMonitorLinuxCore::GetKeyPressCount() const { - return counter_.GetKeyPressCount(); -} - -void UserInputMonitorLinuxCore::StartMonitor() { - DCHECK(io_task_runner_->BelongsToCurrentThread()); - - // TODO(https://crbug.com/1116414): support UserInputMonitorLinux on - // Ozone/Linux. +UserInputMonitorAdapter* CreateUserInputMonitor( + const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner) { +#if defined(USE_OZONE) if (features::IsUsingOzonePlatform()) { - NOTIMPLEMENTED_LOG_ONCE(); - StopMonitor(); - return; + return new UserInputMonitorLinuxCore<ui::PlatformUserInputMonitor>( + ui::OzonePlatform::GetInstance()->GetPlatformUserInputMonitor( + io_task_runner)); } - - if (!connection_) { - // TODO(jamiewalch): We should pass the connection in. - if (auto* connection = x11::Connection::Get()) { - connection_ = x11::Connection::Get()->Clone(); - } else { - LOG(ERROR) << "Couldn't open X connection"; - StopMonitor(); - return; - } - } - - if (!connection_->xinput().present()) { - LOG(ERROR) << "X Input extension not available."; - StopMonitor(); - return; - } - // Let the server know the client XInput version. - connection_->xinput().XIQueryVersion( - {x11::Input::major_version, x11::Input::minor_version}); - - x11::Input::XIEventMask mask; - ui::SetXinputMask(&mask, x11::Input::RawDeviceEvent::RawKeyPress); - ui::SetXinputMask(&mask, x11::Input::RawDeviceEvent::RawKeyRelease); - connection_->xinput().XISelectEvents( - {connection_->default_root(), - {{x11::Input::DeviceId::AllMaster, {mask}}}}); - connection_->Flush(); - - // Register OnConnectionData() to be called every time there is something to - // read from |connection_|. - watch_controller_ = base::FileDescriptorWatcher::WatchReadable( - connection_->GetFd(), - base::BindRepeating(&UserInputMonitorLinuxCore::OnConnectionData, - base::Unretained(this))); - - // Start observing message loop destruction if we start monitoring the first - // event. - base::CurrentThread::Get()->AddDestructionObserver(this); - - // Fetch pending events if any. - OnConnectionData(); -} - -void UserInputMonitorLinuxCore::StartMonitorWithMapping( - base::WritableSharedMemoryMapping mapping) { - StartMonitor(); - key_press_count_mapping_ = - std::make_unique<base::WritableSharedMemoryMapping>(std::move(mapping)); -} - -void UserInputMonitorLinuxCore::StopMonitor() { - DCHECK(io_task_runner_->BelongsToCurrentThread()); - - watch_controller_.reset(); - connection_.reset(); - key_press_count_mapping_.reset(); - - // Stop observing message loop destruction if no event is being monitored. - base::CurrentThread::Get()->RemoveDestructionObserver(this); -} - -void UserInputMonitorLinuxCore::OnConnectionData() { - DCHECK(io_task_runner_->BelongsToCurrentThread()); - connection_->Dispatch(this); +#endif +#if defined(USE_X11) + return new UserInputMonitorLinuxCore<ui::XUserInputMonitor>( + std::make_unique<ui::XUserInputMonitor>(io_task_runner)); +#else + NOTREACHED(); + return nullptr; +#endif } // @@ -222,34 +146,44 @@ void UserInputMonitorLinuxCore::OnConnectionData() { UserInputMonitorLinux::UserInputMonitorLinux( const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner) : io_task_runner_(io_task_runner), - core_(new UserInputMonitorLinuxCore(io_task_runner)) {} + core_(CreateUserInputMonitor(io_task_runner_)) {} UserInputMonitorLinux::~UserInputMonitorLinux() { - if (!io_task_runner_->DeleteSoon(FROM_HERE, core_)) + if (core_ && !io_task_runner_->DeleteSoon(FROM_HERE, core_)) delete core_; } uint32_t UserInputMonitorLinux::GetKeyPressCount() const { + if (!core_) + return 0; return core_->GetKeyPressCount(); } void UserInputMonitorLinux::StartKeyboardMonitoring() { + if (!core_) + return; io_task_runner_->PostTask( - FROM_HERE, base::BindOnce(&UserInputMonitorLinuxCore::StartMonitor, - core_->AsWeakPtr())); + FROM_HERE, + base::BindOnce(&UserInputMonitorAdapter::StartMonitor, core_->AsWeakPtr(), + base::BindRepeating(&WriteKeyPressMonitorCount))); } void UserInputMonitorLinux::StartKeyboardMonitoring( base::WritableSharedMemoryMapping mapping) { + if (!core_) + return; io_task_runner_->PostTask( FROM_HERE, - base::BindOnce(&UserInputMonitorLinuxCore::StartMonitorWithMapping, - core_->AsWeakPtr(), std::move(mapping))); + base::BindOnce( + &UserInputMonitorAdapter::StartMonitorWithMapping, core_->AsWeakPtr(), + base::BindRepeating(&WriteKeyPressMonitorCount), std::move(mapping))); } void UserInputMonitorLinux::StopKeyboardMonitoring() { + if (!core_) + return; io_task_runner_->PostTask( - FROM_HERE, base::BindOnce(&UserInputMonitorLinuxCore::StopMonitor, + FROM_HERE, base::BindOnce(&UserInputMonitorAdapter::StopMonitor, core_->AsWeakPtr())); } diff --git a/chromium/media/base/user_input_monitor_unittest.cc b/chromium/media/base/user_input_monitor_unittest.cc index fafc98e2db2..5e85052bad6 100644 --- a/chromium/media/base/user_input_monitor_unittest.cc +++ b/chromium/media/base/user_input_monitor_unittest.cc @@ -17,9 +17,21 @@ #include "base/files/file_descriptor_watcher_posix.h" #endif +#if defined(USE_OZONE) +#include "ui/base/ui_base_features.h" // nogncheck +#endif + namespace media { TEST(UserInputMonitorTest, CreatePlatformSpecific) { +#if defined(USE_OZONE) + // TODO(crbug.com/1109112): enable those tests for Ozone. + // Here, the only issue why they don't work is that the Ozone platform is not + // initialised. + if (features::IsUsingOzonePlatform()) + return; +#endif + #if defined(OS_LINUX) || defined(OS_CHROMEOS) base::test::TaskEnvironment task_environment( base::test::TaskEnvironment::MainThreadType::IO); @@ -42,6 +54,14 @@ TEST(UserInputMonitorTest, CreatePlatformSpecific) { } TEST(UserInputMonitorTest, CreatePlatformSpecificWithMapping) { +#if defined(USE_OZONE) + // TODO(crbug.com/1109112): enable those tests for Ozone. + // Here, the only issue why they don't work is that the Ozone platform is not + // initialised. + if (features::IsUsingOzonePlatform()) + return; +#endif + #if defined(OS_LINUX) || defined(OS_CHROMEOS) base::test::TaskEnvironment task_environment( base::test::TaskEnvironment::MainThreadType::IO); diff --git a/chromium/media/base/user_input_monitor_win.cc b/chromium/media/base/user_input_monitor_win.cc index 48abe735741..8187d23f282 100644 --- a/chromium/media/base/user_input_monitor_win.cc +++ b/chromium/media/base/user_input_monitor_win.cc @@ -17,8 +17,8 @@ #include "base/synchronization/lock.h" #include "base/task/current_thread.h" #include "base/win/message_window.h" -#include "media/base/keyboard_event_counter.h" #include "third_party/skia/include/core/SkPoint.h" +#include "ui/events/keyboard_event_counter.h" #include "ui/events/keycodes/keyboard_code_conversion_win.h" namespace media { @@ -77,7 +77,7 @@ class UserInputMonitorWinCore // These members are only accessed on the UI thread. std::unique_ptr<base::win::MessageWindow> window_; - KeyboardEventCounter counter_; + ui::KeyboardEventCounter counter_; DISALLOW_COPY_AND_ASSIGN(UserInputMonitorWinCore); }; @@ -164,8 +164,7 @@ void UserInputMonitorWinCore::StopMonitor() { // Stop receiving raw input. std::unique_ptr<RAWINPUTDEVICE> device( - GetRawInputDevices(window_->hwnd(), RIDEV_REMOVE)); - + GetRawInputDevices(nullptr, RIDEV_REMOVE)); if (!RegisterRawInputDevices(device.get(), 1, sizeof(*device))) { PLOG(INFO) << "RegisterRawInputDevices() failed for RIDEV_REMOVE"; } diff --git a/chromium/media/base/video_codecs.cc b/chromium/media/base/video_codecs.cc index 78a829ce194..6c58bbabd66 100644 --- a/chromium/media/base/video_codecs.cc +++ b/chromium/media/base/video_codecs.cc @@ -9,6 +9,7 @@ #include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" #include "base/strings/string_util.h" +#include "base/strings/stringprintf.h" #include "media/base/video_color_space.h" namespace media { @@ -110,6 +111,50 @@ std::string GetProfileName(VideoCodecProfile profile) { return ""; } +std::string BuildH264MimeSuffix(media::VideoCodecProfile profile, + uint8_t level) { + std::string profile_str; + switch (profile) { + case media::VideoCodecProfile::H264PROFILE_BASELINE: + profile_str = "42"; + break; + case media::VideoCodecProfile::H264PROFILE_MAIN: + profile_str = "4d"; + break; + case media::VideoCodecProfile::H264PROFILE_SCALABLEBASELINE: + profile_str = "53"; + break; + case media::VideoCodecProfile::H264PROFILE_SCALABLEHIGH: + profile_str = "56"; + break; + case media::VideoCodecProfile::H264PROFILE_EXTENDED: + profile_str = "58"; + break; + case media::VideoCodecProfile::H264PROFILE_HIGH: + profile_str = "64"; + break; + case media::VideoCodecProfile::H264PROFILE_HIGH10PROFILE: + profile_str = "6e"; + break; + case media::VideoCodecProfile::H264PROFILE_MULTIVIEWHIGH: + profile_str = "76"; + break; + case media::VideoCodecProfile::H264PROFILE_HIGH422PROFILE: + profile_str = "7a"; + break; + case media::VideoCodecProfile::H264PROFILE_STEREOHIGH: + profile_str = "80"; + break; + case media::VideoCodecProfile::H264PROFILE_HIGH444PREDICTIVEPROFILE: + profile_str = "f4"; + break; + default: + return ""; + } + + return base::StringPrintf(".%s%04x", profile_str.c_str(), level); +} + bool ParseNewStyleVp9CodecID(const std::string& codec_id, VideoCodecProfile* profile, uint8_t* level_idc, @@ -889,4 +934,46 @@ void ParseCodec(const std::string& codec_id, codec = kUnknownVideoCodec; } +VideoCodec VideoCodecProfileToVideoCodec(VideoCodecProfile profile) { + switch (profile) { + case VIDEO_CODEC_PROFILE_UNKNOWN: + return kUnknownVideoCodec; + case H264PROFILE_BASELINE: + case H264PROFILE_MAIN: + case H264PROFILE_EXTENDED: + case H264PROFILE_HIGH: + case H264PROFILE_HIGH10PROFILE: + case H264PROFILE_HIGH422PROFILE: + case H264PROFILE_HIGH444PREDICTIVEPROFILE: + case H264PROFILE_SCALABLEBASELINE: + case H264PROFILE_SCALABLEHIGH: + case H264PROFILE_STEREOHIGH: + case H264PROFILE_MULTIVIEWHIGH: + return kCodecH264; + case HEVCPROFILE_MAIN: + case HEVCPROFILE_MAIN10: + case HEVCPROFILE_MAIN_STILL_PICTURE: + return kCodecHEVC; + case VP8PROFILE_ANY: + return kCodecVP8; + case VP9PROFILE_PROFILE0: + case VP9PROFILE_PROFILE1: + case VP9PROFILE_PROFILE2: + case VP9PROFILE_PROFILE3: + return kCodecVP9; + case DOLBYVISION_PROFILE0: + case DOLBYVISION_PROFILE4: + case DOLBYVISION_PROFILE5: + case DOLBYVISION_PROFILE7: + case DOLBYVISION_PROFILE8: + case DOLBYVISION_PROFILE9: + return kCodecDolbyVision; + case THEORAPROFILE_ANY: + return kCodecTheora; + case AV1PROFILE_PROFILE_MAIN: + case AV1PROFILE_PROFILE_HIGH: + case AV1PROFILE_PROFILE_PRO: + return kCodecAV1; + } +} } // namespace media diff --git a/chromium/media/base/video_codecs.h b/chromium/media/base/video_codecs.h index a28472dcef5..0e7dce197d8 100644 --- a/chromium/media/base/video_codecs.h +++ b/chromium/media/base/video_codecs.h @@ -107,6 +107,8 @@ struct CodecProfileLevel { std::string MEDIA_EXPORT GetCodecName(VideoCodec codec); std::string MEDIA_EXPORT GetProfileName(VideoCodecProfile profile); +std::string MEDIA_EXPORT BuildH264MimeSuffix(VideoCodecProfile profile, + uint8_t level); // ParseNewStyleVp9CodecID handles parsing of new style vp9 codec IDs per // proposed VP Codec ISO Media File Format Binding specification: @@ -154,6 +156,9 @@ MEDIA_EXPORT void ParseCodec(const std::string& codec_id, VideoColorSpace& color_space); MEDIA_EXPORT VideoCodec StringToVideoCodec(const std::string& codec_id); +MEDIA_EXPORT VideoCodec +VideoCodecProfileToVideoCodec(VideoCodecProfile profile); + #if BUILDFLAG(ENABLE_MSE_MPEG2TS_STREAM_PARSER) // Translate legacy avc1 codec ids (like avc1.66.30 or avc1.77.31) into a new // style standard avc1 codec ids like avc1.4D002F. If the input codec is not diff --git a/chromium/media/base/video_decoder_config.cc b/chromium/media/base/video_decoder_config.cc index f59b7394a03..85cc6a64396 100644 --- a/chromium/media/base/video_decoder_config.cc +++ b/chromium/media/base/video_decoder_config.cc @@ -24,51 +24,6 @@ static bool IsValidSize(const gfx::Size& size) { size.height() <= limits::kMaxDimension; } -VideoCodec VideoCodecProfileToVideoCodec(VideoCodecProfile profile) { - switch (profile) { - case VIDEO_CODEC_PROFILE_UNKNOWN: - return kUnknownVideoCodec; - case H264PROFILE_BASELINE: - case H264PROFILE_MAIN: - case H264PROFILE_EXTENDED: - case H264PROFILE_HIGH: - case H264PROFILE_HIGH10PROFILE: - case H264PROFILE_HIGH422PROFILE: - case H264PROFILE_HIGH444PREDICTIVEPROFILE: - case H264PROFILE_SCALABLEBASELINE: - case H264PROFILE_SCALABLEHIGH: - case H264PROFILE_STEREOHIGH: - case H264PROFILE_MULTIVIEWHIGH: - return kCodecH264; - case HEVCPROFILE_MAIN: - case HEVCPROFILE_MAIN10: - case HEVCPROFILE_MAIN_STILL_PICTURE: - return kCodecHEVC; - case VP8PROFILE_ANY: - return kCodecVP8; - case VP9PROFILE_PROFILE0: - case VP9PROFILE_PROFILE1: - case VP9PROFILE_PROFILE2: - case VP9PROFILE_PROFILE3: - return kCodecVP9; - case DOLBYVISION_PROFILE0: - case DOLBYVISION_PROFILE4: - case DOLBYVISION_PROFILE5: - case DOLBYVISION_PROFILE7: - case DOLBYVISION_PROFILE8: - case DOLBYVISION_PROFILE9: - return kCodecDolbyVision; - case THEORAPROFILE_ANY: - return kCodecTheora; - case AV1PROFILE_PROFILE_MAIN: - case AV1PROFILE_PROFILE_HIGH: - case AV1PROFILE_PROFILE_PRO: - return kCodecAV1; - } - NOTREACHED(); - return kUnknownVideoCodec; -} - VideoDecoderConfig::VideoDecoderConfig() = default; VideoDecoderConfig::VideoDecoderConfig(VideoCodec codec, diff --git a/chromium/media/base/video_decoder_config.h b/chromium/media/base/video_decoder_config.h index 01ad01d48ca..5d04d524bad 100644 --- a/chromium/media/base/video_decoder_config.h +++ b/chromium/media/base/video_decoder_config.h @@ -20,13 +20,10 @@ #include "media/base/video_types.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/size.h" -#include "ui/gl/hdr_metadata.h" +#include "ui/gfx/hdr_metadata.h" namespace media { -MEDIA_EXPORT VideoCodec -VideoCodecProfileToVideoCodec(VideoCodecProfile profile); - // Describes the content of a video stream, as described by the media container // (or otherwise determined by the demuxer). class MEDIA_EXPORT VideoDecoderConfig { @@ -80,6 +77,7 @@ class MEDIA_EXPORT VideoDecoderConfig { VideoCodec codec() const { return codec_; } VideoCodecProfile profile() const { return profile_; } + void set_profile(VideoCodecProfile profile) { profile_ = profile; } AlphaMode alpha_mode() const { return alpha_mode_; } // Difference between encoded and display orientation. @@ -154,10 +152,10 @@ class MEDIA_EXPORT VideoDecoderConfig { const VideoColorSpace& color_space_info() const { return color_space_info_; } // Dynamic range of the image data. - void set_hdr_metadata(const gl::HDRMetadata& hdr_metadata) { + void set_hdr_metadata(const gfx::HDRMetadata& hdr_metadata) { hdr_metadata_ = hdr_metadata; } - const base::Optional<gl::HDRMetadata>& hdr_metadata() const { + const base::Optional<gfx::HDRMetadata>& hdr_metadata() const { return hdr_metadata_; } @@ -192,7 +190,7 @@ class MEDIA_EXPORT VideoDecoderConfig { EncryptionScheme encryption_scheme_ = EncryptionScheme::kUnencrypted; VideoColorSpace color_space_info_; - base::Optional<gl::HDRMetadata> hdr_metadata_; + base::Optional<gfx::HDRMetadata> hdr_metadata_; // Not using DISALLOW_COPY_AND_ASSIGN here intentionally to allow the compiler // generated copy constructor and assignment operator. Since the extra data is diff --git a/chromium/media/base/video_decoder_config_unittest.cc b/chromium/media/base/video_decoder_config_unittest.cc index 6c083a0da02..20929bc4036 100644 --- a/chromium/media/base/video_decoder_config_unittest.cc +++ b/chromium/media/base/video_decoder_config_unittest.cc @@ -91,4 +91,13 @@ TEST(VideoDecoderConfigTest, Invalid_AspectRatioDenominatorVeryLarge) { EXPECT_FALSE(config.IsValidConfig()); } +TEST(VideoDecoderConfigTest, SetProfile) { + VideoDecoderConfig config( + kCodecVP9, VP9PROFILE_PROFILE0, VideoDecoderConfig::AlphaMode::kIsOpaque, + VideoColorSpace(), kNoTransformation, kCodedSize, kVisibleRect, + kNaturalSize, EmptyExtraData(), EncryptionScheme::kUnencrypted); + config.set_profile(VP9PROFILE_PROFILE2); + EXPECT_EQ(config.profile(), VP9PROFILE_PROFILE2); +} + } // namespace media diff --git a/chromium/media/base/video_encoder.h b/chromium/media/base/video_encoder.h index 9b1badf5835..1513367c15c 100644 --- a/chromium/media/base/video_encoder.h +++ b/chromium/media/base/video_encoder.h @@ -39,10 +39,9 @@ class MEDIA_EXPORT VideoEncoder { Options(const Options&); ~Options(); base::Optional<uint64_t> bitrate; - double framerate = 30.0; + base::Optional<double> framerate; - int width = 0; - int height = 0; + gfx::Size frame_size; base::Optional<int> keyframe_interval = 10000; }; @@ -92,14 +91,16 @@ class MEDIA_EXPORT VideoEncoder { bool key_frame, StatusCB done_cb) = 0; - // Adjust encoder options for future frames, executing the - // |done_cb| upon completion. + // Adjust encoder options and the output callback for future frames, executing + // the |done_cb| upon completion. // // Note: // 1. Not all options can be changed on the fly. // 2. ChangeOptions() should be called after calling Flush() and waiting // for it to finish. - virtual void ChangeOptions(const Options& options, StatusCB done_cb) = 0; + virtual void ChangeOptions(const Options& options, + OutputCB output_cb, + StatusCB done_cb) = 0; // Requests all outputs for already encoded frames to be // produced via |output_cb| and calls |dene_cb| after that. diff --git a/chromium/media/base/video_frame.cc b/chromium/media/base/video_frame.cc index e889678706f..f3833229a48 100644 --- a/chromium/media/base/video_frame.cc +++ b/chromium/media/base/video_frame.cc @@ -606,6 +606,11 @@ scoped_refptr<VideoFrame> VideoFrame::WrapExternalGpuMemoryBuffer( return nullptr; } + const size_t num_planes = + NumberOfPlanesForLinearBufferFormat(gpu_memory_buffer->GetFormat()); + std::vector<ColorPlaneLayout> planes(num_planes); + for (size_t i = 0; i < num_planes; ++i) + planes[i].stride = gpu_memory_buffer->stride(i); uint64_t modifier = gfx::NativePixmapHandle::kNoModifier; #if defined(OS_LINUX) || defined(OS_CHROMEOS) if (gpu_memory_buffer->GetType() == gfx::NATIVE_PIXMAP) { @@ -615,17 +620,24 @@ scoped_refptr<VideoFrame> VideoFrame::WrapExternalGpuMemoryBuffer( DLOG(ERROR) << "Failed to clone the GpuMemoryBufferHandle"; return nullptr; } + if (gmb_handle.native_pixmap_handle.planes.size() != num_planes) { + DLOG(ERROR) << "Invalid number of planes=" + << gmb_handle.native_pixmap_handle.planes.size() + << ", expected num_planes=" << num_planes; + return nullptr; + } + for (size_t i = 0; i < num_planes; ++i) { + const auto& plane = gmb_handle.native_pixmap_handle.planes[i]; + planes[i].stride = plane.stride; + planes[i].offset = plane.offset; + planes[i].size = plane.size; + } modifier = gmb_handle.native_pixmap_handle.modifier; } #endif - const size_t num_planes = - NumberOfPlanesForLinearBufferFormat(gpu_memory_buffer->GetFormat()); - std::vector<int32_t> strides; - for (size_t i = 0; i < num_planes; ++i) - strides.push_back(gpu_memory_buffer->stride(i)); - const auto layout = VideoFrameLayout::CreateWithStrides( - *format, coded_size, std::move(strides), + const auto layout = VideoFrameLayout::CreateWithPlanes( + *format, coded_size, std::move(planes), VideoFrameLayout::kBufferAddressAlignment, modifier); if (!layout) { DLOG(ERROR) << __func__ << " Invalid layout"; @@ -689,7 +701,7 @@ scoped_refptr<VideoFrame> VideoFrame::WrapExternalDmabufs( #if defined(OS_MAC) // static -scoped_refptr<VideoFrame> VideoFrame::WrapIOSurface( +scoped_refptr<VideoFrame> VideoFrame::WrapUnacceleratedIOSurface( gfx::GpuMemoryBufferHandle handle, const gfx::Rect& visible_rect, base::TimeDelta timestamp) { @@ -697,8 +709,7 @@ scoped_refptr<VideoFrame> VideoFrame::WrapIOSurface( DLOG(ERROR) << "Non-IOSurface handle."; return nullptr; } - base::ScopedCFTypeRef<IOSurfaceRef> io_surface = - gfx::IOSurfaceMachPortToIOSurface(std::move(handle.mach_port)); + gfx::ScopedIOSurface io_surface = handle.io_surface; if (!io_surface) { return nullptr; } @@ -1102,12 +1113,9 @@ bool VideoFrame::IsMappable() const { bool VideoFrame::HasTextures() const { // A SharedImage can be turned into a texture, and so it counts as a texture // in the context of this call. - if (mailbox_holders_[0].mailbox.IsSharedImage()) - return true; - - DCHECK(!wrapped_frame_ || !wrapped_frame_->HasTextures()); return wrapped_frame_ ? wrapped_frame_->HasTextures() - : !mailbox_holders_[0].mailbox.IsZero(); + : (mailbox_holders_[0].mailbox.IsSharedImage() || + !mailbox_holders_[0].mailbox.IsZero()); } size_t VideoFrame::NumTextures() const { @@ -1299,12 +1307,6 @@ VideoFrame::~VideoFrame() { std::move(mailbox_holders_release_cb_).Run(release_sync_token); } - // Someone might be monitoring original wrapped frame for feedback. - // Ensure all accumulated feedback is propagated to the original frame. - if (wrapped_frame_) { - wrapped_frame_->feedback()->Combine(feedback_); - } - for (auto& callback : done_callbacks_) std::move(callback).Run(); } diff --git a/chromium/media/base/video_frame.h b/chromium/media/base/video_frame.h index e31d70dfe0f..4185e3ce506 100644 --- a/chromium/media/base/video_frame.h +++ b/chromium/media/base/video_frame.h @@ -27,14 +27,13 @@ #include "build/build_config.h" #include "gpu/command_buffer/common/mailbox_holder.h" #include "gpu/ipc/common/vulkan_ycbcr_info.h" -#include "media/base/video_frame_feedback.h" #include "media/base/video_frame_layout.h" #include "media/base/video_frame_metadata.h" #include "media/base/video_types.h" #include "ui/gfx/color_space.h" #include "ui/gfx/geometry/rect.h" #include "ui/gfx/geometry/size.h" -#include "ui/gl/hdr_metadata.h" +#include "ui/gfx/hdr_metadata.h" #if defined(OS_MAC) #include <CoreVideo/CVPixelBuffer.h> @@ -293,8 +292,11 @@ class MEDIA_EXPORT VideoFrame : public base::RefCountedThreadSafe<VideoFrame> { base::TimeDelta timestamp); // Wraps a provided IOSurface with a VideoFrame. The IOSurface is retained - // and locked for the lifetime of the VideoFrame. - static scoped_refptr<VideoFrame> WrapIOSurface( + // and locked for the lifetime of the VideoFrame. This is for unaccelerated + // (CPU-only) access to the IOSurface, and is not efficient. It is the path + // that video capture uses when hardware acceleration is disabled. + // https://crbug.com/1125879 + static scoped_refptr<VideoFrame> WrapUnacceleratedIOSurface( gfx::GpuMemoryBufferHandle handle, const gfx::Rect& visible_rect, base::TimeDelta timestamp); @@ -440,11 +442,11 @@ class MEDIA_EXPORT VideoFrame : public base::RefCountedThreadSafe<VideoFrame> { color_space_ = color_space; } - const base::Optional<gl::HDRMetadata>& hdr_metadata() const { + const base::Optional<gfx::HDRMetadata>& hdr_metadata() const { return hdr_metadata_; } - void set_hdr_metadata(const base::Optional<gl::HDRMetadata>& hdr_metadata) { + void set_hdr_metadata(const base::Optional<gfx::HDRMetadata>& hdr_metadata) { hdr_metadata_ = hdr_metadata; } @@ -568,9 +570,6 @@ class MEDIA_EXPORT VideoFrame : public base::RefCountedThreadSafe<VideoFrame> { // Resets |metadata_|. void clear_metadata() { set_metadata(VideoFrameMetadata()); } - const VideoFrameFeedback* feedback() const { return &feedback_; } - VideoFrameFeedback* feedback() { return &feedback_; } - // The time span between the current frame and the first frame of the stream. // This is the media timestamp, and not the reference time. // See VideoFrameMetadata::REFERENCE_TIME for details. @@ -724,13 +723,11 @@ class MEDIA_EXPORT VideoFrame : public base::RefCountedThreadSafe<VideoFrame> { VideoFrameMetadata metadata_; - VideoFrameFeedback feedback_; - // Generated at construction time. const int unique_id_; gfx::ColorSpace color_space_; - base::Optional<gl::HDRMetadata> hdr_metadata_; + base::Optional<gfx::HDRMetadata> hdr_metadata_; // Sampler conversion information which is used in vulkan context for android. base::Optional<gpu::VulkanYCbCrInfo> ycbcr_info_; diff --git a/chromium/media/base/video_frame_feedback.h b/chromium/media/base/video_frame_feedback.h index efb89f5034a..3e64b3fded9 100644 --- a/chromium/media/base/video_frame_feedback.h +++ b/chromium/media/base/video_frame_feedback.h @@ -7,10 +7,16 @@ #include <limits> +#include "base/callback.h" #include "media/base/media_export.h" namespace media { +struct VideoFrameFeedback; + +using VideoCaptureFeedbackCB = + base::RepeatingCallback<void(const VideoFrameFeedback&)>; + // Feedback from the frames consumer. // This class is passed from the frames sink to the capturer to limit // incoming video feed frame-rate and/or resolution. diff --git a/chromium/media/base/video_frame_metadata.cc b/chromium/media/base/video_frame_metadata.cc index 584bdf6bc43..6cd1c5dcfb0 100644 --- a/chromium/media/base/video_frame_metadata.cc +++ b/chromium/media/base/video_frame_metadata.cc @@ -56,6 +56,7 @@ void VideoFrameMetadata::MergeMetadataFrom( MERGE_FIELD(rtp_timestamp, metadata_source); MERGE_FIELD(receive_time, metadata_source); MERGE_FIELD(wallclock_frame_duration, metadata_source); + MERGE_FIELD(maximum_composition_delay_in_frames, metadata_source); } } // namespace media diff --git a/chromium/media/base/video_frame_metadata.h b/chromium/media/base/video_frame_metadata.h index eed8b133a9b..ded4b13adf6 100644 --- a/chromium/media/base/video_frame_metadata.h +++ b/chromium/media/base/video_frame_metadata.h @@ -178,6 +178,13 @@ struct MEDIA_EXPORT VideoFrameMetadata { // expected to spend on the screen during playback. Unlike FRAME_DURATION // this field takes into account current playback rate. base::Optional<base::TimeDelta> wallclock_frame_duration; + + // WebRTC streams only: if present, this field represents the maximum + // composition delay that is allowed for this frame. This is respected + // in a best effort manner. + // This is an experimental feature, see crbug.com/1138888 for more + // information. + base::Optional<int> maximum_composition_delay_in_frames; }; } // namespace media diff --git a/chromium/media/base/video_frame_unittest.cc b/chromium/media/base/video_frame_unittest.cc index da2f4a9120f..30f2bbc64e0 100644 --- a/chromium/media/base/video_frame_unittest.cc +++ b/chromium/media/base/video_frame_unittest.cc @@ -9,7 +9,6 @@ #include <memory> #include "base/bind.h" -#include "base/bind_helpers.h" #include "base/callback_helpers.h" #include "base/format_macros.h" #include "base/memory/aligned_memory.h" diff --git a/chromium/media/base/video_thumbnail_decoder.cc b/chromium/media/base/video_thumbnail_decoder.cc index e1ba856efe0..ab3033cc166 100644 --- a/chromium/media/base/video_thumbnail_decoder.cc +++ b/chromium/media/base/video_thumbnail_decoder.cc @@ -5,7 +5,7 @@ #include "media/base/video_thumbnail_decoder.h" #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "media/base/decoder_buffer.h" #include "media/base/video_frame.h" diff --git a/chromium/media/base/video_thumbnail_decoder_unittest.cc b/chromium/media/base/video_thumbnail_decoder_unittest.cc index 93e343345b9..10aa6e34f6b 100644 --- a/chromium/media/base/video_thumbnail_decoder_unittest.cc +++ b/chromium/media/base/video_thumbnail_decoder_unittest.cc @@ -6,7 +6,7 @@ #include <vector> #include "base/bind.h" -#include "base/bind_helpers.h" +#include "base/callback_helpers.h" #include "base/run_loop.h" #include "base/test/gmock_callback_support.h" #include "base/test/task_environment.h" diff --git a/chromium/media/base/win/BUILD.gn b/chromium/media/base/win/BUILD.gn index b3b33bd42d2..b4a7cb764a1 100644 --- a/chromium/media/base/win/BUILD.gn +++ b/chromium/media/base/win/BUILD.gn @@ -2,13 +2,6 @@ # Use of this source code is governed by a BSD-style license that can be # found in the LICENSE file. -# This file depends on the legacy global sources assignment filter. It should -# be converted to check target platform before assigning source files to the -# sources variable. Remove this import and set_sources_assignment_filter call -# when the file has been converted. See https://crbug.com/1018739 for details. -import("//build/config/deprecated_default_sources_assignment_filter.gni") -set_sources_assignment_filter(deprecated_default_sources_assignment_filter) - assert(is_win) config("delay_load_mf") { @@ -21,7 +14,6 @@ config("delay_load_mf") { component("media_foundation_util") { defines = [ "MF_INITIALIZER_IMPLEMENTATION" ] - set_sources_assignment_filter([]) sources = [ "mf_helpers.cc", "mf_helpers.h", @@ -29,7 +21,6 @@ component("media_foundation_util") { "mf_initializer.h", "mf_initializer_export.h", ] - set_sources_assignment_filter(deprecated_default_sources_assignment_filter) configs += [ # TODO(crbug.com/167187): Fix size_t to int truncations. "//build/config/compiler:no_size_t_to_int_warning", diff --git a/chromium/media/base/win/d3d11_mocks.cc b/chromium/media/base/win/d3d11_mocks.cc index 8d41b19a940..41853a4fa24 100644 --- a/chromium/media/base/win/d3d11_mocks.cc +++ b/chromium/media/base/win/d3d11_mocks.cc @@ -50,4 +50,7 @@ D3D11VideoProcessorEnumeratorMock::~D3D11VideoProcessorEnumeratorMock() = D3D11DeviceContextMock::D3D11DeviceContextMock() = default; D3D11DeviceContextMock::~D3D11DeviceContextMock() = default; +D3D11FenceMock::D3D11FenceMock() = default; +D3D11FenceMock::~D3D11FenceMock() = default; + } // namespace media
\ No newline at end of file diff --git a/chromium/media/base/win/d3d11_mocks.h b/chromium/media/base/win/d3d11_mocks.h index 71314f08199..d2ad6b8b426 100644 --- a/chromium/media/base/win/d3d11_mocks.h +++ b/chromium/media/base/win/d3d11_mocks.h @@ -5,8 +5,7 @@ #ifndef MEDIA_BASE_WIN_D3D11_MOCKS_H_ #define MEDIA_BASE_WIN_D3D11_MOCKS_H_ -#include <d3d11.h> -#include <d3d11_1.h> +#include <d3d11_4.h> #include <dxgi1_4.h> #include <dxgi1_6.h> #include <wrl/client.h> @@ -58,7 +57,7 @@ class D3D11BufferMock class D3D11DeviceMock : public Microsoft::WRL::RuntimeClass< Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>, - ID3D11Device> { + ID3D11Device5> { public: D3D11DeviceMock(); ~D3D11DeviceMock() override; @@ -211,6 +210,108 @@ class D3D11DeviceMock MOCK_STDCALL_METHOD1(SetExceptionMode, HRESULT(UINT)); MOCK_STDCALL_METHOD0(GetExceptionMode, UINT()); + + // ID3D11Device1 + MOCK_STDCALL_METHOD1(GetImmediateContext1, void(ID3D11DeviceContext1**)); + + MOCK_STDCALL_METHOD2(CreateDeferredContext1, + HRESULT(UINT, ID3D11DeviceContext1**)); + + MOCK_STDCALL_METHOD2(CreateBlendState1, + HRESULT(const D3D11_BLEND_DESC1*, ID3D11BlendState1**)); + + MOCK_STDCALL_METHOD2(CreateRasterizerState1, + HRESULT(const D3D11_RASTERIZER_DESC1*, + ID3D11RasterizerState1**)); + + MOCK_STDCALL_METHOD7(CreateDeviceContextState, + HRESULT(UINT, + const D3D_FEATURE_LEVEL*, + UINT, + UINT, + REFIID, + D3D_FEATURE_LEVEL*, + ID3DDeviceContextState**)); + + MOCK_STDCALL_METHOD3(OpenSharedResource1, HRESULT(HANDLE, REFIID, void**)); + + MOCK_STDCALL_METHOD4(OpenSharedResourceByName, + HRESULT(LPCWSTR, DWORD, REFIID, void**)); + + // ID3D11Device2 + MOCK_STDCALL_METHOD4(CheckMultisampleQualityLevels1, + HRESULT(DXGI_FORMAT, UINT, UINT, UINT*)); + + MOCK_STDCALL_METHOD2(CreateDeferredContext2, + HRESULT(UINT, ID3D11DeviceContext2**)); + + MOCK_STDCALL_METHOD1(GetImmediateContext2, void(ID3D11DeviceContext2**)); + + MOCK_STDCALL_METHOD7(GetResourceTiling, + void(ID3D11Resource*, + UINT*, + D3D11_PACKED_MIP_DESC*, + D3D11_TILE_SHAPE*, + UINT*, + UINT, + D3D11_SUBRESOURCE_TILING*)); + + // ID3D11Device3 + MOCK_STDCALL_METHOD3(CreateTexture2D1, + HRESULT(const D3D11_TEXTURE2D_DESC1*, + const D3D11_SUBRESOURCE_DATA*, + ID3D11Texture2D1**)); + + MOCK_STDCALL_METHOD3(CreateTexture3D1, + HRESULT(const D3D11_TEXTURE3D_DESC1*, + const D3D11_SUBRESOURCE_DATA*, + ID3D11Texture3D1**)); + + MOCK_STDCALL_METHOD2(CreateRasterizerState2, + HRESULT(const D3D11_RASTERIZER_DESC2*, + ID3D11RasterizerState2**)); + + MOCK_STDCALL_METHOD3(CreateShaderResourceView1, + HRESULT(ID3D11Resource*, + const D3D11_SHADER_RESOURCE_VIEW_DESC1*, + ID3D11ShaderResourceView1**)); + + MOCK_STDCALL_METHOD3(CreateUnorderedAccessView1, + HRESULT(ID3D11Resource*, + const D3D11_UNORDERED_ACCESS_VIEW_DESC1*, + ID3D11UnorderedAccessView1**)); + + MOCK_STDCALL_METHOD3(CreateRenderTargetView1, + HRESULT(ID3D11Resource*, + const D3D11_RENDER_TARGET_VIEW_DESC1*, + ID3D11RenderTargetView1**)); + + MOCK_STDCALL_METHOD2(CreateQuery1, + HRESULT(const D3D11_QUERY_DESC1*, ID3D11Query1**)); + + MOCK_STDCALL_METHOD1(GetImmediateContext3, void(ID3D11DeviceContext3**)); + + MOCK_STDCALL_METHOD2(CreateDeferredContext3, + HRESULT(UINT, ID3D11DeviceContext3**)); + + MOCK_STDCALL_METHOD6( + WriteToSubresource, + void(ID3D11Resource*, UINT, const D3D11_BOX*, const void*, UINT, UINT)); + + MOCK_STDCALL_METHOD6( + ReadFromSubresource, + void(void*, UINT, UINT, ID3D11Resource*, UINT, const D3D11_BOX*)); + + // ID3D11Device4 + MOCK_STDCALL_METHOD2(RegisterDeviceRemovedEvent, HRESULT(HANDLE, DWORD*)); + + MOCK_STDCALL_METHOD1(UnregisterDeviceRemoved, void(DWORD)); + + // ID3D11Device5 + MOCK_STDCALL_METHOD3(OpenSharedFence, HRESULT(HANDLE, REFIID, void**)); + + MOCK_STDCALL_METHOD4(CreateFence, + HRESULT(UINT64, D3D11_FENCE_FLAG, REFIID, void**)); }; class DXGIFactoryMock @@ -773,7 +874,7 @@ class D3D11VideoDecoderMock class D3D11DeviceContextMock : public Microsoft::WRL::RuntimeClass< Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>, - ID3D11DeviceContext> { + ID3D11DeviceContext4> { public: D3D11DeviceContextMock(); ~D3D11DeviceContextMock() override; @@ -1299,6 +1400,167 @@ class D3D11DeviceContextMock MOCK_STDCALL_METHOD2(FinishCommandList, HRESULT(BOOL RestoreDeferredContextState, ID3D11CommandList** ppCommandList)); + + // ID3D11DeviceContext1 + MOCK_STDCALL_METHOD9(CopySubresourceRegion1, + void(ID3D11Resource*, + UINT, + UINT, + UINT, + UINT, + ID3D11Resource*, + UINT, + const D3D11_BOX*, + UINT)); + + MOCK_STDCALL_METHOD7(UpdateSubresource1, + void(ID3D11Resource*, + UINT, + const D3D11_BOX*, + const void*, + UINT, + UINT, + UINT)); + + MOCK_STDCALL_METHOD1(DiscardResource, void(ID3D11Resource*)); + + MOCK_STDCALL_METHOD1(DiscardView, void(ID3D11View*)); + + MOCK_STDCALL_METHOD5( + VSSetConstantBuffers1, + void(UINT, UINT, ID3D11Buffer* const*, const UINT*, const UINT*)); + + MOCK_STDCALL_METHOD5( + HSSetConstantBuffers1, + void(UINT, UINT, ID3D11Buffer* const*, const UINT*, const UINT*)); + + MOCK_STDCALL_METHOD5( + DSSetConstantBuffers1, + void(UINT, UINT, ID3D11Buffer* const*, const UINT*, const UINT*)); + + MOCK_STDCALL_METHOD5( + GSSetConstantBuffers1, + void(UINT, UINT, ID3D11Buffer* const*, const UINT*, const UINT*)); + + MOCK_STDCALL_METHOD5( + PSSetConstantBuffers1, + void(UINT, UINT, ID3D11Buffer* const*, const UINT*, const UINT*)); + + MOCK_STDCALL_METHOD5( + CSSetConstantBuffers1, + void(UINT, UINT, ID3D11Buffer* const*, const UINT*, const UINT*)); + + MOCK_STDCALL_METHOD5(VSGetConstantBuffers1, + void(UINT, UINT, ID3D11Buffer**, UINT*, UINT*)); + + MOCK_STDCALL_METHOD5(HSGetConstantBuffers1, + void(UINT, UINT, ID3D11Buffer**, UINT*, UINT*)); + + MOCK_STDCALL_METHOD5(DSGetConstantBuffers1, + void(UINT, UINT, ID3D11Buffer**, UINT*, UINT*)); + + MOCK_STDCALL_METHOD5(GSGetConstantBuffers1, + void(UINT, UINT, ID3D11Buffer**, UINT*, UINT*)); + + MOCK_STDCALL_METHOD5(PSGetConstantBuffers1, + void(UINT, UINT, ID3D11Buffer**, UINT*, UINT*)); + + MOCK_STDCALL_METHOD5(CSGetConstantBuffers1, + void(UINT, UINT, ID3D11Buffer**, UINT*, UINT*)); + + MOCK_STDCALL_METHOD2(SwapDeviceContextState, + void(ID3DDeviceContextState*, ID3DDeviceContextState**)); + + MOCK_STDCALL_METHOD4( + ClearView, + void(ID3D11View*, const FLOAT[4], const D3D11_RECT*, UINT)); + + MOCK_STDCALL_METHOD3(DiscardView1, + void(ID3D11View*, const D3D11_RECT*, UINT)); + + // ID3D11DeviceContext2 + MOCK_STDCALL_METHOD10(UpdateTileMappings, + HRESULT(ID3D11Resource*, + UINT, + const D3D11_TILED_RESOURCE_COORDINATE*, + const D3D11_TILE_REGION_SIZE*, + ID3D11Buffer*, + UINT, + const UINT*, + const UINT*, + const UINT*, + UINT)); + + MOCK_STDCALL_METHOD6(CopyTileMappings, + HRESULT(ID3D11Resource*, + const D3D11_TILED_RESOURCE_COORDINATE*, + ID3D11Resource*, + const D3D11_TILED_RESOURCE_COORDINATE*, + const D3D11_TILE_REGION_SIZE*, + UINT)); + + MOCK_STDCALL_METHOD6(CopyTiles, + void(ID3D11Resource*, + const D3D11_TILED_RESOURCE_COORDINATE*, + const D3D11_TILE_REGION_SIZE*, + ID3D11Buffer*, + UINT64, + UINT)); + + MOCK_STDCALL_METHOD5(UpdateTiles, + void(ID3D11Resource*, + const D3D11_TILED_RESOURCE_COORDINATE*, + const D3D11_TILE_REGION_SIZE*, + const void*, + UINT)); + + MOCK_STDCALL_METHOD2(ResizeTilePool, HRESULT(ID3D11Buffer*, UINT64)); + + MOCK_STDCALL_METHOD2(TiledResourceBarrier, + void(ID3D11DeviceChild*, ID3D11DeviceChild*)); + + MOCK_STDCALL_METHOD0(IsAnnotationEnabled, BOOL()); + + MOCK_STDCALL_METHOD2(SetMarkerInt, void(LPCWSTR, INT)); + + MOCK_STDCALL_METHOD2(BeginEventInt, void(LPCWSTR, INT)); + + MOCK_STDCALL_METHOD0(EndEvent, void()); + + // ID3D11DeviceContext3 + MOCK_STDCALL_METHOD2(Flush1, void(D3D11_CONTEXT_TYPE, HANDLE)); + + MOCK_STDCALL_METHOD1(SetHardwareProtectionState, void(BOOL)); + + MOCK_STDCALL_METHOD1(GetHardwareProtectionState, void(BOOL*)); + + // ID3D11DeviceContext4 + MOCK_STDCALL_METHOD2(Signal, HRESULT(ID3D11Fence*, UINT64)); + + MOCK_STDCALL_METHOD2(Wait, HRESULT(ID3D11Fence*, UINT64)); +}; + +class D3D11FenceMock + : public Microsoft::WRL::RuntimeClass< + Microsoft::WRL::RuntimeClassFlags<Microsoft::WRL::ClassicCom>, + ID3D11Fence> { + public: + D3D11FenceMock(); + ~D3D11FenceMock() override; + + MOCK_STDCALL_METHOD1(GetDevice, void(ID3D11Device**)); + MOCK_STDCALL_METHOD3(GetPrivateData, HRESULT(const GUID&, UINT*, void*)); + MOCK_STDCALL_METHOD3(SetPrivateData, HRESULT(const GUID&, UINT, const void*)); + MOCK_STDCALL_METHOD2(SetPrivateDataInterface, + HRESULT(const GUID&, const IUnknown*)); + + MOCK_STDCALL_METHOD4( + CreateSharedHandle, + HRESULT(const SECURITY_ATTRIBUTES*, DWORD, LPCWSTR, HANDLE*)); + + MOCK_STDCALL_METHOD0(GetCompletedValue, UINT64()); + + MOCK_STDCALL_METHOD2(SetEventOnCompletion, HRESULT(UINT64, HANDLE)); }; } // namespace media diff --git a/chromium/media/base/win/test_utils.h b/chromium/media/base/win/test_utils.h index 9af55425019..8c7243af34a 100644 --- a/chromium/media/base/win/test_utils.h +++ b/chromium/media/base/win/test_utils.h @@ -43,6 +43,9 @@ #define MOCK_STDCALL_METHOD9(Name, Types) \ MOCK_METHOD9_WITH_CALLTYPE(STDMETHODCALLTYPE, Name, Types) +#define MOCK_STDCALL_METHOD10(Name, Types) \ + MOCK_METHOD10_WITH_CALLTYPE(STDMETHODCALLTYPE, Name, Types) + // Helper ON_CALL and EXPECT_CALL for Microsoft::WRL::ComPtr, e.g. // COM_EXPECT_CALL(foo_, Bar()); // where |foo_| is ComPtr<D3D11FooMock>. |