[M120 Migration][HBBTV] Merge track and subtitle related patches 59/308259/3
authorzhishun.zhou <zhishun.zhou@samsung.com>
Fri, 15 Mar 2024 11:10:37 +0000 (19:10 +0800)
committerYanqing Lu <yanqing.lu@samsung.com>
Thu, 21 Mar 2024 01:27:21 +0000 (01:27 +0000)
1. Support subtitle notification feature:
   ewk interface:
     ewk_view_media_current_time_get
     ewk_settings_media_subtitle_notification_set
     ewk_settings_media_subtitle_notification_get
   ewk view callback:
     SubtitlePlay, SubtitlePause, SubtitleStop,
     SubtitleResume, SubtitleSeekStart,
     SubtitleSeekComplete, SubtitleNotifyData
2. Support track and subtitle interfaces
   ewk interface:
     ewk_media_set_subtitle_lang
   ewk view callback:
     FirstTimestamp,
     PESData

Patches from:
https://review.tizen.org/gerrit/#/c/292656/
https://review.tizen.org/gerrit/#/c/293447/
https://review.tizen.org/gerrit/#/c/293815/
https://review.tizen.org/gerrit/#/c/294812/
https://review.tizen.org/gerrit/#/c/300412/
https://review.tizen.org/gerrit/#/c/296871/
https://review.tizen.org/gerrit/#/c/301281/

Change-Id: Idd2374d50006c95ebcfa2d197df991376fda1acc
Signed-off-by: peng1xiao <peng1.xiao@samsung.com>
Signed-off-by: zhishun.zhou <zhishun.zhou@samsung.com>
90 files changed:
components/cast_streaming/renderer/control/playback_command_forwarding_renderer.cc
components/plugins/renderer/webview_plugin.h
content/browser/renderer_host/render_widget_host_impl.cc
content/browser/renderer_host/render_widget_host_impl.h
content/browser/renderer_host/render_widget_host_view_aura.cc
content/browser/renderer_host/render_widget_host_view_aura.h
content/browser/renderer_host/render_widget_host_view_base.h
content/public/browser/web_contents_delegate.h
content/public/common/content_switches.cc
content/public/common/content_switches.h
content/public/test/fake_render_widget_host.h
media/base/pipeline.h
media/base/pipeline_impl.cc
media/base/pipeline_impl.h
media/base/renderer.h
media/base/renderer_client.h
media/filters/pipeline_controller.cc
media/filters/pipeline_controller.h
media/mojo/clients/mojo_renderer.cc
media/mojo/clients/mojo_renderer.h
media/mojo/clients/mojo_renderer_wrapper.cc
media/mojo/clients/mojo_renderer_wrapper.h
media/mojo/mojom/renderer.mojom
media/mojo/mojom/renderer_extensions.mojom
media/mojo/services/mojo_renderer_service.cc
media/mojo/services/mojo_renderer_service.h
net/base/mime_util.cc
third_party/blink/common/web_preferences/web_preferences_mojom_traits.cc
third_party/blink/public/common/web_preferences/web_preferences.h
third_party/blink/public/common/web_preferences/web_preferences_mojom_traits.h
third_party/blink/public/mojom/webpreferences/web_preferences.mojom
third_party/blink/public/mojom/widget/platform_widget.mojom
third_party/blink/public/platform/web_media_player.h
third_party/blink/public/platform/web_media_player_client.h
third_party/blink/public/web/web_settings.h
third_party/blink/public/web/web_view.h
third_party/blink/renderer/bindings/generated_in_core.gni
third_party/blink/renderer/bindings/idl_in_core.gni
third_party/blink/renderer/core/dom/document.cc
third_party/blink/renderer/core/dom/document.h
third_party/blink/renderer/core/execution_context/execution_context.cc
third_party/blink/renderer/core/execution_context/execution_context.h
third_party/blink/renderer/core/execution_context/execution_context_lifecycle_state_observer.h
third_party/blink/renderer/core/exported/web_settings_impl.cc
third_party/blink/renderer/core/exported/web_settings_impl.h
third_party/blink/renderer/core/exported/web_view_impl.cc
third_party/blink/renderer/core/exported/web_view_impl.h
third_party/blink/renderer/core/frame/settings.h
third_party/blink/renderer/core/frame/web_frame_widget_impl.cc
third_party/blink/renderer/core/frame/web_frame_widget_impl.h
third_party/blink/renderer/core/html/build.gni
third_party/blink/renderer/core/html/media/html_media_element.cc
third_party/blink/renderer/core/html/media/html_media_element.h
third_party/blink/renderer/core/html/track/html_track_element.cc
third_party/blink/renderer/core/html/track/text_track.cc
third_party/blink/renderer/core/html/track/text_track.h
third_party/blink/renderer/core/html/track/text_track.idl
third_party/blink/renderer/core/html/track/text_track_cue.cc
third_party/blink/renderer/core/html/track/text_track_cue.h
third_party/blink/renderer/core/html/track/text_track_list.cc
third_party/blink/renderer/core/html/track/text_track_list.h
third_party/blink/renderer/core/html/track/track_base.h
third_party/blink/renderer/platform/media/web_media_player_impl.cc
third_party/blink/renderer/platform/media/web_media_player_impl.h
third_party/blink/renderer/platform/runtime_enabled_features.json5
third_party/blink/renderer/platform/widget/widget_base.cc
third_party/blink/renderer/platform/widget/widget_base.h
third_party/blink/renderer/platform/widget/widget_base_client.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/browser/renderer_host/rwhv_aura_common_helper_efl.cc
tizen_src/chromium_impl/content/browser/renderer_host/rwhv_aura_common_helper_efl.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/base/efl/media_player_util_efl.cc
tizen_src/chromium_impl/media/base/efl/media_player_util_efl.h
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
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/eweb_view_callbacks.h
tizen_src/ewk/efl_integration/public/ewk_media_subtitle_info.cc
tizen_src/ewk/efl_integration/public/ewk_media_subtitle_info_product.h
tizen_src/ewk/efl_integration/public/ewk_settings.cc
tizen_src/ewk/efl_integration/public/ewk_view.cc
tizen_src/ewk/efl_integration/web_contents_delegate_efl.cc
tizen_src/ewk/efl_integration/web_contents_delegate_efl.h

index b35995a..ccf00d8 100644 (file)
@@ -76,6 +76,13 @@ class RendererCommandForwarder : public media::mojom::Renderer {
     owning_renderer_->MojoRendererSetCdm(cdm_id, std::move(callback));
   }
 
+#if BUILDFLAG(IS_TIZEN_TV)
+  void SetActiveTextTrack(int, bool) override {}
+  void SetActiveAudioTrack(int) override {}
+  void SetActiveVideoTrack(int) override {}
+  void SetPreferTextLanguage(const std::string&) override {}
+#endif
+
  private:
   const raw_ptr<PlaybackCommandForwardingRenderer, ExperimentalRenderer>
       owning_renderer_;
index 773dc1b..4d9c310 100644 (file)
@@ -197,6 +197,9 @@ class WebViewPlugin : public blink::WebPlugin, public blink::WebViewObserver {
     void SetCursor(const ui::Cursor& cursor) override;
 #if BUILDFLAG(IS_TIZEN_TV)
     void DidEdgeScrollBy(const gfx::Point& point, bool handled) override {}
+    void NotifyTrackInfoToBrowser(int active_track_id,
+                                  const std::string& url,
+                                  const std::string& lang) override {}
 #endif
     void UpdateTooltipUnderCursor(const std::u16string& tooltip_text,
                                   base::i18n::TextDirection hint) override;
index 3bd35b3..43ed9e9 100644 (file)
@@ -639,6 +639,14 @@ void RenderWidgetHostImpl::SetParentalRatingResult(const std::string& url,
   }
   blink_widget_->SetParentalRatingResult(url, is_pass);
 }
+
+void RenderWidgetHostImpl::SetPreferSubtitleLang(std::string lang_list) {
+  if (!blink_widget_) {
+    LOG(ERROR) << "blink_widget_ is null";
+    return;
+  }
+  blink_widget_->SetPreferSubtitleLang(lang_list);
+}
 #endif
 
 // static
@@ -2781,6 +2789,18 @@ void RenderWidgetHostImpl::SetTranslatedURL(const std::string& url) {
     return;
   blink_widget_->SetTranslatedURL(url);
 }
