decrypting_renderer.cc 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. // Copyright 2018 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/renderers/decrypting_renderer.h"
  5. #include "base/bind.h"
  6. #include "base/callback_helpers.h"
  7. #include "media/base/cdm_context.h"
  8. #include "media/base/demuxer_stream.h"
  9. #include "media/base/media_log.h"
  10. #include "media/base/media_resource.h"
  11. #include "media/base/renderer_client.h"
  12. #include "media/filters/decrypting_demuxer_stream.h"
  13. #include "media/filters/decrypting_media_resource.h"
  14. namespace media {
  15. DecryptingRenderer::DecryptingRenderer(
  16. std::unique_ptr<Renderer> renderer,
  17. MediaLog* media_log,
  18. const scoped_refptr<base::SingleThreadTaskRunner> media_task_runner)
  19. : renderer_(std::move(renderer)),
  20. media_log_(media_log),
  21. media_task_runner_(media_task_runner),
  22. client_(nullptr),
  23. media_resource_(nullptr),
  24. decrypting_media_resource_(nullptr) {
  25. DCHECK(renderer_);
  26. }
  27. DecryptingRenderer::~DecryptingRenderer() {}
  28. // The behavior of Initialize():
  29. //
  30. // Streams CdmContext Action
  31. // ---------------------------------------------------------------------
  32. // Clear nullptr InitializeRenderer()
  33. // Clear AesDecryptor CreateAndInitializeDecryptingMediaResource()
  34. // Clear Other InitializeRenderer()
  35. // Encrypted nullptr Wait
  36. // Encrypted AesDecryptor CreateAndInitializeDecryptingMediaResource()
  37. // Encrypted Other InitializeRenderer()
  38. void DecryptingRenderer::Initialize(MediaResource* media_resource,
  39. RendererClient* client,
  40. PipelineStatusCallback init_cb) {
  41. DCHECK(media_task_runner_->BelongsToCurrentThread());
  42. DCHECK(media_resource);
  43. DCHECK(client);
  44. // Using |this| with a MediaResource::Type::URL will result in a crash.
  45. DCHECK_EQ(media_resource->GetType(), MediaResource::Type::STREAM);
  46. media_resource_ = media_resource;
  47. client_ = client;
  48. init_cb_ = std::move(init_cb);
  49. bool has_encrypted_stream = HasEncryptedStream();
  50. // If we do not have a valid |cdm_context_| and there are encrypted streams we
  51. // need to wait.
  52. if (!cdm_context_ && has_encrypted_stream) {
  53. waiting_for_cdm_ = true;
  54. return;
  55. }
  56. if (cdm_context_ && cdm_context_->GetDecryptor() &&
  57. cdm_context_->GetDecryptor()->CanAlwaysDecrypt()) {
  58. CreateAndInitializeDecryptingMediaResource();
  59. return;
  60. }
  61. InitializeRenderer(true);
  62. }
  63. void DecryptingRenderer::SetCdm(CdmContext* cdm_context,
  64. CdmAttachedCB cdm_attached_cb) {
  65. DCHECK(media_task_runner_->BelongsToCurrentThread());
  66. if (cdm_context_) {
  67. DVLOG(1) << "Switching CDM not supported.";
  68. std::move(cdm_attached_cb).Run(false);
  69. return;
  70. }
  71. cdm_context_ = cdm_context;
  72. // If we are using an AesDecryptor all decryption will be handled by the
  73. // DecryptingMediaResource instead of the renderer implementation.
  74. if (cdm_context_->GetDecryptor() &&
  75. cdm_context_->GetDecryptor()->CanAlwaysDecrypt()) {
  76. // If Initialize() was invoked prior to this function then
  77. // |waiting_for_cdm_| will be true (if we reached this branch). In this
  78. // scenario we want to initialize the DecryptingMediaResource here.
  79. if (waiting_for_cdm_)
  80. CreateAndInitializeDecryptingMediaResource();
  81. std::move(cdm_attached_cb).Run(true);
  82. return;
  83. }
  84. renderer_->SetCdm(cdm_context_, std::move(cdm_attached_cb));
  85. // We only want to initialize the renderer if we were waiting for the
  86. // CdmContext, otherwise it will already have been initialized.
  87. if (waiting_for_cdm_)
  88. InitializeRenderer(true);
  89. }
  90. void DecryptingRenderer::SetLatencyHint(
  91. absl::optional<base::TimeDelta> latency_hint) {
  92. renderer_->SetLatencyHint(latency_hint);
  93. }
  94. void DecryptingRenderer::SetPreservesPitch(bool preserves_pitch) {
  95. renderer_->SetPreservesPitch(preserves_pitch);
  96. }
  97. void DecryptingRenderer::SetWasPlayedWithUserActivation(
  98. bool was_played_with_user_activation) {
  99. renderer_->SetWasPlayedWithUserActivation(was_played_with_user_activation);
  100. }
  101. void DecryptingRenderer::Flush(base::OnceClosure flush_cb) {
  102. renderer_->Flush(std::move(flush_cb));
  103. }
  104. void DecryptingRenderer::StartPlayingFrom(base::TimeDelta time) {
  105. renderer_->StartPlayingFrom(time);
  106. }
  107. void DecryptingRenderer::SetPlaybackRate(double playback_rate) {
  108. renderer_->SetPlaybackRate(playback_rate);
  109. }
  110. void DecryptingRenderer::SetVolume(float volume) {
  111. renderer_->SetVolume(volume);
  112. }
  113. base::TimeDelta DecryptingRenderer::GetMediaTime() {
  114. return renderer_->GetMediaTime();
  115. }
  116. void DecryptingRenderer::OnSelectedVideoTracksChanged(
  117. const std::vector<DemuxerStream*>& enabled_tracks,
  118. base::OnceClosure change_completed_cb) {
  119. renderer_->OnSelectedVideoTracksChanged(enabled_tracks,
  120. std::move(change_completed_cb));
  121. }
  122. void DecryptingRenderer::OnEnabledAudioTracksChanged(
  123. const std::vector<DemuxerStream*>& enabled_tracks,
  124. base::OnceClosure change_completed_cb) {
  125. renderer_->OnEnabledAudioTracksChanged(enabled_tracks,
  126. std::move(change_completed_cb));
  127. }
  128. void DecryptingRenderer::CreateAndInitializeDecryptingMediaResource() {
  129. DCHECK(media_task_runner_->BelongsToCurrentThread());
  130. DCHECK(init_cb_);
  131. decrypting_media_resource_ = std::make_unique<DecryptingMediaResource>(
  132. media_resource_, cdm_context_, media_log_, media_task_runner_);
  133. decrypting_media_resource_->Initialize(
  134. base::BindOnce(&DecryptingRenderer::InitializeRenderer,
  135. weak_factory_.GetWeakPtr()),
  136. base::BindRepeating(&DecryptingRenderer::OnWaiting,
  137. weak_factory_.GetWeakPtr()));
  138. }
  139. void DecryptingRenderer::InitializeRenderer(bool success) {
  140. DCHECK(media_task_runner_->BelongsToCurrentThread());
  141. if (!success) {
  142. std::move(init_cb_).Run(PIPELINE_ERROR_INITIALIZATION_FAILED);
  143. return;
  144. }
  145. // |decrypting_media_resource_| when |cdm_context_| is null and there are no
  146. // encrypted streams.
  147. MediaResource* const maybe_decrypting_media_resource =
  148. decrypting_media_resource_ ? decrypting_media_resource_.get()
  149. : media_resource_.get();
  150. renderer_->Initialize(maybe_decrypting_media_resource, client_,
  151. std::move(init_cb_));
  152. }
  153. bool DecryptingRenderer::HasEncryptedStream() {
  154. DCHECK(media_task_runner_->BelongsToCurrentThread());
  155. for (auto* stream : media_resource_->GetAllStreams()) {
  156. if ((stream->type() == DemuxerStream::AUDIO &&
  157. stream->audio_decoder_config().is_encrypted()) ||
  158. (stream->type() == DemuxerStream::VIDEO &&
  159. stream->video_decoder_config().is_encrypted())) {
  160. return true;
  161. }
  162. }
  163. return false;
  164. }
  165. bool DecryptingRenderer::HasDecryptingMediaResourceForTesting() const {
  166. return decrypting_media_resource_ != nullptr;
  167. }
  168. void DecryptingRenderer::OnWaiting(WaitingReason reason) {
  169. DCHECK(media_task_runner_->BelongsToCurrentThread());
  170. client_->OnWaiting(reason);
  171. }
  172. } // namespace media