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.
5 #include "media/filters/decrypting_audio_decoder.h"
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"
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
32 const int64_t kOutOfSyncThresholdInMilliseconds = 100;
33 return std::abs(timestamp_1.InMilliseconds() - timestamp_2.InMilliseconds()) >
34 kOutOfSyncThresholdInMilliseconds;
37 DecryptingAudioDecoder::DecryptingAudioDecoder(
38 const scoped_refptr<base::SequencedTaskRunner>& task_runner,
40 : task_runner_(task_runner), media_log_(media_log) {}
42 bool DecryptingAudioDecoder::SupportsDecryption() const {
46 AudioDecoderType DecryptingAudioDecoder::GetDecoderType() const {
47 return AudioDecoderType::kDecrypting;
50 void DecryptingAudioDecoder::Initialize(const AudioDecoderConfig& config,
51 CdmContext* cdm_context,
53 const OutputCB& output_cb,
54 const WaitingCB& waiting_cb) {
55 DVLOG(2) << "Initialize()";
56 DCHECK(task_runner_->RunsTasksInCurrentSequence());
60 init_cb_ = base::BindPostTaskToCurrentDefault(std::move(init_cb));
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);
68 if (!config.is_encrypted() && !support_clear_content_) {
69 std::move(init_cb_).Run(DecoderStatus::Codes::kUnsupportedEncryptionMode);
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;
77 output_cb_ = base::BindPostTaskToCurrentDefault(output_cb);
80 waiting_cb_ = waiting_cb;
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);
91 if (state_ == kUninitialized) {
92 if (!cdm_context->GetDecryptor()) {
93 DVLOG(1) << __func__ << ": no decryptor";
94 std::move(init_cb_).Run(DecoderStatus::Codes::kUnsupportedEncryptionMode);
98 decryptor_ = cdm_context->GetDecryptor();
99 event_cb_registration_ = cdm_context->RegisterEventCB(
100 base::BindRepeating(&DecryptingAudioDecoder::OnCdmContextEvent,
101 weak_factory_.GetWeakPtr()));
103 // Reinitialization (i.e. upon a config change). The new config can be
104 // encrypted or clear.
105 decryptor_->DeinitializeDecoder(Decryptor::kAudio);
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_;
117 CHECK(!decode_cb_) << "Overlapping decodes are not supported.";
119 decode_cb_ = base::BindPostTaskToCurrentDefault(std::move(decode_cb));
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);
128 // Initialize the |next_output_timestamp_| to be the timestamp of the first
130 if (timestamp_helper_->base_timestamp() == kNoTimestamp &&
131 !buffer->end_of_stream()) {
132 timestamp_helper_->SetBaseTimestamp(buffer->timestamp());
135 pending_buffer_to_decode_ = std::move(buffer);
136 state_ = kPendingDecode;
137 DecodePendingBuffer();
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)
146 DCHECK(!init_cb_); // No Reset() during pending initialization.
149 reset_cb_ = base::BindPostTaskToCurrentDefault(std::move(closure));
151 decryptor_->ResetDecoder(Decryptor::kAudio);
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
157 if (state_ == kPendingDecode) {
162 if (state_ == kWaitingForKey) {
164 pending_buffer_to_decode_.reset();
165 std::move(decode_cb_).Run(DecoderStatus::Codes::kAborted);
172 DecryptingAudioDecoder::~DecryptingAudioDecoder() {
173 DVLOG(2) << __func__;
174 DCHECK(task_runner_->RunsTasksInCurrentSequence());
176 if (state_ == kUninitialized)
180 decryptor_->DeinitializeDecoder(Decryptor::kAudio);
181 decryptor_ = nullptr;
183 pending_buffer_to_decode_.reset();
185 std::move(init_cb_).Run(DecoderStatus::Codes::kInterrupted);
187 std::move(decode_cb_).Run(DecoderStatus::Codes::kAborted);
189 std::move(reset_cb_).Run();
192 void DecryptingAudioDecoder::InitializeDecoder() {
193 state_ = kPendingDecoderInit;
194 decryptor_->InitializeAudioDecoder(
195 config_, base::BindPostTaskToCurrentDefault(
196 base::BindOnce(&DecryptingAudioDecoder::FinishInitialization,
197 weak_factory_.GetWeakPtr())));
200 void DecryptingAudioDecoder::FinishInitialization(bool success) {
201 DVLOG(2) << "FinishInitialization()";
202 DCHECK(task_runner_->RunsTasksInCurrentSequence());
203 DCHECK(state_ == kPendingDecoderInit) << state_;
205 DCHECK(!reset_cb_); // No Reset() before initialization finished.
206 DCHECK(!decode_cb_); // No Decode() before initialization finished.
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();
219 std::make_unique<AudioTimestampHelper>(config_.samples_per_second());
222 std::move(init_cb_).Run(DecoderStatus::Codes::kOk);
225 void DecryptingAudioDecoder::DecodePendingBuffer() {
226 DCHECK(task_runner_->RunsTasksInCurrentSequence());
227 DCHECK_EQ(state_, kPendingDecode) << state_;
230 if (!pending_buffer_to_decode_->end_of_stream()) {
231 buffer_size = pending_buffer_to_decode_->data_size();
234 if (!DecoderBuffer::DoSubsamplesMatch(*pending_buffer_to_decode_)) {
235 MEDIA_LOG(ERROR, media_log_)
236 << "DecryptingAudioDecoder: Subsamples for Buffer do not match";
238 std::move(decode_cb_).Run(DecoderStatus::Codes::kFailed);
242 decryptor_->DecryptAndDecodeAudio(
243 pending_buffer_to_decode_,
244 base::BindPostTaskToCurrentDefault(
245 base::BindRepeating(&DecryptingAudioDecoder::DeliverFrame,
246 weak_factory_.GetWeakPtr(), buffer_size)));
249 void DecryptingAudioDecoder::DeliverFrame(
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_;
257 DCHECK(pending_buffer_to_decode_.get());
259 bool need_to_try_again_if_nokey_is_returned = key_added_while_decode_pending_;
260 key_added_while_decode_pending_ = false;
262 scoped_refptr<DecoderBuffer> scoped_pending_buffer_to_decode =
263 std::move(pending_buffer_to_decode_);
266 std::move(decode_cb_).Run(DecoderStatus::Codes::kAborted);
271 DCHECK_EQ(status == Decryptor::kSuccess, !frames.empty());
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);
281 if (status == Decryptor::kNoKey) {
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;
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);
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();
302 state_ = kWaitingForKey;
303 waiting_cb_.Run(WaitingReason::kNoDecryptionKey);
307 if (status == Decryptor::kNeedMoreData) {
308 DVLOG(2) << "DeliverFrame() - kNeedMoreData";
309 state_ = scoped_pending_buffer_to_decode->end_of_stream() ? kDecodeFinished
311 std::move(decode_cb_).Run(DecoderStatus::Codes::kOk);
315 DCHECK_EQ(status, Decryptor::kSuccess);
316 DCHECK(!frames.empty());
317 ProcessDecodedFrames(frames);
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();
328 std::move(decode_cb_).Run(DecoderStatus::Codes::kOk);
331 void DecryptingAudioDecoder::OnCdmContextEvent(CdmContext::Event event) {
332 DCHECK(task_runner_->RunsTasksInCurrentSequence());
334 if (event != CdmContext::Event::kHasAdditionalUsableKey)
337 if (state_ == kPendingDecode) {
338 key_added_while_decode_pending_ = true;
342 if (state_ == kWaitingForKey) {
343 MEDIA_LOG(INFO, media_log_)
344 << GetDecoderType() << ": key added, resuming decode";
345 state_ = kPendingDecode;
346 DecodePendingBuffer();
350 void DecryptingAudioDecoder::DoReset() {
353 timestamp_helper_->SetBaseTimestamp(kNoTimestamp);
355 std::move(reset_cb_).Run();
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;
363 DCHECK(!frame->end_of_stream()) << "EOS frame returned.";
364 DCHECK_GT(frame->frame_count(), 0) << "Empty frame returned.";
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).";
374 frame->set_timestamp(current_time);
375 timestamp_helper_->AddFrames(frame->frame_count());
377 output_cb_.Run(frame);