[M130 Migration][HBBTV] Porting TA feature 65/325065/2
authorMichal Jurkiewicz/Web Solutions (VD) /SRPOL <m.jurkiewicz@samsung.com>
Fri, 17 May 2024 10:20:17 +0000 (11:20 +0100)
committerBot Blink <blinkbot@samsung.com>
Mon, 2 Jun 2025 13:18:30 +0000 (13:18 +0000)
Ported commit:
https://review.tizen.org/gerrit/c/platform/framework/web/chromium-efl/+/317586
https://review.tizen.org/gerrit/c/platform/framework/web/chromium-efl/+/314923

Bug: https://jira-eu.sec.samsung.net/browse/VDWASM-1817
Signed-off-by: Robert Bycul <r.bycul@samsung.com>
Signed-off-by: Kajetan Brzuszczak <k.brzuszczak@partner.samsung.com>
Change-Id: Ica879e38b1985c803535dd08d17a3db4901e12da

20 files changed:
media/base/pipeline.h
media/base/pipeline_impl.cc
media/base/pipeline_impl.h
media/base/renderer_client.h
media/mojo/mojom/renderer_extensions.mojom
third_party/blink/renderer/platform/media/web_media_player_impl.cc
third_party/blink/renderer/platform/media/web_media_player_impl.h
tizen_src/chromium_impl/content/browser/media/tizen_renderer_impl.cc
tizen_src/chromium_impl/content/browser/media/tizen_renderer_impl.h
tizen_src/chromium_impl/content/renderer/media/tizen/media_player_renderer_client.cc
tizen_src/chromium_impl/content/renderer/media/tizen/media_player_renderer_client.h
tizen_src/chromium_impl/media/filters/media_player_esplusplayer.cc
tizen_src/chromium_impl/media/filters/media_player_esplusplayer_tv.cc
tizen_src/chromium_impl/media/filters/media_player_esplusplayer_tv.h
tizen_src/chromium_impl/media/filters/media_player_tizen.h
tizen_src/chromium_impl/media/filters/media_player_tizen_client.h
tizen_src/ewk/efl_integration/eweb_view.cc
tizen_src/ewk/efl_integration/eweb_view.h
tizen_src/ewk/efl_integration/public/ewk_view.cc
tizen_src/ewk/efl_integration/public/ewk_view_product.h

index abc5cea75097a191c79bb0f7d05442e8cbfc5d99..c3ab0df5c1847e7d573e8a619921de77057ed605 100644 (file)
@@ -110,6 +110,9 @@ class MEDIA_EXPORT Pipeline {
     virtual void OnMrsUrlChange(const std::string& url) {}
     virtual void OnContentIdChange(const std::string& id) {}
     virtual void OnInitData(const std::vector<unsigned char>& init_data) = 0;
+    virtual void RequestPlay() {}
+    virtual void RequestPause() {}
+    virtual void RequestResume() {}
 #endif
 
     // Executed whenever the presentation duration changes.
index 1311b97099acc06d223637b48766815dd72ef16a..476ebc9803cf1e6f1959caa9955829f92a076798 100644 (file)
@@ -146,6 +146,7 @@ class PipelineImpl::RendererWrapper final : public DemuxerHost,
                     int64_t wallclock_pos,
                     int tolerance);
   bool SetWallClock(const std::string& wallclock_url);
+  void OnUpdatePlayerID(int player_id) override;
   void Activate();
   void Deactivate();
   void Show();
@@ -156,6 +157,10 @@ class PipelineImpl::RendererWrapper final : public DemuxerHost,
   void OnDemuxerFpsGot(int num, int den);
   void SetDecryptorHandle(eme::eme_decryptor_t decryptor);
   void SetHasEncryptedListenerOrCdm(bool value);
+
+  void RequestPlay() override;
+  void RequestPause() override;
+  void RequestResume() override;
 #endif
 
   // |enabled_track_ids| contains track ids of enabled audio tracks.
@@ -244,7 +249,7 @@ class PipelineImpl::RendererWrapper final : public DemuxerHost,
 #if BUILDFLAG(IS_TIZEN_TV)
   void UpdateVideoId(int player_id) final;
   void NotifyTrackInfoToBrowser(int active_track_id) final;
-  void AddTrackInfo(media::MediaTrackInfo trackinfo);
+  void AddTrackInfo(media::MediaTrackInfo trackinfo) override;
   void OnRegisterTimelineCbInfo(register_timeline_cb_info_s info) final;
   void OnSyncTimelineCbInfo(const std::string& timeline_selector,
                             int sync) final;
@@ -261,7 +266,7 @@ class PipelineImpl::RendererWrapper final : public DemuxerHost,
   void GetContentIdCB(const std::string& content_id);
   void SyncTimelineCB(bool success);
   void SetWallClockCB(bool success);
-  void OnInitData(const std::vector<unsigned char>& init_data);
+  void OnInitData(const std::vector<unsigned char>& init_data) override;
 #endif
   void OnBufferingStateChange(BufferingState state,
                               BufferingStateChangeReason reason) final;
@@ -859,6 +864,12 @@ int32_t PipelineImpl::RendererWrapper::GetVideoId() {
   return player_id_;
 }
 
+void PipelineImpl::RendererWrapper::OnUpdatePlayerID(int player_id) {
+  LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__
+            << " player_id " << player_id;
+  player_id_ = player_id;
+}
+
 void PipelineImpl::RendererWrapper::WaitSignal() {
   LOG(INFO) << "Signal the sync_with_worker_task_runner_";
   sync_with_worker_task_runner_.Signal();
@@ -1243,6 +1254,24 @@ void PipelineImpl::RendererWrapper::SetHasEncryptedListenerOrCdm(bool value) {
     has_encrypted_listener_or_cdm_ = value;
   }
 }
