[M120 Migration] Support Dash high bitrate
[platform/framework/web/chromium-efl.git] / tizen_src / chromium_impl / media / filters / media_player_bridge_capi_tv.cc
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.
4
5 #include "media/filters/media_player_bridge_capi_tv.h"
6
7 #include "media/base/efl/media_player_util_efl.h"
8 #include "tizen_src/chromium_impl/media/filters/media_player_tizen_client.h"
9
10 namespace {
11 const int kSeekableTimeUpdateInterval = 500;
12 }
13
14 namespace media {
15
16 MediaPlayerBridgeCapiTV::MediaPlayerBridgeCapiTV(const GURL& url,
17                                                  const std::string& user_agent,
18                                                  double volume)
19     : MediaPlayerBridgeCapi(url, user_agent, volume), weak_factory_(this) {
20   LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__;
21 }
22
23 MediaPlayerBridgeCapiTV::~MediaPlayerBridgeCapiTV() {
24   LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__;
25   weak_factory_.InvalidateWeakPtrs();
26 }
27
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;
32 }
33
34 void MediaPlayerBridgeCapiTV::Prepare() {
35   if (blink::IsHbbTV() && CheckHighBitRate() && stream_type_ == DASH_STREAM)
36     AppendUrlHighBitRate(url_.spec());
37   MediaPlayerBridgeCapi::Prepare();
38 }
39
40 void MediaPlayerBridgeCapiTV::Release() {
41   StopSeekableTimeUpdateTimer();
42   MediaPlayerBridgeCapi::Release();
43 }
44
45 bool MediaPlayerBridgeCapiTV::Play() {
46   if (!MediaPlayerBridgeCapi::Play())
47     return false;
48   return true;
49 }
50
51 void MediaPlayerBridgeCapiTV::PlaybackCompleteUpdate() {
52   MediaPlayerBridgeCapi::PlaybackCompleteUpdate();
53 }  // namespace media
54
55 void MediaPlayerBridgeCapiTV::PlayerPrepared() {
56   MediaPlayerBridgeCapi::PlayerPrepared();
57
58   GetAdaptiveStreamingInfo();
59   if (/*!blink::IsHbbTV() && */is_live_stream_) {
60     UpdateSeekableTime();
61     StartSeekableTimeUpdateTimer();
62   }
63 }
64
65 void MediaPlayerBridgeCapiTV::StartSeekableTimeUpdateTimer() {
66   if (!seekable_time_update_timer_.IsRunning()) {
67     seekable_time_update_timer_.Start(
68         FROM_HERE, base::Milliseconds(kSeekableTimeUpdateInterval), this,
69         &MediaPlayerBridgeCapiTV::OnSeekableTimeUpdateTimerFired);
70   }
71 }
72
73 void MediaPlayerBridgeCapiTV::StopSeekableTimeUpdateTimer() {
74   if (seekable_time_update_timer_.IsRunning())
75     seekable_time_update_timer_.Stop();
76 }
77
78 void MediaPlayerBridgeCapiTV::OnSeekableTimeUpdateTimerFired() {
79   UpdateSeekableTime();
80 }
81
82 void MediaPlayerBridgeCapiTV::GetAdaptiveStreamingInfo() {
83   int ret = player_get_adaptive_streaming_info(player_, &is_live_stream_,
84                                                PLAYER_ADAPTIVE_INFO_IS_LIVE);
85   if (ret != PLAYER_ERROR_NONE || is_live_stream_) {
86     LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__
87               << " A live stream.";
88   }
89 }
90
91 void MediaPlayerBridgeCapiTV::UpdateSeekableTime() {
92   if (GetPlayerState() == PLAYER_STATE_NONE || !is_live_stream_)
93     return;
94
95   int64_t min = 0, max = 0;
96   if (GetLiveStreamingDuration(&min, &max)) {
97     if (min_seekable_time_.InMilliseconds() != min ||
98         max_seekable_time_.InMilliseconds() != max) {
99       min_seekable_time_ = base::Milliseconds(min);
100       max_seekable_time_ = base::Milliseconds(max);
101       if (GetMediaPlayerClient())
102       GetMediaPlayerClient()->OnSeekableTimeChange(
103           min_seekable_time_, max_seekable_time_, is_live_stream_);
104     }
105
106     return;
107   }
108
109   GetAdaptiveStreamingInfo();
110   if (!is_live_stream_) {
111     LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__
112               << " changed to static stream";
113     if (GetMediaPlayerClient())
114       GetMediaPlayerClient()->OnSeekableTimeChange({}, {}, is_live_stream_);
115     MediaPlayerBridgeCapi::UpdateDuration();
116   }
117 }
118
119 bool MediaPlayerBridgeCapiTV::GetLiveStreamingDuration(int64_t* min,
120                                                        int64_t* max) {
121   DCHECK(min);
122   DCHECK(max);
123   constexpr const size_t kDurationBufferSize = 64;
124   char live_duration[kDurationBufferSize] = {
125       0,
126   };
127   char* live_ptr = live_duration;
128   const auto err = player_get_adaptive_streaming_info(
129       player_, live_duration, PLAYER_ADAPTIVE_INFO_LIVE_DURATION);
130   if (err != PLAYER_ERROR_NONE) {
131     LOG(ERROR) << "(" << static_cast<void*>(this) << ") " << __func__
132                << " |player_get_adaptive_streaming_info| failed " << err;
133     return false;
134   }
135
136   const std::string duration(live_duration);
137   const std::string::size_type delimiter = duration.find('|');
138   if (delimiter == std::string::npos) {
139     LOG(ERROR) << "(" << static_cast<void*>(this) << ") " << __func__
140                << " Failed to find delimiter | in duration: " << duration;
141     return false;
142   }
143
144   const std::string duration_min = duration.substr(0, delimiter);
145   if (duration_min.empty()) {
146     LOG(ERROR) << "(" << static_cast<void*>(this) << ") " << __func__
147                << " Failed empty min sub str: " << duration << ", "
148                << delimiter;
149     return false;
150   }
151
152   int64_t out_min = 0;
153   if (!base::StringToInt64(duration_min, &out_min)) {
154     LOG(ERROR) << "(" << static_cast<void*>(this) << ") " << __func__
155                << " Failed to get min from duration: " << duration;
156     return false;
157   }
158
159   const std::string duration_max = duration.substr(delimiter + 1);
160   if (duration_max.empty()) {
161     LOG(ERROR) << "(" << static_cast<void*>(this) << ") " << __func__
162                << " empty max sub str: " << duration << ", " << delimiter;
163     return false;
164   }
165
166   int64_t out_max = 0;
167   if (!base::StringToInt64(duration_max, &out_max)) {
168     LOG(ERROR) << "(" << static_cast<void*>(this) << ") " << __func__
169                << " Failed to get max from duration: " << duration;
170     return false;
171   }
172
173   *min = out_min;
174   *max = out_max;
175   return true;
176 }
177
178 void MediaPlayerBridgeCapiTV::AppendUrlHighBitRate(const std::string& url) {
179   // don't use url.append("|STARTBITRATE=HIGHEST") to get hbbtv url
180   // "|" will be replaced with "%7C"
181   const char high_bitrate[] = "|STARTBITRATE=HIGHEST";
182   int len = url.length() + strlen(high_bitrate) + 1;
183   char* str_url = new char[len];
184   if (!str_url) {
185     return;
186   }
187
188   memset(str_url, 0, len);
189   strncat(str_url, url.c_str(), url.length());
190   strncat(str_url, high_bitrate, strlen(high_bitrate));
191   hbbtv_url_ = str_url;
192   BLINKFREE(str_url);
193   LOG(INFO) << "hbbtv url:" << hbbtv_url_.c_str();
194 }
195
196 bool MediaPlayerBridgeCapiTV::CheckHighBitRate() {
197   if (!GetMediaPlayerClient()) {
198     LOG(ERROR) << "MediaPlayerClient is null";
199     return false;
200   }
201   content::WebContentsDelegate* web_contents_delegate =
202       GetMediaPlayerClient()->GetWebContentsDelegate();
203   if (!web_contents_delegate) {
204     LOG(ERROR) << "get web_contents_delegate fail";
205     return false;
206   }
207   bool ret = web_contents_delegate->IsHighBitRate();
208   LOG(INFO) << "get high bit rate: " << std::boolalpha << ret;
209   return ret;
210 }
211
212 }  // namespace media