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 const SetDecryptorReadyCB
& set_decryptor_ready_cb
)
56 : task_runner_(task_runner
),
57 decoders_(decoders
.Pass()),
58 set_decryptor_ready_cb_(set_decryptor_ready_cb
),
60 weak_ptr_factory_(this) {}
62 template <DemuxerStream::Type StreamType
>
63 DecoderSelector
<StreamType
>::~DecoderSelector() {
64 DVLOG(2) << __FUNCTION__
;
65 DCHECK(select_decoder_cb_
.is_null());
68 template <DemuxerStream::Type StreamType
>
69 void DecoderSelector
<StreamType
>::SelectDecoder(
70 DemuxerStream
* stream
,
72 const SelectDecoderCB
& select_decoder_cb
,
73 const typename
Decoder::OutputCB
& output_cb
) {
74 DVLOG(2) << __FUNCTION__
;
75 DCHECK(task_runner_
->BelongsToCurrentThread());
78 // Make sure |select_decoder_cb| runs on a different execution stack.
79 select_decoder_cb_
= BindToCurrentLoop(select_decoder_cb
);
81 if (!HasValidStreamConfig(stream
)) {
82 DLOG(ERROR
) << "Invalid stream config.";
87 input_stream_
= stream
;
88 low_delay_
= low_delay
;
89 output_cb_
= output_cb
;
91 if (!IsStreamEncrypted(input_stream_
)) {
96 // This could happen if Encrypted Media Extension (EME) is not enabled.
97 if (set_decryptor_ready_cb_
.is_null()) {
102 decoder_
.reset(new typename
StreamTraits::DecryptingDecoderType(
103 task_runner_
, set_decryptor_ready_cb_
));
105 DecoderStreamTraits
<StreamType
>::Initialize(
107 StreamTraits::GetDecoderConfig(*input_stream_
),
109 base::Bind(&DecoderSelector
<StreamType
>::DecryptingDecoderInitDone
,
110 weak_ptr_factory_
.GetWeakPtr()),
114 template <DemuxerStream::Type StreamType
>
115 void DecoderSelector
<StreamType
>::Abort() {
116 DVLOG(2) << __FUNCTION__
;
117 DCHECK(task_runner_
->BelongsToCurrentThread());
119 // This could happen when SelectDecoder() was not called or when
120 // |select_decoder_cb_| was already posted but not fired (e.g. in the
121 // message loop queue).
122 if (select_decoder_cb_
.is_null())
125 // We must be trying to initialize the |decoder_| or the
126 // |decrypted_stream_|. Invalid all weak pointers so that all initialization
127 // callbacks won't fire.
128 weak_ptr_factory_
.InvalidateWeakPtrs();
131 // |decrypted_stream_| is either NULL or already initialized. We don't
132 // need to Stop() |decrypted_stream_| in either case.
138 if (decrypted_stream_
) {
139 decrypted_stream_
->Stop(
140 base::Bind(&DecoderSelector
<StreamType
>::ReturnNullDecoder
,
141 weak_ptr_factory_
.GetWeakPtr()));
148 template <DemuxerStream::Type StreamType
>
149 void DecoderSelector
<StreamType
>::DecryptingDecoderInitDone(
150 PipelineStatus status
) {
151 DVLOG(2) << __FUNCTION__
;
152 DCHECK(task_runner_
->BelongsToCurrentThread());
154 if (status
== PIPELINE_OK
) {
155 base::ResetAndReturn(&select_decoder_cb_
)
156 .Run(decoder_
.Pass(), scoped_ptr
<DecryptingDemuxerStream
>());
162 decrypted_stream_
.reset(
163 new DecryptingDemuxerStream(task_runner_
, set_decryptor_ready_cb_
));
165 decrypted_stream_
->Initialize(
167 base::Bind(&DecoderSelector
<StreamType
>::DecryptingDemuxerStreamInitDone
,
168 weak_ptr_factory_
.GetWeakPtr()));
171 template <DemuxerStream::Type StreamType
>
172 void DecoderSelector
<StreamType
>::DecryptingDemuxerStreamInitDone(
173 PipelineStatus status
) {
174 DVLOG(2) << __FUNCTION__
;
175 DCHECK(task_runner_
->BelongsToCurrentThread());
177 if (status
!= PIPELINE_OK
) {
182 DCHECK(!IsStreamEncrypted(decrypted_stream_
.get()));
183 input_stream_
= decrypted_stream_
.get();
187 template <DemuxerStream::Type StreamType
>
188 void DecoderSelector
<StreamType
>::InitializeDecoder() {
189 DVLOG(2) << __FUNCTION__
;
190 DCHECK(task_runner_
->BelongsToCurrentThread());
193 if (decoders_
.empty()) {
198 decoder_
.reset(decoders_
.front());
199 decoders_
.weak_erase(decoders_
.begin());
201 DecoderStreamTraits
<StreamType
>::Initialize(
203 StreamTraits::GetDecoderConfig(*input_stream_
),
205 base::Bind(&DecoderSelector
<StreamType
>::DecoderInitDone
,
206 weak_ptr_factory_
.GetWeakPtr()),
210 template <DemuxerStream::Type StreamType
>
211 void DecoderSelector
<StreamType
>::DecoderInitDone(PipelineStatus status
) {
212 DVLOG(2) << __FUNCTION__
;
213 DCHECK(task_runner_
->BelongsToCurrentThread());
215 if (status
!= PIPELINE_OK
) {
221 base::ResetAndReturn(&select_decoder_cb_
)
222 .Run(decoder_
.Pass(), decrypted_stream_
.Pass());
225 template <DemuxerStream::Type StreamType
>
226 void DecoderSelector
<StreamType
>::ReturnNullDecoder() {
227 DVLOG(2) << __FUNCTION__
;
228 DCHECK(task_runner_
->BelongsToCurrentThread());
229 base::ResetAndReturn(&select_decoder_cb_
)
230 .Run(scoped_ptr
<Decoder
>(),
231 scoped_ptr
<DecryptingDemuxerStream
>());
234 // These forward declarations tell the compiler that we will use
235 // DecoderSelector with these arguments, allowing us to keep these definitions
236 // in our .cc without causing linker errors. This also means if anyone tries to
237 // instantiate a DecoderSelector with anything but these two specializations
238 // they'll most likely get linker errors.
239 template class DecoderSelector
<DemuxerStream::AUDIO
>;
240 template class DecoderSelector
<DemuxerStream::VIDEO
>;