[MM]EME implementation using EncryptedMediaPlayerSupport.
[platform/framework/web/chromium-efl.git] / tizen_src / impl / media / base / tizen / webmediaplayer_tizen.cc
1 // Copyright 2014 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/base/tizen/webmediaplayer_tizen.h"
6
7 #include <gst/gst.h>
8
9 #include "cc/blink/web_layer_impl.h"
10 #include "cc/layers/video_layer.h"
11 #include "content/renderer/media/render_media_log.h"
12 #include "content/renderer/media/renderer_gpu_video_accelerator_factories.h"
13 #include "content/renderer/render_frame_impl.h"
14 #include "content/renderer/render_thread_impl.h"
15 #include "media/base/tizen/media_player_tizen.h"
16 #include "media/base/bind_to_current_loop.h"
17 #include "media/base/video_frame.h"
18 #include "media/blink/webmediaplayer_util.h"
19 #include "third_party/libyuv/include/libyuv/planar_functions.h"
20 #include "third_party/WebKit/public/platform/WebMediaPlayerClient.h"
21 #include "wrt/wrt_url_parse.h"
22
23 #define BIND_TO_RENDER_LOOP(function) \
24   (DCHECK(main_loop_->BelongsToCurrentThread()), \
25   media::BindToCurrentLoop(base::Bind(function, AsWeakPtr())))
26
27 namespace media {
28
29 // fourcc for gst-video-format
30 const uint32 GST_VIDEO_SN12 = GST_MAKE_FOURCC('S','N','1','2');
31 const uint32 GST_VIDEO_I420 = GST_MAKE_FOURCC('I','4','2','0');
32 const uint32 GST_VIDEO_NV12 = GST_MAKE_FOURCC('N','V','1','2');
33
34 // tile size for SN12
35 const uint SN12_TILE_WIDTH = 64;
36 const uint SN12_TILE_HEIGHT = 32;
37 const uint SN12_TILE_SIZE = SN12_TILE_WIDTH * SN12_TILE_HEIGHT;
38
39 // Removes query string from URI
40 GURL GetCleanURL(std::string url) {
41   // FIXME: Need to consider "app://" scheme.
42   if (!url.compare(0, 7, "file://")) {
43     int position = url.find("?");
44     if(position != -1)
45       url.erase(url.begin() + position, url.end());
46   }
47   GURL url_(url);
48   return url_;
49 }
50
51 WebMediaPlayerTizen::WebMediaPlayerTizen(
52     content::RendererMediaPlayerManagerTizen* manager,
53     blink::WebLocalFrame* frame,
54     blink::WebMediaPlayerClient* client,
55     base::WeakPtr<media::WebMediaPlayerDelegate> delegate,
56     const WebMediaPlayerParams& params,
57     content::WrtUrlParseBase* wrt_url_parse)
58     : frame_(frame),
59       network_state_(blink::WebMediaPlayer::NetworkStateEmpty),
60       ready_state_(blink::WebMediaPlayer::ReadyStateHaveNothing),
61       main_loop_(base::MessageLoopProxy::current()),
62       media_task_runner_(
63           content::RenderThreadImpl::current()->GetMediaThreadTaskRunner()),
64       manager_(manager),
65       client_(client),
66       media_log_(new content::RenderMediaLog()),
67       delegate_(delegate),
68       compositor_task_runner_(
69           content::RenderThreadImpl::current()->compositor_message_loop_proxy()),
70       compositor_(new media::VideoFrameCompositor(
71           BIND_TO_RENDER_LOOP(&WebMediaPlayerTizen::OnNaturalSizeChanged),
72           BIND_TO_RENDER_LOOP(&WebMediaPlayerTizen::OnOpacityChanged))),
73       weak_factory_(this),
74       gst_video_format_(0),
75       audio_(false),
76       video_(false),
77       current_time_(0),
78       duration_(0),
79       is_paused_(true),
80       is_seeking_(false),
81       seek_time_(0),
82       pending_seek_(0),
83       pending_seek_time_(0),
84       opaque_(false),
85       natural_size_(0, 0),
86       did_loading_progress_(false),
87       volume_(0),
88       gpu_factories_(content::RenderThreadImpl::current()->GetGpuFactories()),
89       encrypted_media_support_(
90           params.CreateEncryptedMediaPlayerSupport(client)),
91       wrt_url_parse_(wrt_url_parse) {
92   DCHECK(manager_);
93   DCHECK(encrypted_media_support_);
94   VLOG(1) << "WebMediaPlayerTizen::" << __FUNCTION__;
95   FrameAvailable_ = false;
96   // We want to be notified of |main_loop_| destruction.
97   base::MessageLoop::current()->AddDestructionObserver(this);
98
99   player_id_ = manager_->RegisterMediaPlayer(this);
100
101   // Threaded compositing isn't enabled universally yet.
102   if (!compositor_task_runner_.get())
103     compositor_task_runner_ = base::MessageLoopProxy::current();
104
105   media_log_->AddEvent(
106       media_log_->CreateEvent(media::MediaLogEvent::WEBMEDIAPLAYER_CREATED));
107 }
108
109 WebMediaPlayerTizen::~WebMediaPlayerTizen() {
110   VLOG(1) << "WebMediaPlayerTizen::" << __FUNCTION__;
111   if (manager_) {
112     manager_->DestroyPlayer(player_id_);
113     manager_->UnregisterMediaPlayer(player_id_);
114   }
115
116   SetVideoFrameProviderClient(NULL);
117   client_->setWebLayer(NULL);
118   if (delegate_.get())
119     delegate_->PlayerGone(this);
120   if (base::MessageLoop::current())
121     base::MessageLoop::current()->RemoveDestructionObserver(this);
122     compositor_task_runner_->DeleteSoon(FROM_HERE, compositor_);
123   if (media_source_delegate_) {
124     // Part of |media_source_delegate_| needs to be stopped
125     // on the media thread.
126     // Wait until |media_source_delegate_| is fully stopped
127     // before tearing down other objects.
128     base::WaitableEvent waiter(false, false);
129     media_source_delegate_->Stop(
130         base::Bind(&base::WaitableEvent::Signal, base::Unretained(&waiter)));
131     waiter.Wait();
132   }
133 }
134
135 void WebMediaPlayerTizen::load(LoadType load_type,
136     const blink::WebURL& url,
137     CORSMode cors_mode) {
138   VLOG(1) << "WebMediaPlayerTizen::" << __FUNCTION__ << " load type - "
139           << load_type;
140   int demuxer_client_id = 0;
141   if (load_type == LoadTypeMediaSource) {
142     // FIXME: EFL GST-package on desktop cannot handle AAC decoding.
143     // Disabling MSE for desktop.
144 #ifdef OS_TIZEN
145     player_type_ = MEDIA_PLAYER_TYPE_MEDIA_SOURCE;
146     content::RendererDemuxerTizen* demuxer =
147         content::RenderThreadImpl::current()->renderer_demuxer();
148     demuxer_client_id = demuxer->GetNextDemuxerClientID();
149     media_source_delegate_.reset(new content::MediaSourceDelegateTizen(
150         demuxer, demuxer_client_id, media_task_runner_, media_log_.get()));
151     SetDecryptorReadyCB set_decryptor_ready_cb =
152         encrypted_media_support_->CreateSetDecryptorReadyCB();
153     Demuxer::NeedKeyCB need_key_cb =
154         encrypted_media_support_->CreateNeedKeyCB();
155     media_source_delegate_->InitializeMediaSource(
156         base::Bind(&WebMediaPlayerTizen::OnMediaSourceOpened,
157                    weak_factory_.GetWeakPtr()),
158         need_key_cb,
159         set_decryptor_ready_cb,
160         base::Bind(&WebMediaPlayerTizen::SetNetworkState,
161                    weak_factory_.GetWeakPtr()),
162         base::Bind(&WebMediaPlayerTizen::OnDurationChange,
163                    weak_factory_.GetWeakPtr()));
164 #else
165     // Posting Error Message to HTMLMediaElement.
166     SetNetworkState(WebMediaPlayer::NetworkStateDecodeError);
167 #endif
168   } else if (load_type == LoadTypeURL) {
169     player_type_ = MEDIA_PLAYER_TYPE_URL;
170   } else {
171     LOG(ERROR) << "Unsupported load type " << load_type;
172     return;
173   }
174
175   blink::WebURL real_url;
176   if (wrt_url_parse_)
177     real_url = wrt_url_parse_->parseUrl(url);
178   else
179     real_url = url;
180
181   // FIXME: Check URL, Volume for MS.
182   manager_->Initialize(player_id_,
183                        player_type_,
184                        GetCleanURL(real_url.string().utf8()),
185                        volume_,
186                        demuxer_client_id);
187 }
188
189 blink::WebMediaPlayer::MediaKeyException
190 WebMediaPlayerTizen::generateKeyRequest(const blink::WebString& key_system,
191                                         const unsigned char* init_data,
192                                         unsigned init_data_length) {
193   DCHECK(main_loop_->BelongsToCurrentThread());
194
195   return encrypted_media_support_->GenerateKeyRequest(
196       frame_, key_system, init_data, init_data_length);
197 }
198
199 blink::WebMediaPlayer::MediaKeyException WebMediaPlayerTizen::addKey(
200     const blink::WebString& key_system,
201     const unsigned char* key,
202     unsigned key_length,
203     const unsigned char* init_data,
204     unsigned init_data_length,
205     const blink::WebString& session_id) {
206   DCHECK(main_loop_->BelongsToCurrentThread());
207
208   return encrypted_media_support_->AddKey(
209       key_system, key, key_length, init_data, init_data_length, session_id);
210 }
211
212 blink::WebMediaPlayer::MediaKeyException WebMediaPlayerTizen::cancelKeyRequest(
213     const blink::WebString& key_system,
214     const blink::WebString& session_id) {
215   DCHECK(main_loop_->BelongsToCurrentThread());
216
217   return encrypted_media_support_->CancelKeyRequest(key_system, session_id);
218 }
219
220 void WebMediaPlayerTizen::setContentDecryptionModule(
221     blink::WebContentDecryptionModule* cdm) {
222   DCHECK(main_loop_->BelongsToCurrentThread());
223
224   encrypted_media_support_->SetContentDecryptionModule(cdm);
225 }
226
227 void WebMediaPlayerTizen::setContentDecryptionModule(
228     blink::WebContentDecryptionModule* cdm,
229     blink::WebContentDecryptionModuleResult result) {
230   DCHECK(main_loop_->BelongsToCurrentThread());
231
232   encrypted_media_support_->SetContentDecryptionModule(cdm, result);
233 }
234
235 void WebMediaPlayerTizen::OnMediaSourceOpened(
236     blink::WebMediaSource* web_media_source) {
237   client_->mediaSourceOpened(web_media_source);
238 }
239
240 void WebMediaPlayerTizen::play() {
241   manager_->Play(player_id_);
242   // Has to be updated from |MediaPlayerBridgeGstreamer| but IPC causes delay.
243   // There are cases were play - pause are fired successively and would fail.
244   is_paused_ = false;
245 }
246
247 void WebMediaPlayerTizen::pause() {
248   manager_->Pause(player_id_, true);
249   // Has to be updated from |MediaPlayerBridgeGstreamer| but IPC causes delay.
250   // There are cases were play - pause are fired successively and would fail.
251   is_paused_ = true;
252 }
253
254 void WebMediaPlayerTizen::RequestPause() {
255   pause();
256   client_->playbackStateChanged();
257 }
258
259 bool WebMediaPlayerTizen::supportsSave() const {
260   return false;
261 }
262
263 void WebMediaPlayerTizen::seek(double seconds) {
264   VLOG(1) << "WebMediaPlayerTizen::" << __FUNCTION__ <<  " : " << seconds
265           << " ID " << player_id_;
266   DCHECK(main_loop_->BelongsToCurrentThread());
267
268   if (is_seeking_) {
269     if (seconds == seek_time_) {
270       if (media_source_delegate_) {
271         if (!pending_seek_) {
272           // If using media source demuxer, only suppress redundant seeks if
273           // there is no pending seek. This enforces that any pending seek that
274           // results in a demuxer seek is preceded by matching
275           // CancelPendingSeek() and StartSeek() calls.
276           return;
277         }
278       } else {
279         // Suppress all redundant seeks if unrestricted by media source
280         // demuxer API.
281         pending_seek_ = false;
282         return;
283       }
284     }
285
286     pending_seek_ = true;
287     pending_seek_time_ = seconds;
288     if (media_source_delegate_)
289       media_source_delegate_->CancelPendingSeek(
290           media::ConvertSecondsToTimestamp(pending_seek_time_));
291     // Later, OnSeekComplete will trigger the pending seek.
292     return;
293   }
294
295   is_seeking_ = true;
296   seek_time_ = seconds;
297
298   // Once Chunk demuxer seeks GST seek will be intiated.
299   if (media_source_delegate_)
300     media_source_delegate_->StartWaitingForSeek(
301         media::ConvertSecondsToTimestamp(seek_time_));
302   manager_->Seek(player_id_, seek_time_);
303
304   // Draw empty frame during seek.
305   if (video_) {
306     gfx::Size size(gst_width_, gst_height_);
307     scoped_refptr<VideoFrame> video_frame = VideoFrame::CreateBlackFrame(size);
308     FrameReady(video_frame);
309   }
310 }
311
312 void WebMediaPlayerTizen::setRate(double rate) {
313   manager_->SetRate(player_id_, rate);
314 }
315
316 void WebMediaPlayerTizen::setVolume(double volume) {
317   volume_ = volume;
318   manager_->SetVolume(player_id_, volume);
319 }
320
321 blink::WebTimeRanges WebMediaPlayerTizen::buffered() const{
322   return buffered_;
323 }
324
325 blink::WebTimeRanges WebMediaPlayerTizen::seekable() const {
326   const double seekable_end = duration();
327   if (std::isinf(seekable_end))
328     return blink::WebTimeRanges();
329
330   blink::WebTimeRange seekable_range(0.0, seekable_end);
331   return blink::WebTimeRanges(&seekable_range, 1);
332 }
333
334 void WebMediaPlayerTizen::paint(blink::WebCanvas* canvas,
335     const blink::WebRect& rect,
336     unsigned char alpha,
337     SkXfermode::Mode mode) {
338   scoped_refptr<media::VideoFrame> video_frame =
339       GetCurrentFrameFromCompositor();
340
341   gfx::Rect gfx_rect(rect);
342   skcanvas_video_renderer_.Paint(
343       video_frame.get(), canvas, gfx_rect, alpha,
344       SkXfermode::kSrcOver_Mode, media::VIDEO_ROTATION_0);
345 }
346
347 bool WebMediaPlayerTizen::hasVideo() const {
348   return video_;
349 }
350
351 bool WebMediaPlayerTizen::hasAudio() const {
352   return audio_;
353 }
354
355 blink::WebSize WebMediaPlayerTizen::naturalSize() const {
356   return blink::WebSize(natural_size_);
357 }
358
359 bool WebMediaPlayerTizen::paused() const {
360   return is_paused_;
361 }
362
363 bool WebMediaPlayerTizen::seeking() const {
364   return is_seeking_;
365 }
366
367 double WebMediaPlayerTizen::duration() const {
368   return duration_;
369 }
370
371 double WebMediaPlayerTizen::currentTime() const {
372   if (seeking())
373     return pending_seek_ ? pending_seek_time_ : seek_time_;
374   return current_time_;
375 }
376
377 blink::WebMediaPlayer::NetworkState WebMediaPlayerTizen::networkState() const {
378   return network_state_;
379 }
380
381 blink::WebMediaPlayer::ReadyState WebMediaPlayerTizen::readyState() const {
382   return ready_state_;
383 }
384
385 bool WebMediaPlayerTizen::didLoadingProgress() {
386   if (did_loading_progress_) {
387     did_loading_progress_ = false;
388     return true;
389   }
390   return false;
391 }
392
393 bool WebMediaPlayerTizen::hasSingleSecurityOrigin() const {
394   return true;
395 }
396
397 bool WebMediaPlayerTizen::didPassCORSAccessCheck() const {
398   return false;
399 }
400
401 double WebMediaPlayerTizen::mediaTimeForTimeValue(double timeValue) const {
402   return media::ConvertSecondsToTimestamp(timeValue).InSecondsF();
403 }
404
405 void WebMediaPlayerTizen::SetVideoFrameProviderClient(
406     cc::VideoFrameProvider::Client* client) {
407   // This is called from both the main renderer thread and the compositor
408   // thread (when the main thread is blocked).
409   compositor_->SetVideoFrameProviderClient(client);
410 }
411
412 scoped_refptr<media::VideoFrame>WebMediaPlayerTizen::GetCurrentFrame() {
413   scoped_refptr<media::VideoFrame> current_frame =
414       GetCurrentFrameFromCompositor();
415   return current_frame;
416 }
417
418 void WebMediaPlayerTizen::SetReadyState(WebMediaPlayer::ReadyState state) {
419   ready_state_ = state;
420   client_->readyStateChanged();
421 }
422
423 void WebMediaPlayerTizen::SetNetworkState(WebMediaPlayer::NetworkState state) {
424   network_state_ = state;
425   client_->networkStateChanged();
426 }
427
428 void WebMediaPlayerTizen::OnNewFrameAvailable(base::SharedMemoryHandle Handle,
429     uint32 yuv_size,
430     base::TimeDelta timestamp) {
431   base::SharedMemory shared_memory(Handle, false);
432   shared_memory.Map(yuv_size);
433   uint8* const yuv_buffer = static_cast<uint8*>(shared_memory.memory());
434
435   gfx::Size size(gst_width_, gst_height_);
436   scoped_refptr<VideoFrame> video_frame =
437       VideoFrame::CreateFrame(
438           VideoFrame::YV12, size, gfx::Rect(size), size, timestamp);
439
440   // decoded format is SN12 on Tizen device
441   // video format converted from SN12 to YV12
442   uint8* gst_buf = yuv_buffer;
443   switch(gst_video_format_) {
444     case GST_VIDEO_I420: {
445       const uint c_frm_size = yuv_size / 6;
446       const uint y_frm_size = c_frm_size << 2;  // * 4;
447       // U Plane buffer.
448       uint8* gst_buf_u = gst_buf + y_frm_size;
449       // V Plane buffer.
450       uint8* gst_buf_v = gst_buf_u + c_frm_size;
451
452
453       // Get the videoframe stride size.
454       // Calculate the gstreamer buffer stride size.
455       const uint uv_rows = video_frame.get()->rows(VideoFrame::kUPlane);
456       const uint gst_stride = c_frm_size / uv_rows;
457
458       libyuv::I420Copy(gst_buf, 2 * gst_stride,
459                        gst_buf_u, gst_stride,
460                        gst_buf_v, gst_stride,
461                        video_frame.get()->data(VideoFrame::kYPlane),
462                        video_frame.get()->stride(VideoFrame::kYPlane),
463                        video_frame.get()->data(VideoFrame::kUPlane),
464                        video_frame.get()->stride(VideoFrame::kUPlane),
465                        video_frame.get()->data(VideoFrame::kVPlane),
466                        video_frame.get()->stride(VideoFrame::kVPlane),
467                        gst_width_, gst_height_);
468       break;
469     }
470     case GST_VIDEO_SN12: {
471       //const uint tile_w = (gst_width_ - 1) / SN12_TILE_WIDTH + 1;
472       //const uint tile_w_align = (tile_w + 1) & ~1;
473       //const uint tile_h_luma = (gst_height_ - 1) / SN12_TILE_HEIGHT + 1;
474       const uint tile_w_align = ((gst_width_ - 1) / SN12_TILE_WIDTH + 2) & ~1;
475       const uint tile_luma_stride = tile_w_align * SN12_TILE_WIDTH;
476       uint luma_size = SN12_TILE_SIZE * tile_w_align
477                        * ((gst_height_-1)/SN12_TILE_HEIGHT + 1);
478
479       uint8* y_frm = video_frame.get()->data(VideoFrame::kYPlane);
480       const uint y_stride = video_frame.get()->stride(VideoFrame::kYPlane);
481
482       // actually copy and convert luma buffer
483       for(int i=0; i<gst_height_; i++) {
484         memcpy(y_frm, gst_buf, gst_width_);
485         y_frm += y_stride;
486         gst_buf += tile_luma_stride;
487       }
488
489       gst_buf = yuv_buffer + luma_size;
490       uint8* gst_buf2 = gst_buf + 1;
491       uint8* u_frm = video_frame.get()->data(VideoFrame::kUPlane);
492       uint8* v_frm = video_frame.get()->data(VideoFrame::kVPlane);
493       const uint uv_stride = video_frame.get()->stride(VideoFrame::kUPlane);
494       const uint uv_rows = video_frame.get()->rows(VideoFrame::kUPlane);
495
496       // actually copy and convert chroma buffer
497       for(uint row=0; row<uv_rows; ++row) {
498         for(uint i=0; i<uv_stride; i++) {
499           u_frm[i] = gst_buf[i*2];
500           v_frm[i] = gst_buf2[i*2];
501         }
502
503         gst_buf += tile_luma_stride;
504         gst_buf2 += tile_luma_stride;
505         u_frm += uv_stride;
506         v_frm += uv_stride;
507       }
508
509       break;
510     }
511     case GST_VIDEO_NV12: {
512       const uint c_frm_size = yuv_size / 6;
513       const uint y_frm_size = c_frm_size << 2;  // * 4;
514
515       // kYPlane
516       memcpy(video_frame.get()->data(VideoFrame::kYPlane),
517              gst_buf, y_frm_size);
518
519       gst_buf += y_frm_size;
520       uint8* gst_buf2 = gst_buf + 1;
521       uint8* u_plane = video_frame.get()->data(VideoFrame::kUPlane);
522       uint8* v_plane = video_frame.get()->data(VideoFrame::kVPlane);
523
524       for(uint i = 0; i < c_frm_size; i++){
525         // kUPlane
526         u_plane[i] = gst_buf[i * 2];
527         // kVPlane
528         v_plane[i] = gst_buf2[i * 2];
529       }
530       break;
531     }
532     default: {
533       LOG(ERROR) << "WebMediaPlayerTizen::" << __FUNCTION__
534           << " not supported video format";
535       break;
536     }
537   }
538
539   shared_memory.Close();
540   FrameReady(video_frame);
541 }
542
543 #if defined(TIZEN_MULTIMEDIA_PIXMAP_SUPPORT)
544 // FIXME: Graphics team need to merge painting of Video-Frame on to 2d-canvas
545 // from m34.
546 void WebMediaPlayerTizen::OnPlatformSurfaceUpdated(
547     int pixmap_id,
548     base::TimeDelta timestamp) {
549   gfx::Size size(gst_width_, gst_height_);
550   scoped_refptr<VideoFrame> video_frame = VideoFrame::WrapNativePixmap(
551       VideoFrame::NATIVE_PIXMAP, size, gfx::Rect(size), size,
552       timestamp, pixmap_id);
553   FrameReady(video_frame);
554 }
555 #endif
556
557 void WebMediaPlayerTizen::FrameReady(
558     const scoped_refptr<media::VideoFrame>& frame) {
559   compositor_task_runner_->PostTask(
560       FROM_HERE,
561       base::Bind(&media::VideoFrameCompositor::UpdateCurrentFrame,
562                  base::Unretained(compositor_),
563                  frame));
564 }
565 void WebMediaPlayerTizen::OnMediaDataChange(int format, int height, int width, int media) {
566   gst_video_format_ = static_cast<uint32>(format);
567   gst_height_ = height;
568   gst_width_  = width;
569   audio_ = media & media::MEDIA_AUDIO_MASK ? true : false;
570   video_ = media & media::MEDIA_VIDEO_MASK ? true : false;
571   natural_size_ = gfx::Size(width, height);
572   SetReadyState(WebMediaPlayer::ReadyStateHaveMetadata);
573   if (hasVideo() && !video_weblayer_.get()) {
574     scoped_refptr<cc::VideoLayer> layer =
575         cc::VideoLayer::Create(compositor_, media::VIDEO_ROTATION_0);
576     video_weblayer_.reset(new cc_blink::WebLayerImpl(layer));
577     video_weblayer_->setOpaque(opaque_);
578     client_->setWebLayer(video_weblayer_.get());
579   }
580 }
581
582 void WebMediaPlayerTizen::OnTimeChanged() {
583   is_seeking_ = false;
584
585   // Handling pending seek for ME. For MSE |CancelPendingSeek|
586   // will handle the pending seeks.
587   if (!media_source_delegate_ && pending_seek_) {
588     pending_seek_ = false;
589     seek(pending_seek_time_);
590     return;
591   }
592   client_->timeChanged();
593 }
594
595 void WebMediaPlayerTizen::OnDurationChange(double duration) {
596   duration_ = duration;
597   client_->durationChanged();
598 }
599
600 void WebMediaPlayerTizen::OnNaturalSizeChanged(gfx::Size size) {
601   DCHECK(main_loop_->BelongsToCurrentThread());
602   DCHECK_NE(ready_state_, WebMediaPlayer::ReadyStateHaveNothing);
603   TRACE_EVENT0("media", "WebMediaPlayerTizen::OnNaturalSizeChanged");
604   media_log_->AddEvent(
605       media_log_->CreateVideoSizeSetEvent(size.width(), size.height()));
606   natural_size_ = size;
607
608   client_->sizeChanged();
609 }
610
611 void WebMediaPlayerTizen::OnOpacityChanged(bool opaque) {
612   DCHECK(main_loop_->BelongsToCurrentThread());
613   DCHECK_NE(ready_state_, WebMediaPlayer::ReadyStateHaveNothing);
614
615   opaque_ = opaque;
616   if (video_weblayer_)
617     video_weblayer_->setOpaque(opaque_);
618 }
619
620 static void GetCurrentFrameAndSignal(
621     media::VideoFrameCompositor* compositor,
622     scoped_refptr<media::VideoFrame>* video_frame_out,
623     base::WaitableEvent* event) {
624   TRACE_EVENT0("media", "GetCurrentFrameAndSignal");
625   *video_frame_out = compositor->GetCurrentFrame();
626   event->Signal();
627 }
628
629 scoped_refptr<media::VideoFrame>
630     WebMediaPlayerTizen::GetCurrentFrameFromCompositor() {
631   TRACE_EVENT0("media", "WebMediaPlayerImpl::GetCurrentFrameFromCompositor");
632
633   if (compositor_task_runner_->BelongsToCurrentThread())
634     return compositor_->GetCurrentFrame();
635
636   // Use a posted task and waitable event instead of a lock otherwise
637   // WebGL/Canvas can see different content than what the compositor is seeing.
638   scoped_refptr<media::VideoFrame> video_frame;
639   base::WaitableEvent event(false, false);
640   compositor_task_runner_->PostTask(FROM_HERE,
641                                     base::Bind(&GetCurrentFrameAndSignal,
642                                                base::Unretained(compositor_),
643                                                &video_frame,
644                                                &event));
645   event.Wait();
646   return video_frame;
647 }
648
649 void WebMediaPlayerTizen::OnTimeUpdate(double current_time) {
650   current_time_ = current_time;
651 }
652
653 void WebMediaPlayerTizen::OnBufferUpdate(
654     std::vector<media::MediaPlayerTizen::TimeRanges> buffer_range) {
655   media::Ranges<base::TimeDelta> time_ranges;
656   std::vector<media::MediaPlayerTizen::TimeRanges>::iterator tr_it;
657   for ( tr_it = buffer_range.begin(); tr_it != buffer_range.end(); ++tr_it) {
658     time_ranges.Add(
659         base::TimeDelta::FromMicroseconds((*tr_it).start),
660         base::TimeDelta::FromMicroseconds((*tr_it).end));
661   }
662   blink::WebTimeRanges web_ranges(ConvertToWebTimeRanges(time_ranges));
663   buffered_.swap(web_ranges);
664   did_loading_progress_ = true;
665 }
666
667 void WebMediaPlayerTizen::OnPauseStateChange(bool state) {
668   VLOG(1) << "WebMediaPlayerTizen::" << __FUNCTION__ << " state:" << state;
669   is_paused_ = state;
670   if (delegate_.get()) {
671     if(is_paused_)
672       delegate_->DidPause(this);
673     else
674       delegate_->DidPlay(this);
675   }
676 }
677
678 void WebMediaPlayerTizen::OnSeekStateChange(bool state) {
679   VLOG(1) << "WebMediaPlayerTizen::" << __FUNCTION__ << " state:" << state
680           << " ID " << player_id_;
681   is_seeking_ = state;
682   // Draw empty frame during seek.
683   if (video_ && is_seeking_) {
684     gfx::Size size(gst_width_, gst_height_);
685     scoped_refptr<VideoFrame> video_frame = VideoFrame::CreateBlackFrame(size);
686     FrameReady(video_frame);
687   }
688 }
689
690 void WebMediaPlayerTizen::OnRequestSeek(double seek_time) {
691   client_->requestSeek(seek_time);
692 }
693
694 } // namespace media