2 * MediaPlayerPrivateElisIPC.cpp
4 * Created on: 2013. 9. 29.
9 #include "MediaPlayerPrivateElisIPC.h"
11 #if ENABLE_VIDEO && ENABLE_ELIS_MEDIA
13 #include "ColorSpace.h"
16 #include "FrameView.h"
17 #include "GraphicsContext.h"
18 #include "GraphicsTypes.h"
21 #include "MIMETypeRegistry.h"
22 #include "MediaPlayer.h"
23 #include "NotImplemented.h"
24 #include "SecurityOrigin.h"
25 #include "TimeRanges.h"
29 #include <wtf/text/CString.h>
32 #include "PlatformContextCairo.h"
36 #include "RefPtrCairo.h"
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>
43 #elif defined(GDK_WINDOWING_DIRECTFB)
46 #elif defined(GDK_WINDOWING_WIN32)
47 #include "PluginMessageThrottlerWin.h"
48 #include <gdk/gdkwin32.h>
55 static void* _ipc_handle = NULL;
56 static bool _load_failed = false;
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* );
70 static void _ipc_init()
72 if( _ipc_handle == NULL && _load_failed == false )
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;
87 char* ipc_dl_path = "/webkit/usr/lib/libhtml5_video.so";
89 if( getenv( "HTML5_IPC_PATH" ) )
91 ipc_dl_path = getenv( "HTML5_IPC_PATH" );
94 _ipc_handle = dlopen( ipc_dl_path, RTLD_NOW );
96 fprintf( stderr, "ipc handle %x\n", _ipc_handle );
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");
115 fprintf( stderr, "error %s\n", dlerror() );
121 bool MediaPlayerPrivateElisIPC::isAvailable()
126 PassOwnPtr<MediaPlayerPrivateInterface> MediaPlayerPrivateElisIPC::create(MediaPlayer* player)
128 return adoptPtr(new MediaPlayerPrivateElisIPC(player));
132 MediaPlayerPrivateElisIPC::MediaPlayerPrivateElisIPC(MediaPlayer* player)
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)
141 , m_mediaLocationCurrentIndex(0)
142 , m_resetPipeline(false)
147 , m_errorOccured(false)
149 , m_startedBuffering(false)
150 , m_fillTimer(this, &MediaPlayerPrivateElisIPC::fillTimerFired)
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)
160 , m_audioTimerHandler(0)
161 , m_videoTimerHandler(0)
162 , m_videoSize( 0, 0 )
166 fprintf( stderr, "MediaPlayer IPC created\n" );
168 if( _ipc_handle == NULL )
172 MediaPlayerPrivateElisIPC::~MediaPlayerPrivateElisIPC()
174 fprintf(stderr, "MediaPlayer IPC Destroyed\n" );
176 if (m_fillTimer.isActive())
179 fprintf( stderr, "cancel load %x", html5_server_cancelLoad );
181 if( html5_server_cancelLoad )
182 html5_server_cancelLoad();
187 void MediaPlayerPrivateElisIPC::registerMediaEngine(MediaEngineRegistrar registrar)
190 registrar(create, getSupportedTypes, supportsType, 0, 0, 0);
193 void MediaPlayerPrivateElisIPC::getSupportedTypes(HashSet<String>& types)
195 types.add( "video/mp4" );
198 MediaPlayer::SupportsType MediaPlayerPrivateElisIPC::supportsType(const String& type, const String& codecs)
200 if (type.isNull() || type.isEmpty())
201 return MediaPlayer::IsNotSupported;
203 // spec says we should not return "probably" if the codecs string is empty
204 if ( type == "video/mp4" )
205 return MediaPlayer::IsSupported;
207 return MediaPlayer::IsNotSupported;
211 void MediaPlayerPrivateElisIPC::load(const String& url)
213 fprintf( stderr, "Load %s %x\n", url.utf8().data(), html5_server_load );
215 m_size = IntSize( 0, 0 );
218 if (m_fillTimer.isActive())
221 m_fillTimer.startRepeating(1.0);
223 if( html5_server_load )
224 (*html5_server_load)( (const char*)url.utf8().data() );
228 float MediaPlayerPrivateElisIPC::playbackPosition() const
230 return m_playbackPosition;
233 void MediaPlayerPrivateElisIPC::prepareToPlay()
238 void MediaPlayerPrivateElisIPC::play()
240 if( html5_server_play )
244 void MediaPlayerPrivateElisIPC::pause()
246 if( html5_server_pause )
247 html5_server_pause();
250 float MediaPlayerPrivateElisIPC::duration() const
255 // Media duration query failed already, don't attempt new useless queries.
256 if (!m_mediaDurationKnown)
257 return numeric_limits<float>::infinity();
260 return m_mediaDuration;
265 float MediaPlayerPrivateElisIPC::currentTime() const
273 return playbackPosition();
277 void MediaPlayerPrivateElisIPC::seek(float time)
279 // Avoid useless seeking.
280 if (time == playbackPosition())
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.
293 if( html5_server_seek )
294 html5_server_seek( time );
297 bool MediaPlayerPrivateElisIPC::paused() const
302 bool MediaPlayerPrivateElisIPC::seeking() const
307 // Returns the size of the video
308 IntSize MediaPlayerPrivateElisIPC::naturalSize() const
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
318 // Get the video PAR and original size.
322 void MediaPlayerPrivateElisIPC::videoChanged()
326 void MediaPlayerPrivateElisIPC::notifyPlayerOfVideo()
328 m_videoTimerHandler = 0;
331 void MediaPlayerPrivateElisIPC::audioChanged()
335 void MediaPlayerPrivateElisIPC::notifyPlayerOfAudio()
339 void MediaPlayerPrivateElisIPC::setVolume(float volume)
341 if( html5_server_setVolume )
342 html5_server_setVolume( volume );
345 void MediaPlayerPrivateElisIPC::notifyPlayerOfVolumeChange()
349 void MediaPlayerPrivateElisIPC::volumeChanged()
353 void MediaPlayerPrivateElisIPC::setRate(float rate)
355 if( html5_server_setRate )
356 html5_server_setRate( rate );
359 MediaPlayer::NetworkState MediaPlayerPrivateElisIPC::networkState() const
361 return m_networkState;
364 MediaPlayer::ReadyState MediaPlayerPrivateElisIPC::readyState() const
369 PassRefPtr<TimeRanges> MediaPlayerPrivateElisIPC::buffered() const
371 RefPtr<TimeRanges> timeRanges = TimeRanges::create();
372 return timeRanges.release();
375 void MediaPlayerPrivateElisIPC::fillTimerFired(Timer<MediaPlayerPrivateElisIPC>*)
382 uint64_t totalBytes = 0;
383 uint64_t currentOffset = 0;
385 if( html5_server_getStatus )
386 html5_server_getStatus( &playTime, &endTime, &speed, &status, &inSeek, &totalBytes, ¤tOffset );
388 int videoWidth = 0, videoHeight = 0;
390 if( html5_server_getVideoDimension )
391 html5_server_getVideoDimension( &videoWidth, &videoHeight );
393 float duration = endTime / 1000.0;
394 float currentPos = playTime / 1000.0;
395 float ratio = speed / 100.0;
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 );
400 m_totalBytes = totalBytes;
401 m_bytesLoaded = m_totalBytes;
403 if( m_mediaDuration != duration )
405 m_mediaDuration = duration;
406 m_mediaDurationKnown = true;
410 MediaPlayer::ReadyState readyState = MediaPlayer::HaveMetadata;
411 MediaPlayer::NetworkState networkState = MediaPlayer::Loading;
415 case 0: /* STOPPED */
416 // readyState = MediaPlayer::HaveNothing;
417 // networkState = MediaPlayer::Idle;
420 case 1: /* PLAYING */
422 readyState = MediaPlayer::HaveEnoughData;
423 networkState = MediaPlayer::Loading;
428 case 3: /* Connecting */
429 readyState = MediaPlayer::HaveMetadata;
430 networkState = MediaPlayer::Loading;
432 case 4: /* Buffering */
433 readyState = MediaPlayer::HaveMetadata;
434 networkState = MediaPlayer::Loading;
436 case 5: /* Finished */
437 readyState = MediaPlayer::HaveEnoughData;
438 networkState = MediaPlayer::Loaded;
441 readyState = MediaPlayer::HaveNothing;
445 if( status == 5 && m_prevStatus != 5 )
447 m_prevStatus = status;
448 m_player->playbackStateChanged();
451 if( status == 1 && m_prevStatus != 1 )
453 m_prevStatus = status;
454 m_player->playbackStateChanged();
457 if( readyState != m_readyState )
459 m_readyState = readyState;
460 m_player->readyStateChanged();
463 if( networkState != m_networkState )
465 m_networkState = networkState;
466 m_player->networkStateChanged();
469 if( m_videoSize.width() != videoWidth || m_videoSize.height() != videoHeight )
471 m_videoSize.setWidth( videoWidth );
472 m_videoSize.setHeight( videoHeight );
474 m_player->sizeChanged();
477 m_player->timeChanged();
483 if( paused != m_paused && status != 5 && status != 6 )
494 m_playbackPosition = currentPos;
497 float MediaPlayerPrivateElisIPC::maxTimeSeekable() const
502 LOG_VERBOSE(Media, "maxTimeSeekable");
503 // infinite duration means live stream
504 if (isinf(duration()))
510 float MediaPlayerPrivateElisIPC::maxTimeLoaded() const
515 float loaded = m_maxTimeLoaded;
516 if (!loaded && !m_fillTimer.isActive())
518 LOG_VERBOSE(Media, "maxTimeLoaded: %f", loaded);
522 unsigned MediaPlayerPrivateElisIPC::bytesLoaded() const
524 if (!m_mediaDuration)
527 return m_bytesLoaded;
530 unsigned MediaPlayerPrivateElisIPC::totalBytes() const
538 unsigned MediaPlayerPrivateElisIPC::decodedFrameCount() const
543 unsigned MediaPlayerPrivateElisIPC::droppedFrameCount() const
548 unsigned MediaPlayerPrivateElisIPC::audioDecodedByteCount() const
553 unsigned MediaPlayerPrivateElisIPC::videoDecodedByteCount() const
558 void MediaPlayerPrivateElisIPC::updateAudioSink()
563 void MediaPlayerPrivateElisIPC::sourceChanged()
567 void MediaPlayerPrivateElisIPC::cancelLoad()
569 if (m_fillTimer.isActive())
572 fprintf( stderr, "cancel load %x", html5_server_cancelLoad );
574 if( html5_server_cancelLoad )
575 html5_server_cancelLoad();
578 void MediaPlayerPrivateElisIPC::updateStates()
583 bool MediaPlayerPrivateElisIPC::loadNextLocation()
587 void MediaPlayerPrivateElisIPC::loadStateChanged()
592 void MediaPlayerPrivateElisIPC::sizeChanged()
597 void MediaPlayerPrivateElisIPC::timeChanged()
600 m_player->timeChanged();
603 void MediaPlayerPrivateElisIPC::didEnd()
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();
610 m_mediaDuration = now;
611 m_mediaDurationKnown = true;
612 m_player->durationChanged();
616 void MediaPlayerPrivateElisIPC::cacheDuration()
618 // Reset cached media duration
622 void MediaPlayerPrivateElisIPC::durationChanged()
624 m_player->durationChanged();
627 bool MediaPlayerPrivateElisIPC::supportsMuting() const
632 void MediaPlayerPrivateElisIPC::setMuted(bool muted)
634 if( html5_server_setMuted )
635 html5_server_setMuted( muted );
638 void MediaPlayerPrivateElisIPC::notifyPlayerOfMute()
640 m_muteTimerHandler = 0;
644 void MediaPlayerPrivateElisIPC::muteChanged()
646 if (m_muteTimerHandler)
647 g_source_remove(m_muteTimerHandler);
650 void MediaPlayerPrivateElisIPC::loadingFailed(MediaPlayer::NetworkState error)
652 m_errorOccured = true;
653 if (m_networkState != error) {
654 m_networkState = error;
655 m_player->networkStateChanged();
657 if (m_readyState != MediaPlayer::HaveNothing) {
658 m_readyState = MediaPlayer::HaveNothing;
659 m_player->readyStateChanged();
663 void MediaPlayerPrivateElisIPC::setSize(const IntSize& size)
665 fprintf( stderr, "setsize %d %d\n", size.width(), size.height() );
669 void MediaPlayerPrivateElisIPC::setVisible(bool visible)
675 void MediaPlayerPrivateElisIPC::paint(GraphicsContext* context, const IntRect& rect)
678 if (context->paintingDisabled())
680 fprintf( stderr, "%s %s %d\n", __FILE__, __func__, __LINE__ );
684 if (!m_player->visible())
686 fprintf( stderr, "%s %s %d\n", __FILE__, __func__, __LINE__ );
692 Display* display = GDK_DISPLAY_XDISPLAY(gdk_display_get_default());
694 cairo_t* cr = context->platformContext()->cr();
699 rect.width(), rect.height());
701 cairo_set_source_rgba(cr, 0xff, 0x0, 0x0, 0xff );
703 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
708 cairo_t* cr = context->platformContext()->cr();
713 rect.width(), rect.height());
715 cairo_set_source_rgba(cr, 0, 0x0, 0x0, 0 );
717 cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE);
726 static HashSet<String> mimeTypeCache()
731 bool MediaPlayerPrivateElisIPC::hasSingleSecurityOrigin() const
736 bool MediaPlayerPrivateElisIPC::supportsFullscreen() const
741 PlatformMedia MediaPlayerPrivateElisIPC::platformMedia() const
745 void MediaPlayerPrivateElisIPC::setPreload(MediaPlayer::Preload preload)
750 #endif // USE(GSTREAMER)