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