decoder_buffer_transcryptor.cc 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. // Copyright 2021 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. #include "media/gpu/chromeos/decoder_buffer_transcryptor.h"
  5. #include "base/callback.h"
  6. #include "chromeos/components/cdm_factory_daemon/chromeos_cdm_context.h"
  7. #include "media/base/bind_to_current_loop.h"
  8. namespace media {
  9. DecoderBufferTranscryptor::TranscryptTask::TranscryptTask(
  10. scoped_refptr<DecoderBuffer> buffer,
  11. VideoDecoder::DecodeCB decode_done_cb)
  12. : buffer(std::move(buffer)), decode_done_cb(std::move(decode_done_cb)) {}
  13. DecoderBufferTranscryptor::TranscryptTask::~TranscryptTask() = default;
  14. DecoderBufferTranscryptor::TranscryptTask::TranscryptTask(TranscryptTask&&) =
  15. default;
  16. DecoderBufferTranscryptor::DecoderBufferTranscryptor(
  17. CdmContext* cdm_context,
  18. OnBufferTranscryptedCB transcrypt_callback,
  19. WaitingCB waiting_callback)
  20. : transcrypt_callback_(std::move(transcrypt_callback)),
  21. waiting_callback_(std::move(waiting_callback)) {
  22. weak_this_ = weak_this_factory_.GetWeakPtr();
  23. DCHECK(cdm_context);
  24. cdm_event_cb_registration_ = cdm_context->RegisterEventCB(base::BindRepeating(
  25. &DecoderBufferTranscryptor::OnCdmContextEvent, weak_this_));
  26. cdm_context_ref_ = cdm_context->GetChromeOsCdmContext()->GetCdmContextRef();
  27. DCHECK(cdm_context->GetDecryptor());
  28. }
  29. DecoderBufferTranscryptor::~DecoderBufferTranscryptor() {
  30. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  31. Reset(DecoderStatus::Codes::kAborted);
  32. }
  33. void DecoderBufferTranscryptor::EnqueueBuffer(
  34. scoped_refptr<DecoderBuffer> buffer,
  35. VideoDecoder::DecodeCB decode_cb) {
  36. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  37. transcrypt_task_queue_.emplace(std::move(buffer), std::move(decode_cb));
  38. DecryptPendingBuffer();
  39. }
  40. void DecoderBufferTranscryptor::Reset(DecoderStatus status) {
  41. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  42. if (current_transcrypt_task_) {
  43. std::move(current_transcrypt_task_->decode_done_cb).Run(status);
  44. current_transcrypt_task_ = absl::nullopt;
  45. }
  46. while (!transcrypt_task_queue_.empty()) {
  47. std::move(transcrypt_task_queue_.front().decode_done_cb).Run(status);
  48. transcrypt_task_queue_.pop();
  49. }
  50. }
  51. void DecoderBufferTranscryptor::OnCdmContextEvent(CdmContext::Event event) {
  52. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  53. if (event != CdmContext::Event::kHasAdditionalUsableKey)
  54. return;
  55. if (transcrypt_pending_)
  56. key_added_while_decrypting_ = true;
  57. else
  58. DecryptPendingBuffer();
  59. }
  60. void DecoderBufferTranscryptor::DecryptPendingBuffer() {
  61. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  62. if (transcrypt_pending_)
  63. return;
  64. if (!current_transcrypt_task_) {
  65. if (transcrypt_task_queue_.empty())
  66. return;
  67. current_transcrypt_task_ = std::move(transcrypt_task_queue_.front());
  68. transcrypt_task_queue_.pop();
  69. }
  70. if (current_transcrypt_task_->buffer->end_of_stream()) {
  71. OnBufferTranscrypted(Decryptor::kSuccess, current_transcrypt_task_->buffer);
  72. return;
  73. }
  74. transcrypt_pending_ = true;
  75. cdm_context_ref_->GetCdmContext()->GetDecryptor()->Decrypt(
  76. Decryptor::kVideo, current_transcrypt_task_->buffer,
  77. BindToCurrentLoop(base::BindOnce(
  78. &DecoderBufferTranscryptor::OnBufferTranscrypted, weak_this_)));
  79. }
  80. void DecoderBufferTranscryptor::OnBufferTranscrypted(
  81. Decryptor::Status status,
  82. scoped_refptr<DecoderBuffer> transcrypted_buffer) {
  83. DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
  84. transcrypt_pending_ = false;
  85. // If we've cleared the task then drop this one.
  86. if (!current_transcrypt_task_) {
  87. DecryptPendingBuffer();
  88. return;
  89. }
  90. const bool need_to_try_again_if_nokey = key_added_while_decrypting_;
  91. key_added_while_decrypting_ = false;
  92. // This should never happen w/our decryptor.
  93. DCHECK_NE(status, Decryptor::kNeedMoreData);
  94. if (status == Decryptor::kError) {
  95. // Clear |current_transcrypt_task_| now so when the pipeline invokes Reset
  96. // on us we don't try to invoke the move'd callback.
  97. absl::optional<TranscryptTask> temp_task =
  98. std::move(current_transcrypt_task_);
  99. current_transcrypt_task_ = absl::nullopt;
  100. transcrypt_callback_.Run(nullptr, std::move(temp_task->decode_done_cb));
  101. return;
  102. }
  103. if (status == Decryptor::kNoKey) {
  104. if (need_to_try_again_if_nokey) {
  105. DecryptPendingBuffer();
  106. return;
  107. }
  108. waiting_callback_.Run(WaitingReason::kNoDecryptionKey);
  109. return;
  110. }
  111. DCHECK_EQ(status, Decryptor::kSuccess);
  112. DCHECK(transcrypted_buffer);
  113. const bool eos_buffer = transcrypted_buffer->end_of_stream();
  114. absl::optional<TranscryptTask> temp_task =
  115. std::move(current_transcrypt_task_);
  116. current_transcrypt_task_ = absl::nullopt;
  117. transcrypt_callback_.Run(std::move(transcrypted_buffer),
  118. std::move(temp_task->decode_done_cb));
  119. // Do not post this as another task, execute it immediately instead. Otherwise
  120. // we will not be parallelizing decrypt and decode fully. We want to have the
  121. // Mojo IPC call for decrypt active whenever we are processing a decode task,
  122. // and since the decoder probably just put a decode task in the queue...if we
  123. // hand control back to the task runner it'll do decode now even though we
  124. // have no decrypt task in flight.
  125. if (!eos_buffer)
  126. DecryptPendingBuffer();
  127. }
  128. } // namespace media