1 // Copyright 2014 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "decoder_selector.h"
8 #include "base/callback_helpers.h"
9 #include "base/logging.h"
10 #include "base/single_thread_task_runner.h"
11 #include "media/base/audio_decoder.h"
12 #include "media/base/bind_to_current_loop.h"
13 #include "media/base/demuxer_stream.h"
14 #include "media/base/pipeline.h"
15 #include "media/base/video_decoder.h"
16 #include "media/filters/decoder_stream_traits.h"
17 #include "media/filters/decrypting_audio_decoder.h"
18 #include "media/filters/decrypting_demuxer_stream.h"
19 #include "media/filters/decrypting_video_decoder.h"
23 static bool HasValidStreamConfig(DemuxerStream
* stream
) {
24 switch (stream
->type()) {
25 case DemuxerStream::AUDIO
:
26 return stream
->audio_decoder_config().IsValidConfig();
27 case DemuxerStream::VIDEO
:
28 return stream
->video_decoder_config().IsValidConfig();
29 case DemuxerStream::UNKNOWN
:
30 case DemuxerStream::TEXT
:
31 case DemuxerStream::NUM_TYPES
:
37 static bool IsStreamEncrypted(DemuxerStream
* stream
) {
38 switch (stream
->type()) {
39 case DemuxerStream::AUDIO
:
40 return stream
->audio_decoder_config().is_encrypted();
41 case DemuxerStream::VIDEO
:
42 return stream
->video_decoder_config().is_encrypted();
43 case DemuxerStream::UNKNOWN
:
44 case DemuxerStream::TEXT
:
45 case DemuxerStream::NUM_TYPES
:
51 template <DemuxerStream::Type StreamType
>
52 DecoderSelector
<StreamType
>::DecoderSelector(
53 const scoped_refptr
<base::SingleThreadTaskRunner
>& task_runner
,
54 ScopedVector
<Decoder
> decoders
)
55 : task_runner_(task_runner
),
56 decoders_(decoders
.Pass()),
58 weak_ptr_factory_(this) {
61 template <DemuxerStream::Type StreamType
>
62 DecoderSelector
<StreamType
>::~DecoderSelector() {
63 DVLOG(2) << __FUNCTION__
;
64 DCHECK(task_runner_
->BelongsToCurrentThread());
66 if (!select_decoder_cb_
.is_null())
70 decrypted_stream_
.reset();
73 template <DemuxerStream::Type StreamType
>
74 void DecoderSelector
<StreamType
>::SelectDecoder(
75 DemuxerStream
* stream
,
76 const SetDecryptorReadyCB
& set_decryptor_ready_cb
,
77 const SelectDecoderCB
& select_decoder_cb
,
78 const typename
Decoder::OutputCB
& output_cb
,
79 const base::Closure
& waiting_for_decryption_key_cb
) {
80 DVLOG(2) << __FUNCTION__
;
81 DCHECK(task_runner_
->BelongsToCurrentThread());
83 DCHECK(select_decoder_cb_
.is_null());
85 set_decryptor_ready_cb_
= set_decryptor_ready_cb
;
86 waiting_for_decryption_key_cb_
= waiting_for_decryption_key_cb
;
88 // Make sure |select_decoder_cb| runs on a different execution stack.
89 select_decoder_cb_
= BindToCurrentLoop(select_decoder_cb
);
91 if (!HasValidStreamConfig(stream
)) {
92 DLOG(ERROR
) << "Invalid stream config.";
97 input_stream_
= stream
;
98 output_cb_
= output_cb
;
100 if (!IsStreamEncrypted(input_stream_
)) {
105 // This could be null if Encrypted Media Extension (EME) is not enabled.
106 if (set_decryptor_ready_cb_
.is_null()) {
111 decoder_
.reset(new typename
StreamTraits::DecryptingDecoderType(
112 task_runner_
, set_decryptor_ready_cb_
, waiting_for_decryption_key_cb_
));
114 DecoderStreamTraits
<StreamType
>::InitializeDecoder(
115 decoder_
.get(), input_stream_
,
116 base::Bind(&DecoderSelector
<StreamType
>::DecryptingDecoderInitDone
,
117 weak_ptr_factory_
.GetWeakPtr()),
121 template <DemuxerStream::Type StreamType
>
122 void DecoderSelector
<StreamType
>::DecryptingDecoderInitDone(
123 PipelineStatus status
) {
124 DVLOG(2) << __FUNCTION__
;
125 DCHECK(task_runner_
->BelongsToCurrentThread());
127 if (status
== PIPELINE_OK
) {
128 base::ResetAndReturn(&select_decoder_cb_
)
129 .Run(decoder_
.Pass(), scoped_ptr
<DecryptingDemuxerStream
>());
135 decrypted_stream_
.reset(new DecryptingDemuxerStream(
136 task_runner_
, set_decryptor_ready_cb_
, waiting_for_decryption_key_cb_
));
138 decrypted_stream_
->Initialize(
140 base::Bind(&DecoderSelector
<StreamType
>::DecryptingDemuxerStreamInitDone
,
141 weak_ptr_factory_
.GetWeakPtr()));
144 template <DemuxerStream::Type StreamType
>
145 void DecoderSelector
<StreamType
>::DecryptingDemuxerStreamInitDone(
146 PipelineStatus status
) {
147 DVLOG(2) << __FUNCTION__
;
148 DCHECK(task_runner_
->BelongsToCurrentThread());
150 if (status
!= PIPELINE_OK
) {
155 DCHECK(!IsStreamEncrypted(decrypted_stream_
.get()));
156 input_stream_
= decrypted_stream_
.get();
160 template <DemuxerStream::Type StreamType
>
161 void DecoderSelector
<StreamType
>::InitializeDecoder() {
162 DVLOG(2) << __FUNCTION__
;
163 DCHECK(task_runner_
->BelongsToCurrentThread());
166 if (decoders_
.empty()) {
171 decoder_
.reset(decoders_
.front());
172 decoders_
.weak_erase(decoders_
.begin());
174 DecoderStreamTraits
<StreamType
>::InitializeDecoder(
175 decoder_
.get(), input_stream_
,
176 base::Bind(&DecoderSelector
<StreamType
>::DecoderInitDone
,
177 weak_ptr_factory_
.GetWeakPtr()),
181 template <DemuxerStream::Type StreamType
>
182 void DecoderSelector
<StreamType
>::DecoderInitDone(PipelineStatus status
) {
183 DVLOG(2) << __FUNCTION__
;
184 DCHECK(task_runner_
->BelongsToCurrentThread());
186 if (status
!= PIPELINE_OK
) {
192 base::ResetAndReturn(&select_decoder_cb_
)
193 .Run(decoder_
.Pass(), decrypted_stream_
.Pass());
196 template <DemuxerStream::Type StreamType
>
197 void DecoderSelector
<StreamType
>::ReturnNullDecoder() {
198 DVLOG(2) << __FUNCTION__
;
199 DCHECK(task_runner_
->BelongsToCurrentThread());
200 base::ResetAndReturn(&select_decoder_cb_
)
201 .Run(scoped_ptr
<Decoder
>(),
202 scoped_ptr
<DecryptingDemuxerStream
>());
205 // These forward declarations tell the compiler that we will use
206 // DecoderSelector with these arguments, allowing us to keep these definitions
207 // in our .cc without causing linker errors. This also means if anyone tries to
208 // instantiate a DecoderSelector with anything but these two specializations
209 // they'll most likely get linker errors.
210 template class DecoderSelector
<DemuxerStream::AUDIO
>;
211 template class DecoderSelector
<DemuxerStream::VIDEO
>;