1 // Copyright 2023 Samsung Electronics Inc. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "media/filters/media_player_bridge_capi_tv.h"
7 #include "base/strings/string_split.h"
8 #include "media/base/efl/media_player_util_efl.h"
9 #include "third_party/blink/public/common/web_preferences/web_preferences.h"
10 #include "third_party/blink/public/platform/web_media_player.h"
11 #include "tizen_src/chromium_impl/media/filters/media_player_tizen_client.h"
13 #include <jsoncpp/json/json.h>
14 #include <vconf/vconf.h>
17 const int kSeekableTimeUpdateInterval = 500;
20 static void OnSubtitleDataCallback(unsigned long long time_stamp,
25 media::MediaPlayerBridgeCapiTV* player =
26 static_cast<media::MediaPlayerBridgeCapiTV*>(user_data);
28 const std::string info{static_cast<char*>(buffer)};
29 LOG(INFO) << " onSubtitleDataCallback : index=" << index
30 << ",time stamp=" << time_stamp << ",bufferSize=" << info.size();
32 constexpr size_t null_terminator_size = 1;
33 player->SubtitleDataCB(time_stamp, index, info,
34 info.size() + null_terminator_size);
38 static void PlayerPreLoadingCb(void* data) {
40 LOG(ERROR) << "input data is null";
43 media::MediaPlayerBridgeCapiTV* player =
44 static_cast<media::MediaPlayerBridgeCapiTV*>(data);
45 player->OnPlayerPreloading();
48 static void DrmErrorCb(int err_code, char* err_str, void* data) {
50 media::MediaPlayerBridgeCapiTV* player =
51 static_cast<media::MediaPlayerBridgeCapiTV*>(data);
53 player->OnDrmError(err_code, err_str);
56 static void OtherEventCb(int event_type, void* event_data, void* data) {
58 media::MediaPlayerBridgeCapiTV* player =
59 static_cast<media::MediaPlayerBridgeCapiTV*>(data);
60 player->OnOtherEvent(event_type, event_data);
63 #if TIZEN_VERSION_AT_LEAST(6, 0, 0)
64 static void FirstTimeStampCb(unsigned long long timestamp,
69 media::MediaPlayerBridgeCapiTV* player =
70 static_cast<media::MediaPlayerBridgeCapiTV*>(user_data);
71 player->OnFirstTimeStamp(timestamp, time_base_num, time_base_den);
74 static void TSSubtitleDataCb(int pid,
79 media::MediaPlayerBridgeCapiTV* player =
80 static_cast<media::MediaPlayerBridgeCapiTV*>(user_data);
82 player->OnTSSubtitleData(pid, data, len);
88 MediaPlayerBridgeCapiTV::MediaPlayerBridgeCapiTV(const GURL& url,
89 const std::string& user_agent,
91 : MediaPlayerBridgeCapi(url, user_agent, volume), weak_factory_(this) {
92 LOG_ID(INFO, GetPlayerId())
93 << "(" << static_cast<void*>(this) << ") " << __func__;
96 MediaPlayerBridgeCapiTV::~MediaPlayerBridgeCapiTV() {
97 LOG_ID(INFO, GetPlayerId())
98 << "(" << static_cast<void*>(this) << ") " << __func__;
99 weak_factory_.InvalidateWeakPtrs();
102 void MediaPlayerBridgeCapiTV::SetContentMimeType(const std::string& mime_type) {
103 LOG_ID(INFO, GetPlayerId()) << "(" << static_cast<void*>(this) << ") "
104 << __func__ << " mime_type : " << mime_type;
105 mime_type_ = mime_type;
108 void MediaPlayerBridgeCapiTV::Prepare() {
109 bool media_resource_acquired = false;
110 std::string translated_url;
111 std::string drm_info;
113 if (GetMediaPlayerClient())
114 GetMediaPlayerClient()->NotifyPlaybackState(
115 kPlaybackLoad, player_id_, url_.spec(), mime_type_,
116 &media_resource_acquired, &translated_url, &drm_info);
118 LOG_ID(INFO, GetPlayerId())
119 << "media_resource_acquired: " << media_resource_acquired
120 << ",translated_url:" << translated_url << ",drm_info: " << drm_info;
122 if (mime_type_.find("application/vnd.oipf.contentaccessstreaming+xml") !=
124 LOG_ID(INFO, GetPlayerId())
125 << "CASD url,waiting for hbbtv parse the real url and set "
130 if (GetMediaPlayerClient() &&
131 GetMediaPlayerClient()->PlaybackNotificationEnabled() &&
133 #if !defined(TIZEN_MULTIMEDIA_DRMMANAGER_SUPPORT)
134 if (!SetDrmInfo(drm_info)) {
135 LOG_ID(ERROR, GetPlayerId()) << "SetDrmInfo failed";
139 if (!translated_url.empty())
140 url_ = media::GetCleanURL(translated_url);
143 if (blink::IsHbbTV()) {
144 GetUserPreferAudioLanguage();
146 if (url_.spec().find(".mpd") != std::string::npos)
147 stream_type_ = DASH_STREAM;
148 else if (url_.spec().find(".m3u") != std::string::npos)
149 stream_type_ = HLS_STREAM;
150 else if (mime_type_.find("application/dash+xml") != std::string::npos) {
151 char steaming_type_dash[] = "DASH";
152 char steaming_type_dash_ex[] = "DASHEX";
153 player_set_streaming_type(
154 player_, blink::IsHbbTV() ? steaming_type_dash_ex : steaming_type_dash);
155 stream_type_ = DASH_STREAM;
158 if (blink::IsHbbTV() && !is_preloaded_) {
159 int ret = player_set_others_event_cb(player_, OtherEventCb, this);
160 if (ret != PLAYER_ERROR_NONE)
161 LOG(ERROR) << "player_set_others_event_cb() failed";
162 #if TIZEN_VERSION_AT_LEAST(6, 0, 0)
163 if (stream_type_ == TS_STREAM) {
164 if (prefer_subtitle_lang_ == "") {
165 prefer_subtitle_lang_ = "und";
166 player_set_ini_param(player_, "set_subtitle_language = und");
168 if (prefer_subtitle_lang_ != "off") {
169 //-999 means invalid pes id, MM will decide use which pes id
170 player_set_pes_cb(player_, -999, TSSubtitleDataCb, this);
171 player_set_first_timestamp_callback(player_, FirstTimeStampCb, this);
176 if (blink::IsHbbTV() && CheckHighBitRate() && stream_type_ == DASH_STREAM)
177 AppendUrlHighBitRate(url_.spec());
178 player_prepared_ = false;
180 parental_rating_pass_ = true;
181 MediaPlayerBridgeCapi::Prepare();
182 if (GetMediaPlayerClient())
183 GetMediaPlayerClient()->NotifyPlaybackState(kPlaybackReady, player_id_);
186 void MediaPlayerBridgeCapiTV::Release() {
187 is_preloaded_ = false;
188 player_prepared_ = false;
189 StopSeekableTimeUpdateTimer();
190 MediaPlayerBridgeCapi::Release();
191 if (GetMediaPlayerClient())
192 GetMediaPlayerClient()->NotifyPlaybackState(kPlaybackStop, player_id_);
193 NotifySubtitleState(blink::WebMediaPlayer::kSubtitleStop);
194 pending_active_text_track_id_ = active_text_track_id_;
195 pending_active_audio_track_id_ = active_audio_track_id_;
196 pending_active_video_track_id_ = active_video_track_id_;
197 active_audio_track_id_ = -1;
198 active_video_track_id_ = -1;
199 active_text_track_id_ = -1;
200 #if TIZEN_VERSION_AT_LEAST(6, 0, 0)
201 player_unset_pes_cb(player_, -999);
205 bool MediaPlayerBridgeCapiTV::Play() {
206 LOG_ID(INFO, GetPlayerId())
207 << "(" << static_cast<void*>(this) << ") " << __func__
208 << ",current_time:" << GetCurrentTime().InSecondsF();
210 // HBBTV run in preloading and preplay mode. If no prepread do prepare
211 // in PlayerPrePlay(), otherwise do normal Play.
212 if (blink::IsHbbTV() && !player_prepared_) {
213 if (!PlayerPrePlay())
214 LOG_ID(ERROR, GetPlayerId()) << "HBBTV prePlay fail.";
218 if (blink::IsHbbTV() && !parental_rating_pass_) {
219 LOG_ID(INFO, GetPlayerId())
220 << "parental rating authenticatoin is not pass yet,waiting...";
221 delayed_player_state_ = PLAYER_STATE_DELAYED_PLAY;
222 MediaPlayerBridgeCapi::ExecuteDelayedPlayerState();
226 if (!MediaPlayerBridgeCapi::Play())
228 if (blink::IsHbbTV()) {
232 LOG_ID(INFO, player_id_) << "pending_active_text_track_id_:"
233 << pending_active_text_track_id_
234 << " active_text_track_id_ " << active_text_track_id_
235 << " pending_active_audio_track_id_ "
236 << pending_active_audio_track_id_
237 << " active_audio_track_id_ "
238 << active_audio_track_id_
239 << " pending_active_video_track_id_ "
240 << pending_active_video_track_id_
241 << " active_video_track_id_ "
242 << active_video_track_id_;
244 if (pending_active_text_track_id_ != -1 && active_text_track_id_ == -1) {
245 active_text_track_id_ = pending_active_text_track_id_;
246 pending_active_text_track_id_ = -1;
249 if (pending_active_audio_track_id_ != -1 && active_audio_track_id_ == -1) {
250 SetActiveAudioTrack(pending_active_audio_track_id_);
251 pending_active_audio_track_id_ = -1;
254 if (pending_active_video_track_id_ != -1 && active_video_track_id_ == -1) {
255 SetActiveVideoTrack(pending_active_video_track_id_);
256 pending_active_video_track_id_ = -1;
259 if (GetMediaPlayerClient())
260 GetMediaPlayerClient()->NotifyPlaybackState(kPlaybackStart, player_id_);
261 NotifySubtitleState(blink::WebMediaPlayer::kSubtitlePlay);
265 void MediaPlayerBridgeCapiTV::Pause(bool is_media_related_action) {
266 if (!player_prepared_) {
267 LOG_ID(INFO, GetPlayerId())
268 << "(" << static_cast<void*>(this)
269 << "), pause while player is not prepared, pause delay";
270 delayed_player_state_ = PLAYER_STATE_DELAYED_PAUSE;
273 MediaPlayerBridgeCapi::Pause(is_media_related_action);
274 NotifySubtitleState(blink::WebMediaPlayer::kSubtitlePause);
277 void MediaPlayerBridgeCapiTV::PlaybackCompleteUpdate() {
278 MediaPlayerBridgeCapi::PlaybackCompleteUpdate();
279 if (GetMediaPlayerClient()) {
280 GetMediaPlayerClient()->NotifyPlaybackState(kPlaybackFinish, player_id_);
281 GetMediaPlayerClient()->UpdateCurrentTime(
282 MediaPlayerBridgeCapi::GetCurrentTime());
284 GetMediaPlayerClient()->OnLivePlaybackComplete();
287 NotifySubtitleState(blink::WebMediaPlayer::kSubtitleStop);
290 void MediaPlayerBridgeCapiTV::Seek(base::TimeDelta time,
291 base::OnceClosure seek_cb) {
292 LOG_ID(INFO, player_id_) << "(" << static_cast<void*>(this) << ") "
293 << __func__ << " time: " << time.InSecondsF();
295 seek_cb_ = std::move(seek_cb);
296 if (IsPlayerSuspended() && playback_time_ != time) {
297 playback_time_ = time;
298 delayed_player_state_ = PLAYER_STATE_DELAYED_SEEK;
299 pending_seek_duration_ = playback_time_;
300 OnTimeUpdate(player_id_, playback_time_);
301 OnTimeChanged(player_id_);
306 MediaPlayerBridgeCapi::SeekInternal(time);
307 NotifySubtitleState(blink::WebMediaPlayer::kSubtitleSeekStart,
311 void MediaPlayerBridgeCapiTV::SubtitleDataCB(long long time_stamp,
313 const std::string& buffer,
314 unsigned buffer_size) {
315 task_runner_->PostTask(
316 FROM_HERE, base::BindOnce(&MediaPlayerBridgeCapiTV::NotifySubtitleData,
317 weak_factory_.GetWeakPtr(), index, time_stamp,
318 buffer, buffer_size));
321 void MediaPlayerBridgeCapiTV::NotifySubtitlePlay(int id,
322 const std::string& url,
323 const std::string& lang) {
324 if (!GetMediaPlayerClient()) {
325 LOG(ERROR) << "MediaPlayerClient is null";
328 content::WebContentsDelegate* web_contents_delegate =
329 GetMediaPlayerClient()->GetWebContentsDelegate();
330 if (!web_contents_delegate)
333 web_contents_delegate->NotifySubtitlePlay(id, url, lang);
336 void MediaPlayerBridgeCapiTV::NotifySubtitleData(int track_id,
338 const std::string& data,
340 content::WebContentsDelegate* web_contents_delegate =
341 GetMediaPlayerClient()->GetWebContentsDelegate();
343 if (!web_contents_delegate) {
344 LOG(ERROR) << "web_contents_delegate is null";
348 web_contents_delegate->NotifySubtitleData(track_id, time_stamp, data, size);
351 void MediaPlayerBridgeCapiTV::NotifySubtitleState(int new_state,
353 if (!blink::IsHbbTV() || !GetMediaPlayerClient() ||
354 !GetMediaPlayerClient()->SubtitleNotificationEnabled() ||
355 subtitle_state_ == new_state) {
357 << " MediaPlayerBridgeCapiTV::NotifySubtitleState null condition ";
361 content::WebContentsDelegate* web_contents_delegate =
362 GetMediaPlayerClient()->GetWebContentsDelegate();
363 if (!web_contents_delegate) {
364 LOG(ERROR) << "web_contents_delegate is null";
368 // Workaround. Use subtitle state machine only when player has
369 // activated a text_track. Right now, subtitle state machine
370 // is shared between players, so any Player A notification
371 // influences Player B notification, which causes issues.
372 // This workaround won't work when two players have activated a text_track.
373 if (active_text_track_id_ == -1) {
374 LOG(ERROR) << "active_text_track_id_==-1";
378 int old_state = subtitle_state_;
379 if (new_state != blink::WebMediaPlayer::kSubtitleSeekStart &&
380 new_state != blink::WebMediaPlayer::kSubtitleSeekComplete)
381 subtitle_state_ = new_state;
383 LOG(INFO) << "subtitle state transision:"
384 << "new_state=" << new_state << ", old_state=" << old_state
385 << ", subtitle_state=" << subtitle_state_
386 << ", time_stamp=" << time_stamp;
389 case blink::WebMediaPlayer::kSubtitlePlay:
390 if (old_state == blink::WebMediaPlayer::kSubtitlePause)
391 web_contents_delegate->NotifySubtitleState(
392 blink::WebMediaPlayer::kSubtitleResume);
396 case blink::WebMediaPlayer::kSubtitlePause:
397 if (old_state != blink::WebMediaPlayer::kSubtitleStop)
398 web_contents_delegate->NotifySubtitleState(new_state);
400 case blink::WebMediaPlayer::kSubtitleStop:
403 case blink::WebMediaPlayer::kSubtitleSeekStart:
404 web_contents_delegate->NotifySubtitleState(new_state, time_stamp);
406 case blink::WebMediaPlayer::kSubtitleSeekComplete:
407 web_contents_delegate->NotifySubtitleState(new_state);
415 void MediaPlayerBridgeCapiTV::NotifyPlayTrack() {
416 if (active_text_track_id_ == -1 ||
417 subtitle_state_ == blink::WebMediaPlayer::kSubtitleStop)
419 if (is_inband_text_track_) {
420 // process select player's track ...
421 UpdateActiveTextTrack(active_text_track_id_);
422 NotifySubtitlePlay(active_text_track_id_, blink::WebString().Utf8(),
423 blink::WebString().Utf8());
425 // get outband track info and then NotifyPlayTrack
426 LOG_ID(INFO, player_id_) << __func__;
428 if (GetMediaPlayerClient())
429 GetMediaPlayerClient()->NotifyTrackInfoToBrowser(active_text_track_id_);
433 void MediaPlayerBridgeCapiTV::NotifyStopTrack() {
434 active_text_track_id_ = -1;
435 if (is_inband_text_track_)
436 UpdateActiveTextTrack(active_text_track_id_);
438 is_inband_text_track_ = false;
439 if (!GetMediaPlayerClient()) {
440 LOG(ERROR) << "MediaPlayerClient is null";
443 content::WebContentsDelegate* web_contents_delegate =
444 GetMediaPlayerClient()->GetWebContentsDelegate();
445 if (!web_contents_delegate) {
446 LOG(ERROR) << "web contents delegate is null";
450 web_contents_delegate->NotifySubtitleState(
451 blink::WebMediaPlayer::kSubtitleStop);
454 void MediaPlayerBridgeCapiTV::UpdateActiveTextTrack(int id) {
455 int ret = PLAYER_ERROR_NONE;
459 LOG_ID(INFO, player_id_) << "UpdateActiveTextTrack id=-1";
464 int err = player_get_track_count(player_, PLAYER_STREAM_TYPE_TEXT, &count);
465 if (err != PLAYER_ERROR_NONE || count <= 0 || id >= count) {
466 LOG(ERROR) << "player_get_track_count err,ret=" << ret
467 << ",count=" << count;
471 ret = player_select_track_ex(player_, PLAYER_STREAM_TYPE_TEXT, id,
472 -1); //-1 means use the default mode for
473 // mmplayer demuxer to select stream
474 if (ret != PLAYER_ERROR_NONE) {
475 LOG(ERROR) << "player_select_track_ex err,ret=" << ret;
480 void MediaPlayerBridgeCapiTV::OnCurrentTimeUpdateTimerFired() {
481 MediaPlayerBridgeCapi::OnCurrentTimeUpdateTimerFired();
482 if (!GetMediaPlayerClient()) {
483 LOG(ERROR) << "media player client is null";
486 GetMediaPlayerClient()->UpdateCurrentTime(
487 MediaPlayerBridgeCapi::GetCurrentTime());
490 void MediaPlayerBridgeCapiTV::SeekCompleteUpdate() {
491 MediaPlayerBridgeCapi::SeekCompleteUpdate();
492 NotifySubtitleState(blink::WebMediaPlayer::kSubtitleSeekComplete);
495 void MediaPlayerBridgeCapiTV::OnResumeComplete(bool success) {
496 LOG(INFO) << __func__ << ", success: " << success;
497 MediaPlayerBridgeCapi::OnResumeComplete(success);
499 if (!GetMediaPlayerClient()) {
500 LOG(ERROR) << "media player client is null";
505 GetMediaPlayerClient()->UpdateCurrentTime(
506 MediaPlayerBridgeCapi::GetCurrentTime());
509 void MediaPlayerBridgeCapiTV::PlayerPrepared() {
510 player_prepared_ = true;
511 MediaPlayerBridgeCapi::PlayerPrepared();
514 int retVal = player_seek_available(player_, &canSeek);
515 if (retVal == PLAYER_ERROR_NONE && !canSeek)
516 is_player_seek_available_ = false;
518 GetAdaptiveStreamingInfo();
519 if (!blink::IsHbbTV() && is_live_stream_) {
520 UpdateSeekableTime();
521 StartSeekableTimeUpdateTimer();
524 if (blink::IsHbbTV())
528 void MediaPlayerBridgeCapiTV::StartSeekableTimeUpdateTimer() {
529 if (!seekable_time_update_timer_.IsRunning()) {
530 seekable_time_update_timer_.Start(
531 FROM_HERE, base::Milliseconds(kSeekableTimeUpdateInterval), this,
532 &MediaPlayerBridgeCapiTV::OnSeekableTimeUpdateTimerFired);
536 void MediaPlayerBridgeCapiTV::StopSeekableTimeUpdateTimer() {
537 if (seekable_time_update_timer_.IsRunning())
538 seekable_time_update_timer_.Stop();
541 void MediaPlayerBridgeCapiTV::OnSeekableTimeUpdateTimerFired() {
542 UpdateSeekableTime();
545 void MediaPlayerBridgeCapiTV::GetAdaptiveStreamingInfo() {
546 int ret = player_get_adaptive_streaming_info(player_, &is_live_stream_,
547 PLAYER_ADAPTIVE_INFO_IS_LIVE);
548 if (ret != PLAYER_ERROR_NONE || is_live_stream_) {
549 LOG_ID(INFO, GetPlayerId()) << "(" << static_cast<void*>(this) << ") "
550 << __func__ << " A live stream.";
554 void MediaPlayerBridgeCapiTV::UpdateSeekableTime() {
555 if (GetPlayerState() == PLAYER_STATE_NONE || !is_live_stream_)
558 int64_t min = 0, max = 0;
559 if (GetLiveStreamingDuration(&min, &max)) {
560 if (min_seekable_time_.InMilliseconds() != min ||
561 max_seekable_time_.InMilliseconds() != max) {
562 min_seekable_time_ = base::Milliseconds(min);
563 max_seekable_time_ = base::Milliseconds(max);
564 if (GetMediaPlayerClient())
565 GetMediaPlayerClient()->OnSeekableTimeChange(
566 min_seekable_time_, max_seekable_time_, is_live_stream_);
572 GetAdaptiveStreamingInfo();
573 if (!is_live_stream_) {
574 LOG_ID(INFO, GetPlayerId()) << "(" << static_cast<void*>(this) << ") "
575 << __func__ << " changed to static stream";
576 if (GetMediaPlayerClient())
577 GetMediaPlayerClient()->OnSeekableTimeChange({}, {}, is_live_stream_);
578 MediaPlayerBridgeCapi::UpdateDuration();
582 bool MediaPlayerBridgeCapiTV::GetLiveStreamingDuration(int64_t* min,
586 constexpr const size_t kDurationBufferSize = 64;
587 char live_duration[kDurationBufferSize] = {
590 char* live_ptr = live_duration;
591 const auto err = player_get_adaptive_streaming_info(
592 player_, &live_ptr, PLAYER_ADAPTIVE_INFO_LIVE_DURATION);
593 if (err != PLAYER_ERROR_NONE) {
594 LOG(ERROR) << "(" << static_cast<void*>(this) << ") " << __func__
595 << " |player_get_adaptive_streaming_info| failed " << err;
599 const std::string duration(live_duration);
600 const std::string::size_type delimiter = duration.find('|');
601 if (delimiter == std::string::npos) {
602 LOG_ID(ERROR, GetPlayerId())
603 << "(" << static_cast<void*>(this) << ") " << __func__
604 << " Failed to find delimiter | in duration: " << duration;
608 const std::string duration_min = duration.substr(0, delimiter);
609 if (duration_min.empty()) {
610 LOG_ID(ERROR, GetPlayerId())
611 << "(" << static_cast<void*>(this) << ") " << __func__
612 << " Failed empty min sub str: " << duration << ", " << delimiter;
617 if (!base::StringToInt64(duration_min, &out_min)) {
618 LOG_ID(ERROR, GetPlayerId())
619 << "(" << static_cast<void*>(this) << ") " << __func__
620 << " Failed to get min from duration: " << duration;
624 const std::string duration_max = duration.substr(delimiter + 1);
625 if (duration_max.empty()) {
626 LOG_ID(ERROR, GetPlayerId())
627 << "(" << static_cast<void*>(this) << ") " << __func__
628 << " empty max sub str: " << duration << ", " << delimiter;
633 if (!base::StringToInt64(duration_max, &out_max)) {
634 LOG_ID(ERROR, GetPlayerId())
635 << "(" << static_cast<void*>(this) << ") " << __func__
636 << " Failed to get max from duration: " << duration;
645 void MediaPlayerBridgeCapiTV::ParseDashInfo() {
646 std::string dash_info = GetDashInfo();
647 Json::CharReaderBuilder builder;
648 Json::CharReader* reader(builder.newCharReader());
651 if (reader->parse(dash_info.c_str(), dash_info.c_str() + dash_info.length(),
653 mrs_url_ = value["mrsUrl"].asString();
654 std::string periodId = value["periodId"].asString();
656 content_id_ = clean_url_ + "#period=" + periodId;
658 LOG(INFO) << "mrsUrl: " << mrs_url_ << ",contentId: " << content_id_;
661 std::string MediaPlayerBridgeCapiTV::GetDashInfo() {
662 char* dash_info = nullptr;
664 // {"type":0,"minBufferTime":4000,"mrsUrl":"","periodId":"first"}
665 const int ret = player_get_dash_info(player_, &dash_info);
666 if (ret != PLAYER_ERROR_NONE) {
669 LOG(ERROR) << "Fail to call player_get_dash_info,ret:" << ret;
674 LOG(ERROR) << "empty dash_info.";
678 const std::string info(dash_info);
680 LOG(INFO) << "dash info str: " << info;
685 bool MediaPlayerBridgeCapiTV::GetDashLiveDuration(int64_t* duration) {
687 std::string dash_info = GetDashInfo();
688 Json::CharReaderBuilder builder;
689 Json::CharReader* reader(builder.newCharReader());
691 int64_t out_duration = 0;
693 if (reader->parse(dash_info.c_str(), dash_info.c_str() + dash_info.length(),
695 out_duration = value["mediaPresentationDuration"].asInt();
698 // According to dash spec, if duration == -1, set max time as duration.
699 if (out_duration == -1)
700 out_duration = base::TimeDelta::Max().InMilliseconds();
701 *duration = out_duration;
706 void MediaPlayerBridgeCapiTV::HandleBufferingStatus(int percent) {
707 if (is_paused_ || is_seeking_)
710 if (percent == 100) {
711 LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__;
712 is_buffering_compeleted_ = true;
713 if (MediaPlayerBridgeCapi::GetPlayerState() != PLAYER_STATE_PAUSED)
715 if (player_start(player_) != PLAYER_ERROR_NONE) {
716 LOG(ERROR) << "|player_start| failed";
720 if (is_buffering_compeleted_ && blink::IsHbbTV())
724 MediaPlayerBridgeCapi::StartBufferingUpdateTimer();
726 MediaPlayerBridgeCapi::OnReadyStateChange(
727 player_id_, blink::WebMediaPlayer::kReadyStateHaveEnoughData);
729 is_buffering_compeleted_ = false;
730 if (GetPlayerState() != PLAYER_STATE_PLAYING)
732 if (player_pause(player_) != PLAYER_ERROR_NONE) {
733 LOG(ERROR) << "|player_pause| failed";
737 MediaPlayerBridgeCapi::StopCurrentTimeUpdateTimer();
738 MediaPlayerBridgeCapi::OnReadyStateChange(
739 player_id_, blink::WebMediaPlayer::kReadyStateHaveCurrentData);
741 MediaPlayerBridgeCapi::OnNetworkStateChange(
742 player_id_, blink::WebMediaPlayer::kNetworkStateLoading);
745 void MediaPlayerBridgeCapiTV::AppendUrlHighBitRate(const std::string& url) {
746 // don't use url.append("|STARTBITRATE=HIGHEST") to get hbbtv url
747 // "|" will be replaced with "%7C"
748 const char high_bitrate[] = "|STARTBITRATE=HIGHEST";
749 int len = url.length() + strlen(high_bitrate) + 1;
750 char* str_url = new char[len];
755 memset(str_url, 0, len);
756 strncat(str_url, url.c_str(), url.length());
757 strncat(str_url, high_bitrate, strlen(high_bitrate));
758 hbbtv_url_ = str_url;
760 LOG_ID(INFO, GetPlayerId()) << "hbbtv url:" << hbbtv_url_.c_str();
763 bool MediaPlayerBridgeCapiTV::CheckHighBitRate() {
764 if (!GetMediaPlayerClient()) {
765 LOG_ID(ERROR, GetPlayerId()) << "MediaPlayerClient is null";
768 content::WebContentsDelegate* web_contents_delegate =
769 GetMediaPlayerClient()->GetWebContentsDelegate();
770 if (!web_contents_delegate) {
771 LOG_ID(ERROR, GetPlayerId()) << "get web_contents_delegate fail";
774 bool ret = web_contents_delegate->IsHighBitRate();
775 LOG_ID(INFO, GetPlayerId()) << "get high bit rate: " << std::boolalpha << ret;
779 void MediaPlayerBridgeCapiTV::HandleDownloadableFontInfo(
780 const std::string& scheme_id_uri,
781 const std::string& value,
782 const std::string& data,
784 content::WebContentsDelegate* web_contents_delegate =
785 GetMediaPlayerClient()->GetWebContentsDelegate();
786 if (!web_contents_delegate)
788 web_contents_delegate->NotifyDownloadableFontInfo(scheme_id_uri, value, data,
792 bool MediaPlayerBridgeCapiTV::PreloadIfNeeded(int& ret) {
793 LOG_ID(INFO, GetPlayerId())
794 << "PreloadIfNeeded, is_preloaded_ " << is_preloaded_;
795 if (blink::IsHbbTV() && !is_preloaded_) {
796 ret = player_preloading_async(player_, -1, PlayerPreLoadingCb, this);
800 // fixup : kPlaybackReady status need checked by HBBTVResourceAcquired() patch
801 if (GetMediaPlayerClient())
802 GetMediaPlayerClient()->NotifyPlaybackState(kPlaybackReady, player_id_);
804 LOG_ID(ERROR, GetPlayerId()) << "(" << static_cast<void*>(this)
805 << "), GetMediaPlayerClient return null";
806 SetDisplayAtPausedState();
810 void MediaPlayerBridgeCapiTV::SetDisplayAtPausedState() {
811 int ret = PLAYER_ERROR_NONE;
812 if (!pending_seek_duration_.is_zero())
813 ret = player_display_video_at_paused_state(player_, false);
815 ret = player_display_video_at_paused_state(player_, true);
817 if (ret != PLAYER_ERROR_NONE)
818 LOG_ID(ERROR, GetPlayerId())
819 << "player_display_video_at_paused_state() failed";
822 #if TIZEN_VERSION_AT_LEAST(6, 0, 0)
823 void MediaPlayerBridgeCapiTV::HandleFirstTimeStamp(unsigned long long timestamp,
826 LOG_ID(INFO, player_id_) << "HandleFirstTimeStamp,timestamp:" << timestamp
827 << ",time_base_num:" << time_base_num
828 << ",time_base_den:" << time_base_den;
829 NotifyFirstTimeStamp(timestamp, time_base_num, time_base_den);
832 void MediaPlayerBridgeCapiTV::HandleTSSubtitleData(int pid,
833 const std::string& buf,
835 NotifyPESData(buf, len, GetCurrentTime().InMilliseconds());
838 void MediaPlayerBridgeCapiTV::OnFirstTimeStamp(unsigned long long timestamp,
841 task_runner_->PostTask(
842 FROM_HERE, base::BindOnce(&MediaPlayerBridgeCapiTV::HandleFirstTimeStamp,
843 weak_factory_.GetWeakPtr(), timestamp,
844 time_base_num, time_base_den));
847 void MediaPlayerBridgeCapiTV::OnTSSubtitleData(int pid,
850 // maybe prefer subtitle lang changed
851 if (prefer_subtitle_lang_ == "off")
855 LOG(ERROR) << "invalid data";
859 std::string buf((char*)data);
860 task_runner_->PostTask(
861 FROM_HERE, base::BindOnce(&MediaPlayerBridgeCapiTV::HandleTSSubtitleData,
862 weak_factory_.GetWeakPtr(), pid, buf, len));
865 void MediaPlayerBridgeCapiTV::NotifyFirstTimeStamp(unsigned long long timestamp,
868 if (!GetMediaPlayerClient()) {
869 LOG(ERROR) << "MediaPlayerClient is null";
872 if (!blink::IsHbbTV() ||
873 !GetMediaPlayerClient()->SubtitleNotificationEnabled())
875 content::WebContentsDelegate* web_contents_delegate =
876 GetMediaPlayerClient()->GetWebContentsDelegate();
877 if (!web_contents_delegate) {
878 LOG(ERROR) << "web contents delegate is null";
881 web_contents_delegate->NotifyFirstTimeStamp(timestamp, time_base_num,
885 void MediaPlayerBridgeCapiTV::NotifyPESData(const std::string& buf,
887 int media_position) {
888 if (!GetMediaPlayerClient()) {
889 LOG(ERROR) << "MediaPlayerClient is null";
892 if (!blink::IsHbbTV() ||
893 !GetMediaPlayerClient()->SubtitleNotificationEnabled())
895 content::WebContentsDelegate* web_contents_delegate =
896 GetMediaPlayerClient()->GetWebContentsDelegate();
897 if (!web_contents_delegate) {
898 LOG(ERROR) << "web contents delegate is null";
901 web_contents_delegate->NotifyPESData(buf, len, media_position);
905 void MediaPlayerBridgeCapiTV::UpdateDuration() {
906 LOG_ID(INFO, GetPlayerId())
907 << "(" << static_cast<void*>(this) << ") " << __func__;
908 if (blink::IsHbbTV() && !is_preloaded_) {
909 LOG_ID(INFO, GetPlayerId())
910 << "HBBTV preload not finished, no need update duration. ";
913 if (is_live_stream_) {
914 int64_t duration = 0;
915 if (stream_type_ == HLS_STREAM) {
917 if (!GetLiveStreamingDuration(&min, &duration)) {
918 LOG(ERROR) << "Fail to get duration for hls live stream.";
921 } else if (stream_type_ == DASH_STREAM) {
922 if (!GetDashLiveDuration(&duration)) {
923 if (duration_ != base::TimeDelta::Max()) {
924 duration_ = base::TimeDelta::Max();
925 OnDurationChange(player_id_, duration_.InSecondsF());
930 LOG(ERROR) << "Unknown live stream type : " << stream_type_;
934 LOG(WARNING) << "live stream type : convert duration to max";
935 duration_ = base::TimeDelta::Max();
936 OnDurationChange(player_id_, duration_.InSecondsF());
937 } else if (duration_.InSecondsF() !=
938 ConvertMilliSecondsToSeconds(duration)) {
939 duration_ = base::Milliseconds(duration);
940 OnDurationChange(player_id_, duration_.InSecondsF());
942 } else { // non-live stream sequence
943 MediaPlayerBridgeCapi::UpdateDuration();
947 void MediaPlayerBridgeCapiTV::UpdateMediaType() {
948 LOG_ID(INFO, GetPlayerId())
949 << "(" << static_cast<void*>(this) << ") " << __func__;
951 if (blink::IsHbbTV() && !is_preloaded_) {
952 LOG_ID(INFO, GetPlayerId())
953 << "HBBTV preload not finished, no need update media type. ";
956 MediaPlayerBridgeCapi::UpdateMediaType();
959 bool MediaPlayerBridgeCapiTV::CheckLiveStreaming() const {
961 int retVal = player_get_adaptive_streaming_info(player_, &isLive,
962 PLAYER_ADAPTIVE_INFO_IS_LIVE);
963 if (retVal != PLAYER_ERROR_NONE) {
964 LOG(ERROR) << "player_get_adaptive_streaming_info failed, error: "
972 LOG(INFO) << "This is a live streaming.";
976 void MediaPlayerBridgeCapiTV::OnPlayerPreloading() {
977 task_runner_->PostTask(
978 FROM_HERE, base::BindOnce(&MediaPlayerBridgeCapiTV::PlayerPreloaded,
979 weak_factory_.GetWeakPtr()));
982 bool MediaPlayerBridgeCapiTV::HBBTVResourceAcquired() {
983 bool media_resource_acquired = false;
984 if (!GetMediaPlayerClient()) {
985 LOG_ID(ERROR, GetPlayerId()) << "MediaPlayerTizenClient is nullptr";
989 GetMediaPlayerClient()->NotifyPlaybackState(
990 kPlaybackReady, player_id_, url_.spec(), mime_type_,
991 &media_resource_acquired, NULL, NULL);
992 if (!media_resource_acquired) {
993 GetMediaPlayerClient()->NotifyPlaybackState(kPlaybackStop, player_id_);
994 LOG_ID(ERROR, GetPlayerId()) << "HBBTV media resource acquired failed";
996 return media_resource_acquired;
999 void MediaPlayerBridgeCapiTV::PlayerPreloaded() {
1000 LOG_ID(INFO, GetPlayerId()) << "PlayerPreloaded,this: " << this
1001 << ",player_prepared_:" << player_prepared_;
1003 is_preloaded_ = true;
1004 is_live_stream_ = CheckLiveStreaming();
1005 if (stream_type_ == DASH_STREAM)
1007 if (is_live_stream_ && stream_type_ != OTHER_STREAM) {
1008 // UpdateSeekableTime();
1009 // StartSeekableTimeUpdateTimer();
1011 UpdateAudioTrackInfo();
1012 UpdateVideoTrackInfo();
1013 UpdateTextTrackInfo();
1016 if (GetMediaType() == MediaType::Invalid) {
1017 LOG_ID(ERROR, GetPlayerId()) << "Media type is not valid!";
1021 OnReadyStateChange(player_id_,
1022 blink::WebMediaPlayer::kReadyStateHaveFutureData);
1023 OnNetworkStateChange(player_id_, blink::WebMediaPlayer::kNetworkStateLoading);
1025 if (!player_prepared_ && HBBTVResourceAcquired()) {
1026 int ret = SetPlayerPrepareAsync();
1027 if (ret != PLAYER_ERROR_NONE) {
1028 OnHandlePlayerError(ret, FROM_HERE);
1033 bool MediaPlayerBridgeCapiTV::PlayerPrePlay() {
1034 LOG_ID(INFO, GetPlayerId()) << "PlayerPrePlay, this: " << this
1035 << ",is_player_prepared : " << player_prepared_;
1036 if (IsPlayerSuspended()) {
1037 LOG_ID(INFO, GetPlayerId()) << "PlayerPrePlay while player is suspended";
1041 if (!HBBTVResourceAcquired()) {
1042 LOG_ID(INFO, GetPlayerId())
1043 << "PlayerPrePlay while it's not in case of HBBTV Resource Acquired";
1047 delayed_player_state_ = PLAYER_STATE_DELAYED_PLAY;
1048 LOG_ID(INFO, GetPlayerId()) << "begin to |player_prepare_async|";
1050 SetDisplayAtPausedState();
1051 int ret = SetPlayerPrepareAsync();
1052 if (ret != PLAYER_ERROR_NONE) {
1053 OnHandlePlayerError(ret, FROM_HERE);
1059 void MediaPlayerBridgeCapiTV::Initialize(VideoRendererSink* sink) {
1060 player_set_drm_error_cb(player_, DrmErrorCb, this);
1061 MediaPlayerBridgeCapi::Initialize(sink);
1064 bool MediaPlayerBridgeCapiTV::SetDrmInfo(std::string& drm_info) {
1065 // The DRM info from HbbTV comes as a JSON-like string in the following
1067 // pair = Property ':' Value
1068 // string = pair {',' pair}
1069 std::vector<std::string> drm_info_pairs = base::SplitStringUsingSubstr(
1070 drm_info, ", ", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
1071 for (auto it = drm_info_pairs.begin(); it != drm_info_pairs.end(); ++it) {
1072 std::vector<std::string> drm_info_pair = base::SplitStringUsingSubstr(
1073 *it, ": ", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
1075 if (drm_info_pair.size() != 2)
1078 std::string trim_key = drm_info_pair.at(0);
1079 std::string trim_value = drm_info_pair.at(1);
1080 LOG_ID(INFO, GetPlayerId()) << "trim_key: " << trim_key.c_str()
1081 << ",trim_value: " << trim_value.c_str();
1083 if (!SetMediaDRMInfo(trim_key, trim_value)) {
1084 LOG_ID(ERROR, GetPlayerId())
1085 << "MediaPlayerBridgeCapiTV::SetDrmInfo SetMediaDRMInfo failed";
1093 bool MediaPlayerBridgeCapiTV::SetMediaDRMInfo(const std::string& type_data,
1094 const std::string& value_data) {
1095 LOG_ID(INFO, GetPlayerId())
1096 << "player_set_drm_info(type_length(" << type_data.length() << ") "
1097 << " value_length(" << value_data.length() << ")) ";
1098 int ret = PLAYER_ERROR_INVALID_OPERATION;
1099 const void* type_data_ptr = type_data.c_str();
1100 const void* value_data_ptr = value_data.c_str();
1101 player_drm_type_e drm_type = PLAYER_DRM_TYPE_PLAYREADY;
1102 ret = player_set_drm_info(player_, type_data_ptr, type_data.length(),
1103 value_data_ptr, value_data.length(), drm_type);
1104 if (ret != PLAYER_ERROR_NONE) {
1105 MediaPlayerBridgeCapi::OnHandlePlayerError(ret, FROM_HERE);
1112 void MediaPlayerBridgeCapiTV::OnDrmError(int err_code, char* err_str) {
1113 LOG_ID(ERROR, GetPlayerId()) << "OnDrmError err_str[" << err_str << "]";
1114 if (!task_runner_->BelongsToCurrentThread()) {
1115 task_runner_->PostTask(
1117 base::BindOnce(&MediaPlayerBridgeCapiTV::OnDrmError,
1118 weak_factory_.GetWeakPtr(), err_code, err_str));
1120 MediaPlayerBridgeCapi::OnHandlePlayerError(err_code, FROM_HERE);
1123 void MediaPlayerBridgeCapiTV::HandleParentalRatingInfo(const std::string& info,
1124 const std::string& url) {
1125 content::WebContentsDelegate* web_contents_delegate =
1126 GetMediaPlayerClient()->GetWebContentsDelegate();
1127 if (!web_contents_delegate) {
1128 LOG_ID(ERROR, GetPlayerId()) << "web_contents_delegate is null";
1131 web_contents_delegate->NotifyParentalRatingInfo(info, url);
1134 void MediaPlayerBridgeCapiTV::SetParentalRatingResult(bool is_pass) {
1135 LOG_ID(INFO, GetPlayerId())
1136 << "ParentalRatingResult:" << std::boolalpha << is_pass;
1137 parental_rating_pass_ = is_pass;
1139 // if authentication fail, raise MEDIA_ERROR_DECODE
1140 if (!parental_rating_pass_) {
1141 OnHandlePlayerError(PLAYER_ERROR_INVALID_OPERATION, FROM_HERE);
1145 if (player_prepared_) {
1146 LOG_ID(INFO, GetPlayerId()) << "player already prepared,execute play";
1147 ExecuteDelayedPlayerState();
1150 void MediaPlayerBridgeCapiTV::AddAudioTrackInfo(const std::string& id,
1151 const std::string& kind,
1152 const std::string& label,
1153 const std::string& lang,
1155 LOG_ID(INFO, player_id_) << "AudioTrack Info - id: " << id
1156 << ", kind: " << kind.c_str()
1157 << ", label: " << label.c_str()
1158 << ", lang: " << lang.c_str();
1160 media::mojom::MediaTrackInfoPtr trackinfo =
1161 media::mojom::MediaTrackInfo::New();
1162 trackinfo->cmd = media::mojom::TRACKCMD::SETAUDIO;
1163 trackinfo->ck = media::mojom::COOKIES::NewTrack(
1164 media::mojom::Track::New(id, kind, label, lang, enabled));
1165 if (GetMediaPlayerClient())
1166 GetMediaPlayerClient()->AddTrackInfo(std::move(trackinfo));
1168 LOG(ERROR) << "Media player client is null";
1171 void MediaPlayerBridgeCapiTV::OnOtherEvent(int event_type, void* event_data) {
1173 LOG(ERROR) << "event_data is null.";
1176 switch (event_type) {
1177 case PLAYER_MSG_STREAM_EVENT_TYPE: {
1178 LOG_ID(INFO, player_id_) << "PLAYER_MSG_STREAM_EVENT_TYPE";
1179 EventStream* eventstream = static_cast<EventStream*>(event_data);
1181 LOG(ERROR) << "eventstream is null.";
1184 std::string uri(eventstream->schemeIdUri ? eventstream->schemeIdUri : "");
1185 std::string value(eventstream->value ? eventstream->value : "");
1186 #if TIZEN_VERSION_AT_LEAST(6, 5, 0)
1187 int band_type = eventstream->type;
1188 int event_mode = static_cast<player_event_mode>(
1189 (band_type >= IN_BAND) ? (band_type - IN_BAND)
1190 : (band_type - OUT_BAND));
1192 player_event_mode event_mode = eventstream->type;
1193 int band_type = static_cast<int>(event_mode);
1195 LOG_ID(INFO, player_id_)
1196 << "uri:" << uri << ",value:" << value << ",band_type:" << band_type
1197 << ",event_mode:" << event_mode;
1199 // parental rating event only need to handle data info
1200 if (event_mode == PLAYER_DVB_EVENT_MODE_PARENTAL_GUIDANCE) {
1201 LOG_ID(INFO, player_id_) << "parental rating event, skip type";
1205 if (!uri.compare("urn:mpeg:dash:event:2012") ||
1206 !uri.compare("urn:dvb:iptv:cpm:2014")) {
1207 LOG_ID(INFO, player_id_) << "not supported scheme id uri,uri:" << uri;
1211 if (!uri.compare("urn:dvb:css")) {
1212 LOG_ID(INFO, player_id_) << "event->value:" << eventstream->value
1213 << " evalue " << value.c_str();
1214 task_runner_->PostTask(
1215 FROM_HERE, base::BindOnce(&MediaPlayerBridgeCapi::UpdateEventData,
1216 weak_factory_.GetWeakPtr(), value));
1220 const std::string info = uri + " " + value;
1221 task_runner_->PostTask(
1223 base::BindOnce(&MediaPlayerBridgeCapiTV::HandleInbandTextTrack,
1224 weak_factory_.GetWeakPtr(), info, band_type,
1225 ADD_INBAND_TEXT_TRACK));
1228 case PLAYER_MSG_STREAM_EVENT_DATA: {
1229 LOG_ID(INFO, player_id_) << "PLAYER_MSG_STREAM_EVENT_DATA";
1230 Event* event = static_cast<Event*>(event_data);
1232 LOG(ERROR) << "event is null.";
1235 std::string uri(event->schemeIdUri ? event->schemeIdUri : "");
1236 std::string value(event->value ? event->value : "");
1237 unsigned int id = event->id;
1238 long long int start_time = event->startTimeMs;
1239 long long int end_time = event->endTimeMs;
1240 std::string data(event->data ? event->data : "");
1241 #if TIZEN_VERSION_AT_LEAST(6, 5, 0)
1242 int band_type = event->type;
1243 int event_mode = static_cast<player_event_mode>(
1244 (band_type >= IN_BAND) ? (band_type - IN_BAND)
1245 : (band_type - OUT_BAND));
1247 player_event_mode event_mode = event->type;
1248 int band_type = static_cast<int>(event_mode);
1250 LOG_ID(INFO, player_id_)
1251 << "uri:" << uri << ",value:" << value << ",data:" << data
1252 << ",id:" << id << ",start_time:" << start_time
1253 << ",end_time:" << end_time << ",band_type:" << band_type
1254 << ",event_mode:" << event_mode;
1256 if (event_mode == PLAYER_DVB_EVENT_MODE_DEAULT) {
1257 if (0 == uri.compare("urn:mpeg:dash:event:2012") ||
1258 0 == uri.compare("urn:dvb:iptv:cpm:2014")) {
1259 LOG_ID(INFO, player_id_) << "not supported scheme id uri,uri:" << uri;
1262 const std::string info = uri + " " + value + "$" + data;
1263 task_runner_->PostTask(
1265 base::BindOnce(&MediaPlayerBridgeCapiTV::HandleInbandTextCue,
1266 weak_factory_.GetWeakPtr(), info, id, band_type,
1267 start_time, end_time));
1268 } else if (event_mode == PLAYER_DVB_EVENT_MODE_PARENTAL_GUIDANCE) {
1269 //<mpeg7:ParentalRating href="urn:dvb:iptv:rating:2014:15"/>
1270 std::size_t pos = data.find("ParentalRating href=");
1271 if (pos != std::string::npos) {
1272 parental_rating_pass_ = false;
1273 std::size_t quotation1 = data.find('"', pos);
1274 std::size_t quotation2 = data.find('"', quotation1 + 1);
1275 std::string target =
1276 data.substr(quotation1 + 1, quotation2 - quotation1 - 1);
1277 LOG_ID(INFO, player_id_)
1278 << "parentl rating info string is:" << target;
1279 task_runner_->PostTask(
1281 base::BindOnce(&MediaPlayerBridgeCapiTV::HandleParentalRatingInfo,
1282 weak_factory_.GetWeakPtr(), target, url_.spec()));
1286 PLAYER_DVB_EVENT_MODE_SUPPLEMENTAL_PROPERTY_FONT_DOWNLOAD ||
1288 PLAYER_DVB_EVENT_MODE_ESSENTIAL_PROPERTY_FONT_DOWNLOAD) {
1289 task_runner_->PostTask(
1291 base::BindOnce(&MediaPlayerBridgeCapiTV::HandleDownloadableFontInfo,
1292 weak_factory_.GetWeakPtr(), uri, value, data,
1297 case PLAYER_MSG_STREAM_EVENT_MRS_URL_CHANGED: {
1298 LOG_ID(INFO, player_id_) << "PLAYER_MSG_STREAM_EVENT_MRS_URL_CHANGED";
1299 char* url = static_cast<char*>(event_data);
1300 std::string mrsUrl(url ? url : "");
1301 LOG_ID(INFO, player_id_) << "mrsUrl:" << mrsUrl;
1302 #if !defined(EWK_BRINGUP)
1303 task_runner_->PostTask(
1305 base::BindOnce(&MediaPlayerBridgeCapiTV::HandleMrsUrlChange,
1306 weak_factory_.GetWeakPtr(), mrsUrl));
1310 case PLAYER_MSG_STREAM_EVENT_PERIOAD_ID_CHANGED: {
1311 LOG_ID(INFO, player_id_) << "PLAYER_MSG_STREAM_EVENT_PERIOAD_ID_CHANGED";
1312 char* id = static_cast<char*>(event_data);
1313 std::string periodId(id ? id : "");
1314 LOG_ID(INFO, player_id_) << "periodId:" << periodId;
1315 #if !defined(EWK_BRINGUP)
1316 task_runner_->PostTask(
1318 base::BindOnce(&MediaPlayerBridgeCapiTV::HandlePeriodIdChange,
1319 weak_factory_.GetWeakPtr(), periodId));
1323 case PLAYER_MSG_STREAM_EVENT_REMOVE_TRACK: {
1324 LOG_ID(INFO, player_id_) << "PLAYER_MSG_STREAM_EVENT_REMOVE_TRACK";
1325 EventStream* eventstream = static_cast<EventStream*>(event_data);
1327 LOG(ERROR) << "eventstream is null.";
1330 std::string uri(eventstream->schemeIdUri ? eventstream->schemeIdUri : "");
1331 std::string value(eventstream->value ? eventstream->value : "");
1332 LOG_ID(INFO, player_id_) << "uri:" << uri << ",value:" << value;
1334 const std::string info = uri + " " + value;
1335 #if TIZEN_VERSION_AT_LEAST(6, 5, 0)
1336 int band_type = eventstream->type;
1338 int band_type = static_cast<int>(eventstream->type);
1340 task_runner_->PostTask(
1342 base::BindOnce(&MediaPlayerBridgeCapiTV::HandleInbandTextTrack,
1343 weak_factory_.GetWeakPtr(), info, band_type,
1344 DEL_INBAND_TEXT_TRACK));
1348 LOG_ID(INFO, player_id_) << "unknow event type:" << event_type;
1353 void MediaPlayerBridgeCapiTV::HandleInbandTextTrack(const std::string& info,
1356 LOG_ID(INFO, player_id_) << "HandleInbandTextTrack info:" << info
1357 << " band_type:" << band_type
1358 << " action:" << action;
1359 media::mojom::MediaTrackInfoPtr trackinfo =
1360 media::mojom::MediaTrackInfo::New();
1361 trackinfo->cmd = media::mojom::TRACKCMD::SETINBAND;
1362 trackinfo->ck = media::mojom::COOKIES::NewInband(
1363 media::mojom::InbandTextInfo::New(info, band_type, action));
1364 if (GetMediaPlayerClient())
1365 GetMediaPlayerClient()->AddTrackInfo(std::move(trackinfo));
1368 void MediaPlayerBridgeCapiTV::HandleInbandTextCue(const std::string& info,
1371 long long int start_time,
1372 long long int end_time) {
1373 LOG_ID(INFO, player_id_) << "HandleInbandTextCue info:" << info
1374 << " id:" << id << " band_type:" << band_type
1375 << " start_time:" << start_time
1376 << " end_time:" << end_time;
1377 media::mojom::MediaTrackInfoPtr trackinfo =
1378 media::mojom::MediaTrackInfo::New();
1379 trackinfo->cmd = media::mojom::TRACKCMD::SETCUE;
1381 media::mojom::COOKIES::NewCue(media::mojom::InbandCueInfo::New(
1382 info, id, band_type, start_time, end_time));
1383 if (GetMediaPlayerClient())
1384 GetMediaPlayerClient()->AddTrackInfo(std::move(trackinfo));
1386 LOG(ERROR) << "Media player client is null";
1389 std::string MediaPlayerBridgeCapiTV::MapDashMediaTrackKind(
1390 const std::string& role,
1393 // HBBTV Spec : A.2.12.3 Modifications to clause 8.4.6
1394 // HBBTV spec v2.0.2 seperate audioTrack and videoTrack kind definition
1395 // and changed the "main" definiton of audioTrack(page 258)
1396 if (role.find("alternate") != std::string::npos &&
1397 role.find("main") == std::string::npos &&
1398 role.find("commentary") == std::string::npos &&
1399 role.find("dub") == std::string::npos)
1400 return "alternative";
1402 if (role.find("caption") != std::string::npos &&
1403 role.find("main") != std::string::npos)
1406 if (role.find("description") != std::string::npos &&
1407 role.find("supplementary") != std::string::npos)
1408 return "descriptions";
1410 if (role.find("main") != std::string::npos &&
1411 role.find("caption") == std::string::npos &&
1412 role.find("subtitle") == std::string::npos &&
1413 role.find("dub") == std::string::npos) {
1416 else if (role.find("description") == std::string::npos)
1420 if (role.find("main") != std::string::npos &&
1421 role.find("description") != std::string::npos)
1424 if (role.find("subtitle") != std::string::npos &&
1425 role.find("main") != std::string::npos)
1428 if (role.find("dub") != std::string::npos &&
1429 role.find("main") != std::string::npos)
1430 return "translation";
1432 if (role.find("commentary") != std::string::npos &&
1433 role.find("main") == std::string::npos)
1434 return "commentary";
1439 void MediaPlayerBridgeCapiTV::UpdateAudioTrackInfo() {
1441 int err = player_get_adaptationset_count(player_, PLAYER_STREAM_TYPE_AUDIO,
1443 if (err != PLAYER_ERROR_NONE || cntTracks == 0) {
1444 LOG_ID(ERROR, player_id_)
1445 << "get audio track fail,err:" << err << ",count:" << cntTracks;
1449 LOG_ID(INFO, player_id_) << "audio track count: " << cntTracks;
1451 player_audio_adaptationset_info* audio_track_info =
1452 static_cast<player_audio_adaptationset_info*>(
1453 malloc(cntTracks * sizeof(player_audio_adaptationset_info)));
1454 if (!audio_track_info) {
1455 LOG_ID(ERROR, player_id_) << "malloc fail";
1458 memset(audio_track_info, 0,
1459 cntTracks * sizeof(player_audio_adaptationset_info));
1461 unsigned audio_alter_count_total = 0;
1462 for (int i = 0; i < cntTracks; i++) {
1463 int audio_alter_count = 0;
1464 err = player_get_alternative_count(player_, PLAYER_STREAM_TYPE_AUDIO, i,
1465 &audio_alter_count);
1466 if (err != PLAYER_ERROR_NONE || audio_alter_count == 0) {
1467 LOG_ID(WARNING, player_id_)
1468 << "player_get_alternative_count error,idx: " << i
1469 << ",audio_alter_count: " << audio_alter_count;
1473 LOG_ID(INFO, player_id_)
1474 << "audio track idx:" << i << ",alter_count:" << audio_alter_count;
1475 audio_alter_count_total += audio_alter_count;
1476 audio_track_info[i].alternatives =
1477 static_cast<Alternative_audioStreamInfo*>(
1478 malloc(audio_alter_count * sizeof(Alternative_audioStreamInfo)));
1479 if (!audio_track_info[i].alternatives) {
1480 LOG_ID(ERROR, player_id_)
1481 << "malloc fail,free memory which is already malloced";
1483 for (int j = 0; j <= i - 1; j++)
1484 BLINKFREE(audio_track_info[j].alternatives);
1486 BLINKFREE(audio_track_info);
1489 memset(audio_track_info[i].alternatives, 0,
1490 audio_alter_count * sizeof(Alternative_audioStreamInfo));
1492 #if !defined(EWK_BRINGUP)
1493 if (blink::IsHbbTV())
1494 AudioTracksCountChanged(audio_alter_count_total);
1496 err = player_get_audio_adaptationset_info(player_, audio_track_info);
1497 if (err != PLAYER_ERROR_NONE) {
1498 LOG_ID(ERROR, player_id_) << "|player_get_audio_adaptationset_info| failed";
1499 for (int i = 0; i < cntTracks; i++)
1500 BLINKFREE(audio_track_info[i].alternatives);
1501 BLINKFREE(audio_track_info);
1505 int selected_idx = -1;
1506 int audio_track_index = 0;
1508 /* Get audio index for prefer languange & audio description */
1509 for (int i = 0; i < cntTracks; i++) {
1510 if (!audio_track_info[i].alternatives) {
1511 LOG_ID(WARNING, player_id_) << "track[" << i << "] fail,ignore it.";
1515 const char* language = audio_track_info[i].language;
1516 if (prefer_audio_lang_.find(language) != std::string::npos ||
1517 (GetAlpha2(prefer_audio_lang_).find(language) != std::string::npos)) {
1518 if (stream_type_ == DASH_STREAM)
1519 prefer_audio_adaptionset_idx_ = audio_track_info[i].index;
1521 prefer_audio_adaptionset_idx_ = i;
1527 LOG_ID(INFO, player_id_) << "prefer_audio_adaptationset_idx_: "
1528 << prefer_audio_adaptionset_idx_
1529 << ",selected_idx:" << selected_idx;
1531 audio_track_index = 0;
1533 for (int i = 0; i < cntTracks; i++) {
1534 #if TIZEN_VERSION_AT_LEAST(7, 0, 0)
1535 if (audio_track_info[i].preselectionInfo_count) {
1536 for (int j = 0; j < audio_track_info[i].preselectionInfo_count; j++) {
1537 std::string pres_id = audio_track_info[i].preselectionInfos[j].m_id;
1538 std::string language = audio_track_info[i].preselectionInfos[j].m_lang;
1539 std::string kind = audio_track_info[i].preselectionInfos[j].m_roleValue;
1540 std::string label = "";
1541 int enabled = (selected_idx == audio_track_index);
1542 AddAudioTrackInfo(pres_id, kind, label, language, enabled);
1543 audio_track_index++;
1549 if (!audio_track_info[i].alternatives) {
1550 LOG_ID(WARNING, player_id_) << "track[" << i << "] fail,ignore it.";
1553 const char* lang = audio_track_info[i].language;
1554 std::string langStr(lang ? lang : "");
1556 std::stringstream roleInfoBuilder;
1557 const int role_count = audio_track_info[i].role_count;
1559 for (int k = 0; k < role_count; k++) {
1560 const char* role_member = audio_track_info[i].role_value[k];
1561 const std::string role_str(role_member ? role_member : "");
1562 roleInfoBuilder << role_str << ",";
1565 LOG_ID(INFO, player_id_)
1566 << "role str:" << roleInfoBuilder.str() << ",role count:" << role_count;
1567 std::string kindStr = "";
1568 if (stream_type_ == DASH_STREAM)
1569 kindStr = MapDashMediaTrackKind(roleInfoBuilder.str(), role_count, true);
1570 if (stream_type_ == TS_STREAM) // role_count = 1
1571 kindStr = audio_track_info[i].role_value[0];
1573 char* label = nullptr;
1574 err = player_get_content_info(player_, PLAYER_CONTENT_INFO_TITLE, &label);
1575 if (err != PLAYER_ERROR_NONE)
1576 LOG_ID(WARNING, player_id_) << "|player_get_content_info| failed";
1577 std::string labelStr(label ? label : "");
1581 if (stream_type_ == DASH_STREAM)
1582 id = audio_track_info[i].adaptationset_id;
1584 id = audio_track_info[i].alternatives[0].track_id;
1586 std::string pres_id = std::to_string(id);
1587 std::string language = langStr;
1588 std::string kind = kindStr;
1589 std::string labels = labelStr;
1590 int enabled = (selected_idx == audio_track_index);
1591 AddAudioTrackInfo(pres_id, kind, labels, language, enabled);
1592 audio_track_index++;
1595 for (int j = 0; j < cntTracks; j++) {
1596 BLINKFREE(audio_track_info[j].alternatives);
1597 #if TIZEN_VERSION_AT_LEAST(7, 0, 0)
1598 BLINKFREE(audio_track_info[j].preselectionInfos);
1602 BLINKFREE(audio_track_info);
1605 void MediaPlayerBridgeCapiTV::UpdateVideoTrackInfo() {
1607 int err = player_get_adaptationset_count(player_, PLAYER_STREAM_TYPE_VIDEO,
1609 if (err != PLAYER_ERROR_NONE || cntTracks == 0) {
1610 LOG(ERROR) << "get video track fail,err:" << err << ",count" << cntTracks;
1614 LOG_ID(INFO, player_id_) << "video track count: " << cntTracks;
1616 player_video_adaptationset_info* video_track_info =
1617 static_cast<player_video_adaptationset_info*>(
1618 malloc(cntTracks * sizeof(player_video_adaptationset_info)));
1619 if (!video_track_info) {
1620 LOG(ERROR) << "malloc fail";
1623 memset(video_track_info, 0,
1624 cntTracks * sizeof(player_video_adaptationset_info));
1626 int adaptionSetIdx = -1;
1627 int alternativeIdx = -1;
1628 err = player_get_current_track_ex(player_, PLAYER_STREAM_TYPE_VIDEO,
1629 &adaptionSetIdx, &alternativeIdx);
1630 if (err != PLAYER_ERROR_NONE)
1631 LOG(WARNING) << "|player_get_current_track| failed";
1632 LOG_ID(INFO, player_id_) << "video adaptionSetIdx:" << adaptionSetIdx
1633 << ",alternativeIdx:" << alternativeIdx;
1635 for (int i = 0; i < cntTracks; i++) {
1636 int video_alter_count = 0;
1637 err = player_get_alternative_count(player_, PLAYER_STREAM_TYPE_VIDEO, i,
1638 &video_alter_count);
1639 if (err != PLAYER_ERROR_NONE || video_alter_count == 0) {
1640 LOG(WARNING) << "player_get_alternative_count error,idx: " << i
1641 << ",video_alter_count: " << video_alter_count;
1645 LOG_ID(INFO, player_id_)
1646 << "video track idx:" << i << ",alter_count:" << video_alter_count;
1647 video_track_info[i].alternatives =
1648 static_cast<Alternative_videoStreamInfo*>(
1649 malloc(video_alter_count * sizeof(Alternative_videoStreamInfo)));
1650 if (!video_track_info[i].alternatives) {
1651 LOG(ERROR) << "malloc fail,free memory which is already malloced";
1653 for (int j = 0; j <= i - 1; j++)
1654 BLINKFREE(video_track_info[j].alternatives);
1656 BLINKFREE(video_track_info);
1659 memset(video_track_info[i].alternatives, 0,
1660 video_alter_count * sizeof(Alternative_videoStreamInfo));
1663 err = player_get_video_adaptationset_info(player_, video_track_info);
1664 if (err != PLAYER_ERROR_NONE) {
1665 LOG(WARNING) << "|player_get_video_adaptationset_info| failed";
1666 for (int i = 0; i < cntTracks; i++)
1667 BLINKFREE(video_track_info[i].alternatives);
1668 BLINKFREE(video_track_info);
1672 for (int i = 0; i < cntTracks; i++) {
1673 if (!video_track_info[i].alternatives) {
1674 LOG(WARNING) << "track[" << i << "] fail,ignore it.";
1678 char* lang = nullptr;
1679 err = player_get_track_language_code_ex(player_, PLAYER_STREAM_TYPE_VIDEO,
1681 if (err != PLAYER_ERROR_NONE)
1682 LOG(WARNING) << "|player_get_track_language_code| failed";
1683 std::string langStr(lang ? lang : "");
1686 std::stringstream roleInfoBuilder;
1687 const int role_count = video_track_info[i].role_count;
1689 for (int k = 0; k < role_count; k++) {
1690 const char* role_member = video_track_info[i].role_value[k];
1691 const std::string role_str(role_member ? role_member : "");
1692 roleInfoBuilder << role_str << ",";
1695 LOG_ID(INFO, player_id_)
1696 << "role str:" << roleInfoBuilder.str() << ",role count:" << role_count;
1698 std::string kindStr = "";
1699 if (stream_type_ == DASH_STREAM)
1700 kindStr = MapDashMediaTrackKind(roleInfoBuilder.str(), role_count, false);
1702 char* label = nullptr;
1703 err = player_get_content_info(player_, PLAYER_CONTENT_INFO_TITLE, &label);
1704 if (err != PLAYER_ERROR_NONE)
1705 LOG(WARNING) << "|player_get_content_info| failed";
1706 std::string labelStr(label ? label : "");
1710 if (stream_type_ == DASH_STREAM)
1711 id = video_track_info[i].adaptationset_id;
1713 id = video_track_info[i].alternatives[0].track_id;
1715 if (adaptionSetIdx == i)
1716 LOG_ID(INFO, player_id_) << "VideoTrack index: [" << i << "] is selected";
1718 BLINKFREE(video_track_info[i].alternatives);
1720 LOG_ID(INFO, player_id_)
1721 << "VideoTrack Info - id: " << id << ", kind: " << kindStr.c_str()
1722 << ", label: " << labelStr.c_str() << ", lang: " << langStr.c_str();
1724 media::mojom::MediaTrackInfoPtr trackinfo =
1725 media::mojom::MediaTrackInfo::New();
1726 trackinfo->cmd = media::mojom::TRACKCMD::SETVIDEO;
1727 trackinfo->ck = media::mojom::COOKIES::NewTrack(media::mojom::Track::New(
1728 std::to_string(id), kindStr, labelStr, langStr, adaptionSetIdx == i));
1730 if (GetMediaPlayerClient())
1731 GetMediaPlayerClient()->AddTrackInfo(std::move(trackinfo));
1733 LOG(ERROR) << "Media player client is null";
1735 BLINKFREE(video_track_info);
1738 void MediaPlayerBridgeCapiTV::UpdateTextTrackInfo() {
1740 int err = player_get_adaptationset_count(player_, PLAYER_STREAM_TYPE_TEXT,
1742 if (err != PLAYER_ERROR_NONE || cntTracks == 0) {
1743 LOG_ID(ERROR, player_id_)
1744 << "get text track fail,err:" << err << ",count:" << cntTracks;
1748 LOG_ID(INFO, player_id_) << "text track count: " << cntTracks;
1750 player_subtitle_adaptationset_info* text_track_info =
1751 static_cast<player_subtitle_adaptationset_info*>(
1752 malloc(cntTracks * sizeof(player_subtitle_adaptationset_info)));
1753 if (!text_track_info) {
1754 LOG_ID(ERROR, player_id_) << "malloc fail";
1757 memset(text_track_info, 0,
1758 cntTracks * sizeof(player_subtitle_adaptationset_info));
1760 int adaptionSetIdx = -1;
1761 int alternativeIdx = -1;
1762 err = player_get_current_track_ex(player_, PLAYER_STREAM_TYPE_TEXT,
1763 &adaptionSetIdx, &alternativeIdx);
1764 if (err != PLAYER_ERROR_NONE)
1765 LOG_ID(WARNING, player_id_) << "|player_get_current_track| failed";
1766 LOG_ID(INFO, player_id_) << "text adaptionSetIdx:" << adaptionSetIdx
1767 << ",alternativeIdx:" << alternativeIdx;
1769 for (int i = 0; i < cntTracks; i++) {
1770 int text_alter_count = 0;
1771 err = player_get_alternative_count(player_, PLAYER_STREAM_TYPE_TEXT, i,
1773 if (err != PLAYER_ERROR_NONE || text_alter_count == 0) {
1774 LOG_ID(WARNING, player_id_)
1775 << "player_get_alternative_count error,idx: " << i
1776 << ",text_alter_count: " << text_alter_count;
1780 LOG_ID(INFO, player_id_)
1781 << "text track idx:" << i << ",alter_count:" << text_alter_count;
1782 text_track_info[i].alternatives =
1783 static_cast<Alternative_subtitleStreamInfo*>(
1784 malloc(text_alter_count * sizeof(Alternative_subtitleStreamInfo)));
1785 if (!text_track_info[i].alternatives) {
1786 LOG_ID(ERROR, player_id_)
1787 << "malloc fail,free memory which is already malloced";
1789 for (int j = 0; j <= i - 1; j++)
1790 BLINKFREE(text_track_info[j].alternatives);
1792 BLINKFREE(text_track_info);
1795 memset(text_track_info[i].alternatives, 0,
1796 text_alter_count * sizeof(Alternative_subtitleStreamInfo));
1799 err = player_get_subtitle_adaptationset_info(player_, text_track_info);
1800 if (err != PLAYER_ERROR_NONE) {
1801 LOG_ID(ERROR, player_id_)
1802 << "|player_get_subtitle_adaptationset_info| failed";
1803 for (int i = 0; i < cntTracks; i++)
1804 BLINKFREE(text_track_info[i].alternatives);
1805 BLINKFREE(text_track_info);
1809 for (int i = 0; i < cntTracks; i++) {
1810 if (!text_track_info[i].alternatives) {
1811 LOG_ID(WARNING, player_id_) << "track[" << i << "] fail,ignore it.";
1815 char* lang = nullptr;
1816 err = player_get_track_language_code_ex(player_, PLAYER_STREAM_TYPE_TEXT, i,
1818 if (err != PLAYER_ERROR_NONE)
1819 LOG_ID(ERROR, player_id_) << "|player_get_track_language_code| failed";
1820 std::string langStr(lang ? lang : "");
1823 char* label = nullptr;
1824 err = player_get_content_info(player_, PLAYER_CONTENT_INFO_TITLE, &label);
1825 if (err != PLAYER_ERROR_NONE)
1826 LOG_ID(ERROR, player_id_) << "|player_get_content_info| failed";
1827 std::string labelStr(label ? label : "");
1831 if (stream_type_ == TS_STREAM)
1832 id = text_track_info[i].alternatives[0].track_id;
1834 id = text_track_info[i].adaptationset_id;
1836 std::string kindStr("");
1837 #if TIZEN_VERSION_AT_LEAST(6, 0, 0)
1838 // subtitling_type: 8bit, maybe unvisible char
1839 if (stream_type_ == TS_STREAM) {
1840 int subitle_type = (int)text_track_info[i].role_value[0][0];
1841 LOG(INFO) << "subitle_type:" << subitle_type;
1842 if (subitle_type == 0x10 || subitle_type == 0x11 ||
1843 subitle_type == 0x12 || subitle_type == 0x13 ||
1844 subitle_type == 0x14 || subitle_type == 0x15)
1845 kindStr = "subtitles";
1849 if (adaptionSetIdx == i)
1850 LOG_ID(INFO, player_id_) << "TextTrack index: [" << i << "] is selected";
1852 BLINKFREE(text_track_info[i].alternatives);
1854 LOG_ID(INFO, player_id_)
1855 << "TextTrack Info - id: " << id << ", label: " << labelStr.c_str()
1856 << ", lang: " << langStr.c_str() << ", kind: " << kindStr.c_str();
1858 media::mojom::MediaTrackInfoPtr trackinfo =
1859 media::mojom::MediaTrackInfo::New();
1860 trackinfo->cmd = media::mojom::TRACKCMD::SETTEXT;
1861 trackinfo->ck = media::mojom::COOKIES::NewTrack(media::mojom::Track::New(
1862 std::to_string(id), kindStr, labelStr, langStr, true));
1864 if (GetMediaPlayerClient())
1865 GetMediaPlayerClient()->AddTrackInfo(std::move(trackinfo));
1868 BLINKFREE(text_track_info);
1871 void MediaPlayerBridgeCapiTV::UpdatePreferAudio() {
1872 LOG(INFO) << "UpdatePreferAudio,idx: " << prefer_audio_adaptionset_idx_
1873 << ",last idx:" << last_prefer_audio_adaptionset_idx_;
1874 if (prefer_audio_adaptionset_idx_ == last_prefer_audio_adaptionset_idx_) {
1875 LOG_ID(ERROR, player_id_) << "same track,no need to select";
1878 int ret = player_select_track_ex(player_, PLAYER_STREAM_TYPE_AUDIO,
1879 prefer_audio_adaptionset_idx_, -1);
1880 if (ret != PLAYER_ERROR_NONE) {
1881 LOG_ID(ERROR, player_id_) << "player_select_track_ex fail";
1884 active_audio_track_id_ = prefer_audio_adaptionset_idx_;
1885 last_prefer_audio_adaptionset_idx_ = prefer_audio_adaptionset_idx_;
1888 bool MediaPlayerBridgeCapiTV::GetUserPreferAudioLanguage() {
1889 prefer_audio_lang_.clear();
1891 const char* primary_audio_lang =
1892 "db/menu/broadcasting/audio_options/primary_audio_language";
1893 int ret = vconf_get_int(primary_audio_lang, &retval);
1895 LOG(ERROR) << "vconf_get_int failed";
1898 prefer_audio_lang_ += (char)(retval >> 16 & 0xFF);
1899 prefer_audio_lang_ += (char)(retval >> 8 & 0xFF);
1900 prefer_audio_lang_ += (char)(retval & 0xFF);
1901 LOG_ID(INFO, player_id_) << "primary audio lang is: "
1902 << prefer_audio_lang_.c_str();
1906 void MediaPlayerBridgeCapiTV::SetActiveTextTrack(int id, bool is_in_band) {
1907 LOG_ID(INFO, player_id_) << "id=" << id << ",is_in_band=" << is_in_band
1908 << " active_text_track_id_ "
1909 << active_text_track_id_;
1910 if (!GetMediaPlayerClient()) {
1911 LOG(ERROR) << "GetMediaPlayerClient return null";
1914 if (!GetMediaPlayerClient()->SubtitleNotificationEnabled()) {
1915 LOG(ERROR) << "SubtitleNotificationEnabled failed";
1919 #if !defined(EWK_BRINGUP)
1925 if (active_text_track_id_ == id)
1928 active_text_track_id_ = id;
1930 is_inband_text_track_ = is_in_band;
1935 void MediaPlayerBridgeCapiTV::SetActiveAudioTrack(int index) {
1936 LOG_ID(INFO, player_id_) << "active_audio_track_id_ "
1937 << active_audio_track_id_ << " index " << index;
1940 player_set_mute(player_, true);
1941 active_audio_track_id_ = -1;
1945 if (active_audio_track_id_ == index)
1947 active_audio_track_id_ = index;
1948 int ret = player_select_track_ex(player_, PLAYER_STREAM_TYPE_AUDIO,
1949 active_audio_track_id_, -1);
1950 if (ret != PLAYER_ERROR_NONE)
1951 LOG_ID(WARNING, player_id_) << "player_select_track_ex fail,ret:" << ret;
1954 void MediaPlayerBridgeCapiTV::SetActiveVideoTrack(int index) {
1955 LOG_ID(INFO, player_id_) << "active_video_track_id_ "
1956 << active_video_track_id_ << " index " << index;
1959 player_set_display_visible(player_, false);
1960 active_video_track_id_ = -1;
1964 if (active_video_track_id_ == index)
1966 active_video_track_id_ = index;
1967 int ret = player_select_track_ex(player_, PLAYER_STREAM_TYPE_VIDEO,
1968 active_video_track_id_, -1);
1969 if (ret != PLAYER_ERROR_NONE)
1970 LOG_ID(WARNING, player_id_) << "player_select_track_ex fail,ret:" << ret;
1973 void MediaPlayerBridgeCapiTV::SetPreferTextLanguage(const std::string& lang) {
1974 LOG_ID(INFO, player_id_)
1975 << "MediaPlayerBridgeCapiTV::SetPreferTextLanguage lang" << lang
1976 << " prefer_subtitle_lang_ " << prefer_subtitle_lang_;
1978 if (lang == prefer_subtitle_lang_)
1980 prefer_subtitle_lang_ = lang;
1981 const std::string prefer_subtitle_language =
1982 "set_subtitle_language = " + lang;
1984 LOG_ID(INFO, player_id_) << "prefer_subtitle_language:"
1985 << prefer_subtitle_language.c_str();
1986 player_set_ini_param(player_, prefer_subtitle_language.c_str());
1989 std::string MediaPlayerBridgeCapiTV::ParseDashKeyword(
1990 const std::string& keyword) {
1991 std::string dash_info = GetDashInfo();
1992 Json::CharReaderBuilder builder;
1993 Json::CharReader* reader(builder.newCharReader());
1995 std::string valueForKey;
1997 if (reader->parse(dash_info.c_str(), dash_info.c_str() + dash_info.length(),
1999 valueForKey = value[keyword].asString();
2000 LOG_ID(INFO, player_id_)
2001 << "keyword: " << keyword << ",valueForKey:" << valueForKey;
2007 double MediaPlayerBridgeCapiTV::GetStartDate() {
2008 int64_t millisecond = 0;
2009 int ret = player_get_start_date(player_, &millisecond);
2010 if (ret != PLAYER_ERROR_NONE) {
2011 /* In case of invalid state try to use player_get_dash_info()
2012 and parse it for availabilityStartTime -legacy hack*/
2013 if (ret == PLAYER_ERROR_INVALID_STATE) {
2014 const std::string start_date_keyword = "availabilityStartTime";
2015 std::string start_date = ParseDashKeyword(start_date_keyword);
2016 LOG_ID(ERROR, player_id_) << "from ParseDashKeyword: " << start_date;
2017 if (!start_date.empty()) {
2018 double start_date_ret = 0.0;
2019 std::stringstream ss;
2021 ss >> start_date_ret;
2022 OnHandlePlayerError(ret, FROM_HERE);
2023 return start_date_ret;
2026 OnHandlePlayerError(ret, FROM_HERE);
2027 LOG_ID(ERROR, player_id_) << "player_get_start_date fail,ret:" << ret;
2028 return std::numeric_limits<double>::quiet_NaN();
2031 return static_cast<double>(millisecond);
2033 } // namespace media