[M120 Migration][hbbtv] Audio tracks count notification
[platform/framework/web/chromium-efl.git] / media / filters / decrypting_audio_decoder.cc
1 // Copyright 2012 The Chromium Authors
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 <stdint.h>
8
9 #include <cstdlib>
10 #include <memory>
11
12 #include "base/functional/bind.h"
13 #include "base/functional/callback_helpers.h"
14 #include "base/location.h"
15 #include "base/logging.h"
16 #include "base/strings/string_number_conversions.h"
17 #include "base/task/bind_post_task.h"
18 #include "base/task/sequenced_task_runner.h"
19 #include "media/base/audio_buffer.h"
20 #include "media/base/audio_decoder_config.h"
21 #include "media/base/audio_timestamp_helper.h"
22 #include "media/base/decoder_buffer.h"
23 #include "media/base/media_log.h"
24 #include "media/base/timestamp_constants.h"
25
26 namespace media {
27
28 static 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_t kOutOfSyncThresholdInMilliseconds = 100;
33   return std::abs(timestamp_1.InMilliseconds() - timestamp_2.InMilliseconds()) >
34          kOutOfSyncThresholdInMilliseconds;
35 }
36
37 DecryptingAudioDecoder::DecryptingAudioDecoder(
38     const scoped_refptr<base::SequencedTaskRunner>& task_runner,
39     MediaLog* media_log)
40     : task_runner_(task_runner), media_log_(media_log) {}
41
42 bool DecryptingAudioDecoder::SupportsDecryption() const {
43   return true;
44 }
45
46 AudioDecoderType DecryptingAudioDecoder::GetDecoderType() const {
47   return AudioDecoderType::kDecrypting;
48 }
49
50 void DecryptingAudioDecoder::Initialize(const AudioDecoderConfig& config,
51                                         CdmContext* cdm_context,
52                                         InitCB init_cb,
53                                         const OutputCB& output_cb,
54                                         const WaitingCB& waiting_cb) {
55   DVLOG(2) << "Initialize()";
56   DCHECK(task_runner_->RunsTasksInCurrentSequence());
57   DCHECK(!decode_cb_);
58   DCHECK(!reset_cb_);
59
60   init_cb_ = base::BindPostTaskToCurrentDefault(std::move(init_cb));
61   if (!cdm_context) {
62     // Once we have a CDM context, one should always be present.
63     DCHECK(!support_clear_content_);
64     std::move(init_cb_).Run(DecoderStatus::Codes::kUnsupportedEncryptionMode);
65     return;
66   }
67
68   if (!config.is_encrypted() && !support_clear_content_) {
69     std::move(init_cb_).Run(DecoderStatus::Codes::kUnsupportedEncryptionMode);
70     return;
71   }
72
73   // Once initialized with encryption support, the value is sticky, so we'll use
74   // the decryptor for clear content as well.
75   support_clear_content_ = true;
76
77   output_cb_ = base::BindPostTaskToCurrentDefault(output_cb);
78
79   DCHECK(waiting_cb);
80   waiting_cb_ = waiting_cb;
81
82   // TODO(xhwang): We should be able to DCHECK config.IsValidConfig().
83   if (!config.IsValidConfig()) {
84     DLOG(ERROR) << "Invalid audio stream config.";
85     std::move(init_cb_).Run(DecoderStatus::Codes::kUnsupportedCodec);
86     return;
87   }
88
89   config_ = config;
90
91   if (state_ == kUninitialized) {
92     if (!cdm_context->GetDecryptor()) {
93       DVLOG(1) << __func__ << ": no decryptor";
94       std::move(init_cb_).Run(DecoderStatus::Codes::kUnsupportedEncryptionMode);
95       return;
96     }
97
98     decryptor_ = cdm_context->GetDecryptor();
99     event_cb_registration_ = cdm_context->RegisterEventCB(
100         base::BindRepeating(&DecryptingAudioDecoder::OnCdmContextEvent,
101                             weak_factory_.GetWeakPtr()));
102   } else {
103     // Reinitialization (i.e. upon a config change). The new config can be
104     // encrypted or clear.
105     decryptor_->DeinitializeDecoder(Decryptor::kAudio);
106   }
107
108   InitializeDecoder();
109 }
110
111 void DecryptingAudioDecoder::Decode(scoped_refptr<DecoderBuffer> buffer,
112                                     DecodeCB decode_cb) {
113   DVLOG(3) << "Decode()";
114   DCHECK(task_runner_->RunsTasksInCurrentSequence());
115   DCHECK(state_ == kIdle || state_ == kDecodeFinished) << state_;
116   DCHECK(decode_cb);
117   CHECK(!decode_cb_) << "Overlapping decodes are not supported.";
118
119   decode_cb_ = base::BindPostTaskToCurrentDefault(std::move(decode_cb));
120
121   // Return empty (end-of-stream) frames if decoding has finished.
122   if (state_ == kDecodeFinished) {
123     output_cb_.Run(AudioBuffer::CreateEOSBuffer());
124     std::move(decode_cb_).Run(DecoderStatus::Codes::kOk);
125     return;
126   }
127
128   // Initialize the |next_output_timestamp_| to be the timestamp of the first
129   // non-EOS buffer.
130   if (timestamp_helper_->base_timestamp() == kNoTimestamp &&
131       !buffer->end_of_stream()) {
132     timestamp_helper_->SetBaseTimestamp(buffer->timestamp());
133   }
134
135   pending_buffer_to_decode_ = std::move(buffer);
136   state_ = kPendingDecode;
137   DecodePendingBuffer();
138 }
139
140 void DecryptingAudioDecoder::Reset(base::OnceClosure closure) {
141   DVLOG(2) << "Reset() - state: " << state_;
142   DCHECK(task_runner_->RunsTasksInCurrentSequence());
143   DCHECK(state_ == kIdle || state_ == kPendingDecode ||
144          state_ == kWaitingForKey || state_ == kDecodeFinished)
145       << state_;
146   DCHECK(!init_cb_);  // No Reset() during pending initialization.
147   DCHECK(!reset_cb_);
148
149   reset_cb_ = base::BindPostTaskToCurrentDefault(std::move(closure));
150
151   decryptor_->ResetDecoder(Decryptor::kAudio);
152
153   // Reset() cannot complete if the read callback is still pending.
154   // Defer the resetting process in this case. The |reset_cb_| will be fired
155   // after the read callback is fired - see DecryptAndDecodeBuffer() and
156   // DeliverFrame().
157   if (state_ == kPendingDecode) {
158     DCHECK(decode_cb_);
159     return;
160   }
161
162   if (state_ == kWaitingForKey) {
163     DCHECK(decode_cb_);
164     pending_buffer_to_decode_.reset();
165     std::move(decode_cb_).Run(DecoderStatus::Codes::kAborted);
166   }
167
168   DCHECK(!decode_cb_);
169   DoReset();
170 }
171
172 DecryptingAudioDecoder::~DecryptingAudioDecoder() {
173   DVLOG(2) << __func__;
174   DCHECK(task_runner_->RunsTasksInCurrentSequence());
175
176   if (state_ == kUninitialized)
177     return;
178
179   if (decryptor_) {
180     decryptor_->DeinitializeDecoder(Decryptor::kAudio);
181     decryptor_ = nullptr;
182   }
183   pending_buffer_to_decode_.reset();
184   if (init_cb_)
185     std::move(init_cb_).Run(DecoderStatus::Codes::kInterrupted);
186   if (decode_cb_)
187     std::move(decode_cb_).Run(DecoderStatus::Codes::kAborted);
188   if (reset_cb_)
189     std::move(reset_cb_).Run();
190 }
191
192 void DecryptingAudioDecoder::InitializeDecoder() {
193   state_ = kPendingDecoderInit;
194   decryptor_->InitializeAudioDecoder(
195       config_, base::BindPostTaskToCurrentDefault(
196                    base::BindOnce(&DecryptingAudioDecoder::FinishInitialization,
197                                   weak_factory_.GetWeakPtr())));
198 }
199
200 void DecryptingAudioDecoder::FinishInitialization(bool success) {
201   DVLOG(2) << "FinishInitialization()";
202   DCHECK(task_runner_->RunsTasksInCurrentSequence());
203   DCHECK(state_ == kPendingDecoderInit) << state_;
204   DCHECK(init_cb_);
205   DCHECK(!reset_cb_);   // No Reset() before initialization finished.
206   DCHECK(!decode_cb_);  // No Decode() before initialization finished.
207
208   if (!success) {
209     DVLOG(1) << __func__ << ": failed to init audio decoder on decryptor";
210     std::move(init_cb_).Run(DecoderStatus::Codes::kFailedToCreateDecoder);
211     decryptor_ = nullptr;
212     event_cb_registration_.reset();
213     state_ = kError;
214     return;
215   }
216
217   // Success!
218   timestamp_helper_ =
219       std::make_unique<AudioTimestampHelper>(config_.samples_per_second());
220
221   state_ = kIdle;
222   std::move(init_cb_).Run(DecoderStatus::Codes::kOk);
223 }
224
225 void DecryptingAudioDecoder::DecodePendingBuffer() {
226   DCHECK(task_runner_->RunsTasksInCurrentSequence());
227   DCHECK_EQ(state_, kPendingDecode) << state_;
228
229   int buffer_size = 0;
230   if (!pending_buffer_to_decode_->end_of_stream()) {
231     buffer_size = pending_buffer_to_decode_->data_size();
232   }
233
234   if (!DecoderBuffer::DoSubsamplesMatch(*pending_buffer_to_decode_)) {
235     MEDIA_LOG(ERROR, media_log_)
236         << "DecryptingAudioDecoder: Subsamples for Buffer do not match";
237     state_ = kError;
238     std::move(decode_cb_).Run(DecoderStatus::Codes::kFailed);
239     return;
240   }
241
242   decryptor_->DecryptAndDecodeAudio(
243       pending_buffer_to_decode_,
244       base::BindPostTaskToCurrentDefault(
245           base::BindRepeating(&DecryptingAudioDecoder::DeliverFrame,
246                               weak_factory_.GetWeakPtr(), buffer_size)));
247 }
248
249 void DecryptingAudioDecoder::DeliverFrame(
250     int buffer_size,
251     Decryptor::Status status,
252     const Decryptor::AudioFrames& frames) {
253   DVLOG(3) << "DeliverFrame() - status: " << status;
254   DCHECK(task_runner_->RunsTasksInCurrentSequence());
255   DCHECK_EQ(state_, kPendingDecode) << state_;
256   DCHECK(decode_cb_);
257   DCHECK(pending_buffer_to_decode_.get());
258
259   bool need_to_try_again_if_nokey_is_returned = key_added_while_decode_pending_;
260   key_added_while_decode_pending_ = false;
261
262   scoped_refptr<DecoderBuffer> scoped_pending_buffer_to_decode =
263       std::move(pending_buffer_to_decode_);
264
265   if (reset_cb_) {
266     std::move(decode_cb_).Run(DecoderStatus::Codes::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     MEDIA_LOG(ERROR, media_log_) << GetDecoderType() << ": decode error";
276     state_ = kDecodeFinished;  // TODO add kError state
277     std::move(decode_cb_).Run(DecoderStatus::Codes::kFailed);
278     return;
279   }
280
281   if (status == Decryptor::kNoKey) {
282     std::string key_id =
283         scoped_pending_buffer_to_decode->decrypt_config()->key_id();
284     std::string log_message =
285         "no key for key ID " + base::HexEncode(key_id.data(), key_id.size()) +
286         "; will resume decoding after new usable key is available";
287     DVLOG(1) << __func__ << ": " << log_message;
288     MEDIA_LOG(INFO, media_log_) << GetDecoderType() << ": " << log_message;
289
290     // Set |pending_buffer_to_decode_| back as we need to try decoding the
291     // pending buffer again when new key is added to the decryptor.
292     pending_buffer_to_decode_ = std::move(scoped_pending_buffer_to_decode);
293
294     if (need_to_try_again_if_nokey_is_returned) {
295       // The |state_| is still kPendingDecode.
296       MEDIA_LOG(INFO, media_log_)
297           << GetDecoderType() << ": key was added, resuming decode";
298       DecodePendingBuffer();
299       return;
300     }
301
302     state_ = kWaitingForKey;
303     waiting_cb_.Run(WaitingReason::kNoDecryptionKey);
304     return;
305   }
306
307   if (status == Decryptor::kNeedMoreData) {
308     DVLOG(2) << "DeliverFrame() - kNeedMoreData";
309     state_ = scoped_pending_buffer_to_decode->end_of_stream() ? kDecodeFinished
310                                                               : kIdle;
311     std::move(decode_cb_).Run(DecoderStatus::Codes::kOk);
312     return;
313   }
314
315   DCHECK_EQ(status, Decryptor::kSuccess);
316   DCHECK(!frames.empty());
317   ProcessDecodedFrames(frames);
318
319   if (scoped_pending_buffer_to_decode->end_of_stream()) {
320     // Set |pending_buffer_to_decode_| back as we need to keep flushing the
321     // decryptor until kNeedMoreData is returned.
322     pending_buffer_to_decode_ = std::move(scoped_pending_buffer_to_decode);
323     DecodePendingBuffer();
324     return;
325   }
326
327   state_ = kIdle;
328   std::move(decode_cb_).Run(DecoderStatus::Codes::kOk);
329 }
330
331 void DecryptingAudioDecoder::OnCdmContextEvent(CdmContext::Event event) {
332   DCHECK(task_runner_->RunsTasksInCurrentSequence());
333
334   if (event != CdmContext::Event::kHasAdditionalUsableKey)
335     return;
336
337   if (state_ == kPendingDecode) {
338     key_added_while_decode_pending_ = true;
339     return;
340   }
341
342   if (state_ == kWaitingForKey) {
343     MEDIA_LOG(INFO, media_log_)
344         << GetDecoderType() << ": key added, resuming decode";
345     state_ = kPendingDecode;
346     DecodePendingBuffer();
347   }
348 }
349
350 void DecryptingAudioDecoder::DoReset() {
351   DCHECK(!init_cb_);
352   DCHECK(!decode_cb_);
353   timestamp_helper_->SetBaseTimestamp(kNoTimestamp);
354   state_ = kIdle;
355   std::move(reset_cb_).Run();
356 }
357
358 void DecryptingAudioDecoder::ProcessDecodedFrames(
359     const Decryptor::AudioFrames& frames) {
360   for (auto iter = frames.begin(); iter != frames.end(); ++iter) {
361     scoped_refptr<AudioBuffer> frame = *iter;
362
363     DCHECK(!frame->end_of_stream()) << "EOS frame returned.";
364     DCHECK_GT(frame->frame_count(), 0) << "Empty frame returned.";
365
366     base::TimeDelta current_time = timestamp_helper_->GetTimestamp();
367     if (IsOutOfSync(current_time, frame->timestamp())) {
368       DVLOG(1) << "Timestamp returned by the decoder ("
369                << frame->timestamp().InMilliseconds() << " ms)"
370                << " does not match the input timestamp and number of samples"
371                << " decoded (" << current_time.InMilliseconds() << " ms).";
372     }
373
374     frame->set_timestamp(current_time);
375     timestamp_helper_->AddFrames(frame->frame_count());
376
377     output_cb_.Run(frame);
378   }
379 }
380
381 }  // namespace media