dca2c89169d5106a20f976addc43c77a835654bc
[vuplus_webkit] / Source / WebCore / platform / graphics / elis / MediaPlayerPrivateElisIPC.cpp
1 /*
2  * MediaPlayerPrivateElisIPC.cpp
3  *
4  *  Created on: 2013. 9. 29.
5  *      Author: kdhong
6  */
7
8 #include "config.h"
9 #include "MediaPlayerPrivateElisIPC.h"
10
11 #if ENABLE_VIDEO && ENABLE_ELIS_MEDIA
12
13 #include "ColorSpace.h"
14 #include "Document.h"
15 #include "Frame.h"
16 #include "FrameView.h"
17 #include "GraphicsContext.h"
18 #include "GraphicsTypes.h"
19 #include "IntRect.h"
20 #include "KURL.h"
21 #include "MIMETypeRegistry.h"
22 #include "MediaPlayer.h"
23 #include "NotImplemented.h"
24 #include "SecurityOrigin.h"
25 #include "TimeRanges.h"
26 #include <GOwnPtr.h>
27 #include <limits>
28 #include <math.h>
29 #include <wtf/text/CString.h>
30 #include "Logging.h"
31 #include <gtk/gtk.h>
32 #include "PlatformContextCairo.h"
33 #include <dlfcn.h>
34
35 #if defined(XP_UNIX)
36 #include "RefPtrCairo.h"
37 #if PLATFORM(X11)
38 #define Bool int // this got undefined somewhere
39 #define Status int // ditto
40 #include <X11/extensions/Xrender.h>
41 #include <cairo/cairo-xlib.h>
42 #include <gdk/gdkx.h>
43 #elif defined(GDK_WINDOWING_DIRECTFB)
44 #include <gdk/gdk.h>
45 #endif
46 #elif defined(GDK_WINDOWING_WIN32)
47 #include "PluginMessageThrottlerWin.h"
48 #include <gdk/gdkwin32.h>
49 #endif
50
51 using namespace std;
52
53 namespace WebCore {
54
55 static void* _ipc_handle = NULL;
56 static bool _load_failed = false;
57
58 static int (*html5_server_load)( const char* );
59 static int (*html5_server_cancelLoad)();
60 static int (*html5_server_play)();
61 static int (*html5_server_pause)();
62 static int (*html5_server_seek)( float );
63 static int (*html5_server_setRate)( float );
64 static int (*html5_server_setVolume)( float );
65 static int (*html5_server_setSize)( int, int );
66 static int (*html5_server_setMuted)( bool );
67 static int (*html5_server_getStatus)( int*, int*, int*, int*, int*, uint64_t*, uint64_t* );
68 static int (*html5_server_getVideoDimension)( int*, int* );
69
70 static void _ipc_init()
71 {
72         if( _ipc_handle == NULL && _load_failed == false )
73         {
74                 fprintf( stderr, "ipc_init\n");
75                 html5_server_load = NULL;
76                 html5_server_cancelLoad = NULL;
77                 html5_server_play = NULL;
78                 html5_server_pause = NULL;
79                 html5_server_seek = NULL;
80                 html5_server_setRate = NULL;
81                 html5_server_setVolume = NULL;
82                 html5_server_setSize = NULL;
83                 html5_server_setMuted = NULL;
84                 html5_server_getStatus = NULL;
85                 html5_server_getVideoDimension = NULL;
86
87                 char* ipc_dl_path = "/webkit/usr/lib/libhtml5_video.so";
88
89                 if( getenv( "HTML5_IPC_PATH" ) )
90                 {
91                         ipc_dl_path = getenv( "HTML5_IPC_PATH" );
92                 }
93
94                 _ipc_handle = dlopen( ipc_dl_path, RTLD_NOW );
95
96                 fprintf( stderr, "ipc handle %x\n", _ipc_handle );
97
98                 if( _ipc_handle )
99                 {
100                         *(void **) (&html5_server_load) = dlsym(_ipc_handle, "html5_video_client_load");
101                         *(void **) (&html5_server_cancelLoad) = dlsym(_ipc_handle, "html5_video_client_cancel_load");
102                         *(void **) (&html5_server_play) = dlsym(_ipc_handle, "html5_video_client_play");
103                         *(void **) (&html5_server_pause) = dlsym(_ipc_handle, "html5_video_client_pause");
104                         *(void **) (&html5_server_seek) = dlsym(_ipc_handle, "html5_video_client_seek");
105                         *(void **) (&html5_server_setRate) = dlsym(_ipc_handle, "html5_video_client_setRate");
106                         *(void **) (&html5_server_setVolume) = dlsym(_ipc_handle, "html5_video_client_setVolume");
107                         *(void **) (&html5_server_setSize) = dlsym(_ipc_handle, "html5_video_client_setSize");
108                         *(void **) (&html5_server_setMuted) = dlsym(_ipc_handle, "html5_video_client_setMuted");
109                         *(void **) (&html5_server_getStatus) = dlsym(_ipc_handle, "html5_video_get_status");
110                         *(void **) (&html5_server_getVideoDimension) = dlsym(_ipc_handle, "html5_video_get_video_dimension");
111
112                 }
113                 else
114                 {
115                         fprintf( stderr, "error %s\n", dlerror() );
116                         _load_failed = true;
117                 }
118         }
119 }
120
121 bool MediaPlayerPrivateElisIPC::isAvailable()
122 {
123     return true;
124 }
125
126 PassOwnPtr<MediaPlayerPrivateInterface> MediaPlayerPrivateElisIPC::create(MediaPlayer* player)
127 {
128     return adoptPtr(new MediaPlayerPrivateElisIPC(player));
129 }
130
131
132 MediaPlayerPrivateElisIPC::MediaPlayerPrivateElisIPC(MediaPlayer* player)
133     : m_player(player)
134     , m_seekTime(0)
135     , m_changingRate(false)
136     , m_endTime(numeric_limits<float>::infinity())
137     , m_networkState(MediaPlayer::Empty)
138     , m_readyState(MediaPlayer::HaveNothing)
139     , m_isStreaming(false)
140     , m_size(IntSize())
141     , m_mediaLocationCurrentIndex(0)
142     , m_resetPipeline(false)
143     , m_paused(true)
144     , m_seeking(false)
145     , m_buffering(false)
146     , m_playbackRate(1)
147     , m_errorOccured(false)
148     , m_mediaDuration(0)
149     , m_startedBuffering(false)
150     , m_fillTimer(this, &MediaPlayerPrivateElisIPC::fillTimerFired)
151     , m_maxTimeLoaded(0)
152     , m_bufferingPercentage(0)
153     , m_preload(MediaPlayer::Auto)
154     , m_delayingLoad(false)
155     , m_mediaDurationKnown(true)
156     , m_volumeTimerHandler(0)
157     , m_muteTimerHandler(0)
158     , m_hasVideo(false)
159     , m_hasAudio(false)
160     , m_audioTimerHandler(0)
161     , m_videoTimerHandler(0)
162         , m_videoSize( 0, 0 )
163         , m_totalBytes( 0 )
164         , m_bytesLoaded( 0 )
165 {
166         fprintf( stderr, "MediaPlayer IPC created\n" );
167
168         if( _ipc_handle == NULL )
169                 _ipc_init();
170 }
171
172 MediaPlayerPrivateElisIPC::~MediaPlayerPrivateElisIPC()
173 {
174         fprintf(stderr, "MediaPlayer IPC Destroyed\n" );
175
176     if (m_fillTimer.isActive())
177         m_fillTimer.stop();
178
179     fprintf( stderr, "cancel load %x", html5_server_cancelLoad );
180
181         if( html5_server_cancelLoad )
182                 html5_server_cancelLoad();
183
184     m_player = 0;
185 }
186
187 void MediaPlayerPrivateElisIPC::registerMediaEngine(MediaEngineRegistrar registrar)
188 {
189     if (isAvailable())
190         registrar(create, getSupportedTypes, supportsType, 0, 0, 0);
191 }
192
193 void MediaPlayerPrivateElisIPC::getSupportedTypes(HashSet<String>& types)
194 {
195     types.add( "video/mp4" );
196 }
197
198 MediaPlayer::SupportsType MediaPlayerPrivateElisIPC::supportsType(const String& type, const String& codecs)
199 {
200     if (type.isNull() || type.isEmpty())
201         return MediaPlayer::IsNotSupported;
202
203     // spec says we should not return "probably" if the codecs string is empty
204     if ( type == "video/mp4" )
205         return MediaPlayer::IsSupported;
206
207     return MediaPlayer::IsNotSupported;
208 }
209
210
211 void MediaPlayerPrivateElisIPC::load(const String& url)
212 {
213         fprintf( stderr, "Load %s %x\n", url.utf8().data(), html5_server_load );
214
215         m_size = IntSize( 0, 0 );
216         m_prevStatus = 0;
217
218     if (m_fillTimer.isActive())
219         m_fillTimer.stop();
220
221         m_fillTimer.startRepeating(1.0);
222
223         if( html5_server_load )
224                 (*html5_server_load)( (const char*)url.utf8().data() );
225 }
226
227
228 float MediaPlayerPrivateElisIPC::playbackPosition() const
229 {
230     return m_playbackPosition;
231 }
232
233 void MediaPlayerPrivateElisIPC::prepareToPlay()
234 {
235         /* TBD */
236 }
237
238 void MediaPlayerPrivateElisIPC::play()
239 {
240         if( html5_server_play )
241                 html5_server_play();
242 }
243
244 void MediaPlayerPrivateElisIPC::pause()
245 {
246         if( html5_server_pause )
247                 html5_server_pause();
248 }
249
250 float MediaPlayerPrivateElisIPC::duration() const
251 {
252     if (m_errorOccured)
253         return 0.0f;
254
255     // Media duration query failed already, don't attempt new useless queries.
256     if (!m_mediaDurationKnown)
257         return numeric_limits<float>::infinity();
258
259     if (m_mediaDuration)
260         return m_mediaDuration;
261
262     return 0.0f;
263 }
264
265 float MediaPlayerPrivateElisIPC::currentTime() const
266 {
267     if (m_errorOccured)
268         return 0.0f;
269
270     if (m_seeking)
271         return m_seekTime;
272
273     return playbackPosition();
274
275 }
276
277 void MediaPlayerPrivateElisIPC::seek(float time)
278 {
279     // Avoid useless seeking.
280     if (time == playbackPosition())
281         return;
282
283     if (m_errorOccured)
284         return;
285
286     // Extract the integer part of the time (seconds) and the
287     // fractional part (microseconds). Attempt to round the
288     // microseconds so no floating point precision is lost and we can
289     // perform an accurate seek.
290     m_seekTime = time;
291     m_seeking = true;
292
293         if( html5_server_seek )
294                 html5_server_seek( time );
295 }
296
297 bool MediaPlayerPrivateElisIPC::paused() const
298 {
299     return m_paused;
300 }
301
302 bool MediaPlayerPrivateElisIPC::seeking() const
303 {
304     return m_seeking;
305 }
306
307 // Returns the size of the video
308 IntSize MediaPlayerPrivateElisIPC::naturalSize() const
309 {
310 //    if (!hasVideo())
311 //        return IntSize();
312
313     // TODO: handle possible clean aperture data. See
314     // https://bugzilla.gnome.org/show_bug.cgi?id=596571
315     // TODO: handle possible transformation matrix. See
316     // https://bugzilla.gnome.org/show_bug.cgi?id=596326
317
318     // Get the video PAR and original size.
319     return m_videoSize;
320 }
321
322 void MediaPlayerPrivateElisIPC::videoChanged()
323 {
324 }
325
326 void MediaPlayerPrivateElisIPC::notifyPlayerOfVideo()
327 {
328     m_videoTimerHandler = 0;
329 }
330
331 void MediaPlayerPrivateElisIPC::audioChanged()
332 {
333 }
334
335 void MediaPlayerPrivateElisIPC::notifyPlayerOfAudio()
336 {
337 }
338
339 void MediaPlayerPrivateElisIPC::setVolume(float volume)
340 {
341         if( html5_server_setVolume )
342                 html5_server_setVolume( volume );
343 }
344
345 void MediaPlayerPrivateElisIPC::notifyPlayerOfVolumeChange()
346 {
347 }
348
349 void MediaPlayerPrivateElisIPC::volumeChanged()
350 {
351 }
352
353 void MediaPlayerPrivateElisIPC::setRate(float rate)
354 {
355         if( html5_server_setRate )
356                 html5_server_setRate( rate );
357 }
358
359 MediaPlayer::NetworkState MediaPlayerPrivateElisIPC::networkState() const
360 {
361     return m_networkState;
362 }
363
364 MediaPlayer::ReadyState MediaPlayerPrivateElisIPC::readyState() const
365 {
366     return m_readyState;
367 }
368
369 PassRefPtr<TimeRanges> MediaPlayerPrivateElisIPC::buffered() const
370 {
371         RefPtr<TimeRanges> timeRanges = TimeRanges::create();
372     return timeRanges.release();
373 }
374
375 void MediaPlayerPrivateElisIPC::fillTimerFired(Timer<MediaPlayerPrivateElisIPC>*)
376 {
377         int playTime = 0;
378         int endTime = 0;
379         int speed = 100;
380         int status = 0;
381         int inSeek = 0;
382         uint64_t totalBytes = 0;
383         uint64_t currentOffset = 0;
384
385         if( html5_server_getStatus )
386                 html5_server_getStatus( &playTime, &endTime, &speed, &status, &inSeek, &totalBytes, &currentOffset );
387
388         int videoWidth = 0, videoHeight = 0;
389
390         if( html5_server_getVideoDimension )
391                 html5_server_getVideoDimension( &videoWidth, &videoHeight );
392
393         float duration = endTime / 1000.0;
394         float currentPos = playTime / 1000.0;
395         float ratio = speed / 100.0;
396
397         fprintf( stderr, "Duration %f, currentPos %f, ratio %f videoWidth = %d, videoHeight = %d Download[%lld:%lld]\n",
398                                                 duration, currentPos, ratio, videoWidth, videoHeight, totalBytes, currentOffset );
399
400         m_totalBytes = totalBytes;
401         m_bytesLoaded = m_totalBytes;
402
403         if( m_mediaDuration != duration )
404         {
405                 m_mediaDuration = duration;
406                 m_mediaDurationKnown = true;
407                 durationChanged();
408         }
409
410         MediaPlayer::ReadyState readyState = MediaPlayer::HaveMetadata;
411         MediaPlayer::NetworkState networkState = MediaPlayer::Loading;
412
413         switch( status )
414         {
415         case 0: /* STOPPED */
416 //              readyState = MediaPlayer::HaveNothing;
417 //              networkState = MediaPlayer::Idle;
418                 break;
419
420         case 1: /* PLAYING */
421                 if( videoWidth > 0 )
422                         readyState = MediaPlayer::HaveEnoughData;
423                 networkState = MediaPlayer::Loading;
424                 break;
425
426         case 2: /* Paused */
427                 break;
428         case 3: /* Connecting */
429                 readyState = MediaPlayer::HaveMetadata;
430                 networkState = MediaPlayer::Loading;
431                 break;
432         case 4: /* Buffering */
433                 readyState = MediaPlayer::HaveMetadata;
434                 networkState = MediaPlayer::Loading;
435                 break;
436         case 5: /* Finished */
437                 readyState = MediaPlayer::HaveEnoughData;
438                 networkState = MediaPlayer::Loaded;
439                 break;
440         case 6: /* Error */
441                 readyState = MediaPlayer::HaveNothing;
442                 break;
443         }
444
445         if( status == 5 && m_prevStatus != 5 )
446         {
447                 m_prevStatus = status;
448                 m_player->playbackStateChanged();
449         }
450
451         if( status == 1 && m_prevStatus != 1 )
452         {
453                 m_prevStatus = status;
454                 m_player->playbackStateChanged();
455         }
456
457         if( readyState != m_readyState )
458         {
459                 m_readyState = readyState;
460                 m_player->readyStateChanged();
461         }
462
463         if( networkState != m_networkState )
464         {
465                 m_networkState = networkState;
466                 m_player->networkStateChanged();
467         }
468
469         if( m_videoSize.width() != videoWidth || m_videoSize.height() != videoHeight )
470         {
471                 m_videoSize.setWidth( videoWidth );
472                 m_videoSize.setHeight( videoHeight );
473
474                 m_player->sizeChanged();
475         }
476
477         m_player->timeChanged();
478
479         bool paused = false;
480         if( ratio == 0.0f )
481                 paused = true;
482
483         if( paused != m_paused && status != 5 && status !=  6 )
484         {
485                 m_paused = paused;
486         }
487
488         if( status == 5 )
489                 m_paused = false;
490
491         if( inSeek == 0 )
492                 m_seeking = false;
493
494         m_playbackPosition = currentPos;
495 }
496
497 float MediaPlayerPrivateElisIPC::maxTimeSeekable() const
498 {
499     if (m_errorOccured)
500         return 0.0f;
501
502     LOG_VERBOSE(Media, "maxTimeSeekable");
503     // infinite duration means live stream
504     if (isinf(duration()))
505         return 0.0f;
506
507     return duration();
508 }
509
510 float MediaPlayerPrivateElisIPC::maxTimeLoaded() const
511 {
512     if (m_errorOccured)
513         return 0.0f;
514
515     float loaded = m_maxTimeLoaded;
516     if (!loaded && !m_fillTimer.isActive())
517         loaded = duration();
518     LOG_VERBOSE(Media, "maxTimeLoaded: %f", loaded);
519     return loaded;
520 }
521
522 unsigned MediaPlayerPrivateElisIPC::bytesLoaded() const
523 {
524     if (!m_mediaDuration)
525         return 0;
526
527     return m_bytesLoaded;
528 }
529
530 unsigned MediaPlayerPrivateElisIPC::totalBytes() const
531 {
532     if (m_errorOccured)
533         return 0;
534
535     return m_totalBytes;
536 }
537
538 unsigned MediaPlayerPrivateElisIPC::decodedFrameCount() const
539 {
540         return 0;
541 }
542
543 unsigned MediaPlayerPrivateElisIPC::droppedFrameCount() const
544 {
545         return 0;
546 }
547
548 unsigned MediaPlayerPrivateElisIPC::audioDecodedByteCount() const
549 {
550         return 0;
551 }
552
553 unsigned MediaPlayerPrivateElisIPC::videoDecodedByteCount() const
554 {
555         return 0;
556 }
557
558 void MediaPlayerPrivateElisIPC::updateAudioSink()
559 {
560 }
561
562
563 void MediaPlayerPrivateElisIPC::sourceChanged()
564 {
565 }
566
567 void MediaPlayerPrivateElisIPC::cancelLoad()
568 {
569     if (m_fillTimer.isActive())
570         m_fillTimer.stop();
571
572     fprintf( stderr, "cancel load %x", html5_server_cancelLoad );
573
574         if( html5_server_cancelLoad )
575                 html5_server_cancelLoad();
576 }
577
578 void MediaPlayerPrivateElisIPC::updateStates()
579 {
580 }
581
582
583 bool MediaPlayerPrivateElisIPC::loadNextLocation()
584 {
585 }
586
587 void MediaPlayerPrivateElisIPC::loadStateChanged()
588 {
589     updateStates();
590 }
591
592 void MediaPlayerPrivateElisIPC::sizeChanged()
593 {
594     notImplemented();
595 }
596
597 void MediaPlayerPrivateElisIPC::timeChanged()
598 {
599     updateStates();
600     m_player->timeChanged();
601 }
602
603 void MediaPlayerPrivateElisIPC::didEnd()
604 {
605     // EOS was reached but in case of reverse playback the position is
606     // not always 0. So to not confuse the HTMLMediaElement we
607     // synchronize position and duration values.
608     float now = currentTime();
609     if (now > 0) {
610         m_mediaDuration = now;
611         m_mediaDurationKnown = true;
612         m_player->durationChanged();
613     }
614 }
615
616 void MediaPlayerPrivateElisIPC::cacheDuration()
617 {
618     // Reset cached media duration
619     m_mediaDuration = 0;
620 }
621
622 void MediaPlayerPrivateElisIPC::durationChanged()
623 {
624     m_player->durationChanged();
625 }
626
627 bool MediaPlayerPrivateElisIPC::supportsMuting() const
628 {
629     return true;
630 }
631
632 void MediaPlayerPrivateElisIPC::setMuted(bool muted)
633 {
634         if( html5_server_setMuted )
635                 html5_server_setMuted( muted );
636 }
637
638 void MediaPlayerPrivateElisIPC::notifyPlayerOfMute()
639 {
640     m_muteTimerHandler = 0;
641
642 }
643
644 void MediaPlayerPrivateElisIPC::muteChanged()
645 {
646     if (m_muteTimerHandler)
647         g_source_remove(m_muteTimerHandler);
648 }
649
650 void MediaPlayerPrivateElisIPC::loadingFailed(MediaPlayer::NetworkState error)
651 {
652     m_errorOccured = true;
653     if (m_networkState != error) {
654         m_networkState = error;
655         m_player->networkStateChanged();
656     }
657     if (m_readyState != MediaPlayer::HaveNothing) {
658         m_readyState = MediaPlayer::HaveNothing;
659         m_player->readyStateChanged();
660     }
661 }
662
663 void MediaPlayerPrivateElisIPC::setSize(const IntSize& size)
664 {
665         fprintf( stderr, "setsize %d %d\n", size.width(), size.height() );
666     m_size = size;
667 }
668
669 void MediaPlayerPrivateElisIPC::setVisible(bool visible)
670 {
671 }
672
673
674
675 void MediaPlayerPrivateElisIPC::paint(GraphicsContext* context, const IntRect& rect)
676 {
677
678     if (context->paintingDisabled())
679     {
680         fprintf( stderr, "%s %s %d\n", __FILE__, __func__, __LINE__ );
681         return;
682     }
683
684     if (!m_player->visible())
685     {
686         fprintf( stderr, "%s %s %d\n", __FILE__, __func__, __LINE__ );
687         return;
688     }
689
690 #if defined(XP_UNIX)
691 #if PLATFORM(X11)
692                 Display* display = GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
693
694                 cairo_t* cr = context->platformContext()->cr();
695                 cairo_save(cr);
696
697                 cairo_rectangle(cr,
698                                 rect.x(), rect.y(),
699                                 rect.width(), rect.height());
700
701                 cairo_set_source_rgba(cr, 0xff, 0x0, 0x0, 0xff );
702
703         cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
704             cairo_fill(cr);
705
706                 cairo_restore(cr);
707 #else
708                 cairo_t* cr = context->platformContext()->cr();
709                 cairo_save(cr);
710
711                 cairo_rectangle(cr,
712                                 rect.x(), rect.y(),
713                                 rect.width(), rect.height());
714
715                 cairo_set_source_rgba(cr, 0, 0x0, 0x0, 0 );
716
717         cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
718             cairo_fill(cr);
719
720                 cairo_restore(cr);
721
722 #endif
723 #endif
724 }
725
726 static HashSet<String> mimeTypeCache()
727 {
728
729 }
730
731 bool MediaPlayerPrivateElisIPC::hasSingleSecurityOrigin() const
732 {
733     return true;
734 }
735
736 bool MediaPlayerPrivateElisIPC::supportsFullscreen() const
737 {
738     return true;
739 }
740
741 PlatformMedia MediaPlayerPrivateElisIPC::platformMedia() const
742 {
743 }
744
745 void MediaPlayerPrivateElisIPC::setPreload(MediaPlayer::Preload preload)
746 {
747 }
748
749 }
750 #endif // USE(GSTREAMER)
751
752