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_;
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;
}
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
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(
#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,
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_; }
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) {
#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(
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.
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)
"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
#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
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,
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 {
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;
#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
};
#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.
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;
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)
}
}
+#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) {
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) {
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);
#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|.
#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
// 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,
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
#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.
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) {
#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:
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
#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;
[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
[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,
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
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(
#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:
{"video/mpeg", "mpeg,mpg"},
#if BUILDFLAG(IS_TIZEN_TV)
{"application/dash+xml", "mpd"},
+ {"application/ttml+xml", "ttml"},
{"application/vnd.oipf.contentaccessstreaming+xml", "casd"},
#endif
};
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;
}
#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.
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);
};
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]
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.
[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);
kLoadTypeMax = kLoadTypeMediaStream,
};
+#if BUILDFLAG(IS_TIZEN_TV)
+ enum {
+ kSubtitlePlay,
+ kSubtitlePause,
+ kSubtitleSeekStart,
+ kSubtitleSeekComplete,
+ kSubtitleStop,
+ kSubtitleResume,
+ };
+#endif
+
typedef WebString TrackId;
enum TrackType { kTextTrack, kAudioTrack, kVideoTrack };
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
};
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;
#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:
#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)
// 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:
"$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",
"//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",
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>;
#if BUILDFLAG(IS_TIZEN_TV)
void SetParentalRatingResult(const String& url, bool is_pass);
+ void SetPreferTextLang(const String&);
#endif
#if DCHECK_IS_ON()
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(
bool CheckVideoPlaying() const;
void SetTranslatedURL(const String&);
void SetParentalRatingResult(const String& url, bool is_pass);
+ void SetPreferTextLang(const String&);
#endif
protected:
virtual String GetUrl() const { return ""; }
virtual void SetParentalRatingResult(bool) {}
virtual void SetTranslatedURL(const String&) {}
+ virtual void SetPreferTextLang(const String&) {}
#endif
void SetExecutionContext(ExecutionContext*) override;
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)
bool AllowFileAccessFromExternalURLs() override;
void SetMediaPlaybackNotificationEnabled(bool) override;
bool MediaPlaybackNotificationEnabled() override;
+ void SetMediaSubtitleNotificationEnabled(bool) override;
+ bool MediaSubtitleNotificationEnabled() override;
#endif
#if defined(TIZEN_ATK_SUPPORT)
}
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
#if BUILDFLAG(IS_TIZEN_TV)
bool IsVideoPlaying() const override;
void SetParentalRatingResult(const WebString&, bool) override;
+ void SetPreferTextLang(const WebString&) override;
#endif
PageScaleConstraintsSet& GetPageScaleConstraintsSet() const;
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;
}
#if BUILDFLAG(IS_TIZEN_TV)
bool media_playback_notification_enabled_ : 1 = false;
+ bool media_subtitle_notification_enabled_ : 1 = false;
#endif
#if BUILDFLAG(IS_EFL)
}
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() {
}
#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) {
// 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;
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.
"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",
#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
#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),
}
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 {
// 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();
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);
}
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);
}
web_media_player_->EnabledAudioTracksChanged(enabled_track_ids);
+#endif
}
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();
}
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(
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();
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());
}
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 {
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)
} // 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;
#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)
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;
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();
#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.
#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 {
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);
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);
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)) {
#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;
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;
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.
DCHECK(!cue->IsActive() || GetCueTimeline());
cue->SetTrack(nullptr);
+#if BUILDFLAG(IS_TIZEN_TV)
+ indexs_.erase(cue->index().ToInt());
+#endif
if (GetCueTimeline())
GetCueTimeline()->RemoveCue(this, cue);
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();
}
#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;
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,
};
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();
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>>&);
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_;
readonly attribute DOMString language;
readonly attribute DOMString id;
- // readonly attribute DOMString inBandMetadataTrackDispatchType;
+ readonly attribute DOMString inBandMetadataTrackDispatchType;
attribute TextTrackMode mode;
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;
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);
DispatchEventResult DispatchEventInternal(Event&) override;
private:
+#if BUILDFLAG(IS_TIZEN_TV)
+ AtomicString index_;
+#endif
AtomicString id_;
double start_time_;
double end_time_;
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
void Trace(Visitor*) const override;
+#if BUILDFLAG(IS_TIZEN_TV)
+ bool IsAllDisabledByApp();
+#endif
+
private:
void ScheduleTrackEvent(const AtomicString& event_name, TextTrack*);
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;
}
AtomicString label_;
AtomicString language_;
String id_;
+ AtomicString inband_metadata_track_dispatch_type_;
Member<HTMLMediaElement> media_element_;
};
} // 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 {
}
}
+#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;
}
#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() {
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;
},
{
name: "AudioVideoTracks",
- status: "experimental",
+ status: "stable",
base_feature: "none",
},
{
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() {
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,
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;
#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);
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
}
#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();
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_)
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,
#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"
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 = "",
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
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;
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();
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);
}
#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());
// 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,
#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) {
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);
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;
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);
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};
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)
#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";
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,
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)
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;
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() {
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;
}
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();
UpdateSeekableTime();
StartSeekableTimeUpdateTimer();
}
+
+ if (blink::IsHbbTV())
+ UpdatePreferAudio();
}
void MediaPlayerBridgeCapiTV::StartSeekableTimeUpdateTimer() {
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"
<< "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__;
// UpdateSeekableTime();
// StartSeekableTimeUpdateTimer();
}
- // UpdateAudioTrackInfo();
- // UpdateVideoTrackInfo();
- // UpdateTextTrackInfo();
+ UpdateAudioTrackInfo();
+ UpdateVideoTrackInfo();
+ UpdateTextTrackInfo();
UpdateDuration();
UpdateMediaType();
if (GetMediaType() == MediaType::Invalid) {
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
#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,
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:
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;
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();
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()};
#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"
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
#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"
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;
#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 = "",
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
#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)
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 =
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) {
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 =
kPlaybackFinish,
kPlaybackStop,
};
+ double current_time_ = 0.0;
#endif
std::unique_ptr<_Ewk_Back_Forward_List> back_forward_list_;
UserMediaState,
PopupMenuShow,
PopupMenuHide,
+ SubtitlePlay,
+ SubtitlePause,
+ SubtitleStop,
+ SubtitleResume,
+ SubtitleSeekStart,
+ SubtitleSeekComplete,
+ SubtitleNotifyData,
+ FirstTimestamp,
+ PESData,
#endif
OverscrolledLeft,
OverscrolledRight,
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);
#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
}
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
#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.
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
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)
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)
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)
// 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,
#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;