+
+void PipelineImpl::RendererWrapper::RequestPlay() {
+  DCHECK(media_task_runner_->RunsTasksInCurrentSequence());
+  main_task_runner_->PostTask(
+      FROM_HERE, base::BindOnce(&PipelineImpl::RequestPlay, weak_pipeline_));
+}
+
+void PipelineImpl::RendererWrapper::RequestPause() {
+  DCHECK(media_task_runner_->RunsTasksInCurrentSequence());
+  main_task_runner_->PostTask(
+      FROM_HERE, base::BindOnce(&PipelineImpl::RequestPause, weak_pipeline_));
+}
+
+void PipelineImpl::RendererWrapper::RequestResume() {
+  DCHECK(media_task_runner_->RunsTasksInCurrentSequence());
+  main_task_runner_->PostTask(
+      FROM_HERE, base::BindOnce(&PipelineImpl::RequestResume, weak_pipeline_));
+}
 #endif
 
 void PipelineImpl::RendererWrapper::CreateRendererInternal(
@@ -2598,6 +2627,24 @@ void PipelineImpl::SetHasEncryptedListenerOrCdm(bool value) {
   DCHECK(thread_checker_.CalledOnValidThread());
   renderer_wrapper_->SetHasEncryptedListenerOrCdm(value);
 }
+
+void PipelineImpl::RequestPlay() {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK(client_);
+  client_->RequestPlay();
+}
+
+void PipelineImpl::RequestPause() {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK(client_);
+  client_->RequestPause();
+}
+
+void PipelineImpl::RequestResume() {
+  DCHECK(thread_checker_.CalledOnValidThread());
+  DCHECK(client_);
+  client_->RequestResume();
+}
 #endif
 
 #if defined(TIZEN_MULTIMEDIA)
index 79ab9db53abc32eb2c1805f98070483b4850728f..650e49aa85c0bcd5f3675eefc3c93d9f9d0d3da5 100644 (file)
@@ -221,6 +221,9 @@ class MEDIA_EXPORT PipelineImpl : public Pipeline {
   void SetDecryptorHandle(eme::eme_decryptor_t decryptor) override;
   void OnInitData(const std::vector<unsigned char>& init_data);
   void SetHasEncryptedListenerOrCdm(bool value) override;
+  void RequestPlay();
+  void RequestPause();
+  void RequestResume();
 #endif
   void OnBufferingStateChange(BufferingState state,
                               BufferingStateChangeReason reason);
index 115a8b5a62ffb714d367fbc924acd5f60fab4fc0..9e5d6b6e999bcab70a5ca8deb021ede80900001d 100644 (file)
@@ -52,6 +52,9 @@ class MEDIA_EXPORT RendererClient {
   virtual void OnMrsUrlChange(const std::string& url) {}
   virtual void OnContentIdChange(const std::string& id) {}
   virtual void OnInitData(const std::vector<unsigned char>& init_data) {}
+  virtual void RequestPlay() {}
+  virtual void RequestPause() {}
+  virtual void RequestResume() {}
 #endif
 
   // Executed when buffering state is changed. |reason| indicates the cause of
index 695ce940b632f9e7bc9d21309b23ea57c4d0cf93..fbfaff9e50346c6aa3135bc1a789f06e03d731ec 100644 (file)
@@ -111,6 +111,15 @@ interface MediaPlayerRendererClientExtension {
 
   [EnableIf=is_tizen_tv]
   OnContentIdChange(string id);
+
+  [EnableIf=is_tizen_tv]
+  RequestPlay();
+
+  [EnableIf=is_tizen_tv]
+  RequestPause();
+
+  [EnableIf=is_tizen_tv]
+  RequestResume();
 };
 
 // Extension of the mojo::Renderer communication layer for HLS and Android
index 4c7e29f5bf3b88644324bf7a9f4a3e0081729858..97d3cb6cc16f893dd357df71ea94f6b779881f93 100644 (file)
@@ -2973,6 +2973,23 @@ void WebMediaPlayerImpl::OnInitData(
   OnEncryptedMediaInitData(media::EmeInitDataType::CENC, init_data);
 }
 
+void WebMediaPlayerImpl::RequestPlay() {
+  client_->ResumePlayback();
+}
+
+void WebMediaPlayerImpl::RequestPause() {
+  client_->PausePlayback(WebMediaPlayerClient::PauseReason::kUnknown);
+}
+
+void WebMediaPlayerImpl::RequestResume() {
+  if (!pipeline_controller_->IsSuspended()) {
+    LOG(INFO) << __func__ << " Already resumed.";
+    return;
+  }
+  was_suspended_by_player_ = false;
+  Resume();
+}
+
 void WebMediaPlayerImpl::SetVideoVisibility(bool visible) {
   return pipeline_controller_->SetVideoVisibility(visible);
 }
@@ -4047,6 +4064,9 @@ WebMediaPlayerImpl::UpdatePlayState_ComputePlayState(
 
   LOG(INFO) << __func__ << ": must_suspend=" << must_suspend
             << ", idle_suspended=" << idle_suspended
+#if defined(TIZEN_MULTIMEDIA)
+            << ", was_suspended_by_player_=" << was_suspended_by_player_
+#endif
             << ", background_suspended=" << background_suspended
             << ", can_stay_suspended=" << can_stay_suspended
             << ", is_stale=" << is_stale
index 8b9ac0a56f4efcda1dcb114edbb7a1767cfd1190..c394a5032041bbd06b580f656d48be755db0366c 100644 (file)
@@ -284,6 +284,9 @@ class PLATFORM_EXPORT WebMediaPlayerImpl
   void OnMrsUrlChange(const std::string& url);
   void OnContentIdChange(const std::string& id);
   void OnInitData(const std::vector<unsigned char>& init_data) override;
+  void RequestPlay() override;
+  void RequestPause() override;
+  void RequestResume() override;
 #endif
 
   // Shared between the WebMediaPlayer and DemuxerManager::Client interfaces.
index f14b0e7246e8e7b2697336548a663af9c603f450..6c16bb371da2e487151072265540174b1b247504 100644 (file)
@@ -1051,6 +1051,31 @@ void TizenRendererImpl::OnInitData(
     client_->OnInitData(init_data);
   }
 }
+void TizenRendererImpl::RequestPlay() {
+  if (client_extension_) {
+    client_extension_->RequestPlay();
+  }
+}
+
+void TizenRendererImpl::RequestPause() {
+  if (client_extension_) {
+    client_extension_->RequestPause();
+  }
+}
+
+void TizenRendererImpl::RequestResume() {
+  if (client_extension_) {
+    client_extension_->RequestResume();
+  }
+  media_player_->SetVolume(volume_);
+}
+
+void TizenRendererImpl::OnVideoRect(const gfx::RectF& video_rect) {
+#if defined(TIZEN_VIDEO_HOLE)
+  SetMediaGeometry(video_rect);
+#endif // defined(TIZEN_VIDEO_HOLE)
+}
+
 #endif  // BUILDFLAG(IS_TIZEN_TV)
 
 void TizenRendererImpl::OnSeekableTimeChange(base::TimeDelta min_time,
index 705c5118126fc44e8ad2eeadceccae30169d1064..0dc5d0bc45c61acc32b721251ad0baf8155ef748 100644 (file)
@@ -155,6 +155,10 @@ class CONTENT_EXPORT TizenRendererImpl
   void Hide() override;
   void GetFpsInfo(int& num, int& den) override;
   void OnInitData(const std::vector<unsigned char>& init_data) override;
+  void RequestPlay() override;
+  void RequestPause() override;
+  void RequestResume() override;
+  void OnVideoRect(const gfx::RectF& video_rect) override;
 #endif
 
 #if defined(TIZEN_TBM_SUPPORT)
index 2fc65de050578e6156140f1b78a090aed6455fe6..6460a57e9cd1e8d23eb7425f2a63cf7b08196eb1 100644 (file)
@@ -216,6 +216,21 @@ void MediaPlayerRendererClient::OnContentIdChange(const std::string& id) {
   DCHECK(media_task_runner_->RunsTasksInCurrentSequence());
   client_->OnContentIdChange(id);
 }
+
+void MediaPlayerRendererClient::RequestPlay() {
+  DCHECK(media_task_runner_->RunsTasksInCurrentSequence());
+  client_->RequestPlay();
+}
+
+void MediaPlayerRendererClient::RequestPause() {
+  DCHECK(media_task_runner_->RunsTasksInCurrentSequence());
+  client_->RequestPause();
+}
+
+void MediaPlayerRendererClient::RequestResume() {
+  DCHECK(media_task_runner_->RunsTasksInCurrentSequence());
+  client_->RequestResume();
+}
 #endif
 
 void MediaPlayerRendererClient::OnNewFrameAvailable(
index 837bbbbc96d37f5417638fb8b61dcca7b104a4cb..65a059d050bc0d089cd88abc96bfd8e603961b3b 100644 (file)
@@ -81,6 +81,10 @@ class CONTENT_EXPORT MediaPlayerRendererClient
                             int sync) override;
   void OnMrsUrlChange(const std::string& url) override;
   void OnContentIdChange(const std::string& id) override;
+
+  void RequestPlay() override;
+  void RequestPause() override;
+  void RequestResume() override;
 #endif
   void OnVideoSizeChange(const gfx::Size& size) override;
   void OnBufferUpdate(base::TimeDelta time) override;
index 91bbc83a5904ed47fcd58fb4c06b42530c6ae905..a9eda95b8003e26ba474f2d09ecb72469e2c76dc 100644 (file)
@@ -1231,17 +1231,18 @@ void MediaPlayerESPlusPlayer::OnPrepareComplete(bool result) {
     return;
   }
 
-  if (!result) {
-    LOG_ID(ERROR, player_id_) << "OnPrepareComplete prepare_async failed.";
-    return;
-  }
-
   if (GetPlayerState() != ESPLUSPLAYER_STATE_READY) {
     LOG_ID(ERROR, player_id_) << "Invalid state (" << GetString(GetPlayerState())
                << ") change during prepare. Returning.";
     return;
   }
 
+  if (!result) {
+    LOG_ID(ERROR, player_id_) << "OnPrepareComplete prepare_async failed.";
+    GetMediaPlayerClient()->OnError(PIPELINE_ERROR_INITIALIZATION_FAILED);
+    return;
+  }
+
   LOG_ID(INFO, player_id_) << "(" << static_cast<void*>(this) << ") " << __func__
             << " is_paused_ : " << is_paused_
             << " seek_position : " << seek_position_
index 536d0432d603ac77b2b24372fb6734a14d110bc2..67c72ffc51a7c0781f19351cc4e1c4d7ed692912 100644 (file)
@@ -5,12 +5,15 @@
 #include "tizen_src/chromium_impl/media/filters/media_player_esplusplayer_tv.h"
 
 #include "base/command_line.h"
+#include "base/time/time.h"
 #include "base/trace_event/trace_event.h"
 #include "content/public/common/content_switches.h"
 #include "media/base/audio_codecs.h"
 #include "media/base/decoder_buffer.h"
 #include "media/base/renderer_client.h"
 #include "media/filters/esplusplayer_util.h"
+#include "media/filters/hardware_resource_types.h"
+#include "third_party/blink/public/platform/web_application_type.h"
 #include "tizen/system_info.h"
 #include "tizen_src/chromium_impl/media/filters/media_player_tizen_client.h"
 
 #define TIMELINESTATE 3
 #define TIMELINEPAUSED true
 
+namespace {
+
+std::pair<uint32_t, uint32_t> GetHBBTvTAResolution(uint32_t width,
+                                                   uint32_t height) {
+  // NOTE: HBBTV TA requires to play two videos on two different scalers at the
+  //        same time. To achive this behavior we limit maximal resolution to
+  //        the value which always allow two HW decoder playbacks.
+  return {std::min(static_cast<uint32_t>(kFHDVideoMaxWidth), width),
+          std::min(static_cast<uint32_t>(kFHDVideoMaxHeight), height)};
+}
+
 // malloc_trim(0) will be called every 2 minutes.
 const base::TimeDelta kMallocTrimInterval = base::TimeDelta::FromSeconds(120);
+
+// Only for HBBTV TA
+// Estimated pulling ZOrder interval time, to proceed a fastswitch.
+const base::TimeDelta kHbbTVZorderCheckInterval = base::Milliseconds(500);
+}  // namespace
+
 namespace media {
 
 // Limit of platform player's total (audio and video) buffer size
@@ -126,19 +146,51 @@ void MediaPlayerESPlusPlayerTV::InitializeStreamConfig(
 bool MediaPlayerESPlusPlayerTV::Play() {
   LOG_ID(INFO, player_id_) << "(" << static_cast<void*>(this) << ") "
                            << __func__;
+
+  if (!IsInitialized()) {
+    LOG_ID(ERROR, GetPlayerId()) << "Player not initialized!";
+    return false;
+  }
+
   auto td_ptr = suitable_decoder_.lock();
   auto dec_name = content::kNoneDecoder;
-  if (td_ptr) {
-    dec_name = td_ptr->GetDecoderType();
-    SetDecoderAcquired(td_ptr->GetDecoderType());
-  }
-  if (GetMediaPlayerClient()) {
-    bool media_resource_acquired = false;
-    GetMediaPlayerClient()->NotifyPlaybackState(kPlaybackStart, player_id_, "",
-                                                "", &media_resource_acquired,
-                                                NULL, NULL, dec_name);
-    if (blink::IsHbbTV() && !media_resource_acquired) {
-      LOG_ID(ERROR, player_id_) << "HbbTV failed to allocate media resources";
+  if (td_ptr || !(GetMediaType() & MediaType::Video) ||
+      !content::HardwareResourceHelper::Get().IsDualDecoding()) {
+    if (td_ptr) {
+      dec_name = td_ptr->GetDecoderType();
+    }
+    if (blink::IsHbbTV() && CanPrepare()) {
+      if (DemuxerStream* stream =
+              GetDemuxerStream(media::DemuxerStream::VIDEO)) {
+        VideoDecoderConfig video_config = stream->video_decoder_config();
+        ChooseDecoderIfNeeded(video_config.codec(), true /* ignore_conflict */);
+        MediaPlayerESPlusPlayer::Prepare();
+        MediaPlayerESPlusPlayer::Play();
+        return true;
+      }
+    }
+    if (!IsPrepared()) {
+      if (blink::IsHbbTV() && GetMediaPlayerClient()) {
+        bool media_resource_acquired = false;
+        GetMediaPlayerClient()->NotifyPlaybackState(
+            kPlaybackReady, GetPlayerId(), "", "", &media_resource_acquired,
+            NULL, NULL, dec_name);
+        if (!media_resource_acquired) {
+          LOG_ID(ERROR, GetPlayerId())
+              << "HbbTV media resource was not acquired";
+          return false;
+        }
+      }
+
+      if (td_ptr) {
+        SetDecoderAcquired(td_ptr->GetDecoderType());
+        if (td_ptr->RequiresBothDecoders()) {
+          SetDecoderAcquired(content::kSubDecoder);
+        }
+      }
+      MediaPlayerESPlusPlayer::Prepare();
+      MediaPlayerESPlusPlayer::Play();
+
       return false;
     }
   }
@@ -149,12 +201,20 @@ bool MediaPlayerESPlusPlayerTV::Play() {
   }
   ActivateAudioStreamIfNeeded();
 
+  if (GetMediaPlayerClient()) {
+    GetMediaPlayerClient()->NotifyPlaybackState(kPlaybackStart, player_id_, "",
+                                                "", NULL, NULL, NULL, dec_name);
+    GetMediaPlayerClient()->OnPlayerStarted(true);
+  }
+  StartMallocTrimTimer();
+
 #if TIZEN_VERSION_AT_LEAST(8, 0, 0)
   if (!SwitchAudioFocusIfNeeded()) {
     LOG_ID(INFO, player_id_) << "switch audio focus failed";
     return false;
   }
 #endif
+
   return true;
 }
 
@@ -169,20 +229,148 @@ void MediaPlayerESPlusPlayerTV::Pause(bool is_media_related_action) {
 void MediaPlayerESPlusPlayerTV::Prepare() {
   LOG_ID(INFO, player_id_) << "(" << static_cast<void*>(this) << ") "
                            << __func__;
+  if (!blink::IsHbbTV()) {
+    MediaPlayerESPlusPlayer::Prepare();
+    return;
+  }
 
-  if (blink::IsHbbTV() && !decoder_assigned_) {
-    DemuxerStream* stream = GetDemuxerStream(media::DemuxerStream::VIDEO);
-    if (stream) {
-      VideoDecoderConfig video_config = stream->video_decoder_config();
-      ChooseDecoderIfNeeded(video_config.codec());
-      if (auto td_ptr = suitable_decoder_.lock()) {
-        decoder_assigned_ = true;
-      }
+  DemuxerStream* stream = GetDemuxerStream(media::DemuxerStream::VIDEO);
+  if (stream) {
+    VideoDecoderConfig video_config = stream->video_decoder_config();
+    ChooseDecoderIfNeeded(video_config.codec());
+  }
+
+  if (IsHbbTvTaAllowed() && GetMediaPlayerClient()) {
+    GetMediaPlayerClient()->OnBufferingStateChange(
+        BUFFERING_HAVE_ENOUGH, BUFFERING_CHANGE_REASON_UNKNOWN);
+  }
+
+  bool has_suitable_decoder = suitable_decoder_.lock() != nullptr;
+  if (!stream && HasAudio()) {
+    // Support standalone audio.
+    decoder_conflict_ = IsHwAudioConflicted();
+    has_suitable_decoder = true;
+  }
+
+  if (has_suitable_decoder && !decoder_conflict_) {
+    MediaPlayerESPlusPlayer::Prepare();
+  } else {
+    LOG_ID(WARNING, player_id_)
+        << "Delaying |Prepare| to avoid resource conflict. "
+        << (has_suitable_decoder ? "Has" : "NO") << " suitable decoder. "
+        << (decoder_conflict_ ? "Decoder Conflict!" : "");
+  }
+
+  if (!stream || suitable_decoder_.lock() ||
+      content::HardwareResourceHelper::Get().IsDualDecoding()) {
+    return;
+  }
+
+  // No decoder - is dual decoding not available?
+  if (GetMediaPlayerClient()) {
+    bool media_resource_acquired = false;
+    auto dec_name = content::kNoneDecoder;
+    if (GetMediaType() & MediaType::Video)
+      dec_name = content::kMainDecoder;
+    GetMediaPlayerClient()->NotifyPlaybackState(
+      kPlaybackVideoReady, GetPlayerId(), "", "", &media_resource_acquired,
+      NULL, NULL, dec_name);
+    if (!media_resource_acquired) {
+      LOG_ID(INFO, GetPlayerId()) << "HbbTV media resource was not acquired";
+      MediaPlayerESPlusPlayer::OnError(ESPLUSPLAYER_ERROR_TYPE_UNKNOWN);
     }
   }
+}
+
+
+void MediaPlayerESPlusPlayerTV::PrepareToMediaSwitch() {
+  if (!IsHbbTvTaAllowed()) {
+    LOG_ID(ERROR, player_id_) << "HbbTV-TA is not allowed";
+    return;
+  }
+
+  LOG_ID(INFO, player_id_);
+  is_for_ta_ = true;
+
+  if (GetPlayerState() == ESPLUSPLAYER_STATE_NONE) {
+    LOG_ID(INFO, player_id_)
+        << "Initialization order was wrong, request resume.";
+    should_trigger_ta_zorder_checking_ = true;
+    GetMediaPlayerClient()->RequestResume();
+    return;
+  }
+
+  bool has_suitable_decoder = (suitable_decoder_.lock() != nullptr);
+  if (has_suitable_decoder && !decoder_conflict_ && !CanPrepare()) {
+    LOG_ID(INFO, player_id_)
+        << "Already prepared (or still preparing), continue.";
+    StartCheckingHbbTVZOrder();
+    return;
+  }
+
+  LOG_ID(INFO, player_id_) << "Not prepared, choose decoder again and prepare.";
+  DemuxerStream* stream = GetDemuxerStream(media::DemuxerStream::VIDEO);
+  if (stream) {
+    VideoDecoderConfig video_config = stream->video_decoder_config();
+    ChooseDecoderIfNeeded(video_config.codec(), true /* ignore_conflict */);
+    auto td_ptr = suitable_decoder_.lock();
+    if (!td_ptr) {
+      LOG_ID(ERROR, player_id_) << "No decoder assigned!";
+      return;
+    }
+  }
+
+  should_trigger_ta_zorder_checking_ = true;
   MediaPlayerESPlusPlayer::Prepare();
 }
 
+void MediaPlayerESPlusPlayerTV::RequestPlay() {
+  LOG_ID(INFO, player_id_) << "(" << static_cast<void*>(this) << ")";
+  if (!is_for_ta_) {
+    LOG_ID(ERROR, player_id_)
+        << "This method should be called for HbbTV-TA only";
+    return;
+  }
+
+  if (!GetMediaPlayerClient()) {
+    LOG_ID(ERROR, player_id_)
+        << "(" << static_cast<void*>(this) << ") No media player client";
+    return;
+  }
+  Play();
+  should_trigger_ta_zorder_checking_ = false;
+  StopCheckingHbbTVZOrder();
+  if (!is_ta_geometry_set_) {
+    // Setting geometry if prepare was significantly delayed.
+    is_ta_geometry_set_ = true;
+    GetMediaPlayerClient()->OnVideoRect(video_rect_);
+  }
+  ForceVideoOrder(VideoOrder::kOnTop);
+  GetMediaPlayerClient()->RequestPlay();
+}
+
+void MediaPlayerESPlusPlayerTV::RequestPause() {
+  LOG_ID(INFO, player_id_) << "(" << static_cast<void*>(this) << ")";
+  if (!is_for_ta_) {
+    LOG_ID(ERROR, player_id_)
+        << "This method should be called for HbbTV-TA only";
+    return;
+  }
+
+  if (!GetMediaPlayerClient()) {
+    LOG_ID(ERROR, player_id_)
+        << "(" << static_cast<void*>(this) << ") No media player client";
+    return;
+  }
+  GetMediaPlayerClient()->RequestPause();
+  ForceVideoOrder(VideoOrder::kOnBottom);
+}
+
+void MediaPlayerESPlusPlayerTV::SetVideoRect(const gfx::RectF& video_rect) {
+  LOG_ID(INFO, player_id_) << "(" << static_cast<void*>(this) << ")";
+  video_rect_ = video_rect;
+}
+
 void MediaPlayerESPlusPlayerTV::Release() {
   LOG_ID(INFO, player_id_) << "(" << static_cast<void*>(this) << ") "
                            << __func__;
@@ -267,6 +455,11 @@ int MediaPlayerESPlusPlayerTV::SetVideoStreamInfo(
     video_stream_info.framerate_den = 1;
   }
 
+  if (is_for_ta_) {
+    std::tie(video_stream_info.max_width, video_stream_info.max_height) =
+        GetHBBTvTAResolution(video_stream_info.width, video_stream_info.height);
+  }
+
   video_codec_ = video_config.codec();
   if (hdr_info_.compare(video_config.hdr_info()) != 0) {
     is_hdr_changed_ = true;
@@ -549,7 +742,21 @@ void MediaPlayerESPlusPlayerTV::OnPrepareComplete(bool result) {
     return;
   }
 
-  return MediaPlayerESPlusPlayer::OnPrepareComplete(result);
+  if (result && IsValid(DemuxerStream::VIDEO) &&
+      !ReadRequested(DemuxerStream::VIDEO)) {
+    SetShouldFeed(DemuxerStream::VIDEO, true);
+    ReadBuffer(DemuxerStream::VIDEO);
+  }
+
+  if (result && GetMediaPlayerClient())
+    GetMediaPlayerClient()->NotifyPlaybackState(kPlaybackReady, player_id_);
+
+  MediaPlayerESPlusPlayer::OnPrepareComplete(result);
+
+  if (is_for_ta_ && result && should_trigger_ta_zorder_checking_) {
+    should_trigger_ta_zorder_checking_ = false;
+    StartCheckingHbbTVZOrder();
+  }
 }
 
 void MediaPlayerESPlusPlayerTV::OnEos() {
@@ -961,12 +1168,28 @@ void MediaPlayerESPlusPlayerTV::SetHwAudioDecoder() {
 #endif  // TIZEN_VERSION_AT_LEAST(6, 5, 0)
 }
 
-void MediaPlayerESPlusPlayerTV::ChooseDecoderIfNeeded(VideoCodec codec) {
+void MediaPlayerESPlusPlayerTV::ChooseDecoderIfNeeded(VideoCodec codec,
+                                                      bool ignore_conflict) {
   if (!blink::IsHbbTV()) {
     return;
   }
-  content::WebContentsDelegate* contents_delegate =
-      GetMediaPlayerClient()->GetWebContentsDelegate();
+
+  if (!content::HardwareResourceHelper::Get().IsDualDecoding()) {
+    LOG_ID(INFO, player_id_) << "No dual decoder support...";
+    return;
+  }
+
+  if (auto td_ptr = suitable_decoder_.lock()) {
+    SetDecoderReleased(td_ptr->GetDecoderType());
+  }
+
+  // Prevent checking ZOrder for invalid decoder.
+  StopCheckingHbbTVZOrder();
+
+  content::WebContentsDelegate* contents_delegate = nullptr;
+  if (GetMediaPlayerClient()) {
+    contents_delegate = GetMediaPlayerClient()->GetWebContentsDelegate();
+  }
   if (contents_delegate != nullptr) {
     content::HardwareResourceHelper::Get().HandleBroadcastDecoder(
         contents_delegate->GetBroadcastDecoder());
@@ -977,8 +1200,12 @@ void MediaPlayerESPlusPlayerTV::ChooseDecoderIfNeeded(VideoCodec codec) {
   auto fps = static_cast<int>(framerate);
   const auto max_resolution =
       GetMaxResolution(capi_media_format_video_.mime_type, is_video_hole_);
-  const auto max_width = max_resolution.width();
-  const auto max_height = max_resolution.height();
+  auto max_width = max_resolution.width();
+  auto max_height = max_resolution.height();
+  if (is_for_ta_) {
+    std::tie(max_width, max_height) =
+        GetHBBTvTAResolution(max_width, max_height);
+  }
   suitable_decoder_ =
       content::HardwareResourceHelper::Get().GetSuitableResource(
           media::MediaType::Video, content::HWAquirePolicy::SWITCH, max_width,
@@ -996,18 +1223,39 @@ void MediaPlayerESPlusPlayerTV::ChooseDecoderIfNeeded(VideoCodec codec) {
     use_sw_audio_decoder = IsSwAudioSupported();
   }
 
+  // NOTE: Broadcast always uses HW, so we need to avoid also audio conflicts
+  const bool is_hw_audio_conflicted =
+      IsHwAudioConflicted() && !use_sw_audio_decoder;
+  decoder_conflict_ = td_ptr->IsAcquired() || is_hw_audio_conflicted;
+  if (decoder_conflict_) {
+    LOG_ID(INFO, player_id_) << "Conflict:"
+                             << " audio_conflicted=" << is_hw_audio_conflicted
+                             << " video_conflicted=" << td_ptr->IsAcquired();
+    if (!ignore_conflict) {
+      LOG_ID(ERROR, player_id_)
+          << "Selected decoder but it's already acquired.";
+      return;
+    }
+    LOG_ID(INFO, player_id_)
+        << "Selected decoder with conflict, but we're force to ignore it.";
+  }
+
   SetHwAudioDecoder();
 #if TIZEN_VERSION_AT_LEAST(6, 0, 0)
+  constexpr int kAllResourcesForMain = 0;
+  constexpr int kAllResourcesForSub = 1;
   if ((dec_name & content::kSubDecoder) == content::kSubDecoder) {
     LOG_ID(INFO, player_id_) << "SUB decoder is used for this " << this;
     // 1 = set all video resources(decoder/scaler) to sub resources
-    esplusplayer_set_alternative_video_resource(esplayer_, 1);
+    esplusplayer_set_alternative_video_resource(esplayer_, kAllResourcesForSub);
   } else if ((dec_name & content::kMainDecoder) == content::kMainDecoder) {
     LOG_ID(INFO, player_id_) << "MAIN decoder is used for this " << this;
     // 0 = set all video resources(decoder/scaler) to main resources
-    esplusplayer_set_alternative_video_resource(esplayer_, 0);
+    esplusplayer_set_alternative_video_resource(esplayer_,
+                                                kAllResourcesForMain);
     // If using SW audio decoding is possible. HW audio decoder
     // should be explicitly used for MAIN decoder.
+
   } else {
     LOG_ID(ERROR, GetPlayerId()) << "CANNOT USE ANY VIDEO DECODER";
   }
@@ -1017,8 +1265,10 @@ void MediaPlayerESPlusPlayerTV::ChooseDecoderIfNeeded(VideoCodec codec) {
     SetSwAudioDecoder();
   }
 #endif
-  decoder_conflict_ = td_ptr->IsAcquired();
-  if (!decoder_conflict_) {
+
+  // Decoder conflict is now checked above and we do not get here
+  // if there is one.
+  if (GetMediaPlayerClient()) {
     // is_notification_playback_ready_delayed_ = true;
     bool media_resource_acquired = false;
     GetMediaPlayerClient()->NotifyPlaybackState(
@@ -1028,9 +1278,8 @@ void MediaPlayerESPlusPlayerTV::ChooseDecoderIfNeeded(VideoCodec codec) {
       LOG_ID(INFO, GetPlayerId()) << "HbbTV media resource was not acquired";
       return;
     }
-
-    SetDecoderAcquired(dec_name);
   }
+  SetDecoderAcquired(dec_name);
 }
 
 void MediaPlayerESPlusPlayerTV::SetDecoderAcquired(
@@ -1121,19 +1370,31 @@ bool MediaPlayerESPlusPlayerTV::IsSwAudioSupported() const {
   return !is_audio_drm_eme_ && audio_codec_ != media::AudioCodec::kAC4;
 }
 
+bool MediaPlayerESPlusPlayerTV::HasAudio() const {
+  return GetMediaType() & MediaType::Audio;
+}
+
+void MediaPlayerESPlusPlayerTV::ForceVideoOrder(VideoOrder videoOrder) {
+#if defined(TIZEN_VIDEO_HOLE) && TIZEN_VERSION_AT_LEAST(6, 0, 0)
+  const auto decoder = suitable_decoder_.lock();
+  if (!decoder) {
+    return;
+  }
+  const auto dec_type = decoder->GetDecoderType(content::kDecoders);
+  ::media::ForceVideoOrder<content::DecoderType, VideoOrder,
+                           VideoOrder::kOnTop>(dec_type, videoOrder,
+                                               player_id_);
+#endif  // defined(TIZEN_VIDEO_HOLE) && TIZEN_VERSION_AT_LEAST(6, 0, 0)
+}
+
 #if defined(TIZEN_VIDEO_HOLE)
 void MediaPlayerESPlusPlayerTV::SetVideoVisibility(bool visible) {
-  if (!blink::IsHbbTV() || !is_video_hole_) {
+  if (!blink::IsHbbTV() || !is_video_hole_ || is_for_ta_)
     return;
-  }
 
 
 #if TIZEN_VERSION_AT_LEAST(6, 0, 0)
   if (auto td_ptr = suitable_decoder_.lock()) {
-    if (td_ptr->GetDecoderType(content::kDecoders) == content::kMainDecoder &&
-        td_ptr->GetDecoderType(content::kResolutions) == content::kFHDDecoder) {
-      return;
-    }
     auto dec_type = td_ptr->GetDecoderType(content::kDecoders);
     const unsigned int kFullVisibility = 255;
     const unsigned int kNoVisibility = 0;
@@ -1148,4 +1409,99 @@ void MediaPlayerESPlusPlayerTV::SetVideoVisibility(bool visible) {
 }
 #endif
 
+bool MediaPlayerESPlusPlayerTV::IsHbbTvTaAllowed() const {
+  // HbbTV Targeted Advertisement is allowed only when SW audio decoding is set.
+  return blink::IsHbbTV() && UseSwAudioDecoding();
+}
+
+void MediaPlayerESPlusPlayerTV::StartCheckingHbbTVZOrder() {
+  if (!is_for_ta_) {
+    return;
+  }
+  if (hbbtv_zorder_checker_timer_.IsRunning())
+    return;
+
+  LOG_ID(INFO, player_id_) << __func__;
+  is_ta_geometry_set_ = false;
+  hbbtv_zorder_checker_timer_.Start(
+      FROM_HERE, kHbbTVZorderCheckInterval, this,
+      &MediaPlayerESPlusPlayerTV::OnCheckingHbbtvTVZorder);
+}
+
+void MediaPlayerESPlusPlayerTV::StopCheckingHbbTVZOrder() {
+  if (!hbbtv_zorder_checker_timer_.IsRunning())
+    return;
+
+  LOG_ID(INFO, player_id_) << __func__;
+  hbbtv_zorder_checker_timer_.Stop();
+}
+
+void MediaPlayerESPlusPlayerTV::OnCheckingHbbtvTVZorder() {
+  if (is_ta_geometry_set_)
+    return;
+
+  auto decoder = suitable_decoder_.lock();
+  if (!decoder) {
+    LOG_ID(WARNING, player_id_) << "No suitable decoder";
+    return;
+  }
+
+  constexpr int kMainPlane = 0;
+  constexpr int kSubPlane = 1;
+  int expected_zorder_on_top;
+  const auto dec_type = decoder->GetDecoderType(content::kDecoders);
+  if ((dec_type & content::kDecoders) == content::kSubDecoder) {
+    expected_zorder_on_top = kSubPlane;
+  } else if ((dec_type & content::kDecoders) == content::kMainDecoder) {
+    expected_zorder_on_top = kMainPlane;
+  } else {
+    LOG_ID(WARNING, player_id_)
+        << "Cannot understand a decoder type: " << dec_type;
+    return;
+  }
+
+  constexpr size_t kZOrderRawMinimalLength = 8;
+  unsigned char order[kZOrderRawMinimalLength];
+#if TIZEN_VERSION_AT_LEAST(9, 0, 0) && !BUILDFLAG(IS_RISCV64_TV)
+  const auto error = ppi_video_dp_control_get_zorder_raw(order);
+#else
+  const auto error = IVideoDpControl::getInstance()->getZorderRaw(order);
+#endif
+  if (error) {
+    LOG_ID(WARNING, player_id_) << "Cannot acquire ZORDER: " << strerror(error);
+    return;
+  }
+
+  auto ToText = [](int plane) -> std::string {
+    switch (plane) {
+      case kMainPlane:
+        return "MAIN-SUB-BG";
+      case kSubPlane:
+        return "SUB-MAIN-BG";
+      default:
+        return "UNACCEPTED";
+    }
+  };
+
+  LOG_ID(INFO, player_id_) << "ZOrder=" << ToText(order[0])
+                           << " expected=" << ToText(expected_zorder_on_top);
+
+  if (expected_zorder_on_top == order[0]) {
+    LOG_ID(INFO, player_id_)
+        << "ZOrder updated. Changing a geometry in advance.";
+    is_ta_geometry_set_ = true;
+    hbbtv_zorder_checker_timer_.Stop();
+    ForceVideoOrder(VideoOrder::kOnBottom);
+    GetMediaPlayerClient()->OnVideoRect(video_rect_);
+  }
+}
+
+bool MediaPlayerESPlusPlayerTV::IsHwAudioConflicted() const {
+  // NOTE: Broadcast always uses HW, so we need to avoid also audio conflicts
+  return HasAudio() &&
+         content::HardwareResourceHelper::Get()
+             .IsAnyDecoderAcquiredByBroadcast() &&
+         !UseSwAudioDecoding();
+}
+
 }  // namespace media
index 120b074e2ba76334bef2f95e8f4b6001bf532c64..bd95755eede522c5088f46ab1796f4079507dcd3 100644 (file)
@@ -73,12 +73,20 @@ class MEDIA_EXPORT MediaPlayerESPlusPlayerTV : public MediaPlayerESPlusPlayer {
   void SetHwAudioDecoder();
   void SetSwAudioDecoder();
   bool IsSwAudioSupported() const;
-  bool UseSwAudioDecoding() const;
   player_buffer_size_t GetMaxVideoBufferSize(
       const media::VideoDecoderConfig& video_config) override;
-  void ChooseDecoderIfNeeded(media::VideoCodec codec);
+  void SetTbmCallbackPolicy(const media::VideoDecoderConfig& video_config);
+  void ChooseDecoderIfNeeded(media::VideoCodec codec,
+                             bool ignore_conflict = false);
+
+  void PrepareToMediaSwitch() override;
+  void RequestPlay() override;
+  void RequestPause() override;
+  void SetVideoRect(const gfx::RectF& video_rect) override;
 
  private:
+  enum class VideoOrder { kOnTop, kOnBottom };
+
 #if TIZEN_VERSION_AT_LEAST(6, 0, 0)
   class DrmInfo {
    public:
@@ -132,6 +140,16 @@ class MEDIA_EXPORT MediaPlayerESPlusPlayerTV : public MediaPlayerESPlusPlayer {
   void OnMallocTrimTimerFired();
   void StartMallocTrimTimer();
   void StopMallocTrimTimer();
+  bool HasAudio() const;
+
+  void ForceVideoOrder(VideoOrder videoOrder);
+  bool IsHbbTvTaAllowed() const;
+  bool UseSwAudioDecoding() const;
+  bool IsHwAudioConflicted() const;
+
+  void StartCheckingHbbTVZOrder();
+  void StopCheckingHbbTVZOrder();
+  void OnCheckingHbbtvTVZorder();
 
   std::string hdr_info_;
   bool is_hdr_changed_{false};
@@ -139,13 +157,22 @@ class MEDIA_EXPORT MediaPlayerESPlusPlayerTV : public MediaPlayerESPlusPlayer {
 
   bool use_sw_audio_decoder_{false};
   bool audio_preloading_set_{false};
+  esplusplayer_decoded_video_frame_buffer_type decoded_frame_buffer_type_{
+      ESPLUSPLAYER_DECODED_VIDEO_FRAME_BUFFER_TYPE_NONE};
+  bool enable_tbm_buffer_callback_{false};
   bool decoder_conflict_{true};
   esplusplayer_video_stream_info capi_media_format_video_;
   base::RepeatingTimer malloc_trim_timer;
   std::weak_ptr<content::DecoderState> suitable_decoder_;
-  bool decoder_assigned_{false};
+  base::RepeatingTimer current_time_update_timer_;
+  base::RepeatingTimer hbbtv_zorder_checker_timer_;
   bool audio_stream_activated_{true};
 
+  gfx::RectF video_rect_;
+  bool is_for_ta_{false};
+  bool is_ta_geometry_set_{false};
+  bool should_trigger_ta_zorder_checking_{false};
+
 #if TIZEN_VERSION_AT_LEAST(8, 0, 0)
   static esplusplayer_handle audio_focus_player_;
 #endif
index 22953b67cb5d4c3c5d4d66a1e1ed81b80971fb1a..13a92b8dd6b8ed92e8c387c83579ea81991b66d5 100644 (file)
@@ -73,8 +73,8 @@ class MEDIA_EXPORT MediaPlayerTizen {
  public:
   using RequestSuspendCB = base::RepeatingCallback<void(bool)>;
 
-  MediaPlayerTizen() {}
-  virtual ~MediaPlayerTizen() {}
+  MediaPlayerTizen() = default;
+  virtual ~MediaPlayerTizen() = default;
 
   virtual bool CreatePlayer(int player_id) = 0;
   virtual void Initialize(VideoRendererSink* sink) = 0;
@@ -172,6 +172,10 @@ class MEDIA_EXPORT MediaPlayerTizen {
 #if BUILDFLAG(IS_TIZEN_TV)
   virtual void SetDecryptorHandle(eme::eme_decryptor_t decryptor) {}
   virtual void SetHasEncryptedListenerOrCdm(bool value) {}
+  virtual void PrepareToMediaSwitch() {}
+  virtual void RequestPlay() {}
+  virtual void RequestPause() {}
+  virtual void SetVideoRect(const gfx::RectF& video_rect) {}
 #endif
 };
 
index 89791b013d64db2078020d97bf94bb7c35155d7b..6ce8746ed459ac3020d3178e66f9b74a9c796fbf 100644 (file)
@@ -90,6 +90,11 @@ class MEDIA_EXPORT MediaPlayerTizenClient {
   virtual void OnPlayerStarted(bool play_started) = 0;
   virtual void GetFpsInfo(int& num, int& den) = 0;
   virtual void OnInitData(const std::vector<unsigned char>& init_data) = 0;
+
+  virtual void RequestPlay();
+  virtual void RequestPause();
+  virtual void RequestResume();
+  virtual void OnVideoRect(const gfx::RectF& video_rect);
 #endif
 };
 
index 45c77fcd608c30b1d9c9c7aaaa8a8d34b3e098cd..9fdfe6c2958eb2395297154b23cc97c4500c0bac 100644 (file)
 #include "public/ewk_media_subtitle_info_product.h"
 #include "public/ewk_user_media_internal.h"
 #include "third_party/blink/public/platform/web_media_player.h"
+#include "tizen_src/chromium_impl/media/filters/hardware_resource_helper.h"
+#include "tizen_src/chromium_impl/media/filters/media_player_registry.h"
 #endif
 
 #if defined(TIZEN_PEPPER_EXTENSIONS)
@@ -145,6 +147,7 @@ const char kReplaceChars[] = " ";
 const char kReplaceWith[] = "_";
 #if BUILDFLAG(IS_TIZEN_TV)
 static const int kMousePressAndHoldTimeout = 500;  // long press: 500ms
+const int kBroadcastPlayerId = 0;
 #endif
 
 static const char* kRendererCrashedHTMLMessage =
@@ -4134,9 +4137,9 @@ std::vector<std::string> EWebView::NotifyPlaybackState(
   Ewk_Media_Playback_Info* playback_info =
       ewkMediaPlaybackInfoCreate(player_id, url, mime_type, decoder);
 
-  LOG(INFO)
-      << "player_id:" << player_id << ",state: " << state
-      << "(0-load : 1-videoready : 2-ready : 3-start : 4-finish : 5-stop)";
+  LOG(INFO) << "player_id:" << player_id << ",state: " << state
+            << "(0-load : 1-videoready : 2-ready : 3-start : 4-finish : 5-stop)"
+            << ", decoder: " << static_cast<int>(decoder);
   switch (state) {
     case kPlaybackLoad:
       SmartCallback<EWebViewCallbacks::PlaybackLoad>().call(
@@ -4304,6 +4307,74 @@ void EWebView::SetBroadcastDecoder(Ewk_Hardware_Decoders decoder) {
 Ewk_Hardware_Decoders EWebView::GetBroadcastDecoder() const {
   return broadcast_decoder_;
 }
+
+void EWebView::SetNextPlayerForMediaSwitch(int player_id) {
+  LOG(INFO) << player_id;
+  if (!UseSwAudioDecoding()) {
+    LOG(ERROR) << "This method should be used for HbbTV-TA only";
+    return;
+  }
+
+  if (player_id == kBroadcastPlayerId) {
+    auto resource = content::HardwareResourceHelper::Get().GetResource(
+        content::kMainDecoder);
+    if (resource) {
+      resource->Owner().Suspend();
+    }
+    return;
+  }
+
+  auto player =
+      media::MediaPlayerRegistry::GetInstance()->GetMediaPlayer(player_id);
+  if (!player) {
+    LOG(ERROR) << "Player with id " << player_id << " is not found";
+    return;
+  }
+  player->PrepareToMediaSwitch();
+}
+
+void EWebView::VideoPlay(int player_id) {
+  LOG(INFO) << player_id;
+  if (!UseSwAudioDecoding()) {
+    LOG(ERROR) << "This method should be used for HbbTV-TA only";
+    return;
+  }
+
+  auto player =
+      media::MediaPlayerRegistry::GetInstance()->GetMediaPlayer(player_id);
+  if (!player) {
+    LOG(ERROR) << "Player with id " << player_id << " is not found";
+    return;
+  }
+  player->RequestPlay();
+}
+
+void EWebView::VideoPause(int player_id) {
+  LOG(INFO) << player_id;
+  if (!UseSwAudioDecoding()) {
+    LOG(ERROR) << "This method should be used for HbbTV-TA only";
+    return;
+  }
+
+  auto player =
+      media::MediaPlayerRegistry::GetInstance()->GetMediaPlayer(player_id);
+  if (!player) {
+    LOG(ERROR) << "Player with id " << player_id << " is not found";
+    return;
+  }
+  player->RequestPause();
+}
+
+void EWebView::SetVideoGeometry(int x, int y, int w, int h) {
+  if (!UseSwAudioDecoding()) {
+    LOG(ERROR) << "This method should be used for HbbTV-TA only";
+    return;
+  }
+
+  for (auto p : media::MediaPlayerRegistry::GetInstance()->GetMediaPlayers()) {
+    p.second->SetVideoRect(gfx::RectF(x, y, w, h));
+  }
+}
 #endif
 
 void EWebView::SetIMEWindow(void* window) {
index 26868df140c82a4112d2f84828aa5bd01e885367..d1124949c60e2c3ae5458746e94c9bd0af14ab4d 100644 (file)
@@ -908,6 +908,10 @@ class EWebView {
   void OnMouseMove();
   void SetBroadcastDecoder(Ewk_Hardware_Decoders decoder);
   Ewk_Hardware_Decoders GetBroadcastDecoder() const;
+  void SetNextPlayerForMediaSwitch(int player_id);
+  void VideoPlay(int player_id);
+  void VideoPause(int player_id);
+  void SetVideoGeometry(int x, int y, int w, int h);
 #endif  // IS_TIZEN_TV
 
   void SetScriptsCanOpenWindows(bool);
index 790d3a05865a9cd3ed76f779dc877c0134e2525e..ffdea3a316b2e19081b5bcf463dd6fd8d6bbb427 100644 (file)
@@ -47,6 +47,7 @@
 #include "public/ewk_context.h"
 #include "public/ewk_enums_internal.h"
 #include "public/ewk_settings.h"
+#include "tizen_src/chromium_impl/tizen/tizen_tv_platform.h"
 #include "third_party/blink/public/common/page/page_zoom.h"
 #include "third_party/blink/public/common/web_preferences/web_preferences.h"
 #include "ui/events/gesture_detection/gesture_configuration.h"
@@ -1307,21 +1308,52 @@ Eina_Bool ewk_view_set_custom_device_pixel_ratio(Evas_Object* ewkView, Eina_Bool
 Ewk_Board_Decoding_Capabilities ewk_view_board_decoding_capabilities_get(
   const Evas_Object* view)
 {
-  LOG_EWK_API_MOCKUP();
+#if BUILDFLAG(IS_TIZEN_TV)
+  // This one should be moved into HbbTV code.
+  auto DecodingCapabilities = []() -> Ewk_Board_Decoding_Capabilities {
+    const std::string chipset = GetTVChipset();
+    const ResourceTableIndex rt_idx = GetResourceTableIndex();
+    // 1x FHD decoder: KantS2
+    // 1x UHD decoder: NikeL 1.5G
+    if (chipset == "KANTS2" || rt_idx == ResourceTableIndex::DTV_NIKEL_1_5G) {
+      LOG(INFO) << "It is low-end board, do not use dual decoding";
+      return EWK_BOARD_DECODING_CAPABILITIES_SINGLE;
+    }
+    // 2x FHD decoder: KantSU2E
+    if (chipset == "KANTSU2E") {
+      LOG(INFO) << "It is KantSU2e, use 2x FHD decoders";
+      return EWK_BOARD_DECODING_CAPABILITIES_DOUBLE_FHD;
+    }
+    // 1x UHD, 1x FHD decoder: other boards
+    LOG(INFO) << "It is " << chipset << ", rt idx is "
+              << static_cast<int>(rt_idx) << ", use both decoders";
+    return EWK_BOARD_DECODING_CAPABILITIES_FHD_AND_UHD;
+  };
+
+  static Ewk_Board_Decoding_Capabilities board_decoding_capabilities =
+      DecodingCapabilities();
+  return board_decoding_capabilities;
+#else
+  LOG_EWK_API_MOCKUP("Only for Tizen TV.");
   return EWK_BOARD_DECODING_CAPABILITIES_UNKNOWN;
+#endif
 }
 
 void ewk_view_next_player_for_media_switch_set(
   Evas_Object* view,
   int player_id)
 {
-  LOG_EWK_API_MOCKUP();
+#if BUILDFLAG(IS_TIZEN_TV)
+  LOG(INFO) << "Notify about media switch, next player id: " << player_id;
+  EWK_VIEW_IMPL_GET_OR_RETURN(view, impl);
+  impl->SetNextPlayerForMediaSwitch(player_id);
+#else
+  LOG_EWK_API_MOCKUP("Only for Tizen TV.");
+#endif  // BUILDFLAG(IS_TIZEN_TV)
 }
 
-void ewk_view_sw_audio_decoding_set(
-  Evas_Object* view,
-  Eina_Bool use_sw_audio_decoder)
-{
+void ewk_view_sw_audio_decoding_set(Evas_Object* view,
+                                    Eina_Bool use_sw_audio_decoder) {
 #if BUILDFLAG(IS_TIZEN_TV)
   LOG(INFO) << "Use sw audio decoding: "
             << static_cast<bool>(use_sw_audio_decoder);
@@ -1332,11 +1364,22 @@ void ewk_view_sw_audio_decoding_set(
 #endif  // BUILDFLAG(IS_TIZEN_TV)
 }
 
+void ewk_view_sw_audio_volume(Evas_Object* view, double volume) {
+  LOG_EWK_API_MOCKUP();
+}
+
 void ewk_view_set_video_geometry(
   Evas_Object* view,
   Eina_Rectangle v_area)
 {
-  LOG_EWK_API_MOCKUP();
+#if BUILDFLAG(IS_TIZEN_TV)
+  LOG(INFO) << "Notify about geometry: " << v_area.x << ", " << v_area.y << " "
+            << v_area.w << "x" << v_area.h;
+  EWK_VIEW_IMPL_GET_OR_RETURN(view, impl);
+  impl->SetVideoGeometry(v_area.x, v_area.y, v_area.w, v_area.h);
+#else
+  LOG_EWK_API_MOCKUP("Only for Tizen TV.");
+#endif  // BUILDFLAG(IS_TIZEN_TV)
 }
 
 void ewk_view_release_players(
@@ -1370,14 +1413,26 @@ void ewk_view_player_play(
   Evas_Object* view,
   int video_id)
 {
-  LOG_EWK_API_MOCKUP();
+#if BUILDFLAG(IS_TIZEN_TV)
+  LOG(INFO) << "Video play: " << video_id;
+  EWK_VIEW_IMPL_GET_OR_RETURN(view, impl);
+  impl->VideoPlay(video_id);
+#else
+  LOG_EWK_API_MOCKUP("Only for Tizen TV.");
+#endif  // BUILDFLAG(IS_TIZEN_TV)
 }
 
 void ewk_view_player_pause(
   Evas_Object* view,
   int video_id)
 {
-  LOG_EWK_API_MOCKUP();
+#if BUILDFLAG(IS_TIZEN_TV)
+  LOG(INFO) << "Video pause: " << video_id;
+  EWK_VIEW_IMPL_GET_OR_RETURN(view, impl);
+  impl->VideoPause(video_id);
+#else
+  LOG_EWK_API_MOCKUP("Only for Tizen TV.");
+#endif  // BUILDFLAG(IS_TIZEN_TV)
 }
 
 Eina_Bool ewk_media_translated_url_set(Evas_Object* ewkView, const char* url)
index 9852722ee6a21fa9a3c851034e4f0d5098a47184..232a06caa4655d51881a636444fc425382c61b71 100644 (file)
@@ -831,6 +831,13 @@ EXPORT_API void ewk_view_broadcast_decoder_set(Evas_Object* view,
 EXPORT_API void ewk_view_sw_audio_decoding_set(Evas_Object* view,
   Eina_Bool use_sw_audio_decoder);
 
+/**
+ * Sets volume for player using sw decoder
+ * @param view View object
+ * @param volume value of volume level, range 0.0 - 1.0
+ */
+EXPORT_API void ewk_view_sw_audio_volume(Evas_Object* view, double volume);
+
 /**
  * Set visibility of video with player_id
  *