Fix Mac GN build
[chromium-blink-merge.git] / media / filters / decrypting_demuxer_stream.cc
blob7a6f43ce797854d65faf80280956a061fa244efc
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 const base::Closure& waiting_for_decryption_key_cb)
35 : task_runner_(task_runner),
36 state_(kUninitialized),
37 waiting_for_decryption_key_cb_(waiting_for_decryption_key_cb),
38 demuxer_stream_(NULL),
39 set_decryptor_ready_cb_(set_decryptor_ready_cb),
40 decryptor_(NULL),
41 key_added_while_decrypt_pending_(false),
42 weak_factory_(this) {
45 void DecryptingDemuxerStream::Initialize(DemuxerStream* stream,
46 const PipelineStatusCB& status_cb) {
47 DVLOG(2) << __FUNCTION__;
48 DCHECK(task_runner_->BelongsToCurrentThread());
49 DCHECK_EQ(state_, kUninitialized) << state_;
51 DCHECK(!demuxer_stream_);
52 weak_this_ = weak_factory_.GetWeakPtr();
53 demuxer_stream_ = stream;
54 init_cb_ = BindToCurrentLoop(status_cb);
56 InitializeDecoderConfig();
58 state_ = kDecryptorRequested;
59 set_decryptor_ready_cb_.Run(BindToCurrentLoop(
60 base::Bind(&DecryptingDemuxerStream::SetDecryptor, weak_this_)));
63 void DecryptingDemuxerStream::Read(const ReadCB& read_cb) {
64 DVLOG(3) << __FUNCTION__;
65 DCHECK(task_runner_->BelongsToCurrentThread());
66 DCHECK_EQ(state_, kIdle) << state_;
67 DCHECK(!read_cb.is_null());
68 CHECK(read_cb_.is_null()) << "Overlapping reads are not supported.";
70 read_cb_ = BindToCurrentLoop(read_cb);
71 state_ = kPendingDemuxerRead;
72 demuxer_stream_->Read(
73 base::Bind(&DecryptingDemuxerStream::DecryptBuffer, weak_this_));
76 void DecryptingDemuxerStream::Reset(const base::Closure& closure) {
77 DVLOG(2) << __FUNCTION__ << " - state: " << state_;
78 DCHECK(task_runner_->BelongsToCurrentThread());
79 DCHECK(state_ != kUninitialized) << state_;
80 DCHECK(reset_cb_.is_null());
82 reset_cb_ = BindToCurrentLoop(closure);
84 // TODO(xhwang): This should not happen. Remove it, DCHECK against the
85 // condition and clean up related tests.
86 if (state_ == kDecryptorRequested) {
87 DCHECK(!init_cb_.is_null());
88 set_decryptor_ready_cb_.Run(DecryptorReadyCB());
89 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_ABORT);
90 DoReset();
91 return;
94 decryptor_->CancelDecrypt(GetDecryptorStreamType());
96 // Reset() cannot complete if the read callback is still pending.
97 // Defer the resetting process in this case. The |reset_cb_| will be fired
98 // after the read callback is fired - see DoDecryptBuffer() and
99 // DoDeliverBuffer().
100 if (state_ == kPendingDemuxerRead || state_ == kPendingDecrypt) {
101 DCHECK(!read_cb_.is_null());
102 return;
105 if (state_ == kWaitingForKey) {
106 DCHECK(!read_cb_.is_null());
107 pending_buffer_to_decrypt_ = NULL;
108 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL);
111 DCHECK(read_cb_.is_null());
112 DoReset();
115 AudioDecoderConfig DecryptingDemuxerStream::audio_decoder_config() {
116 DCHECK(state_ != kUninitialized && state_ != kDecryptorRequested) << state_;
117 CHECK_EQ(demuxer_stream_->type(), AUDIO);
118 return audio_config_;
121 VideoDecoderConfig DecryptingDemuxerStream::video_decoder_config() {
122 DCHECK(state_ != kUninitialized && state_ != kDecryptorRequested) << state_;
123 CHECK_EQ(demuxer_stream_->type(), VIDEO);
124 return video_config_;
127 DemuxerStream::Type DecryptingDemuxerStream::type() const {
128 DCHECK(state_ != kUninitialized && state_ != kDecryptorRequested) << state_;
129 return demuxer_stream_->type();
132 DemuxerStream::Liveness DecryptingDemuxerStream::liveness() const {
133 DCHECK(state_ != kUninitialized && state_ != kDecryptorRequested) << state_;
134 return demuxer_stream_->liveness();
137 void DecryptingDemuxerStream::EnableBitstreamConverter() {
138 demuxer_stream_->EnableBitstreamConverter();
141 bool DecryptingDemuxerStream::SupportsConfigChanges() {
142 return demuxer_stream_->SupportsConfigChanges();
145 VideoRotation DecryptingDemuxerStream::video_rotation() {
146 return VIDEO_ROTATION_0;
149 DecryptingDemuxerStream::~DecryptingDemuxerStream() {
150 DVLOG(2) << __FUNCTION__ << " : state_ = " << state_;
151 DCHECK(task_runner_->BelongsToCurrentThread());
153 if (state_ == kUninitialized)
154 return;
156 if (decryptor_) {
157 decryptor_->CancelDecrypt(GetDecryptorStreamType());
158 decryptor_ = NULL;
160 if (!set_decryptor_ready_cb_.is_null())
161 base::ResetAndReturn(&set_decryptor_ready_cb_).Run(DecryptorReadyCB());
162 if (!init_cb_.is_null())
163 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_ABORT);
164 if (!read_cb_.is_null())
165 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL);
166 if (!reset_cb_.is_null())
167 base::ResetAndReturn(&reset_cb_).Run();
168 pending_buffer_to_decrypt_ = NULL;
171 void DecryptingDemuxerStream::SetDecryptor(
172 Decryptor* decryptor,
173 const DecryptorAttachedCB& decryptor_attached_cb) {
174 DVLOG(2) << __FUNCTION__;
175 DCHECK(task_runner_->BelongsToCurrentThread());
176 DCHECK_EQ(state_, kDecryptorRequested) << state_;
177 DCHECK(!init_cb_.is_null());
178 DCHECK(!set_decryptor_ready_cb_.is_null());
180 set_decryptor_ready_cb_.Reset();
182 if (!decryptor) {
183 state_ = kUninitialized;
184 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED);
185 decryptor_attached_cb.Run(false);
186 return;
189 decryptor_ = decryptor;
191 decryptor_->RegisterNewKeyCB(
192 GetDecryptorStreamType(),
193 BindToCurrentLoop(
194 base::Bind(&DecryptingDemuxerStream::OnKeyAdded, weak_this_)));
196 state_ = kIdle;
197 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK);
198 decryptor_attached_cb.Run(true);
201 void DecryptingDemuxerStream::DecryptBuffer(
202 DemuxerStream::Status status,
203 const scoped_refptr<DecoderBuffer>& buffer) {
204 DVLOG(3) << __FUNCTION__;
205 DCHECK(task_runner_->BelongsToCurrentThread());
206 DCHECK_EQ(state_, kPendingDemuxerRead) << state_;
207 DCHECK(!read_cb_.is_null());
208 DCHECK_EQ(buffer.get() != NULL, status == kOk) << status;
210 // Even when |!reset_cb_.is_null()|, we need to pass |kConfigChanged| back to
211 // the caller so that the downstream decoder can be properly reinitialized.
212 if (status == kConfigChanged) {
213 DVLOG(2) << "DoDecryptBuffer() - kConfigChanged.";
214 DCHECK_EQ(demuxer_stream_->type() == AUDIO, audio_config_.IsValidConfig());
215 DCHECK_EQ(demuxer_stream_->type() == VIDEO, video_config_.IsValidConfig());
217 // Update the decoder config, which the decoder will use when it is notified
218 // of kConfigChanged.
219 InitializeDecoderConfig();
220 state_ = kIdle;
221 base::ResetAndReturn(&read_cb_).Run(kConfigChanged, NULL);
222 if (!reset_cb_.is_null())
223 DoReset();
224 return;
227 if (!reset_cb_.is_null()) {
228 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL);
229 DoReset();
230 return;
233 if (status == kAborted) {
234 DVLOG(2) << "DoDecryptBuffer() - kAborted.";
235 state_ = kIdle;
236 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL);
237 return;
240 if (buffer->end_of_stream()) {
241 DVLOG(2) << "DoDecryptBuffer() - EOS buffer.";
242 state_ = kIdle;
243 base::ResetAndReturn(&read_cb_).Run(status, buffer);
244 return;
247 DCHECK(buffer->decrypt_config());
248 // An empty iv string signals that the frame is unencrypted.
249 if (buffer->decrypt_config()->iv().empty()) {
250 DVLOG(2) << "DoDecryptBuffer() - clear buffer.";
251 scoped_refptr<DecoderBuffer> decrypted = DecoderBuffer::CopyFrom(
252 buffer->data(), buffer->data_size());
253 decrypted->set_timestamp(buffer->timestamp());
254 decrypted->set_duration(buffer->duration());
255 if (buffer->is_key_frame())
256 decrypted->set_is_key_frame(true);
258 state_ = kIdle;
259 base::ResetAndReturn(&read_cb_).Run(kOk, decrypted);
260 return;
263 pending_buffer_to_decrypt_ = buffer;
264 state_ = kPendingDecrypt;
265 DecryptPendingBuffer();
268 void DecryptingDemuxerStream::DecryptPendingBuffer() {
269 DCHECK(task_runner_->BelongsToCurrentThread());
270 DCHECK_EQ(state_, kPendingDecrypt) << state_;
271 decryptor_->Decrypt(
272 GetDecryptorStreamType(),
273 pending_buffer_to_decrypt_,
274 BindToCurrentLoop(
275 base::Bind(&DecryptingDemuxerStream::DeliverBuffer, weak_this_)));
278 void DecryptingDemuxerStream::DeliverBuffer(
279 Decryptor::Status status,
280 const scoped_refptr<DecoderBuffer>& decrypted_buffer) {
281 DVLOG(3) << __FUNCTION__ << " - status: " << status;
282 DCHECK(task_runner_->BelongsToCurrentThread());
283 DCHECK_EQ(state_, kPendingDecrypt) << state_;
284 DCHECK_NE(status, Decryptor::kNeedMoreData);
285 DCHECK(!read_cb_.is_null());
286 DCHECK(pending_buffer_to_decrypt_.get());
288 bool need_to_try_again_if_nokey = key_added_while_decrypt_pending_;
289 key_added_while_decrypt_pending_ = false;
291 if (!reset_cb_.is_null()) {
292 pending_buffer_to_decrypt_ = NULL;
293 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL);
294 DoReset();
295 return;
298 DCHECK_EQ(status == Decryptor::kSuccess, decrypted_buffer.get() != NULL);
300 if (status == Decryptor::kError) {
301 DVLOG(2) << "DoDeliverBuffer() - kError";
302 pending_buffer_to_decrypt_ = NULL;
303 state_ = kIdle;
304 base::ResetAndReturn(&read_cb_).Run(kAborted, NULL);
305 return;
308 if (status == Decryptor::kNoKey) {
309 DVLOG(2) << "DoDeliverBuffer() - kNoKey";
310 if (need_to_try_again_if_nokey) {
311 // The |state_| is still kPendingDecrypt.
312 DecryptPendingBuffer();
313 return;
316 state_ = kWaitingForKey;
317 waiting_for_decryption_key_cb_.Run();
318 return;
321 DCHECK_EQ(status, Decryptor::kSuccess);
323 // Copy the key frame flag from the encrypted to decrypted buffer, assuming
324 // that the decryptor initialized the flag to false.
325 if (pending_buffer_to_decrypt_->is_key_frame())
326 decrypted_buffer->set_is_key_frame(true);
328 pending_buffer_to_decrypt_ = NULL;
329 state_ = kIdle;
330 base::ResetAndReturn(&read_cb_).Run(kOk, decrypted_buffer);
333 void DecryptingDemuxerStream::OnKeyAdded() {
334 DCHECK(task_runner_->BelongsToCurrentThread());
336 if (state_ == kPendingDecrypt) {
337 key_added_while_decrypt_pending_ = true;
338 return;
341 if (state_ == kWaitingForKey) {
342 state_ = kPendingDecrypt;
343 DecryptPendingBuffer();
347 void DecryptingDemuxerStream::DoReset() {
348 DCHECK(state_ != kUninitialized);
349 DCHECK(init_cb_.is_null());
350 DCHECK(read_cb_.is_null());
352 if (state_ == kDecryptorRequested)
353 state_ = kUninitialized;
354 else
355 state_ = kIdle;
357 base::ResetAndReturn(&reset_cb_).Run();
360 Decryptor::StreamType DecryptingDemuxerStream::GetDecryptorStreamType() const {
361 if (demuxer_stream_->type() == AUDIO)
362 return Decryptor::kAudio;
364 DCHECK_EQ(demuxer_stream_->type(), VIDEO);
365 return Decryptor::kVideo;
368 void DecryptingDemuxerStream::InitializeDecoderConfig() {
369 // The decoder selector or upstream demuxer make sure the stream is valid and
370 // potentially encrypted.
371 DCHECK(IsStreamValidAndEncrypted(demuxer_stream_));
373 switch (demuxer_stream_->type()) {
374 case AUDIO: {
375 AudioDecoderConfig input_audio_config =
376 demuxer_stream_->audio_decoder_config();
377 audio_config_.Initialize(input_audio_config.codec(),
378 input_audio_config.sample_format(),
379 input_audio_config.channel_layout(),
380 input_audio_config.samples_per_second(),
381 input_audio_config.extra_data(),
382 input_audio_config.extra_data_size(),
383 false, // Output audio is not encrypted.
384 false,
385 input_audio_config.seek_preroll(),
386 input_audio_config.codec_delay());
387 break;
390 case VIDEO: {
391 VideoDecoderConfig input_video_config =
392 demuxer_stream_->video_decoder_config();
393 video_config_.Initialize(input_video_config.codec(),
394 input_video_config.profile(),
395 input_video_config.format(),
396 input_video_config.coded_size(),
397 input_video_config.visible_rect(),
398 input_video_config.natural_size(),
399 input_video_config.extra_data(),
400 input_video_config.extra_data_size(),
401 false, // Output video is not encrypted.
402 false);
403 break;
406 default:
407 NOTREACHED();
408 return;
412 } // namespace media