diff options
Diffstat (limited to 'chromium/media/webcodecs')
-rw-r--r-- | chromium/media/webcodecs/BUILD.gn | 39 | ||||
-rw-r--r-- | chromium/media/webcodecs/wc_decoder_selector.cc | 142 | ||||
-rw-r--r-- | chromium/media/webcodecs/wc_decoder_selector.h | 83 | ||||
-rw-r--r-- | chromium/media/webcodecs/wc_decoder_selector_unittest.cc | 240 |
4 files changed, 0 insertions, 504 deletions
diff --git a/chromium/media/webcodecs/BUILD.gn b/chromium/media/webcodecs/BUILD.gn deleted file mode 100644 index 325aa27053d..00000000000 --- a/chromium/media/webcodecs/BUILD.gn +++ /dev/null @@ -1,39 +0,0 @@ -# Copyright 2020 The Chromium Authors. All rights reserved. -# Use of this source code is governed by a BSD-style license that can be -# found in the LICENSE file. - -import("//testing/test.gni") - -source_set("webcodecs") { - # Do not expand the visibility here without double-checking with OWNERS, this - # is a roll-up target which is part of the //media component. Most other DEPs - # should be using //media and not directly DEP this roll-up target. - visibility = [ "//media" ] - - sources = [ - "wc_decoder_selector.cc", - "wc_decoder_selector.h", - ] - - public_deps = [ - "//base", - "//media/base", - "//media/filters", - ] - - deps = [] - - configs += [ "//media:subcomponent_config" ] -} - -source_set("unit_tests") { - testonly = true - sources = [ "wc_decoder_selector_unittest.cc" ] - - deps = [ - "//base/test:test_support", - "//media:test_support", - "//testing/gmock", - "//testing/gtest", - ] -} diff --git a/chromium/media/webcodecs/wc_decoder_selector.cc b/chromium/media/webcodecs/wc_decoder_selector.cc deleted file mode 100644 index 73b927dc4cc..00000000000 --- a/chromium/media/webcodecs/wc_decoder_selector.cc +++ /dev/null @@ -1,142 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "media/webcodecs/wc_decoder_selector.h" - -#include "base/bind.h" -#include "base/check_op.h" -#include "base/notreached.h" -#include "base/single_thread_task_runner.h" -#include "media/base/channel_layout.h" -#include "media/base/demuxer_stream.h" -#include "media/filters/decrypting_demuxer_stream.h" - -namespace media { - -// Demuxing isn't part of WebCodecs. This shim allows us to reuse decoder -// selection logic from <video>. -// TODO(chcunningham): Maybe refactor DecoderSelector to separate dependency on -// DemuxerStream. DecoderSelection doesn't conceptually require a Demuxer. The -// tough part is re-working DecryptingDemuxerStream. -template <DemuxerStream::Type StreamType> -class ShimDemuxerStream : public DemuxerStream { - public: - using DecoderConfigType = - typename DecoderStreamTraits<StreamType>::DecoderConfigType; - - ~ShimDemuxerStream() override = default; - - void Read(ReadCB read_cb) override { NOTREACHED(); } - bool IsReadPending() const override { - NOTREACHED(); - return false; - } - - void Configure(DecoderConfigType config); - - AudioDecoderConfig audio_decoder_config() override { - DCHECK_EQ(type(), DemuxerStream::AUDIO); - return audio_decoder_config_; - } - - VideoDecoderConfig video_decoder_config() override { - DCHECK_EQ(type(), DemuxerStream::VIDEO); - return video_decoder_config_; - } - - Type type() const override { return stream_type; } - - bool SupportsConfigChanges() override { - NOTREACHED(); - return true; - } - - private: - static const DemuxerStream::Type stream_type = StreamType; - - AudioDecoderConfig audio_decoder_config_; - VideoDecoderConfig video_decoder_config_; -}; - -template <> -void ShimDemuxerStream<DemuxerStream::AUDIO>::Configure( - DecoderConfigType config) { - audio_decoder_config_ = config; -} - -template <> -void ShimDemuxerStream<DemuxerStream::VIDEO>::Configure( - DecoderConfigType config) { - video_decoder_config_ = config; -} - -template <DemuxerStream::Type StreamType> -WebCodecsDecoderSelector<StreamType>::WebCodecsDecoderSelector( - scoped_refptr<base::SingleThreadTaskRunner> task_runner, - CreateDecodersCB create_decoders_cb, - typename Decoder::OutputCB output_cb) - : impl_(std::move(task_runner), - std::move(create_decoders_cb), - &null_media_log_), - demuxer_stream_(new ShimDemuxerStream<StreamType>()), - stream_traits_(CreateStreamTraits()), - output_cb_(output_cb) { - impl_.Initialize(stream_traits_.get(), demuxer_stream_.get(), - nullptr /*CdmContext*/, WaitingCB()); -} - -template <DemuxerStream::Type StreamType> -WebCodecsDecoderSelector<StreamType>::~WebCodecsDecoderSelector() {} - -template <DemuxerStream::Type StreamType> -void WebCodecsDecoderSelector<StreamType>::SelectDecoder( - const DecoderConfig& config, - SelectDecoderCB select_decoder_cb) { - // |impl_| will internally use this the |config| from our ShimDemuxerStream. - demuxer_stream_->Configure(config); - - // |impl_| uses a WeakFactory for its SelectDecoderCB, so we're safe to use - // Unretained here. - impl_.SelectDecoder( - base::BindOnce(&WebCodecsDecoderSelector<StreamType>::OnDecoderSelected, - base::Unretained(this), std::move(select_decoder_cb)), - output_cb_); -} - -template <> -std::unique_ptr<WebCodecsAudioDecoderSelector::StreamTraits> -WebCodecsDecoderSelector<DemuxerStream::AUDIO>::CreateStreamTraits() { - // TODO(chcunningham): Consider plumbing real hw channel layout. - return std::make_unique<WebCodecsDecoderSelector::StreamTraits>( - &null_media_log_, CHANNEL_LAYOUT_NONE); -} - -template <> -std::unique_ptr<WebCodecsVideoDecoderSelector::StreamTraits> -WebCodecsDecoderSelector<DemuxerStream::VIDEO>::CreateStreamTraits() { - return std::make_unique<WebCodecsDecoderSelector::StreamTraits>( - &null_media_log_); -} - -template <DemuxerStream::Type StreamType> -void WebCodecsDecoderSelector<StreamType>::OnDecoderSelected( - SelectDecoderCB select_decoder_cb, - std::unique_ptr<Decoder> decoder, - std::unique_ptr<DecryptingDemuxerStream> decrypting_demuxer_stream) { - DCHECK(!decrypting_demuxer_stream); - - // We immediately finalize decoder selection. From a spec POV we strongly - // prefer to avoid replicating our internal design of having to wait for the - // first frame to arrive before we consider configuration successful. - // TODO(chcunningham): Measure first frame decode failures and find other ways - // to solve (or minimize) the problem. - impl_.FinalizeDecoderSelection(); - - std::move(select_decoder_cb).Run(std::move(decoder)); -} - -template class WebCodecsDecoderSelector<DemuxerStream::VIDEO>; -template class WebCodecsDecoderSelector<DemuxerStream::AUDIO>; - -} // namespace media diff --git a/chromium/media/webcodecs/wc_decoder_selector.h b/chromium/media/webcodecs/wc_decoder_selector.h deleted file mode 100644 index 207350f1a94..00000000000 --- a/chromium/media/webcodecs/wc_decoder_selector.h +++ /dev/null @@ -1,83 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef MEDIA_WEBCODECS_WC_DECODER_SELECTOR_H_ -#define MEDIA_WEBCODECS_WC_DECODER_SELECTOR_H_ - -#include <memory> - -#include "media/base/demuxer_stream.h" -#include "media/base/media_export.h" -#include "media/base/media_util.h" -#include "media/filters/decoder_selector.h" -#include "media/filters/decoder_stream_traits.h" - -namespace media { - -template <DemuxerStream::Type StreamType> -class ShimDemuxerStream; - -template <DemuxerStream::Type StreamType> -class MEDIA_EXPORT WebCodecsDecoderSelector { - public: - typedef DecoderStreamTraits<StreamType> StreamTraits; - typedef typename StreamTraits::DecoderType Decoder; - typedef typename StreamTraits::DecoderConfigType DecoderConfig; - - // Callback to create a list of decoders to select from. - using CreateDecodersCB = - base::RepeatingCallback<std::vector<std::unique_ptr<Decoder>>()>; - - // Emits the result of a single call to SelectDecoder(). Parameter is - // the initialized Decoder. nullptr if selection failed. The caller owns the - // Decoder. - using SelectDecoderCB = base::OnceCallback<void(std::unique_ptr<Decoder>)>; - - WebCodecsDecoderSelector( - scoped_refptr<base::SingleThreadTaskRunner> task_runner, - CreateDecodersCB create_decoders_cb, - typename Decoder::OutputCB output_cb); - - // Aborts any pending decoder selection. - ~WebCodecsDecoderSelector(); - - // Selects and initializes a decoder using |config|. Decoder will - // be returned via |select_decoder_cb| posted to |task_runner_|. Subsequent - // calls will again select from the full list of decoders. - void SelectDecoder(const DecoderConfig& config, - SelectDecoderCB select_decoder_cb); - - private: - // Helper to create |stream_traits_|. - std::unique_ptr<StreamTraits> CreateStreamTraits(); - - // Proxy SelectDecoderCB from impl_ to our |select_decoder_cb|. - void OnDecoderSelected(SelectDecoderCB select_decoder_cb, - std::unique_ptr<Decoder> decoder, - std::unique_ptr<DecryptingDemuxerStream>); - - // Implements heavy lifting for decoder selection. - DecoderSelector<StreamType> impl_; - - // Shim to satisfy dependencies of |impl_|. Provides DecoderConfig to |impl_|. - std::unique_ptr<ShimDemuxerStream<StreamType>> demuxer_stream_; - - // Helper to unify API for configuring audio/video decoders. - std::unique_ptr<StreamTraits> stream_traits_; - - // Repeating callback for decoder outputs. - typename Decoder::OutputCB output_cb_; - - // TODO(chcunningham): Route MEDIA_LOG for WebCodecs. - NullMediaLog null_media_log_; -}; - -typedef WebCodecsDecoderSelector<DemuxerStream::VIDEO> - WebCodecsVideoDecoderSelector; -typedef WebCodecsDecoderSelector<DemuxerStream::AUDIO> - WebCodecsAudioDecoderSelector; - -} // namespace media - -#endif // MEDIA_WEBCODECS_WC_DECODER_SELECTOR_H_ diff --git a/chromium/media/webcodecs/wc_decoder_selector_unittest.cc b/chromium/media/webcodecs/wc_decoder_selector_unittest.cc deleted file mode 100644 index a14258468ee..00000000000 --- a/chromium/media/webcodecs/wc_decoder_selector_unittest.cc +++ /dev/null @@ -1,240 +0,0 @@ -// Copyright 2020 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include <vector> - -#include "base/test/task_environment.h" -#include "media/base/demuxer_stream.h" -#include "media/base/media_util.h" -#include "media/base/mock_filters.h" -#include "media/base/status.h" -#include "media/base/test_helpers.h" -#include "media/base/video_decoder.h" -#include "media/filters/decoder_stream.h" -#include "testing/gmock/include/gmock/gmock.h" -#include "testing/gtest/include/gtest/gtest.h" - -#include "media/webcodecs/wc_decoder_selector.h" - -using ::testing::_; -using ::testing::IsNull; -using ::testing::StrictMock; - -namespace media { - -namespace { - -enum DecoderCapability { - kFail, - kSucceed, -}; - -const char kNoDecoder[] = ""; -const char kDecoder1[] = "Decoder1"; -const char kDecoder2[] = "Decoder2"; - -// Specializations for the AUDIO version of the test. -class AudioDecoderSelectorTestParam { - public: - static constexpr DemuxerStream::Type kStreamType = DemuxerStream::AUDIO; - - using DecoderSelector = WebCodecsDecoderSelector<DemuxerStream::AUDIO>; - using MockDecoder = MockAudioDecoder; - using Output = AudioBuffer; - - static AudioDecoderConfig CreateConfig() { return TestAudioConfig::Normal(); } - - // Create a config that won't match the return of CreateConfig(). - static AudioDecoderConfig CreateAlternateConfig() { - return TestAudioConfig::NormalEncrypted(); - } - - // Decoder::Initialize() takes different parameters depending on the type. - static void ExpectInitialize(MockDecoder* decoder, - DecoderCapability capability, - AudioDecoderConfig expected_config) { - EXPECT_CALL(*decoder, Initialize_(_, _, _, _, _)) - .WillRepeatedly([capability, expected_config]( - const AudioDecoderConfig& config, CdmContext*, - AudioDecoder::InitCB& init_cb, - const AudioDecoder::OutputCB&, const WaitingCB&) { - EXPECT_TRUE(config.Matches(expected_config)); - std::move(init_cb).Run(capability == kSucceed - ? OkStatus() - : StatusCode::kCodeOnlyForTesting); - }); - } -}; - -// Specializations for the VIDEO version of the test. -class VideoDecoderSelectorTestParam { - public: - static constexpr DemuxerStream::Type kStreamType = DemuxerStream::VIDEO; - - using DecoderSelector = WebCodecsDecoderSelector<DemuxerStream::VIDEO>; - using MockDecoder = MockVideoDecoder; - using Output = VideoFrame; - - static VideoDecoderConfig CreateConfig() { return TestVideoConfig::Normal(); } - - // Create a config that won't match the return of CreateConfig(). - static VideoDecoderConfig CreateAlternateConfig() { - return TestVideoConfig::LargeEncrypted(); - } - - static void ExpectInitialize(MockDecoder* decoder, - DecoderCapability capability, - VideoDecoderConfig expected_config) { - EXPECT_CALL(*decoder, Initialize_(_, _, _, _, _, _)) - .WillRepeatedly([capability, expected_config]( - const VideoDecoderConfig& config, bool low_delay, - CdmContext*, VideoDecoder::InitCB& init_cb, - const VideoDecoder::OutputCB&, const WaitingCB&) { - EXPECT_TRUE(config.Matches(expected_config)); - std::move(init_cb).Run(capability == kSucceed - ? OkStatus() - : StatusCode::kCodeOnlyForTesting); - }); - } -}; - -// Allocate storage for the member variables. -constexpr DemuxerStream::Type AudioDecoderSelectorTestParam::kStreamType; -constexpr DemuxerStream::Type VideoDecoderSelectorTestParam::kStreamType; - -} // namespace - -// Note: The parameter is called TypeParam in the test cases regardless of what -// we call it here. It's been named the same for convenience. -// Note: The test fixtures inherit from this class. Inside the test cases the -// test fixture class is called TestFixture. -template <typename TypeParam> -class WebCodecsDecoderSelectorTest : public ::testing::Test { - public: - // Convenience aliases. - using Self = WebCodecsDecoderSelectorTest<TypeParam>; - using Decoder = typename TypeParam::DecoderSelector::Decoder; - using DecoderConfig = typename TypeParam::DecoderSelector::DecoderConfig; - using MockDecoder = typename TypeParam::MockDecoder; - using Output = typename TypeParam::Output; - - WebCodecsDecoderSelectorTest() { CreateDecoderSelector(); } - - void OnOutput(scoped_refptr<Output> output) { NOTREACHED(); } - - MOCK_METHOD1_T(OnDecoderSelected, void(std::string)); - - void OnDecoderSelectedThunk(std::unique_ptr<Decoder> decoder) { - // Report only the name of the decoder, since that's what the tests care - // about. The decoder will be destructed immediately. - OnDecoderSelected(decoder ? decoder->GetDisplayName() : kNoDecoder); - } - - void AddMockDecoder(const std::string& decoder_name, - DecoderCapability capability) { - // Actual decoders are created in CreateDecoders(), which may be called - // multiple times by the DecoderSelector. - mock_decoders_to_create_.emplace_back(decoder_name, capability); - } - - std::vector<std::unique_ptr<Decoder>> CreateDecoders() { - std::vector<std::unique_ptr<Decoder>> decoders; - - for (const auto& info : mock_decoders_to_create_) { - std::unique_ptr<StrictMock<MockDecoder>> decoder = - std::make_unique<StrictMock<MockDecoder>>(info.first); - TypeParam::ExpectInitialize(decoder.get(), info.second, - last_set_decoder_config_); - decoders.push_back(std::move(decoder)); - } - - return decoders; - } - - void CreateDecoderSelector() { - decoder_selector_ = - std::make_unique<WebCodecsDecoderSelector<TypeParam::kStreamType>>( - task_environment_.GetMainThreadTaskRunner(), - base::BindRepeating(&Self::CreateDecoders, base::Unretained(this)), - base::BindRepeating(&Self::OnOutput, base::Unretained(this))); - } - - void SelectDecoder(DecoderConfig config = TypeParam::CreateConfig()) { - last_set_decoder_config_ = config; - decoder_selector_->SelectDecoder( - config, - base::BindOnce(&Self::OnDecoderSelectedThunk, base::Unretained(this))); - RunUntilIdle(); - } - - void RunUntilIdle() { task_environment_.RunUntilIdle(); } - - base::test::TaskEnvironment task_environment_; - NullMediaLog media_log_; - - DecoderConfig last_set_decoder_config_; - - std::unique_ptr<WebCodecsDecoderSelector<TypeParam::kStreamType>> - decoder_selector_; - - std::vector<std::pair<std::string, DecoderCapability>> - mock_decoders_to_create_; - - private: - DISALLOW_COPY_AND_ASSIGN(WebCodecsDecoderSelectorTest); -}; - -using WebCodecsDecoderSelectorTestParams = - ::testing::Types<AudioDecoderSelectorTestParam, - VideoDecoderSelectorTestParam>; -TYPED_TEST_SUITE(WebCodecsDecoderSelectorTest, - WebCodecsDecoderSelectorTestParams); - -TYPED_TEST(WebCodecsDecoderSelectorTest, NoDecoders) { - EXPECT_CALL(*this, OnDecoderSelected(kNoDecoder)); - this->SelectDecoder(); -} - -TYPED_TEST(WebCodecsDecoderSelectorTest, OneDecoder) { - this->AddMockDecoder(kDecoder1, kSucceed); - - EXPECT_CALL(*this, OnDecoderSelected(kDecoder1)); - this->SelectDecoder(); -} - -TYPED_TEST(WebCodecsDecoderSelectorTest, TwoDecoders) { - this->AddMockDecoder(kDecoder1, kFail); - this->AddMockDecoder(kDecoder2, kSucceed); - - EXPECT_CALL(*this, OnDecoderSelected(kDecoder2)); - this->SelectDecoder(); -} - -TYPED_TEST(WebCodecsDecoderSelectorTest, TwoDecoders_SelectAgain) { - this->AddMockDecoder(kDecoder1, kSucceed); - this->AddMockDecoder(kDecoder2, kSucceed); - - EXPECT_CALL(*this, OnDecoderSelected(kDecoder1)); - this->SelectDecoder(); - - // Selecting again should give (a new instance of) the same decoder. - EXPECT_CALL(*this, OnDecoderSelected(kDecoder1)); - this->SelectDecoder(); -} - -TYPED_TEST(WebCodecsDecoderSelectorTest, TwoDecoders_NewConfigSelectAgain) { - this->AddMockDecoder(kDecoder1, kSucceed); - this->AddMockDecoder(kDecoder2, kSucceed); - - EXPECT_CALL(*this, OnDecoderSelected(kDecoder1)); - this->SelectDecoder(TypeParam::CreateConfig()); - - // Selecting again should give (a new instance of) the same decoder. - EXPECT_CALL(*this, OnDecoderSelected(kDecoder1)); - // Select again with a different config. Expected config verified during - // CreateDecoders() the SelectDecoder() call. - this->SelectDecoder(TypeParam::CreateAlternateConfig()); -} - -} // namespace media |