class AlsaPcmOutputStream;
class AlsaPcmInputStream;
class FakeAudioWorker;
+#if defined(TIZEN_MULTIMEDIA)
+class PipelineImpl;
+#endif
} // namespace media
namespace base {
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 {};
virtual void OnVideoFrameRateChange(absl::optional<int> fps) = 0;
#if defined(TIZEN_MULTIMEDIA)
- virtual void OnRequestSuspend() = 0;
+ virtual void OnRequestSuspend(bool resource_conflicted) = 0;
#endif
};
void OnVideoOpacityChange(bool opaque) final;
void OnVideoFrameRateChange(absl::optional<int> fps) final;
#if defined(TIZEN_MULTIMEDIA)
- void OnRequestSuspend() final;
+ void OnRequestSuspend(bool resource_conflict) final;
void OnRequestSeek(base::TimeDelta time) final;
#endif
#if defined(TIZEN_MULTIMEDIA)
bool renderer_suspended_ = false;
+ base::DelayedTaskHandle request_suspend_task_handle_;
#endif
#if defined(TIZEN_VIDEO_HOLE)
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
}
#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;
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) {
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(
}
#if defined(TIZEN_MULTIMEDIA)
-void PipelineImpl::OnRequestSuspend() {
+void PipelineImpl::OnRequestSuspend(bool resource_conflicted) {
DVLOG(3) << __func__;
- client_->OnRequestSuspend();
+ client_->OnRequestSuspend(resource_conflicted);
}
#endif
void OnRemotePlayStateChange(MediaStatus::State state);
void OnVideoFrameRateChange(absl::optional<int> fps);
#if defined(TIZEN_MULTIMEDIA)
- void OnRequestSuspend();
+ void OnRequestSuspend(bool resource_conflicted);
#endif
// Task completion callbacks from RendererWrapper.
virtual void OnVideoFrameRateChange(absl::optional<int> fps) = 0;
#if defined(TIZEN_MULTIMEDIA)
- virtual void OnRequestSuspend() {}
+ virtual void OnRequestSuspend(bool resource_conflicted) {}
virtual void OnRequestSeek(base::TimeDelta time) {}
#endif
}
#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) {
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
OnWaiting(WaitingReason reason);
[EnableIf=tizen_multimedia]
- OnRequestSuspend();
+ OnRequestSuspend(bool resource_conflicted);
[EnableIf=tizen_multimedia]
OnRequestSeek(mojo_base.mojom.TimeDelta time);
}
#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) {
void OnVideoOpacityChange(bool opaque) final;
void OnVideoFrameRateChange(absl::optional<int> fps) final;
#if defined(TIZEN_MULTIMEDIA)
- void OnRequestSuspend() final;
+ void OnRequestSuspend(bool resource_conflicted) final;
void OnRequestSeek(base::TimeDelta time) final;
#endif
#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
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<AudioTrackList>(*this)),
video_tracks_(MakeGarbageCollected<VideoTrackList>(*this)),
absl::optional<DOMExceptionCode> HTMLMediaElement::Play() {
DVLOG(2) << "play(" << *this << ")";
-#if defined(TIZEN_MULTIMEDIA)
- suspended_by_player_ = false;
-#endif
-
absl::optional<DOMExceptionCode> exception_code =
autoplay_policy_->RequestPlay();
#if BUILDFLAG(IS_TIZEN_TV)
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())
ScheduleEvent(event_type_names::kSuspend);
SetShouldDelayLoadEvent(false);
SetNetworkState(kNetworkIdle);
- suspended_by_player_ = true;
}
#endif
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.
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);
#if defined(TIZEN_MULTIMEDIA)
void Suspend() override;
void Resume() override;
+
+ bool SuspendedByPlayer() override { return was_suspended_by_player_; }
#endif
void OnFrozen() override;
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
LOG(INFO) << "(" << static_cast<void*>(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();
void TizenRendererImpl::OnRequestSuspend(bool resource_conflicted) {
LOG(INFO) << "(" << static_cast<void*>(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)
// Called by player_set_interrupted_cb()
static void InterruptCb(player_interrupted_code_e code, void* data) {
- NOTIMPLEMENTED();
+ DCHECK(data);
+ media::MediaPlayerBridgeCapi* player =
+ static_cast<media::MediaPlayerBridgeCapi*>(data);
+
+ player->OnResourceConflict();
}
} // namespace
}
#endif
+void MediaPlayerBridgeCapi::RequestSuspend(bool resource_conflicted) {
+ LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__;
+ GetMediaPlayerClient()->OnRequestSuspend(resource_conflicted);
+ Suspend();
+}
+
void MediaPlayerBridgeCapi::UpdateMediaType() {
LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__;
int sample_rate = 0;
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<void*>(this) << ") " << __func__;
+ RequestSuspend(true);
+}
+
void MediaPlayerBridgeCapi::OnResumeComplete(bool success) {
NOTIMPLEMENTED();
}
void SetMediaGeometry(const gfx::Rect& viewport_rect,
const gfx::RectF& rect) override;
#endif
+ void RequestSuspend(bool resource_conflicted) override;
void ExecuteDelayedPlayerState();
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);
}
LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__;
- GetMediaPlayerClient()->OnRequestSuspend(true);
+ RequestSuspend(true);
}
void MediaPlayerESPlusPlayer::OnError(const esplusplayer_error_type error) {
}
#endif
-void MediaPlayerESPlusPlayer::RequestSuspend() {
+void MediaPlayerESPlusPlayer::RequestSuspend(bool resource_conflicted) {
LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__;
- GetMediaPlayerClient()->OnRequestSuspend(true);
+ GetMediaPlayerClient()->OnRequestSuspend(resource_conflicted);
Release();
}
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;
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;