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/media_log.h"
15 #include "media/base/pipeline.h"
16 #include "media/base/video_decoder.h"
17 #include "media/filters/decoder_stream_traits.h"
18 #include "media/filters/decrypting_audio_decoder.h"
19 #include "media/filters/decrypting_demuxer_stream.h"
20 #include "media/filters/decrypting_video_decoder.h"
24 static bool HasValidStreamConfig(DemuxerStream
* stream
) {
25 switch (stream
->type()) {
26 case DemuxerStream::AUDIO
:
27 return stream
->audio_decoder_config().IsValidConfig();
28 case DemuxerStream::VIDEO
:
29 return stream
->video_decoder_config().IsValidConfig();
30 case DemuxerStream::UNKNOWN
:
31 case DemuxerStream::TEXT
:
32 case DemuxerStream::NUM_TYPES
:
38 static bool IsStreamEncrypted(DemuxerStream
* stream
) {
39 switch (stream
->type()) {
40 case DemuxerStream::AUDIO
:
41 return stream
->audio_decoder_config().is_encrypted();
42 case DemuxerStream::VIDEO
:
43 return stream
->video_decoder_config().is_encrypted();
44 case DemuxerStream::UNKNOWN
:
45 case DemuxerStream::TEXT
:
46 case DemuxerStream::NUM_TYPES
:
52 template <DemuxerStream::Type StreamType
>
53 DecoderSelector
<StreamType
>::DecoderSelector(
54 const scoped_refptr
<base::SingleThreadTaskRunner
>& task_runner
,
55 ScopedVector
<Decoder
> decoders
,
56 const scoped_refptr
<MediaLog
>& media_log
)
57 : task_runner_(task_runner
),
58 decoders_(decoders
.Pass()),
59 media_log_(media_log
),
61 weak_ptr_factory_(this) {
64 template <DemuxerStream::Type StreamType
>
65 DecoderSelector
<StreamType
>::~DecoderSelector() {
66 DVLOG(2) << __FUNCTION__
;
67 DCHECK(task_runner_
->BelongsToCurrentThread());
69 if (!select_decoder_cb_
.is_null())
73 decrypted_stream_
.reset();
76 template <DemuxerStream::Type StreamType
>
77 void DecoderSelector
<StreamType
>::SelectDecoder(
78 DemuxerStream
* stream
,
79 const SetDecryptorReadyCB
& set_decryptor_ready_cb
,
80 const SelectDecoderCB
& select_decoder_cb
,
81 const typename
Decoder::OutputCB
& output_cb
,
82 const base::Closure
& waiting_for_decryption_key_cb
) {
83 DVLOG(2) << __FUNCTION__
;
84 DCHECK(task_runner_
->BelongsToCurrentThread());
86 DCHECK(select_decoder_cb_
.is_null());
88 set_decryptor_ready_cb_
= set_decryptor_ready_cb
;
89 waiting_for_decryption_key_cb_
= waiting_for_decryption_key_cb
;
91 // Make sure |select_decoder_cb| runs on a different execution stack.
92 select_decoder_cb_
= BindToCurrentLoop(select_decoder_cb
);
94 if (!HasValidStreamConfig(stream
)) {
95 DLOG(ERROR
) << "Invalid stream config.";
100 input_stream_
= stream
;
101 output_cb_
= output_cb
;
103 if (!IsStreamEncrypted(input_stream_
)) {
108 // This could be null if Encrypted Media Extension (EME) is not enabled.
109 if (set_decryptor_ready_cb_
.is_null()) {
114 decoder_
.reset(new typename
StreamTraits::DecryptingDecoderType(
115 task_runner_
, media_log_
, set_decryptor_ready_cb_
,
116 waiting_for_decryption_key_cb_
));
118 DecoderStreamTraits
<StreamType
>::InitializeDecoder(
119 decoder_
.get(), input_stream_
,
120 base::Bind(&DecoderSelector
<StreamType
>::DecryptingDecoderInitDone
,
121 weak_ptr_factory_
.GetWeakPtr()),
125 template <DemuxerStream::Type StreamType
>
126 void DecoderSelector
<StreamType
>::DecryptingDecoderInitDone(bool success
) {
127 DVLOG(2) << __FUNCTION__
;
128 DCHECK(task_runner_
->BelongsToCurrentThread());
131 base::ResetAndReturn(&select_decoder_cb_
)
132 .Run(decoder_
.Pass(), scoped_ptr
<DecryptingDemuxerStream
>());
138 decrypted_stream_
.reset(new DecryptingDemuxerStream(
139 task_runner_
, media_log_
, set_decryptor_ready_cb_
,
140 waiting_for_decryption_key_cb_
));
142 decrypted_stream_
->Initialize(
144 base::Bind(&DecoderSelector
<StreamType
>::DecryptingDemuxerStreamInitDone
,
145 weak_ptr_factory_
.GetWeakPtr()));
148 template <DemuxerStream::Type StreamType
>
149 void DecoderSelector
<StreamType
>::DecryptingDemuxerStreamInitDone(
150 PipelineStatus status
) {
151 DVLOG(2) << __FUNCTION__
;
152 DCHECK(task_runner_
->BelongsToCurrentThread());
154 if (status
!= PIPELINE_OK
) {
159 DCHECK(!IsStreamEncrypted(decrypted_stream_
.get()));
160 input_stream_
= decrypted_stream_
.get();
164 template <DemuxerStream::Type StreamType
>
165 void DecoderSelector
<StreamType
>::InitializeDecoder() {
166 DVLOG(2) << __FUNCTION__
;
167 DCHECK(task_runner_
->BelongsToCurrentThread());
170 if (decoders_
.empty()) {
175 decoder_
.reset(decoders_
.front());
176 decoders_
.weak_erase(decoders_
.begin());
178 DecoderStreamTraits
<StreamType
>::InitializeDecoder(
179 decoder_
.get(), input_stream_
,
180 base::Bind(&DecoderSelector
<StreamType
>::DecoderInitDone
,
181 weak_ptr_factory_
.GetWeakPtr()),
185 template <DemuxerStream::Type StreamType
>
186 void DecoderSelector
<StreamType
>::DecoderInitDone(bool success
) {
187 DVLOG(2) << __FUNCTION__
;
188 DCHECK(task_runner_
->BelongsToCurrentThread());
196 base::ResetAndReturn(&select_decoder_cb_
)
197 .Run(decoder_
.Pass(), decrypted_stream_
.Pass());
200 template <DemuxerStream::Type StreamType
>
201 void DecoderSelector
<StreamType
>::ReturnNullDecoder() {
202 DVLOG(2) << __FUNCTION__
;
203 DCHECK(task_runner_
->BelongsToCurrentThread());
204 base::ResetAndReturn(&select_decoder_cb_
)
205 .Run(scoped_ptr
<Decoder
>(),
206 scoped_ptr
<DecryptingDemuxerStream
>());
209 // These forward declarations tell the compiler that we will use
210 // DecoderSelector with these arguments, allowing us to keep these definitions
211 // in our .cc without causing linker errors. This also means if anyone tries to
212 // instantiate a DecoderSelector with anything but these two specializations
213 // they'll most likely get linker errors.
214 template class DecoderSelector
<DemuxerStream::AUDIO
>;
215 template class DecoderSelector
<DemuxerStream::VIDEO
>;