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_audio_decoder.h"
6
7#include <cstdlib>
8
9#include "base/bind.h"
10#include "base/callback_helpers.h"
11#include "base/location.h"
12#include "base/logging.h"
13#include "base/single_thread_task_runner.h"
14#include "media/base/audio_buffer.h"
15#include "media/base/audio_decoder_config.h"
16#include "media/base/audio_timestamp_helper.h"
17#include "media/base/bind_to_current_loop.h"
18#include "media/base/buffers.h"
19#include "media/base/decoder_buffer.h"
20#include "media/base/decryptor.h"
21#include "media/base/demuxer_stream.h"
22#include "media/base/pipeline.h"
23
24namespace media {
25
26const int DecryptingAudioDecoder::kSupportedBitsPerChannel = 16;
27
28static inline bool IsOutOfSync(const base::TimeDelta& timestamp_1,
29                               const base::TimeDelta& timestamp_2) {
30  // Out of sync of 100ms would be pretty noticeable and we should keep any
31  // drift below that.
32  const int64 kOutOfSyncThresholdInMilliseconds = 100;
33  return std::abs(timestamp_1.InMilliseconds() - timestamp_2.InMilliseconds()) >
34         kOutOfSyncThresholdInMilliseconds;
35}
36
37DecryptingAudioDecoder::DecryptingAudioDecoder(
38    const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
39    const SetDecryptorReadyCB& set_decryptor_ready_cb)
40    : task_runner_(task_runner),
41      state_(kUninitialized),
42      set_decryptor_ready_cb_(set_decryptor_ready_cb),
43      decryptor_(NULL),
44      key_added_while_decode_pending_(false),
45      weak_factory_(this) {}
46
47std::string DecryptingAudioDecoder::GetDisplayName() const {
48  return "DecryptingAudioDecoder";
49}
50
51void DecryptingAudioDecoder::Initialize(const AudioDecoderConfig& config,
52                                        const PipelineStatusCB& status_cb,
53                                        const OutputCB& output_cb) {
54  DVLOG(2) << "Initialize()";
55  DCHECK(task_runner_->BelongsToCurrentThread());
56  DCHECK(decode_cb_.is_null());
57  DCHECK(reset_cb_.is_null());
58
59  weak_this_ = weak_factory_.GetWeakPtr();
60  init_cb_ = BindToCurrentLoop(status_cb);
61  output_cb_ = BindToCurrentLoop(output_cb);
62
63  if (!config.IsValidConfig()) {
64    DLOG(ERROR) << "Invalid audio stream config.";
65    base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_DECODE);
66    return;
67  }
68
69  // DecryptingAudioDecoder only accepts potentially encrypted stream.
70  if (!config.is_encrypted()) {
71    base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED);
72    return;
73  }
74
75  config_ = config;
76
77  if (state_ == kUninitialized) {
78    state_ = kDecryptorRequested;
79    set_decryptor_ready_cb_.Run(BindToCurrentLoop(
80        base::Bind(&DecryptingAudioDecoder::SetDecryptor, weak_this_)));
81    return;
82  }
83
84  // Reinitialization (i.e. upon a config change)
85  decryptor_->DeinitializeDecoder(Decryptor::kAudio);
86  InitializeDecoder();
87}
88
89void DecryptingAudioDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer,
90                                    const DecodeCB& decode_cb) {
91  DVLOG(3) << "Decode()";
92  DCHECK(task_runner_->BelongsToCurrentThread());
93  DCHECK(state_ == kIdle || state_ == kDecodeFinished) << state_;
94  DCHECK(!decode_cb.is_null());
95  CHECK(decode_cb_.is_null()) << "Overlapping decodes are not supported.";
96
97  decode_cb_ = BindToCurrentLoop(decode_cb);
98
99  // Return empty (end-of-stream) frames if decoding has finished.
100  if (state_ == kDecodeFinished) {
101    output_cb_.Run(AudioBuffer::CreateEOSBuffer());
102    base::ResetAndReturn(&decode_cb_).Run(kOk);
103    return;
104  }
105
106  // Initialize the |next_output_timestamp_| to be the timestamp of the first
107  // non-EOS buffer.
108  if (timestamp_helper_->base_timestamp() == kNoTimestamp() &&
109      !buffer->end_of_stream()) {
110    timestamp_helper_->SetBaseTimestamp(buffer->timestamp());
111  }
112
113  pending_buffer_to_decode_ = buffer;
114  state_ = kPendingDecode;
115  DecodePendingBuffer();
116}
117
118void DecryptingAudioDecoder::Reset(const base::Closure& closure) {
119  DVLOG(2) << "Reset() - state: " << state_;
120  DCHECK(task_runner_->BelongsToCurrentThread());
121  DCHECK(state_ == kIdle ||
122         state_ == kPendingDecode ||
123         state_ == kWaitingForKey ||
124         state_ == kDecodeFinished) << state_;
125  DCHECK(init_cb_.is_null());  // No Reset() during pending initialization.
126  DCHECK(reset_cb_.is_null());
127
128  reset_cb_ = BindToCurrentLoop(closure);
129
130  decryptor_->ResetDecoder(Decryptor::kAudio);
131
132  // Reset() cannot complete if the read callback is still pending.
133  // Defer the resetting process in this case. The |reset_cb_| will be fired
134  // after the read callback is fired - see DecryptAndDecodeBuffer() and
135  // DeliverFrame().
136  if (state_ == kPendingDecode) {
137    DCHECK(!decode_cb_.is_null());
138    return;
139  }
140
141  if (state_ == kWaitingForKey) {
142    DCHECK(!decode_cb_.is_null());
143    pending_buffer_to_decode_ = NULL;
144    base::ResetAndReturn(&decode_cb_).Run(kAborted);
145  }
146
147  DCHECK(decode_cb_.is_null());
148  DoReset();
149}
150
151DecryptingAudioDecoder::~DecryptingAudioDecoder() {
152  DVLOG(2) << __FUNCTION__;
153  DCHECK(task_runner_->BelongsToCurrentThread());
154
155  if (state_ == kUninitialized)
156    return;
157
158  if (decryptor_) {
159    decryptor_->DeinitializeDecoder(Decryptor::kAudio);
160    decryptor_ = NULL;
161  }
162  if (!set_decryptor_ready_cb_.is_null())
163    base::ResetAndReturn(&set_decryptor_ready_cb_).Run(DecryptorReadyCB());
164  pending_buffer_to_decode_ = NULL;
165  if (!init_cb_.is_null())
166    base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED);
167  if (!decode_cb_.is_null())
168    base::ResetAndReturn(&decode_cb_).Run(kAborted);
169  if (!reset_cb_.is_null())
170    base::ResetAndReturn(&reset_cb_).Run();
171}
172
173void DecryptingAudioDecoder::SetDecryptor(
174    Decryptor* decryptor,
175    const DecryptorAttachedCB& decryptor_attached_cb) {
176  DVLOG(2) << "SetDecryptor()";
177  DCHECK(task_runner_->BelongsToCurrentThread());
178  DCHECK_EQ(state_, kDecryptorRequested) << state_;
179  DCHECK(!init_cb_.is_null());
180  DCHECK(!set_decryptor_ready_cb_.is_null());
181
182  set_decryptor_ready_cb_.Reset();
183
184  if (!decryptor) {
185    base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED);
186    state_ = kError;
187    decryptor_attached_cb.Run(false);
188    return;
189  }
190
191  decryptor_ = decryptor;
192
193  InitializeDecoder();
194  decryptor_attached_cb.Run(true);
195}
196
197void DecryptingAudioDecoder::InitializeDecoder() {
198  state_ = kPendingDecoderInit;
199  decryptor_->InitializeAudioDecoder(
200      config_,
201      BindToCurrentLoop(base::Bind(
202          &DecryptingAudioDecoder::FinishInitialization, weak_this_)));
203}
204
205void DecryptingAudioDecoder::FinishInitialization(bool success) {
206  DVLOG(2) << "FinishInitialization()";
207  DCHECK(task_runner_->BelongsToCurrentThread());
208  DCHECK(state_ == kPendingDecoderInit) << state_;
209  DCHECK(!init_cb_.is_null());
210  DCHECK(reset_cb_.is_null());  // No Reset() before initialization finished.
211  DCHECK(decode_cb_.is_null());  // No Decode() before initialization finished.
212
213  if (!success) {
214    base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED);
215    decryptor_ = NULL;
216    state_ = kError;
217    return;
218  }
219
220  // Success!
221  timestamp_helper_.reset(
222      new AudioTimestampHelper(config_.samples_per_second()));
223
224  decryptor_->RegisterNewKeyCB(
225      Decryptor::kAudio,
226      BindToCurrentLoop(
227          base::Bind(&DecryptingAudioDecoder::OnKeyAdded, weak_this_)));
228
229  state_ = kIdle;
230  base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK);
231}
232
233void DecryptingAudioDecoder::DecodePendingBuffer() {
234  DCHECK(task_runner_->BelongsToCurrentThread());
235  DCHECK_EQ(state_, kPendingDecode) << state_;
236
237  int buffer_size = 0;
238  if (!pending_buffer_to_decode_->end_of_stream()) {
239    buffer_size = pending_buffer_to_decode_->data_size();
240  }
241
242  decryptor_->DecryptAndDecodeAudio(
243      pending_buffer_to_decode_,
244      BindToCurrentLoop(base::Bind(
245          &DecryptingAudioDecoder::DeliverFrame, weak_this_, buffer_size)));
246}
247
248void DecryptingAudioDecoder::DeliverFrame(
249    int buffer_size,
250    Decryptor::Status status,
251    const Decryptor::AudioBuffers& frames) {
252  DVLOG(3) << "DeliverFrame() - status: " << status;
253  DCHECK(task_runner_->BelongsToCurrentThread());
254  DCHECK_EQ(state_, kPendingDecode) << state_;
255  DCHECK(!decode_cb_.is_null());
256  DCHECK(pending_buffer_to_decode_.get());
257
258  bool need_to_try_again_if_nokey_is_returned = key_added_while_decode_pending_;
259  key_added_while_decode_pending_ = false;
260
261  scoped_refptr<DecoderBuffer> scoped_pending_buffer_to_decode =
262      pending_buffer_to_decode_;
263  pending_buffer_to_decode_ = NULL;
264
265  if (!reset_cb_.is_null()) {
266    base::ResetAndReturn(&decode_cb_).Run(kAborted);
267    DoReset();
268    return;
269  }
270
271  DCHECK_EQ(status == Decryptor::kSuccess, !frames.empty());
272
273  if (status == Decryptor::kError) {
274    DVLOG(2) << "DeliverFrame() - kError";
275    state_ = kDecodeFinished; // TODO add kError state
276    base::ResetAndReturn(&decode_cb_).Run(kDecodeError);
277    return;
278  }
279
280  if (status == Decryptor::kNoKey) {
281    DVLOG(2) << "DeliverFrame() - kNoKey";
282    // Set |pending_buffer_to_decode_| back as we need to try decoding the
283    // pending buffer again when new key is added to the decryptor.
284    pending_buffer_to_decode_ = scoped_pending_buffer_to_decode;
285
286    if (need_to_try_again_if_nokey_is_returned) {
287      // The |state_| is still kPendingDecode.
288      DecodePendingBuffer();
289      return;
290    }
291
292    state_ = kWaitingForKey;
293    return;
294  }
295
296  if (status == Decryptor::kNeedMoreData) {
297    DVLOG(2) << "DeliverFrame() - kNeedMoreData";
298    state_ = scoped_pending_buffer_to_decode->end_of_stream() ? kDecodeFinished
299                                                              : kIdle;
300    base::ResetAndReturn(&decode_cb_).Run(kOk);
301    return;
302  }
303
304  DCHECK_EQ(status, Decryptor::kSuccess);
305  DCHECK(!frames.empty());
306  ProcessDecodedFrames(frames);
307
308  if (scoped_pending_buffer_to_decode->end_of_stream()) {
309    // Set |pending_buffer_to_decode_| back as we need to keep flushing the
310    // decryptor until kNeedMoreData is returned.
311    pending_buffer_to_decode_ = scoped_pending_buffer_to_decode;
312    DecodePendingBuffer();
313    return;
314  }
315
316  state_ = kIdle;
317  base::ResetAndReturn(&decode_cb_).Run(kOk);
318}
319
320void DecryptingAudioDecoder::OnKeyAdded() {
321  DCHECK(task_runner_->BelongsToCurrentThread());
322
323  if (state_ == kPendingDecode) {
324    key_added_while_decode_pending_ = true;
325    return;
326  }
327
328  if (state_ == kWaitingForKey) {
329    state_ = kPendingDecode;
330    DecodePendingBuffer();
331  }
332}
333
334void DecryptingAudioDecoder::DoReset() {
335  DCHECK(init_cb_.is_null());
336  DCHECK(decode_cb_.is_null());
337  timestamp_helper_->SetBaseTimestamp(kNoTimestamp());
338  state_ = kIdle;
339  base::ResetAndReturn(&reset_cb_).Run();
340}
341
342void DecryptingAudioDecoder::ProcessDecodedFrames(
343    const Decryptor::AudioBuffers& frames) {
344  for (Decryptor::AudioBuffers::const_iterator iter = frames.begin();
345       iter != frames.end();
346       ++iter) {
347    scoped_refptr<AudioBuffer> frame = *iter;
348
349    DCHECK(!frame->end_of_stream()) << "EOS frame returned.";
350    DCHECK_GT(frame->frame_count(), 0) << "Empty frame returned.";
351
352    base::TimeDelta current_time = timestamp_helper_->GetTimestamp();
353    if (IsOutOfSync(current_time, frame->timestamp())) {
354      DVLOG(1) << "Timestamp returned by the decoder ("
355               << frame->timestamp().InMilliseconds() << " ms)"
356               << " does not match the input timestamp and number of samples"
357               << " decoded (" << current_time.InMilliseconds() << " ms).";
358    }
359
360    frame->set_timestamp(current_time);
361    timestamp_helper_->AddFrames(frame->frame_count());
362
363    output_cb_.Run(frame);
364  }
365}
366
367}  // namespace media
368