From: Sun-woo Nam Date: Fri, 2 Feb 2024 04:19:46 +0000 (-0800) Subject: [M120 Migration][MM] Migrate patches for suspend and resume. X-Git-Tag: submit/tizen/20240301.160335~49 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=945a6e5b89689679a0de36e89b257fd23a35d124;p=platform%2Fframework%2Fweb%2Fchromium-efl.git [M120 Migration][MM] Migrate patches for suspend and resume. This patch supports suspend and resume behaviors when media goes to background or the mulit-videos scenario. - Handle suspend for Capi Player. Handle suspend request from MediaCapabilityManager and resource conflict. https://review.tizen.org/gerrit/#/c/292279/ - Arrange the suspend logic. Release the esplusplayer when resource is conflicted. https://review.tizen.org/gerrit/#/c/298638/ - Fix potential crash issue Add null check to avoid crash. https://review.tizen.org/gerrit/#/c/300715/ - Fix the media suspend/resume issue between apps. Cancel the request suspend task if it has not been completed when the player is resumed. Flush the player buffer before seek. https://review.tizen.org/gerrit/#/c/298571/ - Distinguish suspend situations based on the resource conflict. The suspend situation by the player is mainly as follows. 1) If there are multiple videos in one content, request suspend by MediaCapabilityManager. 2) Resource conflict occurs when another video plays in another process. In case 1), these suspended videos doon't need to be resumed when the app is suspended and resumed. In case 2), the video should be resumed when the app is suspended and resumed. https://review.tizen.org/gerrit/#/c/299121/ Change-Id: I53a602665458945bd359b89276f3602479fea5e7 Signed-off-by: Sun-woo Nam --- diff --git a/base/task/sequenced_task_runner.h b/base/task/sequenced_task_runner.h index c19f24af99bf..6668ada703f2 100644 --- a/base/task/sequenced_task_runner.h +++ b/base/task/sequenced_task_runner.h @@ -29,6 +29,9 @@ namespace media { class AlsaPcmOutputStream; class AlsaPcmInputStream; class FakeAudioWorker; +#if defined(TIZEN_MULTIMEDIA) +class PipelineImpl; +#endif } // namespace media namespace base { @@ -64,6 +67,9 @@ class PostDelayedTaskPassKey { friend class media::AlsaPcmOutputStream; friend class media::AlsaPcmInputStream; friend class media::FakeAudioWorker; +#if defined(TIZEN_MULTIMEDIA) + friend class media::PipelineImpl; +#endif }; class PostDelayedTaskPassKeyForTesting : public PostDelayedTaskPassKey {}; diff --git a/media/base/pipeline.h b/media/base/pipeline.h index c267f5821677..820473242d7b 100644 --- a/media/base/pipeline.h +++ b/media/base/pipeline.h @@ -90,7 +90,7 @@ class MEDIA_EXPORT Pipeline { virtual void OnVideoFrameRateChange(absl::optional fps) = 0; #if defined(TIZEN_MULTIMEDIA) - virtual void OnRequestSuspend() = 0; + virtual void OnRequestSuspend(bool resource_conflicted) = 0; #endif }; diff --git a/media/base/pipeline_impl.cc b/media/base/pipeline_impl.cc index a25c770b7965..de940d477aa1 100644 --- a/media/base/pipeline_impl.cc +++ b/media/base/pipeline_impl.cc @@ -186,7 +186,7 @@ class PipelineImpl::RendererWrapper final : public DemuxerHost, void OnVideoOpacityChange(bool opaque) final; void OnVideoFrameRateChange(absl::optional fps) final; #if defined(TIZEN_MULTIMEDIA) - void OnRequestSuspend() final; + void OnRequestSuspend(bool resource_conflict) final; void OnRequestSeek(base::TimeDelta time) final; #endif @@ -258,6 +258,7 @@ class PipelineImpl::RendererWrapper final : public DemuxerHost, #if defined(TIZEN_MULTIMEDIA) bool renderer_suspended_ = false; + base::DelayedTaskHandle request_suspend_task_handle_; #endif #if defined(TIZEN_VIDEO_HOLE) @@ -454,6 +455,11 @@ void PipelineImpl::RendererWrapper::Suspend() { SetState(kSuspending); #if defined(TIZEN_MULTIMEDIA) + if (request_suspend_task_handle_.IsValid()) { + LOG(INFO) << " Cancel posted request suspend task if pended."; + request_suspend_task_handle_.CancelTask(); + } + shared_state_.renderer->Suspend(); #endif @@ -503,6 +509,11 @@ void PipelineImpl::RendererWrapper::Resume( } #if defined(TIZEN_MULTIMEDIA) + if (request_suspend_task_handle_.IsValid()) { + LOG(INFO) << " Cancel posted request suspend task if pended."; + request_suspend_task_handle_.CancelTask(); + } + renderer_suspended_ = false; bool default_renderer_created = default_renderer.get() ? true : false; @@ -1014,11 +1025,16 @@ void PipelineImpl::RendererWrapper::ToggleFullscreenMode( shared_state_.renderer->ToggleFullscreenMode(is_fullscreen, std::move(cb)); } -void PipelineImpl::RendererWrapper::OnRequestSuspend() { +void PipelineImpl::RendererWrapper::OnRequestSuspend(bool resource_conflict) { + if (state_ == kSuspending || state_ == kSuspended) + return; + LOG(INFO) << __func__; - main_task_runner_->PostTask( - FROM_HERE, - base::BindOnce(&PipelineImpl::OnRequestSuspend, weak_pipeline_)); + request_suspend_task_handle_ = main_task_runner_->PostCancelableDelayedTask( + base::subtle::PostDelayedTaskPassKey(), FROM_HERE, + base::BindOnce(&PipelineImpl::OnRequestSuspend, weak_pipeline_, + resource_conflict), + base::TimeDelta()); } void PipelineImpl::RendererWrapper::OnRequestSeek(base::TimeDelta time) { @@ -1035,6 +1051,9 @@ void PipelineImpl::RendererWrapper::OnRequestSeek(base::TimeDelta time) { SerialRunner::Queue bound_fns; demuxer_->AbortPendingReads(); + + bound_fns.Push(base::BindOnce( + &Renderer::Flush, base::Unretained(shared_state_.renderer.get()))); bound_fns.Push( base::BindOnce(&Demuxer::Seek, base::Unretained(demuxer_), time)); pending_callbacks_ = SerialRunner::Run( @@ -1888,9 +1907,9 @@ void PipelineImpl::OnVideoPipelineInfoChange(const VideoPipelineInfo& info) { } #if defined(TIZEN_MULTIMEDIA) -void PipelineImpl::OnRequestSuspend() { +void PipelineImpl::OnRequestSuspend(bool resource_conflicted) { DVLOG(3) << __func__; - client_->OnRequestSuspend(); + client_->OnRequestSuspend(resource_conflicted); } #endif diff --git a/media/base/pipeline_impl.h b/media/base/pipeline_impl.h index 374f67116c1a..e8af8a2036dc 100644 --- a/media/base/pipeline_impl.h +++ b/media/base/pipeline_impl.h @@ -188,7 +188,7 @@ class MEDIA_EXPORT PipelineImpl : public Pipeline { void OnRemotePlayStateChange(MediaStatus::State state); void OnVideoFrameRateChange(absl::optional fps); #if defined(TIZEN_MULTIMEDIA) - void OnRequestSuspend(); + void OnRequestSuspend(bool resource_conflicted); #endif // Task completion callbacks from RendererWrapper. diff --git a/media/base/renderer_client.h b/media/base/renderer_client.h index c61a6756e755..7c3321bed4cf 100644 --- a/media/base/renderer_client.h +++ b/media/base/renderer_client.h @@ -67,7 +67,7 @@ class MEDIA_EXPORT RendererClient { virtual void OnVideoFrameRateChange(absl::optional fps) = 0; #if defined(TIZEN_MULTIMEDIA) - virtual void OnRequestSuspend() {} + virtual void OnRequestSuspend(bool resource_conflicted) {} virtual void OnRequestSeek(base::TimeDelta time) {} #endif diff --git a/media/mojo/clients/mojo_renderer.cc b/media/mojo/clients/mojo_renderer.cc index 845273147c32..6285bf44e5ca 100644 --- a/media/mojo/clients/mojo_renderer.cc +++ b/media/mojo/clients/mojo_renderer.cc @@ -427,9 +427,9 @@ void MojoRenderer::OnFlushed() { } #if defined(TIZEN_MULTIMEDIA) -void MojoRenderer::OnRequestSuspend() { +void MojoRenderer::OnRequestSuspend(bool resource_conflicted) { DVLOG(2) << __func__; - client_->OnRequestSuspend(); + client_->OnRequestSuspend(resource_conflicted); } void MojoRenderer::OnRequestSeek(base::TimeDelta time) { diff --git a/media/mojo/clients/mojo_renderer.h b/media/mojo/clients/mojo_renderer.h index 8acf23f0430c..ce8680b9c209 100644 --- a/media/mojo/clients/mojo_renderer.h +++ b/media/mojo/clients/mojo_renderer.h @@ -92,7 +92,7 @@ class MojoRenderer : public Renderer, public mojom::RendererClient { void OnWaiting(WaitingReason reason) override; void OnStatisticsUpdate(const PipelineStatistics& stats) override; #if defined(TIZEN_MULTIMEDIA) - void OnRequestSuspend() override; + void OnRequestSuspend(bool resource_conflicted) override; void OnRequestSeek(base::TimeDelta time) override; #endif diff --git a/media/mojo/mojom/renderer.mojom b/media/mojo/mojom/renderer.mojom index 645fcc3c888d..f6ad6849dd29 100644 --- a/media/mojo/mojom/renderer.mojom +++ b/media/mojo/mojom/renderer.mojom @@ -114,7 +114,7 @@ interface RendererClient { OnWaiting(WaitingReason reason); [EnableIf=tizen_multimedia] - OnRequestSuspend(); + OnRequestSuspend(bool resource_conflicted); [EnableIf=tizen_multimedia] OnRequestSeek(mojo_base.mojom.TimeDelta time); diff --git a/media/mojo/services/mojo_renderer_service.cc b/media/mojo/services/mojo_renderer_service.cc index 30b4420ea4d0..e3b262ff699b 100644 --- a/media/mojo/services/mojo_renderer_service.cc +++ b/media/mojo/services/mojo_renderer_service.cc @@ -244,9 +244,9 @@ void MojoRendererService::OnVideoOpacityChange(bool opaque) { } #if defined(TIZEN_MULTIMEDIA) -void MojoRendererService::OnRequestSuspend() { +void MojoRendererService::OnRequestSuspend(bool resource_conflicted) { DVLOG(2) << __func__; - client_->OnRequestSuspend(); + client_->OnRequestSuspend(resource_conflicted); } void MojoRendererService::OnRequestSeek(base::TimeDelta time) { diff --git a/media/mojo/services/mojo_renderer_service.h b/media/mojo/services/mojo_renderer_service.h index 7474b500c3ca..e6c297ae86aa 100644 --- a/media/mojo/services/mojo_renderer_service.h +++ b/media/mojo/services/mojo_renderer_service.h @@ -105,7 +105,7 @@ class MEDIA_MOJO_EXPORT MojoRendererService final : public mojom::Renderer, void OnVideoOpacityChange(bool opaque) final; void OnVideoFrameRateChange(absl::optional fps) final; #if defined(TIZEN_MULTIMEDIA) - void OnRequestSuspend() final; + void OnRequestSuspend(bool resource_conflicted) final; void OnRequestSeek(base::TimeDelta time) final; #endif diff --git a/third_party/blink/public/platform/web_media_player.h b/third_party/blink/public/platform/web_media_player.h index 573bbe19179f..6b600f68f582 100644 --- a/third_party/blink/public/platform/web_media_player.h +++ b/third_party/blink/public/platform/web_media_player.h @@ -184,6 +184,7 @@ class WebMediaPlayer { #if defined(TIZEN_MULTIMEDIA) virtual void Suspend() {} virtual void Resume() {} + virtual bool SuspendedByPlayer() { return false; } #endif // Called when the backing media element and the page it is attached to is diff --git a/third_party/blink/renderer/core/html/media/html_media_element.cc b/third_party/blink/renderer/core/html/media/html_media_element.cc index c93d8e7866cf..3974d21f4ace 100644 --- a/third_party/blink/renderer/core/html/media/html_media_element.cc +++ b/third_party/blink/renderer/core/html/media/html_media_element.cc @@ -497,9 +497,6 @@ HTMLMediaElement::HTMLMediaElement(const QualifiedName& tag_name, was_always_muted_(true), #if BUILDFLAG(IS_TIZEN_TV) is_deactivate_(false), -#endif -#if defined(TIZEN_MULTIMEDIA) - suspended_by_player_(false), #endif audio_tracks_(MakeGarbageCollected(*this)), video_tracks_(MakeGarbageCollected(*this)), @@ -2787,10 +2784,6 @@ ScriptPromise HTMLMediaElement::playForBindings(ScriptState* script_state) { absl::optional HTMLMediaElement::Play() { DVLOG(2) << "play(" << *this << ")"; -#if defined(TIZEN_MULTIMEDIA) - suspended_by_player_ = false; -#endif - absl::optional exception_code = autoplay_policy_->RequestPlay(); #if BUILDFLAG(IS_TIZEN_TV) @@ -3986,7 +3979,8 @@ void HTMLMediaElement::ContextLifecycleStateChanged( pause(); } } else if (state == mojom::FrameLifecycleState::kRunning) { - if (suspended_by_player_) + // Do not resume if suspended by player except the resource conflict case. + if (GetWebMediaPlayer() && GetWebMediaPlayer()->SuspendedByPlayer()) return; if (GetWebMediaPlayer()) @@ -4823,7 +4817,6 @@ void HTMLMediaElement::SuspendPlayer() { ScheduleEvent(event_type_names::kSuspend); SetShouldDelayLoadEvent(false); SetNetworkState(kNetworkIdle); - suspended_by_player_ = true; } #endif diff --git a/third_party/blink/renderer/core/html/media/html_media_element.h b/third_party/blink/renderer/core/html/media/html_media_element.h index ec1d65e61a14..1613b3a7a828 100644 --- a/third_party/blink/renderer/core/html/media/html_media_element.h +++ b/third_party/blink/renderer/core/html/media/html_media_element.h @@ -883,10 +883,6 @@ class CORE_EXPORT HTMLMediaElement bool suppress_events_ : 1; #endif -#if defined(TIZEN_MULTIMEDIA) - bool suspended_by_player_ : 1; -#endif - // Whether the player disables the Remote Playback feature. bool is_remote_playback_disabled_ = false; // Whether the player is rendering remotely. diff --git a/third_party/blink/renderer/platform/media/web_media_player_impl.cc b/third_party/blink/renderer/platform/media/web_media_player_impl.cc index 55c0dd0fc2e4..0fea41f720c7 100644 --- a/third_party/blink/renderer/platform/media/web_media_player_impl.cc +++ b/third_party/blink/renderer/platform/media/web_media_player_impl.cc @@ -2547,8 +2547,16 @@ void WebMediaPlayerImpl::Resume() { SetSuspendState(false); } -void WebMediaPlayerImpl::OnRequestSuspend() { - was_suspended_by_player_ = true; +void WebMediaPlayerImpl::OnRequestSuspend(bool resource_conflicted) { + if (pipeline_controller_->IsSuspended()) { + LOG(INFO) << __func__ << " Already suspended."; + return; + } + + // Check if suspended by the resource conflict or not. + // If resource is conflicted by other process, it can be resumed. + was_suspended_by_player_ = !resource_conflicted; + client_->PausePlayback(WebMediaPlayerClient::PauseReason::kUnknown); client_->SuspendPlayer(); SetSuspendState(true); diff --git a/third_party/blink/renderer/platform/media/web_media_player_impl.h b/third_party/blink/renderer/platform/media/web_media_player_impl.h index f3fb38dea898..1e380c28d7ac 100644 --- a/third_party/blink/renderer/platform/media/web_media_player_impl.h +++ b/third_party/blink/renderer/platform/media/web_media_player_impl.h @@ -189,6 +189,8 @@ class PLATFORM_EXPORT WebMediaPlayerImpl #if defined(TIZEN_MULTIMEDIA) void Suspend() override; void Resume() override; + + bool SuspendedByPlayer() override { return was_suspended_by_player_; } #endif void OnFrozen() override; @@ -417,7 +419,7 @@ class PLATFORM_EXPORT WebMediaPlayerImpl void OnVideoPipelineInfoChange(const media::VideoPipelineInfo& info) override; #if defined(TIZEN_MULTIMEDIA) // Called if a player in the browser process is suspended. - void OnRequestSuspend() override; + void OnRequestSuspend(bool resource_conflicted) override; void FullscreenModeToggled(); #endif diff --git a/tizen_src/chromium_impl/content/browser/media/tizen_renderer_impl.cc b/tizen_src/chromium_impl/content/browser/media/tizen_renderer_impl.cc index bf5eee2b7fe0..180dcbe19e7c 100644 --- a/tizen_src/chromium_impl/content/browser/media/tizen_renderer_impl.cc +++ b/tizen_src/chromium_impl/content/browser/media/tizen_renderer_impl.cc @@ -279,6 +279,12 @@ void TizenRendererImpl::Suspend() { LOG(INFO) << "(" << static_cast(this) << ") " << __func__; if (is_suspended_) return; + + if (!media_player_) { + LOG(INFO) << "media_player_ is not created yet"; + return; + } + media::MediaPlayerRegistry::GetInstance()->DeactivateMediaPlayer( player_id_, !resource_conflicted_); media_player_->Release(); @@ -468,11 +474,17 @@ void TizenRendererImpl::OnRequestSeek(base::TimeDelta time) { void TizenRendererImpl::OnRequestSuspend(bool resource_conflicted) { LOG(INFO) << "(" << static_cast(this) << ") " << __func__; + + if (is_suspended_) { + LOG(INFO) << " Media is already suspended."; + return; + } + resource_conflicted_ = resource_conflicted; media::MediaPlayerRegistry::GetInstance()->DeactivateMediaPlayer( player_id_, !resource_conflicted_); is_suspended_ = true; - client_->OnRequestSuspend(); + client_->OnRequestSuspend(resource_conflicted); } #if defined(TIZEN_TBM_SUPPORT) diff --git a/tizen_src/chromium_impl/media/filters/media_player_bridge_capi.cc b/tizen_src/chromium_impl/media/filters/media_player_bridge_capi.cc index 1f5fef87276e..2d1b86f24b38 100644 --- a/tizen_src/chromium_impl/media/filters/media_player_bridge_capi.cc +++ b/tizen_src/chromium_impl/media/filters/media_player_bridge_capi.cc @@ -96,7 +96,11 @@ static void ErrorCb(int error_code, void* data) { // Called by player_set_interrupted_cb() static void InterruptCb(player_interrupted_code_e code, void* data) { - NOTIMPLEMENTED(); + DCHECK(data); + media::MediaPlayerBridgeCapi* player = + static_cast(data); + + player->OnResourceConflict(); } } // namespace @@ -542,6 +546,12 @@ void MediaPlayerBridgeCapi::SetMediaGeometry(const gfx::Rect& viewport_rect, } #endif +void MediaPlayerBridgeCapi::RequestSuspend(bool resource_conflicted) { + LOG(INFO) << "(" << static_cast(this) << ") " << __func__; + GetMediaPlayerClient()->OnRequestSuspend(resource_conflicted); + Suspend(); +} + void MediaPlayerBridgeCapi::UpdateMediaType() { LOG(INFO) << "(" << static_cast(this) << ") " << __func__; int sample_rate = 0; @@ -823,6 +833,17 @@ void MediaPlayerBridgeCapi::OnHandlePlayerError( OnMediaError(GetMediaError(player_error_code)); } +void MediaPlayerBridgeCapi::OnResourceConflict() { + if (!task_runner_->BelongsToCurrentThread()) { + task_runner_->PostTask( + FROM_HERE, base::BindOnce(&MediaPlayerBridgeCapi::OnResourceConflict, + weak_factory_.GetWeakPtr())); + return; + } + LOG(INFO) << "(" << static_cast(this) << ") " << __func__; + RequestSuspend(true); +} + void MediaPlayerBridgeCapi::OnResumeComplete(bool success) { NOTIMPLEMENTED(); } diff --git a/tizen_src/chromium_impl/media/filters/media_player_bridge_capi.h b/tizen_src/chromium_impl/media/filters/media_player_bridge_capi.h index b3270c55725b..285780a9f64e 100644 --- a/tizen_src/chromium_impl/media/filters/media_player_bridge_capi.h +++ b/tizen_src/chromium_impl/media/filters/media_player_bridge_capi.h @@ -78,6 +78,7 @@ class MEDIA_EXPORT MediaPlayerBridgeCapi : public MediaPlayerTizen { void SetMediaGeometry(const gfx::Rect& viewport_rect, const gfx::RectF& rect) override; #endif + void RequestSuspend(bool resource_conflicted) override; void ExecuteDelayedPlayerState(); @@ -86,6 +87,7 @@ class MEDIA_EXPORT MediaPlayerBridgeCapi : public MediaPlayerTizen { void OnPlayerPrepared(); void OnHandleBufferingStatus(int percent); void OnHandlePlayerError(int player_error_code, const base::Location& loc); + void OnResourceConflict(); void OnResumeComplete(bool success); void OnMediaPacketUpdated(media_packet_h packet); diff --git a/tizen_src/chromium_impl/media/filters/media_player_esplusplayer.cc b/tizen_src/chromium_impl/media/filters/media_player_esplusplayer.cc index 60a863991386..2739d4a33355 100644 --- a/tizen_src/chromium_impl/media/filters/media_player_esplusplayer.cc +++ b/tizen_src/chromium_impl/media/filters/media_player_esplusplayer.cc @@ -1175,7 +1175,7 @@ void MediaPlayerESPlusPlayer::OnResourceConflict() { } LOG(INFO) << "(" << static_cast(this) << ") " << __func__; - GetMediaPlayerClient()->OnRequestSuspend(true); + RequestSuspend(true); } void MediaPlayerESPlusPlayer::OnError(const esplusplayer_error_type error) { @@ -1342,9 +1342,9 @@ void MediaPlayerESPlusPlayer::PrepareVideoHole() { } #endif -void MediaPlayerESPlusPlayer::RequestSuspend() { +void MediaPlayerESPlusPlayer::RequestSuspend(bool resource_conflicted) { LOG(INFO) << "(" << static_cast(this) << ") " << __func__; - GetMediaPlayerClient()->OnRequestSuspend(true); + GetMediaPlayerClient()->OnRequestSuspend(resource_conflicted); Release(); } diff --git a/tizen_src/chromium_impl/media/filters/media_player_esplusplayer.h b/tizen_src/chromium_impl/media/filters/media_player_esplusplayer.h index e0541deae94d..40bf0d041736 100644 --- a/tizen_src/chromium_impl/media/filters/media_player_esplusplayer.h +++ b/tizen_src/chromium_impl/media/filters/media_player_esplusplayer.h @@ -91,7 +91,7 @@ class MEDIA_EXPORT MediaPlayerESPlusPlayer : public MediaPlayerTizen { void OnBufferingStatusChanged(DemuxerStream::Type type, BufferStatus status); - void RequestSuspend() override; + void RequestSuspend(bool resource_conflicted) override; MediaTypeFlags GetMediaType() const override { return media_type_; } void SetMediaType(DemuxerStream::Type type) override; diff --git a/tizen_src/chromium_impl/media/filters/media_player_tizen.h b/tizen_src/chromium_impl/media/filters/media_player_tizen.h index 4cb73087eeba..2e4d9749ff8c 100644 --- a/tizen_src/chromium_impl/media/filters/media_player_tizen.h +++ b/tizen_src/chromium_impl/media/filters/media_player_tizen.h @@ -82,7 +82,7 @@ class MEDIA_EXPORT MediaPlayerTizen { const gfx::RectF& rect) = 0; virtual void PrepareVideoHole() {} #endif - virtual void RequestSuspend() {} + virtual void RequestSuspend(bool resource_conflicted = false) = 0; virtual MediaTypeFlags GetMediaType() const = 0; virtual void SetMediaType(DemuxerStream::Type type) = 0;