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_demuxer_stream.h"
8 #include "base/callback_helpers.h"
9 #include "base/location.h"
10 #include "base/logging.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "base/task/sequenced_task_runner.h"
13 #include "base/task/single_thread_task_runner.h"
14 #include "base/trace_event/trace_event.h"
15 #include "media/base/bind_to_current_loop.h"
16 #include "media/base/cdm_context.h"
17 #include "media/base/decoder_buffer.h"
18 #include "media/base/media_log.h"
19 #include "media/base/media_util.h"
23 static bool IsStreamValid(DemuxerStream* stream) {
24 return ((stream->type() == DemuxerStream::AUDIO &&
25 stream->audio_decoder_config().IsValidConfig()) ||
26 (stream->type() == DemuxerStream::VIDEO &&
27 stream->video_decoder_config().IsValidConfig()));
30 DecryptingDemuxerStream::DecryptingDemuxerStream(
31 const scoped_refptr<base::SequencedTaskRunner>& task_runner,
33 const WaitingCB& waiting_cb)
34 : task_runner_(task_runner),
35 media_log_(media_log),
36 waiting_cb_(waiting_cb) {
37 DETACH_FROM_SEQUENCE(sequence_checker_);
40 std::string DecryptingDemuxerStream::GetDisplayName() const {
41 return "DecryptingDemuxerStream";
44 void DecryptingDemuxerStream::Initialize(DemuxerStream* stream,
45 CdmContext* cdm_context,
46 PipelineStatusCallback status_cb) {
48 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
49 DCHECK_EQ(state_, kUninitialized) << state_;
52 DCHECK(!demuxer_stream_);
54 demuxer_stream_ = stream;
55 init_cb_ = BindToCurrentLoop(std::move(status_cb));
57 InitializeDecoderConfig();
59 if (!cdm_context->GetDecryptor()) {
60 DVLOG(1) << __func__ << ": no decryptor";
61 state_ = kUninitialized;
62 std::move(init_cb_).Run(DECODER_ERROR_NOT_SUPPORTED);
66 decryptor_ = cdm_context->GetDecryptor();
68 event_cb_registration_ = cdm_context->RegisterEventCB(base::BindRepeating(
69 &DecryptingDemuxerStream::OnCdmContextEvent, weak_factory_.GetWeakPtr()));
72 std::move(init_cb_).Run(PIPELINE_OK);
75 void DecryptingDemuxerStream::Read(ReadCB read_cb) {
77 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
78 DCHECK_EQ(state_, kIdle) << state_;
80 CHECK(!read_cb_) << "Overlapping reads are not supported.";
82 read_cb_ = BindToCurrentLoop(std::move(read_cb));
83 state_ = kPendingDemuxerRead;
84 demuxer_stream_->Read(
85 base::BindOnce(&DecryptingDemuxerStream::OnBufferReadFromDemuxerStream,
86 weak_factory_.GetWeakPtr()));
89 void DecryptingDemuxerStream::Reset(base::OnceClosure closure) {
90 DVLOG(2) << __func__ << " - state: " << state_;
91 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
92 DCHECK(state_ != kUninitialized) << state_;
95 reset_cb_ = BindToCurrentLoop(std::move(closure));
97 decryptor_->CancelDecrypt(GetDecryptorStreamType());
99 // Reset() cannot complete if the read callback is still pending.
100 // Defer the resetting process in this case. The |reset_cb_| will be fired
101 // after the read callback is fired - see OnBufferReadFromDemuxerStream() and
102 // OnBufferDecrypted().
103 if (state_ == kPendingDemuxerRead || state_ == kPendingDecrypt) {
108 if (state_ == kWaitingForKey) {
109 CompleteWaitingForDecryptionKey();
111 pending_buffer_to_decrypt_ = nullptr;
112 std::move(read_cb_).Run(kAborted, nullptr);
119 AudioDecoderConfig DecryptingDemuxerStream::audio_decoder_config() {
120 DCHECK(state_ != kUninitialized) << state_;
121 CHECK_EQ(demuxer_stream_->type(), AUDIO);
122 return audio_config_;
125 VideoDecoderConfig DecryptingDemuxerStream::video_decoder_config() {
126 DCHECK(state_ != kUninitialized) << state_;
127 CHECK_EQ(demuxer_stream_->type(), VIDEO);
128 return video_config_;
131 DemuxerStream::Type DecryptingDemuxerStream::type() const {
132 DCHECK(state_ != kUninitialized) << state_;
133 return demuxer_stream_->type();
136 StreamLiveness DecryptingDemuxerStream::liveness() const {
137 DCHECK(state_ != kUninitialized) << state_;
138 return demuxer_stream_->liveness();
141 void DecryptingDemuxerStream::EnableBitstreamConverter() {
142 demuxer_stream_->EnableBitstreamConverter();
145 bool DecryptingDemuxerStream::SupportsConfigChanges() {
146 return demuxer_stream_->SupportsConfigChanges();
149 bool DecryptingDemuxerStream::HasClearLead() const {
150 return has_clear_lead_.value_or(false);
153 DecryptingDemuxerStream::~DecryptingDemuxerStream() {
154 DVLOG(2) << __func__ << " : state_ = " << state_;
155 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
157 if (state_ == kUninitialized)
160 if (state_ == kWaitingForKey)
161 CompleteWaitingForDecryptionKey();
162 if (state_ == kPendingDecrypt)
163 CompletePendingDecrypt(Decryptor::kError);
166 decryptor_->CancelDecrypt(GetDecryptorStreamType());
167 decryptor_ = nullptr;
170 std::move(init_cb_).Run(PIPELINE_ERROR_ABORT);
172 std::move(read_cb_).Run(kAborted, nullptr);
174 std::move(reset_cb_).Run();
175 pending_buffer_to_decrypt_ = nullptr;
178 void DecryptingDemuxerStream::OnBufferReadFromDemuxerStream(
179 DemuxerStream::Status status,
180 scoped_refptr<DecoderBuffer> buffer) {
181 DVLOG(3) << __func__ << ": status = " << status;
182 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
183 DCHECK_EQ(state_, kPendingDemuxerRead) << state_;
185 DCHECK_EQ(buffer.get() != nullptr, status == kOk) << status;
187 // Even when |reset_cb_|, we need to pass |kConfigChanged| back to
188 // the caller so that the downstream decoder can be properly reinitialized.
189 if (status == kConfigChanged) {
190 DVLOG(2) << __func__ << ": config change";
191 DCHECK_EQ(demuxer_stream_->type() == AUDIO, audio_config_.IsValidConfig());
192 DCHECK_EQ(demuxer_stream_->type() == VIDEO, video_config_.IsValidConfig());
194 // Update the decoder config, which the decoder will use when it is notified
195 // of kConfigChanged.
196 InitializeDecoderConfig();
199 std::move(read_cb_).Run(kConfigChanged, nullptr);
206 std::move(read_cb_).Run(kAborted, nullptr);
211 if (status == kAborted || status == kError) {
212 if (status == kError) {
213 MEDIA_LOG(ERROR, media_log_)
214 << GetDisplayName() << ": demuxer stream read error.";
217 std::move(read_cb_).Run(status, nullptr);
221 DCHECK_EQ(kOk, status);
223 if (buffer->end_of_stream()) {
224 DVLOG(2) << __func__ << ": EOS buffer";
226 std::move(read_cb_).Run(kOk, std::move(buffer));
230 // One time set of `has_clear_lead_`.
231 if (!has_clear_lead_.has_value()) {
232 has_clear_lead_ = !buffer->decrypt_config();
235 if (!buffer->decrypt_config()) {
236 DVLOG(2) << __func__ << ": clear buffer";
238 std::move(read_cb_).Run(kOk, std::move(buffer));
242 pending_buffer_to_decrypt_ = std::move(buffer);
243 state_ = kPendingDecrypt;
244 DecryptPendingBuffer();
247 void DecryptingDemuxerStream::DecryptPendingBuffer() {
248 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
249 DCHECK_EQ(state_, kPendingDecrypt) << state_;
250 DCHECK(!pending_buffer_to_decrypt_->end_of_stream());
251 TRACE_EVENT_ASYNC_BEGIN2(
252 "media", "DecryptingDemuxerStream::DecryptPendingBuffer", this, "type",
253 DemuxerStream::GetTypeName(demuxer_stream_->type()), "timestamp_us",
254 pending_buffer_to_decrypt_->timestamp().InMicroseconds());
255 decryptor_->Decrypt(GetDecryptorStreamType(), pending_buffer_to_decrypt_,
256 BindToCurrentLoop(base::BindOnce(
257 &DecryptingDemuxerStream::OnBufferDecrypted,
258 weak_factory_.GetWeakPtr())));
261 void DecryptingDemuxerStream::OnBufferDecrypted(
262 Decryptor::Status status,
263 scoped_refptr<DecoderBuffer> decrypted_buffer) {
264 DVLOG(3) << __func__ << " - status: " << status;
265 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
266 DCHECK_EQ(state_, kPendingDecrypt) << state_;
268 DCHECK(pending_buffer_to_decrypt_);
269 CompletePendingDecrypt(status);
271 bool need_to_try_again_if_nokey = key_added_while_decrypt_pending_;
272 key_added_while_decrypt_pending_ = false;
275 pending_buffer_to_decrypt_ = nullptr;
276 std::move(read_cb_).Run(kAborted, nullptr);
281 DCHECK_EQ(status == Decryptor::kSuccess, decrypted_buffer.get() != nullptr);
283 if (status == Decryptor::kError || status == Decryptor::kNeedMoreData) {
284 DVLOG(2) << __func__ << ": Error with status " << status;
285 MEDIA_LOG(ERROR, media_log_)
286 << GetDisplayName() << ": decrypt error " << status;
287 pending_buffer_to_decrypt_ = nullptr;
289 std::move(read_cb_).Run(kError, nullptr);
293 if (status == Decryptor::kNoKey) {
294 std::string key_id = pending_buffer_to_decrypt_->decrypt_config()->key_id();
296 std::string log_message =
297 "no key for key ID " + base::HexEncode(key_id.data(), key_id.size()) +
298 "; will resume decrypting after new usable key is available";
299 DVLOG(1) << __func__ << ": " << log_message;
300 MEDIA_LOG(INFO, media_log_) << GetDisplayName() << ": " << log_message;
302 if (need_to_try_again_if_nokey) {
303 // The |state_| is still kPendingDecrypt.
304 MEDIA_LOG(INFO, media_log_)
305 << GetDisplayName() << ": key was added, resuming decrypt";
306 DecryptPendingBuffer();
310 state_ = kWaitingForKey;
312 TRACE_EVENT_ASYNC_BEGIN0(
313 "media", "DecryptingDemuxerStream::WaitingForDecryptionKey", this);
314 waiting_cb_.Run(WaitingReason::kNoDecryptionKey);
318 DCHECK_EQ(status, Decryptor::kSuccess);
320 // Copy the key frame flag and duration from the encrypted to decrypted
322 // TODO(crbug.com/1116263): Ensure all fields are copied by Decryptor.
323 decrypted_buffer->set_is_key_frame(
324 pending_buffer_to_decrypt_->is_key_frame());
325 decrypted_buffer->set_duration(pending_buffer_to_decrypt_->duration());
327 pending_buffer_to_decrypt_ = nullptr;
329 std::move(read_cb_).Run(kOk, std::move(decrypted_buffer));
332 void DecryptingDemuxerStream::OnCdmContextEvent(CdmContext::Event event) {
333 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
335 if (event != CdmContext::Event::kHasAdditionalUsableKey)
338 if (state_ == kPendingDecrypt) {
339 key_added_while_decrypt_pending_ = true;
344 if (state_ != kWaitingForKey)
347 CompleteWaitingForDecryptionKey();
348 MEDIA_LOG(INFO, media_log_)
349 << GetDisplayName() << ": key was added, resuming decrypt";
350 state_ = kPendingDecrypt;
351 DecryptPendingBuffer();
354 void DecryptingDemuxerStream::DoReset() {
355 DCHECK(state_ != kUninitialized);
360 std::move(reset_cb_).Run();
363 Decryptor::StreamType DecryptingDemuxerStream::GetDecryptorStreamType() const {
364 if (demuxer_stream_->type() == AUDIO)
365 return Decryptor::kAudio;
367 DCHECK_EQ(demuxer_stream_->type(), VIDEO);
368 return Decryptor::kVideo;
371 void DecryptingDemuxerStream::InitializeDecoderConfig() {
372 // The decoder selector or upstream demuxer make sure the stream is valid.
373 DCHECK(IsStreamValid(demuxer_stream_));
375 // Since |this| is a decrypted version of |demuxer_stream_|, the decoder
376 // config of |this| should always be a decrypted version of |demuxer_stream_|
378 switch (demuxer_stream_->type()) {
380 audio_config_ = demuxer_stream_->audio_decoder_config();
381 if (audio_config_.is_encrypted())
382 audio_config_.SetIsEncrypted(false);
387 video_config_ = demuxer_stream_->video_decoder_config();
388 if (video_config_.is_encrypted())
389 video_config_.SetIsEncrypted(false);
400 void DecryptingDemuxerStream::LogMetadata() {
401 std::vector<AudioDecoderConfig> audio_metadata{audio_config_};
402 std::vector<VideoDecoderConfig> video_metadata{video_config_};
403 media_log_->SetProperty<MediaLogProperty::kAudioTracks>(audio_metadata);
404 media_log_->SetProperty<MediaLogProperty::kVideoTracks>(video_metadata);
405 // FFmpegDemuxer also provides a max diration, start time, and bitrate.
408 void DecryptingDemuxerStream::CompletePendingDecrypt(Decryptor::Status status) {
409 DCHECK_EQ(state_, kPendingDecrypt);
410 TRACE_EVENT_ASYNC_END1("media",
411 "DecryptingDemuxerStream::DecryptPendingBuffer", this,
412 "status", Decryptor::GetStatusName(status));
415 void DecryptingDemuxerStream::CompleteWaitingForDecryptionKey() {
416 DCHECK_EQ(state_, kWaitingForKey);
417 TRACE_EVENT_ASYNC_END0(
418 "media", "DecryptingDemuxerStream::WaitingForDecryptionKey", this);