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. 4 5#include "media/filters/decrypting_video_decoder.h" 6 7#include "base/bind.h" 8#include "base/callback_helpers.h" 9#include "base/debug/trace_event.h" 10#include "base/location.h" 11#include "base/logging.h" 12#include "base/single_thread_task_runner.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/pipeline.h" 17#include "media/base/video_decoder_config.h" 18#include "media/base/video_frame.h" 19 20namespace media { 21 22DecryptingVideoDecoder::DecryptingVideoDecoder( 23 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner, 24 const SetDecryptorReadyCB& set_decryptor_ready_cb) 25 : task_runner_(task_runner), 26 state_(kUninitialized), 27 set_decryptor_ready_cb_(set_decryptor_ready_cb), 28 decryptor_(NULL), 29 key_added_while_decode_pending_(false), 30 trace_id_(0), 31 weak_factory_(this) {} 32 33std::string DecryptingVideoDecoder::GetDisplayName() const { 34 return "DecryptingVideoDecoder"; 35} 36 37void DecryptingVideoDecoder::Initialize(const VideoDecoderConfig& config, 38 bool /* low_delay */, 39 const PipelineStatusCB& status_cb, 40 const OutputCB& output_cb) { 41 DVLOG(2) << "Initialize()"; 42 DCHECK(task_runner_->BelongsToCurrentThread()); 43 DCHECK(state_ == kUninitialized || 44 state_ == kIdle || 45 state_ == kDecodeFinished) << state_; 46 DCHECK(decode_cb_.is_null()); 47 DCHECK(reset_cb_.is_null()); 48 DCHECK(config.IsValidConfig()); 49 DCHECK(config.is_encrypted()); 50 51 init_cb_ = BindToCurrentLoop(status_cb); 52 output_cb_ = BindToCurrentLoop(output_cb); 53 weak_this_ = weak_factory_.GetWeakPtr(); 54 config_ = config; 55 56 if (state_ == kUninitialized) { 57 state_ = kDecryptorRequested; 58 set_decryptor_ready_cb_.Run(BindToCurrentLoop(base::Bind( 59 &DecryptingVideoDecoder::SetDecryptor, weak_this_))); 60 return; 61 } 62 63 // Reinitialization. 64 decryptor_->DeinitializeDecoder(Decryptor::kVideo); 65 state_ = kPendingDecoderInit; 66 decryptor_->InitializeVideoDecoder(config, BindToCurrentLoop(base::Bind( 67 &DecryptingVideoDecoder::FinishInitialization, weak_this_))); 68} 69 70void DecryptingVideoDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer, 71 const DecodeCB& decode_cb) { 72 DVLOG(3) << "Decode()"; 73 DCHECK(task_runner_->BelongsToCurrentThread()); 74 DCHECK(state_ == kIdle || 75 state_ == kDecodeFinished || 76 state_ == kError) << state_; 77 DCHECK(!decode_cb.is_null()); 78 CHECK(decode_cb_.is_null()) << "Overlapping decodes are not supported."; 79 80 decode_cb_ = BindToCurrentLoop(decode_cb); 81 82 if (state_ == kError) { 83 base::ResetAndReturn(&decode_cb_).Run(kDecodeError); 84 return; 85 } 86 87 // Return empty frames if decoding has finished. 88 if (state_ == kDecodeFinished) { 89 base::ResetAndReturn(&decode_cb_).Run(kOk); 90 return; 91 } 92 93 pending_buffer_to_decode_ = buffer; 94 state_ = kPendingDecode; 95 DecodePendingBuffer(); 96} 97 98void DecryptingVideoDecoder::Reset(const base::Closure& closure) { 99 DVLOG(2) << "Reset() - state: " << state_; 100 DCHECK(task_runner_->BelongsToCurrentThread()); 101 DCHECK(state_ == kIdle || 102 state_ == kPendingDecode || 103 state_ == kWaitingForKey || 104 state_ == kDecodeFinished || 105 state_ == kError) << state_; 106 DCHECK(init_cb_.is_null()); // No Reset() during pending initialization. 107 DCHECK(reset_cb_.is_null()); 108 109 reset_cb_ = BindToCurrentLoop(closure); 110 111 decryptor_->ResetDecoder(Decryptor::kVideo); 112 113 // Reset() cannot complete if the decode callback is still pending. 114 // Defer the resetting process in this case. The |reset_cb_| will be fired 115 // after the decode callback is fired - see DecryptAndDecodeBuffer() and 116 // DeliverFrame(). 117 if (state_ == kPendingDecode) { 118 DCHECK(!decode_cb_.is_null()); 119 return; 120 } 121 122 if (state_ == kWaitingForKey) { 123 DCHECK(!decode_cb_.is_null()); 124 pending_buffer_to_decode_ = NULL; 125 base::ResetAndReturn(&decode_cb_).Run(kAborted); 126 } 127 128 DCHECK(decode_cb_.is_null()); 129 DoReset(); 130} 131 132DecryptingVideoDecoder::~DecryptingVideoDecoder() { 133 DCHECK(task_runner_->BelongsToCurrentThread()); 134 135 if (state_ == kUninitialized) 136 return; 137 138 if (decryptor_) { 139 decryptor_->DeinitializeDecoder(Decryptor::kVideo); 140 decryptor_ = NULL; 141 } 142 if (!set_decryptor_ready_cb_.is_null()) 143 base::ResetAndReturn(&set_decryptor_ready_cb_).Run(DecryptorReadyCB()); 144 pending_buffer_to_decode_ = NULL; 145 if (!init_cb_.is_null()) 146 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); 147 if (!decode_cb_.is_null()) 148 base::ResetAndReturn(&decode_cb_).Run(kAborted); 149 if (!reset_cb_.is_null()) 150 base::ResetAndReturn(&reset_cb_).Run(); 151} 152 153void DecryptingVideoDecoder::SetDecryptor( 154 Decryptor* decryptor, 155 const DecryptorAttachedCB& decryptor_attached_cb) { 156 DVLOG(2) << "SetDecryptor()"; 157 DCHECK(task_runner_->BelongsToCurrentThread()); 158 DCHECK_EQ(state_, kDecryptorRequested) << state_; 159 DCHECK(!init_cb_.is_null()); 160 DCHECK(!set_decryptor_ready_cb_.is_null()); 161 set_decryptor_ready_cb_.Reset(); 162 163 if (!decryptor) { 164 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); 165 state_ = kError; 166 decryptor_attached_cb.Run(false); 167 return; 168 } 169 170 decryptor_ = decryptor; 171 172 state_ = kPendingDecoderInit; 173 decryptor_->InitializeVideoDecoder( 174 config_, 175 BindToCurrentLoop(base::Bind( 176 &DecryptingVideoDecoder::FinishInitialization, weak_this_))); 177 decryptor_attached_cb.Run(true); 178} 179 180void DecryptingVideoDecoder::FinishInitialization(bool success) { 181 DVLOG(2) << "FinishInitialization()"; 182 DCHECK(task_runner_->BelongsToCurrentThread()); 183 DCHECK_EQ(state_, kPendingDecoderInit) << state_; 184 DCHECK(!init_cb_.is_null()); 185 DCHECK(reset_cb_.is_null()); // No Reset() before initialization finished. 186 DCHECK(decode_cb_.is_null()); // No Decode() before initialization finished. 187 188 if (!success) { 189 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED); 190 decryptor_ = NULL; 191 state_ = kError; 192 return; 193 } 194 195 decryptor_->RegisterNewKeyCB( 196 Decryptor::kVideo, 197 BindToCurrentLoop( 198 base::Bind(&DecryptingVideoDecoder::OnKeyAdded, weak_this_))); 199 200 // Success! 201 state_ = kIdle; 202 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK); 203} 204 205 206void DecryptingVideoDecoder::DecodePendingBuffer() { 207 DCHECK(task_runner_->BelongsToCurrentThread()); 208 DCHECK_EQ(state_, kPendingDecode) << state_; 209 TRACE_EVENT_ASYNC_BEGIN0( 210 "media", "DecryptingVideoDecoder::DecodePendingBuffer", ++trace_id_); 211 212 int buffer_size = 0; 213 if (!pending_buffer_to_decode_->end_of_stream()) { 214 buffer_size = pending_buffer_to_decode_->data_size(); 215 } 216 217 decryptor_->DecryptAndDecodeVideo( 218 pending_buffer_to_decode_, BindToCurrentLoop(base::Bind( 219 &DecryptingVideoDecoder::DeliverFrame, weak_this_, buffer_size))); 220} 221 222void DecryptingVideoDecoder::DeliverFrame( 223 int buffer_size, 224 Decryptor::Status status, 225 const scoped_refptr<VideoFrame>& frame) { 226 DVLOG(3) << "DeliverFrame() - status: " << status; 227 DCHECK(task_runner_->BelongsToCurrentThread()); 228 DCHECK_EQ(state_, kPendingDecode) << state_; 229 DCHECK(!decode_cb_.is_null()); 230 DCHECK(pending_buffer_to_decode_.get()); 231 232 TRACE_EVENT_ASYNC_END2( 233 "media", "DecryptingVideoDecoder::DecodePendingBuffer", trace_id_, 234 "buffer_size", buffer_size, "status", status); 235 236 bool need_to_try_again_if_nokey_is_returned = key_added_while_decode_pending_; 237 key_added_while_decode_pending_ = false; 238 239 scoped_refptr<DecoderBuffer> scoped_pending_buffer_to_decode = 240 pending_buffer_to_decode_; 241 pending_buffer_to_decode_ = NULL; 242 243 if (!reset_cb_.is_null()) { 244 base::ResetAndReturn(&decode_cb_).Run(kAborted); 245 DoReset(); 246 return; 247 } 248 249 DCHECK_EQ(status == Decryptor::kSuccess, frame.get() != NULL); 250 251 if (status == Decryptor::kError) { 252 DVLOG(2) << "DeliverFrame() - kError"; 253 state_ = kError; 254 base::ResetAndReturn(&decode_cb_).Run(kDecodeError); 255 return; 256 } 257 258 if (status == Decryptor::kNoKey) { 259 DVLOG(2) << "DeliverFrame() - kNoKey"; 260 // Set |pending_buffer_to_decode_| back as we need to try decoding the 261 // pending buffer again when new key is added to the decryptor. 262 pending_buffer_to_decode_ = scoped_pending_buffer_to_decode; 263 264 if (need_to_try_again_if_nokey_is_returned) { 265 // The |state_| is still kPendingDecode. 266 DecodePendingBuffer(); 267 return; 268 } 269 270 state_ = kWaitingForKey; 271 return; 272 } 273 274 if (status == Decryptor::kNeedMoreData) { 275 DVLOG(2) << "DeliverFrame() - kNeedMoreData"; 276 state_ = scoped_pending_buffer_to_decode->end_of_stream() ? kDecodeFinished 277 : kIdle; 278 base::ResetAndReturn(&decode_cb_).Run(kOk); 279 return; 280 } 281 282 DCHECK_EQ(status, Decryptor::kSuccess); 283 // No frame returned with kSuccess should be end-of-stream frame. 284 DCHECK(!frame->end_of_stream()); 285 output_cb_.Run(frame); 286 287 if (scoped_pending_buffer_to_decode->end_of_stream()) { 288 // Set |pending_buffer_to_decode_| back as we need to keep flushing the 289 // decryptor. 290 pending_buffer_to_decode_ = scoped_pending_buffer_to_decode; 291 DecodePendingBuffer(); 292 return; 293 } 294 295 state_ = kIdle; 296 base::ResetAndReturn(&decode_cb_).Run(kOk); 297} 298 299void DecryptingVideoDecoder::OnKeyAdded() { 300 DVLOG(2) << "OnKeyAdded()"; 301 DCHECK(task_runner_->BelongsToCurrentThread()); 302 303 if (state_ == kPendingDecode) { 304 key_added_while_decode_pending_ = true; 305 return; 306 } 307 308 if (state_ == kWaitingForKey) { 309 state_ = kPendingDecode; 310 DecodePendingBuffer(); 311 } 312} 313 314void DecryptingVideoDecoder::DoReset() { 315 DCHECK(init_cb_.is_null()); 316 DCHECK(decode_cb_.is_null()); 317 state_ = kIdle; 318 base::ResetAndReturn(&reset_cb_).Run(); 319} 320 321} // namespace media 322