b18eaa33be711f3aecb3688992dc234dbab4dfb2
[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 "base/strings/string_split.h"
8 #include "media/base/efl/media_player_util_efl.h"
9 #include "tizen_src/chromium_impl/media/filters/media_player_tizen_client.h"
10
11 #include <jsoncpp/json/json.h>
12
13 namespace {
14 const int kSeekableTimeUpdateInterval = 500;
15 }
16
17 static void PlayerPreLoadingCb(void* data) {
18   if (!data) {
19     LOG(ERROR) << "input data is null";
20     return;
21   }
22   media::MediaPlayerBridgeCapiTV* player =
23       static_cast<media::MediaPlayerBridgeCapiTV*>(data);
24   player->OnPlayerPreloading();
25 }
26
27 static void DrmErrorCb(int err_code, char* err_str, void* data) {
28   DCHECK(data);
29   media::MediaPlayerBridgeCapiTV* player =
30       static_cast<media::MediaPlayerBridgeCapiTV*>(data);
31
32   player->OnDrmError(err_code, err_str);
33 }
34
35 namespace media {
36
37 MediaPlayerBridgeCapiTV::MediaPlayerBridgeCapiTV(const GURL& url,
38                                                  const std::string& user_agent,
39                                                  double volume)
40     : MediaPlayerBridgeCapi(url, user_agent, volume), weak_factory_(this) {
41   LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__;
42 }
43
44 MediaPlayerBridgeCapiTV::~MediaPlayerBridgeCapiTV() {
45   LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__;
46   weak_factory_.InvalidateWeakPtrs();
47 }
48
49 void MediaPlayerBridgeCapiTV::SetContentMimeType(const std::string& mime_type) {
50   LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__
51             << " mime_type : " << mime_type;
52   mime_type_ = mime_type;
53 }
54
55 void MediaPlayerBridgeCapiTV::Prepare() {
56   bool media_resource_acquired = false;
57   std::string translated_url;
58   std::string drm_info;
59
60   if (GetMediaPlayerClient())
61     GetMediaPlayerClient()->NotifyPlaybackState(
62         kPlaybackLoad, player_id_, url_.spec(), mime_type_,
63         &media_resource_acquired, &translated_url, &drm_info);
64
65   LOG(INFO) << "media_resource_acquired: " << media_resource_acquired
66             << ",translated_url:" << translated_url
67             << ",drm_info: " << drm_info;
68
69   if (mime_type_.find("application/vnd.oipf.contentaccessstreaming+xml") !=
70       std::string::npos) {
71     LOG(INFO) << "CASD url,waiting for hbbtv parse the real url and set "
72                  "translated url";
73     return;
74   }
75
76   if (GetMediaPlayerClient() &&
77       GetMediaPlayerClient()->PlaybackNotificationEnabled() &&
78       blink::IsHbbTV()) {
79     if (!SetDrmInfo(drm_info)) {
80       LOG(ERROR) << "SetDrmInfo failed";
81       return;
82     }
83     if (!translated_url.empty())
84       url_ = media::GetCleanURL(translated_url);
85   }
86
87   if (url_.spec().find(".mpd") != std::string::npos)
88     stream_type_ = DASH_STREAM;
89   else if (url_.spec().find(".m3u") != std::string::npos)
90     stream_type_ = HLS_STREAM;
91   else if (mime_type_.find("application/dash+xml") != std::string::npos) {
92     char steaming_type_dash[] = "DASH";
93     char steaming_type_dash_ex[] = "DASHEX";
94     player_set_streaming_type(
95         player_, blink::IsHbbTV() ? steaming_type_dash_ex : steaming_type_dash);
96     stream_type_ = DASH_STREAM;
97   }
98
99   if (blink::IsHbbTV() && CheckHighBitRate() && stream_type_ == DASH_STREAM)
100     AppendUrlHighBitRate(url_.spec());
101   player_prepared_ = false;
102
103   parental_rating_pass_ = true;
104   MediaPlayerBridgeCapi::Prepare();
105   if (GetMediaPlayerClient())
106     GetMediaPlayerClient()->NotifyPlaybackState(kPlaybackReady, player_id_);
107 }
108
109 void MediaPlayerBridgeCapiTV::Release() {
110   is_preloaded_ = false;
111   player_prepared_ = false;
112   StopSeekableTimeUpdateTimer();
113   MediaPlayerBridgeCapi::Release();
114   if (GetMediaPlayerClient())
115     GetMediaPlayerClient()->NotifyPlaybackState(kPlaybackStop, player_id_);
116 }
117
118 bool MediaPlayerBridgeCapiTV::Play() {
119   LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__
120             << ",current_time:" << GetCurrentTime().InSecondsF();
121
122   // HBBTV run in preloading and preplay mode. If no prepread do prepare
123   // in PlayerPrePlay(), otherwise do normal Play.
124   if (blink::IsHbbTV() && !player_prepared_) {
125     if (!PlayerPrePlay())
126       LOG(ERROR) << "HBBTV prePlay fail.";
127     return false;
128   }
129
130   if (blink::IsHbbTV() && !parental_rating_pass_) {
131     LOG(INFO) << "parental rating authenticatoin is not pass yet,waiting...";
132     delayed_player_state_ = PLAYER_STATE_DELAYED_PLAY;
133     MediaPlayerBridgeCapi::ExecuteDelayedPlayerState();
134     return false;
135   }
136
137   if (!MediaPlayerBridgeCapi::Play())
138     return false;
139   if (GetMediaPlayerClient())
140     GetMediaPlayerClient()->NotifyPlaybackState(kPlaybackStart, player_id_);
141   return true;
142 }
143
144 void MediaPlayerBridgeCapiTV::Pause(bool is_media_related_action) {
145   if (!player_prepared_) {
146     LOG(INFO) << "(" << static_cast<void*>(this)
147               << "), pause while player is not prepared, pause delay";
148     delayed_player_state_ = PLAYER_STATE_DELAYED_PAUSE;
149     return;
150   }
151   MediaPlayerBridgeCapi::Pause(is_media_related_action);
152 }
153
154 void MediaPlayerBridgeCapiTV::PlaybackCompleteUpdate() {
155   MediaPlayerBridgeCapi::PlaybackCompleteUpdate();
156   if (GetMediaPlayerClient()) {
157     GetMediaPlayerClient()->NotifyPlaybackState(kPlaybackFinish, player_id_);
158     if (is_live_stream_)
159       GetMediaPlayerClient()->OnLivePlaybackComplete();
160   }
161 }  // namespace media
162
163 void MediaPlayerBridgeCapiTV::PlayerPrepared() {
164   player_prepared_ = true;
165   MediaPlayerBridgeCapi::PlayerPrepared();
166
167   int canSeek = 0;
168   int retVal = player_seek_available(player_, &canSeek);
169   if (retVal == PLAYER_ERROR_NONE && !canSeek)
170     is_player_seek_available_ = false;
171
172   GetAdaptiveStreamingInfo();
173   if (!blink::IsHbbTV() && is_live_stream_) {
174     UpdateSeekableTime();
175     StartSeekableTimeUpdateTimer();
176   }
177 }
178
179 void MediaPlayerBridgeCapiTV::StartSeekableTimeUpdateTimer() {
180   if (!seekable_time_update_timer_.IsRunning()) {
181     seekable_time_update_timer_.Start(
182         FROM_HERE, base::Milliseconds(kSeekableTimeUpdateInterval), this,
183         &MediaPlayerBridgeCapiTV::OnSeekableTimeUpdateTimerFired);
184   }
185 }
186
187 void MediaPlayerBridgeCapiTV::StopSeekableTimeUpdateTimer() {
188   if (seekable_time_update_timer_.IsRunning())
189     seekable_time_update_timer_.Stop();
190 }
191
192 void MediaPlayerBridgeCapiTV::OnSeekableTimeUpdateTimerFired() {
193   UpdateSeekableTime();
194 }
195
196 void MediaPlayerBridgeCapiTV::GetAdaptiveStreamingInfo() {
197   int ret = player_get_adaptive_streaming_info(player_, &is_live_stream_,
198                                                PLAYER_ADAPTIVE_INFO_IS_LIVE);
199   if (ret == PLAYER_ERROR_NONE && is_live_stream_) {
200     LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__
201               << " A live stream.";
202   }
203 }
204
205 void MediaPlayerBridgeCapiTV::UpdateSeekableTime() {
206   if (GetPlayerState() == PLAYER_STATE_NONE || !is_live_stream_)
207     return;
208
209   int64_t min = 0, max = 0;
210   if (GetLiveStreamingDuration(&min, &max)) {
211     if (min_seekable_time_.InMilliseconds() != min ||
212         max_seekable_time_.InMilliseconds() != max) {
213       min_seekable_time_ = base::Milliseconds(min);
214       max_seekable_time_ = base::Milliseconds(max);
215       if (GetMediaPlayerClient())
216       GetMediaPlayerClient()->OnSeekableTimeChange(
217           min_seekable_time_, max_seekable_time_, is_live_stream_);
218     }
219
220     return;
221   }
222
223   GetAdaptiveStreamingInfo();
224   if (!is_live_stream_) {
225     LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__
226               << " changed to static stream";
227     if (GetMediaPlayerClient())
228       GetMediaPlayerClient()->OnSeekableTimeChange({}, {}, is_live_stream_);
229     MediaPlayerBridgeCapi::UpdateDuration();
230   }
231 }
232
233 bool MediaPlayerBridgeCapiTV::GetLiveStreamingDuration(int64_t* min,
234                                                        int64_t* max) {
235   DCHECK(min);
236   DCHECK(max);
237   constexpr const size_t kDurationBufferSize = 64;
238   char live_duration[kDurationBufferSize] = {
239       0,
240   };
241   char* live_ptr = live_duration;
242   const auto err = player_get_adaptive_streaming_info(
243       player_, &live_ptr, PLAYER_ADAPTIVE_INFO_LIVE_DURATION);
244   if (err != PLAYER_ERROR_NONE) {
245     LOG(ERROR) << "(" << static_cast<void*>(this) << ") " << __func__
246                << " |player_get_adaptive_streaming_info| failed " << err;
247     return false;
248   }
249
250   const std::string duration(live_duration);
251   const std::string::size_type delimiter = duration.find('|');
252   if (delimiter == std::string::npos) {
253     LOG(ERROR) << "(" << static_cast<void*>(this) << ") " << __func__
254                << " Failed to find delimiter | in duration: " << duration;
255     return false;
256   }
257
258   const std::string duration_min = duration.substr(0, delimiter);
259   if (duration_min.empty()) {
260     LOG(ERROR) << "(" << static_cast<void*>(this) << ") " << __func__
261                << " Failed empty min sub str: " << duration << ", "
262                << delimiter;
263     return false;
264   }
265
266   int64_t out_min = 0;
267   if (!base::StringToInt64(duration_min, &out_min)) {
268     LOG(ERROR) << "(" << static_cast<void*>(this) << ") " << __func__
269                << " Failed to get min from duration: " << duration;
270     return false;
271   }
272
273   const std::string duration_max = duration.substr(delimiter + 1);
274   if (duration_max.empty()) {
275     LOG(ERROR) << "(" << static_cast<void*>(this) << ") " << __func__
276                << " empty max sub str: " << duration << ", " << delimiter;
277     return false;
278   }
279
280   int64_t out_max = 0;
281   if (!base::StringToInt64(duration_max, &out_max)) {
282     LOG(ERROR) << "(" << static_cast<void*>(this) << ") " << __func__
283                << " Failed to get max from duration: " << duration;
284     return false;
285   }
286
287   *min = out_min;
288   *max = out_max;
289   return true;
290 }
291
292 void MediaPlayerBridgeCapiTV::ParseDashInfo() {
293   std::string dash_info = GetDashInfo();
294   Json::CharReaderBuilder builder;
295   Json::CharReader* reader(builder.newCharReader());
296   Json::Value value;
297
298   if (reader->parse(dash_info.c_str(), dash_info.c_str() + dash_info.length(),
299                     &value, nullptr)) {
300     mrs_url_ = value["mrsUrl"].asString();
301     std::string periodId = value["periodId"].asString();
302     if (periodId != "")
303       content_id_ = clean_url_ + "#period=" + periodId;
304   }
305   LOG(INFO) << "mrsUrl: " << mrs_url_ << ",contentId: " << content_id_;
306 }
307
308 std::string MediaPlayerBridgeCapiTV::GetDashInfo() {
309   char* dash_info = nullptr;
310   // dash_info format:
311   // {"type":0,"minBufferTime":4000,"mrsUrl":"","periodId":"first"}
312   const int ret = player_get_dash_info(player_, &dash_info);
313   if (ret != PLAYER_ERROR_NONE) {
314     if (dash_info)
315       free(dash_info);
316     LOG(ERROR) << "Fail to call player_get_dash_info,ret:" << ret;
317     return "";
318   }
319
320   if (!dash_info) {
321     LOG(ERROR) << "empty dash_info.";
322     return "";
323   }
324
325   const std::string info(dash_info);
326   free(dash_info);
327   LOG(INFO) << "dash info str: " << info;
328
329   return info;
330 }
331
332 bool MediaPlayerBridgeCapiTV::GetDashLiveDuration(int64_t* duration) {
333   DCHECK(duration);
334   std::string dash_info = GetDashInfo();
335   Json::CharReaderBuilder builder;
336   Json::CharReader* reader(builder.newCharReader());
337   Json::Value value;
338   int64_t out_duration = 0;
339
340   if (reader->parse(dash_info.c_str(), dash_info.c_str() + dash_info.length(),
341                     &value, nullptr)) {
342     out_duration = value["mediaPresentationDuration"].asInt();
343   }
344
345   // According to dash spec, if duration == -1, set max time as duration.
346   if (out_duration == -1)
347     out_duration = base::TimeDelta::Max().InMilliseconds();
348   *duration = out_duration;
349
350   return true;
351 }
352
353 void MediaPlayerBridgeCapiTV::AppendUrlHighBitRate(const std::string& url) {
354   // don't use url.append("|STARTBITRATE=HIGHEST") to get hbbtv url
355   // "|" will be replaced with "%7C"
356   const char high_bitrate[] = "|STARTBITRATE=HIGHEST";
357   int len = url.length() + strlen(high_bitrate) + 1;
358   char* str_url = new char[len];
359   if (!str_url) {
360     return;
361   }
362
363   memset(str_url, 0, len);
364   strncat(str_url, url.c_str(), url.length());
365   strncat(str_url, high_bitrate, strlen(high_bitrate));
366   hbbtv_url_ = str_url;
367   BLINKFREE(str_url);
368   LOG(INFO) << "hbbtv url:" << hbbtv_url_.c_str();
369 }
370
371 bool MediaPlayerBridgeCapiTV::CheckHighBitRate() {
372   if (!GetMediaPlayerClient()) {
373     LOG(ERROR) << "MediaPlayerClient is null";
374     return false;
375   }
376   content::WebContentsDelegate* web_contents_delegate =
377       GetMediaPlayerClient()->GetWebContentsDelegate();
378   if (!web_contents_delegate) {
379     LOG(ERROR) << "get web_contents_delegate fail";
380     return false;
381   }
382   bool ret = web_contents_delegate->IsHighBitRate();
383   LOG(INFO) << "get high bit rate: " << std::boolalpha << ret;
384   return ret;
385 }
386
387 void MediaPlayerBridgeCapiTV::HandleDownloadableFontInfo(
388     const std::string& scheme_id_uri,
389     const std::string& value,
390     const std::string& data,
391     int type) {
392   content::WebContentsDelegate* web_contents_delegate =
393       GetMediaPlayerClient()->GetWebContentsDelegate();
394   if (!web_contents_delegate)
395     return;
396   web_contents_delegate->NotifyDownloadableFontInfo(scheme_id_uri, value, data,
397                                                     type);
398 }
399
400 bool MediaPlayerBridgeCapiTV::PreloadIfNeeded(int& ret) {
401   LOG(INFO) << "PreloadIfNeeded, is_preloaded_ " << is_preloaded_;
402   if (blink::IsHbbTV() && !is_preloaded_) {
403     ret = player_preloading_async(player_, -1, PlayerPreLoadingCb, this);
404     return true;
405   }
406
407   // fixup : kPlaybackReady status need checked by HBBTVResourceAcquired() patch
408   if (GetMediaPlayerClient())
409     GetMediaPlayerClient()->NotifyPlaybackState(kPlaybackReady, player_id_);
410   else
411     LOG(ERROR) << "(" << static_cast<void*>(this)
412                << "), GetMediaPlayerClient return null";
413   SetDisplayAtPausedState();
414   return false;
415 }
416
417 void MediaPlayerBridgeCapiTV::SetDisplayAtPausedState() {
418   int ret = PLAYER_ERROR_NONE;
419   if (!pending_seek_duration_.is_zero())
420     ret = player_display_video_at_paused_state(player_, false);
421   else
422     ret = player_display_video_at_paused_state(player_, true);
423
424   if (ret != PLAYER_ERROR_NONE)
425     LOG(ERROR) << "player_display_video_at_paused_state() failed";
426 }
427
428 void MediaPlayerBridgeCapiTV::UpdateDuration() {
429   LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__;
430   if (blink::IsHbbTV() && !is_preloaded_) {
431     LOG(INFO) << "HBBTV preload not finished, no need update duration. ";
432     return;
433   }
434   if (is_live_stream_) {
435     int64_t duration = 0;
436     if (stream_type_ == HLS_STREAM) {
437       int64_t min = 0;
438       if (!GetLiveStreamingDuration(&min, &duration)) {
439         LOG(ERROR) << "Fail to get duration for hls live stream.";
440         return;
441       }
442     } else if (stream_type_ == DASH_STREAM) {
443       if (!GetDashLiveDuration(&duration)) {
444         if (duration_ != base::TimeDelta::Max()) {
445           duration_ = base::TimeDelta::Max();
446           OnDurationChange(player_id_, duration_.InSecondsF());
447         }
448         return;
449       }
450     } else {
451       LOG(ERROR) << "Unknown live stream type : " << stream_type_;
452     }
453
454     if (duration == 0) {
455       LOG(WARNING) << "live stream type : convert duration to max";
456       duration_ = base::TimeDelta::Max();
457       OnDurationChange(player_id_, duration_.InSecondsF());
458     } else if (duration_.InSecondsF() !=
459                ConvertMilliSecondsToSeconds(duration)) {
460       duration_ = base::Milliseconds(duration);
461       OnDurationChange(player_id_, duration_.InSecondsF());
462     }
463   } else {  // non-live stream sequence
464     MediaPlayerBridgeCapi::UpdateDuration();
465   }
466 }
467
468 void MediaPlayerBridgeCapiTV::UpdateMediaType() {
469   LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__;
470
471   if (blink::IsHbbTV() && !is_preloaded_) {
472     LOG(INFO) << "HBBTV preload not finished, no need update media type. ";
473     return;
474   }
475   MediaPlayerBridgeCapi::UpdateMediaType();
476 }
477
478 bool MediaPlayerBridgeCapiTV::CheckLiveStreaming() const {
479   int isLive = 0;
480   int retVal = player_get_adaptive_streaming_info(player_, &isLive,
481                                                   PLAYER_ADAPTIVE_INFO_IS_LIVE);
482   if (retVal != PLAYER_ERROR_NONE) {
483     LOG(ERROR) << "player_get_adaptive_streaming_info failed, error: "
484                << retVal;
485     return false;
486   }
487
488   if (!isLive)
489     return false;
490
491   LOG(INFO) << "This is a live streaming.";
492   return true;
493 }
494
495 void MediaPlayerBridgeCapiTV::OnPlayerPreloading() {
496   task_runner_->PostTask(
497       FROM_HERE, base::BindOnce(&MediaPlayerBridgeCapiTV::PlayerPreloaded,
498                                 weak_factory_.GetWeakPtr()));
499 }
500
501 bool MediaPlayerBridgeCapiTV::HBBTVResourceAcquired() {
502   bool media_resource_acquired = false;
503   if (!GetMediaPlayerClient()) {
504     LOG(ERROR) << "MediaPlayerTizenClient is nullptr";
505     return false;
506   }
507
508   GetMediaPlayerClient()->NotifyPlaybackState(
509       kPlaybackReady, player_id_, url_.spec(), mime_type_,
510       &media_resource_acquired, NULL, NULL);
511   if (!media_resource_acquired) {
512     GetMediaPlayerClient()->NotifyPlaybackState(kPlaybackStop, player_id_);
513     LOG(ERROR) << "HBBTV media resource acquired failed";
514   }
515   return media_resource_acquired;
516 }
517
518 void MediaPlayerBridgeCapiTV::PlayerPreloaded() {
519   LOG(INFO) << "PlayerPreloaded,this: " << this
520             << ",player_prepared_:" << player_prepared_;
521
522   is_preloaded_ = true;
523   is_live_stream_ = CheckLiveStreaming();
524   if (stream_type_ == DASH_STREAM)
525     ParseDashInfo();
526   if (is_live_stream_ && stream_type_ != OTHER_STREAM) {
527     // UpdateSeekableTime();
528     // StartSeekableTimeUpdateTimer();
529   }
530   // UpdateAudioTrackInfo();
531   // UpdateVideoTrackInfo();
532   // UpdateTextTrackInfo();
533   UpdateDuration();
534   UpdateMediaType();
535   if (GetMediaType() == MediaType::Invalid) {
536     LOG(ERROR) << "Media type is not valid!";
537     return;
538   }
539
540   OnReadyStateChange(player_id_,
541                      blink::WebMediaPlayer::kReadyStateHaveFutureData);
542   OnNetworkStateChange(player_id_, blink::WebMediaPlayer::kNetworkStateLoading);
543
544   if (!player_prepared_ && HBBTVResourceAcquired()) {
545     int ret = SetPlayerPrepareAsync();
546     if (ret != PLAYER_ERROR_NONE) {
547       OnHandlePlayerError(ret, FROM_HERE);
548     }
549   }
550 }
551
552 bool MediaPlayerBridgeCapiTV::PlayerPrePlay() {
553   LOG(INFO) << "PlayerPrePlay, this: " << this
554             << ",is_player_prepared : " << player_prepared_;
555   if (IsPlayerSuspended()) {
556     LOG(INFO) << "PlayerPrePlay while player is suspended";
557     return false;
558   }
559
560   if (!HBBTVResourceAcquired()) {
561     LOG(INFO)
562         << "PlayerPrePlay while it's not in case of HBBTV Resource Acquired";
563     return false;
564   }
565
566   delayed_player_state_ = PLAYER_STATE_DELAYED_PLAY;
567   LOG(INFO) << "begin to |player_prepare_async|";
568
569   SetDisplayAtPausedState();
570   int ret = SetPlayerPrepareAsync();
571   if (ret != PLAYER_ERROR_NONE) {
572     OnHandlePlayerError(ret, FROM_HERE);
573     return false;
574   }
575
576   return true;
577 }
578 void MediaPlayerBridgeCapiTV::Initialize(VideoRendererSink* sink) {
579   player_set_drm_error_cb(player_, DrmErrorCb, this);
580   MediaPlayerBridgeCapi::Initialize(sink);
581 }
582
583 bool MediaPlayerBridgeCapiTV::SetDrmInfo(std::string& drm_info) {
584   // The DRM info from HbbTV comes as a JSON-like string in the following
585   // format:
586   // pair = Property ':' Value
587   // string = pair {',' pair}
588   std::vector<std::string> drm_info_pairs = base::SplitStringUsingSubstr(
589       drm_info, ", ", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
590   for (auto it = drm_info_pairs.begin(); it != drm_info_pairs.end(); ++it) {
591     std::vector<std::string> drm_info_pair = base::SplitStringUsingSubstr(
592         *it, ": ", base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
593
594     if (drm_info_pair.size() != 2)
595       continue;
596
597     std::string trim_key = drm_info_pair.at(0);
598     std::string trim_value = drm_info_pair.at(1);
599     LOG(INFO) << "trim_key: " << trim_key.c_str()
600               << ",trim_value: " << trim_value.c_str();
601
602     if (!SetMediaDRMInfo(trim_key, trim_value)) {
603       LOG(ERROR)
604           << "MediaPlayerBridgeCapiTV::SetDrmInfo SetMediaDRMInfo failed";
605       return false;
606     }
607   }
608
609   return true;
610 }
611
612 bool MediaPlayerBridgeCapiTV::SetMediaDRMInfo(const std::string& type_data,
613                                               const std::string& value_data) {
614   LOG(INFO) << "player_set_drm_info(type_length(" << type_data.length() << ") "
615             << " value_length(" << value_data.length() << ")) ";
616   int ret = PLAYER_ERROR_INVALID_OPERATION;
617   const void* type_data_ptr = type_data.c_str();
618   const void* value_data_ptr = value_data.c_str();
619   player_drm_type_e drm_type = PLAYER_DRM_TYPE_PLAYREADY;
620   ret = player_set_drm_info(player_, type_data_ptr, type_data.length(),
621                             value_data_ptr, value_data.length(), drm_type);
622   if (ret != PLAYER_ERROR_NONE) {
623     MediaPlayerBridgeCapi::OnHandlePlayerError(ret, FROM_HERE);
624     return false;
625   }
626
627   return true;
628 }
629
630 void MediaPlayerBridgeCapiTV::OnDrmError(int err_code, char* err_str) {
631   LOG(ERROR) << "OnDrmError err_str[" << err_str << "]";
632   if (!task_runner_->BelongsToCurrentThread()) {
633     task_runner_->PostTask(
634         FROM_HERE,
635         base::BindOnce(&MediaPlayerBridgeCapiTV::OnDrmError,
636                        weak_factory_.GetWeakPtr(), err_code, err_str));
637   }
638   MediaPlayerBridgeCapi::OnHandlePlayerError(err_code, FROM_HERE);
639 }
640
641 void MediaPlayerBridgeCapiTV::HandleParentalRatingInfo(const std::string& info,
642                                                        const std::string& url) {
643   content::WebContentsDelegate* web_contents_delegate =
644       GetMediaPlayerClient()->GetWebContentsDelegate();
645   if (!web_contents_delegate){
646     LOG(ERROR) << "web_contents_delegate is null";
647     return;
648   }
649   web_contents_delegate->NotifyParentalRatingInfo(info, url);
650 }
651
652 void MediaPlayerBridgeCapiTV::SetParentalRatingResult(bool is_pass) {
653   LOG(INFO) << "ParentalRatingResult:" << std::boolalpha << is_pass;
654   parental_rating_pass_ = is_pass;
655
656   // if authentication fail, raise MEDIA_ERROR_DECODE
657   if (!parental_rating_pass_) {
658     OnHandlePlayerError(PLAYER_ERROR_INVALID_OPERATION, FROM_HERE);
659     return;
660   }
661
662   if (player_prepared_) {
663     LOG(INFO) << "player already prepared,execute play";
664     ExecuteDelayedPlayerState();
665   }
666 }
667 }  // namespace media