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