+
+void RenderWidgetHostImpl::NotifyTrackInfoToBrowser(int active_track_id,
+                                                    const std::string& url,
+                                                    const std::string& lang) {
+  LOG(INFO) << __func__;
+  if (!GetView()) {
+    LOG(ERROR) << __func__ << ", GetView return null";
+    return;
+  }
+
+  view_->NotifyTrackInfoToBrowser(active_track_id, url, lang);
+}
 #endif
 
 void RenderWidgetHostImpl::UpdateTooltipUnderCursor(
index 5141bdf..d895491 100644 (file)
@@ -322,6 +322,9 @@ class CONTENT_EXPORT RenderWidgetHostImpl
 #if BUILDFLAG(IS_TIZEN_TV)
   //Browser edge scroll
   void DidEdgeScrollBy(const gfx::Point& point, bool handled) override;
+  void NotifyTrackInfoToBrowser(int active_track_id,
+                                const std::string& url,
+                                const std::string& lang) override;
 #endif
   void UpdateTooltipUnderCursor(
       const std::u16string& tooltip_text,
@@ -384,6 +387,7 @@ class CONTENT_EXPORT RenderWidgetHostImpl
   void OnGetVideoPlayingStatus(int callback_id, bool is_playing);
   void SetTranslatedURL(const std::string& url);
   void SetParentalRatingResult(const std::string& url, bool is_pass);
+  void SetPreferSubtitleLang(std::string lang_list);
 #endif
 
   RenderWidgetHostDelegate* delegate() const { return delegate_; }
index c6efa4f..b22ac2a 100644 (file)
@@ -2313,6 +2313,17 @@ void RenderWidgetHostViewAura::DidEdgeScrollBy(const gfx::Point& offset,
     bool handled) {
     efl_helper_->DidEdgeScrollBy(offset, handled);
 }
+
+void RenderWidgetHostViewAura::NotifyTrackInfoToBrowser(
+    int active_track_id,
+    const std::string& url,
+    const std::string& lang) {
+  if (!aura_efl_helper()) {
+    LOG(ERROR) << "aura_efl_helper() is null";
+    return;
+  }
+  aura_efl_helper()->NotifyTrackInfoToBrowser(active_track_id, url, lang);
+}
 #endif
 
 void RenderWidgetHostViewAura::OnScrollEvent(ui::ScrollEvent* event) {
index d18e39a..92245f7 100644 (file)
@@ -230,6 +230,9 @@ class CONTENT_EXPORT RenderWidgetHostViewAura
 #if BUILDFLAG(IS_TIZEN_TV)
   //Browser edge scroll
   void DidEdgeScrollBy(const gfx::Point& offset, bool handled) override ;
+  void NotifyTrackInfoToBrowser(int active_track_id,
+                                const std::string& url,
+                                const std::string& lang) override;
 #endif
   void OnSynchronizedDisplayPropertiesChanged(bool rotation = false) override;
   viz::ScopedSurfaceIdAllocator DidUpdateVisualProperties(
index a47162f..2b55acf 100644 (file)
@@ -509,6 +509,11 @@ class CONTENT_EXPORT RenderWidgetHostViewBase : public RenderWidgetHostView {
   virtual void DidEdgeScrollBy(const gfx::Point& offset, bool handled) {}
   // notify web browser video playing status
   virtual void VideoPlayingStatusReceived(bool is_playing, int callback_id) {}
+
+  // Notify track info to browser
+  virtual void NotifyTrackInfoToBrowser(int active_track_id,
+                                        const std::string& url,
+                                        const std::string& lang) {}
 #endif
 
   // Calls UpdateTooltip if the view is under the cursor.
index 1ad242e..c561d38 100644 (file)
@@ -754,6 +754,21 @@ class CONTENT_EXPORT WebContentsDelegate {
                                           const std::string& value,
                                           const std::string& data,
                                           int type) {}
+  virtual void NotifySubtitleState(int state, double time_stamp = 0.0) {}
+  virtual void NotifySubtitlePlay(int active_track_id,
+                                  const std::string& url,
+                                  const std::string& lang) {}
+  virtual void NotifySubtitleData(int track_id,
+                                  double time_stamp,
+                                  const std::string& data,
+                                  unsigned size) {}
+  virtual void UpdateCurrentTime(double current_time) {}
+  virtual void NotifyFirstTimeStamp(unsigned long long timestamp,
+                                    int time_base_num,
+                                    int time_base_den) {}
+  virtual void NotifyPESData(const std::string& buf,
+                             unsigned int len,
+                             int media_position) {}
 #endif
 
 #if BUILDFLAG(IS_ANDROID)
index 7f95a83..6da2f0e 100644 (file)
@@ -1083,6 +1083,9 @@ const char kEnableMediaPlaybackNotification[] =
     "enable-media-playback-notification";
 // Enables dual decoding for webrtc video call
 const char kDualDecodingWebRTC[] = "enable-webrtc-dual-decoding";
+// Enables media subtitle notification for other applications
+const char kEnableMediaSubtitleNotification[] =
+    "enable-media-subtitle-notification";
 // Enables multiplayers feature for web app
 const char kEnableMultiPlayerForWebapp[] = "enable-multiplayer-for-webapp";
 #endif
index a851eed..f5c5852 100644 (file)
@@ -302,6 +302,7 @@ CONTENT_EXPORT extern const char kMaxRefreshRate[];
 #if BUILDFLAG(IS_TIZEN_TV)
 CONTENT_EXPORT extern const char kEnableMediaPlaybackNotification[];
 CONTENT_EXPORT extern const char kDualDecodingWebRTC[];
+CONTENT_EXPORT extern const char kEnableMediaSubtitleNotification[];
 CONTENT_EXPORT extern const char kEnableMultiPlayerForWebapp[];
 #endif
 
index b286d8d..983e724 100644 (file)
@@ -60,6 +60,9 @@ class FakeRenderWidgetHost : public blink::mojom::FrameWidgetHost,
   void SetCursor(const ui::Cursor& cursor) override;
 #if BUILDFLAG(IS_TIZEN_TV)
   void DidEdgeScrollBy(const ::gfx::Point& offset, bool handled) override;
+  void NotifyTrackInfoToBrowser(int active_track_id,
+                                const std::string& url,
+                                const std::string& lang) override {}
 #endif
   void UpdateTooltipUnderCursor(
       const std::u16string& tooltip_text,
index 62f5dae..0a1260e 100644 (file)
@@ -31,6 +31,35 @@ namespace media {
 class CdmContext;
 class Demuxer;
 
+enum TRACKCMD { SETTEXT, SETAUDIO, SETVIDEO, SETINBAND, SETCUE };
+
+struct InbandTextInfo {
+  std::string info;
+  int band_type;
+  int action;
+};
+
+struct TrackInfo {
+  std::string id;
+  std::string kind;
+  std::string label;
+  std::string language;
+  bool enabled;
+};
+
+struct InbandCueInfo {
+  std::string info;
+  int id;
+  int band_type;
+  int stime;
+  int etime;
+};
+
+struct MediaTrackInfo {
+  TRACKCMD cmd;
+  void* info;
+};
+
 class MEDIA_EXPORT Pipeline {
  public:
   class Client {
@@ -59,6 +88,11 @@ class MEDIA_EXPORT Pipeline {
     virtual void OnBufferingStateChange(BufferingState state,
                                         BufferingStateChangeReason reason) = 0;
 
+#if BUILDFLAG(IS_TIZEN_TV)
+    virtual void NotifyTrackInfoToBrowser(int active_track_id) {}
+    virtual void AddTrackInfo(MediaTrackInfo trackinfo) {}
+#endif
+
     // Executed whenever the presentation duration changes.
     virtual void OnDurationChange() = 0;
 
@@ -282,6 +316,10 @@ class MEDIA_EXPORT Pipeline {
 #if BUILDFLAG(IS_TIZEN_TV)
   virtual void SetContentMimeType(const std::string& mime_type) = 0;
   virtual void SetParentalRatingResult(bool is_pass) = 0;
+  virtual void SetActiveTextTrack(int id, bool is_in_band) = 0;
+  virtual void SetActiveAudioTrack(int index) = 0;
+  virtual void SetActiveVideoTrack(int index) = 0;
+  virtual void SetPreferTextLanguage(const std::string& lang) = 0;
 #endif
 };
 
index 63aaf7d..05d72c1 100644 (file)
@@ -117,6 +117,10 @@ class PipelineImpl::RendererWrapper final : public DemuxerHost,
 #if BUILDFLAG(IS_TIZEN_TV)
   void SetContentMimeType(const std::string& mime_type);
   void SetParentalRatingResult(bool is_pass);
+  void SetActiveTextTrack(int id, bool is_in_band);
+  void SetActiveAudioTrack(int index);
+  void SetActiveVideoTrack(int index);
+  void SetPreferTextLanguage(const std::string& lang);
 #endif
 
   // |enabled_track_ids| contains track ids of enabled audio tracks.
@@ -185,6 +189,10 @@ class PipelineImpl::RendererWrapper final : public DemuxerHost,
   void OnFallback(PipelineStatus status) final;
   void OnEnded() final;
   void OnStatisticsUpdate(const PipelineStatistics& stats) final;
+#if BUILDFLAG(IS_TIZEN_TV)
+  void NotifyTrackInfoToBrowser(int active_track_id) final;
+  void AddTrackInfo(media::MediaTrackInfo trackinfo);
+#endif
   void OnBufferingStateChange(BufferingState state,
                               BufferingStateChangeReason reason) final;
   void OnWaiting(WaitingReason reason) final;
@@ -714,6 +722,48 @@ void PipelineImpl::RendererWrapper::SetParentalRatingResult(bool is_pass) {
   else
     LOG(ERROR) << "renderer is null";
 }
+
+void PipelineImpl::RendererWrapper::SetActiveTextTrack(int id,
+                                                       bool is_in_band) {
+  DCHECK(media_task_runner_->RunsTasksInCurrentSequence());
+
+  if (!shared_state_.renderer) {
+    LOG(ERROR) << "renderer is null";
+    return;
+  }
+  shared_state_.renderer->SetActiveTextTrack(id, is_in_band);
+}
+
+void PipelineImpl::RendererWrapper::SetActiveAudioTrack(int index) {
+  DCHECK(media_task_runner_->RunsTasksInCurrentSequence());
+
+  if (!shared_state_.renderer) {
+    LOG(ERROR) << "renderer is null";
+    return;
+  }
+  shared_state_.renderer->SetActiveAudioTrack(index);
+}
+
+void PipelineImpl::RendererWrapper::SetActiveVideoTrack(int index) {
+  DCHECK(media_task_runner_->RunsTasksInCurrentSequence());
+
+  if (!shared_state_.renderer) {
+    LOG(ERROR) << "renderer is null";
+    return;
+  }
+  shared_state_.renderer->SetActiveVideoTrack(index);
+}
+
+void PipelineImpl::RendererWrapper::SetPreferTextLanguage(
+    const std::string& lang) {
+  DCHECK(media_task_runner_->RunsTasksInCurrentSequence());
+
+  if (!shared_state_.renderer) {
+    LOG(ERROR) << "renderer is null";
+    return;
+  }
+  shared_state_.renderer->SetPreferTextLanguage(lang);
+}
 #endif
 
 #if BUILDFLAG(IS_TIZEN_TV)
@@ -1026,6 +1076,24 @@ void PipelineImpl::RendererWrapper::OnStatisticsUpdate(
   }
 }
 
+#if BUILDFLAG(IS_TIZEN_TV)
+void PipelineImpl::RendererWrapper::NotifyTrackInfoToBrowser(
+    int active_track_id) {
+  DVLOG(2) << __func__;
+  main_task_runner_->PostTask(
+      FROM_HERE, base::BindOnce(&PipelineImpl::NotifyTrackInfoToBrowser,
+                                weak_pipeline_, active_track_id));
+}
+
+void PipelineImpl::RendererWrapper::AddTrackInfo(
+    media::MediaTrackInfo trackinfo) {
+  DVLOG(2) << __func__;
+  main_task_runner_->PostTask(
+      FROM_HERE, base::BindOnce(&PipelineImpl::AddTrackInfo, weak_pipeline_,
+                                std::move(trackinfo)));
+}
+#endif
+
 void PipelineImpl::RendererWrapper::OnBufferingStateChange(
     BufferingState state,
     BufferingStateChangeReason reason) {
@@ -1949,6 +2017,52 @@ void PipelineImpl::SetParentalRatingResult(bool is_pass) {
   DCHECK(thread_checker_.CalledOnValidThread());
   renderer_wrapper_->SetParentalRatingResult(is_pass);
 }
+
+void PipelineImpl::SetActiveTextTrack(int id, bool is_in_band) {
+  DVLOG(2) << __func__;
+  DCHECK(thread_checker_.CalledOnValidThread());
+  media_task_runner_->PostTask(
+      FROM_HERE, base::BindOnce(&RendererWrapper::SetActiveTextTrack,
+                                base::Unretained(renderer_wrapper_.get()), id,
+                                is_in_band));
+}
+
+void PipelineImpl::SetActiveAudioTrack(int index) {
+  DVLOG(2) << __func__;
+  DCHECK(thread_checker_.CalledOnValidThread());
+  media_task_runner_->PostTask(
+      FROM_HERE,
+      base::BindOnce(&RendererWrapper::SetActiveAudioTrack,
+                     base::Unretained(renderer_wrapper_.get()), index));
+}
+
+void PipelineImpl::SetActiveVideoTrack(int index) {
+  DVLOG(2) << __func__;
+  DCHECK(thread_checker_.CalledOnValidThread());
+  media_task_runner_->PostTask(
+      FROM_HERE,
+      base::BindOnce(&RendererWrapper::SetActiveVideoTrack,
+                     base::Unretained(renderer_wrapper_.get()), index));
+}
+
+void PipelineImpl::SetPreferTextLanguage(const std::string& lang) {
+  DVLOG(2) << __func__;
+  DCHECK(thread_checker_.CalledOnValidThread());
+  media_task_runner_->PostTask(
+      FROM_HERE,
+      base::BindOnce(&RendererWrapper::SetPreferTextLanguage,
+                     base::Unretained(renderer_wrapper_.get()), lang));
+}
+
+void PipelineImpl::NotifyTrackInfoToBrowser(int active_track_id) {
+  DCHECK(client_);
+  client_->NotifyTrackInfoToBrowser(active_track_id);
+}
+
+void PipelineImpl::AddTrackInfo(media::MediaTrackInfo trackinfo) {
+  DCHECK(client_);
+  client_->AddTrackInfo(std::move(trackinfo));
+}
 #endif
 
 void PipelineImpl::OnDurationChange(base::TimeDelta duration) {
index d49ba75..c933533 100644 (file)
@@ -176,7 +176,13 @@ class MEDIA_EXPORT PipelineImpl : public Pipeline {
   void OnMetadata(const PipelineMetadata& metadata);
 #if BUILDFLAG(IS_TIZEN_TV)
   void SetContentMimeType(const std::string& mime_type) override;
+  void NotifyTrackInfoToBrowser(int active_track_id);
   void SetParentalRatingResult(bool is_pass) override;
+  void AddTrackInfo(media::MediaTrackInfo trackinfo);
+  void SetActiveTextTrack(int id, bool is_in_band) override;
+  void SetActiveAudioTrack(int index) override;
+  void SetActiveVideoTrack(int index) override;
+  void SetPreferTextLanguage(const std::string& lang) override;
 #endif
   void OnBufferingStateChange(BufferingState state,
                               BufferingStateChangeReason reason);
index e1c5783..bde538a 100644 (file)
@@ -110,6 +110,10 @@ class MEDIA_EXPORT Renderer {
 #if BUILDFLAG(IS_TIZEN_TV)
   virtual void SetContentMimeType(const std::string& mime_type) {}
   virtual void SetParentalRatingResult(bool is_pass) {}
+  virtual void SetActiveTextTrack(int id, bool is_in_band) {}
+  virtual void SetActiveAudioTrack(int index) {}
+  virtual void SetActiveVideoTrack(int index) {}
+  virtual void SetPreferTextLanguage(const std::string& lang) {}
 #endif
 
   // Starts rendering from |time|.
index f53f7e6..1dcbdd1 100644 (file)
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/gfx/geometry/size.h"
 
+#if BUILDFLAG(IS_TIZEN_TV)
+#include "media/base/pipeline.h"
+#include "media/mojo/mojom/renderer_extensions.mojom.h"
+#endif
+
 namespace media {
 
 // Interface used by Renderer, AudioRenderer, VideoRenderer and
@@ -35,6 +40,11 @@ class MEDIA_EXPORT RendererClient {
   // OnStatisticsUpdate() call.
   virtual void OnStatisticsUpdate(const PipelineStatistics& stats) = 0;
 
+#if BUILDFLAG(IS_TIZEN_TV)
+  virtual void NotifyTrackInfoToBrowser(int active_track_id) {}
+  virtual void AddTrackInfo(media::MediaTrackInfo trackinfo) {}
+#endif
+
   // Executed when buffering state is changed. |reason| indicates the cause of
   // the state change, when known.
   virtual void OnBufferingStateChange(BufferingState state,
index 1bb647a..eed47f6 100644 (file)
@@ -489,5 +489,37 @@ void PipelineController::SetParentalRatingResult(bool is_pass) {
   else
     LOG(ERROR) << "pipeline_ is null";
 }
+
+void PipelineController::SetActiveTextTrack(int id, bool is_in_band) {
+  if (!pipeline_) {
+    LOG(ERROR) << "pipeline_ is null";
+    return;
+  }
+  pipeline_->SetActiveTextTrack(id, is_in_band);
+}
+
+void PipelineController::SetActiveAudioTrack(int index) {
+  if (!pipeline_) {
+    LOG(ERROR) << "pipeline_ is null";
+    return;
+  }
+  pipeline_->SetActiveAudioTrack(index);
+}
+
+void PipelineController::SetActiveVideoTrack(int index) {
+  if (!pipeline_) {
+    LOG(ERROR) << "pipeline_ is null";
+    return;
+  }
+  pipeline_->SetActiveVideoTrack(index);
+}
+
+void PipelineController::SetPreferTextLanguage(const std::string& lang) {
+  if (!pipeline_) {
+    LOG(ERROR) << "pipeline_ is null";
+    return;
+  }
+  pipeline_->SetPreferTextLanguage(lang);
+}
 #endif
 }  // namespace media
index c7d06ef..113d8bb 100644 (file)
@@ -166,6 +166,10 @@ class MEDIA_EXPORT PipelineController {
 #if BUILDFLAG(IS_TIZEN_TV)
   void SetContentMimeType(const std::string& mime_type);
   void SetParentalRatingResult(bool is_pass);
+  void SetActiveTextTrack(int id, bool is_in_band);
+  void SetActiveAudioTrack(int index);
+  void SetActiveVideoTrack(int index);
+  void SetPreferTextLanguage(const std::string& lang);
 #endif
  private:
   // Attempts to make progress from the current state to the target state.
index da89779..55c5084 100644 (file)
@@ -360,6 +360,46 @@ void MojoRenderer::SetParentalRatingResult(bool is_pass) {
   else
     LOG(ERROR) << "remote_renderer is null";
 }
+
+void MojoRenderer::SetActiveTextTrack(int id, bool is_in_band) {
+  DCHECK(task_runner_->RunsTasksInCurrentSequence());
+
+  if (!remote_renderer_.is_bound()) {
+    LOG(ERROR) << "remote_renderer is not bound";
+    return;
+  }
+  remote_renderer_->SetActiveTextTrack(id, is_in_band);
+}
+
+void MojoRenderer::SetActiveAudioTrack(int index) {
+  DCHECK(task_runner_->RunsTasksInCurrentSequence());
+
+  if (!remote_renderer_.is_bound()) {
+    LOG(ERROR) << "remote_renderer is not bound";
+    return;
+  }
+  remote_renderer_->SetActiveAudioTrack(index);
+}
+
+void MojoRenderer::SetActiveVideoTrack(int index) {
+  DCHECK(task_runner_->RunsTasksInCurrentSequence());
+
+  if (!remote_renderer_.is_bound()) {
+    LOG(ERROR) << "remote_renderer is not bound";
+    return;
+  }
+  remote_renderer_->SetActiveVideoTrack(index);
+}
+
+void MojoRenderer::SetPreferTextLanguage(const std::string& lang) {
+  DCHECK(task_runner_->RunsTasksInCurrentSequence());
+
+  if (!remote_renderer_.is_bound()) {
+    LOG(ERROR) << "remote_renderer is not bound";
+    return;
+  }
+  remote_renderer_->SetPreferTextLanguage(lang);
+}
 #endif
 
 void MojoRenderer::OnWaiting(WaitingReason reason) {
index bb3ca96..aa08217 100644 (file)
@@ -79,6 +79,10 @@ class MojoRenderer : public Renderer, public mojom::RendererClient {
 #if BUILDFLAG(IS_TIZEN_TV)
   void SetContentMimeType(const std::string& mime_type) override;
   void SetParentalRatingResult(bool is_pass) override;
+  void SetActiveTextTrack(int id, bool is_in_band) override;
+  void SetActiveAudioTrack(int index) override;
+  void SetActiveVideoTrack(int index) override;
+  void SetPreferTextLanguage(const std::string& lang) override;
 #endif
 
  private:
index 798099f..4f1c591 100644 (file)
@@ -88,6 +88,29 @@ void MojoRendererWrapper::SetParentalRatingResult(bool is_pass) {
   else
     LOG(ERROR) << "mojo_renderer_ is null";
 }
+
+void MojoRendererWrapper::SetActiveTextTrack(int id, bool is_in_band) {
+  if (!mojo_renderer_) {
+    LOG(ERROR) << "mojo_renderer_ is null";
+    return;
+  }
+  mojo_renderer_->SetActiveTextTrack(id, is_in_band);
+}
+
+void MojoRendererWrapper::SetActiveAudioTrack(int index) {
+  if (mojo_renderer_)
+    mojo_renderer_->SetActiveAudioTrack(index);
+}
+
+void MojoRendererWrapper::SetActiveVideoTrack(int index) {
+  if (mojo_renderer_)
+    mojo_renderer_->SetActiveVideoTrack(index);
+}
+
+void MojoRendererWrapper::SetPreferTextLanguage(const std::string& lang) {
+  if (mojo_renderer_)
+    mojo_renderer_->SetPreferTextLanguage(lang);
+}
 #endif
 
 }  // namespace media
index cd3b5d9..fb68130 100644 (file)
@@ -51,6 +51,10 @@ class MojoRendererWrapper : public Renderer {
 #if BUILDFLAG(IS_TIZEN_TV)
   void SetContentMimeType(const std::string& mime_type) override;
   void SetParentalRatingResult(bool is_pass) override;
+  void SetActiveTextTrack(int id, bool is_in_band) override;
+  void SetActiveVideoTrack(int index) override;
+  void SetActiveAudioTrack(int index) override;
+  void SetPreferTextLanguage(const std::string& lang) override;
 #endif
 
   base::TimeDelta GetMediaTime() override;
index e1342e6..71979eb 100644 (file)
@@ -73,6 +73,18 @@ interface Renderer {
 
   [EnableIf=is_tizen_tv]
   SetParentalRatingResult(bool is_pass);
+
+  [EnableIf=is_tizen_tv]
+  SetActiveTextTrack(int32 id, bool is_in_band);
+
+  [EnableIf=is_tizen_tv]
+  SetActiveAudioTrack(int32 index);
+
+  [EnableIf=is_tizen_tv]
+  SetActiveVideoTrack(int32 index);
+
+  [EnableIf=is_tizen_tv]
+  SetPreferTextLanguage(string lang);
 };
 
 // A Mojo equivalent of media::RendererClient. See media/mojo/README.md
index 93abe9e..966f077 100644 (file)
@@ -13,6 +13,46 @@ import "ui/gfx/mojom/buffer_types.mojom";
 
 [EnableIf=is_win]
 import "ui/gfx/mojom/buffer_types.mojom";
+enum TRACKCMD{
+  SETTEXT,
+  SETAUDIO,
+  SETVIDEO,
+  SETINBAND,
+  SETCUE
+};
+
+struct InbandTextInfo {
+  string info;
+  int32 band_type;
+  int32 action;
+};
+
+struct Track {
+  string id;
+  string kind;
+  string label;
+  string language;
+  bool enabled;
+};
+
+struct InbandCueInfo {
+  string info;
+  uint32 id;
+  int32 band_type;
+  int64 stime;
+  int64 etime;
+};
+
+union COOKIES {
+  Track track;
+  InbandTextInfo inband;
+  InbandCueInfo cue;
+};
+
+struct MediaTrackInfo {
+  TRACKCMD cmd;
+  COOKIES ck;
+};
 // Extension of the mojo::RendererClient communication layer for HLS and Android
 // software rendering fallback paths.
 // This allows the Browser side to call back into the Renderer side. Concretely,
@@ -39,6 +79,12 @@ interface MediaPlayerRendererClientExtension {
   OnNewTbmFrameAvailable(uint32 playerId,
                          gfx.mojom.TbmBufferHandle tbm_buffer_handle,
                          mojo_base.mojom.TimeDelta timestamp);
+
+  [EnableIf=is_tizen_tv]
+  NotifyTrackInfoToBrowser(int32 active_track_id);
+
+  [EnableIf=is_tizen_tv]
+  AddTrackInfo(MediaTrackInfo trackinfo);
 };
 
 // Extension of the mojo::Renderer communication layer for HLS and Android
index 9cf82ee..5537033 100644 (file)
@@ -223,6 +223,42 @@ void MojoRendererService::SetParentalRatingResult(bool is_pass) {
   else
     LOG(ERROR) << "renderer_ is null";
 }
+
+void MojoRendererService::SetActiveTextTrack(int id, bool is_in_band) {
+  DVLOG(2) << __func__ << "(id:" << id << ", is_in_band:" << is_in_band << ")";
+  if (!renderer_) {
+    LOG(ERROR) << "renderer_ is null";
+    return;
+  }
+  renderer_->SetActiveTextTrack(id, is_in_band);
+}
+
+void MojoRendererService::SetActiveAudioTrack(int index) {
+  DVLOG(2) << __func__ << "(index:" << index << ")";
+  if (!renderer_) {
+    LOG(ERROR) << "renderer_ is null";
+    return;
+  }
+  renderer_->SetActiveAudioTrack(index);
+}
+
+void MojoRendererService::SetActiveVideoTrack(int index) {
+  DVLOG(2) << __func__ << "(index:" << index << ")";
+  if (!renderer_) {
+    LOG(ERROR) << "renderer_ is null";
+    return;
+  }
+  renderer_->SetActiveVideoTrack(index);
+}
+
+void MojoRendererService::SetPreferTextLanguage(const std::string& lang) {
+  DVLOG(2) << __func__ << "(lang:" << lang << ")";
+  if (!renderer_) {
+    LOG(ERROR) << "renderer_ is null";
+    return;
+  }
+  renderer_->SetPreferTextLanguage(lang);
+}
 #endif
 
 void MojoRendererService::OnBufferingStateChange(
index 4088111..afc535a 100644 (file)
@@ -85,6 +85,10 @@ class MEDIA_MOJO_EXPORT MojoRendererService final : public mojom::Renderer,
 #if BUILDFLAG(IS_TIZEN_TV)
   void SetContentMimeType(const std::string& mime_type) final;
   void SetParentalRatingResult(bool is_pass) final;
+  void SetActiveTextTrack(int id, bool is_in_band) final;
+  void SetActiveAudioTrack(int index) final;
+  void SetActiveVideoTrack(int index) final;
+  void SetPreferTextLanguage(const std::string& lang) final;
 #endif
 
  private:
index 0cc3af3..af82113 100644 (file)
@@ -235,6 +235,7 @@ static const MimeInfo kSecondaryMappings[] = {
     {"video/mpeg", "mpeg,mpg"},
 #if BUILDFLAG(IS_TIZEN_TV)
     {"application/dash+xml", "mpd"},
+    {"application/ttml+xml", "ttml"},
     {"application/vnd.oipf.contentaccessstreaming+xml", "casd"},
 #endif
 };
index 1c09ddf..699cd9d 100644 (file)
@@ -265,6 +265,8 @@ bool StructTraits<blink::mojom::WebPreferencesDataView,
       data.allow_file_access_from_external_urls();
   out->media_playback_notification_enabled =
       data.media_playback_notification_enabled();
+  out->media_subtitle_notification_enabled =
+      data.media_subtitle_notification_enabled();
 #endif
   return true;
 }
index cb56a6a..3c79709 100644 (file)
@@ -322,6 +322,7 @@ struct BLINK_COMMON_EXPORT WebPreferences {
 
 #if BUILDFLAG(IS_TIZEN_TV)
   bool media_playback_notification_enabled = false;
+  bool media_subtitle_notification_enabled = false;
 #endif
 
   // Whether download UI should be hidden on this page.
index 0ed0971..1bc71f9 100644 (file)
@@ -893,6 +893,13 @@ struct BLINK_COMMON_EXPORT StructTraits<blink::mojom::WebPreferencesDataView,
     return r.modal_context_menu;
   }
 
+#if BUILDFLAG(IS_TIZEN_TV)
+  static bool media_subtitle_notification_enabled(
+      const blink::web_pref::WebPreferences& r) {
+    return r.media_subtitle_notification_enabled;
+  }
+#endif
+
   static bool Read(blink::mojom::WebPreferencesDataView r,
                    blink::web_pref::WebPreferences* out);
 };
index 617e848..b88d418 100644 (file)
@@ -533,6 +533,9 @@ struct WebPreferences {
   bool media_playback_notification_enabled;
 
   [EnableIf=is_tizen_tv]
+  bool media_subtitle_notification_enabled;
+
+  [EnableIf=is_tizen_tv]
   bool allow_file_access_from_external_urls;
 
   [EnableIf=is_tizen_tv]
index 4d8b29a..72a92f1 100644 (file)
@@ -46,6 +46,10 @@ interface WidgetHost {
   UpdateTooltipUnderCursor(mojo_base.mojom.String16 tooltip_text,
                            mojo_base.mojom.TextDirection text_direction_hint);
 
+  //Notitfy trackinfo to browser process
+  [EnableIf=is_tizen_tv]
+  NotifyTrackInfoToBrowser(int32 active_track_id, string url, string lang);
+
   // Sent by a widget to the browser to set the tooltip text and trigger a
   // tooltip to show up, aligned with the bounds (in widget-relative DIPS)
   // passed by parameter. An empty |tooltip_text| will hide the tooltip view.
@@ -148,6 +152,9 @@ interface Widget {
   [EnableIf=is_tizen_tv]
   SetParentalRatingResult(string url, bool is_pass);
 
+  [EnableIf=is_tizen_tv]
+  SetPreferSubtitleLang(string lang_list);
+
   [EnableIf=is_efl]
   PrintToPdf(uint32 width, uint32 height, mojo_base.mojom.FilePath filename);
 
index 645766f..9dbf24f 100644 (file)
@@ -105,6 +105,17 @@ class WebMediaPlayer {
     kLoadTypeMax = kLoadTypeMediaStream,
   };
 
+#if BUILDFLAG(IS_TIZEN_TV)
+  enum {
+    kSubtitlePlay,
+    kSubtitlePause,
+    kSubtitleSeekStart,
+    kSubtitleSeekComplete,
+    kSubtitleStop,
+    kSubtitleResume,
+  };
+#endif
+
   typedef WebString TrackId;
   enum TrackType { kTextTrack, kAudioTrack, kVideoTrack };
 
@@ -396,7 +407,12 @@ class WebMediaPlayer {
   virtual void UnregisterFrameSinkHierarchy() {}
 
 #if BUILDFLAG(IS_TIZEN_TV)
+  virtual void GetPlayTrackInfo(int) {}
   virtual void SetParentalRatingResult(bool is_pass) {}
+  virtual void SetActiveTextTrack(int, bool) {}
+  virtual void SetActiveAudioTrack(int) {}
+  virtual void SetActiveVideoTrack(int) {}
+  virtual void SetPreferTextLanguage(const std::string&) {}
 #endif
 };
 
index 21830e6..3c5356f 100644 (file)
@@ -103,6 +103,12 @@ class BLINK_PLATFORM_EXPORT WebMediaPlayerClient {
                                                 const WebString& language,
                                                 bool selected) = 0;
   virtual void RemoveVideoTrack(WebMediaPlayer::TrackId) = 0;
+#if BUILDFLAG(IS_TIZEN_TV)
+  virtual void AddTextTrack(const WebString& id,
+                            const WebString& Kind,
+                            const WebString& label,
+                            const WebString& language) = 0;
+#endif
   virtual void MediaSourceOpened(WebMediaSource*) = 0;
   virtual void RemotePlaybackCompatibilityChanged(const WebURL&,
                                                   bool is_compatible) = 0;
@@ -230,6 +236,15 @@ class BLINK_PLATFORM_EXPORT WebMediaPlayerClient {
 
 #if BUILDFLAG(IS_TIZEN_TV)
   virtual WebString GetContentMIMEType() = 0;
+  virtual void NotifyTrackInfoToBrowser(int) = 0;
+  virtual void OnInbandTextTrack(const std::string& info,
+                                 int band_type,
+                                 int action) = 0;
+  virtual void AddInbandCue(const std::string& info,
+                            unsigned int id,
+                            int band_type,
+                            long long int start_time,
+                            long long int end_time) = 0;
 #endif
 
  protected:
index ab84944..31df3a4 100644 (file)
@@ -296,6 +296,8 @@ class WebSettings {
 #if BUILDFLAG(IS_TIZEN_TV)
   virtual bool AllowFileAccessFromExternalURLs() = 0;
   virtual void SetAllowFileAccessFromExternalURLs(bool) = 0;
+  virtual void SetMediaSubtitleNotificationEnabled(bool) = 0;
+  virtual bool MediaSubtitleNotificationEnabled() = 0;
 #endif
 
 #if defined(TIZEN_ATK_SUPPORT)
index 1b65e05..f637d7f 100644 (file)
@@ -540,6 +540,7 @@ class BLINK_EXPORT WebView {
   // Return if there is any active video in the view
   virtual bool IsVideoPlaying() const = 0;
   virtual void SetParentalRatingResult(const WebString&, bool) = 0;
+  virtual void SetPreferTextLang(const WebString&) = 0;
 #endif
 
  protected:
index 8f9d93b..ac39b56 100644 (file)
@@ -1085,6 +1085,8 @@ generated_interface_sources_in_core = [
   "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_image_bitmap.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_image_data.cc",
   "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_image_data.h",
+  "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_inband_cue.cc",
+  "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_inband_cue.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_input_device_capabilities.cc",
   "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_input_device_capabilities.h",
   "$root_gen_dir/third_party/blink/renderer/bindings/core/v8/v8_input_event.cc",
index 6401d4f..7ec8487 100644 (file)
@@ -466,6 +466,7 @@ static_idl_files_in_core = [
   "//third_party/blink/renderer/core/html/track/audio_track.idl",
   "//third_party/blink/renderer/core/html/track/audio_track_list.idl",
   "//third_party/blink/renderer/core/html/track/html_track_element.idl",
+  "//third_party/blink/renderer/core/html/track/inband_cue.idl",
   "//third_party/blink/renderer/core/html/track/text_track.idl",
   "//third_party/blink/renderer/core/html/track/text_track_cue.idl",
   "//third_party/blink/renderer/core/html/track/text_track_cue_list.idl",
index f1a0a8a..d6cdaa6 100644 (file)
@@ -9425,6 +9425,14 @@ void Document::SetParentalRatingResult(const String& url, bool is_pass) {
   else
     LOG(ERROR) << "GetExecutionContext() is false";
 }
+
+void Document::SetPreferTextLang(const String& lang) {
+  if (!GetExecutionContext()) {
+    LOG(ERROR) << "Execution Context is null";
+    return;
+  }
+  GetExecutionContext()->SetPreferTextLang(lang);
+}
 #endif
 
 template class CORE_TEMPLATE_EXPORT Supplement<Document>;
index c64ad1f..960abdd 100644 (file)
@@ -1745,6 +1745,7 @@ class CORE_EXPORT Document : public ContainerNode,
 
 #if BUILDFLAG(IS_TIZEN_TV)
   void SetParentalRatingResult(const String& url, bool is_pass);
+  void SetPreferTextLang(const String&);
 #endif
 
 #if DCHECK_IS_ON()
index c0382ee..f370d36 100644 (file)
@@ -328,6 +328,25 @@ bool ExecutionContext::CheckVideoPlaying() const {
 
   return result;
 }
+
+void ExecutionContext::SetPreferTextLang(const String& lang) {
+  ContextLifecycleNotifier::observers().ForEachObserver(
+      [&](ContextLifecycleObserver* observer) {
+        if (!observer->IsExecutionContextLifecycleObserver())
+          return;
+        if (static_cast<ExecutionContextLifecycleObserver*>(observer)
+                ->ObserverType() !=
+            ExecutionContextLifecycleObserver::kStateObjectType)
+          return;
+        ExecutionContextLifecycleStateObserver* state_observer =
+            static_cast<ExecutionContextLifecycleStateObserver*>(observer);
+#if DCHECK_IS_ON()
+        DCHECK_EQ(state_observer->GetExecutionContext(), Context());
+        DCHECK(state_observer->UpdateStateIfNeededCalled());
+#endif
+        state_observer->SetPreferTextLang(lang);
+      });
+}
 #endif
 
 void ExecutionContext::AddConsoleMessageImpl(
index bfac902..b9a40ab 100644 (file)
@@ -480,6 +480,7 @@ class CORE_EXPORT ExecutionContext : public Supplementable<ExecutionContext>,
   bool CheckVideoPlaying() const;
   void SetTranslatedURL(const String&);
   void SetParentalRatingResult(const String& url, bool is_pass);
+  void SetPreferTextLang(const String&);
 #endif
 
  protected:
index 45b9b86..f427c5f 100644 (file)
@@ -77,6 +77,7 @@ class CORE_EXPORT ExecutionContextLifecycleStateObserver
   virtual String GetUrl() const { return ""; }
   virtual void SetParentalRatingResult(bool) {}
   virtual void SetTranslatedURL(const String&) {}
+  virtual void SetPreferTextLang(const String&) {}
 #endif
 
   void SetExecutionContext(ExecutionContext*) override;
index e9d6b3c..5082766 100644 (file)
@@ -838,6 +838,14 @@ void WebSettingsImpl::SetAllowFileAccessFromExternalURLs(bool allow) {
 bool WebSettingsImpl::AllowFileAccessFromExternalURLs() {
   return settings_->GetAllowFileAccessFromExternalURLs();
 }
+
+void WebSettingsImpl::SetMediaSubtitleNotificationEnabled(bool enabled) {
+  settings_->SetMediaSubtitleNotificationEnabled(enabled);
+}
+
+bool WebSettingsImpl::MediaSubtitleNotificationEnabled() {
+  return settings_->MediaSubtitleNotificationEnabled();
+}
 #endif
 
 #if defined(TIZEN_ATK_SUPPORT)
index f64d55d..aacdcf1 100644 (file)
@@ -245,6 +245,8 @@ class CORE_EXPORT WebSettingsImpl final : public WebSettings {
   bool AllowFileAccessFromExternalURLs() override;
   void SetMediaPlaybackNotificationEnabled(bool) override;
   bool MediaPlaybackNotificationEnabled() override;
+  void SetMediaSubtitleNotificationEnabled(bool) override;
+  bool MediaSubtitleNotificationEnabled() override;
 #endif
 
 #if defined(TIZEN_ATK_SUPPORT)
index 57e90f8..a1e160c 100644 (file)
@@ -4632,6 +4632,19 @@ bool WebViewImpl::IsVideoPlaying() const {
   }
   return false;
 }
+void WebViewImpl::SetPreferTextLang(const WebString& lang) {
+  if (!MainFrameImpl()) {
+    LOG(ERROR) << "no main frame.";
+    return;
+  }
+
+  for (const Frame* frame = MainFrameImpl()->GetFrame(); frame;
+       frame = frame->Tree().TraverseNext()) {
+    Document* document = To<LocalFrame>(frame)->GetDocument();
+    DCHECK(document);
+    document->SetPreferTextLang(lang);
+  }
+}
 #endif
 
 }  // namespace blink
index 1414e9f..af2b529 100644 (file)
@@ -565,6 +565,7 @@ class CORE_EXPORT WebViewImpl final : public WebView,
 #if BUILDFLAG(IS_TIZEN_TV)
   bool IsVideoPlaying() const override;
   void SetParentalRatingResult(const WebString&, bool) override;
+  void SetPreferTextLang(const WebString&) override;
 #endif
 
   PageScaleConstraintsSet& GetPageScaleConstraintsSet() const;
index f424df9..de16276 100644 (file)
@@ -88,6 +88,13 @@ class CORE_EXPORT Settings {
   void SetDelegate(SettingsDelegate*);
 
 #if BUILDFLAG(IS_TIZEN_TV)
+  void SetMediaSubtitleNotificationEnabled(bool enabled) {
+    media_subtitle_notification_enabled_ = enabled;
+  }
+  bool MediaSubtitleNotificationEnabled() const {
+    return media_subtitle_notification_enabled_;
+  }
+
   void SetMediaPlaybackNotificationEnabled(bool enabled) {
     media_playback_notification_enabled_ = enabled;
   }
@@ -105,6 +112,7 @@ class CORE_EXPORT Settings {
 
 #if BUILDFLAG(IS_TIZEN_TV)
   bool media_playback_notification_enabled_ : 1 = false;
+  bool media_subtitle_notification_enabled_ : 1 = false;
 #endif
 
 #if BUILDFLAG(IS_EFL)
index 6f16d70..49630e7 100644 (file)
@@ -1461,6 +1461,15 @@ bool WebFrameWidgetImpl::IsVideoPlaying() {
   }
   return webview->IsVideoPlaying();
 }
+
+void WebFrameWidgetImpl::SetPreferSubtitleLang(const WTF::String lang_list) {
+  WebViewImpl* webview = View();
+  if (!webview) {
+    LOG(ERROR) << "no webview.";
+    return;
+  }
+  webview->SetPreferTextLang(lang_list);
+}
 #endif
 
 void WebFrameWidgetImpl::SetNeedsRecalculateRasterScales() {
@@ -5164,6 +5173,16 @@ void WebFrameWidgetImpl::NotifyKeyEvent(WebInputEvent::Type type,
 }
 #endif
 
+#if BUILDFLAG(IS_TIZEN_TV)
+void WebFrameWidgetImpl::NotifyTrackInfoToBrowser(int active_track_id,
+                                                  const std::string& url,
+                                                  const std::string& lang) {
+  LOG(INFO) << __func__ << " active_track_id:" << active_track_id
+            << " url:" << url << " lang:" << lang;
+  widget_base_->NotifyTrackInfoToBrowser(active_track_id, url, lang);
+}
+#endif
+
 #if BUILDFLAG(IS_TIZEN)
 void WebFrameWidgetImpl::SetDrawsTransparentBackground(
     bool draws_transparent_background) {
index 3d779fd..2f28251 100644 (file)
@@ -709,6 +709,12 @@ class CORE_EXPORT WebFrameWidgetImpl
   // coordinate space.
   Vector<gfx::Rect> CalculateVisibleLineBoundsOnScreen();
 
+#if BUILDFLAG(IS_TIZEN_TV)
+  void NotifyTrackInfoToBrowser(int active_track_id,
+                                const std::string& url,
+                                const std::string& lang);
+#endif
+
  protected:
   // WidgetBaseClient overrides:
   void WillBeginMainFrame() override;
@@ -870,6 +876,7 @@ class CORE_EXPORT WebFrameWidgetImpl
   bool IsVideoPlaying() override;
   void SetTranslatedURL(const WTF::String& url) override;
   void SetParentalRatingResult(const WTF::String& url, bool is_pass) override;
+  void SetPreferSubtitleLang(const WTF::String lang_list) override;
 #endif
 
   // mojom::blink::FrameWidgetInputHandler overrides.
index 260cf2d..f5c3c56 100644 (file)
@@ -525,6 +525,8 @@ blink_core_sources_html = [
   "track/cue_timeline.h",
   "track/html_track_element.cc",
   "track/html_track_element.h",
+  "track/inband_cue.cpp",
+  "track/inband_cue.h",
   "track/loadable_text_track.cc",
   "track/loadable_text_track.h",
   "track/text_track.cc",
index abdb046..8ff57d2 100644 (file)
@@ -35,6 +35,7 @@
 #include "base/memory/ptr_util.h"
 #include "base/metrics/histogram_functions.h"
 #include "base/metrics/histogram_macros.h"
+#include "base/strings/string_split.h"
 #include "base/synchronization/lock.h"
 #include "base/time/time.h"
 #include "cc/layers/layer.h"
 #include "ui/display/screen_info.h"
 
 #if BUILDFLAG(IS_TIZEN_TV)
+#include <json/json.h>
 #include "third_party/blink/public/platform/web_application_type.h"
+#include "third_party/blink/renderer/core/frame/web_frame_widget_impl.h"
 #endif
 
 #ifndef LOG_MEDIA_EVENTS
@@ -502,6 +505,7 @@ HTMLMediaElement::HTMLMediaElement(const QualifiedName& tag_name,
 #if BUILDFLAG(IS_TIZEN_TV)
       is_deactivate_(false),
       is_translated_url_(false),
+      text_track_menu_on_(false),
 #endif
 #if defined(TIZEN_MULTIMEDIA)
       live_playback_complete_(false),
@@ -1734,11 +1738,27 @@ void HTMLMediaElement::TextTrackReadyStateChanged(TextTrack* track) {
 }
 
 void HTMLMediaElement::TextTrackModeChanged(TextTrack* track) {
+  LOG(INFO) << "textTrackModeChanged,mode:" << (int)track->mode().AsEnum()
+            << ",this:" << (void*)this;
   // Mark this track as "configured" so configureTextTracks won't change the
   // mode again.
   if (IsA<LoadableTextTrack>(track))
     track->SetHasBeenConfigured(true);
 
+#if BUILDFLAG(IS_TIZEN_TV)
+  // if current track is showing, disable other texttrack
+  // Chromium support one active TextTrack shown on screen at the same time from
+  // 2018 Tizen TV Upstream can support more than one TextTrack shown up
+  if (track->mode() == TextTrackMode::kShowing) {
+    for (unsigned i = 0; i < text_tracks_->length(); ++i) {
+      TextTrack* textTrack = text_tracks_->AnonymousIndexedGetter(i);
+      if (textTrack && textTrack != track &&
+          textTrack->mode() == TextTrackMode::kShowing)
+        textTrack->SetModeEnum(TextTrackMode::kDisabled);
+    }
+  }
+#endif
+
   if (track->IsRendered()) {
     GetDocument().GetStyleEngine().AddTextTrack(track);
   } else {
@@ -2147,7 +2167,9 @@ void HTMLMediaElement::SetReadyState(ReadyState state) {
   // Once enough of the media data has been fetched to determine the duration of
   // the media resource, its dimensions, and other metadata...
   if (ready_state_ >= kHaveMetadata && old_state < kHaveMetadata) {
+#if !BUILDFLAG(IS_TIZEN_TV)
     CreatePlaceholderTracksIfNecessary();
+#endif
 
     MediaFragmentURIParser fragment_parser(current_src_.GetSource());
     fragment_end_time_ = fragment_parser.EndTime();
@@ -3218,6 +3240,18 @@ void HTMLMediaElement::AudioTrackChanged(AudioTrack* track) {
 
   audioTracks().ScheduleChangeEvent();
 
+#if BUILDFLAG(IS_TIZEN_TV)
+  // Active:
+  // only need to notify mmplayer about the active id
+  // Deactive:
+  // if track_count > 1 set the active id,others will be deactive
+  // if track_count = 1  player_set_mute / player_set_display_visible
+  if (track->enabled())
+    DisableOtherAudioTracks(track);
+  if (!track->enabled() && 1 == audioTracks().length() && GetWebMediaPlayer())
+    GetWebMediaPlayer()->SetActiveAudioTrack(-1);
+#endif
+
   if (media_source_attachment_)
     media_source_attachment_->OnTrackChanged(media_source_tracer_, track);
 
@@ -3226,6 +3260,18 @@ void HTMLMediaElement::AudioTrackChanged(AudioTrack* track) {
 }
 
 void HTMLMediaElement::AudioTracksTimerFired(TimerBase*) {
+#if BUILDFLAG(IS_TIZEN_TV)
+  for (unsigned i = 0; i < audioTracks().length(); ++i) {
+    AudioTrack* track = audioTracks().AnonymousIndexedGetter(i);
+    // player_select_track_ex parameter is "index",not "id"
+    //"index" is defined by mmplayer,start from 0
+    //"id" is defined by file,mp4/dash/ts  id definition is different
+    if (track->enabled() && GetWebMediaPlayer()) {
+      GetWebMediaPlayer()->SetActiveAudioTrack(i);
+      break;
+    }
+  }
+#else
   Vector<WebMediaPlayer::TrackId> enabled_track_ids;
   for (unsigned i = 0; i < audioTracks().length(); ++i) {
     AudioTrack* track = audioTracks().AnonymousIndexedGetter(i);
@@ -3234,6 +3280,7 @@ void HTMLMediaElement::AudioTracksTimerFired(TimerBase*) {
   }
 
   web_media_player_->EnabledAudioTracksChanged(enabled_track_ids);
+#endif
 }
 
 WebMediaPlayer::TrackId HTMLMediaElement::AddAudioTrack(
@@ -3251,6 +3298,11 @@ WebMediaPlayer::TrackId HTMLMediaElement::AddAudioTrack(
                                                        language, enabled);
   audioTracks().Add(audio_track);
 
+#if BUILDFLAG(IS_TIZEN_TV)
+  if (enabled)
+    DisableOtherAudioTracks(audio_track);
+#endif
+
   return audio_track->id();
 }
 
@@ -3276,9 +3328,29 @@ void HTMLMediaElement::SelectedVideoTrackChanged(VideoTrack* track) {
   if (media_source_attachment_)
     media_source_attachment_->OnTrackChanged(media_source_tracer_, track);
 
+  if (!GetWebMediaPlayer()) {
+    LOG(ERROR) << "GetWebMediaPlayer fail";
+    return;
+  }
+
+#if BUILDFLAG(IS_TIZEN_TV)
+  if (track->selected()) {
+    for (unsigned i = 0; i < videoTracks().length(); ++i) {
+      VideoTrack* cur_track = videoTracks().AnonymousIndexedGetter(i);
+      if (cur_track->selected()) {
+        GetWebMediaPlayer()->SetActiveVideoTrack(i);
+        break;
+      }
+    }
+  } else {
+    if (1 == videoTracks().length())
+      GetWebMediaPlayer()->SetActiveVideoTrack(-1);
+  }
+#else
   WebMediaPlayer::TrackId id = track->id();
   web_media_player_->SelectedVideoTrackChanged(track->selected() ? &id
                                                                  : nullptr);
+#endif
 }
 
 WebMediaPlayer::TrackId HTMLMediaElement::AddVideoTrack(
@@ -3309,6 +3381,48 @@ void HTMLMediaElement::RemoveVideoTrack(WebMediaPlayer::TrackId track_id) {
   videoTracks().Remove(track_id);
 }
 
+#if BUILDFLAG(IS_TIZEN_TV)
+void HTMLMediaElement::AddTextTrack(const WebString& id,
+                                    const WebString& kind,
+                                    const WebString& label,
+                                    const WebString& language) {
+  // 4.8.12.11.2 Sourcing in-band text tracks
+  // 1. Associate the relevant data with a new text track and its corresponding
+  // new TextTrack object.
+  auto* text_track = TextTrack::CreateInband(kind, label, language, id, *this);
+
+  // 2. Set the new text track's kind, label, and language based on the
+  // semantics of the relevant data, as defined by the relevant specification.
+  // If there is no label in that data, then the label must be set to the empty
+  // string.
+  // 3. Associate the text track list of cues with the rules for updating the
+  // text track rendering appropriate for the format in question.
+  // 4. If the new text track's kind is metadata, then set the text track
+  // in-band metadata track dispatch type as follows, based on the type of the
+  // media resource:
+  // 5. Populate the new text track's list of cues with the cues parsed so far,
+  // folllowing the guidelines for exposing cues, and begin updating it
+  // dynamically as necessary.
+  //   - Thess are all done by the media engine.
+
+  // 6. Set the new text track's readiness state to loaded.
+  text_track->SetReadinessState(TextTrack::kLoaded);
+
+  // 7. Set the new text track's mode to the mode consistent with the user's
+  // preferences and the requirements of the relevant specification for the
+  // data.
+  //  - This will happen in honorUserPreferencesForAutomaticTextTrackSelection()
+  ScheduleTextTrackResourceLoad();
+
+  // 8. Add the new text track to the media element's list of text tracks.
+  // 9. Fire an event with the name addtrack, that does not bubble and is not
+  // cancelable, and that uses the TrackEvent interface, with the track
+  // attribute initialized to the text track's TextTrack object, at the media
+  // element's textTracks attribute's TextTrackList object.
+  textTracks()->Append(text_track);
+}
+#endif
+
 void HTMLMediaElement::ForgetResourceSpecificTracks() {
   audio_tracks_->RemoveAll();
   video_tracks_->RemoveAll();
@@ -4089,6 +4203,40 @@ WebString HTMLMediaElement::GetContentMIMEType() {
   return WebString(content_mime_type_);
 }
 
+void HTMLMediaElement::NotifyTrackInfoToBrowser(int active_track_id) {
+  LOG(INFO) << __func__ << "id " << active_track_id;
+
+  LocalFrame* frame = GetDocument().GetFrame();
+  if (!frame) {
+    LOG(ERROR) << "frame is null";
+    return;
+  }
+
+  if (!text_tracks_ ||
+      text_tracks_->length() <= static_cast<unsigned>(active_track_id)) {
+    LOG(ERROR) << "text_tracks_ is null";
+    return;
+  }
+
+  TextTrack* text_track = text_tracks_->AnonymousIndexedGetter(active_track_id);
+  if (!text_track) {
+    LOG(ERROR) << "text_track is null";
+    return;
+  }
+
+  if (IsHTMLVideoElement()) {
+    WebFrameWidgetImpl* wfwgt =
+        static_cast<WebFrameWidgetImpl*>(frame->GetWidgetForLocalRoot());
+    wfwgt->NotifyTrackInfoToBrowser(active_track_id,
+                                    text_track->SrcUrl().GetString().Utf8(),
+                                    text_track->language().Utf8());
+    LOG(INFO) << "HTMLMediaElement(" << (void*)this
+              << "),NotifyTrackInfoToBrowser:"
+              << text_track->SrcUrl().GetString().Utf8()
+              << text_track->language().Utf8();
+  }
+}
+
 void HTMLMediaElement::RequestReload(const KURL& new_url) {
   DCHECK(GetWebMediaPlayer());
   DCHECK(new_url.IsValid());
@@ -4120,6 +4268,236 @@ void HTMLMediaElement::SetParentalRatingResult(bool is_pass) {
   }
   GetWebMediaPlayer()->SetParentalRatingResult(is_pass);
 }
+
+// MMPLAYER only support one audio track active
+void HTMLMediaElement::DisableOtherAudioTracks(AudioTrack* audio_track) {
+  for (unsigned i = 0; i < audioTracks().length(); ++i) {
+    AudioTrack* track = audioTracks().AnonymousIndexedGetter(i);
+    if (track && track != audio_track && track->enabled())
+      track->setEnabled(false);
+  }
+}
+
+TextTrack* HTMLMediaElement::FindTextTrack(int band_type,
+                                           const std::string& info) {
+  for (unsigned int i = 0; i < textTracks()->length(); i++) {
+    TextTrack* text_track = textTracks()->AnonymousIndexedGetter(i);
+    if (text_track && (band_type == text_track->GetTextTrackType()) &&
+        (!info.compare(
+            text_track->inBandMetadataTrackDispatchType().Ascii().data())))
+      return text_track;
+  }
+  return nullptr;
+}
+
+void HTMLMediaElement::OnInbandTextTrack(const std::string& info,
+                                         int band_type,
+                                         int action) {
+  LOG(INFO) << "inband text info" << info << " band_type " << band_type
+            << " action " << action;
+  TextTrack* find_track = FindTextTrack(band_type, info);
+  if (action == ADD_INBAND_TEXT_TRACK) {
+    if (find_track) {
+      LOG(ERROR) << "inBandMetadataTrackDispatchType" << info.c_str()
+                 << "alredy exsit";
+      return;
+    }
+    TextTrack* text_track = TextTrack::Create(
+        TextTrack::MetadataKeyword(), g_empty_atom, g_empty_atom, *this);
+    if (!text_track) {
+      LOG(ERROR) << "create textTrack fail(" << (void*)this << ")";
+      return;
+    }
+    text_track->setInBandMetadataTrackDispatchType(
+        AtomicString::FromUTF8(info.c_str()));
+    text_track->SetReadinessState(TextTrack::kLoaded);
+    textTracks()->Append(text_track);
+    text_track->SetModeEnum(TextTrackMode::kHidden);
+    text_track->SetTextTrackType(band_type);
+    LOG(INFO) << "add inband text successfully(" << (void*)this << ")";
+  } else if (action == DEL_INBAND_TEXT_TRACK) {
+    if (!find_track) {
+      LOG(ERROR) << "inBandMetadataTrackDispatchType" << info.c_str()
+                 << "not exsit";
+      return;
+    }
+    textTracks()->Remove(find_track);
+  }
+}
+
+void HTMLMediaElement::AddInbandCue(const std::string& info,
+                                    unsigned int id,
+                                    int band_type,
+                                    long long int start_time,
+                                    long long int end_time) {
+  // info: "scheme_id_uri value data"
+  // Before: Use space to split, but string may contain multiple spaces
+  // After : Use $ to split, $ is added for string on purpose
+  std::string::size_type delimiter = info.rfind('$');
+  if (delimiter == std::string::npos) {
+    LOG(ERROR) << "can't find $ delimiter in info: " << info.c_str();
+    return;
+  }
+  std::string type = info.substr(0, delimiter);
+  std::string json_data = info.substr(delimiter + 1);
+  std::string data = "";
+  unsigned int index = std::numeric_limits<unsigned int>::max();
+  Json::Reader reader;
+  Json::Value value;
+  if (reader.parse(json_data, value)) {
+    data = value["data"].asString();
+    index = atoi(value["index"].asString().c_str());
+  }
+  LOG(INFO) << "type: " << type.c_str() << ",data: " << data.c_str()
+            << ", index: " << index;
+
+  blink::TextTrack* text_track = FindTextTrack(band_type, type);
+  if (!text_track) {
+    LOG(ERROR) << "find textTrack fail";
+    return;
+  }
+
+  if (text_track->FindCue(index)) {
+    LOG(ERROR) << "cue already exsit,pass it";
+    return;
+  }
+
+  // Please refer to this spec:
+  // HbbTV_v202_specification.pdf chapter 9.3.2.2
+  // 1. For any Dash event with a duration of 250ms or less, the terminal
+  //    shall set the end time of the corresponding DataCue object to the
+  //    startTime + 250ms
+  // 2. If event duration is OxFFFF,endTime shall be set to Number.MAX_VALUE
+  double start = start_time / 1000.0;
+  double end = end_time / 1000.0;
+  if (end_time - start_time <= 250)
+    end = (start_time + 250) / 1000.0;
+  if ((end_time - start_time) / 1000 == 0xFFFF)
+    end = std::numeric_limits<double>::max();
+
+  AtomicString str_id("");
+  if (id != std::numeric_limits<unsigned int>::max())
+    str_id = AtomicString::Number(id);
+
+  text_track->AddCue(start, end, str_id, index, data);
+}
+
+int HTMLMediaElement::FindMatchTrack(const String& lang) {
+  std::vector<std::string> textLangList;
+  textLangList.clear();
+  textLangList = base::SplitStringUsingSubstr(lang.Ascii().data(), ",",
+                                              base::TRIM_WHITESPACE,
+                                              base::SPLIT_WANT_NONEMPTY);
+  if (textLangList.empty()) {
+    LOG(ERROR) << "textLangList is empty";
+    return -1;
+  }
+  for (unsigned i = 0; i < textTracks()->length(); i++) {
+    TextTrack* text_track = textTracks()->AnonymousIndexedGetter(i);
+    if (!text_track)
+      continue;
+    std::string lang = text_track->language().Ascii().data();
+    for (unsigned k = 0; k < textLangList.size(); k++) {
+      if (textLangList[k].find(lang) != std::string::npos)
+        return i;
+    }
+  }
+  return -1;
+}
+
+bool HTMLMediaElement::IsTs() {
+  return current_src_.GetSource().GetString().EndsWithIgnoringCase(".ts");
+}
+
+void HTMLMediaElement::SetPreferTextLang(const String& lang) {
+  // 1.Menu OFF
+  if (lang.empty()) {
+    LOG(INFO) << "HTMLMediaElement::SetPreferTextLang Menu set subtitle off";
+    text_track_menu_on_ = false;
+    active_text_track_id_ = -1;
+    prefer_text_lang_ = "off";
+    // app may not call setMode(),it should call setActiveTextTrack(-1,false)
+    // here
+    // if app call setMode(), check menu on/off in  configureTextTrackDisplay
+    if (GetWebMediaPlayer() && !IsTs())
+      GetWebMediaPlayer()->SetActiveTextTrack(active_text_track_id_, false);
+  } else {
+    text_track_menu_on_ = true;
+    // 2.Menu is ON, all tracks are disabled/hidden by App
+    if (textTracks()->IsAllDisabledByApp()) {
+      LOG(INFO) << "all tracks are disabled by App";
+      active_text_track_id_ = -1;
+      prefer_text_lang_ = "off";
+      if (GetWebMediaPlayer() && !IsTs())
+        GetWebMediaPlayer()->SetActiveTextTrack(active_text_track_id_, false);
+      return;
+    }
+    prefer_text_lang_ = lang.Ascii().data();
+    // 3.Menu ON, has showing track,then match prefer language
+    int idx = FindMatchTrack(lang);
+    // 4. If not foud matched track,the current TC is to display app enabled
+    // track.  find m_activeTextTrackId when app set mode showing
+    if (idx == -1) {
+      active_text_track_id_ = -1;
+      LOG(INFO) << "can't find matched track";
+
+      // 4.1 if app also not set active texttrack, show default track
+      for (unsigned i = 0; i < textTracks()->length(); i++) {
+        TextTrack* textTrack = textTracks()->AnonymousIndexedGetter(i);
+        if (!textTrack)
+          continue;
+        if (textTrack->TrackType() == TextTrack::kTrackElement &&
+            textTrack->IsDefault()) {
+          LOG(INFO) << "default track id:" << i;
+          active_text_track_id_ = i;
+          break;
+        }
+      }
+
+      // 4.2 if no default track,show track0
+      if (active_text_track_id_ == -1) {
+        LOG(INFO) << "no defaut track,show track 0";
+        active_text_track_id_ = 0;
+      }
+
+      TextTrack* finalTrack =
+          textTracks()->AnonymousIndexedGetter(active_text_track_id_);
+      if (finalTrack) {
+        // When TrackElement is inserted, the mode may change to showing,
+        // but WMP is not created, so active text track won't be set.
+        // And setMode will return if we set the same mode again,
+        // so for showing TrackElement, we need to set active text track
+        // here directly.
+        LOG(INFO) << "finalTrack mode " << (int)finalTrack->mode().AsEnum();
+        if (finalTrack->mode() != TextTrackMode::kShowing) {
+          finalTrack->SetModeEnum(TextTrackMode::kShowing);
+        } else if (GetWebMediaPlayer() && !IsTs()) {
+          GetWebMediaPlayer()->SetActiveTextTrack(
+              active_text_track_id_,
+              finalTrack->TrackType() == TextTrack::kInBand);
+        }
+      }
+    }
+    // 5.foud, showing
+    else {
+      LOG(INFO) << "find matched track id:" << idx;
+      if (idx != active_text_track_id_) {
+        active_text_track_id_ = idx;
+        TextTrack* textTrack = textTracks()->AnonymousIndexedGetter(idx);
+        if (textTrack->mode() != TextTrackMode::kShowing) {
+          textTrack->SetModeEnum(TextTrackMode::kShowing);
+        } else if (GetWebMediaPlayer() && !IsTs()) {
+          GetWebMediaPlayer()->SetActiveTextTrack(
+              active_text_track_id_,
+              textTrack->TrackType() == TextTrack::kInBand);
+        }
+      }
+    }
+  }
+
+  if (GetWebMediaPlayer() && IsTs())
+    GetWebMediaPlayer()->SetPreferTextLanguage(prefer_text_lang_);
+}
 #endif
 
 bool HTMLMediaElement::HasPendingActivity() const {
@@ -4439,8 +4817,57 @@ void HTMLMediaElement::ConfigureTextTrackDisplay() {
   bool have_visible_text_track = text_tracks_->HasShowingTracks();
   text_tracks_visible_ = have_visible_text_track;
 
-  if (!have_visible_text_track && !GetMediaControls())
-    return;
+#if BUILDFLAG(IS_TIZEN_TV)
+  if (IsHbbTV()) {
+    if (!have_visible_text_track) {
+      active_text_track_id_ = -1;
+      prefer_text_lang_ = "off";
+      DVLOG(3) << "have no visible text track(" << *this << ")";
+      if (GetWebMediaPlayer() && !IsTs())
+        GetWebMediaPlayer()->SetActiveTextTrack(-1, false);
+    }
+  } else {
+#endif
+    if (!have_visible_text_track && !GetMediaControls()) {
+      DVLOG(3) << "have no visible text track && media_controls_ is null ("
+               << *this << ")";
+      return;
+    }
+#if BUILDFLAG(IS_TIZEN_TV)
+  }
+#endif
+
+#if BUILDFLAG(IS_TIZEN_TV)
+  if (!text_track_menu_on_) {
+    DVLOG(3) << "text track is off (" << *this << ")";
+    prefer_text_lang_ = "off";
+    if (GetWebMediaPlayer() && !IsTs())
+      GetWebMediaPlayer()->SetActiveTextTrack(-1, false);
+  } else {
+    // there is a case,when prefer language match a track
+    // and then js set another active texttrack
+    for (unsigned i = 0; i < text_tracks_->length(); ++i) {
+      TextTrack* textTrack = text_tracks_->AnonymousIndexedGetter(i);
+      if (textTrack && textTrack->mode() == TextTrackMode::kShowing) {
+        active_text_track_id_ = i;
+        prefer_text_lang_ = textTrack->language().Ascii().data();
+        break;
+      }
+    }
+    DVLOG(3) << "text_tracks_->length() " << text_tracks_->length()
+             << "active_text_track_id_:" << active_text_track_id_;
+    if (GetWebMediaPlayer() && !IsTs())
+      GetWebMediaPlayer()->SetActiveTextTrack(
+          active_text_track_id_,
+          active_text_track_id_ > -1
+              ? text_tracks_->AnonymousIndexedGetter(active_text_track_id_)
+                        ->TrackType() == TextTrack::kInBand
+              : false);
+  }
+
+  if (GetWebMediaPlayer() && IsTs())
+    GetWebMediaPlayer()->SetPreferTextLanguage(prefer_text_lang_);
+#endif
 
   // Note: The "time marches on" algorithm |CueTimeline::TimeMarchesOn| runs
   // the "rules for updating the text track rendering" (updateTextTrackDisplay)
index d61c516..6a5a2b2 100644 (file)
@@ -72,6 +72,12 @@ enum class MediaContentType;
 }  // namespace media
 
 namespace blink {
+#if BUILDFLAG(IS_TIZEN_TV)
+enum TrackAction {
+  ADD_INBAND_TEXT_TRACK = 0,
+  DEL_INBAND_TEXT_TRACK,
+};
+#endif
 
 class AudioSourceProviderClient;
 class AudioTrack;
@@ -386,11 +392,22 @@ class CORE_EXPORT HTMLMediaElement
 
 #if BUILDFLAG(IS_TIZEN_TV)
   WebString GetContentMIMEType() override;
+  void NotifyTrackInfoToBrowser(int active_track_id) override;
   void RequestReload(const KURL& new_url);
   void SetTranslatedURL(const String&) override;
   bool IsHTMLMediaElement() const override { return true; }
   WTF::String GetUrl() const override { return current_src_.GetSource(); }
   void SetParentalRatingResult(bool is_pass) override;
+  TextTrack* FindTextTrack(int band_type, const std::string& info);
+  void OnInbandTextTrack(const std::string& info,
+                         int band_type,
+                         int action) override;
+  void AddInbandCue(const std::string& info,
+                    unsigned int id,
+                    int band_type,
+                    long long int start_time,
+                    long long int end_time) override;
+  void SetPreferTextLang(const String& lang) override;
 #endif
 
 #if defined(TIZEN_MULTIMEDIA)
@@ -567,6 +584,12 @@ class CORE_EXPORT HTMLMediaElement
                                         const WebString&,
                                         bool) final;
   void RemoveVideoTrack(WebMediaPlayer::TrackId) final;
+#if BUILDFLAG(IS_TIZEN_TV)
+  void AddTextTrack(const WebString& id,
+                    const WebString& kind,
+                    const WebString& label,
+                    const WebString& language) final;
+#endif
   void MediaSourceOpened(WebMediaSource*) final;
   void RemotePlaybackCompatibilityChanged(const WebURL&,
                                           bool is_compatible) final;
@@ -633,6 +656,12 @@ class CORE_EXPORT HTMLMediaElement
   void NotifyPlayingUrl();
 #endif
 
+#if BUILDFLAG(IS_TIZEN_TV)
+  void DisableOtherAudioTracks(AudioTrack*);
+  int FindMatchTrack(const String& lang);
+  bool IsTs();
+#endif
+
   void LoadTimerFired(TimerBase*);
   void ProgressEventTimerFired();
   void PlaybackProgressTimerFired();
@@ -884,8 +913,11 @@ class CORE_EXPORT HTMLMediaElement
 #endif
 
 #if BUILDFLAG(IS_TIZEN_TV)
+  bool text_track_menu_on_ : 1;
+  int active_text_track_id_{-1};
   String content_mime_type_;
   bool is_translated_url_ : 1;
+  std::string prefer_text_lang_{"und"};  // only for ts
 #endif
   // Set if the user has used the context menu to set the visibility of the
   // controls.
index 0a647d3..25bbb42 100644 (file)
 #include "third_party/blink/renderer/core/html_names.h"
 #include "third_party/blink/renderer/platform/heap/garbage_collected.h"
 
+#if BUILDFLAG(IS_TIZEN_TV)
+#include "third_party/blink/public/platform/web_application_type.h"
+#include "third_party/blink/renderer/core/frame/settings.h"
+#endif
+
 #define TRACK_LOG_LEVEL 3
 
 namespace blink {
@@ -155,6 +160,12 @@ void HTMLTrackElement::ScheduleLoad() {
   if (!MediaElement())
     return;
 
+#if BUILDFLAG(IS_TIZEN_TV)
+  if (TextTrack* text_track = track())
+    text_track->SetSrcUrl(GetNonEmptyURLAttribute(html_names::kSrcAttr));
+  MediaElement()->ConfigureTextTrackDisplay();
+#endif
+
   // 4. Run the remainder of these steps in parallel, allowing whatever caused
   // these steps to run to continue.
   load_timer_.StartOneShot(base::TimeDelta(), FROM_HERE);
@@ -168,6 +179,18 @@ void HTMLTrackElement::ScheduleLoad() {
 void HTMLTrackElement::LoadTimerFired(TimerBase*) {
   DVLOG(TRACK_LOG_LEVEL) << "loadTimerFired";
 
+#if BUILDFLAG(IS_TIZEN_TV)
+  TextTrack* text_track = track();
+  // Webmedia only handle WEBVTT subtitle
+  if (IsHbbTV() && text_track->IsTTML()) {
+    DVLOG(TRACK_LOG_LEVEL)
+        << "Webmedia ignore TTML subtile,It will be handled by HBBTV";
+    load_timer_.Stop();
+    SetReadyState(ReadyState::kLoaded);
+    return;
+  }
+#endif
+
   // 7. [X] Let URL be the track URL of the track element.
   KURL url = GetNonEmptyURLAttribute(html_names::kSrcAttr);
 
@@ -239,8 +262,18 @@ bool HTMLTrackElement::CanLoadUrl(const KURL& url) {
   if (!parent || !GetExecutionContext())
     return false;
 
-  if (url.IsEmpty())
+  if (url.IsEmpty()) {
+    LOG(INFO) << __func__ << ", url is empty";
     return false;
+  }
+
+#if BUILDFLAG(IS_TIZEN_TV)
+  TextTrack* text_track = track();
+  if (text_track->IsTTML()) {
+    LOG(INFO) << __func__ << ", text track is ttml";
+    return false;
+  }
+#endif
 
   if (!GetExecutionContext()->GetContentSecurityPolicy()->AllowMediaFromSource(
           url)) {
index 2601457..74bb1e0 100644 (file)
 #include "third_party/blink/renderer/platform/bindings/exception_state.h"
 #include "ui/accessibility/accessibility_features.h"
 
+#if BUILDFLAG(IS_TIZEN_TV)
+#include "third_party/blink/renderer/core/html/track/inband_cue.h"
+#endif
+
 namespace blink {
 
 static const int kInvalidTrackIndex = -1;
@@ -76,13 +80,19 @@ TextTrack::TextTrack(const AtomicString& kind,
                      TextTrackType type)
     : TrackBase(WebMediaPlayer::kTextTrack, kind, label, language, id),
       active_cues_(nullptr),
+#if BUILDFLAG(IS_TIZEN_TV)
+      src_url_(KURL()),
+      is_ttml_(false),
+      is_disabled_by_app_(false),
+#endif
       track_list_(nullptr),
       source_element_(source_element),
       track_type_(type),
       readiness_state_(kNotLoaded),
       track_index_(kInvalidTrackIndex),
       rendered_track_index_(kInvalidTrackIndex),
-      has_been_configured_(false) {}
+      has_been_configured_(false) {
+}
 
 TextTrack::~TextTrack() = default;
 
@@ -123,6 +133,14 @@ void TextTrack::setMode(const V8TextTrackMode& mode) {
   if (mode_ == mode.AsEnum())
     return;
 
+#if BUILDFLAG(IS_TIZEN_TV)
+  // default mode = disabled, is_disabled_by_app_ means user set disabled/hidden
+  if (mode == TextTrackMode::kDisabled || mode == TextTrackMode::kHidden)
+    is_disabled_by_app_ = true;
+  else
+    is_disabled_by_app_ = false;
+#endif
+
   if (cues_ && GetCueTimeline()) {
     // If mode changes to disabled, remove this track's cues from the client
     // because they will no longer be accessible from the cues() function.
@@ -272,6 +290,9 @@ void TextTrack::removeCue(TextTrackCue* cue, ExceptionState& exception_state) {
   DCHECK(!cue->IsActive() || GetCueTimeline());
 
   cue->SetTrack(nullptr);
+#if BUILDFLAG(IS_TIZEN_TV)
+  indexs_.erase(cue->index().ToInt());
+#endif
 
   if (GetCueTimeline())
     GetCueTimeline()->RemoveCue(this, cue);
@@ -375,6 +396,42 @@ CueTimeline* TextTrack::GetCueTimeline() const {
   return MediaElement() ? &MediaElement()->GetCueTimeline() : nullptr;
 }
 
+#if BUILDFLAG(IS_TIZEN_TV)
+void TextTrack::SetSrcUrl(const KURL& url) {
+  src_url_ = url;
+  String last_path = url.LastPathComponent();
+  size_t pos = last_path.ReverseFind('.');
+  if (pos != kNotFound) {
+    String extension = last_path.Substring(pos + 1);
+    String mime_type = MIMETypeRegistry::GetMIMETypeForExtension(extension);
+    if (mime_type == "text/xml" || mime_type == "application/ttml+xml")
+      is_ttml_ = true;
+  }
+}
+
+bool TextTrack::FindCue(unsigned int index) {
+  if (indexs_.find(index) == indexs_.end())
+    return false;
+  else
+    return true;
+}
+
+void TextTrack::AddCue(double start_time,
+                       double end_time,
+                       AtomicString& id,
+                       unsigned int index,
+                       const std::string& data) {
+  TextTrackCue* cue = InbandCue::Create(start_time, end_time, data);
+  if (cue) {
+    cue->setId(id);
+    cue->setIndex(AtomicString::Number(index));
+    // index&id can make sure which cue is. because some TCs id will be null.
+    indexs_.insert(std::pair<unsigned int, AtomicString>(index, id));
+    addCue(cue);
+  }
+}
+#endif
+
 Node* TextTrack::Owner() const {
   return MediaElement();
 }
index 8106c6a..f25ee9b 100644 (file)
 #include "third_party/blink/renderer/platform/wtf/casting.h"
 #include "third_party/blink/renderer/platform/wtf/text/wtf_string.h"
 
+#if BUILDFLAG(IS_TIZEN_TV)
+#include "third_party/blink/renderer/platform/weborigin/kurl.h"
+#endif
+
 namespace blink {
 
 class CueTimeline;
@@ -54,6 +58,25 @@ class CORE_EXPORT TextTrack : public EventTarget, public TrackBase {
   DEFINE_WRAPPERTYPEINFO();
 
  public:
+  static TextTrack* Create(const AtomicString& kind,
+                           const AtomicString& label,
+                           const AtomicString& language,
+                           HTMLElement& source_element) {
+    return MakeGarbageCollected<TextTrack>(
+        kind, label, language, source_element, g_empty_atom, kAddTrack);
+  }
+
+#if BUILDFLAG(IS_TIZEN_TV)
+  static TextTrack* CreateInband(const AtomicString& kind,
+                                 const AtomicString& label,
+                                 const AtomicString& language,
+                                 const AtomicString& id,
+                                 HTMLElement& source_element) {
+    return MakeGarbageCollected<TextTrack>(kind, label, language,
+                                           source_element, id, kInBand);
+  }
+#endif
+
   enum TextTrackType { kTrackElement, kAddTrack, kInBand };
 
   TextTrack(const AtomicString& kind,
@@ -94,6 +117,8 @@ class CORE_EXPORT TextTrack : public EventTarget, public TrackBase {
   };
   ReadinessState GetReadinessState() const { return readiness_state_; }
   void SetReadinessState(ReadinessState state) { readiness_state_ = state; }
+  void SetTextTrackType(int band_type) { band_type_ = band_type; }
+  int GetTextTrackType() { return band_type_; }
 
   TextTrackCueList* cues();
   TextTrackCueList* activeCues();
@@ -138,6 +163,19 @@ class CORE_EXPORT TextTrack : public EventTarget, public TrackBase {
 
   void SetCSSStyleSheets(HeapVector<Member<CSSStyleSheet>>);
 
+#if BUILDFLAG(IS_TIZEN_TV)
+  virtual void SetSrcUrl(const KURL&);
+  const KURL& SrcUrl() const { return src_url_; }
+  virtual bool IsTTML() { return is_ttml_; }
+  bool FindCue(unsigned int index);
+  void AddCue(double start_time,
+              double end_time,
+              AtomicString& id,
+              unsigned int index,
+              const std::string& data);
+  bool IsDisabledByApp() { return is_disabled_by_app_; }
+#endif
+
  protected:
   void AddListOfCues(HeapVector<Member<TextTrackCue>>&);
 
@@ -149,11 +187,19 @@ class CORE_EXPORT TextTrack : public EventTarget, public TrackBase {
   Member<TextTrackCueList> active_cues_;
   HeapVector<Member<CSSStyleSheet>> style_sheets_;
 
+#if BUILDFLAG(IS_TIZEN_TV)
+  KURL src_url_;
+  bool is_ttml_;
+  bool is_disabled_by_app_;
+  std::unordered_map<unsigned int, AtomicString> indexs_;
+#endif
+
   Member<TextTrackList> track_list_;
   Member<HTMLElement> source_element_;
   TextTrackMode mode_ = TextTrackMode::kDisabled;
   TextTrackType track_type_;
   ReadinessState readiness_state_;
+  int band_type_{0};
   int track_index_;
   int rendered_track_index_;
   bool has_been_configured_;
index a4268f5..cef5559 100644 (file)
@@ -35,7 +35,7 @@ interface TextTrack : EventTarget {
     readonly attribute DOMString language;
 
     readonly attribute DOMString id;
-    // readonly attribute DOMString inBandMetadataTrackDispatchType;
+    readonly attribute DOMString inBandMetadataTrackDispatchType;
 
     attribute TextTrackMode mode;
 
index 154ab34..6b4c360 100644 (file)
@@ -80,6 +80,17 @@ void TextTrackCue::setId(const AtomicString& id) {
   CueDidChange();
 }
 
+#if BUILDFLAG(IS_TIZEN_TV)
+void TextTrackCue::setIndex(const AtomicString& index) {
+  if (index_ == index)
+    return;
+
+  CueWillChange();
+  index_ = index;
+  CueDidChange();
+}
+#endif
+
 void TextTrackCue::setStartTime(double value) {
   if (start_time_ == value)
     return;
index 555ead2..fe65fba 100644 (file)
@@ -67,6 +67,11 @@ class CORE_EXPORT TextTrackCue : public EventTarget {
   double endTime() const { return end_time_; }
   void setEndTime(double);
 
+#if BUILDFLAG(IS_TIZEN_TV)
+  const AtomicString& index() const { return index_; }
+  void setIndex(const AtomicString&);
+#endif
+
   bool pauseOnExit() const { return pause_on_exit_; }
   void setPauseOnExit(bool);
 
@@ -125,6 +130,9 @@ class CORE_EXPORT TextTrackCue : public EventTarget {
   DispatchEventResult DispatchEventInternal(Event&) override;
 
  private:
+#if BUILDFLAG(IS_TIZEN_TV)
+  AtomicString index_;
+#endif
   AtomicString id_;
   double start_time_;
   double end_time_;
index cb899fc..ca85dc5 100644 (file)
@@ -266,4 +266,20 @@ void TextTrackList::Trace(Visitor* visitor) const {
   EventTarget::Trace(visitor);
 }
 
+#if BUILDFLAG(IS_TIZEN_TV)
+bool TextTrackList::IsAllDisabledByApp() {
+  unsigned long disableCount = 0;
+  if (length() <= 0)
+    return false;
+
+  for (unsigned i = 0; i < length(); i++) {
+    if (AnonymousIndexedGetter(i)->IsDisabledByApp())
+      disableCount++;
+  }
+  if (disableCount >= length())
+    return true;
+  return false;
+}
+#endif
+
 }  // namespace blink
index 1386ea2..cdc2506 100644 (file)
@@ -72,6 +72,10 @@ class CORE_EXPORT TextTrackList final : public EventTarget {
 
   void Trace(Visitor*) const override;
 
+#if BUILDFLAG(IS_TIZEN_TV)
+  bool IsAllDisabledByApp();
+#endif
+
  private:
   void ScheduleTrackEvent(const AtomicString& event_name, TextTrack*);
 
index e099be8..13d2e1f 100644 (file)
@@ -48,6 +48,20 @@ class CORE_EXPORT TrackBase : public Supplementable<TrackBase> {
   AtomicString label() const { return label_; }
   AtomicString language() const { return language_; }
 
+  AtomicString inBandMetadataTrackDispatchType() const {
+#if BUILDFLAG(IS_TIZEN_TV)
+    return inband_metadata_track_dispatch_type_;
+#else
+    return g_empty_atom;
+#endif
+  }
+
+  void setInBandMetadataTrackDispatchType(const AtomicString& type) {
+#if BUILDFLAG(IS_TIZEN_TV)
+    inband_metadata_track_dispatch_type_ = type;
+#endif
+  }
+
   void SetMediaElement(HTMLMediaElement* media_element) {
     media_element_ = media_element;
   }
@@ -67,6 +81,7 @@ class CORE_EXPORT TrackBase : public Supplementable<TrackBase> {
   AtomicString label_;
   AtomicString language_;
   String id_;
+  AtomicString inband_metadata_track_dispatch_type_;
   Member<HTMLMediaElement> media_element_;
 };
 
index e568676..b632c01 100644 (file)
@@ -111,6 +111,37 @@ const base::TimeDelta kLayerBoundUpdateInterval = base::Milliseconds(50);
 }  // namespace
 #endif
 
+#if BUILDFLAG(IS_TIZEN_TV)
+#include "tizen_src/chromium_impl/tizen/tizen_tv_platform.h"
+#include "tizen_src/ewk/efl_integration/common/application_type.h"
+
+typedef struct {
+  const std::string kind_str_;
+  blink::WebMediaPlayerClient::AudioTrackKind kind_enum_;
+} AudioKind;
+
+static AudioKind audioKinds[] = {
+    {"alternative", blink::WebMediaPlayerClient::kAudioTrackKindAlternative},
+    {"descriptions", blink::WebMediaPlayerClient::kAudioTrackKindDescriptions},
+    {"main", blink::WebMediaPlayerClient::kAudioTrackKindMain},
+    {"main-desc", blink::WebMediaPlayerClient::kAudioTrackKindMainDescriptions},
+    {"translation", blink::WebMediaPlayerClient::kAudioTrackKindTranslation},
+    {"commentary", blink::WebMediaPlayerClient::kAudioTrackKindCommentary}};
+
+typedef struct {
+  const std::string kind_str_;
+  blink::WebMediaPlayerClient::VideoTrackKind kind_enum_;
+} VideoKind;
+
+static VideoKind videoKinds[] = {
+    {"alternative", blink::WebMediaPlayerClient::kVideoTrackKindAlternative},
+    {"captions", blink::WebMediaPlayerClient::kVideoTrackKindCaptions},
+    {"main", blink::WebMediaPlayerClient::kVideoTrackKindMain},
+    {"sign", blink::WebMediaPlayerClient::kVideoTrackKindSign},
+    {"subtitles", blink::WebMediaPlayerClient::kVideoTrackKindSubtitles},
+    {"commentary", blink::WebMediaPlayerClient::kVideoTrackKindCommentary}};
+#endif
+
 namespace blink {
 namespace {
 
@@ -2214,6 +2245,24 @@ void WebMediaPlayerImpl::OnProgress() {
   }
 }
 
+#if BUILDFLAG(IS_TIZEN_TV)
+void WebMediaPlayerImpl::SetActiveTextTrack(int id, bool is_in_band) {
+  pipeline_controller_->SetActiveTextTrack(id, is_in_band);
+}
+
+void WebMediaPlayerImpl::SetActiveAudioTrack(int index) {
+  pipeline_controller_->SetActiveAudioTrack(index);
+}
+
+void WebMediaPlayerImpl::SetActiveVideoTrack(int index) {
+  pipeline_controller_->SetActiveVideoTrack(index);
+}
+
+void WebMediaPlayerImpl::SetPreferTextLanguage(const std::string& lang) {
+  pipeline_controller_->SetPreferTextLanguage(lang);
+}
+#endif
+
 bool WebMediaPlayerImpl::CanPlayThrough() {
   if (!base::FeatureList::IsEnabled(media::kSpecCompliantCanPlayThrough))
     return true;
@@ -2343,9 +2392,110 @@ void WebMediaPlayerImpl::OnBufferingStateChangeInternal(
 }
 
 #if BUILDFLAG(IS_TIZEN_TV)
+void WebMediaPlayerImpl::NotifyTrackInfoToBrowser(int active_track_id) {
+  LOG(INFO) << __func__ << "active_track_id " << active_track_id;
+  if (!client_) {
+    LOG(ERROR) << __func__ << " client is null ";
+    return;
+  }
+  client_->NotifyTrackInfoToBrowser(active_track_id);
+}
+
 void WebMediaPlayerImpl::SetParentalRatingResult(bool is_pass) {
   pipeline_controller_->SetParentalRatingResult(is_pass);
 }
+
+void WebMediaPlayerImpl::AddTrackInfo(media::MediaTrackInfo trackinfo) {
+  LOG(INFO) << "WebMediaPlayerEfl::AddTrackInfo trackinfo->cmd "
+            << (int)trackinfo.cmd;
+  media::TrackInfo* pTrack;
+  if (trackinfo.cmd == media::TRACKCMD::SETTEXT) {
+    pTrack = (media::TrackInfo*)trackinfo.info;
+    LOG(INFO) << "AddTrackInfo SETTEXT-pTrack:" << pTrack;
+    LOG(INFO) << "AddTrackInfo SETTEXT kind " << pTrack->kind << " label "
+              << pTrack->label << " language " << pTrack->language << " id "
+              << pTrack->id;
+
+    client_->AddTextTrack(blink::WebString::FromUTF8(pTrack->id),
+                          blink::WebString::FromUTF8(pTrack->kind),
+                          blink::WebString::FromUTF8(pTrack->label),
+                          blink::WebString::FromUTF8(pTrack->language));
+    delete (pTrack);
+  } else if (trackinfo.cmd == media::TRACKCMD::SETAUDIO) {
+    pTrack = (media::TrackInfo*)trackinfo.info;
+    LOG(INFO) << "AddTrackInfo SETAUDIO - id: " << pTrack->id
+              << ", kind: " << pTrack->kind.c_str()
+              << ", label: " << pTrack->label.c_str()
+              << ", lang: " << pTrack->language.c_str();
+
+    blink::WebMediaPlayerClient::AudioTrackKind audio_track_kind =
+        blink::WebMediaPlayerClient::kAudioTrackKindNone;
+
+    for (const auto& i : audioKinds) {
+      if (pTrack->kind.compare(i.kind_str_) == 0) {
+        audio_track_kind = i.kind_enum_;
+        break;
+      }
+    }
+
+    client_->AddAudioTrack(
+        blink::WebString::FromUTF8(pTrack->id), audio_track_kind,
+        blink::WebString::FromUTF8(pTrack->label),
+        blink::WebString::FromUTF8(pTrack->language), pTrack->enabled);
+    delete (pTrack);
+  } else if (trackinfo.cmd == media::TRACKCMD::SETVIDEO) {
+    pTrack = (media::TrackInfo*)trackinfo.info;
+    LOG(INFO) << "SETVIDEO - id: " << pTrack->id
+              << ", kind: " << pTrack->kind.c_str()
+              << ", label: " << pTrack->label.c_str()
+              << ", lang: " << pTrack->language.c_str();
+
+    blink::WebMediaPlayerClient::VideoTrackKind video_track_kind =
+        blink::WebMediaPlayerClient::kVideoTrackKindNone;
+
+    for (const auto& i : videoKinds) {
+      if (pTrack->kind.compare(i.kind_str_) == 0) {
+        video_track_kind = i.kind_enum_;
+        break;
+      }
+    }
+
+    LOG(INFO) << "video track kind type is: " << video_track_kind;
+    client_->AddVideoTrack(
+        blink::WebString::FromUTF8(pTrack->id), video_track_kind,
+        blink::WebString::FromUTF8(pTrack->label),
+        blink::WebString::FromUTF8(pTrack->language), pTrack->enabled);
+    delete (pTrack);
+  } else if (trackinfo.cmd == media::TRACKCMD::SETINBAND) {
+    media::InbandTextInfo* pInBand = (media::InbandTextInfo*)trackinfo.info;
+
+    LOG(INFO) << "AddTrackInfo SETINBAND-pInBand:" << pInBand;
+    LOG(INFO) << "AddTrackInfo SETINBAND-info:" << pInBand->info
+              << ", band_type: " << pInBand->band_type
+              << ", action: " << pInBand->action;
+
+    if (client_)
+      client_->OnInbandTextTrack(pInBand->info, pInBand->band_type,
+                                 pInBand->action);
+    delete (pInBand);
+  } else if (trackinfo.cmd == media::TRACKCMD::SETCUE) {
+    media::InbandCueInfo* pInbandCue = (media::InbandCueInfo*)trackinfo.info;
+
+    LOG(INFO) << "AddTrackInfo SETCUE-pInbandCue:" << pInbandCue;
+    LOG(INFO) << "AddTrackInfo SETCUE-info:" << pInbandCue->info
+              << ", id: " << pInbandCue->id
+              << ", band_type: " << pInbandCue->band_type
+              << ", stime: " << pInbandCue->stime
+              << ", etime: " << pInbandCue->etime;
+
+    if (client_)
+      client_->AddInbandCue(pInbandCue->info, pInbandCue->id,
+                            pInbandCue->band_type, pInbandCue->stime,
+                            pInbandCue->etime);
+
+    delete (pInbandCue);
+  }
+}
 #endif
 
 void WebMediaPlayerImpl::OnDurationChange() {
index 3340d55..e4b2115 100644 (file)
@@ -409,7 +409,13 @@ class PLATFORM_EXPORT WebMediaPlayerImpl
       media::BufferingStateChangeReason reason) override;
   void OnDurationChange() override;
 #if BUILDFLAG(IS_TIZEN_TV)
+  void NotifyTrackInfoToBrowser(int active_track_id) override;
   void SetParentalRatingResult(bool is_pass) override;
+  void AddTrackInfo(media::MediaTrackInfo trackinfo) override;
+  void SetActiveTextTrack(int id, bool is_in_band) override;
+  void SetActiveAudioTrack(int index) override;
+  void SetActiveVideoTrack(int index) override;
+  void SetPreferTextLanguage(const std::string& lang) override;
 #endif
   void OnWaiting(media::WaitingReason reason) override;
   void OnAudioConfigChange(const media::AudioDecoderConfig& config) override;
index c529cc3..31e383b 100644 (file)
     },
     {
       name: "AudioVideoTracks",
-      status: "experimental",
+      status: "stable",
       base_feature: "none",
     },
     {
index 209997e..02db385 100644 (file)
@@ -582,6 +582,10 @@ void WidgetBase::SetParentalRatingResult(const WTF::String& url, bool is_pass) {
 void WidgetBase::IsVideoPlaying(IsVideoPlayingCallback callback) {
   std::move(callback).Run(client_->IsVideoPlaying());
 }
+
+void WidgetBase::SetPreferSubtitleLang(const WTF::String& lang_list) {
+  client_->SetPreferSubtitleLang(lang_list);
+}
 #endif // IS_TIZEN_TV
 
 void WidgetBase::WasHidden() {
@@ -1154,6 +1158,17 @@ void WidgetBase::SetCursor(const ui::Cursor& cursor) {
 void WidgetBase::DidEdgeScrollBy(const gfx::Point& offset, bool handled) {
   widget_host_->DidEdgeScrollBy(offset, handled);
 }
+
+void WidgetBase::NotifyTrackInfoToBrowser(int active_track_id,
+                                          const std::string& url,
+                                          const std::string& lang) {
+  if (!widget_host_) {
+    LOG(ERROR) << "widget host is null ";
+    return;
+  }
+  widget_host_->NotifyTrackInfoToBrowser(
+      active_track_id, WTF::String::FromUTF8(url), WTF::String::FromUTF8(lang));
+}
 #endif
 
 void WidgetBase::UpdateTooltipUnderCursor(const String& tooltip_text,
index 0fd2e85..9f3e2b1 100644 (file)
@@ -173,6 +173,7 @@ class PLATFORM_EXPORT WidgetBase : public mojom::blink::Widget,
   void SetTranslatedURL(const WTF::String& url) override;
   void IsVideoPlaying(IsVideoPlayingCallback callback) override;
   void SetParentalRatingResult(const WTF::String& url, bool is_pass) override;
+  void SetPreferSubtitleLang(const WTF::String& lang_list) override;
 #endif
 
   void WasHidden() override;
@@ -263,6 +264,9 @@ class PLATFORM_EXPORT WidgetBase : public mojom::blink::Widget,
 #if BUILDFLAG(IS_TIZEN_TV)
   //Browser edge scroll
   void DidEdgeScrollBy(const gfx::Point& offset, bool handled);
+  void NotifyTrackInfoToBrowser(int active_track_id,
+                                const std::string& url,
+                                const std::string& lang);
 #endif
 
   void UpdateTooltipUnderCursor(const String& tooltip_text, TextDirection dir);
index 1486406..623a994 100644 (file)
@@ -208,6 +208,7 @@ class WidgetBaseClient {
   virtual bool IsVideoPlaying() {}
   virtual void SetTranslatedURL(const WTF::String& url) {}
   virtual void SetParentalRatingResult(const WTF::String& url, bool is_pass) {}
+  virtual void SetPreferSubtitleLang(const WTF::String lang_list) {}
 #endif
 
   // Convert screen coordinates to device emulated coordinates (scaled
index 46c28dc..835c40b 100644 (file)
@@ -371,6 +371,49 @@ void TizenRendererImpl::Suspend() {
 }
 
 #if BUILDFLAG(IS_TIZEN_TV)
+void TizenRendererImpl::SetActiveTextTrack(int id, bool is_in_band) {
+  LOG_ID(INFO, player_id_) << "(" << static_cast<void*>(this) << ") "
+                           << __func__ << " " << id << "/ " << is_in_band;
+
+  if (!media_player_) {
+    LOG_ID(ERROR, player_id_) << "media_player_ is not created yet";
+    return;
+  }
+  media_player_->SetActiveTextTrack(id, is_in_band);
+}
+
+void TizenRendererImpl::SetActiveAudioTrack(int index) {
+  LOG_ID(INFO, player_id_) << "(" << static_cast<void*>(this) << ") "
+                           << __func__ << " index:" << index;
+
+  if (!media_player_) {
+    LOG_ID(ERROR, player_id_) << "media_player_ is not created yet";
+    return;
+  }
+  media_player_->SetActiveAudioTrack(index);
+}
+
+void TizenRendererImpl::SetActiveVideoTrack(int index) {
+  LOG_ID(INFO, player_id_) << "(" << static_cast<void*>(this) << ") "
+                           << __func__ << " index:" << index;
+
+  if (!media_player_) {
+    LOG_ID(ERROR, player_id_) << "media_player_ is not created yet";
+    return;
+  }
+  media_player_->SetActiveVideoTrack(index);
+}
+
+void TizenRendererImpl::SetPreferTextLanguage(const std::string& lang) {
+  LOG_ID(INFO, player_id_) << "(" << static_cast<void*>(this) << ") "
+                           << __func__ << " " << lang;
+
+  if (!media_player_) {
+    LOG_ID(ERROR, player_id_) << "media_player_ is not created yet";
+    return;
+  }
+  media_player_->SetPreferTextLanguage(lang);
+}
 content::WebContentsDelegate* TizenRendererImpl::GetWebContentsDelegate()
     const {
   content::WebContents* web_contents = GetWebContents();
@@ -484,6 +527,30 @@ void TizenRendererImpl::OnStatisticsUpdate(
   NOTIMPLEMENTED();
 }
 #if BUILDFLAG(IS_TIZEN_TV)
+void TizenRendererImpl::NotifyTrackInfoToBrowser(int active_track_id) {
+  LOG_ID(INFO, player_id_)
+      << "TizenRendererImpl::NotifyTrackInfoToBrowser active_track_id "
+      << active_track_id;
+  client_extension_->NotifyTrackInfoToBrowser(active_track_id);
+}
+
+void TizenRendererImpl::AddTrackInfo(
+    media::mojom::MediaTrackInfoPtr trackinfo) {
+  client_extension_->AddTrackInfo(std::move(trackinfo));
+}
+
+void TizenRendererImpl::UpdateCurrentTime(base::TimeDelta current_time) {
+  content::WebContentsDelegate* web_contents_delegate =
+      GetWebContentsDelegate();
+
+  if (!web_contents_delegate) {
+    LOG_ID(ERROR, player_id_) << "GetWebContentsDelegate is nullprt";
+    return;
+  }
+
+  web_contents_delegate->UpdateCurrentTime(current_time.InSecondsF());
+}
+
 void TizenRendererImpl::SetContentMimeType(const std::string& mime_type) {
   mime_type_ = mime_type;
   if (media_player_)
@@ -510,6 +577,19 @@ bool TizenRendererImpl::PlaybackNotificationEnabled() {
   return enable;
 }
 
+bool TizenRendererImpl::SubtitleNotificationEnabled() {
+  content::WebContents* web_contents = GetWebContents();
+  if (!web_contents) {
+    LOG_ID(ERROR, player_id_) << "web_contents is nullptr";
+    return false;
+  }
+  blink::web_pref::WebPreferences web_preference =
+      web_contents->GetOrCreateWebPreferences();
+  bool enable = web_preference.media_subtitle_notification_enabled;
+  LOG_ID(INFO, player_id_) << "media_subtitle_notification_enabled:" << enable;
+  return enable;
+}
+
 void TizenRendererImpl::NotifyPlaybackState(int state,
                                             int player_id,
                                             const std::string& url,
index 5e50009..bf9f6ad 100644 (file)
@@ -23,6 +23,7 @@
 #include "mojo/public/cpp/bindings/receiver.h"
 #include "mojo/public/cpp/bindings/remote.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
+#include "third_party/blink/public/platform/web_media_player.h"
 #include "tizen_src/chromium_impl/media/filters/media_player_tizen_client.h"
 #include "ui/gfx/geometry/size.h"
 
@@ -116,7 +117,10 @@ class CONTENT_EXPORT TizenRendererImpl
   void OnBufferUpdate(base::TimeDelta time) override;
 
 #if BUILDFLAG(IS_TIZEN_TV)
+  void NotifyTrackInfoToBrowser(int active_track_id) override;
+  void AddTrackInfo(media::mojom::MediaTrackInfoPtr trackinfo) override;
   bool PlaybackNotificationEnabled();
+  bool SubtitleNotificationEnabled() override;
   void NotifyPlaybackState(int state,
                            int player_id = 0,
                            const std::string& url = "",
@@ -124,6 +128,7 @@ class CONTENT_EXPORT TizenRendererImpl
                            bool* media_resource_acquired = NULL,
                            std::string* translated_url = NULL,
                            std::string* drm_info = NULL) override;
+  void UpdateCurrentTime(base::TimeDelta current_time) override;
   void OnLivePlaybackComplete() override;
 #endif
 
@@ -178,6 +183,12 @@ class CONTENT_EXPORT TizenRendererImpl
   void SetPlayerMediaGeometry();
   void OnWebViewMoved();
 #endif
+#if BUILDFLAG(IS_TIZEN_TV)
+  void SetActiveTextTrack(int id, bool is_in_band) override;
+  void SetActiveAudioTrack(int index) override;
+  void SetActiveVideoTrack(int index) override;
+  void SetPreferTextLanguage(const std::string& lang) override;
+#endif
   content::WebContents* GetWebContents() const;
 
   media::RendererClient* client_ = nullptr;
index ca2b174..caac65a 100644 (file)
@@ -484,11 +484,32 @@ void RWHVAuraCommonHelperEfl::SetPopupMenuBounds(
   NOTIMPLEMENTED();
 }
 
+void RWHVAuraCommonHelperEfl::NotifyTrackInfoToBrowser(
+    int active_track_id,
+    const std::string& url,
+    const std::string& lang) {
+  LOG(INFO) << __FUNCTION__ << " url " << url << " lang:" << lang;
+  if (!web_contents_ || !web_contents_->GetDelegate()) {
+    LOG(ERROR) << "content or delegate is null";
+    return;
+  }
+
+  web_contents_->GetDelegate()->NotifySubtitlePlay(active_track_id, url, lang);
+}
+
 void RWHVAuraCommonHelperEfl::SetTranslatedURL(const std::string& url) {
   if (rwhv_aura_)
     rwhv_aura_->host()->SetTranslatedURL(url);
 }
 
+void RWHVAuraCommonHelperEfl::SetPreferSubtitleLang(std::string lang_list) {
+  if (!rwhv_aura_) {
+    LOG(ERROR) << "rwhv_aura_ is null";
+    return;
+  }
+  rwhv_aura_->host()->SetPreferSubtitleLang(lang_list);
+}
+
 void RWHVAuraCommonHelperEfl::SetIMERecommendedWords(
     const std::string& recommended_words) {
   auto im_context = GetIMContextEfl();
index a216b09..f2a5da0 100644 (file)
@@ -140,6 +140,11 @@ class CONTENT_EXPORT RWHVAuraCommonHelperEfl {
   void SetPopupMenuVisible(const bool visible);
   void SetPopupMenuBounds(const gfx::Rect& popup_bounds);
   void SetCursorByClient(bool enable) { cursor_set_by_client_ = enable; }
+  // notify track info to browser process
+  void NotifyTrackInfoToBrowser(int active_track_id,
+                                const std::string& url,
+                                const std::string& lang);
+  void SetPreferSubtitleLang(std::string lang_list);
   void SetIMERecommendedWords(const std::string& recommended_words);
   void SetIMERecommendedWordsType(bool should_enable);
   void SetMouseEventsEnabled(bool enabled);
index 988f07a..caf7284 100644 (file)
@@ -80,6 +80,75 @@ void MediaPlayerRendererClient::SetMediaGeometry(const gfx::RectF& rect) {
 }
 #endif
 
+#if BUILDFLAG(IS_TIZEN_TV)
+void MediaPlayerRendererClient::NotifyTrackInfoToBrowser(int active_track_id) {
+  DCHECK(media_task_runner_->RunsTasksInCurrentSequence());
+  client_->NotifyTrackInfoToBrowser(active_track_id);
+}
+
+void MediaPlayerRendererClient::AddTrackInfo(
+    media::mojom::MediaTrackInfoPtr trackinfo) {
+  DCHECK(media_task_runner_->RunsTasksInCurrentSequence());
+  media::MediaTrackInfo sMediatrackInfo;
+
+  LOG(INFO) << "trackinfo->cmd " << (int)trackinfo->cmd;
+  sMediatrackInfo.cmd = (media::TRACKCMD)trackinfo->cmd;
+
+  if ((trackinfo->cmd == media::mojom::TRACKCMD::SETTEXT ||
+       trackinfo->cmd == media::mojom::TRACKCMD::SETAUDIO ||
+       trackinfo->cmd == media::mojom::TRACKCMD::SETVIDEO) &&
+      trackinfo->ck->is_track()) {
+    LOG(INFO) << "AddTrackInfo SETTEXT kind:"
+              << trackinfo->ck->get_track()->kind << " label "
+              << trackinfo->ck->get_track()->label << " language "
+              << trackinfo->ck->get_track()->language << " id "
+              << trackinfo->ck->get_track()->id << " enabled "
+              << trackinfo->ck->get_track()->enabled;
+
+    media::TrackInfo* ptinfo = new (media::TrackInfo);
+    ptinfo->id = trackinfo->ck->get_track()->id;
+    ptinfo->kind = trackinfo->ck->get_track()->kind;
+    ptinfo->label = trackinfo->ck->get_track()->label;
+    ptinfo->language = trackinfo->ck->get_track()->language;
+    ptinfo->enabled = trackinfo->ck->get_track()->enabled;
+    LOG(INFO) << "AddTrackInfo SETTEXT-ptinfo:" << ptinfo;
+    sMediatrackInfo.info = std::move((void*)ptinfo);
+
+  } else if (trackinfo->cmd == media::mojom::TRACKCMD::SETINBAND &&
+             trackinfo->ck->is_inband()) {
+    LOG(INFO) << "SETINBAND - info: " << trackinfo->ck->get_inband()->info
+              << ", band_type: " << trackinfo->ck->get_inband()->band_type
+              << ", action: " << trackinfo->ck->get_inband()->action;
+
+    media::InbandTextInfo* pinband = new (media::InbandTextInfo);
+    pinband->info = trackinfo->ck->get_inband()->info;
+    pinband->band_type = trackinfo->ck->get_inband()->band_type;
+    pinband->action = trackinfo->ck->get_inband()->action;
+    LOG(INFO) << "AddTrackInfo SETCUE-pinband:" << pinband;
+    sMediatrackInfo.info = std::move((void*)pinband);
+  } else if (trackinfo->cmd == media::mojom::TRACKCMD::SETCUE &&
+             trackinfo->ck->is_cue()) {
+    LOG(INFO) << "AddTrackInfo SETCUE - info: "
+              << trackinfo->ck->get_cue()->info
+              << ", id: " << trackinfo->ck->get_cue()->id
+              << ", band_type: " << trackinfo->ck->get_cue()->band_type
+              << ", stime: " << trackinfo->ck->get_cue()->stime
+              << ", etime: " << trackinfo->ck->get_cue()->etime;
+
+    media::InbandCueInfo* pinbandcue = new (media::InbandCueInfo);
+    pinbandcue->info = trackinfo->ck->get_cue()->info;
+    pinbandcue->id = trackinfo->ck->get_cue()->id;
+    pinbandcue->band_type = trackinfo->ck->get_cue()->band_type;
+    pinbandcue->stime = trackinfo->ck->get_cue()->stime;
+    pinbandcue->etime = trackinfo->ck->get_cue()->etime;
+    LOG(INFO) << "AddTrackInfo SETCUE-inbandcue:" << pinbandcue;
+    sMediatrackInfo.info = std::move((void*)pinbandcue);
+  }
+  LOG(INFO) << "AddTrackInfo SETCUE-info:" << sMediatrackInfo.info;
+  client_->AddTrackInfo(std::move(sMediatrackInfo));
+}
+#endif
+
 void MediaPlayerRendererClient::OnRemoteRendererInitialized(
     media::PipelineStatus status) {
   DCHECK(media_task_runner_->RunsTasksInCurrentSequence());
index 85fc655..5109bf4 100644 (file)
@@ -72,6 +72,10 @@ class CONTENT_EXPORT MediaPlayerRendererClient
 
   // media::mojom::MediaPlayerRendererClientExtension implementation
   void OnDurationChange(base::TimeDelta duration) override;
+#if BUILDFLAG(IS_TIZEN_TV)
+  void NotifyTrackInfoToBrowser(int active_track_id) override;
+  void AddTrackInfo(media::mojom::MediaTrackInfoPtr trackinfo) override;
+#endif
   void OnVideoSizeChange(const gfx::Size& size) override;
   void OnBufferUpdate(base::TimeDelta time) override;
   void OnNewFrameAvailable(uint32_t playerId,
index 60f291f..9724b9d 100644 (file)
 
 #include <device/power.h>
 #include <player.h>
+#include <map>
 
 namespace media {
+// key: alpha3     value: alpha2
+std::map<std::string, std::string> language_code_ = {
+    // ISO639-2/B  ISO639-1
+    {"aar", "aa"},
+    {"abk", "ab"},
+    {"afr", "af"},
+    {"aka", "ak"},
+    {"alb", "sq"},
+    {"amh", "am"},
+    {"ara", "ar"},
+    {"arg", "an"},
+    {"arm", "hy"},
+    {"asm", "as"},
+    {"ava", "av"},
+    {"ave", "ae"},
+    {"aym", "ay"},
+    {"aze", "az"},
+    {"bak", "ba"},
+    {"bam", "bm"},
+    {"bel", "be"},
+    {"ben", "bn"},
+    {"baq", "eu"},
+    {"bih", "bh"},
+    {"bis", "bi"},
+    {"bos", "bs"},
+    {"bre", "br"},
+    {"bul", "bg"},
+    {"bur", "my"},
+    {"cat", "ca"},
+    {"cze", "cs"},
+    {"cha", "ch"},
+    {"che", "ce"},
+    {"chi", "zh"},
+    {"chu", "cu"},
+    {"chv", "cv"},
+    {"cym", "cy"},
+    {"cor", "kw"},
+    {"cos", "co"},
+    {"cre", "cr"},
+    {"dan", "da"},
+    {"div", "dv"},
+    {"dut", "nl"},
+    {"dzo", "dz"},
+    {"eng", "en"},
+    {"epo", "eo"},
+    {"est", "et"},
+    {"ewe", "ee"},
+    {"fao", "fo"},
+    {"fij", "fj"},
+    {"fin", "fi"},
+    {"fre", "fr"},
+    {"fry", "fy"},
+    {"ful", "ff"},
+    {"gre", "el"},
+    {"ger", "de"},
+    {"geo", "ka"},
+    {"gla", "gd"},
+    {"gle", "ga"},
+    {"glg", "gl"},
+    {"glv", "gv"},
+    {"grn", "gn"},
+    {"guj", "gu"},
+    {"hat", "ht"},
+    {"hau", "ha"},
+    {"heb", "he"},
+    {"her", "hz"},
+    {"hin", "hi"},
+    {"hmo", "ho"},
+    {"hrv", "hr"},
+    {"hun", "hu"},
+    {"ibo", "ig"},
+    {"ice", "is"},
+    {"ido", "io"},
+    {"iii", "ii"},
+    {"iku", "iu"},
+    {"ile", "ie"},
+    {"ina", "ia"},
+    {"ind", "id"},
+    {"ipk", "ik"},
+    {"ita", "it"},
+    {"jav", "jv"},
+    {"jpn", "ja"},
+    {"kal", "kl"},
+    {"kan", "kn"},
+    {"kas", "ks"},
+    {"kau", "kr"},
+    {"kaz", "kk"},
+    {"khm", "km"},
+    {"kik", "ki"},
+    {"kin", "rw"},
+    {"kir", "ky"},
+    {"kom", "kv"},
+    {"kon", "kg"},
+    {"kor", "ko"},
+    {"kua", "kj"},
+    {"kur", "ku"},
+    {"lao", "lo"},
+    {"lat", "la"},
+    {"lav", "lv"},
+    {"lim", "li"},
+    {"lin", "ln"},
+    {"lit", "lt"},
+    {"ltz", "lb"},
+    {"lub", "lu"},
+    {"lug", "lg"},
+    {"mac", "mk"},
+    {"mah", "mh"},
+    {"mal", "ml"},
+    {"mao", "mi"},
+    {"mar", "mr"},
+    {"may", "ms"},
+    {"mlg", "mg"},
+    {"mlt", "mt"},
+    {"mon", "mn"},
+    {"nau", "na"},
+    {"nav", "nv"},
+    {"nbl", "nr"},
+    {"nde", "nd"},
+    {"ndo", "ng"},
+    {"nep", "ne"},
+    {"nno", "nn"},
+    {"nob", "nb"},
+    {"nor", "no"},
+    {"nya", "ny"},
+    {"oci", "oc"},
+    {"oji", "oj"},
+    {"ori", "or"},
+    {"orm", "om"},
+    {"oss", "os"},
+    {"pan", "pa"},
+    {"pli", "pi"},
+    {"pol", "pl"},
+    {"por", "pt"},
+    {"pus", "ps"},
+    {"per", "fa"},
+    {"que", "qu"},
+    {"roh", "rm"},
+    {"rum", "ro"},
+    {"run", "rn"},
+    {"rus", "ru"},
+    {"sag", "sg"},
+    {"san", "sa"},
+    {"sin", "si"},
+    {"slo", "sk"},
+    {"slv", "sl"},
+    {"sme", "se"},
+    {"smo", "sm"},
+    {"sna", "sn"},
+    {"snd", "sd"},
+    {"som", "so"},
+    {"sot", "st"},
+    {"spa", "es"},
+    {"srd", "sc"},
+    {"srp", "sr"},
+    {"ssw", "ss"},
+    {"sun", "su"},
+    {"swa", "sw"},
+    {"swe", "sv"},
+    {"tah", "ty"},
+    {"tam", "ta"},
+    {"tat", "tt"},
+    {"tel", "te"},
+    {"tgk", "tg"},
+    {"tgl", "tl"},
+    {"tha", "th"},
+    {"tib", "bo"},
+    {"tir", "ti"},
+    {"ton", "to"},
+    {"tsn", "tn"},
+    {"tso", "ts"},
+    {"tuk", "tk"},
+    {"tur", "tr"},
+    {"twi", "tw"},
+    {"uig", "ug"},
+    {"ukr", "uk"},
+    {"urd", "ur"},
+    {"uzb", "uz"},
+    {"ven", "ve"},
+    {"vie", "vi"},
+    {"vol", "vo"},
+    {"wel", "cy"},
+    {"wln", "wa"},
+    {"wol", "wo"},
+    {"xho", "xh"},
+    {"yid", "yi"},
+    {"yor", "yo"},
+    {"zha", "za"},
+    {"zul", "zu"},
+    // ISO639-2/T  ISO639-1
+    {"sqi", "sq"},
+    {"hye", "hy"},
+    {"eus", "eu"},
+    {"mya", "my"},
+    {"zho", "zh"},
+    {"ces", "cs"},
+    {"nld", "nl"},
+    {"fra", "fr"},
+    {"kat", "ka"},
+    {"deu", "de"},
+    {"deu", "de"},
+    {"ell", "el"},
+    {"isl", "is"},
+    {"mkd", "mk"},
+    {"msa", "ms"},
+    {"mri", "mi"},
+    {"fas", "fa"},
+    {"ron", "ro"},
+    {"slk", "sk"},
+    {"bod", "bo"},
+    {"cym", "cy"},
+};
+
+const std::string GetAlpha2(const std::string& alpha3) {
+  if (alpha3 == "")
+    return "";
+  auto iter = language_code_.find(alpha3);
+  if (iter == language_code_.end()) {
+    LOG(ERROR) << "can't find alpha2 for lang:" << alpha3.c_str();
+    return "";
+  }
+  std::string alpha2 = iter->second;
+  LOG(INFO) << "alpha3:" << alpha3.c_str() << ",alpha2:" << alpha2.c_str();
+  return alpha2;
+}
 
 std::string GetErrorString(int player_error) {
   switch (player_error) {
index 00cd6dd..50da37f 100644 (file)
@@ -45,6 +45,7 @@ enum MediaError {
   MEDIA_ERROR_NETWORK, // Network error.
 };
 
+const std::string GetAlpha2(const std::string& alpha3);
 std::string GetErrorString(int capi_player_error);
 MediaError GetMediaError(int capi_player_error);
 
index 5d5025c..c5a748b 100644 (file)
@@ -88,7 +88,7 @@ class MEDIA_EXPORT MediaPlayerBridgeCapi : public MediaPlayerTizen {
   void SetMediaPlayerClient(MediaPlayerTizenClient* client) override {
     client_ = client;
   }
-  void SetParentalRatingResult(bool is_pass) override{};
+  void SetParentalRatingResult(bool is_pass) override {}
 
 #if defined(TIZEN_VIDEO_HOLE)
   void SetVideoHole(bool is_video_hole) override;
@@ -105,7 +105,6 @@ class MEDIA_EXPORT MediaPlayerBridgeCapi : public MediaPlayerTizen {
   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);
 
   void OnDurationChange(int player_id, double duration);
@@ -143,9 +142,17 @@ class MEDIA_EXPORT MediaPlayerBridgeCapi : public MediaPlayerTizen {
   bool SetPlayerPrepareAsync();
   virtual void PlayerPrepared();
   virtual void PlaybackCompleteUpdate();
-  virtual bool PreloadIfNeeded(int& ret) { return false; };
+  virtual bool PreloadIfNeeded(int& ret) { return false; }
   virtual void UpdateMediaType();
   virtual void UpdateDuration();
+  virtual void OnCurrentTimeUpdateTimerFired();
+  virtual void SeekCompleteUpdate();
+  virtual void OnResumeComplete(bool success);
+  virtual void HandleBufferingStatus(int percent);
+
+  void SeekInternal(base::TimeDelta time);
+  void StartBufferingUpdateTimer();
+  void StopCurrentTimeUpdateTimer();
 
   GURL url_;
   bool is_live_stream_{false};
@@ -159,46 +166,38 @@ class MEDIA_EXPORT MediaPlayerBridgeCapi : public MediaPlayerTizen {
   int width_{0};
   int height_{0};
 
+  base::TimeDelta playback_time_{base::TimeDelta()};
   base::TimeDelta duration_{base::TimeDelta()};
+  base::OnceClosure seek_cb_;
+  bool is_file_url_{false};
+  bool is_paused_{true};
+  bool is_seeking_{false};
   bool is_preparing_{false};
   bool is_play_pending_{false};
   bool suspended_{false};
 
  private:
   // |duration_update_timer_| related
-  void OnCurrentTimeUpdateTimerFired();
   void StartCurrentTimeUpdateTimer();
-  void StopCurrentTimeUpdateTimer();
 
   // |buffering_update_timer_| related
   void OnBufferingUpdateTimerFired();
-  void StartBufferingUpdateTimer();
   void StopBufferingUpdateTimer();
 
   void OnTimeChanged();
   void UpdateSeekState(bool state);
 
-  void SeekCompleteUpdate();
-  void HandleBufferingStatus(int percent);
-
-  void SeekInternal(base::TimeDelta time);
-
   MediaPlayerTizenClient* client_ = nullptr;
 
   bool is_end_reached_{false};
-  bool is_file_url_{false};
-  bool is_paused_{false};
-  bool is_seeking_{false};
   bool is_set_playback_rate_delayed_{false};
 
   double playback_rate_{1.0};
   double volume_{0.0};
 
-  base::OnceClosure seek_cb_;
   base::RepeatingTimer current_time_update_timer_;
   base::RepeatingTimer buffering_update_timer_;
   std::string user_agent_;
-  base::TimeDelta playback_time_{base::TimeDelta()};
   base::TimeDelta seek_duration_{base::TimeDelta()};
 
 #if defined(TIZEN_VIDEO_HOLE)
index 8e7420a..44e3845 100644 (file)
@@ -6,14 +6,35 @@
 
 #include "base/strings/string_split.h"
 #include "media/base/efl/media_player_util_efl.h"
+#include "third_party/blink/public/common/web_preferences/web_preferences.h"
+#include "third_party/blink/public/platform/web_media_player.h"
 #include "tizen_src/chromium_impl/media/filters/media_player_tizen_client.h"
 
 #include <jsoncpp/json/json.h>
+#include <vconf/vconf.h>
 
 namespace {
 const int kSeekableTimeUpdateInterval = 500;
 }
 
+static void OnSubtitleDataCallback(unsigned long long time_stamp,
+                                   unsigned index,
+                                   void* buffer,
+                                   void* user_data) {
+  DCHECK(user_data);
+  media::MediaPlayerBridgeCapiTV* player =
+      static_cast<media::MediaPlayerBridgeCapiTV*>(user_data);
+  if (buffer) {
+    const std::string info{static_cast<char*>(buffer)};
+    LOG(INFO) << " onSubtitleDataCallback : index=" << index
+              << ",time stamp=" << time_stamp << ",bufferSize=" << info.size();
+
+    constexpr size_t null_terminator_size = 1;
+    player->SubtitleDataCB(time_stamp, index, info,
+                           info.size() + null_terminator_size);
+  }
+}
+
 static void PlayerPreLoadingCb(void* data) {
   if (!data) {
     LOG(ERROR) << "input data is null";
@@ -32,6 +53,36 @@ static void DrmErrorCb(int err_code, char* err_str, void* data) {
   player->OnDrmError(err_code, err_str);
 }
 
+static void OtherEventCb(int event_type, void* event_data, void* data) {
+  DCHECK(data);
+  media::MediaPlayerBridgeCapiTV* player =
+      static_cast<media::MediaPlayerBridgeCapiTV*>(data);
+  player->OnOtherEvent(event_type, event_data);
+}
+
+#if TIZEN_VERSION_AT_LEAST(6, 0, 0)
+static void FirstTimeStampCb(unsigned long long timestamp,
+                             int time_base_num,
+                             int time_base_den,
+                             void* user_data) {
+  DCHECK(user_data);
+  media::MediaPlayerBridgeCapiTV* player =
+      static_cast<media::MediaPlayerBridgeCapiTV*>(user_data);
+  player->OnFirstTimeStamp(timestamp, time_base_num, time_base_den);
+}
+
+static void TSSubtitleDataCb(int pid,
+                             unsigned char* data,
+                             unsigned int len,
+                             void* user_data) {
+  DCHECK(user_data);
+  media::MediaPlayerBridgeCapiTV* player =
+      static_cast<media::MediaPlayerBridgeCapiTV*>(user_data);
+  if (data) {
+    player->OnTSSubtitleData(pid, data, len);
+  }
+}
+#endif
 namespace media {
 
 MediaPlayerBridgeCapiTV::MediaPlayerBridgeCapiTV(const GURL& url,
@@ -79,14 +130,19 @@ void MediaPlayerBridgeCapiTV::Prepare() {
   if (GetMediaPlayerClient() &&
       GetMediaPlayerClient()->PlaybackNotificationEnabled() &&
       blink::IsHbbTV()) {
+#if !defined(TIZEN_MULTIMEDIA_DRMMANAGER_SUPPORT)
     if (!SetDrmInfo(drm_info)) {
       LOG_ID(ERROR, GetPlayerId()) << "SetDrmInfo failed";
       return;
     }
+#endif
     if (!translated_url.empty())
       url_ = media::GetCleanURL(translated_url);
   }
 
+  if (blink::IsHbbTV()) {
+    GetUserPreferAudioLanguage();
+  }
   if (url_.spec().find(".mpd") != std::string::npos)
     stream_type_ = DASH_STREAM;
   else if (url_.spec().find(".m3u") != std::string::npos)
@@ -99,6 +155,24 @@ void MediaPlayerBridgeCapiTV::Prepare() {
     stream_type_ = DASH_STREAM;
   }
 
+  if (blink::IsHbbTV() && !is_preloaded_) {
+    int ret = player_set_others_event_cb(player_, OtherEventCb, this);
+    if (ret != PLAYER_ERROR_NONE)
+      LOG(ERROR) << "player_set_others_event_cb() failed";
+#if TIZEN_VERSION_AT_LEAST(6, 0, 0)
+    if (stream_type_ == TS_STREAM) {
+      if (prefer_subtitle_lang_ == "") {
+        prefer_subtitle_lang_ = "und";
+        player_set_ini_param(player_, "set_subtitle_language = und");
+      }
+      if (prefer_subtitle_lang_ != "off") {
+        //-999 means invalid pes id, MM will decide use which pes id
+        player_set_pes_cb(player_, -999, TSSubtitleDataCb, this);
+        player_set_first_timestamp_callback(player_, FirstTimeStampCb, this);
+      }
+    }
+#endif
+  }
   if (blink::IsHbbTV() && CheckHighBitRate() && stream_type_ == DASH_STREAM)
     AppendUrlHighBitRate(url_.spec());
   player_prepared_ = false;
@@ -116,6 +190,16 @@ void MediaPlayerBridgeCapiTV::Release() {
   MediaPlayerBridgeCapi::Release();
   if (GetMediaPlayerClient())
     GetMediaPlayerClient()->NotifyPlaybackState(kPlaybackStop, player_id_);
+  NotifySubtitleState(blink::WebMediaPlayer::kSubtitleStop);
+  pending_active_text_track_id_ = active_text_track_id_;
+  pending_active_audio_track_id_ = active_audio_track_id_;
+  pending_active_video_track_id_ = active_video_track_id_;
+  active_audio_track_id_ = -1;
+  active_video_track_id_ = -1;
+  active_text_track_id_ = -1;
+#if TIZEN_VERSION_AT_LEAST(6, 0, 0)
+  player_unset_pes_cb(player_, -999);
+#endif
 }
 
 bool MediaPlayerBridgeCapiTV::Play() {
@@ -141,8 +225,40 @@ bool MediaPlayerBridgeCapiTV::Play() {
 
   if (!MediaPlayerBridgeCapi::Play())
     return false;
+  if (blink::IsHbbTV()) {
+    UpdatePreferAudio();
+  }
+
+  LOG_ID(INFO, player_id_) << "pending_active_text_track_id_:"
+                           << pending_active_text_track_id_
+                           << " active_text_track_id_ " << active_text_track_id_
+                           << " pending_active_audio_track_id_ "
+                           << pending_active_audio_track_id_
+                           << " active_audio_track_id_ "
+                           << active_audio_track_id_
+                           << " pending_active_video_track_id_ "
+                           << pending_active_video_track_id_
+                           << " active_video_track_id_ "
+                           << active_video_track_id_;
+
+  if (pending_active_text_track_id_ != -1 && active_text_track_id_ == -1) {
+    active_text_track_id_ = pending_active_text_track_id_;
+    pending_active_text_track_id_ = -1;
+  }
+
+  if (pending_active_audio_track_id_ != -1 && active_audio_track_id_ == -1) {
+    SetActiveAudioTrack(pending_active_audio_track_id_);
+    pending_active_audio_track_id_ = -1;
+  }
+
+  if (pending_active_video_track_id_ != -1 && active_video_track_id_ == -1) {
+    SetActiveVideoTrack(pending_active_video_track_id_);
+    pending_active_video_track_id_ = -1;
+  }
+
   if (GetMediaPlayerClient())
     GetMediaPlayerClient()->NotifyPlaybackState(kPlaybackStart, player_id_);
+  NotifySubtitleState(blink::WebMediaPlayer::kSubtitlePlay);
   return true;
 }
 
@@ -155,17 +271,241 @@ void MediaPlayerBridgeCapiTV::Pause(bool is_media_related_action) {
     return;
   }
   MediaPlayerBridgeCapi::Pause(is_media_related_action);
+  NotifySubtitleState(blink::WebMediaPlayer::kSubtitlePause);
 }
 
 void MediaPlayerBridgeCapiTV::PlaybackCompleteUpdate() {
   MediaPlayerBridgeCapi::PlaybackCompleteUpdate();
   if (GetMediaPlayerClient()) {
     GetMediaPlayerClient()->NotifyPlaybackState(kPlaybackFinish, player_id_);
+    GetMediaPlayerClient()->UpdateCurrentTime(
+        MediaPlayerBridgeCapi::GetCurrentTime());
     if (is_live_stream_)
       GetMediaPlayerClient()->OnLivePlaybackComplete();
   }
+
+  NotifySubtitleState(blink::WebMediaPlayer::kSubtitleStop);
 }  // namespace media
 
+void MediaPlayerBridgeCapiTV::Seek(base::TimeDelta time,
+                                   base::OnceClosure seek_cb) {
+  LOG_ID(INFO, player_id_) << "(" << static_cast<void*>(this) << ") "
+                           << __func__ << " time: " << time.InSecondsF();
+
+  seek_cb_ = std::move(seek_cb);
+  if (IsPlayerSuspended() && playback_time_ != time) {
+    playback_time_ = time;
+    delayed_player_state_ = PLAYER_STATE_DELAYED_SEEK;
+    pending_seek_duration_ = playback_time_;
+    OnTimeUpdate(player_id_, playback_time_);
+    OnTimeChanged(player_id_);
+    Resume();
+    return;
+  }
+
+  MediaPlayerBridgeCapi::SeekInternal(time);
+  NotifySubtitleState(blink::WebMediaPlayer::kSubtitleSeekStart,
+                      time.InSecondsF());
+}
+
+void MediaPlayerBridgeCapiTV::SubtitleDataCB(long long time_stamp,
+                                             unsigned index,
+                                             const std::string& buffer,
+                                             unsigned buffer_size) {
+  task_runner_->PostTask(
+      FROM_HERE, base::BindOnce(&MediaPlayerBridgeCapiTV::NotifySubtitleData,
+                                weak_factory_.GetWeakPtr(), index, time_stamp,
+                                buffer, buffer_size));
+}
+
+void MediaPlayerBridgeCapiTV::NotifySubtitlePlay(int id,
+                                                 const std::string& url,
+                                                 const std::string& lang) {
+  if (!GetMediaPlayerClient()) {
+    LOG(ERROR) << "MediaPlayerClient is null";
+    return;
+  }
+  content::WebContentsDelegate* web_contents_delegate =
+      GetMediaPlayerClient()->GetWebContentsDelegate();
+  if (!web_contents_delegate)
+    return;
+
+  web_contents_delegate->NotifySubtitlePlay(id, url, lang);
+}
+
+void MediaPlayerBridgeCapiTV::NotifySubtitleData(int track_id,
+                                                 double time_stamp,
+                                                 const std::string& data,
+                                                 unsigned int size) {
+  content::WebContentsDelegate* web_contents_delegate =
+      GetMediaPlayerClient()->GetWebContentsDelegate();
+
+  if (!web_contents_delegate) {
+    LOG(ERROR) << "web_contents_delegate is null";
+    return;
+  }
+
+  web_contents_delegate->NotifySubtitleData(track_id, time_stamp, data, size);
+}
+
+void MediaPlayerBridgeCapiTV::NotifySubtitleState(int new_state,
+                                                  double time_stamp) {
+  if (!blink::IsHbbTV() || !GetMediaPlayerClient() ||
+      !GetMediaPlayerClient()->SubtitleNotificationEnabled() ||
+      subtitle_state_ == new_state) {
+    LOG(ERROR)
+        << " MediaPlayerBridgeCapiTV::NotifySubtitleState null condition  ";
+    return;
+  }
+
+  content::WebContentsDelegate* web_contents_delegate =
+      GetMediaPlayerClient()->GetWebContentsDelegate();
+  if (!web_contents_delegate) {
+    LOG(ERROR) << "web_contents_delegate is null";
+    return;
+  }
+
+  // Workaround. Use subtitle state machine only when player has
+  // activated a text_track. Right now, subtitle state machine
+  // is shared between players, so any Player A notification
+  // influences Player B notification, which causes issues.
+  // This workaround won't work when two players have activated a text_track.
+  if (active_text_track_id_ == -1) {
+    LOG(ERROR) << "active_text_track_id_==-1";
+    return;
+  }
+
+  int old_state = subtitle_state_;
+  if (new_state != blink::WebMediaPlayer::kSubtitleSeekStart &&
+      new_state != blink::WebMediaPlayer::kSubtitleSeekComplete)
+    subtitle_state_ = new_state;
+
+  LOG(INFO) << "subtitle state transision:"
+            << "new_state=" << new_state << ", old_state=" << old_state
+            << ", subtitle_state=" << subtitle_state_
+            << ", time_stamp=" << time_stamp;
+
+  switch (new_state) {
+    case blink::WebMediaPlayer::kSubtitlePlay:
+      if (old_state == blink::WebMediaPlayer::kSubtitlePause)
+        web_contents_delegate->NotifySubtitleState(
+            blink::WebMediaPlayer::kSubtitleResume);
+      else
+        NotifyPlayTrack();
+      break;
+    case blink::WebMediaPlayer::kSubtitlePause:
+      if (old_state != blink::WebMediaPlayer::kSubtitleStop)
+        web_contents_delegate->NotifySubtitleState(new_state);
+      break;
+    case blink::WebMediaPlayer::kSubtitleStop:
+      NotifyStopTrack();
+      break;
+    case blink::WebMediaPlayer::kSubtitleSeekStart:
+      web_contents_delegate->NotifySubtitleState(new_state, time_stamp);
+      break;
+    case blink::WebMediaPlayer::kSubtitleSeekComplete:
+      web_contents_delegate->NotifySubtitleState(new_state);
+      break;
+    default:
+      NOTREACHED();
+      return;
+  }
+}
+
+void MediaPlayerBridgeCapiTV::NotifyPlayTrack() {
+  if (active_text_track_id_ == -1 ||
+      subtitle_state_ == blink::WebMediaPlayer::kSubtitleStop)
+    return;
+  if (is_inband_text_track_) {
+    // process select player's track ...
+    UpdateActiveTextTrack(active_text_track_id_);
+    NotifySubtitlePlay(active_text_track_id_, blink::WebString().Utf8(),
+                       blink::WebString().Utf8());
+  } else {
+    // get outband track info and then NotifyPlayTrack
+    LOG_ID(INFO, player_id_) << __func__;
+
+    if (GetMediaPlayerClient())
+      GetMediaPlayerClient()->NotifyTrackInfoToBrowser(active_text_track_id_);
+  }
+}
+
+void MediaPlayerBridgeCapiTV::NotifyStopTrack() {
+  active_text_track_id_ = -1;
+  if (is_inband_text_track_)
+    UpdateActiveTextTrack(active_text_track_id_);
+
+  is_inband_text_track_ = false;
+  if (!GetMediaPlayerClient()) {
+    LOG(ERROR) << "MediaPlayerClient is null";
+    return;
+  }
+  content::WebContentsDelegate* web_contents_delegate =
+      GetMediaPlayerClient()->GetWebContentsDelegate();
+  if (!web_contents_delegate) {
+    LOG(ERROR) << "web contents delegate is null";
+    return;
+  }
+
+  web_contents_delegate->NotifySubtitleState(
+      blink::WebMediaPlayer::kSubtitleStop);
+}
+
+void MediaPlayerBridgeCapiTV::UpdateActiveTextTrack(int id) {
+  int ret = PLAYER_ERROR_NONE;
+
+  // unselected...
+  if (id == -1) {
+    LOG_ID(INFO, player_id_) << "UpdateActiveTextTrack id=-1";
+    return;
+  }
+
+  int count = 0;
+  int err = player_get_track_count(player_, PLAYER_STREAM_TYPE_TEXT, &count);
+  if (err != PLAYER_ERROR_NONE || count <= 0 || id >= count) {
+    LOG(ERROR) << "player_get_track_count err,ret=" << ret
+               << ",count=" << count;
+    return;
+  }
+
+  ret = player_select_track_ex(player_, PLAYER_STREAM_TYPE_TEXT, id,
+                               -1);  //-1 means use the default mode  for
+                                     // mmplayer demuxer to select stream
+  if (ret != PLAYER_ERROR_NONE) {
+    LOG(ERROR) << "player_select_track_ex err,ret=" << ret;
+    return;
+  }
+}
+
+void MediaPlayerBridgeCapiTV::OnCurrentTimeUpdateTimerFired() {
+  MediaPlayerBridgeCapi::OnCurrentTimeUpdateTimerFired();
+  if (!GetMediaPlayerClient()) {
+    LOG(ERROR) << "media player client is null";
+    return;
+  }
+  GetMediaPlayerClient()->UpdateCurrentTime(
+      MediaPlayerBridgeCapi::GetCurrentTime());
+}
+
+void MediaPlayerBridgeCapiTV::SeekCompleteUpdate() {
+  MediaPlayerBridgeCapi::SeekCompleteUpdate();
+  NotifySubtitleState(blink::WebMediaPlayer::kSubtitleSeekComplete);
+}
+
+void MediaPlayerBridgeCapiTV::OnResumeComplete(bool success) {
+  LOG(INFO) << __func__ << ", success: " << success;
+  MediaPlayerBridgeCapi::OnResumeComplete(success);
+
+  if (!GetMediaPlayerClient()) {
+    LOG(ERROR) << "media player client is null";
+    return;
+  }
+
+  if (success)
+    GetMediaPlayerClient()->UpdateCurrentTime(
+        MediaPlayerBridgeCapi::GetCurrentTime());
+}
+
 void MediaPlayerBridgeCapiTV::PlayerPrepared() {
   player_prepared_ = true;
   MediaPlayerBridgeCapi::PlayerPrepared();
@@ -180,6 +520,9 @@ void MediaPlayerBridgeCapiTV::PlayerPrepared() {
     UpdateSeekableTime();
     StartSeekableTimeUpdateTimer();
   }
+
+  if (blink::IsHbbTV())
+    UpdatePreferAudio();
 }
 
 void MediaPlayerBridgeCapiTV::StartSeekableTimeUpdateTimer() {
@@ -360,6 +703,45 @@ bool MediaPlayerBridgeCapiTV::GetDashLiveDuration(int64_t* duration) {
   return true;
 }
 
+void MediaPlayerBridgeCapiTV::HandleBufferingStatus(int percent) {
+  if (is_paused_ || is_seeking_)
+    return;
+
+  if (percent == 100) {
+    LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__;
+    is_buffering_compeleted_ = true;
+    if (MediaPlayerBridgeCapi::GetPlayerState() != PLAYER_STATE_PAUSED)
+      return;
+    if (player_start(player_) != PLAYER_ERROR_NONE) {
+      LOG(ERROR) << "|player_start| failed";
+      return;
+    }
+
+    if (is_buffering_compeleted_ && blink::IsHbbTV())
+      UpdatePreferAudio();
+
+    if (!is_file_url_)
+      MediaPlayerBridgeCapi::StartBufferingUpdateTimer();
+
+    MediaPlayerBridgeCapi::OnReadyStateChange(
+        player_id_, blink::WebMediaPlayer::kReadyStateHaveEnoughData);
+  } else {
+    is_buffering_compeleted_ = false;
+    if (GetPlayerState() != PLAYER_STATE_PLAYING)
+      return;
+    if (player_pause(player_) != PLAYER_ERROR_NONE) {
+      LOG(ERROR) << "|player_pause| failed";
+      return;
+    }
+
+    MediaPlayerBridgeCapi::StopCurrentTimeUpdateTimer();
+    MediaPlayerBridgeCapi::OnReadyStateChange(
+        player_id_, blink::WebMediaPlayer::kReadyStateHaveCurrentData);
+  }
+  MediaPlayerBridgeCapi::OnNetworkStateChange(
+      player_id_, blink::WebMediaPlayer::kNetworkStateLoading);
+}
+
 void MediaPlayerBridgeCapiTV::AppendUrlHighBitRate(const std::string& url) {
   // don't use url.append("|STARTBITRATE=HIGHEST") to get hbbtv url
   // "|" will be replaced with "%7C"
@@ -437,6 +819,89 @@ void MediaPlayerBridgeCapiTV::SetDisplayAtPausedState() {
         << "player_display_video_at_paused_state() failed";
 }
 
+#if TIZEN_VERSION_AT_LEAST(6, 0, 0)
+void MediaPlayerBridgeCapiTV::HandleFirstTimeStamp(unsigned long long timestamp,
+                                                   int time_base_num,
+                                                   int time_base_den) {
+  LOG_ID(INFO, player_id_) << "HandleFirstTimeStamp,timestamp:" << timestamp
+                           << ",time_base_num:" << time_base_num
+                           << ",time_base_den:" << time_base_den;
+  NotifyFirstTimeStamp(timestamp, time_base_num, time_base_den);
+}
+
+void MediaPlayerBridgeCapiTV::HandleTSSubtitleData(int pid,
+                                                   const std::string& buf,
+                                                   unsigned int len) {
+  NotifyPESData(buf, len, GetCurrentTime().InMilliseconds());
+}
+
+void MediaPlayerBridgeCapiTV::OnFirstTimeStamp(unsigned long long timestamp,
+                                               int time_base_num,
+                                               int time_base_den) {
+  task_runner_->PostTask(
+      FROM_HERE, base::BindOnce(&MediaPlayerBridgeCapiTV::HandleFirstTimeStamp,
+                                weak_factory_.GetWeakPtr(), timestamp,
+                                time_base_num, time_base_den));
+}
+
+void MediaPlayerBridgeCapiTV::OnTSSubtitleData(int pid,
+                                               unsigned char* data,
+                                               unsigned int len) {
+  // maybe prefer subtitle lang changed
+  if (prefer_subtitle_lang_ == "off")
+    return;
+
+  if (!data || !len) {
+    LOG(ERROR) << "invalid data";
+    return;
+  }
+
+  std::string buf((char*)data);
+  task_runner_->PostTask(
+      FROM_HERE, base::BindOnce(&MediaPlayerBridgeCapiTV::HandleTSSubtitleData,
+                                weak_factory_.GetWeakPtr(), pid, buf, len));
+}
+
+void MediaPlayerBridgeCapiTV::NotifyFirstTimeStamp(unsigned long long timestamp,
+                                                   int time_base_num,
+                                                   int time_base_den) {
+  if (!GetMediaPlayerClient()) {
+    LOG(ERROR) << "MediaPlayerClient is null";
+    return;
+  }
+  if (!blink::IsHbbTV() ||
+      !GetMediaPlayerClient()->SubtitleNotificationEnabled())
+    return;
+  content::WebContentsDelegate* web_contents_delegate =
+      GetMediaPlayerClient()->GetWebContentsDelegate();
+  if (!web_contents_delegate) {
+    LOG(ERROR) << "web contents delegate is null";
+    return;
+  }
+  web_contents_delegate->NotifyFirstTimeStamp(timestamp, time_base_num,
+                                              time_base_den);
+}
+
+void MediaPlayerBridgeCapiTV::NotifyPESData(const std::string& buf,
+                                            unsigned int len,
+                                            int media_position) {
+  if (!GetMediaPlayerClient()) {
+    LOG(ERROR) << "MediaPlayerClient is null";
+    return;
+  }
+  if (!blink::IsHbbTV() ||
+      !GetMediaPlayerClient()->SubtitleNotificationEnabled())
+    return;
+  content::WebContentsDelegate* web_contents_delegate =
+      GetMediaPlayerClient()->GetWebContentsDelegate();
+  if (!web_contents_delegate) {
+    LOG(ERROR) << "web contents delegate is null";
+    return;
+  }
+  web_contents_delegate->NotifyPESData(buf, len, media_position);
+}
+#endif
+
 void MediaPlayerBridgeCapiTV::UpdateDuration() {
   LOG_ID(INFO, GetPlayerId())
       << "(" << static_cast<void*>(this) << ") " << __func__;
@@ -543,9 +1008,9 @@ void MediaPlayerBridgeCapiTV::PlayerPreloaded() {
     // UpdateSeekableTime();
     // StartSeekableTimeUpdateTimer();
   }
-  // UpdateAudioTrackInfo();
-  // UpdateVideoTrackInfo();
-  // UpdateTextTrackInfo();
+  UpdateAudioTrackInfo();
+  UpdateVideoTrackInfo();
+  UpdateTextTrackInfo();
   UpdateDuration();
   UpdateMediaType();
   if (GetMediaType() == MediaType::Invalid) {
@@ -682,4 +1147,842 @@ void MediaPlayerBridgeCapiTV::SetParentalRatingResult(bool is_pass) {
     ExecuteDelayedPlayerState();
   }
 }
+void MediaPlayerBridgeCapiTV::AddAudioTrackInfo(const std::string& id,
+                                                const std::string& kind,
+                                                const std::string& label,
+                                                const std::string& lang,
+                                                int enabled) {
+  LOG_ID(INFO, player_id_) << "AudioTrack Info - id: " << id
+                           << ", kind: " << kind.c_str()
+                           << ", label: " << label.c_str()
+                           << ", lang: " << lang.c_str();
+
+  media::mojom::MediaTrackInfoPtr trackinfo =
+      media::mojom::MediaTrackInfo::New();
+  trackinfo->cmd = media::mojom::TRACKCMD::SETAUDIO;
+  trackinfo->ck = media::mojom::COOKIES::NewTrack(
+      media::mojom::Track::New(id, kind, label, lang, enabled));
+  if (GetMediaPlayerClient())
+    GetMediaPlayerClient()->AddTrackInfo(std::move(trackinfo));
+  else
+    LOG(ERROR) << "Media player client is null";
+}
+
+void MediaPlayerBridgeCapiTV::OnOtherEvent(int event_type, void* event_data) {
+  if (!event_data) {
+    LOG(ERROR) << "event_data is null.";
+    return;
+  }
+  switch (event_type) {
+    case PLAYER_MSG_STREAM_EVENT_TYPE: {
+      LOG_ID(INFO, player_id_) << "PLAYER_MSG_STREAM_EVENT_TYPE";
+      EventStream* eventstream = static_cast<EventStream*>(event_data);
+      if (!eventstream) {
+        LOG(ERROR) << "eventstream is null.";
+        return;
+      }
+      std::string uri(eventstream->schemeIdUri ? eventstream->schemeIdUri : "");
+      std::string value(eventstream->value ? eventstream->value : "");
+#if TIZEN_VERSION_AT_LEAST(6, 5, 0)
+      int band_type = eventstream->type;
+      int event_mode = static_cast<player_event_mode>(
+          (band_type >= IN_BAND) ? (band_type - IN_BAND)
+                                 : (band_type - OUT_BAND));
+#else
+      player_event_mode event_mode = eventstream->type;
+      int band_type = static_cast<int>(event_mode);
+#endif
+      LOG_ID(INFO, player_id_)
+          << "uri:" << uri << ",value:" << value << ",band_type:" << band_type
+          << ",event_mode:" << event_mode;
+
+      // parental rating event only need to handle data info
+      if (event_mode == PLAYER_DVB_EVENT_MODE_PARENTAL_GUIDANCE) {
+        LOG_ID(INFO, player_id_) << "parental rating event, skip type";
+        return;
+      }
+
+      if (!uri.compare("urn:mpeg:dash:event:2012") ||
+          !uri.compare("urn:dvb:iptv:cpm:2014")) {
+        LOG_ID(INFO, player_id_) << "not supported scheme id uri,uri:" << uri;
+        return;
+      }
+#if !defined(EWK_BRINGUP)
+      if (!uri.compare("urn:dvb:css")) {
+        LOG_ID(INFO, player_id_) << "event->value:" << eventstream->value
+                                 << " evalue " << value.c_str();
+        task_runner_->PostTask(
+            FROM_HERE, base::BindOnce(&MediaPlayerBridgeCapi::UpdateEventData,
+                                      weak_factory_.GetWeakPtr(), value));
+        return;
+      }
+#endif
+      const std::string info = uri + " " + value;
+      task_runner_->PostTask(
+          FROM_HERE,
+          base::BindOnce(&MediaPlayerBridgeCapiTV::HandleInbandTextTrack,
+                         weak_factory_.GetWeakPtr(), info, band_type,
+                         ADD_INBAND_TEXT_TRACK));
+      break;
+    }
+    case PLAYER_MSG_STREAM_EVENT_DATA: {
+      LOG_ID(INFO, player_id_) << "PLAYER_MSG_STREAM_EVENT_DATA";
+      Event* event = static_cast<Event*>(event_data);
+      if (!event) {
+        LOG(ERROR) << "event is null.";
+        return;
+      }
+      std::string uri(event->schemeIdUri ? event->schemeIdUri : "");
+      std::string value(event->value ? event->value : "");
+      unsigned int id = event->id;
+      long long int start_time = event->startTimeMs;
+      long long int end_time = event->endTimeMs;
+      std::string data(event->data ? event->data : "");
+#if TIZEN_VERSION_AT_LEAST(6, 5, 0)
+      int band_type = event->type;
+      int event_mode = static_cast<player_event_mode>(
+          (band_type >= IN_BAND) ? (band_type - IN_BAND)
+                                 : (band_type - OUT_BAND));
+#else
+      player_event_mode event_mode = event->type;
+      int band_type = static_cast<int>(event_mode);
+#endif
+      LOG_ID(INFO, player_id_)
+          << "uri:" << uri << ",value:" << value << ",data:" << data
+          << ",id:" << id << ",start_time:" << start_time
+          << ",end_time:" << end_time << ",band_type:" << band_type
+          << ",event_mode:" << event_mode;
+
+      if (event_mode == PLAYER_DVB_EVENT_MODE_DEAULT) {
+        if (0 == uri.compare("urn:mpeg:dash:event:2012") ||
+            0 == uri.compare("urn:dvb:iptv:cpm:2014")) {
+          LOG_ID(INFO, player_id_) << "not supported scheme id uri,uri:" << uri;
+          return;
+        }
+        const std::string info = uri + " " + value + "$" + data;
+        task_runner_->PostTask(
+            FROM_HERE,
+            base::BindOnce(&MediaPlayerBridgeCapiTV::HandleInbandTextCue,
+                           weak_factory_.GetWeakPtr(), info, id, band_type,
+                           start_time, end_time));
+      } else if (event_mode == PLAYER_DVB_EVENT_MODE_PARENTAL_GUIDANCE) {
+        //<mpeg7:ParentalRating href="urn:dvb:iptv:rating:2014:15"/>
+        std::size_t pos = data.find("ParentalRating href=");
+        if (pos != std::string::npos) {
+          parental_rating_pass_ = false;
+          std::size_t quotation1 = data.find('"', pos);
+          std::size_t quotation2 = data.find('"', quotation1 + 1);
+          std::string target =
+              data.substr(quotation1 + 1, quotation2 - quotation1 - 1);
+          LOG_ID(INFO, player_id_)
+              << "parentl rating info string is:" << target;
+          task_runner_->PostTask(
+              FROM_HERE,
+              base::BindOnce(&MediaPlayerBridgeCapiTV::HandleParentalRatingInfo,
+                             weak_factory_.GetWeakPtr(), target, url_.spec()));
+        }
+      } else if (
+          event_mode ==
+              PLAYER_DVB_EVENT_MODE_SUPPLEMENTAL_PROPERTY_FONT_DOWNLOAD ||
+          event_mode ==
+              PLAYER_DVB_EVENT_MODE_ESSENTIAL_PROPERTY_FONT_DOWNLOAD) {
+        task_runner_->PostTask(
+            FROM_HERE,
+            base::BindOnce(&MediaPlayerBridgeCapiTV::HandleDownloadableFontInfo,
+                           weak_factory_.GetWeakPtr(), uri, value, data,
+                           event_mode));
+      }
+      break;
+    }
+    case PLAYER_MSG_STREAM_EVENT_MRS_URL_CHANGED: {
+      LOG_ID(INFO, player_id_) << "PLAYER_MSG_STREAM_EVENT_MRS_URL_CHANGED";
+      char* url = static_cast<char*>(event_data);
+      std::string mrsUrl(url ? url : "");
+      LOG_ID(INFO, player_id_) << "mrsUrl:" << mrsUrl;
+#if !defined(EWK_BRINGUP)
+      task_runner_->PostTask(
+          FROM_HERE,
+          base::BindOnce(&MediaPlayerBridgeCapiTV::HandleMrsUrlChange,
+                         weak_factory_.GetWeakPtr(), mrsUrl));
+#endif
+      break;
+    }
+    case PLAYER_MSG_STREAM_EVENT_PERIOAD_ID_CHANGED: {
+      LOG_ID(INFO, player_id_) << "PLAYER_MSG_STREAM_EVENT_PERIOAD_ID_CHANGED";
+      char* id = static_cast<char*>(event_data);
+      std::string periodId(id ? id : "");
+      LOG_ID(INFO, player_id_) << "periodId:" << periodId;
+#if !defined(EWK_BRINGUP)
+      task_runner_->PostTask(
+          FROM_HERE,
+          base::BindOnce(&MediaPlayerBridgeCapiTV::HandlePeriodIdChange,
+                         weak_factory_.GetWeakPtr(), periodId));
+#endif
+      break;
+    }
+    case PLAYER_MSG_STREAM_EVENT_REMOVE_TRACK: {
+      LOG_ID(INFO, player_id_) << "PLAYER_MSG_STREAM_EVENT_REMOVE_TRACK";
+      EventStream* eventstream = static_cast<EventStream*>(event_data);
+      if (!eventstream) {
+        LOG(ERROR) << "eventstream is null.";
+        return;
+      }
+      std::string uri(eventstream->schemeIdUri ? eventstream->schemeIdUri : "");
+      std::string value(eventstream->value ? eventstream->value : "");
+      LOG_ID(INFO, player_id_) << "uri:" << uri << ",value:" << value;
+
+      const std::string info = uri + " " + value;
+#if TIZEN_VERSION_AT_LEAST(6, 5, 0)
+      int band_type = eventstream->type;
+#else
+      int band_type = static_cast<int>(eventstream->type);
+#endif
+      task_runner_->PostTask(
+          FROM_HERE,
+          base::BindOnce(&MediaPlayerBridgeCapiTV::HandleInbandTextTrack,
+                         weak_factory_.GetWeakPtr(), info, band_type,
+                         DEL_INBAND_TEXT_TRACK));
+      break;
+    }
+    default:
+      LOG_ID(INFO, player_id_) << "unknow event type:" << event_type;
+      break;
+  }
+}
+
+void MediaPlayerBridgeCapiTV::HandleInbandTextTrack(const std::string& info,
+                                                    int band_type,
+                                                    int action) {
+  LOG_ID(INFO, player_id_) << "HandleInbandTextTrack info:" << info
+                           << " band_type:" << band_type
+                           << " action:" << action;
+  media::mojom::MediaTrackInfoPtr trackinfo =
+      media::mojom::MediaTrackInfo::New();
+  trackinfo->cmd = media::mojom::TRACKCMD::SETINBAND;
+  trackinfo->ck = media::mojom::COOKIES::NewInband(
+      media::mojom::InbandTextInfo::New(info, band_type, action));
+  if (GetMediaPlayerClient())
+    GetMediaPlayerClient()->AddTrackInfo(std::move(trackinfo));
+}
+
+void MediaPlayerBridgeCapiTV::HandleInbandTextCue(const std::string& info,
+                                                  unsigned int id,
+                                                  int band_type,
+                                                  long long int start_time,
+                                                  long long int end_time) {
+  LOG_ID(INFO, player_id_) << "HandleInbandTextCue info:" << info
+                           << " id:" << id << " band_type:" << band_type
+                           << " start_time:" << start_time
+                           << " end_time:" << end_time;
+  media::mojom::MediaTrackInfoPtr trackinfo =
+      media::mojom::MediaTrackInfo::New();
+  trackinfo->cmd = media::mojom::TRACKCMD::SETCUE;
+  trackinfo->ck =
+      media::mojom::COOKIES::NewCue(media::mojom::InbandCueInfo::New(
+          info, id, band_type, start_time, end_time));
+  if (GetMediaPlayerClient())
+    GetMediaPlayerClient()->AddTrackInfo(std::move(trackinfo));
+  else
+    LOG(ERROR) << "Media player client is null";
+}
+
+std::string MediaPlayerBridgeCapiTV::MapDashMediaTrackKind(
+    const std::string& role,
+    const int size,
+    bool isAudio) {
+  // HBBTV Spec : A.2.12.3 Modifications to clause 8.4.6
+  // HBBTV spec v2.0.2 seperate audioTrack and videoTrack kind definition
+  // and changed the "main" definiton of audioTrack(page 258)
+  if (role.find("alternate") != std::string::npos &&
+      role.find("main") == std::string::npos &&
+      role.find("commentary") == std::string::npos &&
+      role.find("dub") == std::string::npos)
+    return "alternative";
+
+  if (role.find("caption") != std::string::npos &&
+      role.find("main") != std::string::npos)
+    return "captions";
+
+  if (role.find("description") != std::string::npos &&
+      role.find("supplementary") != std::string::npos)
+    return "descriptions";
+
+  if (role.find("main") != std::string::npos &&
+      role.find("caption") == std::string::npos &&
+      role.find("subtitle") == std::string::npos &&
+      role.find("dub") == std::string::npos) {
+    if (!isAudio)
+      return "main";
+    else if (role.find("description") == std::string::npos)
+      return "main";
+  }
+
+  if (role.find("main") != std::string::npos &&
+      role.find("description") != std::string::npos)
+    return "main-desc";
+
+  if (role.find("subtitle") != std::string::npos &&
+      role.find("main") != std::string::npos)
+    return "subtitles";
+
+  if (role.find("dub") != std::string::npos &&
+      role.find("main") != std::string::npos)
+    return "translation";
+
+  if (role.find("commentary") != std::string::npos &&
+      role.find("main") == std::string::npos)
+    return "commentary";
+
+  return "";
+}
+
+void MediaPlayerBridgeCapiTV::UpdateAudioTrackInfo() {
+  int cntTracks = 0;
+  int err = player_get_adaptationset_count(player_, PLAYER_STREAM_TYPE_AUDIO,
+                                           &cntTracks);
+  if (err != PLAYER_ERROR_NONE || cntTracks == 0) {
+    LOG_ID(ERROR, player_id_)
+        << "get audio track fail,err:" << err << ",count:" << cntTracks;
+    return;
+  }
+
+  LOG_ID(INFO, player_id_) << "audio track count: " << cntTracks;
+
+  player_audio_adaptationset_info* audio_track_info =
+      static_cast<player_audio_adaptationset_info*>(
+          malloc(cntTracks * sizeof(player_audio_adaptationset_info)));
+  if (!audio_track_info) {
+    LOG_ID(ERROR, player_id_) << "malloc fail";
+    return;
+  }
+  memset(audio_track_info, 0,
+         cntTracks * sizeof(player_audio_adaptationset_info));
+
+  unsigned audio_alter_count_total = 0;
+  for (int i = 0; i < cntTracks; i++) {
+    int audio_alter_count = 0;
+    err = player_get_alternative_count(player_, PLAYER_STREAM_TYPE_AUDIO, i,
+                                       &audio_alter_count);
+    if (err != PLAYER_ERROR_NONE || audio_alter_count == 0) {
+      LOG_ID(WARNING, player_id_)
+          << "player_get_alternative_count error,idx: " << i
+          << ",audio_alter_count: " << audio_alter_count;
+      continue;
+    }
+
+    LOG_ID(INFO, player_id_)
+        << "audio track idx:" << i << ",alter_count:" << audio_alter_count;
+    audio_alter_count_total += audio_alter_count;
+    audio_track_info[i].alternatives =
+        static_cast<Alternative_audioStreamInfo*>(
+            malloc(audio_alter_count * sizeof(Alternative_audioStreamInfo)));
+    if (!audio_track_info[i].alternatives) {
+      LOG_ID(ERROR, player_id_)
+          << "malloc fail,free memory which is already malloced";
+      if (i >= 1) {
+        for (int j = 0; j <= i - 1; j++)
+          BLINKFREE(audio_track_info[j].alternatives);
+      }
+      BLINKFREE(audio_track_info);
+      return;
+    }
+    memset(audio_track_info[i].alternatives, 0,
+           audio_alter_count * sizeof(Alternative_audioStreamInfo));
+  }
+#if !defined(EWK_BRINGUP)
+  if (blink::IsHbbTV())
+    AudioTracksCountChanged(audio_alter_count_total);
+#endif
+  err = player_get_audio_adaptationset_info(player_, audio_track_info);
+  if (err != PLAYER_ERROR_NONE) {
+    LOG_ID(ERROR, player_id_) << "|player_get_audio_adaptationset_info| failed";
+    for (int i = 0; i < cntTracks; i++)
+      BLINKFREE(audio_track_info[i].alternatives);
+    BLINKFREE(audio_track_info);
+    return;
+  }
+
+  int selected_idx = -1;
+  int audio_track_index = 0;
+
+  /* Get audio index for prefer languange & audio description */
+  for (int i = 0; i < cntTracks; i++) {
+    if (!audio_track_info[i].alternatives) {
+      LOG_ID(WARNING, player_id_) << "track[" << i << "] fail,ignore it.";
+      continue;
+    }
+
+    const char* language = audio_track_info[i].language;
+    if (prefer_audio_lang_.find(language) != std::string::npos ||
+        (GetAlpha2(prefer_audio_lang_).find(language) != std::string::npos)) {
+      if (stream_type_ == DASH_STREAM)
+        prefer_audio_adaptionset_idx_ = audio_track_info[i].index;
+      else
+        prefer_audio_adaptionset_idx_ = i;
+
+      selected_idx = i;
+      break;
+    }
+  }
+  LOG_ID(INFO, player_id_) << "prefer_audio_adaptationset_idx_: "
+                           << prefer_audio_adaptionset_idx_
+                           << ",selected_idx:" << selected_idx;
+
+  audio_track_index = 0;
+
+  for (int i = 0; i < cntTracks; i++) {
+#if TIZEN_VERSION_AT_LEAST(7, 0, 0)
+    if (audio_track_info[i].preselectionInfo_count) {
+      for (int j = 0; j < audio_track_info[i].preselectionInfo_count; j++) {
+        std::string pres_id = audio_track_info[i].preselectionInfos[j].m_id;
+        std::string language = audio_track_info[i].preselectionInfos[j].m_lang;
+        std::string kind = audio_track_info[i].preselectionInfos[j].m_roleValue;
+        std::string label = "";
+        int enabled = (selected_idx == audio_track_index);
+        AddAudioTrackInfo(pres_id, kind, label, language, enabled);
+        audio_track_index++;
+      }
+      continue;
+    }
+#endif
+
+    if (!audio_track_info[i].alternatives) {
+      LOG_ID(WARNING, player_id_) << "track[" << i << "] fail,ignore it.";
+      continue;
+    }
+    const char* lang = audio_track_info[i].language;
+    std::string langStr(lang ? lang : "");
+
+    std::stringstream roleInfoBuilder;
+    const int role_count = audio_track_info[i].role_count;
+
+    for (int k = 0; k < role_count; k++) {
+      const char* role_member = audio_track_info[i].role_value[k];
+      const std::string role_str(role_member ? role_member : "");
+      roleInfoBuilder << role_str << ",";
+    }
+
+    LOG_ID(INFO, player_id_)
+        << "role str:" << roleInfoBuilder.str() << ",role count:" << role_count;
+    std::string kindStr = "";
+    if (stream_type_ == DASH_STREAM)
+      kindStr = MapDashMediaTrackKind(roleInfoBuilder.str(), role_count, true);
+    if (stream_type_ == TS_STREAM)  // role_count = 1
+      kindStr = audio_track_info[i].role_value[0];
+
+    char* label = nullptr;
+    err = player_get_content_info(player_, PLAYER_CONTENT_INFO_TITLE, &label);
+    if (err != PLAYER_ERROR_NONE)
+      LOG_ID(WARNING, player_id_) << "|player_get_content_info| failed";
+    std::string labelStr(label ? label : "");
+    BLINKFREE(label);
+
+    int id = 0;
+    if (stream_type_ == DASH_STREAM)
+      id = audio_track_info[i].adaptationset_id;
+    else
+      id = audio_track_info[i].alternatives[0].track_id;
+
+    std::string pres_id = std::to_string(id);
+    std::string language = langStr;
+    std::string kind = kindStr;
+    std::string labels = labelStr;
+    int enabled = (selected_idx == audio_track_index);
+    AddAudioTrackInfo(pres_id, kind, labels, language, enabled);
+    audio_track_index++;
+  }
+
+  for (int j = 0; j < cntTracks; j++) {
+    BLINKFREE(audio_track_info[j].alternatives);
+#if TIZEN_VERSION_AT_LEAST(7, 0, 0)
+    BLINKFREE(audio_track_info[j].preselectionInfos);
+#endif
+  }
+
+  BLINKFREE(audio_track_info);
+}
+
+void MediaPlayerBridgeCapiTV::UpdateVideoTrackInfo() {
+  int cntTracks = 0;
+  int err = player_get_adaptationset_count(player_, PLAYER_STREAM_TYPE_VIDEO,
+                                           &cntTracks);
+  if (err != PLAYER_ERROR_NONE || cntTracks == 0) {
+    LOG(ERROR) << "get video track fail,err:" << err << ",count" << cntTracks;
+    return;
+  }
+
+  LOG_ID(INFO, player_id_) << "video track count: " << cntTracks;
+
+  player_video_adaptationset_info* video_track_info =
+      static_cast<player_video_adaptationset_info*>(
+          malloc(cntTracks * sizeof(player_video_adaptationset_info)));
+  if (!video_track_info) {
+    LOG(ERROR) << "malloc fail";
+    return;
+  }
+  memset(video_track_info, 0,
+         cntTracks * sizeof(player_video_adaptationset_info));
+
+  int adaptionSetIdx = -1;
+  int alternativeIdx = -1;
+  err = player_get_current_track_ex(player_, PLAYER_STREAM_TYPE_VIDEO,
+                                    &adaptionSetIdx, &alternativeIdx);
+  if (err != PLAYER_ERROR_NONE)
+    LOG(WARNING) << "|player_get_current_track| failed";
+  LOG_ID(INFO, player_id_) << "video adaptionSetIdx:" << adaptionSetIdx
+                           << ",alternativeIdx:" << alternativeIdx;
+
+  for (int i = 0; i < cntTracks; i++) {
+    int video_alter_count = 0;
+    err = player_get_alternative_count(player_, PLAYER_STREAM_TYPE_VIDEO, i,
+                                       &video_alter_count);
+    if (err != PLAYER_ERROR_NONE || video_alter_count == 0) {
+      LOG(WARNING) << "player_get_alternative_count error,idx: " << i
+                   << ",video_alter_count: " << video_alter_count;
+      continue;
+    }
+
+    LOG_ID(INFO, player_id_)
+        << "video track idx:" << i << ",alter_count:" << video_alter_count;
+    video_track_info[i].alternatives =
+        static_cast<Alternative_videoStreamInfo*>(
+            malloc(video_alter_count * sizeof(Alternative_videoStreamInfo)));
+    if (!video_track_info[i].alternatives) {
+      LOG(ERROR) << "malloc fail,free memory which is already malloced";
+      if (i >= 1) {
+        for (int j = 0; j <= i - 1; j++)
+          BLINKFREE(video_track_info[j].alternatives);
+      }
+      BLINKFREE(video_track_info);
+      return;
+    }
+    memset(video_track_info[i].alternatives, 0,
+           video_alter_count * sizeof(Alternative_videoStreamInfo));
+  }
+
+  err = player_get_video_adaptationset_info(player_, video_track_info);
+  if (err != PLAYER_ERROR_NONE) {
+    LOG(WARNING) << "|player_get_video_adaptationset_info| failed";
+    for (int i = 0; i < cntTracks; i++)
+      BLINKFREE(video_track_info[i].alternatives);
+    BLINKFREE(video_track_info);
+    return;
+  }
+
+  for (int i = 0; i < cntTracks; i++) {
+    if (!video_track_info[i].alternatives) {
+      LOG(WARNING) << "track[" << i << "] fail,ignore it.";
+      continue;
+    }
+
+    char* lang = nullptr;
+    err = player_get_track_language_code_ex(player_, PLAYER_STREAM_TYPE_VIDEO,
+                                            i, &lang);
+    if (err != PLAYER_ERROR_NONE)
+      LOG(WARNING) << "|player_get_track_language_code| failed";
+    std::string langStr(lang ? lang : "");
+    BLINKFREE(lang);
+
+    std::stringstream roleInfoBuilder;
+    const int role_count = video_track_info[i].role_count;
+
+    for (int k = 0; k < role_count; k++) {
+      const char* role_member = video_track_info[i].role_value[k];
+      const std::string role_str(role_member ? role_member : "");
+      roleInfoBuilder << role_str << ",";
+    }
+
+    LOG_ID(INFO, player_id_)
+        << "role str:" << roleInfoBuilder.str() << ",role count:" << role_count;
+
+    std::string kindStr = "";
+    if (stream_type_ == DASH_STREAM)
+      kindStr = MapDashMediaTrackKind(roleInfoBuilder.str(), role_count, false);
+
+    char* label = nullptr;
+    err = player_get_content_info(player_, PLAYER_CONTENT_INFO_TITLE, &label);
+    if (err != PLAYER_ERROR_NONE)
+      LOG(WARNING) << "|player_get_content_info| failed";
+    std::string labelStr(label ? label : "");
+    BLINKFREE(label);
+
+    int id = 0;
+    if (stream_type_ == DASH_STREAM)
+      id = video_track_info[i].adaptationset_id;
+    else
+      id = video_track_info[i].alternatives[0].track_id;
+
+    if (adaptionSetIdx == i)
+      LOG_ID(INFO, player_id_) << "VideoTrack index: [" << i << "] is selected";
+
+    BLINKFREE(video_track_info[i].alternatives);
+
+    LOG_ID(INFO, player_id_)
+        << "VideoTrack Info - id: " << id << ", kind: " << kindStr.c_str()
+        << ", label: " << labelStr.c_str() << ", lang: " << langStr.c_str();
+
+    media::mojom::MediaTrackInfoPtr trackinfo =
+        media::mojom::MediaTrackInfo::New();
+    trackinfo->cmd = media::mojom::TRACKCMD::SETVIDEO;
+    trackinfo->ck = media::mojom::COOKIES::NewTrack(media::mojom::Track::New(
+        std::to_string(id), kindStr, labelStr, langStr, adaptionSetIdx == i));
+
+    if (GetMediaPlayerClient())
+      GetMediaPlayerClient()->AddTrackInfo(std::move(trackinfo));
+    else
+      LOG(ERROR) << "Media player client is null";
+  }
+  BLINKFREE(video_track_info);
+}
+
+void MediaPlayerBridgeCapiTV::UpdateTextTrackInfo() {
+  int cntTracks = 0;
+  int err = player_get_adaptationset_count(player_, PLAYER_STREAM_TYPE_TEXT,
+                                           &cntTracks);
+  if (err != PLAYER_ERROR_NONE || cntTracks == 0) {
+    LOG_ID(ERROR, player_id_)
+        << "get text track fail,err:" << err << ",count:" << cntTracks;
+    return;
+  }
+
+  LOG_ID(INFO, player_id_) << "text track count: " << cntTracks;
+
+  player_subtitle_adaptationset_info* text_track_info =
+      static_cast<player_subtitle_adaptationset_info*>(
+          malloc(cntTracks * sizeof(player_subtitle_adaptationset_info)));
+  if (!text_track_info) {
+    LOG_ID(ERROR, player_id_) << "malloc fail";
+    return;
+  }
+  memset(text_track_info, 0,
+         cntTracks * sizeof(player_subtitle_adaptationset_info));
+
+  int adaptionSetIdx = -1;
+  int alternativeIdx = -1;
+  err = player_get_current_track_ex(player_, PLAYER_STREAM_TYPE_TEXT,
+                                    &adaptionSetIdx, &alternativeIdx);
+  if (err != PLAYER_ERROR_NONE)
+    LOG_ID(WARNING, player_id_) << "|player_get_current_track| failed";
+  LOG_ID(INFO, player_id_) << "text adaptionSetIdx:" << adaptionSetIdx
+                           << ",alternativeIdx:" << alternativeIdx;
+
+  for (int i = 0; i < cntTracks; i++) {
+    int text_alter_count = 0;
+    err = player_get_alternative_count(player_, PLAYER_STREAM_TYPE_TEXT, i,
+                                       &text_alter_count);
+    if (err != PLAYER_ERROR_NONE || text_alter_count == 0) {
+      LOG_ID(WARNING, player_id_)
+          << "player_get_alternative_count error,idx: " << i
+          << ",text_alter_count: " << text_alter_count;
+      continue;
+    }
+
+    LOG_ID(INFO, player_id_)
+        << "text track idx:" << i << ",alter_count:" << text_alter_count;
+    text_track_info[i].alternatives =
+        static_cast<Alternative_subtitleStreamInfo*>(
+            malloc(text_alter_count * sizeof(Alternative_subtitleStreamInfo)));
+    if (!text_track_info[i].alternatives) {
+      LOG_ID(ERROR, player_id_)
+          << "malloc fail,free memory which is already malloced";
+      if (i >= 1) {
+        for (int j = 0; j <= i - 1; j++)
+          BLINKFREE(text_track_info[j].alternatives);
+      }
+      BLINKFREE(text_track_info);
+      return;
+    }
+    memset(text_track_info[i].alternatives, 0,
+           text_alter_count * sizeof(Alternative_subtitleStreamInfo));
+  }
+
+  err = player_get_subtitle_adaptationset_info(player_, text_track_info);
+  if (err != PLAYER_ERROR_NONE) {
+    LOG_ID(ERROR, player_id_)
+        << "|player_get_subtitle_adaptationset_info| failed";
+    for (int i = 0; i < cntTracks; i++)
+      BLINKFREE(text_track_info[i].alternatives);
+    BLINKFREE(text_track_info);
+    return;
+  }
+
+  for (int i = 0; i < cntTracks; i++) {
+    if (!text_track_info[i].alternatives) {
+      LOG_ID(WARNING, player_id_) << "track[" << i << "] fail,ignore it.";
+      continue;
+    }
+
+    char* lang = nullptr;
+    err = player_get_track_language_code_ex(player_, PLAYER_STREAM_TYPE_TEXT, i,
+                                            &lang);
+    if (err != PLAYER_ERROR_NONE)
+      LOG_ID(ERROR, player_id_) << "|player_get_track_language_code| failed";
+    std::string langStr(lang ? lang : "");
+    BLINKFREE(lang);
+
+    char* label = nullptr;
+    err = player_get_content_info(player_, PLAYER_CONTENT_INFO_TITLE, &label);
+    if (err != PLAYER_ERROR_NONE)
+      LOG_ID(ERROR, player_id_) << "|player_get_content_info| failed";
+    std::string labelStr(label ? label : "");
+    BLINKFREE(label);
+
+    int id = 0;
+    if (stream_type_ == TS_STREAM)
+      id = text_track_info[i].alternatives[0].track_id;
+    else
+      id = text_track_info[i].adaptationset_id;
+
+    std::string kindStr("");
+#if TIZEN_VERSION_AT_LEAST(6, 0, 0)
+    // subtitling_type: 8bit, maybe unvisible char
+    if (stream_type_ == TS_STREAM) {
+      int subitle_type = (int)text_track_info[i].role_value[0][0];
+      LOG(INFO) << "subitle_type:" << subitle_type;
+      if (subitle_type == 0x10 || subitle_type == 0x11 ||
+          subitle_type == 0x12 || subitle_type == 0x13 ||
+          subitle_type == 0x14 || subitle_type == 0x15)
+        kindStr = "subtitles";
+    }
+#endif
+
+    if (adaptionSetIdx == i)
+      LOG_ID(INFO, player_id_) << "TextTrack index: [" << i << "] is selected";
+
+    BLINKFREE(text_track_info[i].alternatives);
+
+    LOG_ID(INFO, player_id_)
+        << "TextTrack Info - id: " << id << ", label: " << labelStr.c_str()
+        << ", lang: " << langStr.c_str() << ", kind: " << kindStr.c_str();
+
+    media::mojom::MediaTrackInfoPtr trackinfo =
+        media::mojom::MediaTrackInfo::New();
+    trackinfo->cmd = media::mojom::TRACKCMD::SETTEXT;
+    trackinfo->ck = media::mojom::COOKIES::NewTrack(media::mojom::Track::New(
+        std::to_string(id), kindStr, labelStr, langStr, true));
+
+    if (GetMediaPlayerClient())
+      GetMediaPlayerClient()->AddTrackInfo(std::move(trackinfo));
+  }
+
+  BLINKFREE(text_track_info);
+}
+
+void MediaPlayerBridgeCapiTV::UpdatePreferAudio() {
+  LOG(INFO) << "UpdatePreferAudio,idx: " << prefer_audio_adaptionset_idx_
+            << ",last idx:" << last_prefer_audio_adaptionset_idx_;
+  if (prefer_audio_adaptionset_idx_ == last_prefer_audio_adaptionset_idx_) {
+    LOG_ID(ERROR, player_id_) << "same track,no need to select";
+    return;
+  }
+  int ret = player_select_track_ex(player_, PLAYER_STREAM_TYPE_AUDIO,
+                                   prefer_audio_adaptionset_idx_, -1);
+  if (ret != PLAYER_ERROR_NONE) {
+    LOG_ID(ERROR, player_id_) << "player_select_track_ex fail";
+    return;
+  }
+  active_audio_track_id_ = prefer_audio_adaptionset_idx_;
+  last_prefer_audio_adaptionset_idx_ = prefer_audio_adaptionset_idx_;
+}
+
+bool MediaPlayerBridgeCapiTV::GetUserPreferAudioLanguage() {
+  prefer_audio_lang_.clear();
+  int retval;
+  const char* primary_audio_lang =
+      "db/menu/broadcasting/audio_options/primary_audio_language";
+  int ret = vconf_get_int(primary_audio_lang, &retval);
+  if (ret != 0) {
+    LOG(ERROR) << "vconf_get_int failed";
+    return false;
+  }
+  prefer_audio_lang_ += (char)(retval >> 16 & 0xFF);
+  prefer_audio_lang_ += (char)(retval >> 8 & 0xFF);
+  prefer_audio_lang_ += (char)(retval & 0xFF);
+  LOG_ID(INFO, player_id_) << "primary audio lang is: "
+                           << prefer_audio_lang_.c_str();
+  return true;
+}
+
+void MediaPlayerBridgeCapiTV::SetActiveTextTrack(int id, bool is_in_band) {
+  LOG_ID(INFO, player_id_) << "id=" << id << ",is_in_band=" << is_in_band
+                           << " active_text_track_id_ "
+                           << active_text_track_id_;
+  if (!GetMediaPlayerClient()) {
+    LOG(ERROR) << "GetMediaPlayerClient return null";
+    return;
+  }
+  if (!GetMediaPlayerClient()->SubtitleNotificationEnabled()) {
+    LOG(ERROR) << "SubtitleNotificationEnabled failed";
+    return;
+  }
+
+#if !defined(EWK_BRINGUP)
+  if (id == -1) {
+    NotifyStopTrack();
+    return;
+  }
+
+  if (active_text_track_id_ == id)
+    return;
+
+  active_text_track_id_ = id;
+
+  is_inband_text_track_ = is_in_band;
+  NotifyPlayTrack();
+#endif
+}
+
+void MediaPlayerBridgeCapiTV::SetActiveAudioTrack(int index) {
+  LOG_ID(INFO, player_id_) << "active_audio_track_id_ "
+                           << active_audio_track_id_ << " index " << index;
+
+  if (index == -1) {
+    player_set_mute(player_, true);
+    active_audio_track_id_ = -1;
+    return;
+  }
+
+  if (active_audio_track_id_ == index)
+    return;
+  active_audio_track_id_ = index;
+  int ret = player_select_track_ex(player_, PLAYER_STREAM_TYPE_AUDIO,
+                                   active_audio_track_id_, -1);
+  if (ret != PLAYER_ERROR_NONE)
+    LOG_ID(WARNING, player_id_) << "player_select_track_ex fail,ret:" << ret;
+}
+
+void MediaPlayerBridgeCapiTV::SetActiveVideoTrack(int index) {
+  LOG_ID(INFO, player_id_) << "active_video_track_id_ "
+                           << active_video_track_id_ << " index " << index;
+
+  if (index == -1) {
+    player_set_display_visible(player_, false);
+    active_video_track_id_ = -1;
+    return;
+  }
+
+  if (active_video_track_id_ == index)
+    return;
+  active_video_track_id_ = index;
+  int ret = player_select_track_ex(player_, PLAYER_STREAM_TYPE_VIDEO,
+                                   active_video_track_id_, -1);
+  if (ret != PLAYER_ERROR_NONE)
+    LOG_ID(WARNING, player_id_) << "player_select_track_ex fail,ret:" << ret;
+}
+
+void MediaPlayerBridgeCapiTV::SetPreferTextLanguage(const std::string& lang) {
+  LOG_ID(INFO, player_id_)
+      << "MediaPlayerBridgeCapiTV::SetPreferTextLanguage lang" << lang
+      << " prefer_subtitle_lang_ " << prefer_subtitle_lang_;
+
+  if (lang == prefer_subtitle_lang_)
+    return;
+  prefer_subtitle_lang_ = lang;
+  const std::string prefer_subtitle_language =
+      "set_subtitle_language = " + lang;
+
+  LOG_ID(INFO, player_id_) << "prefer_subtitle_language:"
+                           << prefer_subtitle_language.c_str();
+  player_set_ini_param(player_, prefer_subtitle_language.c_str());
+}
 }  // namespace media
index 702a098..dc78210 100644 (file)
@@ -8,8 +8,17 @@
 #include <player_product.h>
 
 #include "media/filters/media_player_bridge_capi.h"
+#include "tizen_src/chromium_impl/build/tizen_version.h"
 
 namespace media {
+/* TC: org.hbbtv_DASH-EVENT0100
+ * Current use @schemeIdUri and @value to divide texttrack.
+ * So add event type to divide InbandEventStreams and EventStreams.
+ * event_type: 0x7700 for eventstream;
+ *             0x9900 for inbandeventstream
+ */
+#define OUT_BAND 0x7700
+#define IN_BAND 0x9900
 
 enum StreamType {
   HLS_STREAM = 0,
@@ -18,6 +27,11 @@ enum StreamType {
   OTHER_STREAM,
 };
 
+enum TrackAction {
+  ADD_INBAND_TEXT_TRACK = 0,
+  DEL_INBAND_TEXT_TRACK,
+};
+
 // This class is focus on HBBTV/HLS feature on Tizen TV.
 class MEDIA_EXPORT MediaPlayerBridgeCapiTV : public MediaPlayerBridgeCapi {
  public:
@@ -43,12 +57,43 @@ class MEDIA_EXPORT MediaPlayerBridgeCapiTV : public MediaPlayerBridgeCapi {
                                   const std::string& data,
                                   int type);
   void OnPlayerPreloading();
+  void OnOtherEvent(int event_type, void* event_data);
+  void SetActiveTextTrack(int id, bool is_in_band) override;
+  void SetActiveAudioTrack(int index) override;
+  void SetActiveVideoTrack(int index) override;
+  void SetPreferTextLanguage(const std::string& lang) override;
 
   void OnDrmError(int err_code, char* err_str);
+  void Seek(base::TimeDelta time, base::OnceClosure seek_cb) override;
+  void OnCurrentTimeUpdateTimerFired() override;
+  void SeekCompleteUpdate() override;
+  void OnResumeComplete(bool success) override;
   void SetParentalRatingResult(bool is_pass) override;
   void HandleParentalRatingInfo(const std::string& info,
                                 const std::string& url);
+  void HandleBufferingStatus(int percent) override;
 
+  void SubtitleDataCB(long long time_stamp,
+                      unsigned index,
+                      const std::string& buffer,
+                      unsigned buffer_size);
+#if TIZEN_VERSION_AT_LEAST(6, 0, 0)
+  void OnFirstTimeStamp(unsigned long long timestamp,
+                        int time_base_num,
+                        int time_base_den);
+  void OnTSSubtitleData(int pid, unsigned char* data, unsigned int len);
+  void HandleFirstTimeStamp(unsigned long long timestamp,
+                            int time_base_num,
+                            int time_base_den);
+  void HandleTSSubtitleData(int pid, const std::string& buf, unsigned int len);
+  void NotifyFirstTimeStamp(unsigned long long timestamp,
+                            int time_base_num,
+                            int time_base_den);
+  void NotifyPESData(const std::string& buf,
+                     unsigned int len,
+                     int media_position);
+
+#endif
  protected:
   void PlayerPrepared() override;
 
@@ -62,6 +107,41 @@ class MEDIA_EXPORT MediaPlayerBridgeCapiTV : public MediaPlayerBridgeCapi {
   bool SetMediaDRMInfo(const std::string&, const std::string&);
   bool is_preloaded_{false};
   bool is_player_seek_available_{true};
+
+  void NotifySubtitlePlay(int id,
+                          const std::string& url,
+                          const std::string& lang);
+  void NotifySubtitleData(int track_id,
+                          double time_stamp,
+                          const std::string& data,
+                          unsigned size);
+  void NotifySubtitleState(int state, double time_stamp = 0.0);
+  void NotifyStopTrack();
+  void NotifyPlayTrack();
+  void UpdateActiveTextTrack(int track_id);
+  void OnHandleOtherEvent(int event_type, void* event_data);
+  void UpdateAudioTrackInfo();
+  void UpdateVideoTrackInfo();
+  void UpdateTextTrackInfo();
+  std::string MapMediaTrackKind(const std::string& role, const int size);
+  bool GetUserPreferAudioLanguage();
+  void UpdatePreferAudio();
+  void HandleInbandTextTrack(const std::string& info,
+                             int band_type,
+                             int action);
+  void HandleInbandTextCue(const std::string& info,
+                           unsigned int id,
+                           int band_type,
+                           long long int start_time,
+                           long long int end_time);
+  std::string MapDashMediaTrackKind(const std::string& role,
+                                    const int size,
+                                    bool isAudio);
+  void AddAudioTrackInfo(const std::string& id,
+                         const std::string& kind,
+                         const std::string& label,
+                         const std::string& lang,
+                         int enabled);
   void StartSeekableTimeUpdateTimer();
   void StopSeekableTimeUpdateTimer();
   void OnSeekableTimeUpdateTimerFired();
@@ -79,7 +159,20 @@ class MEDIA_EXPORT MediaPlayerBridgeCapiTV : public MediaPlayerBridgeCapi {
   std::string mrs_url_{""};
   std::string content_id_{""};  // clean_url + period,only report to APP
 
+  int subtitle_state_{blink::WebMediaPlayer::kSubtitleStop};
+  bool is_inband_text_track_{false};
+  std::string prefer_audio_lang_;
+  std::string prefer_subtitle_lang_{""};
+  int active_audio_track_id_{-1};
+  int active_text_track_id_{-1};
+  int active_video_track_id_{-1};
+  int pending_active_audio_track_id_{-1};
+  int pending_active_text_track_id_{-1};
+  int pending_active_video_track_id_{-1};
+  int prefer_audio_adaptionset_idx_{0};
+  int last_prefer_audio_adaptionset_idx_{0};
   bool parental_rating_pass_{false};
+  bool is_buffering_compeleted_{false};
 
   base::TimeDelta min_seekable_time_{base::TimeDelta()};
   base::TimeDelta max_seekable_time_{base::TimeDelta()};
index d4b9de5..10a5f22 100644 (file)
@@ -10,6 +10,7 @@
 #include "media/base/demuxer_stream.h"
 #include "media/filters/flags.h"
 #include "third_party/blink/public/platform/web_application_type.h"
+#include "third_party/blink/public/platform/web_media_player.h"
 #include "ui/gfx/geometry/rect_f.h"
 #include "ui/gfx/tbm_buffer_handle.h"
 
@@ -110,6 +111,10 @@ class MEDIA_EXPORT MediaPlayerTizen {
   virtual int GetPlayerId() { return -1; }
   virtual void SetContentMimeType(const std::string& mime_type) {}
   virtual void SetParentalRatingResult(bool is_pass) {}
+  virtual void SetActiveTextTrack(int id, bool is_in_band) {}
+  virtual void SetActiveAudioTrack(int index) {}
+  virtual void SetActiveVideoTrack(int index) {}
+  virtual void SetPreferTextLanguage(const std::string& lang) {}
 };
 }  // namespace media
 
index 9b21291..f4ad8ea 100644 (file)
@@ -10,6 +10,7 @@
 #include "media/base/pipeline_status.h"
 #include "media/base/video_decoder_config.h"
 #include "media/base/waiting.h"
+#include "media/mojo/mojom/renderer_extensions.mojom.h"
 #include "third_party/abseil-cpp/absl/types/optional.h"
 #include "ui/gfx/geometry/size.h"
 #include "ui/gfx/tbm_buffer_handle.h"
@@ -37,6 +38,10 @@ class MEDIA_EXPORT MediaPlayerTizenClient {
   virtual void OnRequestSeek(base::TimeDelta time) = 0;
   virtual void OnRequestSuspend(bool resource_conflict) = 0;
 
+#if BUILDFLAG(IS_TIZEN_TV)
+  virtual void NotifyTrackInfoToBrowser(int active_track_id) = 0;
+#endif
+
   // MediaPlayerRendererClientExtension
   virtual void OnVideoSizeChange(const gfx::Size& size) = 0;
   virtual void OnDurationChange(base::TimeDelta duration) = 0;
@@ -55,7 +60,9 @@ class MEDIA_EXPORT MediaPlayerTizenClient {
 #endif
 
 #if BUILDFLAG(IS_TIZEN_TV)
+  virtual void AddTrackInfo(media::mojom::MediaTrackInfoPtr trackinfo) = 0;
   virtual bool PlaybackNotificationEnabled() = 0;
+  virtual bool SubtitleNotificationEnabled() = 0;
   virtual void NotifyPlaybackState(int state,
                                    int player_id = 0,
                                    const std::string& url = "",
@@ -63,6 +70,7 @@ class MEDIA_EXPORT MediaPlayerTizenClient {
                                    bool* media_resource_acquired = NULL,
                                    std::string* translated_url = NULL,
                                    std::string* drm_info = NULL) = 0;
+  virtual void UpdateCurrentTime(base::TimeDelta current_time) = 0;
   virtual void OnLivePlaybackComplete() = 0;
   virtual content::WebContentsDelegate* GetWebContentsDelegate() const = 0;
 #endif
index 964ec6e..62823cf 100644 (file)
 #include "public/ewk_media_downloadable_font_info.h"
 #include "public/ewk_media_parental_rating_info.h"
 #include "public/ewk_media_playback_info_product.h"
+#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"
 #endif
 
 #if defined(TIZEN_PEPPER_EXTENSIONS)
@@ -3384,6 +3386,60 @@ void EWebView::AddDynamicCertificatePath(const std::string& host,
   web_contents_->AddDynamicCertificatePath(host, cert_path);
 }
 
+void EWebView::NotifySubtitleState(int state, double time_stamp) {
+  LOG(INFO) << "subtitle state: " << state
+            << ",(0-Play : 1-Pause : 2-SeekStart : 3-SeekComplete : 4-Stop "
+               ":5-Resume)";
+  switch (state) {
+    case blink::WebMediaPlayer::kSubtitlePause:
+      SmartCallback<EWebViewCallbacks::SubtitlePause>().call();
+      break;
+    case blink::WebMediaPlayer::kSubtitleStop:
+      SmartCallback<EWebViewCallbacks::SubtitleStop>().call();
+      break;
+    case blink::WebMediaPlayer::kSubtitleResume:
+      SmartCallback<EWebViewCallbacks::SubtitleResume>().call();
+      break;
+    case blink::WebMediaPlayer::kSubtitleSeekStart: {
+      double ts = time_stamp;
+      SmartCallback<EWebViewCallbacks::SubtitleSeekStart>().call(&ts);
+    } break;
+    case blink::WebMediaPlayer::kSubtitleSeekComplete:
+      SmartCallback<EWebViewCallbacks::SubtitleSeekComplete>().call();
+      break;
+    default:
+      NOTREACHED();
+      break;
+  }
+}
+
+void EWebView::NotifySubtitlePlay(int active_track_id,
+                                  const char* url,
+                                  const char* lang) {
+  LOG(INFO) << "id:" << active_track_id << ",url:" << url << ",lang:" << lang;
+  Ewk_Media_Subtitle_Info* subtitle_info =
+      ewkMediaSubtitleInfoCreate(active_track_id, url, lang, 0);
+  SmartCallback<EWebViewCallbacks::SubtitlePlay>().call(
+      static_cast<void*>(subtitle_info));
+  ewkMediaSubtitleInfoDelete(subtitle_info);
+}
+
+void EWebView::NotifySubtitleData(int track_id,
+                                  double time_stamp,
+                                  const std::string& data,
+                                  unsigned int size) {
+  const void* buffer = static_cast<const void*>(data.c_str());
+  Ewk_Media_Subtitle_Data* subtitle_data =
+      ewkMediaSubtitleDataCreate(track_id, time_stamp, buffer, size);
+  SmartCallback<EWebViewCallbacks::SubtitleNotifyData>().call(
+      static_cast<void*>(subtitle_data));
+  ewkMediaSubtitleDataDelete(subtitle_data);
+}
+
+void EWebView::UpdateCurrentTime(double current_time) {
+  current_time_ = current_time;
+}
+
 void EWebView::NotifyParentalRatingInfo(const char* info, const char* url) {
   LOG(INFO) << "info:" << info << ",url:" << url;
   Ewk_Media_Parental_Rating_Info* data =
@@ -3404,6 +3460,36 @@ void EWebView::SetParentalRatingResult(const char* url, bool is_pass) {
   rwhva()->aura_efl_helper()->SetParentalRatingResult(
       static_cast<std::string>(url), is_pass);
 }
+void EWebView::NotifyFirstTimeStamp(unsigned long long timestamp,
+                                    int time_base_num,
+                                    int time_base_den) {
+  Ewk_First_Timestamp_Info* info =
+      ewkFirstTimeStampInfoCreate(timestamp, time_base_num, time_base_den);
+  SmartCallback<EWebViewCallbacks::FirstTimestamp>().call(
+      static_cast<void*>(info));
+  ewkFirstTimeStampInfoDelete(info);
+}
+
+void EWebView::NotifyPESData(const std::string& buf,
+                             unsigned int len,
+                             int media_position) {
+  const void* data = static_cast<const void*>(buf.c_str());
+  Ewk_PES_Info* info = ewkPESInfoCreate(data, len, media_position);
+  SmartCallback<EWebViewCallbacks::PESData>().call(static_cast<void*>(info));
+  ewkPESInfoDelete(info);
+}
+
+void EWebView::SetPreferSubtitleLang(const char* lang_list) {
+  LOG(INFO) << "SetPreferSubtitleLang: " << lang_list;
+  const std::string lang(lang_list ? lang_list : "");
+
+  if (!rwhva()) {
+    LOG(ERROR) << "rwhva() is null";
+    return;
+  }
+
+  rwhva()->aura_efl_helper()->SetPreferSubtitleLang(lang);
+}
 #endif
 
 bool EWebView::SetVisibility(bool enable) {
index ccfb65b..f6bf763 100644 (file)
@@ -804,7 +804,23 @@ class EWebView {
                                uint32_t current);
   void SetHighBitRate(Eina_Bool is_high_bitrate);
   bool IsHighBitRate() const { return is_high_bitrate_; }
-
+  void NotifyFirstTimeStamp(unsigned long long timestamp,
+                            int time_base_num,
+                            int time_base_den);
+  void NotifyPESData(const std::string& buf,
+                     unsigned int len,
+                     int media_position);
+  void SetPreferSubtitleLang(const char* lang_list);
+  void NotifySubtitleState(int state, double time_stamp);
+  void NotifySubtitlePlay(int active_track_id,
+                          const char* url,
+                          const char* lang);
+  void NotifySubtitleData(int track_id,
+                          double time_stamp,
+                          const std::string& data,
+                          unsigned int size);
+  void UpdateCurrentTime(double current_time);
+  double GetCurrentTime() { return current_time_; }
   void GetMediaDeviceList(Ewk_Media_Device_List_Get_Callback callback,
                           void* userData);
   using MediaDeviceEnumeration =
@@ -1024,6 +1040,7 @@ class EWebView {
     kPlaybackFinish,
     kPlaybackStop,
   };
+  double current_time_ = 0.0;
 #endif
 
   std::unique_ptr<_Ewk_Back_Forward_List> back_forward_list_;
index 11dea6a..0128cf1 100644 (file)
@@ -129,6 +129,15 @@ enum CallbackType {
   UserMediaState,
   PopupMenuShow,
   PopupMenuHide,
+  SubtitlePlay,
+  SubtitlePause,
+  SubtitleStop,
+  SubtitleResume,
+  SubtitleSeekStart,
+  SubtitleSeekComplete,
+  SubtitleNotifyData,
+  FirstTimestamp,
+  PESData,
 #endif
   OverscrolledLeft,
   OverscrolledRight,
@@ -307,6 +316,19 @@ DECLARE_EWK_VIEW_CALLBACK(PlaybackFinish,
 DECLARE_EWK_VIEW_CALLBACK(UserMediaState, "usermedia,state", void*);
 DECLARE_EWK_VIEW_CALLBACK(PopupMenuShow, "popup,menu,show", void);
 DECLARE_EWK_VIEW_CALLBACK(PopupMenuHide, "popup,menu,hide", void);
+DECLARE_EWK_VIEW_CALLBACK(SubtitlePlay, "notify,subtitle,play", void*);
+DECLARE_EWK_VIEW_CALLBACK(SubtitlePause, "notify,video,pause", void);
+DECLARE_EWK_VIEW_CALLBACK(SubtitleStop, "notify,subtitle,stop", void);
+DECLARE_EWK_VIEW_CALLBACK(SubtitleResume, "notify,video,resume", void);
+DECLARE_EWK_VIEW_CALLBACK(SubtitleSeekStart,
+                          "notify,subtitle,seek,start",
+                          double*);
+DECLARE_EWK_VIEW_CALLBACK(SubtitleSeekComplete,
+                          "notify,subtitle,seek,completed",
+                          void);
+DECLARE_EWK_VIEW_CALLBACK(SubtitleNotifyData, "on,subtitle,data", void*);
+DECLARE_EWK_VIEW_CALLBACK(FirstTimestamp, "on,dvb,subtitle,timestamp", void*);
+DECLARE_EWK_VIEW_CALLBACK(PESData, "on,dvb,subtitle,data", void*);
 #endif
 DECLARE_EWK_VIEW_CALLBACK(OverscrolledLeft, "overscrolled,left", void);
 DECLARE_EWK_VIEW_CALLBACK(OverscrolledRight, "overscrolled,right", void);
index 7c0cb73..f59fd0b 100644 (file)
 #include "build/build_config.h"
 #include "private/ewk_private.h"
 
+/* LCOV_EXCL_START */
+struct _Ewk_Media_Subtitle_Info {
+  int id;
+  const char* url;
+  const char* lang;
+  const char* label;
+};
+
+struct _Ewk_Media_Subtitle_Data {
+  int id;
+  double timestamp;
+  unsigned size;
+  const void* data;
+};
+
+struct _Ewk_First_Timestamp_Info {
+  unsigned long long timestamp;
+  int time_base_num;
+  int time_base_den;
+};
+
+struct _Ewk_PES_Info {
+  const void* data;
+  unsigned int len;
+  int media_position;
+};
+
 int ewk_media_subtitle_info_id_get(Ewk_Media_Subtitle_Info *data)
 {
-  LOG_EWK_API_MOCKUP();
+#if BUILDFLAG(IS_TIZEN_TV)
+  EINA_SAFETY_ON_NULL_RETURN_VAL(data, 0);
+  return data->id;
+#else
   return 0;
+#endif
 }
 
 const char* ewk_media_subtitle_info_url_get(Ewk_Media_Subtitle_Info *data)
 {
-  LOG_EWK_API_MOCKUP();
+#if BUILDFLAG(IS_TIZEN_TV)
+  EINA_SAFETY_ON_NULL_RETURN_VAL(data, NULL);
+  return data->url;
+#else
   return NULL;
+#endif
 }
 
 const char* ewk_media_subtitle_info_lang_get(Ewk_Media_Subtitle_Info *data)
 {
-  LOG_EWK_API_MOCKUP();
+#if BUILDFLAG(IS_TIZEN_TV)
+  EINA_SAFETY_ON_NULL_RETURN_VAL(data, NULL);
+  return data->lang;
+#else
   return NULL;
+#endif
 }
 
 const char* ewk_media_subtitle_info_label_get(Ewk_Media_Subtitle_Info *data)
 {
-  LOG_EWK_API_MOCKUP();
+#if BUILDFLAG(IS_TIZEN_TV)
+  EINA_SAFETY_ON_NULL_RETURN_VAL(data, NULL);
+  return data->label;
+#else
   return NULL;
+#endif
 }
 
 int ewk_media_subtitle_data_id_get(Ewk_Media_Subtitle_Data *data)
 {
-  LOG_EWK_API_MOCKUP();
+#if BUILDFLAG(IS_TIZEN_TV)
+  EINA_SAFETY_ON_NULL_RETURN_VAL(data, 0);
+  return data->id;
+#else
   return 0;
+#endif
 }
 
 double ewk_media_subtitle_data_timestamp_get(Ewk_Media_Subtitle_Data *data)
 {
-  LOG_EWK_API_MOCKUP();
+#if BUILDFLAG(IS_TIZEN_TV)
+  EINA_SAFETY_ON_NULL_RETURN_VAL(data, 0);
+  return data->timestamp;
+#else
   return 0;
+#endif
+
 }
 
 unsigned ewk_media_subtitle_data_size_get(Ewk_Media_Subtitle_Data *data)
 {
-  LOG_EWK_API_MOCKUP();
+#if BUILDFLAG(IS_TIZEN_TV)
+  EINA_SAFETY_ON_NULL_RETURN_VAL(data, 0);
+  return data->size;
+#else
   return 0;
+#endif
 }
 
 const void* ewk_media_subtitle_data_get(Ewk_Media_Subtitle_Data *data)
 {
-  LOG_EWK_API_MOCKUP();
+#if BUILDFLAG(IS_TIZEN_TV)
+  EINA_SAFETY_ON_NULL_RETURN_VAL(data, NULL);
+  return data->data;
+#else
   return NULL;
+#endif
 }
+/* LCOV_EXCL_STOP */
 
 Ewk_Media_Subtitle_Info* ewkMediaSubtitleInfoCreate(int id, const char* url, const char* lang, const char* label)
 {
 #if BUILDFLAG(IS_TIZEN_TV)
-  LOG_EWK_API_MOCKUP();
-  return NULL;
+  Ewk_Media_Subtitle_Info* subtitleInfo = new Ewk_Media_Subtitle_Info;
+  subtitleInfo->id = id;
+  subtitleInfo->url = eina_stringshare_add(url ? url : "");
+  subtitleInfo->lang = eina_stringshare_add(lang ? lang : "");
+  subtitleInfo->label = eina_stringshare_add(label ? label : "");
+  return subtitleInfo;
 #else
-  LOG_EWK_API_MOCKUP("Only for Tizen TV.");
   return NULL;
 #endif
 }
@@ -69,28 +133,91 @@ Ewk_Media_Subtitle_Info* ewkMediaSubtitleInfoCreate(int id, const char* url, con
 void ewkMediaSubtitleInfoDelete(Ewk_Media_Subtitle_Info* data)
 {
 #if BUILDFLAG(IS_TIZEN_TV)
-  LOG_EWK_API_MOCKUP();
+  if (!data)
+    return;
+  if (data->url)
+    eina_stringshare_del(data->url);
+  if (data->lang)
+    eina_stringshare_del(data->lang);
+  if (data->label)
+    eina_stringshare_del(data->label);
+  delete data;
 #else
-  LOG_EWK_API_MOCKUP("Only for Tizen TV.");
+  LOG(INFO)<<"Only for Tizen TV.";
 #endif
 }
 
 Ewk_Media_Subtitle_Data* ewkMediaSubtitleDataCreate(int id, double timestamp, const void* data, unsigned size)
 {
 #if BUILDFLAG(IS_TIZEN_TV)
-  LOG_EWK_API_MOCKUP();
-  return NULL;
+  Ewk_Media_Subtitle_Data* subtitleData = new Ewk_Media_Subtitle_Data;
+  subtitleData->id = id;
+  subtitleData->timestamp = timestamp;
+  subtitleData->size = size;
+  subtitleData->data = eina_binshare_add_length(data, size);
+  return subtitleData;
 #else
-  LOG_EWK_API_MOCKUP("Only for Tizen TV.");
-  return NULL;
+    return NULL;
 #endif
 }
 
 void ewkMediaSubtitleDataDelete(Ewk_Media_Subtitle_Data* data)
 {
 #if BUILDFLAG(IS_TIZEN_TV)
-  LOG_EWK_API_MOCKUP();
+  if (!data)
+    return;
+  if (data->data)
+    eina_binshare_del(data->data);
+  delete data;
+#else
+    LOG(INFO)<<"Only for Tizen TV.";
+#endif
+}
+
+Ewk_First_Timestamp_Info* ewkFirstTimeStampInfoCreate(unsigned long long timestamp,
+                                                      int time_base_num,
+                                                      int time_base_den) {
+#if BUILDFLAG(IS_TIZEN_TV)
+  Ewk_First_Timestamp_Info* info = new Ewk_First_Timestamp_Info;
+  info->timestamp = timestamp;
+  info->time_base_num = time_base_num;
+  info->time_base_den = time_base_den;
+  return info;
+#else
+  return NULL;
+#endif
+}
+
+void ewkFirstTimeStampInfoDelete(Ewk_First_Timestamp_Info* info) {
+#if BUILDFLAG(IS_TIZEN_TV)
+  delete info;
 #else
-  LOG_EWK_API_MOCKUP("Only for Tizen TV.");
+    LOG(INFO)<<"Only for Tizen TV.";
 #endif
 }
+
+Ewk_PES_Info* ewkPESInfoCreate(const void* data,
+                               unsigned int len,
+                               int media_position){
+#if BUILDFLAG(IS_TIZEN_TV)
+  Ewk_PES_Info* info = new Ewk_PES_Info;
+  info->data = eina_binshare_add_length(data, len);
+  info->len = len;
+  info->media_position = media_position;
+  return info;
+#else
+    return NULL;
+#endif
+}
+
+void ewkPESInfoDelete(Ewk_PES_Info* info){
+#if BUILDFLAG(IS_TIZEN_TV)
+  if (!info)
+    return;
+  if (info->data)
+    eina_binshare_del(info->data);
+  delete info;
+#else
+      LOG(INFO)<<"Only for Tizen TV.";
+#endif
+}
\ No newline at end of file
index 6036ad8..c02fd22 100644 (file)
@@ -40,6 +40,8 @@ extern "C" {
 #endif
 
 typedef struct _Ewk_Media_Subtitle_Info Ewk_Media_Subtitle_Info;
+typedef struct _Ewk_First_Timestamp_Info Ewk_First_Timestamp_Info;
+typedef struct _Ewk_PES_Info Ewk_PES_Info;
 
 /**
 * Get id of subtitle.
@@ -125,6 +127,17 @@ const void* data, unsigned size);
 
 void ewkMediaSubtitleDataDelete(Ewk_Media_Subtitle_Data* data);
 
+Ewk_First_Timestamp_Info* ewkFirstTimeStampInfoCreate(unsigned long long timestamp,
+                                                      int time_base_num,
+                                                      int time_base_den);
+
+void ewkFirstTimeStampInfoDelete(Ewk_First_Timestamp_Info* info);
+
+Ewk_PES_Info* ewkPESInfoCreate(const void* data,
+                               unsigned int len,
+                               int media_position);
+
+void ewkPESInfoDelete(Ewk_PES_Info* info);
 #ifdef __cplusplus
 }
 #endif
index 5870cb3..bcbecc9 100644 (file)
@@ -752,13 +752,25 @@ Eina_Bool ewk_settings_media_playback_notification_get(const Ewk_Settings* setti
 
 void ewk_settings_media_subtitle_notification_set(Ewk_Settings *settings, Eina_Bool enabled)
 {
-  LOG_EWK_API_MOCKUP();
+#if BUILDFLAG(IS_TIZEN_TV)
+  LOG(INFO) << "subtitle notification set enabled:" << (bool)enabled;
+  EINA_SAFETY_ON_NULL_RETURN(settings);
+  settings->getPreferences().media_subtitle_notification_enabled = (bool)enabled;
+  ewkUpdateWebkitPreferences(settings->ewk_view());
+#else
+  LOG_EWK_API_MOCKUP("Only for Tizen TV");
+#endif
 }
 
 Eina_Bool ewk_settings_media_subtitle_notification_get(const Ewk_Settings *settings)
 {
-  LOG_EWK_API_MOCKUP();
+#if BUILDFLAG(IS_TIZEN_TV)
+  EINA_SAFETY_ON_NULL_RETURN_VAL(settings, EINA_FALSE);
+  return settings->getPreferences().media_subtitle_notification_enabled;
+#else
+  LOG_EWK_API_MOCKUP("Only for Tizen TV");
   return EINA_FALSE;
+#endif
 }
 
 Eina_Bool ewk_settings_text_autosizing_scale_factor_set(Ewk_Settings* settings, double factor)
index 8a3054f..97c6c20 100644 (file)
@@ -1741,7 +1741,12 @@ void ewk_view_broadcast_decoder_set(
 
 void ewk_media_set_subtitle_lang(Evas_Object* ewkView, const char* lang_list)
 {
-  LOG_EWK_API_MOCKUP();
+#if BUILDFLAG(IS_TIZEN_TV)
+    EWK_VIEW_IMPL_GET_OR_RETURN(ewkView, impl);
+    impl->SetPreferSubtitleLang(lang_list);
+#else
+    LOG_EWK_API_MOCKUP("Only for Tizen TV.");
+#endif
 }
 
 void ewk_media_set_parental_rating_result(Evas_Object* ewkView, const char* url, Eina_Bool is_pass)
@@ -1766,8 +1771,13 @@ void ewk_media_start_with_high_bit_rate(Evas_Object* ewkView, Eina_Bool high_bit
 
 double ewk_view_media_current_time_get(const Evas_Object *o)
 {
-  LOG_EWK_API_MOCKUP();
+#if BUILDFLAG(IS_TIZEN_TV)
+  EWK_VIEW_IMPL_GET_OR_RETURN(o, impl, 0);
+  return impl->GetCurrentTime();
+#else
+  LOG_EWK_API_MOCKUP("Only for Tizen TV.");
   return 0;
+#endif
 }
 
 void ewk_view_request_canvas_fullscreen(Evas_Object* ewkView)
index 54d16b7..1357ccc 100644 (file)
@@ -769,6 +769,40 @@ void WebContentsDelegateEfl::UpdateTargetURL(WebContents* /*source*/,
   // Update latest hovered url.
   last_hovered_url_ = absolute_link_url;
 }
+
+void WebContentsDelegateEfl::UpdateCurrentTime(double current_time) {
+  web_view_->UpdateCurrentTime(current_time);
+}
+
+void WebContentsDelegateEfl::NotifySubtitleState(int state, double time_stamp) {
+  web_view_->NotifySubtitleState(state, time_stamp);
+}
+
+void WebContentsDelegateEfl::NotifySubtitlePlay(int active_track_id,
+                                                const std::string& url,
+                                                const std::string& lang) {
+  web_view_->NotifySubtitlePlay(active_track_id, url.c_str(), lang.c_str());
+}
+
+void WebContentsDelegateEfl::NotifySubtitleData(int track_id,
+                                                double time_stamp,
+                                                const std::string& data,
+                                                unsigned int size) {
+  web_view_->NotifySubtitleData(track_id, time_stamp, data, size);
+}
+
+void WebContentsDelegateEfl::NotifyFirstTimeStamp(unsigned long long timestamp,
+                                                  int time_base_num,
+                                                  int time_base_den) {
+  return web_view_->NotifyFirstTimeStamp(timestamp, time_base_num,
+                                         time_base_den);
+}
+
+void WebContentsDelegateEfl::NotifyPESData(const std::string& buf,
+                                           unsigned int len,
+                                           int media_position) {
+  return web_view_->NotifyPESData(buf, len, media_position);
+}
 #endif
 
 void WebContentsDelegateEfl::OnGetMainFrameScrollbarVisible(int callback_id,
index 4e57012..a4955c8 100644 (file)
@@ -155,6 +155,21 @@ class WebContentsDelegateEfl : public WebContentsDelegate {
 #if BUILDFLAG(IS_TIZEN_TV)
   void UpdateTargetURL(WebContents* source, const GURL& url) override;
   void ShowInspectorPortInfo();
+  void NotifyFirstTimeStamp(unsigned long long timestamp,
+                            int time_base_num,
+                            int time_base_den) override;
+  void NotifyPESData(const std::string& buf,
+                     unsigned int len,
+                     int media_position) override;
+  void UpdateCurrentTime(double current_time) override;
+  void NotifySubtitleState(int state, double time_stamp) override;
+  void NotifySubtitlePlay(int active_track_id,
+                          const std::string& url,
+                          const std::string& lang) override;
+  void NotifySubtitleData(int track_id,
+                          double time_stamp,
+                          const std::string& data,
+                          unsigned int size) override;
   void NotifyMediaStateChanged(uint32_t type,
                                uint32_t previous,
                                uint32_t current) override;