Index: wxwidgets3.0-3.0.2+dfsg/configure.in =================================================================== --- wxwidgets3.0-3.0.2+dfsg.orig/configure.in +++ wxwidgets3.0-3.0.2+dfsg/configure.in @@ -7543,43 +7543,22 @@ if test "$wxUSE_MEDIACTRL" = "yes" -o "$ wxUSE_GSTREAMER="no" dnl ------------------------------------------------------------------- - dnl Test for at least 0.8 gstreamer module from pkg-config - dnl Even totem doesn't accept 0.9 evidently. - dnl - dnl So, we first check to see if 0.10 if available - if not we - dnl try the older 0.8 version + dnl Test for at least gstreamer 1.0 module from pkg-config dnl ------------------------------------------------------------------- - GST_VERSION_MAJOR=0 - GST_VERSION_MINOR=10 + GST_VERSION_MAJOR=1 + GST_VERSION_MINOR=0 GST_VERSION=$GST_VERSION_MAJOR.$GST_VERSION_MINOR - if test "$wxUSE_GSTREAMER8" = "no"; then - PKG_CHECK_MODULES(GST, - [gstreamer-$GST_VERSION gstreamer-plugins-base-$GST_VERSION], - [ - wxUSE_GSTREAMER="yes" - GST_LIBS="$GST_LIBS -lgstinterfaces-$GST_VERSION" - ], - [ - AC_MSG_WARN([GStreamer 0.10 not available, falling back to 0.8]) - GST_VERSION_MINOR=8 - ] - ) - else - dnl check only for 0.8 - GST_VERSION_MINOR=8 - fi - - if test $GST_VERSION_MINOR = "8"; then - GST_VERSION=$GST_VERSION_MAJOR.$GST_VERSION_MINOR - PKG_CHECK_MODULES(GST, - [gstreamer-$GST_VERSION gstreamer-interfaces-$GST_VERSION gstreamer-gconf-$GST_VERSION], - wxUSE_GSTREAMER="yes", - [ - AC_MSG_WARN([GStreamer 0.8/0.10 not available.]) - ]) - fi - + PKG_CHECK_MODULES(GST, + [gstreamer-$GST_VERSION gstreamer-plugins-base-$GST_VERSION], + [ + wxUSE_GSTREAMER="yes" + GST_LIBS="$GST_LIBS -lgstvideo-$GST_VERSION" + ], + [ + AC_MSG_WARN([GStreamer 1.0 not available]) + ] + ) if test "$wxUSE_GSTREAMER" = "yes"; then CPPFLAGS="$GST_CFLAGS $CPPFLAGS" Index: wxwidgets3.0-3.0.2+dfsg/src/unix/mediactrl.cpp =================================================================== --- wxwidgets3.0-3.0.2+dfsg.orig/src/unix/mediactrl.cpp +++ wxwidgets3.0-3.0.2+dfsg/src/unix/mediactrl.cpp @@ -19,13 +19,7 @@ #include // main gstreamer header -// xoverlay/video stuff, gst-gconf for 0.8 -#if GST_VERSION_MAJOR > 0 || GST_VERSION_MINOR >= 10 -# include -#else -# include -# include // gstreamer glib configuration -#endif +#include #ifndef WX_PRECOMP #include "wx/log.h" // wxLogDebug/wxLogSysError/wxLogTrace @@ -48,11 +42,11 @@ //----------------------------------------------------------------------------- /* - This is the GStreamer backend for unix. Currently we require 0.8 or - 0.10. Here we use the "playbin" GstElement for ease of use. + This is the GStreamer backend for unix. Currently we require 1.0. + Here we use the "playbin" GstElement for ease of use. - Note that now we compare state change functions to GST_STATE_FAILURE - now rather than GST_STATE_SUCCESS as newer gstreamer versions return + Note that now we compare state change functions to GST_STATE_CHANGE_FAILURE + now rather than GST_STATE_CHANGE_SUCCESS as newer gstreamer versions return non-success values for returns that are otherwise successful but not immediate. @@ -60,11 +54,8 @@ moment but with a tad bit of work it could theorectically work in straight wxX11 et al. - One last note is that resuming from pausing/seeking can result - in erratic video playback (GStreamer-based bug, happens in totem as well) - - this is better in 0.10, however. One thing that might make it worse - here is that we don't preserve the aspect ratio of the video and stretch - it to the whole window. + One last note is that we don't preserve the aspect ratio of the video and + stretch it to the whole window. Note that there are some things used here that could be undocumented - for reference see the media player Kiss and Totem as well as some @@ -72,12 +63,10 @@ that attempted thread-safety... Then there is the issue of m_asynclock. This serves several purposes: - 1) It prevents the C callbacks from sending wx state change events - so that we don't get duplicate ones in 0.8 - 2) It makes the sync and async handlers in 0.10 not drop any + 1) It makes the sync and async handlers not drop any messages so that while we are polling it we get the messages in SyncStateChange instead of the queue. - 3) Keeps the pausing in Stop() synchronous + 2) Keeps the pausing in Stop() synchronous RN: Note that I've tried to follow the wxGTK conventions here as close as possible. In the implementation the C Callbacks come first, then @@ -90,43 +79,9 @@ //============================================================================= //----------------------------------------------------------------------------- -// GStreamer (most version compatibility) macros +// GStreamer macros //----------------------------------------------------------------------------- -// In 0.9 there was a HUGE change to GstQuery and the -// gst_element_query function changed dramatically and split off -// into two separate ones -#if GST_VERSION_MAJOR == 0 && GST_VERSION_MINOR <= 8 -# define wxGst_element_query_duration(e, f, p) \ - gst_element_query(e, GST_QUERY_TOTAL, f, p) -# define wxGst_element_query_position(e, f, p) \ - gst_element_query(e, GST_QUERY_POSITION, f, p) -#elif GST_VERSION_MAJOR == 0 && GST_VERSION_MINOR == 9 -// However, the actual 0.9 version has a slightly different definition -// and instead of gst_element_query_duration it has two parameters to -// gst_element_query_position instead -# define wxGst_element_query_duration(e, f, p) \ - gst_element_query_position(e, f, 0, p) -# define wxGst_element_query_position(e, f, p) \ - gst_element_query_position(e, f, p, 0) -#else -# define wxGst_element_query_duration \ - gst_element_query_duration -# define wxGst_element_query_position \ - gst_element_query_position -#endif - -// Other 0.10 macros -#if GST_VERSION_MAJOR > 0 || GST_VERSION_MINOR >= 10 -# define GST_STATE_FAILURE GST_STATE_CHANGE_FAILURE -# define GST_STATE_SUCCESS GST_STATE_CHANGE_SUCCESS -# define GstElementState GstState -# define gst_gconf_get_default_video_sink() \ - gst_element_factory_make ("gconfvideosink", "video-sink"); -# define gst_gconf_get_default_audio_sink() \ - gst_element_factory_make ("gconfaudiosink", "audio-sink"); -#endif - // Max wait time for element state waiting - GST_CLOCK_TIME_NONE for inf #define wxGSTREAMER_TIMEOUT (100 * GST_MSECOND) // Max 100 milliseconds @@ -189,11 +144,11 @@ public: bool CheckForErrors(); bool DoLoad(const wxString& locstring); wxMediaCtrl* GetControl() { return m_ctrl; } // for C Callbacks - void HandleStateChange(GstElementState oldstate, GstElementState newstate); + void HandleStateChange(GstState oldstate, GstState newstate); bool QueryVideoSizeFromElement(GstElement* element); bool QueryVideoSizeFromPad(GstPad* caps); - void SetupXOverlay(); - bool SyncStateChange(GstElement* element, GstElementState state, + void SetupVideoOverlay(); + bool SyncStateChange(GstElement* element, GstState state, gint64 llTimeout = wxGSTREAMER_TIMEOUT); bool TryAudioSink(GstElement* audiosink); bool TryVideoSink(GstElement* videosink); @@ -203,7 +158,7 @@ public: double m_dRate; // Current playback rate - // see GetPlaybackRate for notes wxLongLong m_llPausedPos; // Paused position - see Pause() - GstXOverlay* m_xoverlay; // X Overlay that contains the GST video + GstVideoOverlay* m_videooverlay; // Video Overlay that contains the GST video wxMutex m_asynclock; // See "discussion of internals" class wxGStreamerMediaEventHandler* m_eventHandler; // see below @@ -284,7 +239,7 @@ expose_event(GtkWidget* widget, GdkEvent { // I've seen this recommended somewhere... // TODO: Is this needed? Maybe it is just cruft... - // gst_x_overlay_set_xwindow_id( GST_X_OVERLAY(be->m_xoverlay), + // gst_video_overlay_set_window_handle( GST_VIDEO_OVERLAY(be->m_videooverlay), // GDK_WINDOW_XWINDOW( window ) ); // If we have actual video..... @@ -294,7 +249,7 @@ expose_event(GtkWidget* widget, GdkEvent // GST Doesn't redraw automatically while paused // Plus, the video sometimes doesn't redraw when it looses focus // or is painted over so we just tell it to redraw... - gst_x_overlay_expose(be->m_xoverlay); + gst_video_overlay_expose(be->m_videooverlay); } else { @@ -334,7 +289,7 @@ static gint gtk_window_realize_callback( GdkWindow* window = gtk_widget_get_window(widget); wxASSERT(window); - gst_x_overlay_set_xwindow_id( GST_X_OVERLAY(be->m_xoverlay), + gst_video_overlay_set_window_handle( GST_VIDEO_OVERLAY(be->m_videooverlay), GDK_WINDOW_XID(window) ); GtkWidget* w = be->GetControl()->m_wxwindow; @@ -349,30 +304,6 @@ static gint gtk_window_realize_callback( #endif // wxGTK //----------------------------------------------------------------------------- -// "state-change" from m_playbin/GST_MESSAGE_STATE_CHANGE -// -// Called by gstreamer when the state changes - here we -// send the appropriate corresponding wx event. -// -// 0.8 only as HandleStateChange does this in both versions -//----------------------------------------------------------------------------- -#if GST_VERSION_MAJOR == 0 && GST_VERSION_MINOR < 10 -extern "C" { -static void gst_state_change_callback(GstElement *play, - GstElementState oldstate, - GstElementState newstate, - wxGStreamerMediaBackend* be) -{ - if(be->m_asynclock.TryLock() == wxMUTEX_NO_ERROR) - { - be->HandleStateChange(oldstate, newstate); - be->m_asynclock.Unlock(); - } -} -} -#endif // <0.10 - -//----------------------------------------------------------------------------- // "eos" from m_playbin/GST_MESSAGE_EOS // // Called by gstreamer when the media is done playing ("end of stream") @@ -425,69 +356,17 @@ static void gst_notify_caps_callback(Gst } //----------------------------------------------------------------------------- -// "notify::stream-info" from m_playbin -// -// Run through the stuff in "stream-info" of m_playbin for a valid -// video pad, and then attempt to query the video size from it - if not -// set up an event to do so when ready. -// -// Currently unused - now we just query it directly using -// QueryVideoSizeFromElement. -// -// (Undocumented?) -//----------------------------------------------------------------------------- -#if GST_VERSION_MAJOR > 0 || GST_VERSION_MINOR >= 10 -extern "C" { -static void gst_notify_stream_info_callback(GstElement* WXUNUSED(element), - GParamSpec* WXUNUSED(pspec), - wxGStreamerMediaBackend* be) -{ - wxLogTrace(wxTRACE_GStreamer, wxT("gst_notify_stream_info_callback")); - be->QueryVideoSizeFromElement(be->m_playbin); -} -} -#endif - -//----------------------------------------------------------------------------- -// "desired-size-changed" from m_xoverlay -// -// 0.8-specific this provides us with the video size when it changes - -// even though we get the caps as well this seems to come before the -// caps notification does... -// -// Note it will return 16,16 for an early-bird value or for audio -//----------------------------------------------------------------------------- -#if GST_VERSION_MAJOR == 0 && GST_VERSION_MINOR < 10 -extern "C" { -static void gst_desired_size_changed_callback(GstElement * play, - guint width, guint height, - wxGStreamerMediaBackend* be) -{ - if(!(width == 16 && height == 16)) - { - be->m_videoSize.x = width; - be->m_videoSize.y = height; - } - else - be->QueryVideoSizeFromElement(be->m_playbin); -} -} -#endif - -//----------------------------------------------------------------------------- // gst_bus_async_callback [static] // gst_bus_sync_callback [static] // -// Called by m_playbin for notifications such as end-of-stream in 0.10 - -// in previous versions g_signal notifications were used. Because everything +// Called by m_playbin for notifications such as end-of-stream. Because everything // in centered in one switch statement though it reminds one of old WinAPI // stuff. // // gst_bus_sync_callback is that sync version that is called on the main GUI // thread before the async version that we use to set the xwindow id of the -// XOverlay (NB: This isn't currently used - see CreateControl()). +// VideoOverlay (NB: This isn't currently used - see CreateControl()). //----------------------------------------------------------------------------- -#if GST_VERSION_MAJOR > 0 || GST_VERSION_MINOR >= 10 extern "C" { static gboolean gst_bus_async_callback(GstBus* WXUNUSED(bus), GstMessage* message, @@ -537,8 +416,7 @@ static GstBusSyncReply gst_bus_sync_call { // Pass a non-xwindowid-setting event on to the async handler where it // belongs - if (GST_MESSAGE_TYPE (message) != GST_MESSAGE_ELEMENT || - !gst_structure_has_name (message->structure, "prepare-xwindow-id")) + if (!gst_is_video_overlay_prepare_window_handle_message (message)) { // // NB: Unfortunately, the async callback can be quite @@ -552,12 +430,11 @@ static GstBusSyncReply gst_bus_sync_call return GST_BUS_DROP; } - wxLogTrace(wxTRACE_GStreamer, wxT("Got prepare-xwindow-id")); - be->SetupXOverlay(); + wxLogTrace(wxTRACE_GStreamer, wxT("Got prepare-window-handle")); + be->SetupVideoOverlay(); return GST_BUS_DROP; // We handled this message - drop from the queue } } -#endif //----------------------------------------------------------------------------- // @@ -569,11 +446,11 @@ static GstBusSyncReply gst_bus_sync_call // wxGStreamerMediaBackend::HandleStateChange // // Handles a state change event from our C Callback for "state-change" or -// the async queue in 0.10. (Mostly this is here to avoid locking the +// the async queue . (Mostly this is here to avoid locking the // the mutex twice...) //----------------------------------------------------------------------------- -void wxGStreamerMediaBackend::HandleStateChange(GstElementState oldstate, - GstElementState newstate) +void wxGStreamerMediaBackend::HandleStateChange(GstState oldstate, + GstState newstate) { switch(newstate) { @@ -604,83 +481,13 @@ void wxGStreamerMediaBackend::HandleStat } //----------------------------------------------------------------------------- -// wxGStreamerMediaBackend::QueryVideoSizeFromElement -// -// Run through the stuff in "stream-info" of element for a valid -// video pad, and then attempt to query the video size from it - if not -// set up an event to do so when ready. Return true -// if we got a valid video pad. -//----------------------------------------------------------------------------- -bool wxGStreamerMediaBackend::QueryVideoSizeFromElement(GstElement* element) -{ - const GList *list = NULL; - g_object_get (G_OBJECT (element), "stream-info", &list, NULL); - - for ( ; list != NULL; list = list->next) - { - GObject *info = (GObject *) list->data; - gint type; - GParamSpec *pspec; - GEnumValue *val; - GstPad *pad = NULL; - - g_object_get (info, "type", &type, NULL); - pspec = g_object_class_find_property ( - G_OBJECT_GET_CLASS (info), "type"); - val = g_enum_get_value (G_PARAM_SPEC_ENUM (pspec)->enum_class, type); - - if (!strncasecmp(val->value_name, "video", 5) || - !strncmp(val->value_name, "GST_STREAM_TYPE_VIDEO", 21)) - { - // Newer gstreamer 0.8+ plugins are SUPPOSED to have "object"... - // but a lot of old plugins still use "pad" :) - pspec = g_object_class_find_property ( - G_OBJECT_GET_CLASS (info), "object"); - - if (!pspec) - g_object_get (info, "pad", &pad, NULL); - else - g_object_get (info, "object", &pad, NULL); - -#if GST_VERSION_MAJOR == 0 && GST_VERSION_MINOR <= 8 - // Killed in 0.9, presumely because events and such - // should be pushed on pads regardless of whether they - // are currently linked - pad = (GstPad *) GST_PAD_REALIZE (pad); - wxASSERT(pad); -#endif - - if(!QueryVideoSizeFromPad(pad)) - { - // wait for those caps to get ready - g_signal_connect( - pad, - "notify::caps", - G_CALLBACK(gst_notify_caps_callback), - this); - } - break; - }// end if video - }// end searching through info list - - // no video (or extremely delayed stream-info) - if(list == NULL) - { - m_videoSize = wxSize(0,0); - return false; - } - - return true; -} - -//----------------------------------------------------------------------------- // wxGStreamerMediaBackend::QueryVideoSizeFromPad // // Gets the size of our video (in wxSize) from a GstPad //----------------------------------------------------------------------------- bool wxGStreamerMediaBackend::QueryVideoSizeFromPad(GstPad* pad) { - const GstCaps* caps = GST_PAD_CAPS(pad); + GstCaps* caps = gst_pad_get_current_caps(pad); if ( caps ) { const GstStructure *s = gst_caps_get_structure (caps, 0); @@ -706,23 +513,26 @@ bool wxGStreamerMediaBackend::QueryVideo m_videoSize.y = (int) ((float) den * m_videoSize.y / num); } - wxLogTrace(wxTRACE_GStreamer, wxT("Adjusted video size: [%i,%i]"), - m_videoSize.x, m_videoSize.y); + wxLogTrace(wxTRACE_GStreamer, wxT("Adjusted video size: [%i,%i]"), + m_videoSize.x, m_videoSize.y); + + gst_caps_unref (caps); return true; } // end if caps + m_videoSize = wxSize(0,0); return false; // not ready/massive failure } //----------------------------------------------------------------------------- -// wxGStreamerMediaBackend::SetupXOverlay +// wxGStreamerMediaBackend::SetupVideoOverlay // -// Attempts to set the XWindow id of our GstXOverlay to tell it which +// Attempts to set the XWindow id of our GstVideoOverlay to tell it which // window to play video in. //----------------------------------------------------------------------------- -void wxGStreamerMediaBackend::SetupXOverlay() +void wxGStreamerMediaBackend::SetupVideoOverlay() { - // Use the xoverlay extension to tell gstreamer to play in our window + // Use the videooverlay extension to tell gstreamer to play in our window #ifdef __WXGTK__ if (!gtk_widget_get_realized(m_ctrl->m_wxwindow)) { @@ -739,7 +549,7 @@ void wxGStreamerMediaBackend::SetupXOver GdkWindow* window = gtk_widget_get_window(m_ctrl->m_wxwindow); wxASSERT(window); #endif - gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(m_xoverlay), + gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(m_videooverlay), #ifdef __WXGTK__ GDK_WINDOW_XID(window) #else @@ -769,9 +579,8 @@ void wxGStreamerMediaBackend::SetupXOver // // PRECONDITION: Assumes m_asynclock is Lock()ed //----------------------------------------------------------------------------- -#if GST_VERSION_MAJOR > 0 || GST_VERSION_MINOR >= 10 bool wxGStreamerMediaBackend::SyncStateChange(GstElement* element, - GstElementState desiredstate, + GstState desiredstate, gint64 llTimeout) { GstBus* bus = gst_element_get_bus(element); @@ -844,23 +653,6 @@ bool wxGStreamerMediaBackend::SyncStateC return bSuccess; } -#else // 0.8 implementation -bool wxGStreamerMediaBackend::SyncStateChange(GstElement* element, - GstElementState desiredstate, - gint64 llTimeout) -{ - gint64 llTimeWaited = 0; - while(GST_STATE(element) != desiredstate) - { - if(llTimeWaited >= llTimeout) - break; - llTimeWaited += 10*GST_MSECOND; - wxMilliSleep(10); - } - - return llTimeWaited != llTimeout; -} -#endif //----------------------------------------------------------------------------- // wxGStreamerMediaBackend::TryAudioSink @@ -884,25 +676,25 @@ bool wxGStreamerMediaBackend::TryAudioSi bool wxGStreamerMediaBackend::TryVideoSink(GstElement* videosink) { - // Check if the video sink either is an xoverlay or might contain one... - if( !GST_IS_BIN(videosink) && !GST_IS_X_OVERLAY(videosink) ) + // Check if the video sink either is an videooverlay or might contain one... + if( !GST_IS_BIN(videosink) && !GST_IS_VIDEO_OVERLAY(videosink) ) { if(G_IS_OBJECT(videosink)) g_object_unref(videosink); return false; } - // Make our video sink and make sure it supports the x overlay interface - // the x overlay enables us to put the video in our control window + // Make our video sink and make sure it supports the video overlay interface + // the video overlay enables us to put the video in our control window // (i.e. we NEED it!) - also connect to the natural video size change event if( GST_IS_BIN(videosink) ) - m_xoverlay = (GstXOverlay*) + m_videooverlay = (GstVideoOverlay*) gst_bin_get_by_interface (GST_BIN (videosink), - GST_TYPE_X_OVERLAY); + GST_TYPE_VIDEO_OVERLAY); else - m_xoverlay = (GstXOverlay*) videosink; + m_videooverlay = (GstVideoOverlay*) videosink; - if ( !GST_IS_X_OVERLAY(m_xoverlay) ) + if ( !GST_IS_VIDEO_OVERLAY(m_videooverlay) ) { g_object_unref(videosink); return false; @@ -1046,11 +838,7 @@ bool wxGStreamerMediaBackend::CreateCont //Really init gstreamer gboolean bInited; GError* error = NULL; -#if GST_VERSION_MAJOR > 0 || GST_VERSION_MINOR >= 10 bInited = gst_init_check(&argcGST, &argvGST, &error); -#else - bInited = gst_init_check(&argcGST, &argvGST); -#endif // Cleanup arguments for unicode case #if wxUSE_UNICODE @@ -1117,78 +905,52 @@ bool wxGStreamerMediaBackend::CreateCont return false; } -#if GST_VERSION_MAJOR == 0 && GST_VERSION_MINOR < 10 - // Connect the glib events/callbacks we want to our playbin - g_signal_connect(m_playbin, "eos", - G_CALLBACK(gst_finish_callback), this); - g_signal_connect(m_playbin, "error", - G_CALLBACK(gst_error_callback), this); - g_signal_connect(m_playbin, "state-change", - G_CALLBACK(gst_state_change_callback), this); -#else - // GStreamer 0.10+ uses GstBus for this now, connect to the sync - // handler as well so we can set the X window id of our xoverlay + // GStreamer uses GstBus for this now, connect to the sync + // handler as well so we can set the video window id of our videooverlay gst_bus_add_watch (gst_element_get_bus(m_playbin), (GstBusFunc) gst_bus_async_callback, this); gst_bus_set_sync_handler(gst_element_get_bus(m_playbin), - (GstBusSyncHandler) gst_bus_sync_callback, this); - g_signal_connect(m_playbin, "notify::stream-info", - G_CALLBACK(gst_notify_stream_info_callback), this); -#endif + (GstBusSyncHandler) gst_bus_sync_callback, this, NULL); // Get the audio sink - GstElement* audiosink = gst_gconf_get_default_audio_sink(); + // Use autodetection, then alsa, then oss as a stopgap + GstElement* audiosink = gst_element_factory_make ("autoaudiosink", "audio-sink"); if( !TryAudioSink(audiosink) ) { - // fallback to autodetection, then alsa, then oss as a stopgap - audiosink = gst_element_factory_make ("autoaudiosink", "audio-sink"); + audiosink = gst_element_factory_make ("alsasink", "alsa-output"); if( !TryAudioSink(audiosink) ) { - audiosink = gst_element_factory_make ("alsasink", "alsa-output"); + audiosink = gst_element_factory_make ("osssink", "play_audio"); if( !TryAudioSink(audiosink) ) { - audiosink = gst_element_factory_make ("osssink", "play_audio"); - if( !TryAudioSink(audiosink) ) - { - wxLogSysError(wxT("Could not find a valid audiosink")); - return false; - } + wxLogSysError(wxT("Could not find a valid audiosink")); + return false; } } } // Setup video sink - first try gconf, then auto, then xvimage and // then finally plain ximage - GstElement* videosink = gst_gconf_get_default_video_sink(); + GstElement* videosink = gst_element_factory_make ("autovideosink", "video-sink"); if( !TryVideoSink(videosink) ) { - videosink = gst_element_factory_make ("autovideosink", "video-sink"); + videosink = gst_element_factory_make ("xvimagesink", "video-sink"); if( !TryVideoSink(videosink) ) { - videosink = gst_element_factory_make ("xvimagesink", "video-sink"); + // finally, do a final fallback to ximagesink + videosink = + gst_element_factory_make ("ximagesink", "video-sink"); if( !TryVideoSink(videosink) ) { - // finally, do a final fallback to ximagesink - videosink = - gst_element_factory_make ("ximagesink", "video-sink"); - if( !TryVideoSink(videosink) ) - { - g_object_unref(audiosink); - wxLogSysError(wxT("Could not find a suitable video sink")); - return false; - } + g_object_unref(audiosink); + wxLogSysError(wxT("Could not find a suitable video sink")); + return false; } } } -#if GST_VERSION_MAJOR == 0 && GST_VERSION_MINOR < 10 - // Not on 0.10... called when video size changes - g_signal_connect(m_xoverlay, "desired-size-changed", - G_CALLBACK(gst_desired_size_changed_callback), this); -#endif - // Tell GStreamer which window to draw to in 0.8 - 0.10 - // sometimes needs this too... - SetupXOverlay(); + // Tell GStreamer which window to draw to + SetupVideoOverlay(); // Now that we know (or, rather think) our video and audio sink // are valid set our playbin to use them @@ -1197,6 +959,10 @@ bool wxGStreamerMediaBackend::CreateCont "audio-sink", audiosink, NULL); + GstPad *video_sinkpad = gst_element_get_static_pad (videosink, "sink"); + g_signal_connect (video_sinkpad, "notify::caps", G_CALLBACK (gst_notify_caps_callback), this); + gst_object_unref (video_sinkpad); + m_eventHandler = new wxGStreamerMediaEventHandler(this); return true; } @@ -1213,26 +979,10 @@ bool wxGStreamerMediaBackend::Load(const //----------------------------------------------------------------------------- // wxGStreamerMediaBackend::Load (URI version) -// -// In the case of a file URI passes it unencoded - -// also, as of 0.10.3 and earlier GstURI (the uri parser for gstreamer) -// is sort of broken and only accepts uris with at least two slashes -// after the scheme (i.e. file: == not ok, file:// == ok) //----------------------------------------------------------------------------- bool wxGStreamerMediaBackend::Load(const wxURI& location) { - if(location.GetScheme().CmpNoCase(wxT("file")) == 0) - { - wxString uristring = location.BuildUnescapedURI(); - - //Workaround GstURI leading "//" problem and make sure it leads - //with that - return DoLoad(wxString(wxT("file://")) + - uristring.Right(uristring.length() - 5) - ); - } - else - return DoLoad(location.BuildURI()); + return DoLoad(location.BuildURI()); } //----------------------------------------------------------------------------- @@ -1258,7 +1008,7 @@ bool wxGStreamerMediaBackend::DoLoad(con // Set playbin to ready to stop the current media... if( gst_element_set_state (m_playbin, - GST_STATE_READY) == GST_STATE_FAILURE || + GST_STATE_READY) == GST_STATE_CHANGE_FAILURE || !SyncStateChange(m_playbin, GST_STATE_READY)) { CheckForErrors(); @@ -1281,7 +1031,7 @@ bool wxGStreamerMediaBackend::DoLoad(con // Try to pause media as gstreamer won't let us query attributes // such as video size unless it is paused or playing if( gst_element_set_state (m_playbin, - GST_STATE_PAUSED) == GST_STATE_FAILURE || + GST_STATE_PAUSED) == GST_STATE_CHANGE_FAILURE || !SyncStateChange(m_playbin, GST_STATE_PAUSED)) { CheckForErrors(); @@ -1307,12 +1057,11 @@ bool wxGStreamerMediaBackend::DoLoad(con // // Sets the stream to a playing state // -// THREAD-UNSAFE in 0.8, maybe in 0.10 as well //----------------------------------------------------------------------------- bool wxGStreamerMediaBackend::Play() { if (gst_element_set_state (m_playbin, - GST_STATE_PLAYING) == GST_STATE_FAILURE) + GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) { CheckForErrors(); return false; @@ -1326,13 +1075,12 @@ bool wxGStreamerMediaBackend::Play() // // Marks where we paused and pauses the stream // -// THREAD-UNSAFE in 0.8, maybe in 0.10 as well //----------------------------------------------------------------------------- bool wxGStreamerMediaBackend::Pause() { m_llPausedPos = wxGStreamerMediaBackend::GetPosition(); if (gst_element_set_state (m_playbin, - GST_STATE_PAUSED) == GST_STATE_FAILURE) + GST_STATE_PAUSED) == GST_STATE_CHANGE_FAILURE) { CheckForErrors(); return false; @@ -1353,7 +1101,7 @@ bool wxGStreamerMediaBackend::Stop() { // begin state lock wxMutexLocker lock(m_asynclock); if(gst_element_set_state (m_playbin, - GST_STATE_PAUSED) == GST_STATE_FAILURE || + GST_STATE_PAUSED) == GST_STATE_CHANGE_FAILURE || !SyncStateChange(m_playbin, GST_STATE_PAUSED)) { CheckForErrors(); @@ -1417,10 +1165,8 @@ wxLongLong wxGStreamerMediaBackend::GetP else { gint64 pos; - GstFormat fmtTime = GST_FORMAT_TIME; - if (!wxGst_element_query_position(m_playbin, &fmtTime, &pos) || - fmtTime != GST_FORMAT_TIME || pos == -1) + if (!gst_element_query_position(m_playbin, GST_FORMAT_TIME, &pos) || pos == -1) return 0; return pos / GST_MSECOND ; } @@ -1438,44 +1184,21 @@ wxLongLong wxGStreamerMediaBackend::GetP // This is also an exceedingly ugly function due to the three implementations // (or, rather two plus one implementation without a seek function). // -// This is asynchronous and thread-safe on both 0.8 and 0.10. -// // NB: This fires both a stop and play event if the media was previously // playing... which in some ways makes sense. And yes, this makes the video // go all haywire at times - a gstreamer bug... //----------------------------------------------------------------------------- bool wxGStreamerMediaBackend::SetPosition(wxLongLong where) { -#if GST_VERSION_MAJOR == 0 && GST_VERSION_MINOR == 8 \ - && GST_VERSION_MICRO == 0 - // 0.8.0 has no gst_element_seek according to official docs!!! - wxLogSysError(wxT("GStreamer 0.8.0 does not have gst_element_seek") - wxT(" according to official docs")); - return false; -#else // != 0.8.0 - -# if GST_VERSION_MAJOR > 0 || GST_VERSION_MINOR >= 10 - gst_element_seek (m_playbin, m_dRate, GST_FORMAT_TIME, + if ( gst_element_seek (m_playbin, m_dRate, GST_FORMAT_TIME, (GstSeekFlags)(GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT), GST_SEEK_TYPE_SET, where.GetValue() * GST_MSECOND, - GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE ); -# else - // NB: Some gstreamer versions return false basically all the time - // here - even totem doesn't bother to check the return value here - // so I guess we'll just assume it worked - - // TODO: maybe check the gst error callback??? - gst_element_seek (m_playbin, (GstSeekType) (GST_SEEK_METHOD_SET | - GST_FORMAT_TIME | GST_SEEK_FLAG_FLUSH), - where.GetValue() * GST_MSECOND ); - -# endif // GST_VERSION_MAJOR > 0 || GST_VERSION_MINOR >= 10 - + GST_SEEK_TYPE_NONE, GST_CLOCK_TIME_NONE ) ) { m_llPausedPos = where; return true; } - return true; -#endif //== 0.8.0 + return false; } //----------------------------------------------------------------------------- @@ -1487,10 +1210,8 @@ bool wxGStreamerMediaBackend::SetPositio wxLongLong wxGStreamerMediaBackend::GetDuration() { gint64 length; - GstFormat fmtTime = GST_FORMAT_TIME; - if(!wxGst_element_query_duration(m_playbin, &fmtTime, &length) || - fmtTime != GST_FORMAT_TIME || length == -1) + if(!gst_element_query_duration(m_playbin, GST_FORMAT_TIME, &length) || length == -1) return 0; return length / GST_MSECOND ; } @@ -1512,7 +1233,7 @@ void wxGStreamerMediaBackend::Move(int W // wxGStreamerMediaBackend::GetVideoSize // // Returns our cached video size from Load/gst_notify_caps_callback -// gst_x_overlay_get_desired_size also does this in 0.8... +// gst_video_overlay_get_desired_size also does this in 0.8... //----------------------------------------------------------------------------- wxSize wxGStreamerMediaBackend::GetVideoSize() const { @@ -1539,9 +1260,8 @@ wxSize wxGStreamerMediaBackend::GetVideo //TODO: forcing frame/samplerates, see audioscale and videorate. Audioscale is //TODO: part of playbin. // -// In 0.10 GStreamer has new gst_element_seek API that might -// support this - and I've got an attempt to do so but it is untested -// but it would appear to work... +// In has new gst_element_seek API that supports this - and I've got an attempt +// to do so but it is untested but it would appear to work... //----------------------------------------------------------------------------- double wxGStreamerMediaBackend::GetPlaybackRate() { @@ -1552,7 +1272,6 @@ double wxGStreamerMediaBackend::GetPlayb bool wxGStreamerMediaBackend::SetPlaybackRate(double dRate) { -#if GST_VERSION_MAJOR > 0 || GST_VERSION_MINOR >= 10 #if 0 // not tested enough if( gst_element_seek (m_playbin, dRate, GST_FORMAT_TIME, (GstSeekFlags)(GST_SEEK_FLAG_FLUSH | GST_SEEK_FLAG_KEY_UNIT), @@ -1565,7 +1284,6 @@ bool wxGStreamerMediaBackend::SetPlaybac #else wxUnusedVar(dRate); #endif -#endif // failure return false; @@ -1593,10 +1311,8 @@ wxLongLong wxGStreamerMediaBackend::GetD wxLongLong wxGStreamerMediaBackend::GetDownloadTotal() { gint64 length; - GstFormat fmtBytes = GST_FORMAT_BYTES; - if (!wxGst_element_query_duration(m_playbin, &fmtBytes, &length) || - fmtBytes != GST_FORMAT_BYTES || length == -1) + if (!gst_element_query_duration(m_playbin, GST_FORMAT_BYTES, &length) || length == -1) return 0; return length; }