From 501b377435f628a6bd5924582a24a63a9c3fbc78 Mon Sep 17 00:00:00 2001 From: Scott Talbert Date: Sun, 22 Jan 2017 15:56:50 -0500 Subject: [PATCH] Add support for GStreamer 1.x in Unix wxMediaCtrl implementation Do it while keeping both 0.8 and 0.10 support, unlike the commit d0ef5d7, which this is based on, that removed support for 0.8. Closes https://github.com/wxWidgets/wxWidgets/pull/400 --- configure | 114 ++++++++++++++++++++++++++++++++----- configure.in | 34 ++++++++--- src/unix/mediactrl.cpp | 124 +++++++++++++++++++++++++++++++++++++---- 3 files changed, 239 insertions(+), 33 deletions(-) diff --git a/configure b/configure index 5bf98b9613..47d59e8f6f 100755 --- a/configure +++ b/configure @@ -37321,8 +37321,8 @@ if test "$wxUSE_MEDIACTRL" = "yes" -o "$wxUSE_MEDIACTRL" = "auto"; then if test "$wxUSE_GTK" = 1; then wxUSE_GSTREAMER="no" - 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 @@ -37331,6 +37331,93 @@ pkg_failed=no { $as_echo "$as_me:${as_lineno-$LINENO}: checking for GST" >&5 $as_echo_n "checking for GST... " >&6; } +if test -n "$PKG_CONFIG"; then + if test -n "$GST_CFLAGS"; then + pkg_cv_GST_CFLAGS="$GST_CFLAGS" + else + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gstreamer-\$GST_VERSION gstreamer-video-\$GST_VERSION\""; } >&5 + ($PKG_CONFIG --exists --print-errors "gstreamer-$GST_VERSION gstreamer-video-$GST_VERSION") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_GST_CFLAGS=`$PKG_CONFIG --cflags "gstreamer-$GST_VERSION gstreamer-video-$GST_VERSION" 2>/dev/null` +else + pkg_failed=yes +fi + fi +else + pkg_failed=untried +fi +if test -n "$PKG_CONFIG"; then + if test -n "$GST_LIBS"; then + pkg_cv_GST_LIBS="$GST_LIBS" + else + if test -n "$PKG_CONFIG" && \ + { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"gstreamer-\$GST_VERSION gstreamer-video-\$GST_VERSION\""; } >&5 + ($PKG_CONFIG --exists --print-errors "gstreamer-$GST_VERSION gstreamer-video-$GST_VERSION") 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; then + pkg_cv_GST_LIBS=`$PKG_CONFIG --libs "gstreamer-$GST_VERSION gstreamer-video-$GST_VERSION" 2>/dev/null` +else + pkg_failed=yes +fi + fi +else + pkg_failed=untried +fi + + + +if test $pkg_failed = yes; then + +if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then + _pkg_short_errors_supported=yes +else + _pkg_short_errors_supported=no +fi + if test $_pkg_short_errors_supported = yes; then + GST_PKG_ERRORS=`$PKG_CONFIG --short-errors --errors-to-stdout --print-errors "gstreamer-$GST_VERSION gstreamer-video-$GST_VERSION"` + else + GST_PKG_ERRORS=`$PKG_CONFIG --errors-to-stdout --print-errors "gstreamer-$GST_VERSION gstreamer-video-$GST_VERSION"` + fi + # Put the nasty error message in config.log where it belongs + echo "$GST_PKG_ERRORS" >&5 + + + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: GStreamer 1.0 not available, falling back to 0.10" >&5 +$as_echo "$as_me: WARNING: GStreamer 1.0 not available, falling back to 0.10" >&2;} + GST_VERSION_MAJOR=0 + GST_VERSION_MINOR=10 + GST_VERSION=$GST_VERSION_MAJOR.$GST_VERSION_MINOR + + +elif test $pkg_failed = untried; then + + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: GStreamer 1.0 not available, falling back to 0.10" >&5 +$as_echo "$as_me: WARNING: GStreamer 1.0 not available, falling back to 0.10" >&2;} + GST_VERSION_MAJOR=0 + GST_VERSION_MINOR=10 + GST_VERSION=$GST_VERSION_MAJOR.$GST_VERSION_MINOR + + +else + GST_CFLAGS=$pkg_cv_GST_CFLAGS + GST_LIBS=$pkg_cv_GST_LIBS + { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 +$as_echo "yes" >&6; } + + wxUSE_GSTREAMER="yes" + +fi + + if test $GST_VERSION_MINOR = "10"; then + +pkg_failed=no +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GST" >&5 +$as_echo_n "checking for GST... " >&6; } + if test -n "$PKG_CONFIG"; then if test -n "$GST_CFLAGS"; then pkg_cv_GST_CFLAGS="$GST_CFLAGS" @@ -37386,16 +37473,14 @@ fi echo "$GST_PKG_ERRORS" >&5 - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: GStreamer 0.10 not available, falling back to 0.8" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: GStreamer 0.10 not available, falling back to 0.8" >&5 $as_echo "$as_me: WARNING: GStreamer 0.10 not available, falling back to 0.8" >&2;} - GST_VERSION_MINOR=8 elif test $pkg_failed = untried; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: GStreamer 0.10 not available, falling back to 0.8" >&5 + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: GStreamer 0.10 not available, falling back to 0.8" >&5 $as_echo "$as_me: WARNING: GStreamer 0.10 not available, falling back to 0.8" >&2;} - GST_VERSION_MINOR=8 else @@ -37404,12 +37489,15 @@ else { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5 $as_echo "yes" >&6; } - wxUSE_GSTREAMER="yes" - GST_LIBS="$GST_LIBS -lgstinterfaces-$GST_VERSION" + wxUSE_GSTREAMER="yes" + GST_LIBS="$GST_LIBS -lgstinterfaces-$GST_VERSION" fi + fi + else - GST_VERSION_MINOR=8 + GST_VERSION_MAJOR=0 + GST_VERSION_MINOR=8 fi if test $GST_VERSION_MINOR = "8"; then @@ -37474,13 +37562,13 @@ fi echo "$GST_PKG_ERRORS" >&5 - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: GStreamer 0.8/0.10 not available." >&5 -$as_echo "$as_me: WARNING: GStreamer 0.8/0.10 not available." >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: GStreamer 0.8/0.10/1.0 not available." >&5 +$as_echo "$as_me: WARNING: GStreamer 0.8/0.10/1.0 not available." >&2;} elif test $pkg_failed = untried; then - { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: GStreamer 0.8/0.10 not available." >&5 -$as_echo "$as_me: WARNING: GStreamer 0.8/0.10 not available." >&2;} + { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: GStreamer 0.8/0.10/1.0 not available." >&5 +$as_echo "$as_me: WARNING: GStreamer 0.8/0.10/1.0 not available." >&2;} else GST_CFLAGS=$pkg_cv_GST_CFLAGS diff --git a/configure.in b/configure.in index f1b79e1397..97db3a7a4f 100644 --- a/configure.in +++ b/configure.in @@ -7548,27 +7548,43 @@ if test "$wxUSE_MEDIACTRL" = "yes" -o "$wxUSE_MEDIACTRL" = "auto"; then 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 So, we first check to see if 1.0 if available - if not we + dnl try the older 0.10 and 0.8 versions 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], + [gstreamer-$GST_VERSION gstreamer-video-$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 + AC_MSG_WARN([GStreamer 1.0 not available, falling back to 0.10]) + GST_VERSION_MAJOR=0 + GST_VERSION_MINOR=10 + GST_VERSION=$GST_VERSION_MAJOR.$GST_VERSION_MINOR ] ) + + if test $GST_VERSION_MINOR = "10"; 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]) + ] + ) + fi + else dnl check only for 0.8 + GST_VERSION_MAJOR=0 GST_VERSION_MINOR=8 fi @@ -7578,7 +7594,7 @@ if test "$wxUSE_MEDIACTRL" = "yes" -o "$wxUSE_MEDIACTRL" = "auto"; then [gstreamer-$GST_VERSION gstreamer-interfaces-$GST_VERSION gstreamer-gconf-$GST_VERSION], wxUSE_GSTREAMER="yes", [ - AC_MSG_WARN([GStreamer 0.8/0.10 not available.]) + AC_MSG_WARN([GStreamer 0.8/0.10/1.0 not available.]) ]) fi diff --git a/src/unix/mediactrl.cpp b/src/unix/mediactrl.cpp index 4683ea1e8e..edc8f943f4 100644 --- a/src/unix/mediactrl.cpp +++ b/src/unix/mediactrl.cpp @@ -20,7 +20,9 @@ #include // main gstreamer header // xoverlay/video stuff, gst-gconf for 0.8 -#if GST_VERSION_MAJOR > 0 || GST_VERSION_MINOR >= 10 +#if GST_VERSION_MAJOR > 0 +# include +#elif GST_VERSION_MINOR >= 10 # include #else # include @@ -48,8 +50,8 @@ //----------------------------------------------------------------------------- /* - 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 0.8, 0.10, or + 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 @@ -203,7 +205,11 @@ public: double m_dRate; // Current playback rate - // see GetPlaybackRate for notes wxLongLong m_llPausedPos; // Paused position - see Pause() +#if GST_VERSION_MAJOR > 0 + GstVideoOverlay* m_xoverlay; // X Overlay that contains the GST video +#else GstXOverlay* m_xoverlay; // X Overlay that contains the GST video +#endif wxMutex m_asynclock; // See "discussion of internals" class wxGStreamerMediaEventHandler* m_eventHandler; // see below @@ -294,7 +300,11 @@ expose_event(GtkWidget* widget, GdkEventExpose* event, wxGStreamerMediaBackend* // 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... +#if GST_VERSION_MAJOR > 0 + gst_video_overlay_expose(be->m_xoverlay); +#else gst_x_overlay_expose(be->m_xoverlay); +#endif } else { @@ -334,9 +344,15 @@ static gint gtk_window_realize_callback(GtkWidget* widget, GdkWindow* window = gtk_widget_get_window(widget); wxASSERT(window); +#if GST_VERSION_MAJOR > 0 + gst_video_overlay_set_window_handle(be->m_xoverlay, + GDK_WINDOW_XID(window) + ); +#else gst_x_overlay_set_xwindow_id( GST_X_OVERLAY(be->m_xoverlay), GDK_WINDOW_XID(window) ); +#endif GtkWidget* w = be->GetControl()->m_wxwindow; #ifdef __WXGTK3__ g_signal_connect(w, "draw", G_CALLBACK(draw), be); @@ -436,7 +452,7 @@ static void gst_notify_caps_callback(GstPad* pad, // // (Undocumented?) //----------------------------------------------------------------------------- -#if GST_VERSION_MAJOR > 0 || GST_VERSION_MINOR >= 10 +#if GST_VERSION_MAJOR == 0 && GST_VERSION_MINOR >= 10 extern "C" { static void gst_notify_stream_info_callback(GstElement* WXUNUSED(element), GParamSpec* WXUNUSED(pspec), @@ -537,8 +553,12 @@ static GstBusSyncReply gst_bus_sync_callback(GstBus* bus, { // Pass a non-xwindowid-setting event on to the async handler where it // belongs +#if GST_VERSION_MAJOR > 0 + if (!gst_is_video_overlay_prepare_window_handle_message (message)) +#else if (GST_MESSAGE_TYPE (message) != GST_MESSAGE_ELEMENT || !gst_structure_has_name (message->structure, "prepare-xwindow-id")) +#endif { // // NB: Unfortunately, the async callback can be quite @@ -603,6 +623,7 @@ void wxGStreamerMediaBackend::HandleStateChange(GstElementState oldstate, } } +#if GST_VERSION_MAJOR == 0 //----------------------------------------------------------------------------- // wxGStreamerMediaBackend::QueryVideoSizeFromElement // @@ -672,6 +693,7 @@ bool wxGStreamerMediaBackend::QueryVideoSizeFromElement(GstElement* element) return true; } +#endif //----------------------------------------------------------------------------- // wxGStreamerMediaBackend::QueryVideoSizeFromPad @@ -680,7 +702,11 @@ bool wxGStreamerMediaBackend::QueryVideoSizeFromElement(GstElement* element) //----------------------------------------------------------------------------- bool wxGStreamerMediaBackend::QueryVideoSizeFromPad(GstPad* pad) { +#if GST_VERSION_MAJOR > 0 + GstCaps* caps = gst_pad_get_current_caps(pad); +#else const GstCaps* caps = GST_PAD_CAPS(pad); +#endif if ( caps ) { const GstStructure *s = gst_caps_get_structure (caps, 0); @@ -706,11 +732,15 @@ bool wxGStreamerMediaBackend::QueryVideoSizeFromPad(GstPad* pad) 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); +#if GST_VERSION_MAJOR > 0 + gst_caps_unref (caps); +#endif return true; } // end if caps + m_videoSize = wxSize(0,0); return false; // not ready/massive failure } @@ -739,7 +769,11 @@ void wxGStreamerMediaBackend::SetupXOverlay() GdkWindow* window = gtk_widget_get_window(m_ctrl->m_wxwindow); wxASSERT(window); #endif +#if GST_VERSION_MAJOR > 0 + gst_video_overlay_set_window_handle(m_xoverlay, +#else gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(m_xoverlay), +#endif #ifdef __WXGTK__ GDK_WINDOW_XID(window) #else @@ -884,6 +918,31 @@ bool wxGStreamerMediaBackend::TryAudioSink(GstElement* audiosink) bool wxGStreamerMediaBackend::TryVideoSink(GstElement* videosink) { +#if GST_VERSION_MAJOR > 0 + // Check if the video sink either is an xoverlay 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 + // (i.e. we NEED it!) - also connect to the natural video size change event + if( GST_IS_BIN(videosink) ) + m_xoverlay = (GstVideoOverlay*) + gst_bin_get_by_interface (GST_BIN (videosink), + GST_TYPE_VIDEO_OVERLAY); + else + m_xoverlay = (GstVideoOverlay*) videosink; + + if ( !GST_IS_VIDEO_OVERLAY(m_xoverlay) ) + { + g_object_unref(videosink); + return false; + } +#else // Check if the video sink either is an xoverlay or might contain one... if( !GST_IS_BIN(videosink) && !GST_IS_X_OVERLAY(videosink) ) { @@ -907,7 +966,7 @@ bool wxGStreamerMediaBackend::TryVideoSink(GstElement* videosink) g_object_unref(videosink); return false; } - +#endif return true; } @@ -1130,16 +1189,22 @@ bool wxGStreamerMediaBackend::CreateControl(wxControl* ctrl, wxWindow* parent, // handler as well so we can set the X window id of our xoverlay gst_bus_add_watch (gst_element_get_bus(m_playbin), (GstBusFunc) gst_bus_async_callback, this); +#endif +#if GST_VERSION_MAJOR > 0 + gst_bus_set_sync_handler(gst_element_get_bus(m_playbin), + (GstBusSyncHandler) gst_bus_sync_callback, this, NULL); +#else 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 // Get the audio sink - GstElement* audiosink = gst_gconf_get_default_audio_sink(); + GstElement* audiosink; +#if GST_VERSION_MAJOR == 0 + audiosink = gst_gconf_get_default_audio_sink(); if( !TryAudioSink(audiosink) ) { +#endif // fallback to autodetection, then alsa, then oss as a stopgap audiosink = gst_element_factory_make ("autoaudiosink", "audio-sink"); if( !TryAudioSink(audiosink) ) @@ -1155,13 +1220,18 @@ bool wxGStreamerMediaBackend::CreateControl(wxControl* ctrl, wxWindow* parent, } } } +#if GST_VERSION_MAJOR == 0 } +#endif // 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; +#if GST_VERSION_MAJOR == 0 + videosink = gst_gconf_get_default_video_sink(); if( !TryVideoSink(videosink) ) { +#endif videosink = gst_element_factory_make ("autovideosink", "video-sink"); if( !TryVideoSink(videosink) ) { @@ -1179,13 +1249,25 @@ bool wxGStreamerMediaBackend::CreateControl(wxControl* ctrl, wxWindow* parent, } } } +#if GST_VERSION_MAJOR == 0 } +#endif #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 + +#if GST_VERSION_MAJOR > 0 + 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); +#else + g_signal_connect(m_playbin, "notify::stream-info", + G_CALLBACK(gst_notify_stream_info_callback), this); +#endif + // Tell GStreamer which window to draw to in 0.8 - 0.10 // sometimes needs this too... SetupXOverlay(); @@ -1221,6 +1303,7 @@ bool wxGStreamerMediaBackend::Load(const wxString& fileName) //----------------------------------------------------------------------------- bool wxGStreamerMediaBackend::Load(const wxURI& location) { +#if GST_VERSION_MAJOR == 0 if(location.GetScheme().CmpNoCase(wxT("file")) == 0) { wxString uristring = location.BuildUnescapedURI(); @@ -1232,6 +1315,7 @@ bool wxGStreamerMediaBackend::Load(const wxURI& location) ); } else +#endif return DoLoad(location.BuildURI()); } @@ -1417,11 +1501,17 @@ wxLongLong wxGStreamerMediaBackend::GetPosition() else { gint64 pos; +#if GST_VERSION_MAJOR > 0 + if (!gst_element_query_position(m_playbin, GST_FORMAT_TIME, &pos) || + pos == -1) + return 0; +#else GstFormat fmtTime = GST_FORMAT_TIME; if (!wxGst_element_query_position(m_playbin, &fmtTime, &pos) || fmtTime != GST_FORMAT_TIME || pos == -1) return 0; +#endif return pos / GST_MSECOND ; } } @@ -1487,11 +1577,17 @@ bool wxGStreamerMediaBackend::SetPosition(wxLongLong where) wxLongLong wxGStreamerMediaBackend::GetDuration() { gint64 length; +#if GST_VERSION_MAJOR > 0 + if(!gst_element_query_duration(m_playbin, GST_FORMAT_TIME, &length) || + length == -1) + return 0; +#else GstFormat fmtTime = GST_FORMAT_TIME; if(!wxGst_element_query_duration(m_playbin, &fmtTime, &length) || fmtTime != GST_FORMAT_TIME || length == -1) return 0; +#endif return length / GST_MSECOND ; } @@ -1593,11 +1689,17 @@ wxLongLong wxGStreamerMediaBackend::GetDownloadProgress() wxLongLong wxGStreamerMediaBackend::GetDownloadTotal() { gint64 length; +#if GST_VERSION_MAJOR > 0 + if (!gst_element_query_duration(m_playbin, GST_FORMAT_BYTES, &length) || + length == -1) + return 0; +#else GstFormat fmtBytes = GST_FORMAT_BYTES; if (!wxGst_element_query_duration(m_playbin, &fmtBytes, &length) || fmtBytes != GST_FORMAT_BYTES || length == -1) return 0; +#endif return length; }