[M120 Migration][MM] Handle live stream duration and currenttime
[platform/framework/web/chromium-efl.git] / tizen_src / chromium_impl / media / filters / media_player_bridge_capi.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.h"
6
7 #include "base/logging.h"
8 #include "base/strings/string_util.h"
9 #include "build/tizen_version.h"
10 #include "media/base/buffering_state.h"
11 #include "media/base/efl/media_player_util_efl.h"
12 #include "third_party/libyuv/include/libyuv/planar_functions.h"
13 #include "tizen_src/chromium_impl/media/filters/media_player_tizen_client.h"
14 #include "ui/gfx/geometry/size.h"
15
16 #if defined(TIZEN_VIDEO_HOLE)
17 #include <Ecore_Wl2.h>
18 #include "tizen_src/chromium_impl/media/base/tizen/video_plane_controller_capi.h"
19 #if BUILDFLAG(IS_TIZEN_TV)
20 #include <player_product_platform_interface.h>
21 #endif
22 #endif
23
24 namespace {
25 // Update duration every 100ms.
26 const int kDurationUpdateInterval = 100;
27
28 // TODO(max): Remove these proxy free functions.
29
30 // Called by player_prepare_async()
31 // It's guaranteed that no callback after player destructed.
32 static void PlayerPreparedCb(void* data) {
33   DCHECK(data);
34   media::MediaPlayerBridgeCapi* player =
35       static_cast<media::MediaPlayerBridgeCapi*>(data);
36
37   player->OnPlayerPrepared();
38 }
39
40 static void MediaPacketDecodedCb(media_packet_h packet, void* data) {
41   DCHECK(data);
42   if (!packet) {
43     LOG(ERROR) << "media_packet handle is null";
44     return;
45   }
46   media::MediaPlayerBridgeCapi* player =
47       static_cast<media::MediaPlayerBridgeCapi*>(data);
48
49   player->OnMediaPacketUpdated(packet);
50 }
51
52 // Called by player_set_completed_cb()
53 static void PlaybackCompleteCb(void* data) {
54   DCHECK(data);
55   media::MediaPlayerBridgeCapi* player =
56       static_cast<media::MediaPlayerBridgeCapi*>(data);
57
58   player->OnPlaybackCompleteUpdate();
59 }
60
61 // Called by player_set_play_position() / player_set_position()
62 static void SeekCompletedCb(void* data) {
63   DCHECK(data);
64   media::MediaPlayerBridgeCapi* player =
65       static_cast<media::MediaPlayerBridgeCapi*>(data);
66
67   player->OnSeekCompleteUpdate();
68 }
69
70 // Called by player_set_buffering_cb()
71 static void ChangedBufferingStatusCb(int percent, void* data) {
72   DCHECK(data);
73   media::MediaPlayerBridgeCapi* player =
74       static_cast<media::MediaPlayerBridgeCapi*>(data);
75
76   player->OnHandleBufferingStatus(percent);
77 }
78
79 // Called by player_set_error_cb()
80 static void ErrorCb(int error_code, void* data) {
81   DCHECK(data);
82   media::MediaPlayerBridgeCapi* player =
83       static_cast<media::MediaPlayerBridgeCapi*>(data);
84
85   player->OnHandlePlayerError(error_code, FROM_HERE);
86 }
87
88 // Called by player_set_interrupted_cb()
89 static void InterruptCb(player_interrupted_code_e code, void* data) {
90   DCHECK(data);
91   media::MediaPlayerBridgeCapi* player =
92       static_cast<media::MediaPlayerBridgeCapi*>(data);
93
94   player->OnResourceConflict();
95 }
96
97 }  // namespace
98
99 namespace media {
100
101 MediaPlayerBridgeCapi::MediaPlayerBridgeCapi(const GURL& url,
102                                              const std::string& user_agent,
103                                              double volume)
104     : task_runner_(base::SingleThreadTaskRunner::GetCurrentDefault()),
105       delayed_player_state_(PLAYER_STATE_DELAYED_NULL),
106       url_(url),
107       volume_(volume),
108       user_agent_(user_agent),
109       weak_factory_(this) {
110   LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__;
111 }
112
113 MediaPlayerBridgeCapi::~MediaPlayerBridgeCapi() {
114   LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__;
115
116   Release();
117   weak_factory_.InvalidateWeakPtrs();
118   player_destroy(player_);
119 }
120
121 bool MediaPlayerBridgeCapi::IsInitialized() {
122   LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__
123             << " ; state : " << GetPlayerState();
124   // create_player is called before Initialized
125   // after create_player state change to PLAYER_STATE_IDLE
126   return (GetPlayerState() > PLAYER_STATE_IDLE);
127 }
128
129 bool MediaPlayerBridgeCapi::IsPrepared() {
130   return (GetPlayerState() >= PLAYER_STATE_READY);
131 }
132
133 bool MediaPlayerBridgeCapi::CanPrepare() {
134   return !IsPrepared() && !is_preparing_;
135 }
136
137 void MediaPlayerBridgeCapi::Flush(base::OnceClosure flush_cb) {
138   if (flush_cb)
139     std::move(flush_cb).Run();
140 }
141
142 void MediaPlayerBridgeCapi::SetTaskRunner(
143     const scoped_refptr<base::SingleThreadTaskRunner>& task_runner) {
144   task_runner_ = task_runner.get();
145 }
146
147 bool MediaPlayerBridgeCapi::CreatePlayer(int player_id) {
148   player_id_ = player_id;
149
150   // Player is created, state change to PLAYER_STATE_IDLE
151   int ret = player_create(&player_);
152   if (ret != PLAYER_ERROR_NONE) {
153     OnHandlePlayerError(ret, FROM_HERE);
154     return false;
155   }
156   return true;
157 }
158
159 void MediaPlayerBridgeCapi::Prepare() {
160   LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__
161             << " ; player: " << player_ << " ; url: " << url_.spec().c_str();
162   int ret = PLAYER_ERROR_NONE;
163   if (url_.SchemeIsFile())
164     is_file_url_ = true;
165
166   player_set_uri(player_, url_.spec().c_str());
167 #if !defined(EWK_BRINGUP)
168   player_set_sound_type(player_, SOUND_TYPE_MEDIA);
169 #endif
170   player_set_volume(player_, static_cast<float>(volume_),
171                     static_cast<float>(volume_));
172   if (player_set_streaming_user_agent(player_, user_agent_.c_str(),
173                                       user_agent_.length()) !=
174       PLAYER_ERROR_NONE)
175     LOG(ERROR) << "Unable to set streaming user agent.";
176
177 #if defined(TIZEN_VIDEO_HOLE)
178   if (is_video_hole_) {
179     if (video_plane_controller_->rendering_mode() ==
180         VideoPlaneController::RenderingMode::OFFSCREEN) {
181       ret = player_set_display(player_, PLAYER_DISPLAY_TYPE_OVERLAY,
182                                video_plane_controller_->GetVideoPlaneHandle());
183     } else {
184       Ecore_Wl2_Window* window_handle = static_cast<Ecore_Wl2_Window*>(
185           video_plane_controller_->GetVideoPlaneHandle());
186       int wl_w, wl_h, wl_x, wl_y;
187       ecore_wl2_window_geometry_get(window_handle, &wl_x, &wl_y, &wl_w, &wl_h);
188 #if BUILDFLAG(IS_TIZEN_TV)
189       unsigned int resource_id =
190           ecore_wl2_window_resource_id_get(window_handle);
191       ret = player_set_display_webapp(player_, PLAYER_DISPLAY_TYPE_OVERLAY,
192                                       resource_id, wl_h, wl_w, wl_x, wl_y);
193 #else
194       ret = player_set_ecore_wl_display(player_, PLAYER_DISPLAY_TYPE_OVERLAY,
195                                         window_handle, wl_x, wl_y, wl_w, wl_h);
196 #endif
197     }
198
199     if (ret != PLAYER_ERROR_NONE) {
200       OnHandlePlayerError(ret, FROM_HERE);
201       return;
202     }
203   } else
204 #endif
205   {
206     ret = player_set_media_packet_video_frame_decoded_cb(
207         player_, MediaPacketDecodedCb, this);
208     if (ret != PLAYER_ERROR_NONE) {
209       OnHandlePlayerError(ret, FROM_HERE);
210       return;
211     }
212   }
213
214   if (!PreloadIfNeeded(ret))
215     SetPlayerPrepareAsync();
216
217   is_preparing_ = true;
218   OnReadyStateChange(player_id_, blink::WebMediaPlayer::kReadyStateHaveNothing);
219   OnNetworkStateChange(player_id_, blink::WebMediaPlayer::kNetworkStateLoading);
220 }
221
222 bool MediaPlayerBridgeCapi::SetPlayerPrepareAsync() {
223   int ret = player_prepare_async(player_, PlayerPreparedCb, this);
224   if (ret != PLAYER_ERROR_NONE) {
225     OnHandlePlayerError(ret, FROM_HERE);
226     return false;
227   }
228
229   return true;
230 }
231
232 void MediaPlayerBridgeCapi::OnMediaError(MediaError error_type) {
233   LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__
234             << " error_type : " << error_type;
235   StopBufferingUpdateTimer();
236   StopCurrentTimeUpdateTimer();
237
238   blink::WebMediaPlayer::NetworkState state =
239       blink::WebMediaPlayer::kNetworkStateEmpty;
240
241   switch (error_type) {
242     case MEDIA_ERROR_FORMAT:
243       state = blink::WebMediaPlayer::kNetworkStateFormatError;
244       break;
245     case MEDIA_ERROR_DECODE:
246       state = blink::WebMediaPlayer::kNetworkStateDecodeError;
247       break;
248     case MEDIA_ERROR_NETWORK:
249       state = blink::WebMediaPlayer::kNetworkStateNetworkError;
250       break;
251   }
252
253   OnNetworkStateChange(player_id_, state);
254   ReleaseDisplayLock();
255 }
256
257 void MediaPlayerBridgeCapi::Initialize(VideoRendererSink* sink) {
258   LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__;
259
260   // register capi-player callback
261   player_set_completed_cb(player_, PlaybackCompleteCb, this);
262   player_set_buffering_cb(player_, ChangedBufferingStatusCb, this);
263   player_set_interrupted_cb(player_, InterruptCb, this);
264   player_set_error_cb(player_, ErrorCb, this);
265
266 #if defined(TIZEN_VIDEO_HOLE)
267   if (is_video_hole_) {
268     if (!video_plane_controller_)
269       return;
270
271     int ret = video_plane_controller_->Initialize();
272     if (ret != PLAYER_ERROR_NONE) {
273       OnHandlePlayerError(ret, FROM_HERE);
274       return;
275     }
276   }
277 #endif
278 }
279
280 void MediaPlayerBridgeCapi::Resume() {
281   LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__;
282   suspended_ = false;
283   Prepare();
284 }
285
286 void MediaPlayerBridgeCapi::Suspend() {
287   LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__;
288   if (IsPlayerSuspended()) {
289     LOG(INFO) << "Player already suspended. Nothing to do. Returning";
290     return;
291   }
292
293   is_paused_ = true;
294   is_seeking_ = false;
295   is_play_pending_ = false;
296   seek_duration_ = base::TimeDelta();
297   suspended_ = true;
298   playback_time_ = GetCurrentTime();
299
300   Release();
301
302   // Rare scenario: Player's resource are released while prerolling.
303   // In this case we need to inform HTMLMediaElement that we can play,
304   // otherwise we will never be able to play such video.
305   if (GetPlayerState() == PLAYER_STATE_NONE) {
306     OnReadyStateChange(player_id_,
307                        blink::WebMediaPlayer::kReadyStateHaveEnoughData);
308     OnNetworkStateChange(player_id_,
309                          blink::WebMediaPlayer::kNetworkStateLoaded);
310   }
311
312   // manager()->OnPauseStateChange(player_id_, true);
313 }
314
315 void MediaPlayerBridgeCapi::Release() {
316   LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__;
317   is_preparing_ = false;
318   StopCurrentTimeUpdateTimer();
319   StopBufferingUpdateTimer();
320   player_unset_completed_cb(player_);
321   player_unset_interrupted_cb(player_);
322   player_unset_error_cb(player_);
323   player_unset_buffering_cb(player_);
324
325   if (GetPlayerState() > PLAYER_STATE_READY &&
326       player_stop(player_) != PLAYER_ERROR_NONE) {
327     LOG(ERROR) << "|player_stop| failed";
328   }
329
330 #if defined(TIZEN_VIDEO_HOLE)
331   if (!is_video_hole_)
332 #endif
333     player_unset_media_packet_video_frame_decoded_cb(player_);
334
335   if (GetPlayerState() >= PLAYER_STATE_IDLE &&
336       player_unprepare(player_) != PLAYER_ERROR_NONE)
337     LOG(ERROR) << "|player_unprepare| failed";
338
339   // manager()->OnSuspendComplete(player_id_);
340 }
341
342 bool MediaPlayerBridgeCapi::Play() {
343   LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__;
344
345   if (IsPlayerSuspended()) {
346     is_play_pending_ = true;
347     delayed_player_state_ = PLAYER_STATE_DELAYED_PLAY;
348     if (playback_time_ != base::Milliseconds(0)) {
349       delayed_player_state_ = PLAYER_STATE_DELAYED_SEEK;
350       pending_seek_duration_ = playback_time_;
351     }
352     Resume();
353     return false;
354   }
355
356   if (is_seeking_) {
357     delayed_player_state_ = PLAYER_STATE_DELAYED_PLAY;
358     return false;
359   }
360
361   if (GetPlayerState() < PLAYER_STATE_READY || !player_prepared_) {
362     LOG(ERROR) << "(" << static_cast<void*>(this) << ") " << __func__
363                << " Player is not ready.";
364     delayed_player_state_ = PLAYER_STATE_DELAYED_PLAY;
365     return false;
366   }
367
368   if (playback_rate_ == 0.0) {
369     is_paused_ = false;
370     return false;
371   }
372
373   if (is_set_playback_rate_delayed_) {
374     is_set_playback_rate_delayed_ = false;
375     SetRate(playback_rate_);
376   }
377
378   if (player_start(player_) != PLAYER_ERROR_NONE) {
379     LOG(ERROR) << "|player_start| failed";
380     return false;
381   }
382
383 #if defined(TIZEN_VIDEO_HOLE)
384   if (!delayed_rect_.IsEmpty() && !delayed_viewport_rect_.IsEmpty()) {
385     SetMediaGeometry(delayed_viewport_rect_, delayed_rect_);
386     delayed_viewport_rect_ = gfx::Rect();
387     delayed_rect_ = gfx::RectF();
388   }
389 #endif
390
391   WakeUpDisplayAndAcquireDisplayLock();
392
393   StartCurrentTimeUpdateTimer();
394   if (!is_file_url_)
395     StartBufferingUpdateTimer();
396   is_paused_ = false;
397   is_end_reached_ = false;
398
399   return true;
400 }
401
402 void MediaPlayerBridgeCapi::Pause(bool /* is_media_related_action */) {
403   LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__;
404
405   if (GetPlayerState() != PLAYER_STATE_PLAYING) {
406     LOG(ERROR) << "Player is not in playing state, no need to pause.";
407     return;
408   }
409
410   if (is_seeking_) {
411     delayed_player_state_ = PLAYER_STATE_DELAYED_PAUSE;
412     return;
413   }
414
415   if (player_pause(player_) != PLAYER_ERROR_NONE) {
416     LOG(ERROR) << "|player_pause| failed";
417     return;
418   }
419
420   if (!is_file_url_)
421     StartBufferingUpdateTimer();
422
423   ReleaseDisplayLock();
424   StopCurrentTimeUpdateTimer();
425   is_paused_ = true;
426 }
427
428 void MediaPlayerBridgeCapi::SetRate(double rate) {
429   LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__
430             << " rate: " << rate;
431
432   if (playback_rate_ == rate)
433     return;
434
435   if (GetPlayerState() < PLAYER_STATE_READY) {
436     LOG(ERROR) << "(" << static_cast<void*>(this) << ") " << __func__
437                << " ; Player is not ready.";
438     playback_rate_ = rate;
439     is_set_playback_rate_delayed_ = true;
440     return;
441   }
442
443   if (rate == 0.0) {
444     playback_rate_ = rate;
445     Pause(true);
446     return;
447   }
448
449   if (!is_file_url_ &&
450       player_set_streaming_playback_rate(player_, static_cast<float>(rate)) !=
451           PLAYER_ERROR_NONE) {
452     LOG(ERROR) << "|player_set_streaming_playback_rate| failed";
453     return;
454   } else if (player_set_playback_rate(player_, static_cast<float>(rate)) !=
455              PLAYER_ERROR_NONE) {
456     LOG(ERROR) << "|player_set_playback_rate| failed";
457     return;
458   }
459
460   // If previous rate was zero and requested rate is non-zero, change the
461   // playback rate and call play.
462   if (playback_rate_ == 0.0) {
463     playback_rate_ = rate;
464     Play();
465   } else {
466     playback_rate_ = rate;
467   }
468 }
469
470 void MediaPlayerBridgeCapi::Seek(base::TimeDelta time,
471                                  base::OnceClosure seek_cb) {
472   LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__
473             << " time: " << time.InSecondsF();
474
475   seek_cb_ = std::move(seek_cb);
476   if (IsPlayerSuspended() && playback_time_ != time) {
477     playback_time_ = time;
478     delayed_player_state_ = PLAYER_STATE_DELAYED_SEEK;
479     pending_seek_duration_ = playback_time_;
480     OnTimeUpdate(player_id_, playback_time_);
481     OnTimeChanged(player_id_);
482     Resume();
483     return;
484   }
485
486   SeekInternal(time);
487 }
488
489 void MediaPlayerBridgeCapi::SeekInternal(base::TimeDelta time) {
490   int err = player_set_play_position(
491       player_, ConvertSecondsToMilliSeconds(time.InSecondsF()), true,
492       SeekCompletedCb, this);
493   if (err != PLAYER_ERROR_NONE) {
494     LOG(ERROR) << "|player_set_play_position| failed";
495     OnTimeUpdate(player_id_, GetCurrentTime());
496     OnTimeChanged(player_id_);
497     if (seek_cb_)
498       std::move(seek_cb_).Run();
499     return;
500   }
501
502   if (!is_paused_)
503     StopCurrentTimeUpdateTimer();
504
505   StopBufferingUpdateTimer();
506   UpdateSeekState(true);
507   seek_duration_ = time;
508   is_end_reached_ = time != duration_ ? false : true;
509   OnTimeUpdate(player_id_, time);
510
511   if (!is_paused_)
512     StartCurrentTimeUpdateTimer();
513 }
514
515 void MediaPlayerBridgeCapi::SetVolume(double volume) {
516   LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__
517             << " volume: " << volume;
518   if (!IsPrepared()) {
519     LOG(ERROR) << "Player is not ready.";
520     return;
521   }
522
523   if (player_set_volume(player_, volume, volume) != PLAYER_ERROR_NONE)
524     LOG(ERROR) << "|player_set_volume| failed";
525
526   volume_ = volume;
527 }
528
529 #if defined(TIZEN_VIDEO_HOLE)
530 void MediaPlayerBridgeCapi::SetVideoHole(bool is_video_hole) {
531   LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__
532             << " is_video_hole : " << is_video_hole;
533   is_video_hole_ = is_video_hole;
534   if (is_video_hole_ && player_ && !video_plane_controller_) {
535     video_plane_controller_.reset(new VideoPlaneControllerCapi(player_));
536   }
537 }
538
539 void MediaPlayerBridgeCapi::SetMediaGeometry(const gfx::Rect& viewport_rect,
540                                              const gfx::RectF& rect) {
541   LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__;
542   if (!is_video_hole_)
543     return;
544
545   if (GetPlayerState() < PLAYER_STATE_PLAYING) {
546     delayed_viewport_rect_ = viewport_rect;
547     delayed_rect_ = rect;
548     return;
549   }
550
551   LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__
552             << " viewport_rect: " << viewport_rect.ToString()
553             << " rect : " << rect.ToString();
554   video_plane_controller_->SetMediaGeometry(viewport_rect, rect);
555 }
556 #endif
557
558 void MediaPlayerBridgeCapi::RequestSuspend(bool resource_conflicted) {
559   LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__;
560   GetMediaPlayerClient()->OnRequestSuspend(resource_conflicted);
561   Suspend();
562 }
563
564 void MediaPlayerBridgeCapi::UpdateMediaType() {
565   LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__;
566   int sample_rate = 0;
567   int channel = 0;
568   int audio_bit_rate = 0;
569   media_type_ = MediaType::Invalid;
570
571   int err = player_get_audio_stream_info(player_, &sample_rate, &channel,
572                                          &audio_bit_rate);
573   if (err != PLAYER_ERROR_NONE) {
574     OnHandlePlayerError(err, FROM_HERE);
575     return;
576   }
577
578   // Audio stream is present if sample rate is valid.
579   if (sample_rate > 0)
580     media_type_ |= MediaType::Audio;
581
582   // Video stream is present if both video width and height are valid.
583   if (width_ > 0 && height_ > 0)
584     media_type_ |= MediaType::Video;
585
586   OnMediaDataChange(player_id_, width_, height_, media_type_);
587 }
588
589 void MediaPlayerBridgeCapi::UpdateDuration() {
590   int duration = 0;
591   int ret = player_get_duration(player_, &duration);
592   if (ret != PLAYER_ERROR_NONE) {
593     OnHandlePlayerError(ret, FROM_HERE);
594     return;
595   }
596
597   if (duration_.InSecondsF() != ConvertMilliSecondsToSeconds(duration)) {
598     duration_ = base::Milliseconds(duration);
599     OnDurationChange(player_id_, duration_.InSecondsF());
600   }
601
602   // No need to buffer 'local file'. Update buffered percentage.
603   if (is_file_url_) {
604     std::vector<TimeRanges> buffer_range;
605     TimeRanges range;
606     range.start = 0;
607     range.end = duration_.InSecondsF() * base::Time::kMicrosecondsPerSecond;
608     buffer_range.push_back(range);
609     OnBufferUpdate(player_id_, buffer_range);
610   }
611 }
612
613 base::TimeDelta MediaPlayerBridgeCapi::GetCurrentTime() {
614   // If we're seeking or have a stashed pending seek, let's return the seek
615   // time, because the underlying player calls might return pre-seek values.
616   if (delayed_player_state_ == PLAYER_STATE_DELAYED_SEEK) {
617     return pending_seek_duration_;
618   }
619
620   if (is_seeking_) {
621     return seek_duration_;
622   }
623
624   // For http://instagram.com/p/tMQOo0lWqm/
625   // After playback completed current-time and duration are not equal.
626   if (is_end_reached_) {
627     if (playback_rate_ < 0)
628       return base::TimeDelta();
629     if (!is_live_stream_ && duration_.InSecondsF())
630       return duration_;
631   }
632
633   int postion = 0;
634   player_get_play_position(player_, &postion);
635   return base::Milliseconds(postion);
636 }
637
638 void MediaPlayerBridgeCapi::OnCurrentTimeUpdateTimerFired() {
639   OnTimeUpdate(player_id_, GetCurrentTime());
640   UpdateDuration();
641 }
642
643 void MediaPlayerBridgeCapi::StartCurrentTimeUpdateTimer() {
644   if (!current_time_update_timer_.IsRunning()) {
645     current_time_update_timer_.Start(
646         FROM_HERE, base::Milliseconds(kDurationUpdateInterval), this,
647         &MediaPlayerBridgeCapi::OnCurrentTimeUpdateTimerFired);
648   }
649 }
650
651 void MediaPlayerBridgeCapi::StopCurrentTimeUpdateTimer() {
652   if (current_time_update_timer_.IsRunning())
653     current_time_update_timer_.Stop();
654 }
655
656 void MediaPlayerBridgeCapi::OnBufferingUpdateTimerFired() {
657   /* player_get_streaming_download_progress is not apply for live stream
658      here no need triggered*/
659   if (is_live_stream_)
660     return;
661
662   int start = 0, current = 0;
663   if (player_get_streaming_download_progress(player_, &start, &current) ==
664       PLAYER_ERROR_NONE) {
665     if (current == 100) {
666       StopBufferingUpdateTimer();
667       OnNetworkStateChange(player_id_,
668                            blink::WebMediaPlayer::kNetworkStateLoaded);
669     }
670     std::vector<TimeRanges> buffer_range;
671     TimeRanges range;
672     range.start = 0;
673
674     // Get current% of |duration_| and convert into microseconds
675     range.end = ((duration_.InSecondsF() * current) / 100) *
676                 base::Time::kMicrosecondsPerSecond;
677     buffer_range.push_back(range);
678     OnBufferUpdate(player_id_, buffer_range);
679   }
680 }
681
682 void MediaPlayerBridgeCapi::StartBufferingUpdateTimer() {
683   if (!buffering_update_timer_.IsRunning()) {
684     buffering_update_timer_.Start(
685         FROM_HERE, base::Milliseconds(kDurationUpdateInterval), this,
686         &MediaPlayerBridgeCapi::OnBufferingUpdateTimerFired);
687   }
688 }
689
690 void MediaPlayerBridgeCapi::StopBufferingUpdateTimer() {
691   if (buffering_update_timer_.IsRunning())
692     buffering_update_timer_.Stop();
693 }
694
695 void MediaPlayerBridgeCapi::OnTimeChanged() {
696   DCHECK(task_runner_->BelongsToCurrentThread());
697   OnTimeChanged(player_id_);
698 }
699
700 void MediaPlayerBridgeCapi::PlaybackCompleteUpdate() {
701   LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__;
702   is_end_reached_ = true;
703   ReleaseDisplayLock();
704
705   StopCurrentTimeUpdateTimer();
706   OnTimeUpdate(player_id_, GetCurrentTime());
707   OnTimeChanged(player_id_);
708   GetMediaPlayerClient()->OnEnded();
709 }
710
711 void MediaPlayerBridgeCapi::SeekCompleteUpdate() {
712   LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__;
713   UpdateSeekState(false);
714   OnTimeChanged(player_id_);
715
716   if (!is_file_url_)
717     StartBufferingUpdateTimer();
718
719   if (is_play_pending_) {
720     is_play_pending_ = false;
721     delayed_player_state_ =
722         is_end_reached_ ? PLAYER_STATE_DELAYED_NULL : PLAYER_STATE_DELAYED_PLAY;
723   }
724
725   if (seek_cb_)
726     std::move(seek_cb_).Run();
727   ExecuteDelayedPlayerState();
728 }
729
730 void MediaPlayerBridgeCapi::UpdateSeekState(bool state) {
731   is_seeking_ = state;
732 }
733
734 void MediaPlayerBridgeCapi::PlayerPrepared() {
735   LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__;
736   if (GetPlayerState() < PLAYER_STATE_READY) {
737     return;
738   }
739
740   player_prepared_ = true;
741   is_preparing_ = false;
742
743 #if defined(TIZEN_VIDEO_HOLE)
744   if (is_video_hole_)
745     video_plane_controller_->ApplyDeferredVideoRectIfNeeded();
746 #endif
747
748   UpdateMediaType();
749   if (media_type_ == 0) {
750     return;
751   }
752   UpdateDuration();
753   OnReadyStateChange(player_id_,
754                      blink::WebMediaPlayer::kReadyStateHaveEnoughData);
755   OnNetworkStateChange(player_id_, blink::WebMediaPlayer::kNetworkStateLoaded);
756   ExecuteDelayedPlayerState();
757 }
758
759 void MediaPlayerBridgeCapi::HandleBufferingStatus(int percent) {
760   if (is_paused_ || is_seeking_)
761     return;
762
763   if (percent == 100) {
764     LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__;
765     if (GetPlayerState() != PLAYER_STATE_PAUSED)
766       return;
767     if (player_start(player_) != PLAYER_ERROR_NONE) {
768       LOG(ERROR) << "|player_start| failed";
769       return;
770     }
771     StartCurrentTimeUpdateTimer();
772
773     if (!is_file_url_)
774       StartBufferingUpdateTimer();
775
776     OnReadyStateChange(player_id_,
777                        blink::WebMediaPlayer::kReadyStateHaveEnoughData);
778   } else {
779     if (GetPlayerState() != PLAYER_STATE_PLAYING)
780       return;
781     if (player_pause(player_) != PLAYER_ERROR_NONE) {
782       LOG(ERROR) << "|player_pause| failed";
783       return;
784     }
785
786     StopCurrentTimeUpdateTimer();
787     OnReadyStateChange(player_id_,
788                        blink::WebMediaPlayer::kReadyStateHaveCurrentData);
789   }
790   OnNetworkStateChange(player_id_, blink::WebMediaPlayer::kNetworkStateLoading);
791 }
792
793 player_state_e MediaPlayerBridgeCapi::GetPlayerState() {
794   player_state_e state = PLAYER_STATE_NONE;
795   player_get_state(player_, &state);
796   LOG(INFO) << __func__ << " ; state: " << state;
797   return state;
798 }
799
800 void MediaPlayerBridgeCapi::ExecuteDelayedPlayerState() {
801   LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__;
802   switch (delayed_player_state_) {
803     case PLAYER_STATE_DELAYED_PLAY:
804       delayed_player_state_ = PLAYER_STATE_DELAYED_NULL;
805       Play();
806       break;
807     case PLAYER_STATE_DELAYED_PAUSE:
808       delayed_player_state_ = PLAYER_STATE_DELAYED_NULL;
809       Pause(false);
810       break;
811     case PLAYER_STATE_DELAYED_SEEK:
812       LOG(INFO)
813           << "(" << static_cast<void*>(this) << ") " << __func__
814           << " applying pending seek - " << pending_seek_duration_.InSecondsF();
815       delayed_player_state_ = PLAYER_STATE_DELAYED_NULL;
816       SeekInternal(pending_seek_duration_);
817       break;
818     default:
819       break;
820   }
821 }
822
823 void MediaPlayerBridgeCapi::OnMediaPacketUpdated(media_packet_h packet) {
824   ScopedMediaPacket packet_proxy(packet);
825   task_runner_->PostTask(
826       FROM_HERE,
827       base::BindOnce(&MediaPlayerBridgeCapi::DeliverMediaPacket,
828                      weak_factory_.GetWeakPtr(), std::move(packet_proxy)));
829 }
830
831 void MediaPlayerBridgeCapi::OnPlaybackCompleteUpdate() {
832   task_runner_->PostTask(
833       FROM_HERE, base::BindOnce(&MediaPlayerBridgeCapi::PlaybackCompleteUpdate,
834                                 weak_factory_.GetWeakPtr()));
835 }
836
837 void MediaPlayerBridgeCapi::OnSeekCompleteUpdate() {
838   task_runner_->PostTask(
839       FROM_HERE, base::BindOnce(&MediaPlayerBridgeCapi::SeekCompleteUpdate,
840                                 weak_factory_.GetWeakPtr()));
841 }
842
843 void MediaPlayerBridgeCapi::OnPlayerPrepared() {
844   task_runner_->PostTask(FROM_HERE,
845                          base::BindOnce(&MediaPlayerBridgeCapi::PlayerPrepared,
846                                         weak_factory_.GetWeakPtr()));
847 }
848
849 void MediaPlayerBridgeCapi::OnHandleBufferingStatus(int percent) {
850   task_runner_->PostTask(
851       FROM_HERE, base::BindOnce(&MediaPlayerBridgeCapi::HandleBufferingStatus,
852                                 weak_factory_.GetWeakPtr(), percent));
853 }
854
855 void MediaPlayerBridgeCapi::OnHandlePlayerError(
856     int player_error_code,
857     const base::Location& location) {
858   LOG(ERROR) << GetErrorString(player_error_code) << " from "
859              << location.ToString();
860
861   OnMediaError(GetMediaError(player_error_code));
862 }
863
864 void MediaPlayerBridgeCapi::OnResourceConflict() {
865   if (!task_runner_->BelongsToCurrentThread()) {
866     task_runner_->PostTask(
867         FROM_HERE, base::BindOnce(&MediaPlayerBridgeCapi::OnResourceConflict,
868                                   weak_factory_.GetWeakPtr()));
869     return;
870   }
871   LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__;
872   RequestSuspend(true);
873 }
874
875 void MediaPlayerBridgeCapi::OnResumeComplete(bool success) {
876   NOTIMPLEMENTED();
877 }
878
879 void MediaPlayerBridgeCapi::OnReadyStateChange(
880     int player_id,
881     blink::WebMediaPlayer::ReadyState state) {
882   LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__
883             << " ; ready_state : " << state;
884   media::BufferingState buffer_state = media::BUFFERING_HAVE_NOTHING;
885   media::BufferingStateChangeReason reason =
886       media::BUFFERING_CHANGE_REASON_UNKNOWN;
887   switch (state) {
888     case blink::WebMediaPlayer::kReadyStateHaveEnoughData:
889     case blink::WebMediaPlayer::kReadyStateHaveCurrentData:
890       buffer_state = media::BUFFERING_HAVE_ENOUGH;
891       reason = media::BUFFERING_CHANGE_REASON_UNKNOWN;
892       break;
893     case blink::WebMediaPlayer::kReadyStateHaveNothing:
894       // buffer_state = media::BUFFERING_HAVE_NOTHING;
895       // reason = media::DEMUXER_UNDERFLOW;
896       return;
897     default:
898       NOTREACHED();
899   }
900   GetMediaPlayerClient()->OnBufferingStateChange(buffer_state, reason);
901 }
902
903 void MediaPlayerBridgeCapi::OnNetworkStateChange(
904     int player_id,
905     blink::WebMediaPlayer::NetworkState state) {}
906
907 void MediaPlayerBridgeCapi::OnMediaDataChange(int player_id,
908                                               int width,
909                                               int height,
910                                               int media) {
911   LOG(INFO) << "(" << static_cast<void*>(this) << ") " << __func__
912             << " width  : " << width << " ; height : " << height;
913   width_ = width;
914   height_ = height;
915   GetMediaPlayerClient()->OnVideoNaturalSizeChange(gfx::Size(width, height));
916 }
917
918 void MediaPlayerBridgeCapi::OnTimeChanged(int player_id) {}
919
920 void MediaPlayerBridgeCapi::OnTimeUpdate(int player_id,
921                                          base::TimeDelta current_time) {
922   // Move to OnSeekStateChange?
923   GetMediaPlayerClient()->OnBufferingStateChange(
924       media::BUFFERING_HAVE_ENOUGH, media::BUFFERING_CHANGE_REASON_UNKNOWN);
925 }
926
927 void MediaPlayerBridgeCapi::OnDurationChange(int player_id, double duration) {
928   GetMediaPlayerClient()->OnDurationChange(base::Seconds(duration));
929 }
930
931 void MediaPlayerBridgeCapi::OnBufferUpdate(
932     int player_id,
933     std::vector<TimeRanges> buffer_range) {
934   TimeRanges range = buffer_range.at(0);
935   GetMediaPlayerClient()->OnBufferUpdate(base::Microseconds(range.end));
936 }
937
938 void MediaPlayerBridgeCapi::SetMediaType(DemuxerStream::Type type) {
939   if (type == DemuxerStream::AUDIO)
940     SetMediaType(GetMediaType() | MediaType::Audio);
941   else if (type == DemuxerStream::VIDEO)
942     SetMediaType(GetMediaType() | MediaType::Video);
943 }
944
945 PlayerRoleFlags MediaPlayerBridgeCapi::GetRoles() const noexcept {
946   return PlayerRole::UrlBased;
947 }
948
949 void MediaPlayerBridgeCapi::DeliverMediaPacket(ScopedMediaPacket packet) {
950   tbm_surface_info_s suf_info = {
951       0,
952   };
953   tbm_surface_h tbm_surface = nullptr;
954
955   if (MEDIA_PACKET_ERROR_NONE !=
956       media_packet_get_tbm_surface(packet.get(), &tbm_surface)) {
957     LOG(ERROR) << "|media_packet_get_tbm_surface| failed";
958     return;
959   }
960
961   if (TBM_SURFACE_ERROR_NONE != tbm_surface_get_info(tbm_surface, &suf_info)) {
962     LOG(ERROR) << "|tbm_surface_get_info| failed";
963     return;
964   }
965
966   if (width_ != static_cast<int>(suf_info.width) ||
967       height_ != static_cast<int>(suf_info.height)) {
968     width_ = static_cast<int>(suf_info.width);
969     height_ = static_cast<int>(suf_info.height);
970
971     OnMediaDataChange(player_id_, width_, height_,
972                       static_cast<int>(MediaType::Video));
973   }
974
975   // TODO(max): Need to check if we can use "media_packet_get_pts" instead of
976   // generating a new timestamp in here.
977   base::TimeDelta timestamp = GetCurrentTime();
978
979 #if defined(TIZEN_TBM_SUPPORT)
980   gfx::TbmBufferHandle tbm_handle;
981   tbm_handle.tbm_surface = reinterpret_cast<uint64_t>(tbm_surface);
982   tbm_handle.media_packet = reinterpret_cast<uint64_t>(packet.release());
983   OnNewTbmBufferAvailable(player_id_, tbm_handle, timestamp);
984 #else
985   base::UnsafeSharedMemoryRegion shared_memory;
986   base::WritableSharedMemoryMapping memory_mapping;
987   uint32_t shared_memory_size =
988       suf_info.planes[0].size + (suf_info.planes[0].size / 2);
989   shared_memory = base::UnsafeSharedMemoryRegion::Create(shared_memory_size);
990   if (!shared_memory.IsValid()) {
991     LOG(ERROR) << "Shared Memory creation failed. Player " << player_id_;
992     return;
993   }
994
995   memory_mapping = shared_memory.Map();
996   if (!memory_mapping.IsValid()) {
997     LOG(ERROR) << "Shared Memory handle could not be obtained. Player "
998                << player_id_;
999     return;
1000   }
1001
1002   unsigned char* y_ptr = static_cast<unsigned char*>(memory_mapping.memory());
1003
1004   // Video format will always be converted to I420
1005   switch (suf_info.format) {
1006     case TBM_FORMAT_NV12: {
1007       unsigned char* u_ptr = y_ptr + suf_info.planes[0].size;
1008       unsigned char* v_ptr = u_ptr + (suf_info.planes[0].size * 5 / 4);
1009       libyuv::NV12ToI420(suf_info.planes[0].ptr, suf_info.planes[0].stride,
1010                          suf_info.planes[1].ptr, suf_info.planes[1].stride,
1011                          y_ptr, suf_info.planes[0].stride, u_ptr,
1012                          suf_info.planes[1].stride / 2, v_ptr,
1013                          suf_info.planes[1].stride / 2, suf_info.width,
1014                          suf_info.height);
1015       break;
1016     }
1017     case TBM_FORMAT_YUV420: {
1018       unsigned char* u_ptr = y_ptr + suf_info.planes[0].size;
1019       unsigned char* v_ptr = u_ptr + suf_info.planes[1].size;
1020       libyuv::I420Copy(
1021           suf_info.planes[0].ptr, suf_info.planes[0].stride,
1022           suf_info.planes[1].ptr, suf_info.planes[1].stride,
1023           suf_info.planes[2].ptr, suf_info.planes[2].stride, y_ptr,
1024           suf_info.planes[0].stride, u_ptr, suf_info.planes[1].stride, v_ptr,
1025           suf_info.planes[2].stride, suf_info.width, suf_info.height);
1026       break;
1027     }
1028     default: {
1029       NOTIMPLEMENTED();
1030       LOG(WARNING) << "Not supported format";
1031       return;
1032     }
1033   }
1034
1035   OnNewFrameAvailable(player_id_, std::move(shared_memory), shared_memory_size,
1036                       timestamp);
1037 #endif
1038 }
1039
1040 #if defined(TIZEN_TBM_SUPPORT)
1041 void MediaPlayerBridgeCapi::DestroyMediaPacket(void* media_packet) {
1042   if (!task_runner_->BelongsToCurrentThread()) {
1043     task_runner_->PostTask(
1044         FROM_HERE, base::BindOnce(&MediaPlayerBridgeCapi::DestroyMediaPacket,
1045                                   weak_factory_.GetWeakPtr(), media_packet));
1046     return;
1047   }
1048
1049   if (MEDIA_PACKET_ERROR_NONE !=
1050       media_packet_destroy(static_cast<media_packet_h>(media_packet))) {
1051     LOG(WARNING) << "Fail to release media_packet";
1052   }
1053 }
1054
1055 void MediaPlayerBridgeCapi::OnNewTbmBufferAvailable(
1056     int player_id,
1057     gfx::TbmBufferHandle tbm_handle,
1058     base::TimeDelta timestamp) {
1059   DCHECK(GetMediaPlayerClient());
1060
1061   void* media_packet = reinterpret_cast<void*>(tbm_handle.media_packet);
1062   tbm_handle.media_packet = reinterpret_cast<uint64_t>(media_packet);
1063   tbm_handle.player_id = player_id_;
1064   tbm_handle.width = width_;
1065   tbm_handle.height = height_;
1066
1067   GetMediaPlayerClient()->OnNewTbmFrameAvailable(player_id, tbm_handle,
1068                                                  timestamp);
1069 }
1070 #else
1071 void MediaPlayerBridgeCapi::OnNewFrameAvailable(
1072     int player_id,
1073     base::UnsafeSharedMemoryRegion shm_region,
1074     uint32_t length,
1075     base::TimeDelta timestamp) {
1076   NOTIMPLEMENTED();
1077 }
1078 #endif
1079 }  // namespace media