forked from chromium/chromium
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
This wraps media::DecoderSelector in more friendly (simplified) interface for WebCodecs. Re-using the selector is desirable because WebCodecs has common requirements: - walk a list of decoders to find the most suitable for a given config. - do so in generic way for audio and video stream types - (eventually) new smarts around decoder selection (e.g. fallback/fallforward on resolution changes). The wrapping eliminates (or hides) a few things WebCodecs doesn't need - demuxer stream - encryption - decoder selection finalization Bug: 1045247 Change-Id: I37fa629a243bb717bd2413d2bfd97e29f77eeebc Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2150161 Reviewed-by: Dan Sanders <sandersd@chromium.org> Commit-Queue: Chrome Cunningham <chcunningham@chromium.org> Cr-Commit-Position: refs/heads/master@{#762167}
- Loading branch information
1 parent
c501c95
commit 419f14d
Showing
7 changed files
with
506 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
# 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", | ||
] | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,141 @@ | ||
// 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/logging.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 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
// 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_ |
Oops, something went wrong.