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 "media/base/efl/media_player_util_efl.h"
8 #include "tizen_src/chromium_impl/media/filters/media_player_tizen_client.h"
11 const int kSeekableTimeUpdateInterval = 500;
16 MediaPlayerBridgeCapiTV::MediaPlayerBridgeCapiTV(const GURL& url,
17 const std::string& user_agent,
19 : MediaPlayerBridgeCapi(url, user_agent, volume), weak_factory_(this) {
20 LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__;
23 MediaPlayerBridgeCapiTV::~MediaPlayerBridgeCapiTV() {
24 LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__;
25 weak_factory_.InvalidateWeakPtrs();
28 void MediaPlayerBridgeCapiTV::SetContentMimeType(const std::string& mime_type) {
29 LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__
30 << " mime_type : " << mime_type;
31 mime_type_ = mime_type;
34 void MediaPlayerBridgeCapiTV::Prepare() {
35 bool media_resource_acquired = false;
36 std::string translated_url;
39 if (GetMediaPlayerClient())
40 GetMediaPlayerClient()->NotifyPlaybackState(
41 kPlaybackLoad, player_id_, url_.spec(), mime_type_,
42 &media_resource_acquired, &translated_url, &drm_info);
44 LOG(INFO) << "media_resource_acquired: " << media_resource_acquired
45 << ",translated_url:" << translated_url
46 << ",drm_info: " << drm_info;
48 if (GetMediaPlayerClient() &&
49 GetMediaPlayerClient()->PlaybackNotificationEnabled() &&
50 blink::IsHbbTV() && !translated_url.empty())
51 url_ = media::GetCleanURL(translated_url);
53 if (url_.spec().find(".mpd") != std::string::npos)
54 stream_type_ = DASH_STREAM;
55 else if (url_.spec().find(".m3u") != std::string::npos)
56 stream_type_ = HLS_STREAM;
57 else if (mime_type_.find("application/dash+xml") != std::string::npos) {
58 char steaming_type_dash[] = "DASH";
59 char steaming_type_dash_ex[] = "DASHEX";
60 player_set_streaming_type(
61 player_, blink::IsHbbTV() ? steaming_type_dash_ex : steaming_type_dash);
62 stream_type_ = DASH_STREAM;
64 if (blink::IsHbbTV() && CheckHighBitRate() && stream_type_ == DASH_STREAM)
65 AppendUrlHighBitRate(url_.spec());
66 MediaPlayerBridgeCapi::Prepare();
67 if (GetMediaPlayerClient())
68 GetMediaPlayerClient()->NotifyPlaybackState(kPlaybackReady, player_id_);
71 void MediaPlayerBridgeCapiTV::Release() {
72 StopSeekableTimeUpdateTimer();
73 MediaPlayerBridgeCapi::Release();
74 if (GetMediaPlayerClient())
75 GetMediaPlayerClient()->NotifyPlaybackState(kPlaybackStop, player_id_);
78 bool MediaPlayerBridgeCapiTV::Play() {
79 if (!MediaPlayerBridgeCapi::Play())
81 if (GetMediaPlayerClient())
82 GetMediaPlayerClient()->NotifyPlaybackState(kPlaybackStart, player_id_);
86 void MediaPlayerBridgeCapiTV::PlaybackCompleteUpdate() {
87 MediaPlayerBridgeCapi::PlaybackCompleteUpdate();
88 if (GetMediaPlayerClient())
89 GetMediaPlayerClient()->NotifyPlaybackState(kPlaybackFinish, player_id_);
92 void MediaPlayerBridgeCapiTV::PlayerPrepared() {
93 MediaPlayerBridgeCapi::PlayerPrepared();
95 GetAdaptiveStreamingInfo();
96 if (/*!blink::IsHbbTV() && */is_live_stream_) {
98 StartSeekableTimeUpdateTimer();
102 void MediaPlayerBridgeCapiTV::StartSeekableTimeUpdateTimer() {
103 if (!seekable_time_update_timer_.IsRunning()) {
104 seekable_time_update_timer_.Start(
105 FROM_HERE, base::Milliseconds(kSeekableTimeUpdateInterval), this,
106 &MediaPlayerBridgeCapiTV::OnSeekableTimeUpdateTimerFired);
110 void MediaPlayerBridgeCapiTV::StopSeekableTimeUpdateTimer() {
111 if (seekable_time_update_timer_.IsRunning())
112 seekable_time_update_timer_.Stop();
115 void MediaPlayerBridgeCapiTV::OnSeekableTimeUpdateTimerFired() {
116 UpdateSeekableTime();
119 void MediaPlayerBridgeCapiTV::GetAdaptiveStreamingInfo() {
120 int ret = player_get_adaptive_streaming_info(player_, &is_live_stream_,
121 PLAYER_ADAPTIVE_INFO_IS_LIVE);
122 if (ret != PLAYER_ERROR_NONE || is_live_stream_) {
123 LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__
124 << " A live stream.";
128 void MediaPlayerBridgeCapiTV::UpdateSeekableTime() {
129 if (GetPlayerState() == PLAYER_STATE_NONE || !is_live_stream_)
132 int64_t min = 0, max = 0;
133 if (GetLiveStreamingDuration(&min, &max)) {
134 if (min_seekable_time_.InMilliseconds() != min ||
135 max_seekable_time_.InMilliseconds() != max) {
136 min_seekable_time_ = base::Milliseconds(min);
137 max_seekable_time_ = base::Milliseconds(max);
138 if (GetMediaPlayerClient())
139 GetMediaPlayerClient()->OnSeekableTimeChange(
140 min_seekable_time_, max_seekable_time_, is_live_stream_);
146 GetAdaptiveStreamingInfo();
147 if (!is_live_stream_) {
148 LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__
149 << " changed to static stream";
150 if (GetMediaPlayerClient())
151 GetMediaPlayerClient()->OnSeekableTimeChange({}, {}, is_live_stream_);
152 MediaPlayerBridgeCapi::UpdateDuration();
156 bool MediaPlayerBridgeCapiTV::GetLiveStreamingDuration(int64_t* min,
160 constexpr const size_t kDurationBufferSize = 64;
161 char live_duration[kDurationBufferSize] = {
164 char* live_ptr = live_duration;
165 const auto err = player_get_adaptive_streaming_info(
166 player_, live_duration, PLAYER_ADAPTIVE_INFO_LIVE_DURATION);
167 if (err != PLAYER_ERROR_NONE) {
168 LOG(ERROR) << "(" << static_cast<void*>(this) << ") " << __func__
169 << " |player_get_adaptive_streaming_info| failed " << err;
173 const std::string duration(live_duration);
174 const std::string::size_type delimiter = duration.find('|');
175 if (delimiter == std::string::npos) {
176 LOG(ERROR) << "(" << static_cast<void*>(this) << ") " << __func__
177 << " Failed to find delimiter | in duration: " << duration;
181 const std::string duration_min = duration.substr(0, delimiter);
182 if (duration_min.empty()) {
183 LOG(ERROR) << "(" << static_cast<void*>(this) << ") " << __func__
184 << " Failed empty min sub str: " << duration << ", "
190 if (!base::StringToInt64(duration_min, &out_min)) {
191 LOG(ERROR) << "(" << static_cast<void*>(this) << ") " << __func__
192 << " Failed to get min from duration: " << duration;
196 const std::string duration_max = duration.substr(delimiter + 1);
197 if (duration_max.empty()) {
198 LOG(ERROR) << "(" << static_cast<void*>(this) << ") " << __func__
199 << " empty max sub str: " << duration << ", " << delimiter;
204 if (!base::StringToInt64(duration_max, &out_max)) {
205 LOG(ERROR) << "(" << static_cast<void*>(this) << ") " << __func__
206 << " Failed to get max from duration: " << duration;
215 void MediaPlayerBridgeCapiTV::AppendUrlHighBitRate(const std::string& url) {
216 // don't use url.append("|STARTBITRATE=HIGHEST") to get hbbtv url
217 // "|" will be replaced with "%7C"
218 const char high_bitrate[] = "|STARTBITRATE=HIGHEST";
219 int len = url.length() + strlen(high_bitrate) + 1;
220 char* str_url = new char[len];
225 memset(str_url, 0, len);
226 strncat(str_url, url.c_str(), url.length());
227 strncat(str_url, high_bitrate, strlen(high_bitrate));
228 hbbtv_url_ = str_url;
230 LOG(INFO) << "hbbtv url:" << hbbtv_url_.c_str();
233 bool MediaPlayerBridgeCapiTV::CheckHighBitRate() {
234 if (!GetMediaPlayerClient()) {
235 LOG(ERROR) << "MediaPlayerClient is null";
238 content::WebContentsDelegate* web_contents_delegate =
239 GetMediaPlayerClient()->GetWebContentsDelegate();
240 if (!web_contents_delegate) {
241 LOG(ERROR) << "get web_contents_delegate fail";
244 bool ret = web_contents_delegate->IsHighBitRate();
245 LOG(INFO) << "get high bit rate: " << std::boolalpha << ret;
249 void MediaPlayerBridgeCapiTV::HandleDownloadableFontInfo(
250 const std::string& scheme_id_uri,
251 const std::string& value,
252 const std::string& data,
254 content::WebContentsDelegate* web_contents_delegate =
255 GetMediaPlayerClient()->GetWebContentsDelegate();
256 if (!web_contents_delegate)
258 web_contents_delegate->NotifyDownloadableFontInfo(scheme_id_uri, value, data,