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 DVLOG(2) << __FUNCTION__
;
74 DCHECK(task_runner_
->BelongsToCurrentThread());
77 // Make sure |select_decoder_cb| runs on a different execution stack.
78 select_decoder_cb_
= BindToCurrentLoop(select_decoder_cb
);
80 if (!HasValidStreamConfig(stream
)) {
81 DLOG(ERROR
) << "Invalid stream config.";
86 input_stream_
= stream
;
87 low_delay_
= low_delay
;
89 if (!IsStreamEncrypted(input_stream_
)) {
94 // This could happen if Encrypted Media Extension (EME) is not enabled.
95 if (set_decryptor_ready_cb_
.is_null()) {
100 decoder_
.reset(new typename
StreamTraits::DecryptingDecoderType(
101 task_runner_
, set_decryptor_ready_cb_
));
103 DecoderStreamTraits
<StreamType
>::Initialize(
105 StreamTraits::GetDecoderConfig(*input_stream_
),
107 base::Bind(&DecoderSelector
<StreamType
>::DecryptingDecoderInitDone
,
108 weak_ptr_factory_
.GetWeakPtr()));
111 template <DemuxerStream::Type StreamType
>
112 void DecoderSelector
<StreamType
>::Abort() {
113 DVLOG(2) << __FUNCTION__
;
114 DCHECK(task_runner_
->BelongsToCurrentThread());
116 // This could happen when SelectDecoder() was not called or when
117 // |select_decoder_cb_| was already posted but not fired (e.g. in the
118 // message loop queue).
119 if (select_decoder_cb_
.is_null())
122 // We must be trying to initialize the |decoder_| or the
123 // |decrypted_stream_|. Invalid all weak pointers so that all initialization
124 // callbacks won't fire.
125 weak_ptr_factory_
.InvalidateWeakPtrs();
128 // |decrypted_stream_| is either NULL or already initialized. We don't
129 // need to Stop() |decrypted_stream_| in either case.
135 if (decrypted_stream_
) {
136 decrypted_stream_
->Stop(
137 base::Bind(&DecoderSelector
<StreamType
>::ReturnNullDecoder
,
138 weak_ptr_factory_
.GetWeakPtr()));
145 template <DemuxerStream::Type StreamType
>
146 void DecoderSelector
<StreamType
>::DecryptingDecoderInitDone(
147 PipelineStatus status
) {
148 DVLOG(2) << __FUNCTION__
;
149 DCHECK(task_runner_
->BelongsToCurrentThread());
151 if (status
== PIPELINE_OK
) {
152 base::ResetAndReturn(&select_decoder_cb_
)
153 .Run(decoder_
.Pass(), scoped_ptr
<DecryptingDemuxerStream
>());
159 decrypted_stream_
.reset(
160 new DecryptingDemuxerStream(task_runner_
, set_decryptor_ready_cb_
));
162 decrypted_stream_
->Initialize(
164 base::Bind(&DecoderSelector
<StreamType
>::DecryptingDemuxerStreamInitDone
,
165 weak_ptr_factory_
.GetWeakPtr()));
168 template <DemuxerStream::Type StreamType
>
169 void DecoderSelector
<StreamType
>::DecryptingDemuxerStreamInitDone(
170 PipelineStatus status
) {
171 DVLOG(2) << __FUNCTION__
;
172 DCHECK(task_runner_
->BelongsToCurrentThread());
174 if (status
!= PIPELINE_OK
) {
179 DCHECK(!IsStreamEncrypted(decrypted_stream_
.get()));
180 input_stream_
= decrypted_stream_
.get();
184 template <DemuxerStream::Type StreamType
>
185 void DecoderSelector
<StreamType
>::InitializeDecoder() {
186 DVLOG(2) << __FUNCTION__
;
187 DCHECK(task_runner_
->BelongsToCurrentThread());
190 if (decoders_
.empty()) {
195 decoder_
.reset(decoders_
.front());
196 decoders_
.weak_erase(decoders_
.begin());
198 DecoderStreamTraits
<StreamType
>::Initialize(
200 StreamTraits::GetDecoderConfig(*input_stream_
),
202 base::Bind(&DecoderSelector
<StreamType
>::DecoderInitDone
,
203 weak_ptr_factory_
.GetWeakPtr()));
206 template <DemuxerStream::Type StreamType
>
207 void DecoderSelector
<StreamType
>::DecoderInitDone(PipelineStatus status
) {
208 DVLOG(2) << __FUNCTION__
;
209 DCHECK(task_runner_
->BelongsToCurrentThread());
211 if (status
!= PIPELINE_OK
) {
217 base::ResetAndReturn(&select_decoder_cb_
)
218 .Run(decoder_
.Pass(), decrypted_stream_
.Pass());
221 template <DemuxerStream::Type StreamType
>
222 void DecoderSelector
<StreamType
>::ReturnNullDecoder() {
223 DVLOG(2) << __FUNCTION__
;
224 DCHECK(task_runner_
->BelongsToCurrentThread());
225 base::ResetAndReturn(&select_decoder_cb_
)
226 .Run(scoped_ptr
<Decoder
>(),
227 scoped_ptr
<DecryptingDemuxerStream
>());
230 // These forward declarations tell the compiler that we will use
231 // DecoderSelector with these arguments, allowing us to keep these definitions
232 // in our .cc without causing linker errors. This also means if anyone tries to
233 // instantiate a DecoderSelector with anything but these two specializations
234 // they'll most likely get linker errors.
235 template class DecoderSelector
<DemuxerStream::AUDIO
>;
236 template class DecoderSelector
<DemuxerStream::VIDEO
>;