cc: Added inline to Tile::IsReadyToDraw
[chromium-blink-merge.git] / media / filters / decrypting_demuxer_stream.cc
blob1f183ceb2886b3de3907897263a4b827731f2e8f
1 // Copyright (c) 2012 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 "media/filters/decrypting_demuxer_stream.h"
7 #include "base/bind.h"
8 #include "base/callback_helpers.h"
9 #include "base/location.h"
10 #include "base/logging.h"
11 #include "base/message_loop/message_loop_proxy.h"
12 #include "media/base/audio_decoder_config.h"
13 #include "media/base/video_decoder_config.h"
14 #include "media/base/bind_to_loop.h"
15 #include "media/base/decoder_buffer.h"
16 #include "media/base/decryptor.h"
17 #include "media/base/demuxer_stream.h"
18 #include "media/base/pipeline.h"
20 namespace media {
22 #define BIND_TO_LOOP(function) \
23 media::BindToLoop(message_loop_, base::Bind(function, weak_this_))
25 static bool IsStreamValidAndEncrypted(DemuxerStream* stream) {
26 return ((stream->type() == DemuxerStream::AUDIO &&
27 stream->audio_decoder_config().IsValidConfig() &&
28 stream->audio_decoder_config().is_encrypted()) ||
29 (stream->type() == DemuxerStream::VIDEO &&
30 stream->video_decoder_config().IsValidConfig() &&
31 stream->video_decoder_config().is_encrypted()));
34 DecryptingDemuxerStream::DecryptingDemuxerStream(
35 const scoped_refptr<base::MessageLoopProxy>& message_loop,
36 const SetDecryptorReadyCB& set_decryptor_ready_cb)
37 : message_loop_(message_loop),
38 weak_factory_(this),
39 state_(kUninitialized),
40 demuxer_stream_(NULL),
41 set_decryptor_ready_cb_(set_decryptor_ready_cb),
42 decryptor_(NULL),
43 key_added_while_decrypt_pending_(false) {
46 void DecryptingDemuxerStream::Initialize(
47 DemuxerStream* stream,
48 const PipelineStatusCB& status_cb) {
49 DVLOG(2) << "Initialize()";
50 DCHECK(message_loop_->BelongsToCurrentThread());
51 DCHECK_EQ(state_, kUninitialized) << state_;
53 DCHECK(!demuxer_stream_);
54 weak_this_ = weak_factory_.GetWeakPtr();
55 demuxer_stream_ = stream;
56 init_cb_ = status_cb;
58 InitializeDecoderConfig();
60 state_ = kDecryptorRequested;
61 set_decryptor_ready_cb_.Run(
62 BIND_TO_LOOP(&DecryptingDemuxerStream::SetDecryptor));
65 void DecryptingDemuxerStream::Read(const ReadCB& read_cb) {
66 DVLOG(3) << "Read()";
67 DCHECK(message_loop_->BelongsToCurrentThread());
68 DCHECK_EQ(state_, kIdle) << state_;
69 DCHECK(!read_cb.is_null());
70 CHECK(read_cb_.is_null()) << "Overlapping reads are not supported.";
72 read_cb_ = read_cb;
73 state_ = kPendingDemuxerRead;
74 demuxer_stream_->Read(
75 base::Bind(&DecryptingDemuxerStream::DecryptBuffer, weak_this_));
78 void DecryptingDemuxerStream::Reset(const base::Closure& closure) {
79 DVLOG(2) << "Reset() - state: " << state_;
80 DCHECK(message_loop_->BelongsToCurrentThread());
81 DCHECK(state_ != kUninitialized && state_ != kDecryptorRequested) << state_;
82 DCHECK(init_cb_.is_null()); // No Reset() during pending initialization.
83 DCHECK(reset_cb_.is_null());
85 reset_cb_ = BindToCurrentLoop(closure);
87 decryptor_->CancelDecrypt(GetDecryptorStreamType());
89 // Reset() cannot complete if the read callback is still pending.
90 // Defer the resetting process in this case. The |reset_cb_| will be fired
91 // after the read callback is fired - see DoDecryptBuffer() and
92 // DoDeliverBuffer().
93 if (state_ == kPendingDemuxerRead || state_ == kPendingDecrypt) {
94 DCHECK(!read_cb_.is_null());
95 return;
98 if (state_ == kWaitingForKey) {
99 DCHECK(!read_cb_.is_null());
100 pending_buffer_to_decrypt_ = NULL;
101 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL);
104 DCHECK(read_cb_.is_null());
105 DoReset();
108 AudioDecoderConfig DecryptingDemuxerStream::audio_decoder_config() {
109 DCHECK(state_ != kUninitialized && state_ != kDecryptorRequested) << state_;
110 CHECK_EQ(demuxer_stream_->type(), AUDIO);
111 return audio_config_;
114 VideoDecoderConfig DecryptingDemuxerStream::video_decoder_config() {
115 DCHECK(state_ != kUninitialized && state_ != kDecryptorRequested) << state_;
116 CHECK_EQ(demuxer_stream_->type(), VIDEO);
117 return video_config_;
120 DemuxerStream::Type DecryptingDemuxerStream::type() {
121 DCHECK(state_ != kUninitialized && state_ != kDecryptorRequested) << state_;
122 return demuxer_stream_->type();
125 void DecryptingDemuxerStream::EnableBitstreamConverter() {
126 demuxer_stream_->EnableBitstreamConverter();
129 DecryptingDemuxerStream::~DecryptingDemuxerStream() {}
131 void DecryptingDemuxerStream::SetDecryptor(Decryptor* decryptor) {
132 DVLOG(2) << "SetDecryptor()";
133 DCHECK(message_loop_->BelongsToCurrentThread());
134 DCHECK_EQ(state_, kDecryptorRequested) << state_;
135 DCHECK(!init_cb_.is_null());
136 DCHECK(!set_decryptor_ready_cb_.is_null());
138 set_decryptor_ready_cb_.Reset();
140 if (!decryptor) {
141 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED);
142 state_ = kUninitialized;
143 return;
146 decryptor_ = decryptor;
148 decryptor_->RegisterNewKeyCB(
149 GetDecryptorStreamType(),
150 BIND_TO_LOOP(&DecryptingDemuxerStream::OnKeyAdded));
152 state_ = kIdle;
153 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK);
156 void DecryptingDemuxerStream::DecryptBuffer(
157 DemuxerStream::Status status,
158 const scoped_refptr<DecoderBuffer>& buffer) {
159 DVLOG(3) << "DecryptBuffer()";
160 DCHECK(message_loop_->BelongsToCurrentThread());
161 DCHECK_EQ(state_, kPendingDemuxerRead) << state_;
162 DCHECK(!read_cb_.is_null());
163 DCHECK_EQ(buffer.get() != NULL, status == kOk) << status;
165 if (!reset_cb_.is_null()) {
166 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL);
167 DoReset();
168 return;
171 if (status == kAborted) {
172 DVLOG(2) << "DoDecryptBuffer() - kAborted.";
173 state_ = kIdle;
174 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL);
175 return;
178 if (status == kConfigChanged) {
179 DVLOG(2) << "DoDecryptBuffer() - kConfigChanged.";
180 DCHECK_EQ(demuxer_stream_->type() == AUDIO, audio_config_.IsValidConfig());
181 DCHECK_EQ(demuxer_stream_->type() == VIDEO, video_config_.IsValidConfig());
183 // Update the decoder config, which the decoder will use when it is notified
184 // of kConfigChanged.
185 InitializeDecoderConfig();
186 state_ = kIdle;
187 base::ResetAndReturn(&read_cb_).Run(kConfigChanged, NULL);
188 return;
191 if (buffer->end_of_stream()) {
192 DVLOG(2) << "DoDecryptBuffer() - EOS buffer.";
193 state_ = kIdle;
194 base::ResetAndReturn(&read_cb_).Run(status, buffer);
195 return;
198 pending_buffer_to_decrypt_ = buffer;
199 state_ = kPendingDecrypt;
200 DecryptPendingBuffer();
203 void DecryptingDemuxerStream::DecryptPendingBuffer() {
204 DCHECK(message_loop_->BelongsToCurrentThread());
205 DCHECK_EQ(state_, kPendingDecrypt) << state_;
206 decryptor_->Decrypt(
207 GetDecryptorStreamType(),
208 pending_buffer_to_decrypt_,
209 BIND_TO_LOOP(&DecryptingDemuxerStream::DeliverBuffer));
212 void DecryptingDemuxerStream::DeliverBuffer(
213 Decryptor::Status status,
214 const scoped_refptr<DecoderBuffer>& decrypted_buffer) {
215 DVLOG(3) << "DeliverBuffer() - status: " << status;
216 DCHECK(message_loop_->BelongsToCurrentThread());
217 DCHECK_EQ(state_, kPendingDecrypt) << state_;
218 DCHECK_NE(status, Decryptor::kNeedMoreData);
219 DCHECK(!read_cb_.is_null());
220 DCHECK(pending_buffer_to_decrypt_.get());
222 bool need_to_try_again_if_nokey = key_added_while_decrypt_pending_;
223 key_added_while_decrypt_pending_ = false;
225 if (!reset_cb_.is_null()) {
226 pending_buffer_to_decrypt_ = NULL;
227 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL);
228 DoReset();
229 return;
232 DCHECK_EQ(status == Decryptor::kSuccess, decrypted_buffer.get() != NULL);
234 if (status == Decryptor::kError) {
235 DVLOG(2) << "DoDeliverBuffer() - kError";
236 pending_buffer_to_decrypt_ = NULL;
237 state_ = kIdle;
238 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL);
239 return;
242 if (status == Decryptor::kNoKey) {
243 DVLOG(2) << "DoDeliverBuffer() - kNoKey";
244 if (need_to_try_again_if_nokey) {
245 // The |state_| is still kPendingDecrypt.
246 DecryptPendingBuffer();
247 return;
250 state_ = kWaitingForKey;
251 return;
254 DCHECK_EQ(status, Decryptor::kSuccess);
255 pending_buffer_to_decrypt_ = NULL;
256 state_ = kIdle;
257 base::ResetAndReturn(&read_cb_).Run(kOk, decrypted_buffer);
260 void DecryptingDemuxerStream::OnKeyAdded() {
261 DCHECK(message_loop_->BelongsToCurrentThread());
263 if (state_ == kPendingDecrypt) {
264 key_added_while_decrypt_pending_ = true;
265 return;
268 if (state_ == kWaitingForKey) {
269 state_ = kPendingDecrypt;
270 DecryptPendingBuffer();
274 void DecryptingDemuxerStream::DoReset() {
275 DCHECK(init_cb_.is_null());
276 DCHECK(read_cb_.is_null());
277 state_ = kIdle;
278 base::ResetAndReturn(&reset_cb_).Run();
281 Decryptor::StreamType DecryptingDemuxerStream::GetDecryptorStreamType() const {
282 if (demuxer_stream_->type() == AUDIO)
283 return Decryptor::kAudio;
285 DCHECK_EQ(demuxer_stream_->type(), VIDEO);
286 return Decryptor::kVideo;
289 void DecryptingDemuxerStream::InitializeDecoderConfig() {
290 // The decoder selector or upstream demuxer make sure the stream is valid and
291 // potentially encrypted.
292 DCHECK(IsStreamValidAndEncrypted(demuxer_stream_));
294 switch (demuxer_stream_->type()) {
295 case AUDIO: {
296 AudioDecoderConfig input_audio_config =
297 demuxer_stream_->audio_decoder_config();
298 audio_config_.Initialize(input_audio_config.codec(),
299 input_audio_config.sample_format(),
300 input_audio_config.channel_layout(),
301 input_audio_config.samples_per_second(),
302 input_audio_config.extra_data(),
303 input_audio_config.extra_data_size(),
304 false, // Output audio is not encrypted.
305 false);
306 break;
309 case VIDEO: {
310 VideoDecoderConfig input_video_config =
311 demuxer_stream_->video_decoder_config();
312 video_config_.Initialize(input_video_config.codec(),
313 input_video_config.profile(),
314 input_video_config.format(),
315 input_video_config.coded_size(),
316 input_video_config.visible_rect(),
317 input_video_config.natural_size(),
318 input_video_config.extra_data(),
319 input_video_config.extra_data_size(),
320 false, // Output video is not encrypted.
321 false);
322 break;
325 default:
326 NOTREACHED();
327 return;
331 } // namespace media