Move key frame flag from StreamParserBuffer to DecoderBuffer
[chromium-blink-merge.git] / media / filters / decrypting_demuxer_stream.cc
blob2eae710d1fa7503a8785e7881ae920fd02253494
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/single_thread_task_runner.h"
12 #include "media/base/audio_decoder_config.h"
13 #include "media/base/bind_to_current_loop.h"
14 #include "media/base/decoder_buffer.h"
15 #include "media/base/decryptor.h"
16 #include "media/base/demuxer_stream.h"
17 #include "media/base/pipeline.h"
18 #include "media/base/video_decoder_config.h"
20 namespace media {
22 static bool IsStreamValidAndEncrypted(DemuxerStream* stream) {
23 return ((stream->type() == DemuxerStream::AUDIO &&
24 stream->audio_decoder_config().IsValidConfig() &&
25 stream->audio_decoder_config().is_encrypted()) ||
26 (stream->type() == DemuxerStream::VIDEO &&
27 stream->video_decoder_config().IsValidConfig() &&
28 stream->video_decoder_config().is_encrypted()));
31 DecryptingDemuxerStream::DecryptingDemuxerStream(
32 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
33 const SetDecryptorReadyCB& set_decryptor_ready_cb)
34 : task_runner_(task_runner),
35 state_(kUninitialized),
36 demuxer_stream_(NULL),
37 set_decryptor_ready_cb_(set_decryptor_ready_cb),
38 decryptor_(NULL),
39 key_added_while_decrypt_pending_(false),
40 weak_factory_(this) {}
42 void DecryptingDemuxerStream::Initialize(DemuxerStream* stream,
43 const PipelineStatusCB& status_cb) {
44 DVLOG(2) << __FUNCTION__;
45 DCHECK(task_runner_->BelongsToCurrentThread());
46 DCHECK_EQ(state_, kUninitialized) << state_;
48 DCHECK(!demuxer_stream_);
49 weak_this_ = weak_factory_.GetWeakPtr();
50 demuxer_stream_ = stream;
51 init_cb_ = BindToCurrentLoop(status_cb);
53 InitializeDecoderConfig();
55 state_ = kDecryptorRequested;
56 set_decryptor_ready_cb_.Run(BindToCurrentLoop(
57 base::Bind(&DecryptingDemuxerStream::SetDecryptor, weak_this_)));
60 void DecryptingDemuxerStream::Read(const ReadCB& read_cb) {
61 DVLOG(3) << __FUNCTION__;
62 DCHECK(task_runner_->BelongsToCurrentThread());
63 DCHECK_EQ(state_, kIdle) << state_;
64 DCHECK(!read_cb.is_null());
65 CHECK(read_cb_.is_null()) << "Overlapping reads are not supported.";
67 read_cb_ = BindToCurrentLoop(read_cb);
68 state_ = kPendingDemuxerRead;
69 demuxer_stream_->Read(
70 base::Bind(&DecryptingDemuxerStream::DecryptBuffer, weak_this_));
73 void DecryptingDemuxerStream::Reset(const base::Closure& closure) {
74 DVLOG(2) << __FUNCTION__ << " - state: " << state_;
75 DCHECK(task_runner_->BelongsToCurrentThread());
76 DCHECK(state_ != kUninitialized) << state_;
77 DCHECK(reset_cb_.is_null());
79 reset_cb_ = BindToCurrentLoop(closure);
81 // TODO(xhwang): This should not happen. Remove it, DCHECK against the
82 // condition and clean up related tests.
83 if (state_ == kDecryptorRequested) {
84 DCHECK(!init_cb_.is_null());
85 set_decryptor_ready_cb_.Run(DecryptorReadyCB());
86 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_ABORT);
87 DoReset();
88 return;
91 decryptor_->CancelDecrypt(GetDecryptorStreamType());
93 // Reset() cannot complete if the read callback is still pending.
94 // Defer the resetting process in this case. The |reset_cb_| will be fired
95 // after the read callback is fired - see DoDecryptBuffer() and
96 // DoDeliverBuffer().
97 if (state_ == kPendingDemuxerRead || state_ == kPendingDecrypt) {
98 DCHECK(!read_cb_.is_null());
99 return;
102 if (state_ == kWaitingForKey) {
103 DCHECK(!read_cb_.is_null());
104 pending_buffer_to_decrypt_ = NULL;
105 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL);
108 DCHECK(read_cb_.is_null());
109 DoReset();
112 AudioDecoderConfig DecryptingDemuxerStream::audio_decoder_config() {
113 DCHECK(state_ != kUninitialized && state_ != kDecryptorRequested) << state_;
114 CHECK_EQ(demuxer_stream_->type(), AUDIO);
115 return audio_config_;
118 VideoDecoderConfig DecryptingDemuxerStream::video_decoder_config() {
119 DCHECK(state_ != kUninitialized && state_ != kDecryptorRequested) << state_;
120 CHECK_EQ(demuxer_stream_->type(), VIDEO);
121 return video_config_;
124 DemuxerStream::Type DecryptingDemuxerStream::type() {
125 DCHECK(state_ != kUninitialized && state_ != kDecryptorRequested) << state_;
126 return demuxer_stream_->type();
129 void DecryptingDemuxerStream::EnableBitstreamConverter() {
130 demuxer_stream_->EnableBitstreamConverter();
133 bool DecryptingDemuxerStream::SupportsConfigChanges() {
134 return demuxer_stream_->SupportsConfigChanges();
137 VideoRotation DecryptingDemuxerStream::video_rotation() {
138 return VIDEO_ROTATION_0;
141 DecryptingDemuxerStream::~DecryptingDemuxerStream() {
142 DVLOG(2) << __FUNCTION__ << " : state_ = " << state_;
143 DCHECK(task_runner_->BelongsToCurrentThread());
145 if (state_ == kUninitialized)
146 return;
148 if (decryptor_) {
149 decryptor_->CancelDecrypt(GetDecryptorStreamType());
150 decryptor_ = NULL;
152 if (!set_decryptor_ready_cb_.is_null())
153 base::ResetAndReturn(&set_decryptor_ready_cb_).Run(DecryptorReadyCB());
154 if (!init_cb_.is_null())
155 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_ABORT);
156 if (!read_cb_.is_null())
157 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL);
158 if (!reset_cb_.is_null())
159 base::ResetAndReturn(&reset_cb_).Run();
160 pending_buffer_to_decrypt_ = NULL;
163 void DecryptingDemuxerStream::SetDecryptor(
164 Decryptor* decryptor,
165 const DecryptorAttachedCB& decryptor_attached_cb) {
166 DVLOG(2) << __FUNCTION__;
167 DCHECK(task_runner_->BelongsToCurrentThread());
168 DCHECK_EQ(state_, kDecryptorRequested) << state_;
169 DCHECK(!init_cb_.is_null());
170 DCHECK(!set_decryptor_ready_cb_.is_null());
172 set_decryptor_ready_cb_.Reset();
174 if (!decryptor) {
175 state_ = kUninitialized;
176 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED);
177 decryptor_attached_cb.Run(false);
178 return;
181 decryptor_ = decryptor;
183 decryptor_->RegisterNewKeyCB(
184 GetDecryptorStreamType(),
185 BindToCurrentLoop(
186 base::Bind(&DecryptingDemuxerStream::OnKeyAdded, weak_this_)));
188 state_ = kIdle;
189 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK);
190 decryptor_attached_cb.Run(true);
193 void DecryptingDemuxerStream::DecryptBuffer(
194 DemuxerStream::Status status,
195 const scoped_refptr<DecoderBuffer>& buffer) {
196 DVLOG(3) << __FUNCTION__;
197 DCHECK(task_runner_->BelongsToCurrentThread());
198 DCHECK_EQ(state_, kPendingDemuxerRead) << state_;
199 DCHECK(!read_cb_.is_null());
200 DCHECK_EQ(buffer.get() != NULL, status == kOk) << status;
202 // Even when |!reset_cb_.is_null()|, we need to pass |kConfigChanged| back to
203 // the caller so that the downstream decoder can be properly reinitialized.
204 if (status == kConfigChanged) {
205 DVLOG(2) << "DoDecryptBuffer() - kConfigChanged.";
206 DCHECK_EQ(demuxer_stream_->type() == AUDIO, audio_config_.IsValidConfig());
207 DCHECK_EQ(demuxer_stream_->type() == VIDEO, video_config_.IsValidConfig());
209 // Update the decoder config, which the decoder will use when it is notified
210 // of kConfigChanged.
211 InitializeDecoderConfig();
212 state_ = kIdle;
213 base::ResetAndReturn(&read_cb_).Run(kConfigChanged, NULL);
214 if (!reset_cb_.is_null())
215 DoReset();
216 return;
219 if (!reset_cb_.is_null()) {
220 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL);
221 DoReset();
222 return;
225 if (status == kAborted) {
226 DVLOG(2) << "DoDecryptBuffer() - kAborted.";
227 state_ = kIdle;
228 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL);
229 return;
232 if (buffer->end_of_stream()) {
233 DVLOG(2) << "DoDecryptBuffer() - EOS buffer.";
234 state_ = kIdle;
235 base::ResetAndReturn(&read_cb_).Run(status, buffer);
236 return;
239 DCHECK(buffer->decrypt_config());
240 // An empty iv string signals that the frame is unencrypted.
241 if (buffer->decrypt_config()->iv().empty()) {
242 DVLOG(2) << "DoDecryptBuffer() - clear buffer.";
243 scoped_refptr<DecoderBuffer> decrypted = DecoderBuffer::CopyFrom(
244 buffer->data(), buffer->data_size());
245 decrypted->set_timestamp(buffer->timestamp());
246 decrypted->set_duration(buffer->duration());
247 if (buffer->is_key_frame())
248 decrypted->set_is_key_frame(true);
250 state_ = kIdle;
251 base::ResetAndReturn(&read_cb_).Run(kOk, decrypted);
252 return;
255 pending_buffer_to_decrypt_ = buffer;
256 state_ = kPendingDecrypt;
257 DecryptPendingBuffer();
260 void DecryptingDemuxerStream::DecryptPendingBuffer() {
261 DCHECK(task_runner_->BelongsToCurrentThread());
262 DCHECK_EQ(state_, kPendingDecrypt) << state_;
263 decryptor_->Decrypt(
264 GetDecryptorStreamType(),
265 pending_buffer_to_decrypt_,
266 BindToCurrentLoop(
267 base::Bind(&DecryptingDemuxerStream::DeliverBuffer, weak_this_)));
270 void DecryptingDemuxerStream::DeliverBuffer(
271 Decryptor::Status status,
272 const scoped_refptr<DecoderBuffer>& decrypted_buffer) {
273 DVLOG(3) << __FUNCTION__ << " - status: " << status;
274 DCHECK(task_runner_->BelongsToCurrentThread());
275 DCHECK_EQ(state_, kPendingDecrypt) << state_;
276 DCHECK_NE(status, Decryptor::kNeedMoreData);
277 DCHECK(!read_cb_.is_null());
278 DCHECK(pending_buffer_to_decrypt_.get());
280 bool need_to_try_again_if_nokey = key_added_while_decrypt_pending_;
281 key_added_while_decrypt_pending_ = false;
283 if (!reset_cb_.is_null()) {
284 pending_buffer_to_decrypt_ = NULL;
285 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL);
286 DoReset();
287 return;
290 DCHECK_EQ(status == Decryptor::kSuccess, decrypted_buffer.get() != NULL);
292 if (status == Decryptor::kError) {
293 DVLOG(2) << "DoDeliverBuffer() - kError";
294 pending_buffer_to_decrypt_ = NULL;
295 state_ = kIdle;
296 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL);
297 return;
300 if (status == Decryptor::kNoKey) {
301 DVLOG(2) << "DoDeliverBuffer() - kNoKey";
302 if (need_to_try_again_if_nokey) {
303 // The |state_| is still kPendingDecrypt.
304 DecryptPendingBuffer();
305 return;
308 state_ = kWaitingForKey;
309 return;
312 DCHECK_EQ(status, Decryptor::kSuccess);
314 // Copy the key frame flag from the encrypted to decrypted buffer, assuming
315 // that the decryptor initialized the flag to false.
316 if (pending_buffer_to_decrypt_->is_key_frame())
317 decrypted_buffer->set_is_key_frame(true);
319 pending_buffer_to_decrypt_ = NULL;
320 state_ = kIdle;
321 base::ResetAndReturn(&read_cb_).Run(kOk, decrypted_buffer);
324 void DecryptingDemuxerStream::OnKeyAdded() {
325 DCHECK(task_runner_->BelongsToCurrentThread());
327 if (state_ == kPendingDecrypt) {
328 key_added_while_decrypt_pending_ = true;
329 return;
332 if (state_ == kWaitingForKey) {
333 state_ = kPendingDecrypt;
334 DecryptPendingBuffer();
338 void DecryptingDemuxerStream::DoReset() {
339 DCHECK(state_ != kUninitialized);
340 DCHECK(init_cb_.is_null());
341 DCHECK(read_cb_.is_null());
343 if (state_ == kDecryptorRequested)
344 state_ = kUninitialized;
345 else
346 state_ = kIdle;
348 base::ResetAndReturn(&reset_cb_).Run();
351 Decryptor::StreamType DecryptingDemuxerStream::GetDecryptorStreamType() const {
352 if (demuxer_stream_->type() == AUDIO)
353 return Decryptor::kAudio;
355 DCHECK_EQ(demuxer_stream_->type(), VIDEO);
356 return Decryptor::kVideo;
359 void DecryptingDemuxerStream::InitializeDecoderConfig() {
360 // The decoder selector or upstream demuxer make sure the stream is valid and
361 // potentially encrypted.
362 DCHECK(IsStreamValidAndEncrypted(demuxer_stream_));
364 switch (demuxer_stream_->type()) {
365 case AUDIO: {
366 AudioDecoderConfig input_audio_config =
367 demuxer_stream_->audio_decoder_config();
368 audio_config_.Initialize(input_audio_config.codec(),
369 input_audio_config.sample_format(),
370 input_audio_config.channel_layout(),
371 input_audio_config.samples_per_second(),
372 input_audio_config.extra_data(),
373 input_audio_config.extra_data_size(),
374 false, // Output audio is not encrypted.
375 false,
376 input_audio_config.seek_preroll(),
377 input_audio_config.codec_delay());
378 break;
381 case VIDEO: {
382 VideoDecoderConfig input_video_config =
383 demuxer_stream_->video_decoder_config();
384 video_config_.Initialize(input_video_config.codec(),
385 input_video_config.profile(),
386 input_video_config.format(),
387 input_video_config.coded_size(),
388 input_video_config.visible_rect(),
389 input_video_config.natural_size(),
390 input_video_config.extra_data(),
391 input_video_config.extra_data_size(),
392 false, // Output video is not encrypted.
393 false);
394 break;
397 default:
398 NOTREACHED();
399 return;
403 } // namespace media