mojo_renderer_service.cc 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287
  1. // Copyright 2014 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/mojo/services/mojo_renderer_service.h"
  5. #include <memory>
  6. #include <utility>
  7. #include "base/bind.h"
  8. #include "base/memory/ptr_util.h"
  9. #include "media/base/cdm_context.h"
  10. #include "media/base/media_url_demuxer.h"
  11. #include "media/base/renderer.h"
  12. #include "media/mojo/common/media_type_converters.h"
  13. #include "media/mojo/services/media_resource_shim.h"
  14. #include "media/mojo/services/mojo_cdm_service_context.h"
  15. #include "third_party/abseil-cpp/absl/types/optional.h"
  16. namespace media {
  17. // Time interval to update media time.
  18. const int kTimeUpdateIntervalMs = 50;
  19. // static
  20. mojo::SelfOwnedReceiverRef<mojom::Renderer> MojoRendererService::Create(
  21. MojoCdmServiceContext* mojo_cdm_service_context,
  22. std::unique_ptr<media::Renderer> renderer,
  23. mojo::PendingReceiver<mojom::Renderer> receiver) {
  24. MojoRendererService* service =
  25. new MojoRendererService(mojo_cdm_service_context, std::move(renderer));
  26. mojo::SelfOwnedReceiverRef<mojom::Renderer> self_owned_receiver =
  27. mojo::MakeSelfOwnedReceiver<mojom::Renderer>(base::WrapUnique(service),
  28. std::move(receiver));
  29. return self_owned_receiver;
  30. }
  31. MojoRendererService::MojoRendererService(
  32. MojoCdmServiceContext* mojo_cdm_service_context,
  33. std::unique_ptr<media::Renderer> renderer)
  34. : mojo_cdm_service_context_(mojo_cdm_service_context),
  35. state_(STATE_UNINITIALIZED),
  36. playback_rate_(0),
  37. renderer_(std::move(renderer)) {
  38. DVLOG(1) << __func__;
  39. DCHECK(renderer_);
  40. weak_this_ = weak_factory_.GetWeakPtr();
  41. }
  42. MojoRendererService::~MojoRendererService() = default;
  43. void MojoRendererService::Initialize(
  44. mojo::PendingAssociatedRemote<mojom::RendererClient> client,
  45. absl::optional<std::vector<mojo::PendingRemote<mojom::DemuxerStream>>>
  46. streams,
  47. mojom::MediaUrlParamsPtr media_url_params,
  48. InitializeCallback callback) {
  49. DVLOG(1) << __func__;
  50. DCHECK_EQ(state_, STATE_UNINITIALIZED);
  51. client_.Bind(std::move(client));
  52. state_ = STATE_INITIALIZING;
  53. if (!media_url_params) {
  54. DCHECK(streams.has_value());
  55. media_resource_ = std::make_unique<MediaResourceShim>(
  56. std::move(*streams),
  57. base::BindOnce(&MojoRendererService::OnAllStreamsReady, weak_this_,
  58. std::move(callback)));
  59. return;
  60. }
  61. DCHECK(!media_url_params->media_url.is_empty());
  62. media_resource_ = std::make_unique<MediaUrlDemuxer>(
  63. nullptr, media_url_params->media_url, media_url_params->site_for_cookies,
  64. media_url_params->top_frame_origin, media_url_params->allow_credentials,
  65. media_url_params->is_hls);
  66. renderer_->Initialize(
  67. media_resource_.get(), this,
  68. base::BindOnce(&MojoRendererService::OnRendererInitializeDone, weak_this_,
  69. std::move(callback)));
  70. }
  71. void MojoRendererService::Flush(FlushCallback callback) {
  72. DVLOG(2) << __func__;
  73. DCHECK_EQ(state_, STATE_PLAYING);
  74. state_ = STATE_FLUSHING;
  75. CancelPeriodicMediaTimeUpdates();
  76. renderer_->Flush(base::BindOnce(&MojoRendererService::OnFlushCompleted,
  77. weak_this_, std::move(callback)));
  78. }
  79. void MojoRendererService::StartPlayingFrom(base::TimeDelta time_delta) {
  80. DVLOG(2) << __func__ << ": " << time_delta;
  81. renderer_->StartPlayingFrom(time_delta);
  82. SchedulePeriodicMediaTimeUpdates();
  83. }
  84. void MojoRendererService::SetPlaybackRate(double playback_rate) {
  85. DVLOG(2) << __func__ << ": " << playback_rate;
  86. DCHECK(state_ == STATE_PLAYING || state_ == STATE_ERROR);
  87. playback_rate_ = playback_rate;
  88. renderer_->SetPlaybackRate(playback_rate);
  89. }
  90. void MojoRendererService::SetVolume(float volume) {
  91. renderer_->SetVolume(volume);
  92. }
  93. void MojoRendererService::SetCdm(
  94. const absl::optional<base::UnguessableToken>& cdm_id,
  95. SetCdmCallback callback) {
  96. if (cdm_context_ref_) {
  97. DVLOG(1) << "Switching CDM not supported";
  98. std::move(callback).Run(false);
  99. return;
  100. }
  101. if (!mojo_cdm_service_context_) {
  102. DVLOG(1) << "CDM service context not available.";
  103. std::move(callback).Run(false);
  104. return;
  105. }
  106. if (!cdm_id) {
  107. DVLOG(1) << "The CDM ID is invalid.";
  108. std::move(callback).Run(false);
  109. return;
  110. }
  111. auto cdm_context_ref =
  112. mojo_cdm_service_context_->GetCdmContextRef(cdm_id.value());
  113. if (!cdm_context_ref) {
  114. DVLOG(1) << "CdmContextRef not found for CDM ID: " << cdm_id.value();
  115. std::move(callback).Run(false);
  116. return;
  117. }
  118. // |cdm_context_ref_| must be kept as long as |cdm_context| is used by the
  119. // |renderer_|.
  120. cdm_context_ref_ = std::move(cdm_context_ref);
  121. auto* cdm_context = cdm_context_ref_->GetCdmContext();
  122. DCHECK(cdm_context);
  123. renderer_->SetCdm(cdm_context,
  124. base::BindOnce(&MojoRendererService::OnCdmAttached,
  125. weak_this_, std::move(callback)));
  126. }
  127. void MojoRendererService::OnError(PipelineStatus error) {
  128. DVLOG(1) << __func__ << "(" << error << ")";
  129. state_ = STATE_ERROR;
  130. client_->OnError(std::move(error));
  131. }
  132. void MojoRendererService::OnFallback(PipelineStatus error) {
  133. NOTREACHED();
  134. }
  135. void MojoRendererService::OnEnded() {
  136. DVLOG(1) << __func__;
  137. CancelPeriodicMediaTimeUpdates();
  138. client_->OnEnded();
  139. }
  140. void MojoRendererService::OnStatisticsUpdate(const PipelineStatistics& stats) {
  141. DVLOG(3) << __func__;
  142. client_->OnStatisticsUpdate(stats);
  143. }
  144. void MojoRendererService::OnBufferingStateChange(
  145. BufferingState state,
  146. BufferingStateChangeReason reason) {
  147. DVLOG(2) << __func__ << "(" << state << ", " << reason << ")";
  148. client_->OnBufferingStateChange(state, reason);
  149. }
  150. void MojoRendererService::OnWaiting(WaitingReason reason) {
  151. DVLOG(1) << __func__;
  152. client_->OnWaiting(reason);
  153. }
  154. void MojoRendererService::OnAudioConfigChange(
  155. const AudioDecoderConfig& config) {
  156. DVLOG(2) << __func__ << "(" << config.AsHumanReadableString() << ")";
  157. client_->OnAudioConfigChange(config);
  158. }
  159. void MojoRendererService::OnVideoConfigChange(
  160. const VideoDecoderConfig& config) {
  161. DVLOG(2) << __func__ << "(" << config.AsHumanReadableString() << ")";
  162. client_->OnVideoConfigChange(config);
  163. }
  164. void MojoRendererService::OnVideoNaturalSizeChange(const gfx::Size& size) {
  165. DVLOG(2) << __func__ << "(" << size.ToString() << ")";
  166. client_->OnVideoNaturalSizeChange(size);
  167. }
  168. void MojoRendererService::OnVideoOpacityChange(bool opaque) {
  169. DVLOG(2) << __func__ << "(" << opaque << ")";
  170. client_->OnVideoOpacityChange(opaque);
  171. }
  172. void MojoRendererService::OnVideoFrameRateChange(absl::optional<int> fps) {
  173. DVLOG(2) << __func__ << "(" << (fps ? *fps : -1) << ")";
  174. // TODO(liberato): plumb to |client_|.
  175. }
  176. void MojoRendererService::OnAllStreamsReady(
  177. base::OnceCallback<void(bool)> callback) {
  178. DCHECK_EQ(state_, STATE_INITIALIZING);
  179. renderer_->Initialize(
  180. media_resource_.get(), this,
  181. base::BindOnce(&MojoRendererService::OnRendererInitializeDone, weak_this_,
  182. std::move(callback)));
  183. }
  184. void MojoRendererService::OnRendererInitializeDone(
  185. base::OnceCallback<void(bool)> callback,
  186. PipelineStatus status) {
  187. DVLOG(1) << __func__;
  188. DCHECK_EQ(state_, STATE_INITIALIZING);
  189. if (status != PIPELINE_OK) {
  190. state_ = STATE_ERROR;
  191. std::move(callback).Run(false);
  192. return;
  193. }
  194. state_ = STATE_PLAYING;
  195. std::move(callback).Run(true);
  196. }
  197. void MojoRendererService::UpdateMediaTime(bool force) {
  198. const base::TimeDelta media_time = renderer_->GetMediaTime();
  199. if (!force && media_time == last_media_time_)
  200. return;
  201. base::TimeDelta max_time = media_time;
  202. // Allow some slop to account for delays in scheduling time update tasks.
  203. if (time_update_timer_.IsRunning() && (playback_rate_ > 0))
  204. max_time += base::Milliseconds(2 * kTimeUpdateIntervalMs);
  205. client_->OnTimeUpdate(media_time, max_time, base::TimeTicks::Now());
  206. last_media_time_ = media_time;
  207. }
  208. void MojoRendererService::CancelPeriodicMediaTimeUpdates() {
  209. DVLOG(2) << __func__;
  210. time_update_timer_.Stop();
  211. UpdateMediaTime(false);
  212. }
  213. void MojoRendererService::SchedulePeriodicMediaTimeUpdates() {
  214. DVLOG(2) << __func__;
  215. UpdateMediaTime(true);
  216. time_update_timer_.Start(
  217. FROM_HERE, base::Milliseconds(kTimeUpdateIntervalMs),
  218. base::BindRepeating(&MojoRendererService::UpdateMediaTime, weak_this_,
  219. false));
  220. }
  221. void MojoRendererService::OnFlushCompleted(FlushCallback callback) {
  222. DVLOG(1) << __func__;
  223. DCHECK_EQ(state_, STATE_FLUSHING);
  224. state_ = STATE_PLAYING;
  225. std::move(callback).Run();
  226. }
  227. void MojoRendererService::OnCdmAttached(base::OnceCallback<void(bool)> callback,
  228. bool success) {
  229. DVLOG(1) << __func__ << "(" << success << ")";
  230. if (!success)
  231. cdm_context_ref_.reset();
  232. std::move(callback).Run(success);
  233. }
  234. } // namespace media