Unregister from GCM when the only GCM app is removed
[chromium-blink-merge.git] / media / filters / decrypting_audio_decoder.cc
blob0ca20f7a98b1ea19481c73060602bc4e7358162e
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_audio_decoder.h"
7 #include <cstdlib>
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"
24 namespace media {
26 static inline bool IsOutOfSync(const base::TimeDelta& timestamp_1,
27 const base::TimeDelta& timestamp_2) {
28 // Out of sync of 100ms would be pretty noticeable and we should keep any
29 // drift below that.
30 const int64 kOutOfSyncThresholdInMilliseconds = 100;
31 return std::abs(timestamp_1.InMilliseconds() - timestamp_2.InMilliseconds()) >
32 kOutOfSyncThresholdInMilliseconds;
35 DecryptingAudioDecoder::DecryptingAudioDecoder(
36 const scoped_refptr<base::SingleThreadTaskRunner>& task_runner,
37 const SetDecryptorReadyCB& set_decryptor_ready_cb)
38 : task_runner_(task_runner),
39 state_(kUninitialized),
40 set_decryptor_ready_cb_(set_decryptor_ready_cb),
41 decryptor_(NULL),
42 key_added_while_decode_pending_(false),
43 weak_factory_(this) {}
45 std::string DecryptingAudioDecoder::GetDisplayName() const {
46 return "DecryptingAudioDecoder";
49 void DecryptingAudioDecoder::Initialize(const AudioDecoderConfig& config,
50 const PipelineStatusCB& status_cb,
51 const OutputCB& output_cb) {
52 DVLOG(2) << "Initialize()";
53 DCHECK(task_runner_->BelongsToCurrentThread());
54 DCHECK(decode_cb_.is_null());
55 DCHECK(reset_cb_.is_null());
57 weak_this_ = weak_factory_.GetWeakPtr();
58 init_cb_ = BindToCurrentLoop(status_cb);
59 output_cb_ = BindToCurrentLoop(output_cb);
61 if (!config.IsValidConfig()) {
62 DLOG(ERROR) << "Invalid audio stream config.";
63 base::ResetAndReturn(&init_cb_).Run(PIPELINE_ERROR_DECODE);
64 return;
67 // DecryptingAudioDecoder only accepts potentially encrypted stream.
68 if (!config.is_encrypted()) {
69 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED);
70 return;
73 config_ = config;
75 if (state_ == kUninitialized) {
76 state_ = kDecryptorRequested;
77 set_decryptor_ready_cb_.Run(BindToCurrentLoop(
78 base::Bind(&DecryptingAudioDecoder::SetDecryptor, weak_this_)));
79 return;
82 // Reinitialization (i.e. upon a config change)
83 decryptor_->DeinitializeDecoder(Decryptor::kAudio);
84 InitializeDecoder();
87 void DecryptingAudioDecoder::Decode(const scoped_refptr<DecoderBuffer>& buffer,
88 const DecodeCB& decode_cb) {
89 DVLOG(3) << "Decode()";
90 DCHECK(task_runner_->BelongsToCurrentThread());
91 DCHECK(state_ == kIdle || state_ == kDecodeFinished) << state_;
92 DCHECK(!decode_cb.is_null());
93 CHECK(decode_cb_.is_null()) << "Overlapping decodes are not supported.";
95 decode_cb_ = BindToCurrentLoop(decode_cb);
97 // Return empty (end-of-stream) frames if decoding has finished.
98 if (state_ == kDecodeFinished) {
99 output_cb_.Run(AudioBuffer::CreateEOSBuffer());
100 base::ResetAndReturn(&decode_cb_).Run(kOk);
101 return;
104 // Initialize the |next_output_timestamp_| to be the timestamp of the first
105 // non-EOS buffer.
106 if (timestamp_helper_->base_timestamp() == kNoTimestamp() &&
107 !buffer->end_of_stream()) {
108 timestamp_helper_->SetBaseTimestamp(buffer->timestamp());
111 pending_buffer_to_decode_ = buffer;
112 state_ = kPendingDecode;
113 DecodePendingBuffer();
116 void DecryptingAudioDecoder::Reset(const base::Closure& closure) {
117 DVLOG(2) << "Reset() - state: " << state_;
118 DCHECK(task_runner_->BelongsToCurrentThread());
119 DCHECK(state_ == kIdle ||
120 state_ == kPendingDecode ||
121 state_ == kWaitingForKey ||
122 state_ == kDecodeFinished) << state_;
123 DCHECK(init_cb_.is_null()); // No Reset() during pending initialization.
124 DCHECK(reset_cb_.is_null());
126 reset_cb_ = BindToCurrentLoop(closure);
128 decryptor_->ResetDecoder(Decryptor::kAudio);
130 // Reset() cannot complete if the read callback is still pending.
131 // Defer the resetting process in this case. The |reset_cb_| will be fired
132 // after the read callback is fired - see DecryptAndDecodeBuffer() and
133 // DeliverFrame().
134 if (state_ == kPendingDecode) {
135 DCHECK(!decode_cb_.is_null());
136 return;
139 if (state_ == kWaitingForKey) {
140 DCHECK(!decode_cb_.is_null());
141 pending_buffer_to_decode_ = NULL;
142 base::ResetAndReturn(&decode_cb_).Run(kAborted);
145 DCHECK(decode_cb_.is_null());
146 DoReset();
149 DecryptingAudioDecoder::~DecryptingAudioDecoder() {
150 DVLOG(2) << __FUNCTION__;
151 DCHECK(task_runner_->BelongsToCurrentThread());
153 if (state_ == kUninitialized)
154 return;
156 if (decryptor_) {
157 decryptor_->DeinitializeDecoder(Decryptor::kAudio);
158 decryptor_ = NULL;
160 if (!set_decryptor_ready_cb_.is_null())
161 base::ResetAndReturn(&set_decryptor_ready_cb_).Run(DecryptorReadyCB());
162 pending_buffer_to_decode_ = NULL;
163 if (!init_cb_.is_null())
164 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED);
165 if (!decode_cb_.is_null())
166 base::ResetAndReturn(&decode_cb_).Run(kAborted);
167 if (!reset_cb_.is_null())
168 base::ResetAndReturn(&reset_cb_).Run();
171 void DecryptingAudioDecoder::SetDecryptor(
172 Decryptor* decryptor,
173 const DecryptorAttachedCB& decryptor_attached_cb) {
174 DVLOG(2) << "SetDecryptor()";
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 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED);
184 state_ = kError;
185 decryptor_attached_cb.Run(false);
186 return;
189 decryptor_ = decryptor;
191 InitializeDecoder();
192 decryptor_attached_cb.Run(true);
195 void DecryptingAudioDecoder::InitializeDecoder() {
196 state_ = kPendingDecoderInit;
197 decryptor_->InitializeAudioDecoder(
198 config_,
199 BindToCurrentLoop(base::Bind(
200 &DecryptingAudioDecoder::FinishInitialization, weak_this_)));
203 void DecryptingAudioDecoder::FinishInitialization(bool success) {
204 DVLOG(2) << "FinishInitialization()";
205 DCHECK(task_runner_->BelongsToCurrentThread());
206 DCHECK(state_ == kPendingDecoderInit) << state_;
207 DCHECK(!init_cb_.is_null());
208 DCHECK(reset_cb_.is_null()); // No Reset() before initialization finished.
209 DCHECK(decode_cb_.is_null()); // No Decode() before initialization finished.
211 if (!success) {
212 base::ResetAndReturn(&init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED);
213 decryptor_ = NULL;
214 state_ = kError;
215 return;
218 // Success!
219 timestamp_helper_.reset(
220 new AudioTimestampHelper(config_.samples_per_second()));
222 decryptor_->RegisterNewKeyCB(
223 Decryptor::kAudio,
224 BindToCurrentLoop(
225 base::Bind(&DecryptingAudioDecoder::OnKeyAdded, weak_this_)));
227 state_ = kIdle;
228 base::ResetAndReturn(&init_cb_).Run(PIPELINE_OK);
231 void DecryptingAudioDecoder::DecodePendingBuffer() {
232 DCHECK(task_runner_->BelongsToCurrentThread());
233 DCHECK_EQ(state_, kPendingDecode) << state_;
235 int buffer_size = 0;
236 if (!pending_buffer_to_decode_->end_of_stream()) {
237 buffer_size = pending_buffer_to_decode_->data_size();
240 decryptor_->DecryptAndDecodeAudio(
241 pending_buffer_to_decode_,
242 BindToCurrentLoop(base::Bind(
243 &DecryptingAudioDecoder::DeliverFrame, weak_this_, buffer_size)));
246 void DecryptingAudioDecoder::DeliverFrame(
247 int buffer_size,
248 Decryptor::Status status,
249 const Decryptor::AudioFrames& frames) {
250 DVLOG(3) << "DeliverFrame() - status: " << status;
251 DCHECK(task_runner_->BelongsToCurrentThread());
252 DCHECK_EQ(state_, kPendingDecode) << state_;
253 DCHECK(!decode_cb_.is_null());
254 DCHECK(pending_buffer_to_decode_.get());
256 bool need_to_try_again_if_nokey_is_returned = key_added_while_decode_pending_;
257 key_added_while_decode_pending_ = false;
259 scoped_refptr<DecoderBuffer> scoped_pending_buffer_to_decode =
260 pending_buffer_to_decode_;
261 pending_buffer_to_decode_ = NULL;
263 if (!reset_cb_.is_null()) {
264 base::ResetAndReturn(&decode_cb_).Run(kAborted);
265 DoReset();
266 return;
269 DCHECK_EQ(status == Decryptor::kSuccess, !frames.empty());
271 if (status == Decryptor::kError) {
272 DVLOG(2) << "DeliverFrame() - kError";
273 state_ = kDecodeFinished; // TODO add kError state
274 base::ResetAndReturn(&decode_cb_).Run(kDecodeError);
275 return;
278 if (status == Decryptor::kNoKey) {
279 DVLOG(2) << "DeliverFrame() - kNoKey";
280 // Set |pending_buffer_to_decode_| back as we need to try decoding the
281 // pending buffer again when new key is added to the decryptor.
282 pending_buffer_to_decode_ = scoped_pending_buffer_to_decode;
284 if (need_to_try_again_if_nokey_is_returned) {
285 // The |state_| is still kPendingDecode.
286 DecodePendingBuffer();
287 return;
290 state_ = kWaitingForKey;
291 return;
294 if (status == Decryptor::kNeedMoreData) {
295 DVLOG(2) << "DeliverFrame() - kNeedMoreData";
296 state_ = scoped_pending_buffer_to_decode->end_of_stream() ? kDecodeFinished
297 : kIdle;
298 base::ResetAndReturn(&decode_cb_).Run(kOk);
299 return;
302 DCHECK_EQ(status, Decryptor::kSuccess);
303 DCHECK(!frames.empty());
304 ProcessDecodedFrames(frames);
306 if (scoped_pending_buffer_to_decode->end_of_stream()) {
307 // Set |pending_buffer_to_decode_| back as we need to keep flushing the
308 // decryptor until kNeedMoreData is returned.
309 pending_buffer_to_decode_ = scoped_pending_buffer_to_decode;
310 DecodePendingBuffer();
311 return;
314 state_ = kIdle;
315 base::ResetAndReturn(&decode_cb_).Run(kOk);
318 void DecryptingAudioDecoder::OnKeyAdded() {
319 DCHECK(task_runner_->BelongsToCurrentThread());
321 if (state_ == kPendingDecode) {
322 key_added_while_decode_pending_ = true;
323 return;
326 if (state_ == kWaitingForKey) {
327 state_ = kPendingDecode;
328 DecodePendingBuffer();
332 void DecryptingAudioDecoder::DoReset() {
333 DCHECK(init_cb_.is_null());
334 DCHECK(decode_cb_.is_null());
335 timestamp_helper_->SetBaseTimestamp(kNoTimestamp());
336 state_ = kIdle;
337 base::ResetAndReturn(&reset_cb_).Run();
340 void DecryptingAudioDecoder::ProcessDecodedFrames(
341 const Decryptor::AudioFrames& frames) {
342 for (Decryptor::AudioFrames::const_iterator iter = frames.begin();
343 iter != frames.end();
344 ++iter) {
345 scoped_refptr<AudioBuffer> frame = *iter;
347 DCHECK(!frame->end_of_stream()) << "EOS frame returned.";
348 DCHECK_GT(frame->frame_count(), 0) << "Empty frame returned.";
350 base::TimeDelta current_time = timestamp_helper_->GetTimestamp();
351 if (IsOutOfSync(current_time, frame->timestamp())) {
352 DVLOG(1) << "Timestamp returned by the decoder ("
353 << frame->timestamp().InMilliseconds() << " ms)"
354 << " does not match the input timestamp and number of samples"
355 << " decoded (" << current_time.InMilliseconds() << " ms).";
358 frame->set_timestamp(current_time);
359 timestamp_helper_->AddFrames(frame->frame_count());
361 output_cb_.Run(frame);
365 } // namespace media