• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 #include "decoder_selector.h"
6 
7 #include "base/bind.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"
20 
21 namespace media {
22 
HasValidStreamConfig(DemuxerStream * stream)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:
32       NOTREACHED();
33   }
34   return false;
35 }
36 
IsStreamEncrypted(DemuxerStream * stream)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:
46       NOTREACHED();
47   }
48   return false;
49 }
50 
51 template <DemuxerStream::Type StreamType>
DecoderSelector(const scoped_refptr<base::SingleThreadTaskRunner> & task_runner,ScopedVector<Decoder> decoders,const SetDecryptorReadyCB & set_decryptor_ready_cb)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),
59       input_stream_(NULL),
60       weak_ptr_factory_(this) {}
61 
62 template <DemuxerStream::Type StreamType>
~DecoderSelector()63 DecoderSelector<StreamType>::~DecoderSelector() {
64   DVLOG(2) << __FUNCTION__;
65   DCHECK(task_runner_->BelongsToCurrentThread());
66 
67   if (!select_decoder_cb_.is_null())
68     ReturnNullDecoder();
69 
70   decoder_.reset();
71   decrypted_stream_.reset();
72 }
73 
74 template <DemuxerStream::Type StreamType>
SelectDecoder(DemuxerStream * stream,bool low_delay,const SelectDecoderCB & select_decoder_cb,const typename Decoder::OutputCB & output_cb)75 void DecoderSelector<StreamType>::SelectDecoder(
76     DemuxerStream* stream,
77     bool low_delay,
78     const SelectDecoderCB& select_decoder_cb,
79     const typename Decoder::OutputCB& output_cb) {
80   DVLOG(2) << __FUNCTION__;
81   DCHECK(task_runner_->BelongsToCurrentThread());
82   DCHECK(stream);
83 
84   // Make sure |select_decoder_cb| runs on a different execution stack.
85   select_decoder_cb_ = BindToCurrentLoop(select_decoder_cb);
86 
87   if (!HasValidStreamConfig(stream)) {
88     DLOG(ERROR) << "Invalid stream config.";
89     ReturnNullDecoder();
90     return;
91   }
92 
93   input_stream_ = stream;
94   low_delay_ = low_delay;
95   output_cb_ = output_cb;
96 
97   if (!IsStreamEncrypted(input_stream_)) {
98     InitializeDecoder();
99     return;
100   }
101 
102   // This could happen if Encrypted Media Extension (EME) is not enabled.
103   if (set_decryptor_ready_cb_.is_null()) {
104     ReturnNullDecoder();
105     return;
106   }
107 
108   decoder_.reset(new typename StreamTraits::DecryptingDecoderType(
109       task_runner_, set_decryptor_ready_cb_));
110 
111   DecoderStreamTraits<StreamType>::Initialize(
112       decoder_.get(),
113       StreamTraits::GetDecoderConfig(*input_stream_),
114       low_delay_,
115       base::Bind(&DecoderSelector<StreamType>::DecryptingDecoderInitDone,
116                  weak_ptr_factory_.GetWeakPtr()),
117       output_cb_);
118 }
119 
120 template <DemuxerStream::Type StreamType>
DecryptingDecoderInitDone(PipelineStatus status)121 void DecoderSelector<StreamType>::DecryptingDecoderInitDone(
122     PipelineStatus status) {
123   DVLOG(2) << __FUNCTION__;
124   DCHECK(task_runner_->BelongsToCurrentThread());
125 
126   if (status == PIPELINE_OK) {
127     base::ResetAndReturn(&select_decoder_cb_)
128         .Run(decoder_.Pass(), scoped_ptr<DecryptingDemuxerStream>());
129     return;
130   }
131 
132   decoder_.reset();
133 
134   decrypted_stream_.reset(
135       new DecryptingDemuxerStream(task_runner_, set_decryptor_ready_cb_));
136 
137   decrypted_stream_->Initialize(
138       input_stream_,
139       base::Bind(&DecoderSelector<StreamType>::DecryptingDemuxerStreamInitDone,
140                  weak_ptr_factory_.GetWeakPtr()));
141 }
142 
143 template <DemuxerStream::Type StreamType>
DecryptingDemuxerStreamInitDone(PipelineStatus status)144 void DecoderSelector<StreamType>::DecryptingDemuxerStreamInitDone(
145     PipelineStatus status) {
146   DVLOG(2) << __FUNCTION__;
147   DCHECK(task_runner_->BelongsToCurrentThread());
148 
149   if (status != PIPELINE_OK) {
150     ReturnNullDecoder();
151     return;
152   }
153 
154   DCHECK(!IsStreamEncrypted(decrypted_stream_.get()));
155   input_stream_ = decrypted_stream_.get();
156   InitializeDecoder();
157 }
158 
159 template <DemuxerStream::Type StreamType>
InitializeDecoder()160 void DecoderSelector<StreamType>::InitializeDecoder() {
161   DVLOG(2) << __FUNCTION__;
162   DCHECK(task_runner_->BelongsToCurrentThread());
163   DCHECK(!decoder_);
164 
165   if (decoders_.empty()) {
166     ReturnNullDecoder();
167     return;
168   }
169 
170   decoder_.reset(decoders_.front());
171   decoders_.weak_erase(decoders_.begin());
172 
173   DecoderStreamTraits<StreamType>::Initialize(
174       decoder_.get(),
175       StreamTraits::GetDecoderConfig(*input_stream_),
176       low_delay_,
177       base::Bind(&DecoderSelector<StreamType>::DecoderInitDone,
178                  weak_ptr_factory_.GetWeakPtr()),
179       output_cb_);
180 }
181 
182 template <DemuxerStream::Type StreamType>
DecoderInitDone(PipelineStatus status)183 void DecoderSelector<StreamType>::DecoderInitDone(PipelineStatus status) {
184   DVLOG(2) << __FUNCTION__;
185   DCHECK(task_runner_->BelongsToCurrentThread());
186 
187   if (status != PIPELINE_OK) {
188     decoder_.reset();
189     InitializeDecoder();
190     return;
191   }
192 
193   base::ResetAndReturn(&select_decoder_cb_)
194       .Run(decoder_.Pass(), decrypted_stream_.Pass());
195 }
196 
197 template <DemuxerStream::Type StreamType>
ReturnNullDecoder()198 void DecoderSelector<StreamType>::ReturnNullDecoder() {
199   DVLOG(2) << __FUNCTION__;
200   DCHECK(task_runner_->BelongsToCurrentThread());
201   base::ResetAndReturn(&select_decoder_cb_)
202       .Run(scoped_ptr<Decoder>(),
203            scoped_ptr<DecryptingDemuxerStream>());
204 }
205 
206 // These forward declarations tell the compiler that we will use
207 // DecoderSelector with these arguments, allowing us to keep these definitions
208 // in our .cc without causing linker errors. This also means if anyone tries to
209 // instantiate a DecoderSelector with anything but these two specializations
210 // they'll most likely get linker errors.
211 template class DecoderSelector<DemuxerStream::AUDIO>;
212 template class DecoderSelector<DemuxerStream::VIDEO>;
213 
214 }  // namespace media
215