9020597798d98d74c8933af28271b8b091c2d6c2
[platform/framework/web/crosswalk.git] / src / media / filters / decoder_selector.cc
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
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
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>
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>
63 DecoderSelector<StreamType>::~DecoderSelector() {
64   DVLOG(2) << __FUNCTION__;
65   DCHECK(select_decoder_cb_.is_null());
66 }
67
68 template <DemuxerStream::Type StreamType>
69 void DecoderSelector<StreamType>::SelectDecoder(
70     DemuxerStream* stream,
71     bool low_delay,
72     const SelectDecoderCB& select_decoder_cb,
73     const typename Decoder::OutputCB& output_cb) {
74   DVLOG(2) << __FUNCTION__;
75   DCHECK(task_runner_->BelongsToCurrentThread());
76   DCHECK(stream);
77
78   // Make sure |select_decoder_cb| runs on a different execution stack.
79   select_decoder_cb_ = BindToCurrentLoop(select_decoder_cb);
80
81   if (!HasValidStreamConfig(stream)) {
82     DLOG(ERROR) << "Invalid stream config.";
83     ReturnNullDecoder();
84     return;
85   }
86
87   input_stream_ = stream;
88   low_delay_ = low_delay;
89   output_cb_ = output_cb;
90
91   if (!IsStreamEncrypted(input_stream_)) {
92     InitializeDecoder();
93     return;
94   }
95
96   // This could happen if Encrypted Media Extension (EME) is not enabled.
97   if (set_decryptor_ready_cb_.is_null()) {
98     ReturnNullDecoder();
99     return;
100   }
101
102   decoder_.reset(new typename StreamTraits::DecryptingDecoderType(
103       task_runner_, set_decryptor_ready_cb_));
104
105   DecoderStreamTraits<StreamType>::Initialize(
106       decoder_.get(),
107       StreamTraits::GetDecoderConfig(*input_stream_),
108       low_delay_,
109       base::Bind(&DecoderSelector<StreamType>::DecryptingDecoderInitDone,
110                  weak_ptr_factory_.GetWeakPtr()),
111       output_cb_);
112 }
113
114 template <DemuxerStream::Type StreamType>
115 void DecoderSelector<StreamType>::Abort() {
116   DVLOG(2) << __FUNCTION__;
117   DCHECK(task_runner_->BelongsToCurrentThread());
118
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())
123     return;
124
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();
129
130   if (decoder_) {
131     // |decrypted_stream_| is either NULL or already initialized. We don't
132     // need to Stop() |decrypted_stream_| in either case.
133     decoder_->Stop();
134     ReturnNullDecoder();
135     return;
136   }
137
138   if (decrypted_stream_) {
139     decrypted_stream_->Stop(
140         base::Bind(&DecoderSelector<StreamType>::ReturnNullDecoder,
141                    weak_ptr_factory_.GetWeakPtr()));
142     return;
143   }
144
145   NOTREACHED();
146 }
147
148 template <DemuxerStream::Type StreamType>
149 void DecoderSelector<StreamType>::DecryptingDecoderInitDone(
150     PipelineStatus status) {
151   DVLOG(2) << __FUNCTION__;
152   DCHECK(task_runner_->BelongsToCurrentThread());
153
154   if (status == PIPELINE_OK) {
155     base::ResetAndReturn(&select_decoder_cb_)
156         .Run(decoder_.Pass(), scoped_ptr<DecryptingDemuxerStream>());
157     return;
158   }
159
160   decoder_.reset();
161
162   decrypted_stream_.reset(
163       new DecryptingDemuxerStream(task_runner_, set_decryptor_ready_cb_));
164
165   decrypted_stream_->Initialize(
166       input_stream_,
167       base::Bind(&DecoderSelector<StreamType>::DecryptingDemuxerStreamInitDone,
168                  weak_ptr_factory_.GetWeakPtr()));
169 }
170
171 template <DemuxerStream::Type StreamType>
172 void DecoderSelector<StreamType>::DecryptingDemuxerStreamInitDone(
173     PipelineStatus status) {
174   DVLOG(2) << __FUNCTION__;
175   DCHECK(task_runner_->BelongsToCurrentThread());
176
177   if (status != PIPELINE_OK) {
178     ReturnNullDecoder();
179     return;
180   }
181
182   DCHECK(!IsStreamEncrypted(decrypted_stream_.get()));
183   input_stream_ = decrypted_stream_.get();
184   InitializeDecoder();
185 }
186
187 template <DemuxerStream::Type StreamType>
188 void DecoderSelector<StreamType>::InitializeDecoder() {
189   DVLOG(2) << __FUNCTION__;
190   DCHECK(task_runner_->BelongsToCurrentThread());
191   DCHECK(!decoder_);
192
193   if (decoders_.empty()) {
194     ReturnNullDecoder();
195     return;
196   }
197
198   decoder_.reset(decoders_.front());
199   decoders_.weak_erase(decoders_.begin());
200
201   DecoderStreamTraits<StreamType>::Initialize(
202       decoder_.get(),
203       StreamTraits::GetDecoderConfig(*input_stream_),
204       low_delay_,
205       base::Bind(&DecoderSelector<StreamType>::DecoderInitDone,
206                  weak_ptr_factory_.GetWeakPtr()),
207       output_cb_);
208 }
209
210 template <DemuxerStream::Type StreamType>
211 void DecoderSelector<StreamType>::DecoderInitDone(PipelineStatus status) {
212   DVLOG(2) << __FUNCTION__;
213   DCHECK(task_runner_->BelongsToCurrentThread());
214
215   if (status != PIPELINE_OK) {
216     decoder_.reset();
217     InitializeDecoder();
218     return;
219   }
220
221   base::ResetAndReturn(&select_decoder_cb_)
222       .Run(decoder_.Pass(), decrypted_stream_.Pass());
223 }
224
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>());
232 }
233
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>;
241
242 }  // namespace media