[M120 Migration][HBBTV][MM] Support Preloading feature 30/307430/5
authorzhishun.zhou <zhishun.zhou@samsung.com>
Fri, 8 Mar 2024 07:37:34 +0000 (15:37 +0800)
committerYanqing Lu <yanqing.lu@samsung.com>
Tue, 12 Mar 2024 01:15:36 +0000 (01:15 +0000)
Add preload feature for Ligada ADINS tcs.
Which need high performance during video switch.

Patch from:
https://review.tizen.org/gerrit/#/c/292683/

Change-Id: I7c64ff3b89be4b349f343a33f1fdf414f853e4d6
Signed-off-by: xiaofang <fang.xiao@samsung.com>
Signed-off-by: zhishun.zhou <zhishun.zhou@samsung.com>
tizen_src/chromium_impl/media/filters/media_player_bridge_capi.h
tizen_src/chromium_impl/media/filters/media_player_bridge_capi_tv.cc
tizen_src/chromium_impl/media/filters/media_player_bridge_capi_tv.h

index 4085727..efd6250 100644 (file)
 
 typedef struct media_packet_s* media_packet_h;
 
+enum PlayerState {
+  PLAYER_STATE_DELAYED_NULL,
+  PLAYER_STATE_DELAYED_PLAY,
+  PLAYER_STATE_DELAYED_PAUSE,
+  PLAYER_STATE_DELAYED_SEEK,
+};
+
 namespace media {
 class MediaPlayerTizenClient;
 
@@ -145,6 +152,14 @@ class MEDIA_EXPORT MediaPlayerBridgeCapi : public MediaPlayerTizen {
 
   scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
   base::TimeDelta pending_seek_duration_{base::TimeDelta()};
+  MediaTypeFlags media_type_{MediaType::Invalid};
+  int width_{0};
+  int height_{0};
+
+  base::TimeDelta duration_{base::TimeDelta()};
+  bool is_preparing_{false};
+  bool is_play_pending_{false};
+  bool suspended_{false};
 
  private:
   // |duration_update_timer_| related
@@ -171,13 +186,8 @@ class MEDIA_EXPORT MediaPlayerBridgeCapi : public MediaPlayerTizen {
   bool is_file_url_{false};
   bool is_paused_{false};
   bool is_seeking_{false};
-  bool is_play_pending_{false};
   bool is_set_playback_rate_delayed_{false};
-  bool suspended_{false};
-  bool is_preparing_{false};
 
-  int width_{0};
-  int height_{0};
   double playback_rate_{1.0};
   double volume_{0.0};
 
@@ -185,12 +195,9 @@ class MEDIA_EXPORT MediaPlayerBridgeCapi : public MediaPlayerTizen {
   base::RepeatingTimer current_time_update_timer_;
   base::RepeatingTimer buffering_update_timer_;
   std::string user_agent_;
-  base::TimeDelta duration_{base::TimeDelta()};
   base::TimeDelta playback_time_{base::TimeDelta()};
   base::TimeDelta seek_duration_{base::TimeDelta()};
 
-  MediaTypeFlags media_type_{MediaType::Invalid};
-
 #if defined(TIZEN_VIDEO_HOLE)
   bool is_video_hole_{false};
   gfx::Rect delayed_viewport_rect_;
index 5f6a944..c9ece2c 100644 (file)
@@ -12,6 +12,16 @@ namespace {
 const int kSeekableTimeUpdateInterval = 500;
 }
 
+static void PlayerPreLoadingCb(void* data) {
+  if (!data) {
+    LOG(ERROR) << "input data is null";
+    return;
+  }
+  media::MediaPlayerBridgeCapiTV* player =
+      static_cast<media::MediaPlayerBridgeCapiTV*>(data);
+  player->OnPlayerPreloading();
+}
+
 static void DrmErrorCb(int err_code, char* err_str, void* data) {
   DCHECK(data);
   media::MediaPlayerBridgeCapiTV* player =
@@ -86,12 +96,15 @@ void MediaPlayerBridgeCapiTV::Prepare() {
 
   if (blink::IsHbbTV() && CheckHighBitRate() && stream_type_ == DASH_STREAM)
     AppendUrlHighBitRate(url_.spec());
+  player_prepared_ = false;
   MediaPlayerBridgeCapi::Prepare();
   if (GetMediaPlayerClient())
     GetMediaPlayerClient()->NotifyPlaybackState(kPlaybackReady, player_id_);
 }
 
 void MediaPlayerBridgeCapiTV::Release() {
+  is_preloaded_ = false;
+  player_prepared_ = false;
   StopSeekableTimeUpdateTimer();
   MediaPlayerBridgeCapi::Release();
   if (GetMediaPlayerClient())
@@ -99,6 +112,16 @@ void MediaPlayerBridgeCapiTV::Release() {
 }
 
 bool MediaPlayerBridgeCapiTV::Play() {
+  LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__
+            << ",current_time:" << GetCurrentTime().InSecondsF();
+
+  // HBBTV run in preloading and preplay mode. If no prepread do prepare
+  // in PlayerPrePlay(), otherwise do normal Play.
+  if (blink::IsHbbTV() && !player_prepared_) {
+    if (!PlayerPrePlay())
+      LOG(ERROR) << "HBBTV prePlay fail.";
+    return false;
+  }
   if (!MediaPlayerBridgeCapi::Play())
     return false;
   if (GetMediaPlayerClient())
@@ -106,6 +129,16 @@ bool MediaPlayerBridgeCapiTV::Play() {
   return true;
 }
 
+void MediaPlayerBridgeCapiTV::Pause(bool is_media_related_action) {
+  if (!player_prepared_) {
+    LOG(INFO) << "(" << static_cast<void*>(this)
+              << "), pause while player is not prepared, pause delay";
+    delayed_player_state_ = PLAYER_STATE_DELAYED_PAUSE;
+    return;
+  }
+  MediaPlayerBridgeCapi::Pause(is_media_related_action);
+}
+
 void MediaPlayerBridgeCapiTV::PlaybackCompleteUpdate() {
   MediaPlayerBridgeCapi::PlaybackCompleteUpdate();
   if (GetMediaPlayerClient())
@@ -113,10 +146,16 @@ void MediaPlayerBridgeCapiTV::PlaybackCompleteUpdate() {
 }  // namespace media
 
 void MediaPlayerBridgeCapiTV::PlayerPrepared() {
+  player_prepared_ = true;
   MediaPlayerBridgeCapi::PlayerPrepared();
 
+  int canSeek = 0;
+  int retVal = player_seek_available(player_, &canSeek);
+  if (retVal == PLAYER_ERROR_NONE && !canSeek)
+    is_player_seek_available_ = false;
+
   GetAdaptiveStreamingInfo();
-  if (/*!blink::IsHbbTV() && */is_live_stream_) {
+  if (!blink::IsHbbTV() && is_live_stream_) {
     UpdateSeekableTime();
     StartSeekableTimeUpdateTimer();
   }
@@ -282,6 +321,153 @@ void MediaPlayerBridgeCapiTV::HandleDownloadableFontInfo(
                                                     type);
 }
 
+bool MediaPlayerBridgeCapiTV::PreloadIfNeeded(int& ret) {
+  LOG(INFO) << "PreloadIfNeeded, is_preloaded_ " << is_preloaded_;
+  if (blink::IsHbbTV() && !is_preloaded_) {
+    ret = player_preloading_async(player_, -1, PlayerPreLoadingCb, this);
+    return true;
+  }
+
+  // fixup : kPlaybackReady status need checked by HBBTVResourceAcquired() patch
+  if (GetMediaPlayerClient())
+    GetMediaPlayerClient()->NotifyPlaybackState(kPlaybackReady, player_id_);
+  else
+    LOG(ERROR) << "(" << static_cast<void*>(this)
+               << "), GetMediaPlayerClient return null";
+  SetDisplayAtPausedState();
+  return false;
+}
+
+void MediaPlayerBridgeCapiTV::SetDisplayAtPausedState() {
+  int ret = PLAYER_ERROR_NONE;
+  if (!pending_seek_duration_.is_zero())
+    ret = player_display_video_at_paused_state(player_, false);
+  else
+    ret = player_display_video_at_paused_state(player_, true);
+
+  if (ret != PLAYER_ERROR_NONE)
+    LOG(ERROR) << "player_display_video_at_paused_state() failed";
+}
+
+void MediaPlayerBridgeCapiTV::UpdateDuration() {
+  LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__;
+  if (blink::IsHbbTV() && !is_preloaded_) {
+    LOG(INFO) << "HBBTV preload not finished, no need update duration. ";
+    return;
+  }
+  MediaPlayerBridgeCapi::UpdateDuration();
+}
+
+void MediaPlayerBridgeCapiTV::UpdateMediaType() {
+  LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__;
+
+  if (blink::IsHbbTV() && !is_preloaded_) {
+    LOG(INFO) << "HBBTV preload not finished, no need update media type. ";
+    return;
+  }
+  MediaPlayerBridgeCapi::UpdateMediaType();
+}
+
+bool MediaPlayerBridgeCapiTV::CheckLiveStreaming() const {
+  int isLive = 0;
+  int retVal = player_get_adaptive_streaming_info(player_, &isLive,
+                                                  PLAYER_ADAPTIVE_INFO_IS_LIVE);
+  if (retVal != PLAYER_ERROR_NONE) {
+    LOG(ERROR) << "player_get_adaptive_streaming_info failed, error: "
+               << retVal;
+    return false;
+  }
+
+  if (!isLive)
+    return false;
+
+  LOG(INFO) << "This is a live streaming.";
+  return true;
+}
+
+void MediaPlayerBridgeCapiTV::OnPlayerPreloading() {
+  task_runner_->PostTask(
+      FROM_HERE, base::BindOnce(&MediaPlayerBridgeCapiTV::PlayerPreloaded,
+                                weak_factory_.GetWeakPtr()));
+}
+
+bool MediaPlayerBridgeCapiTV::HBBTVResourceAcquired() {
+  bool media_resource_acquired = false;
+  if (!GetMediaPlayerClient()) {
+    LOG(ERROR) << "MediaPlayerTizenClient is nullptr";
+    return false;
+  }
+
+  GetMediaPlayerClient()->NotifyPlaybackState(
+      kPlaybackReady, player_id_, url_.spec(), mime_type_,
+      &media_resource_acquired, NULL, NULL);
+  if (!media_resource_acquired) {
+    GetMediaPlayerClient()->NotifyPlaybackState(kPlaybackStop, player_id_);
+    LOG(ERROR) << "HBBTV media resource acquired failed";
+  }
+  return media_resource_acquired;
+}
+
+void MediaPlayerBridgeCapiTV::PlayerPreloaded() {
+  LOG(INFO) << "PlayerPreloaded,this: " << this
+            << ",player_prepared_:" << player_prepared_;
+
+  is_preloaded_ = true;
+  is_live_stream_ = CheckLiveStreaming();
+  // if (stream_type_ == DASH_STREAM)
+  //  ParseDashInfo();
+  if (is_live_stream_ && stream_type_ != OTHER_STREAM) {
+    // UpdateSeekableTime();
+    // StartSeekableTimeUpdateTimer();
+  }
+  // UpdateAudioTrackInfo();
+  // UpdateVideoTrackInfo();
+  // UpdateTextTrackInfo();
+  UpdateDuration();
+  UpdateMediaType();
+  if (GetMediaType() == MediaType::Invalid) {
+    LOG(ERROR) << "Media type is not valid!";
+    return;
+  }
+
+  OnReadyStateChange(player_id_,
+                     blink::WebMediaPlayer::kReadyStateHaveFutureData);
+  OnNetworkStateChange(player_id_, blink::WebMediaPlayer::kNetworkStateLoading);
+
+  if (!player_prepared_ && HBBTVResourceAcquired()) {
+    int ret = SetPlayerPrepareAsync();
+    if (ret != PLAYER_ERROR_NONE) {
+      OnHandlePlayerError(ret, FROM_HERE);
+    }
+  }
+}
+
+bool MediaPlayerBridgeCapiTV::PlayerPrePlay() {
+  LOG(INFO) << "PlayerPrePlay, this: " << this
+            << ",is_player_prepared : " << player_prepared_;
+  if (IsPlayerSuspended()) {
+    LOG(INFO) << "PlayerPrePlay while player is suspended";
+    return false;
+  }
+
+  if (!HBBTVResourceAcquired()) {
+    LOG(INFO)
+        << "PlayerPrePlay while it's not in case of HBBTV Resource Acquired";
+    return false;
+  }
+
+  delayed_player_state_ = PLAYER_STATE_DELAYED_PLAY;
+  LOG(INFO) << "begin to |player_prepare_async|";
+
+  SetDisplayAtPausedState();
+  int ret = SetPlayerPrepareAsync();
+  if (ret != PLAYER_ERROR_NONE) {
+    OnHandlePlayerError(ret, FROM_HERE);
+    return false;
+  }
+
+  return true;
+}
 void MediaPlayerBridgeCapiTV::Initialize(VideoRendererSink* sink) {
   player_set_drm_error_cb(player_, DrmErrorCb, this);
   MediaPlayerBridgeCapi::Initialize(sink);
index ecebe7d..5cbab59 100644 (file)
@@ -29,14 +29,20 @@ class MEDIA_EXPORT MediaPlayerBridgeCapiTV : public MediaPlayerBridgeCapi {
   bool Play() override;
   void Prepare() override;
   void Release() override;
+  void Pause(bool is_media_related_action) override;
   void SetContentMimeType(const std::string& mime_type) override;
   void PlaybackCompleteUpdate() override;
+  bool PreloadIfNeeded(int& ret) override;
+  void UpdateMediaType() override;
+  void UpdateDuration() override;
+
   void AppendUrlHighBitRate(const std::string& url);
   bool CheckHighBitRate();
   void HandleDownloadableFontInfo(const std::string& scheme_id_uri,
                                   const std::string& value,
                                   const std::string& data,
                                   int type);
+  void OnPlayerPreloading();
 
   void OnDrmError(int err_code, char* err_str);
 
@@ -44,8 +50,15 @@ class MEDIA_EXPORT MediaPlayerBridgeCapiTV : public MediaPlayerBridgeCapi {
   void PlayerPrepared() override;
 
  private:
+  void PlayerPreloaded();
+  bool PlayerPrePlay();
+  void SetDisplayAtPausedState();
+  bool CheckLiveStreaming() const;
+  bool HBBTVResourceAcquired();
   bool SetDrmInfo(std::string& drm_info);
   bool SetMediaDRMInfo(const std::string&, const std::string&);
+  bool is_preloaded_{false};
+  bool is_player_seek_available_{true};
   void StartSeekableTimeUpdateTimer();
   void StopSeekableTimeUpdateTimer();
   void OnSeekableTimeUpdateTimerFired();
@@ -61,7 +74,6 @@ class MEDIA_EXPORT MediaPlayerBridgeCapiTV : public MediaPlayerBridgeCapi {
   base::TimeDelta min_seekable_time_{base::TimeDelta()};
   base::TimeDelta max_seekable_time_{base::TimeDelta()};
   base::RepeatingTimer seekable_time_update_timer_;
-
   // NOTE: Weak pointers must be invalidated before all other member variables.
   base::WeakPtrFactory<MediaPlayerBridgeCapiTV> weak_factory_;
 };