From 6a570205a17663e6adce9e5613eb7694fe2874dc Mon Sep 17 00:00:00 2001 From: Yoann Lopes Date: Thu, 31 Oct 2013 15:06:30 +0100 Subject: [PATCH] Initial porting effort to GStreamer 1.0. Imported from git@github.com:jhodapp/qtmultimedia.git Contributions from: Ilya Smelykh Jim Hodapp Sergio Schvezov Change-Id: I10fa5e5078efa4564ce833befd417008e26a90a9 Reviewed-by: Yoann Lopes (cherry picked from commit d91dac090d92fdbc3a3425e8d969c62e5c79eff9) Conflicts: src/gsttools/qgstreamervideorenderer.cpp src/gsttools/qgstreamervideowidget.cpp src/gsttools/qgstreamervideowindow.cpp src/plugins/gstreamer/camerabin/camerabinsession.cpp src/plugins/gstreamer/mediacapture/qgstreamercapturesession.cpp src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp --- config.tests/gstreamer/gstreamer.pro | 11 +- config.tests/gstreamer_appsrc/gstreamer_appsrc.pro | 13 +- .../gstreamer_encodingprofiles.pro | 13 +- .../gstreamer_photography.pro | 15 +- qtmultimedia.pro | 25 ++- src/gsttools/gsttools.pro | 22 +-- src/gsttools/gstvideoconnector.c | 199 +++++++++++++++++++-- src/gsttools/qgstappsrc.cpp | 29 ++- src/gsttools/qgstreameraudioprobecontrol.cpp | 19 +- src/gsttools/qgstreamerbushelper.cpp | 8 + src/gsttools/qgstreamervideoprobecontrol.cpp | 9 + src/gsttools/qgstreamervideorenderer.cpp | 3 +- src/gsttools/qgstreamervideowidget.cpp | 29 ++- src/gsttools/qgstreamervideowindow.cpp | 79 +++++++- src/gsttools/qgstutils.cpp | 27 ++- src/gsttools/qgstvideobuffer.cpp | 18 +- src/gsttools/qvideosurfacegstsink.cpp | 136 +++++++++++++- src/multimedia/gsttools_headers/qgstappsrc_p.h | 3 + .../qgstreameraudioprobecontrol_p.h | 5 +- .../qgstreamervideoprobecontrol_p.h | 4 + .../gsttools_headers/qgstreamervideowindow_p.h | 4 + src/multimedia/gsttools_headers/qgstutils_p.h | 4 + .../gsttools_headers/qgstvideobuffer_p.h | 3 + .../gsttools_headers/qvideosurfacegstsink_p.h | 6 +- .../qgstreameraudiodecoderserviceplugin.cpp | 27 ++- .../audiodecoder/qgstreameraudiodecodersession.cpp | 33 +++- .../gstreamer/camerabin/camerabinsession.cpp | 25 +++ src/plugins/gstreamer/common.pri | 21 ++- src/plugins/gstreamer/gstreamer.pro | 3 +- .../mediacapture/qgstreamercapturesession.cpp | 5 + src/plugins/gstreamer/mediaplayer/mediaplayer.pro | 1 - .../mediaplayer/qgstreamerplayercontrol.cpp | 2 + .../mediaplayer/qgstreamerplayerservice.cpp | 9 +- .../mediaplayer/qgstreamerplayerserviceplugin.cpp | 27 ++- .../mediaplayer/qgstreamerplayersession.cpp | 154 ++++++++++++++-- .../mediaplayer/qgstreamerplayersession.h | 9 + 36 files changed, 871 insertions(+), 129 deletions(-) diff --git a/config.tests/gstreamer/gstreamer.pro b/config.tests/gstreamer/gstreamer.pro index 02a7e34..6b9843a 100644 --- a/config.tests/gstreamer/gstreamer.pro +++ b/config.tests/gstreamer/gstreamer.pro @@ -3,11 +3,10 @@ SOURCES += main.cpp CONFIG += link_pkgconfig PKGCONFIG += \ - gstreamer-0.10 \ - gstreamer-base-0.10 \ - gstreamer-interfaces-0.10 \ - gstreamer-audio-0.10 \ - gstreamer-video-0.10 \ - gstreamer-pbutils-0.10 + gstreamer-$$GST_VERSION \ + gstreamer-base-$$GST_VERSION \ + gstreamer-audio-$$GST_VERSION \ + gstreamer-video-$$GST_VERSION \ + gstreamer-pbutils-$$GST_VERSION diff --git a/config.tests/gstreamer_appsrc/gstreamer_appsrc.pro b/config.tests/gstreamer_appsrc/gstreamer_appsrc.pro index 9f61703..0f3ca2b 100644 --- a/config.tests/gstreamer_appsrc/gstreamer_appsrc.pro +++ b/config.tests/gstreamer_appsrc/gstreamer_appsrc.pro @@ -3,11 +3,8 @@ SOURCES += main.cpp CONFIG += link_pkgconfig PKGCONFIG += \ - gstreamer-0.10 \ - gstreamer-base-0.10 \ - gstreamer-interfaces-0.10 \ - gstreamer-audio-0.10 \ - gstreamer-video-0.10 \ - gstreamer-app-0.10 - - + gstreamer-$$GST_VERSION \ + gstreamer-base-$$GST_VERSION \ + gstreamer-audio-$$GST_VERSION \ + gstreamer-video-$$GST_VERSION \ + gstreamer-pbutils-$$GST_VERSION diff --git a/config.tests/gstreamer_encodingprofiles/gstreamer_encodingprofiles.pro b/config.tests/gstreamer_encodingprofiles/gstreamer_encodingprofiles.pro index 7e8a9e7..fad40b0 100644 --- a/config.tests/gstreamer_encodingprofiles/gstreamer_encodingprofiles.pro +++ b/config.tests/gstreamer_encodingprofiles/gstreamer_encodingprofiles.pro @@ -2,11 +2,10 @@ SOURCES += main.cpp CONFIG += link_pkgconfig -PKGCONFIG += \ - gstreamer-0.10 \ - gstreamer-base-0.10 \ - gstreamer-interfaces-0.10 \ - gstreamer-audio-0.10 \ - gstreamer-video-0.10 \ - gstreamer-pbutils-0.10 +PKGCONFIG += \ + gstreamer-$$GST_VERSION \ + gstreamer-base-$$GST_VERSION \ + gstreamer-audio-$$GST_VERSION \ + gstreamer-video-$$GST_VERSION \ + gstreamer-pbutils-$$GST_VERSION diff --git a/config.tests/gstreamer_photography/gstreamer_photography.pro b/config.tests/gstreamer_photography/gstreamer_photography.pro index 6b530cb..975991f 100644 --- a/config.tests/gstreamer_photography/gstreamer_photography.pro +++ b/config.tests/gstreamer_photography/gstreamer_photography.pro @@ -3,12 +3,11 @@ SOURCES += main.cpp CONFIG += link_pkgconfig PKGCONFIG += \ - gstreamer-0.10 \ - gstreamer-base-0.10 \ - gstreamer-interfaces-0.10 \ - gstreamer-audio-0.10 \ - gstreamer-video-0.10 \ - gstreamer-pbutils-0.10 - -LIBS += -lgstphotography-0.10 + gstreamer-$$GST_VERSION \ + gstreamer-base-$$GST_VERSION \ + gstreamer-audio-$$GST_VERSION \ + gstreamer-video-$$GST_VERSION \ + gstreamer-pbutils-$$GST_VERSION + +LIBS += -lgstphotography-$$GST_VERSION diff --git a/qtmultimedia.pro b/qtmultimedia.pro index 3cec526..109dd81 100644 --- a/qtmultimedia.pro +++ b/qtmultimedia.pro @@ -17,11 +17,26 @@ win32 { } else { qtCompileTest(alsa) qtCompileTest(pulseaudio) - qtCompileTest(gstreamer) { - qtCompileTest(gstreamer_photography) - qtCompileTest(gstreamer_encodingprofiles) - qtCompileTest(gstreamer_appsrc) - qtCompileTest(linux_v4l) + !done_config_gstreamer { + gstver=1.0 + cache(GST_VERSION, set, gstver); + qtCompileTest(gstreamer) { + qtCompileTest(gstreamer_photography) + qtCompileTest(gstreamer_encodingprofiles) + qtCompileTest(gstreamer_appsrc) + qtCompileTest(linux_v4l) + } else { + gstver=0.10 + cache(GST_VERSION, set, gstver); + # Force a re-run of the test + CONFIG -= done_config_gstreamer + qtCompileTest(gstreamer) { + qtCompileTest(gstreamer_photography) + qtCompileTest(gstreamer_encodingprofiles) + qtCompileTest(gstreamer_appsrc) + qtCompileTest(linux_v4l) + } + } } qtCompileTest(resourcepolicy) qtCompileTest(gpu_vivante) diff --git a/src/gsttools/gsttools.pro b/src/gsttools/gsttools.pro index 7c809a7..6b9bf5d 100644 --- a/src/gsttools/gsttools.pro +++ b/src/gsttools/gsttools.pro @@ -2,7 +2,7 @@ TEMPLATE = lib TARGET = qgsttools_p QPRO_PWD = $$PWD -QT = core-private multimedia-private gui-private +QT = core-private multimedia-private gui-private opengl !static:DEFINES += QT_MAKEDLL DEFINES += GLIB_VERSION_MIN_REQUIRED=GLIB_VERSION_2_26 @@ -15,13 +15,14 @@ LIBS_PRIVATE += \ CONFIG += link_pkgconfig -PKGCONFIG_PRIVATE += \ - gstreamer-0.10 \ - gstreamer-base-0.10 \ - gstreamer-interfaces-0.10 \ - gstreamer-audio-0.10 \ - gstreamer-video-0.10 \ - gstreamer-pbutils-0.10 +PKGCONFIG += \ + gstreamer-$$GST_VERSION \ + gstreamer-base-$$GST_VERSION \ + gstreamer-audio-$$GST_VERSION \ + gstreamer-video-$$GST_VERSION \ + gstreamer-pbutils-$$GST_VERSION + +equals(GST_VERSION,"0.10"): PKGCONFIG_PRIVATE += gstreamer-interfaces-$$GST_VERSION maemo*: PKGCONFIG_PRIVATE +=gstreamer-plugins-bad-0.10 @@ -33,6 +34,7 @@ config_resourcepolicy { # Header files must go inside source directory of a module # to be installed by syncqt. INCLUDEPATH += ../multimedia/gsttools_headers/ +INCLUDEPATH += ../plugins/gstreamer/mediaplayer/ VPATH += ../multimedia/gsttools_headers/ PRIVATE_HEADERS += \ @@ -91,13 +93,13 @@ maemo6 { } config_gstreamer_appsrc { - PKGCONFIG_PRIVATE += gstreamer-app-0.10 + PKGCONFIG_PRIVATE += gstreamer-app-$$GST_VERSION PRIVATE_HEADERS += qgstappsrc_p.h SOURCES += qgstappsrc.cpp DEFINES += HAVE_GST_APPSRC - LIBS_PRIVATE += -lgstapp-0.10 + LIBS_PRIVATE += -lgstapp-$$GST_VERSION } config_linux_v4l: DEFINES += USE_V4L diff --git a/src/gsttools/gstvideoconnector.c b/src/gsttools/gstvideoconnector.c index 3ed539e..ed0ed3c 100644 --- a/src/gsttools/gstvideoconnector.c +++ b/src/gsttools/gstvideoconnector.c @@ -59,26 +59,93 @@ GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_ALWAYS, GST_STATIC_CAPS_ANY); + +#if GST_CHECK_VERSION(1,0,0) + +G_DEFINE_TYPE(GstVideoConnector, gst_video_connector, GST_TYPE_ELEMENT); +#else #define _do_init(bla) \ GST_DEBUG_CATEGORY_INIT (video_connector_debug, \ "video-connector", 0, "An identity like element for reconnecting video stream"); GST_BOILERPLATE_FULL (GstVideoConnector, gst_video_connector, GstElement, GST_TYPE_ELEMENT, _do_init); +#endif static void gst_video_connector_dispose (GObject * object); + +#if GST_CHECK_VERSION(1,0,0) +static GstFlowReturn gst_video_connector_chain (GstPad * pad, GstObject* parent, GstBuffer * buf); +#else static GstFlowReturn gst_video_connector_chain (GstPad * pad, GstBuffer * buf); static GstFlowReturn gst_video_connector_buffer_alloc (GstPad * pad, guint64 offset, guint size, GstCaps * caps, GstBuffer ** buf); +#endif + static GstStateChangeReturn gst_video_connector_change_state (GstElement * element, GstStateChange transition); + +#if GST_CHECK_VERSION(1,0,0) +static gboolean gst_video_connector_handle_sink_event (GstPad * pad, GstObject* parent, + GstEvent * event); +#else static gboolean gst_video_connector_handle_sink_event (GstPad * pad, GstEvent * event); +#endif + +#if GST_CHECK_VERSION(1,0,0) +static GstPadProbeReturn gst_video_connector_new_buffer_probe(GstPad *pad, GstPadProbeInfo *info, gpointer object); +static GstPadProbeReturn gst_video_connector_new_event_probe(GstPad *pad, GstPadProbeInfo *info, gpointer object); +static GstPadProbeReturn gst_video_connector_new_query_probe(GstPad *pad, GstPadProbeInfo *info, gpointer object); +#else static gboolean gst_video_connector_new_buffer_probe(GstObject *pad, GstBuffer *buffer, guint * object); -static void gst_video_connector_resend_new_segment(GstElement * element, gboolean emitFailedSignal); static gboolean gst_video_connector_setcaps (GstPad *pad, GstCaps *caps); static GstCaps *gst_video_connector_getcaps (GstPad * pad); static gboolean gst_video_connector_acceptcaps (GstPad * pad, GstCaps * caps); +#endif + +static void gst_video_connector_resend_new_segment(GstElement * element, gboolean emitFailedSignal); + +#if GST_CHECK_VERSION(1,0,0) +static void +gst_video_connector_class_init (GstVideoConnectorClass * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); + + gst_element_class_set_details_simple (gstelement_class, "Video Connector", + "Generic", + "An identity like element used for reconnecting video stream", + "Dmytro Poplavskiy "); + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&gst_video_connector_sink_factory)); + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&gst_video_connector_src_factory)); + + gst_video_connector_parent_class = g_type_class_peek_parent (klass); + + gobject_class->dispose = gst_video_connector_dispose; + gstelement_class->change_state = gst_video_connector_change_state; + klass->resend_new_segment = gst_video_connector_resend_new_segment; + + gst_video_connector_signals[SIGNAL_RESEND_NEW_SEGMENT] = + g_signal_new ("resend-new-segment", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (GstVideoConnectorClass, resend_new_segment), NULL, NULL, + g_cclosure_marshal_VOID__BOOLEAN, G_TYPE_NONE, 1, G_TYPE_BOOLEAN); + + gst_video_connector_signals[SIGNAL_CONNECTION_FAILED] = + g_signal_new ("connection-failed", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + 0, NULL, NULL, + g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + + GST_DEBUG_CATEGORY_INIT(video_connector_debug, "video-connector", 0, + "An identity like element for reconnecting video stream"); + +} + +#else static void gst_video_connector_base_init (gpointer g_class) @@ -120,18 +187,33 @@ gst_video_connector_class_init (GstVideoConnectorClass * klass) g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); } +#endif + static void -gst_video_connector_init (GstVideoConnector *element, - GstVideoConnectorClass *g_class) +gst_video_connector_init (GstVideoConnector *element +#if GST_CHECK_VERSION(1,0,0) +#else + ,GstVideoConnectorClass *g_class +#endif + ) { +#if GST_CHECK_VERSION(1,0,0) +#else (void) g_class; +#endif element->sinkpad = gst_pad_new_from_static_template (&gst_video_connector_sink_factory, "sink"); gst_pad_set_chain_function(element->sinkpad, GST_DEBUG_FUNCPTR (gst_video_connector_chain)); +#if GST_CHECK_VERSION(1,0,0) + /* gstreamer 1.x uses QUERIES and EVENTS for allocation and caps handiling purposes */ + GST_OBJECT_FLAG_SET (element->sinkpad, GST_PAD_FLAG_PROXY_CAPS); + GST_OBJECT_FLAG_SET (element->sinkpad, GST_PAD_FLAG_PROXY_ALLOCATION); +#else gst_pad_set_event_function(element->sinkpad, GST_DEBUG_FUNCPTR (gst_video_connector_handle_sink_event)); + gst_pad_set_bufferalloc_function(element->sinkpad, GST_DEBUG_FUNCPTR (gst_video_connector_buffer_alloc)); gst_pad_set_setcaps_function(element->sinkpad, @@ -140,14 +222,23 @@ gst_video_connector_init (GstVideoConnector *element, GST_DEBUG_FUNCPTR(gst_video_connector_getcaps)); gst_pad_set_acceptcaps_function(element->sinkpad, GST_DEBUG_FUNCPTR(gst_video_connector_acceptcaps)); - +#endif gst_element_add_pad (GST_ELEMENT (element), element->sinkpad); element->srcpad = gst_pad_new_from_static_template (&gst_video_connector_src_factory, "src"); +#if GST_CHECK_VERSION(1,0,0) + gst_pad_add_probe(element->srcpad, GST_PAD_PROBE_TYPE_BUFFER, + gst_video_connector_new_buffer_probe, element, NULL); + gst_pad_add_probe(element->srcpad, GST_PAD_PROBE_TYPE_QUERY_DOWNSTREAM, + gst_video_connector_new_query_probe, element, NULL); + gst_pad_add_probe(element->sinkpad, GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM, + gst_video_connector_new_event_probe, element, NULL); +#else gst_pad_add_buffer_probe(element->srcpad, G_CALLBACK(gst_video_connector_new_buffer_probe), element); +#endif gst_element_add_pad (GST_ELEMENT (element), element->srcpad); element->relinked = FALSE; @@ -175,9 +266,16 @@ gst_video_connector_dispose (GObject * object) gst_video_connector_reset (element); +#if GST_CHECK_VERSION(1,0,0) + G_OBJECT_CLASS (gst_video_connector_parent_class)->dispose (object); +#else G_OBJECT_CLASS (parent_class)->dispose (object); +#endif } +#if GST_CHECK_VERSION(1,0,0) +/* For gstreamer 1.x we handle it in ALLOCATION Query */ +#else // "When this function returns anything else than GST_FLOW_OK, // the buffer allocation failed and buf does not contain valid data." static GstFlowReturn @@ -221,6 +319,7 @@ gst_video_connector_buffer_alloc (GstPad * pad, guint64 offset, guint size, if (state == GST_STATE_NULL) { GST_DEBUG_OBJECT (element, "Downstream element is in NULL state"); // Downstream filter seems to be in the wrong state + return GST_FLOW_UNEXPECTED; } } @@ -293,6 +392,7 @@ static GstCaps *gst_video_connector_getcaps (GstPad * pad) return caps; } + static gboolean gst_video_connector_acceptcaps (GstPad * pad, GstCaps * caps) { GstVideoConnector *element; @@ -300,6 +400,7 @@ static gboolean gst_video_connector_acceptcaps (GstPad * pad, GstCaps * caps) return gst_pad_peer_accept_caps(element->srcpad, caps); } +#endif static void gst_video_connector_resend_new_segment(GstElement * element, gboolean emitFailedSignal) @@ -311,11 +412,39 @@ gst_video_connector_resend_new_segment(GstElement * element, gboolean emitFailed connector->failedSignalEmited = FALSE; } +#if GST_CHECK_VERSION(1,0,0) +static GstPadProbeReturn gst_video_connector_new_event_probe(GstPad *pad, GstPadProbeInfo *info, gpointer object) +{ + GstVideoConnector *connector = GST_VIDEO_CONNECTOR (object); + GstEvent *event = gst_pad_probe_info_get_event(info); + + GST_DEBUG_OBJECT(connector, "Event %"GST_PTR_FORMAT" received\n", event); + + return GST_PAD_PROBE_OK; +} + +static GstPadProbeReturn gst_video_connector_new_query_probe(GstPad *pad, GstPadProbeInfo *info, gpointer object) +{ + GstVideoConnector *connector = GST_VIDEO_CONNECTOR (object); + GstQuery *query = gst_pad_probe_info_get_query(info); + + GST_DEBUG_OBJECT(connector, "Query %"GST_PTR_FORMAT" received\n", query); + + return GST_PAD_PROBE_OK; +} +#endif +#if GST_CHECK_VERSION(1,0,0) +static GstPadProbeReturn gst_video_connector_new_buffer_probe(GstPad *pad, GstPadProbeInfo *info, gpointer object) +{ + (void) info; +#else static gboolean gst_video_connector_new_buffer_probe(GstObject *pad, GstBuffer *buffer, guint * object) { - (void) pad; (void) buffer; +#endif + (void) pad; + GstVideoConnector *element = GST_VIDEO_CONNECTOR (object); @@ -327,16 +456,23 @@ static gboolean gst_video_connector_new_buffer_probe(GstObject *pad, GstBuffer * if (element->relinked) GST_LOG_OBJECT(element, "rejected buffer because of new segment request"); - return !element->relinked; + return element->relinked ? GST_PAD_PROBE_DROP : GST_PAD_PROBE_OK; } - static GstFlowReturn +#if GST_CHECK_VERSION(1,0,0) +gst_video_connector_chain (GstPad * pad, GstObject* parent, GstBuffer * buf) +#else gst_video_connector_chain (GstPad * pad, GstBuffer * buf) +#endif { GstFlowReturn res; GstVideoConnector *element; +#if GST_CHECK_VERSION(1,0,0) + (void)parent; +#endif + element = GST_VIDEO_CONNECTOR (gst_pad_get_parent (pad)); do { @@ -348,20 +484,29 @@ gst_video_connector_chain (GstPad * pad, GstBuffer * buf) */ while (element->relinked) { element->relinked = FALSE; - +#if GST_CHECK_VERSION(1,0,0) + if (element->latest_buffer && GST_BUFFER_TIMESTAMP_IS_VALID(element->latest_buffer)) { + element->segment.position = GST_BUFFER_TIMESTAMP (element->latest_buffer); + } +#else gint64 pos = element->segment.last_stop; - if (element->latest_buffer && GST_BUFFER_TIMESTAMP_IS_VALID(element->latest_buffer)) { pos = GST_BUFFER_TIMESTAMP (element->latest_buffer); } +#endif //push a new segment and last buffer +#if GST_CHECK_VERSION(1,0,0) + GstEvent *ev = gst_event_new_segment (&element->segment); + +#else GstEvent *ev = gst_event_new_new_segment (TRUE, element->segment.rate, element->segment.format, pos, //start element->segment.stop, pos); +#endif GST_DEBUG_OBJECT (element, "Pushing new segment event"); if (!gst_pad_push_event (element->srcpad, ev)) { @@ -424,8 +569,11 @@ gst_video_connector_change_state (GstElement * element, GstStateChangeReturn result; connector = GST_VIDEO_CONNECTOR(element); +#if GST_CHECK_VERSION(1,0,0) + result = GST_ELEMENT_CLASS (gst_video_connector_parent_class)->change_state(element, transition); +#else result = GST_ELEMENT_CLASS (parent_class)->change_state(element, transition); - +#endif switch (transition) { case GST_STATE_CHANGE_PAUSED_TO_READY: gst_video_connector_reset (connector); @@ -440,9 +588,32 @@ gst_video_connector_change_state (GstElement * element, return result; } -static gboolean -gst_video_connector_handle_sink_event (GstPad * pad, GstEvent * event) +#if GST_CHECK_VERSION(1,0,0) +static gboolean gst_video_connector_handle_sink_event (GstPad * pad, GstObject* parent, + GstEvent * event) +{ + GstVideoConnector *element = GST_VIDEO_CONNECTOR (gst_pad_get_parent (pad)); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_SEGMENT: + break; + case GST_EVENT_CAPS: + break; + default: + break; + } + + gst_object_unref (element); + return gst_pad_event_default (pad, parent, event); +} + +#else + +static gboolean gst_video_connector_handle_sink_event (GstPad * pad, + GstEvent * event) { + (void)parent; + if (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT) { GstVideoConnector *element = GST_VIDEO_CONNECTOR (gst_pad_get_parent (pad)); @@ -453,7 +624,6 @@ gst_video_connector_handle_sink_event (GstPad * pad, GstEvent * event) gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format, &start, &stop, &time); - GST_LOG_OBJECT (element, "NEWSEGMENT update %d, rate %lf, applied rate %lf, " "format %d, " "%" G_GINT64_FORMAT " -- %" G_GINT64_FORMAT ", time %" @@ -461,9 +631,10 @@ gst_video_connector_handle_sink_event (GstPad * pad, GstEvent * event) gst_segment_set_newsegment_full (&element->segment, update, rate, arate, format, start, stop, time); - gst_object_unref (element); } return gst_pad_event_default (pad, event); } + +#endif diff --git a/src/gsttools/qgstappsrc.cpp b/src/gsttools/qgstappsrc.cpp index 561a96f..d5e106f 100644 --- a/src/gsttools/qgstappsrc.cpp +++ b/src/gsttools/qgstappsrc.cpp @@ -147,23 +147,44 @@ void QGstAppSrc::pushDataToAppSrc() size = qMin(m_stream->bytesAvailable(), (qint64)m_dataRequestSize); if (size) { - void *data = g_malloc(size); - GstBuffer* buffer = gst_app_buffer_new(data, size, g_free, data); + GstBuffer* buffer = gst_buffer_new_and_alloc(size); + +#if GST_CHECK_VERSION(1,0,0) + GstMapInfo mapInfo; + gst_buffer_map(buffer, &mapInfo, GST_MAP_WRITE); + void* bufferData = mapInfo.data; +#else + void* bufferData = GST_BUFFER_DATA(buffer); +#endif + buffer->offset = m_stream->pos(); - qint64 bytesRead = m_stream->read((char*)GST_BUFFER_DATA(buffer), size); + qint64 bytesRead = m_stream->read((char*)bufferData, size); buffer->offset_end = buffer->offset + bytesRead - 1; +#if GST_CHECK_VERSION(1,0,0) + gst_buffer_unmap(buffer, &mapInfo); +#endif + if (bytesRead > 0) { m_dataRequested = false; m_enoughData = false; GstFlowReturn ret = gst_app_src_push_buffer (GST_APP_SRC (element()), buffer); if (ret == GST_FLOW_ERROR) { qWarning()<<"appsrc: push buffer error"; +#if GST_CHECK_VERSION(1,0,0) + } else if (ret == GST_FLOW_FLUSHING) { + qWarning()<<"appsrc: push buffer wrong state"; + } +#else } else if (ret == GST_FLOW_WRONG_STATE) { qWarning()<<"appsrc: push buffer wrong state"; - } else if (ret == GST_FLOW_RESEND) { + } +#endif +#if GST_VERSION_MAJOR < 1 + else if (ret == GST_FLOW_RESEND) { qWarning()<<"appsrc: push buffer resend"; } +#endif } } else { sendEOS(); diff --git a/src/gsttools/qgstreameraudioprobecontrol.cpp b/src/gsttools/qgstreameraudioprobecontrol.cpp index 3baca53..be3de3f 100644 --- a/src/gsttools/qgstreameraudioprobecontrol.cpp +++ b/src/gsttools/qgstreameraudioprobecontrol.cpp @@ -45,9 +45,14 @@ QGstreamerAudioProbeControl::~QGstreamerAudioProbeControl() } +#if GST_CHECK_VERSION(1,0,0) +void QGstreamerAudioProbeControl::bufferProbed(GstBuffer* buffer, GstCaps* caps) +{ +#else void QGstreamerAudioProbeControl::bufferProbed(GstBuffer* buffer) { - GstCaps* caps = gst_buffer_get_caps(buffer); + gst_buffer_get_caps(buffer); +#endif if (!caps) return; @@ -56,8 +61,20 @@ void QGstreamerAudioProbeControl::bufferProbed(GstBuffer* buffer) if (!format.isValid()) return; + #if GST_CHECK_VERSION(1,0,0) + + GstMapInfo info; + + gst_buffer_map (buffer, &info, GST_MAP_READ); + QAudioBuffer audioBuffer = QAudioBuffer(QByteArray((const char*)info.data, info.size), format); + gst_buffer_unmap(buffer, &info); + + #else + QAudioBuffer audioBuffer = QAudioBuffer(QByteArray((const char*)buffer->data, buffer->size), format); + #endif + { QMutexLocker locker(&m_bufferMutex); m_pendingBuffer = audioBuffer; diff --git a/src/gsttools/qgstreamerbushelper.cpp b/src/gsttools/qgstreamerbushelper.cpp index 84eda46..eb1fc36 100644 --- a/src/gsttools/qgstreamerbushelper.cpp +++ b/src/gsttools/qgstreamerbushelper.cpp @@ -154,13 +154,21 @@ QGstreamerBusHelper::QGstreamerBusHelper(GstBus* bus, QObject* parent): QObject(parent) { d = new QGstreamerBusHelperPrivate(this, bus); +#if GST_CHECK_VERSION(1,0,0) + gst_bus_set_sync_handler(bus, (GstBusSyncHandler)syncGstBusFilter, d, 0); +#else gst_bus_set_sync_handler(bus, (GstBusSyncHandler)syncGstBusFilter, d); +#endif gst_object_ref(GST_OBJECT(bus)); } QGstreamerBusHelper::~QGstreamerBusHelper() { +#if GST_CHECK_VERSION(1,0,0) + gst_bus_set_sync_handler(d->bus(), 0, 0, 0); +#else gst_bus_set_sync_handler(d->bus(),0,0); +#endif gst_object_unref(GST_OBJECT(d->bus())); } diff --git a/src/gsttools/qgstreamervideoprobecontrol.cpp b/src/gsttools/qgstreamervideoprobecontrol.cpp index a78a9da..9c31140 100644 --- a/src/gsttools/qgstreamervideoprobecontrol.cpp +++ b/src/gsttools/qgstreamervideoprobecontrol.cpp @@ -67,12 +67,21 @@ void QGstreamerVideoProbeControl::stopFlushing() m_flushing = false; } +#if GST_CHECK_VERSION(1,0,0) +void QGstreamerVideoProbeControl::bufferProbed(GstBuffer* buffer, GstCaps* caps) +#else void QGstreamerVideoProbeControl::bufferProbed(GstBuffer* buffer) +#endif { if (m_flushing) return; +#if GST_CHECK_VERSION(1,0,0) + // FIXME: + // GstCaps* caps = NULL;//gst_buffer_get_caps(buffer); +#else GstCaps* caps = gst_buffer_get_caps(buffer); +#endif if (!caps) return; diff --git a/src/gsttools/qgstreamervideorenderer.cpp b/src/gsttools/qgstreamervideorenderer.cpp index 2b66f76..804dce9 100644 --- a/src/gsttools/qgstreamervideorenderer.cpp +++ b/src/gsttools/qgstreamervideorenderer.cpp @@ -35,8 +35,7 @@ #include #include #include - -#include +#include #include diff --git a/src/gsttools/qgstreamervideowidget.cpp b/src/gsttools/qgstreamervideowidget.cpp index aa2e2a3..14c1f04 100644 --- a/src/gsttools/qgstreamervideowidget.cpp +++ b/src/gsttools/qgstreamervideowidget.cpp @@ -40,8 +40,13 @@ #include #include + +#if !GST_CHECK_VERSION(1,0,0) #include #include +#else +#include +#endif QT_BEGIN_NAMESPACE @@ -169,9 +174,13 @@ bool QGstreamerVideoWidgetControl::processSyncMessage(const QGstreamerMessage &m { GstMessage* gm = message.rawMessage(); +#if !GST_CHECK_VERSION(1,0,0) if (gm && (GST_MESSAGE_TYPE(gm) == GST_MESSAGE_ELEMENT) && gst_structure_has_name(gm->structure, "prepare-xwindow-id")) { - +#else + if (gm && (GST_MESSAGE_TYPE(gm) == GST_MESSAGE_ELEMENT) && + gst_structure_has_name(gst_message_get_structure(gm), "prepare-window-handle")) { +#endif setOverlay(); QMetaObject::invokeMethod(this, "updateNativeVideoSize", Qt::QueuedConnection); return true; @@ -199,18 +208,29 @@ bool QGstreamerVideoWidgetControl::processBusMessage(const QGstreamerMessage &me void QGstreamerVideoWidgetControl::setOverlay() { +#if !GST_CHECK_VERSION(1,0,0) if (m_videoSink && GST_IS_X_OVERLAY(m_videoSink)) { gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(m_videoSink), m_windowId); } +#else + if (m_videoSink && GST_IS_VIDEO_OVERLAY(m_videoSink)) { + gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(m_videoSink), m_windowId); + } +#endif } void QGstreamerVideoWidgetControl::updateNativeVideoSize() { if (m_videoSink) { //find video native size to update video widget size hint - GstPad *pad = gst_element_get_static_pad(m_videoSink,"sink"); + GstPad *pad = gst_element_get_static_pad(m_videoSink, "sink"); +#if !GST_CHECK_VERSION(1,0,0) GstCaps *caps = gst_pad_get_negotiated_caps(pad); gst_object_unref(GST_OBJECT(pad)); +#else + GstCaps *caps = gst_pad_get_current_caps(pad); + gst_object_unref(GST_OBJECT(pad)); +#endif if (caps) { m_widget->setNativeSize(QGstUtils::capsCorrectedResolution(caps)); @@ -225,8 +245,13 @@ void QGstreamerVideoWidgetControl::updateNativeVideoSize() void QGstreamerVideoWidgetControl::windowExposed() { +#if !GST_CHECK_VERSION(1,0,0) if (m_videoSink && GST_IS_X_OVERLAY(m_videoSink)) gst_x_overlay_expose(GST_X_OVERLAY(m_videoSink)); +#else + if (m_videoSink && GST_IS_VIDEO_OVERLAY(m_videoSink)) + gst_video_overlay_expose(GST_VIDEO_OVERLAY(m_videoSink)); +#endif } QWidget *QGstreamerVideoWidgetControl::videoWidget() diff --git a/src/gsttools/qgstreamervideowindow.cpp b/src/gsttools/qgstreamervideowindow.cpp index a373dcc..587b010 100644 --- a/src/gsttools/qgstreamervideowindow.cpp +++ b/src/gsttools/qgstreamervideowindow.cpp @@ -37,8 +37,12 @@ #include #include +#include + +#if !GST_CHECK_VERSION(1,0,0) #include #include +#endif QGstreamerVideoWindow::QGstreamerVideoWindow(QObject *parent, const char *elementName) @@ -49,18 +53,25 @@ QGstreamerVideoWindow::QGstreamerVideoWindow(QObject *parent, const char *elemen , m_fullScreen(false) , m_colorKey(QColor::Invalid) { - if (elementName) + if (elementName) { m_videoSink = gst_element_factory_make(elementName, NULL); - else + } else { m_videoSink = gst_element_factory_make("xvimagesink", NULL); + } if (m_videoSink) { qt_gst_object_ref_sink(GST_OBJECT(m_videoSink)); //Take ownership GstPad *pad = gst_element_get_static_pad(m_videoSink,"sink"); +#if GST_CHECK_VERSION(1,0,0) + m_bufferProbeId = gst_pad_add_probe(pad, GST_PAD_PROBE_TYPE_BUFFER, padBufferProbe, this, NULL); +#else m_bufferProbeId = gst_pad_add_buffer_probe(pad, G_CALLBACK(padBufferProbe), this); +#endif gst_object_unref(GST_OBJECT(pad)); } + else + qDebug() << "No m_videoSink available!"; } QGstreamerVideoWindow::~QGstreamerVideoWindow() @@ -82,11 +93,15 @@ void QGstreamerVideoWindow::setWinId(WId id) WId oldId = m_windowId; m_windowId = id; - +#if GST_CHECK_VERSION(1,0,0) + if (m_videoSink && GST_IS_VIDEO_OVERLAY(m_videoSink)) { + gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(m_videoSink), m_windowId); + } +#else if (m_videoSink && GST_IS_X_OVERLAY(m_videoSink)) { gst_x_overlay_set_xwindow_id(GST_X_OVERLAY(m_videoSink), m_windowId); } - +#endif if (!oldId) emit readyChanged(true); @@ -97,7 +112,20 @@ void QGstreamerVideoWindow::setWinId(WId id) bool QGstreamerVideoWindow::processSyncMessage(const QGstreamerMessage &message) { GstMessage* gm = message.rawMessage(); +#if GST_CHECK_VERSION(1,0,0) + const GstStructure *s = gst_message_get_structure(gm); + if ((GST_MESSAGE_TYPE(gm) == GST_MESSAGE_ELEMENT) && + gst_structure_has_name(s, "prepare-window-handle") && + m_videoSink && GST_IS_VIDEO_OVERLAY(m_videoSink)) { + + gst_video_overlay_set_window_handle(GST_VIDEO_OVERLAY(m_videoSink), m_windowId); + GstPad *pad = gst_element_get_static_pad(m_videoSink,"sink"); + m_bufferProbeId = gst_pad_add_probe(pad, GST_PAD_PROBE_TYPE_BUFFER, padBufferProbe, this, NULL); + + return true; + } +#else if ((GST_MESSAGE_TYPE(gm) == GST_MESSAGE_ELEMENT) && gst_structure_has_name(gm->structure, "prepare-xwindow-id") && m_videoSink && GST_IS_X_OVERLAY(m_videoSink)) { @@ -110,7 +138,7 @@ bool QGstreamerVideoWindow::processSyncMessage(const QGstreamerMessage &message) return true; } - +#endif return false; } @@ -122,7 +150,19 @@ QRect QGstreamerVideoWindow::displayRect() const void QGstreamerVideoWindow::setDisplayRect(const QRect &rect) { m_displayRect = rect; - +#if GST_CHECK_VERSION(1,0,0) + if (m_videoSink && GST_IS_VIDEO_OVERLAY(m_videoSink)) { + if (m_displayRect.isEmpty()) + gst_video_overlay_set_render_rectangle(GST_VIDEO_OVERLAY(m_videoSink), -1, -1, -1, -1); + else + gst_video_overlay_set_render_rectangle(GST_VIDEO_OVERLAY(m_videoSink), + m_displayRect.x(), + m_displayRect.y(), + m_displayRect.width(), + m_displayRect.height()); + repaint(); + } +#else if (m_videoSink && GST_IS_X_OVERLAY(m_videoSink)) { #if GST_VERSION_MICRO >= 29 if (m_displayRect.isEmpty()) @@ -136,6 +176,7 @@ void QGstreamerVideoWindow::setDisplayRect(const QRect &rect) repaint(); #endif } +#endif } Qt::AspectRatioMode QGstreamerVideoWindow::aspectRatioMode() const @@ -157,6 +198,16 @@ void QGstreamerVideoWindow::setAspectRatioMode(Qt::AspectRatioMode mode) void QGstreamerVideoWindow::repaint() { +#if GST_CHECK_VERSION(1,0,0) + if (m_videoSink && GST_IS_VIDEO_OVERLAY(m_videoSink)) { + //don't call gst_x_overlay_expose if the sink is in null state + GstState state = GST_STATE_NULL; + GstStateChangeReturn res = gst_element_get_state(m_videoSink, &state, NULL, 1000000); + if (res != GST_STATE_CHANGE_FAILURE && state != GST_STATE_NULL) { + gst_video_overlay_expose(GST_VIDEO_OVERLAY(m_videoSink)); + } + } +#else if (m_videoSink && GST_IS_X_OVERLAY(m_videoSink)) { //don't call gst_x_overlay_expose if the sink is in null state GstState state = GST_STATE_NULL; @@ -165,6 +216,7 @@ void QGstreamerVideoWindow::repaint() gst_x_overlay_expose(GST_X_OVERLAY(m_videoSink)); } } +#endif } QColor QGstreamerVideoWindow::colorKey() const @@ -296,11 +348,22 @@ QSize QGstreamerVideoWindow::nativeSize() const return m_nativeSize; } +#if GST_CHECK_VERSION(1,0,0) +GstPadProbeReturn QGstreamerVideoWindow::padBufferProbe(GstPad *pad, GstPadProbeInfo *info, gpointer user_data) +#else void QGstreamerVideoWindow::padBufferProbe(GstPad *pad, GstBuffer * /* buffer */, gpointer user_data) +#endif { QGstreamerVideoWindow *control = reinterpret_cast(user_data); QMetaObject::invokeMethod(control, "updateNativeVideoSize", Qt::QueuedConnection); + +#if GST_CHECK_VERSION(1,0,0) + Q_UNUSED(pad); + Q_UNUSED(info); + return GST_PAD_PROBE_REMOVE; +#else gst_pad_remove_buffer_probe(pad, control->m_bufferProbeId); +#endif } void QGstreamerVideoWindow::updateNativeVideoSize() @@ -311,7 +374,11 @@ void QGstreamerVideoWindow::updateNativeVideoSize() if (m_videoSink) { //find video native size to update video widget size hint GstPad *pad = gst_element_get_static_pad(m_videoSink,"sink"); +#if GST_CHECK_VERSION(1,0,0) + GstCaps *caps = gst_pad_get_current_caps(pad); +#else GstCaps *caps = gst_pad_get_negotiated_caps(pad); +#endif gst_object_unref(GST_OBJECT(pad)); if (caps) { diff --git a/src/gsttools/qgstutils.cpp b/src/gsttools/qgstutils.cpp index 1281d3f..fe3fba0 100644 --- a/src/gsttools/qgstutils.cpp +++ b/src/gsttools/qgstutils.cpp @@ -89,8 +89,13 @@ static void addTagToMap(const GstTagList *list, break; default: // GST_TYPE_DATE is a function, not a constant, so pull it out of the switch +#if GST_CHECK_VERSION(1,0,0) + if (G_VALUE_TYPE(&val) == G_TYPE_DATE) { + const GDate *date = (const GDate *)g_value_get_boxed(&val); +#else if (G_VALUE_TYPE(&val) == GST_TYPE_DATE) { const GDate *date = gst_value_get_date(&val); +#endif if (g_date_valid(date)) { int year = g_date_get_year(date); int month = g_date_get_month(date); @@ -254,6 +259,24 @@ QAudioFormat QGstUtils::audioFormatForCaps(const GstCaps *caps) } + +#if GST_CHECK_VERSION(1,0,0) +/*! + Returns audio format for a buffer. + If the buffer doesn't have a valid audio format, an empty QAudioFormat is returned. +*/ + +QAudioFormat QGstUtils::audioFormatForSample(GstSample *sample) +{ + GstCaps* caps = gst_sample_get_caps(sample); + if (!caps) + return QAudioFormat(); + + QAudioFormat format = QGstUtils::audioFormatForCaps(caps); + gst_caps_unref(caps); + return format; +} +#else /*! Returns audio format for a buffer. If the buffer doesn't have a valid audio format, an empty QAudioFormat is returned. @@ -269,7 +292,7 @@ QAudioFormat QGstUtils::audioFormatForBuffer(GstBuffer *buffer) gst_caps_unref(caps); return format; } - +#endif /*! Builds GstCaps for an audio format. @@ -581,7 +604,7 @@ QByteArray QGstUtils::cameraDriver(const QString &device, GstElementFactory *fac void qt_gst_object_ref_sink(gpointer object) { -#if (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 24) +#if (GST_VERSION_MAJOR >= 0) && (GST_VERSION_MINOR >= 10) && (GST_VERSION_MICRO >= 24) || GST_CHECK_VERSION(1,0,0) gst_object_ref_sink(object); #else g_return_if_fail (GST_IS_OBJECT(object)); diff --git a/src/gsttools/qgstvideobuffer.cpp b/src/gsttools/qgstvideobuffer.cpp index 18702ec..93f22f5 100644 --- a/src/gsttools/qgstvideobuffer.cpp +++ b/src/gsttools/qgstvideobuffer.cpp @@ -70,21 +70,33 @@ QAbstractVideoBuffer::MapMode QGstVideoBuffer::mapMode() const uchar *QGstVideoBuffer::map(MapMode mode, int *numBytes, int *bytesPerLine) { if (mode != NotMapped && m_mode == NotMapped) { - if (numBytes) - *numBytes = m_buffer->size; + m_mode = mode; if (bytesPerLine) *bytesPerLine = m_bytesPerLine; - m_mode = mode; +#if GST_CHECK_VERSION(1,0,0) + gst_buffer_map(m_buffer, &m_mapInfo, GST_MAP_READ); + if (numBytes) + *numBytes = m_mapInfo.size; + + return m_mapInfo.data; +#else + if (numBytes) + *numBytes = m_buffer->size; return m_buffer->data; +#endif } else { return 0; } } void QGstVideoBuffer::unmap() { +#if GST_CHECK_VERSION(1,0,0) + if (m_mode != NotMapped) + gst_buffer_unmap(m_buffer, &m_mapInfo); +#endif m_mode = NotMapped; } diff --git a/src/gsttools/qvideosurfacegstsink.cpp b/src/gsttools/qvideosurfacegstsink.cpp index f3e2d88..94aaee7 100644 --- a/src/gsttools/qvideosurfacegstsink.cpp +++ b/src/gsttools/qvideosurfacegstsink.cpp @@ -43,7 +43,11 @@ #include "qvideosurfacegstsink_p.h" -//#define DEBUG_VIDEO_SURFACE_SINK +#if GST_VERSION_MAJOR >=1 +#include +#endif + +#define DEBUG_VIDEO_SURFACE_SINK QT_BEGIN_NAMESPACE @@ -62,10 +66,12 @@ QVideoSurfaceGstDelegate::QVideoSurfaceGstDelegate( if (m_surface) { foreach (QObject *instance, bufferPoolLoader()->instances(QGstBufferPoolPluginKey)) { QGstBufferPoolInterface* plugin = qobject_cast(instance); + if (plugin) { m_pools.append(plugin); } } + updateSupportedFormats(); connect(m_surface, SIGNAL(supportedFormatsChanged()), this, SLOT(updateSupportedFormats())); } @@ -198,6 +204,8 @@ GstFlowReturn QVideoSurfaceGstDelegate::render(GstBuffer *buffer) if (QThread::currentThread() == thread()) { if (!m_surface.isNull()) m_surface->present(m_frame); + else + qWarning() << "m_surface.isNull()."; } else { QMetaObject::invokeMethod(this, "queuedRender", Qt::QueuedConnection); m_renderCondition.wait(&m_mutex, 300); @@ -283,6 +291,27 @@ void QVideoSurfaceGstDelegate::updateSupportedFormats() } } +#if GST_CHECK_VERSION(1,0,0) +struct YuvFormat +{ + QVideoFrame::PixelFormat pixelFormat; + GstVideoFormat vfmt; + guint32 fourcc; + int bitsPerPixel; +}; + +static const YuvFormat qt_yuvColorLookup[] = +{ + { QVideoFrame::Format_YUV420P, GST_VIDEO_FORMAT_I420, GST_MAKE_FOURCC('I','4','2','0'), 8 }, + { QVideoFrame::Format_YV12, GST_VIDEO_FORMAT_YV12, GST_MAKE_FOURCC('Y','V','1','2'), 8 }, + { QVideoFrame::Format_UYVY, GST_VIDEO_FORMAT_UYVY, GST_MAKE_FOURCC('U','Y','V','Y'), 16 }, + { QVideoFrame::Format_YUYV, GST_VIDEO_FORMAT_YUY2, GST_MAKE_FOURCC('Y','U','Y','2'), 16 }, + { QVideoFrame::Format_NV12, GST_VIDEO_FORMAT_NV12, GST_MAKE_FOURCC('N','V','1','2'), 8 }, + { QVideoFrame::Format_NV21, GST_VIDEO_FORMAT_NV21, GST_MAKE_FOURCC('N','V','2','1'), 8 }, + { QVideoFrame::Format_AYUV444, GST_VIDEO_FORMAT_AYUV, GST_MAKE_FOURCC('A','Y','U','V'), 32 }, +}; + +#else struct YuvFormat { QVideoFrame::PixelFormat pixelFormat; @@ -300,6 +329,7 @@ static const YuvFormat qt_yuvColorLookup[] = { QVideoFrame::Format_NV21, GST_MAKE_FOURCC('N','V','2','1'), 8 }, { QVideoFrame::Format_AYUV444, GST_MAKE_FOURCC('A','Y','U','V'), 32 } }; +#endif static int indexOfYuvColor(QVideoFrame::PixelFormat format) { @@ -312,12 +342,20 @@ static int indexOfYuvColor(QVideoFrame::PixelFormat format) return -1; } +#if GST_VERSION_MAJOR >=1 +static int indexOfYuvColor(GstVideoFormat vfmt) +#else static int indexOfYuvColor(guint32 fourcc) +#endif { const int count = sizeof(qt_yuvColorLookup) / sizeof(YuvFormat); for (int i = 0; i < count; ++i) +#if GST_VERSION_MAJOR >=1 + if (qt_yuvColorLookup[i].vfmt == vfmt) +#else if (qt_yuvColorLookup[i].fourcc == fourcc) +#endif return i; return -1; @@ -388,13 +426,13 @@ GType QVideoSurfaceGstSink::get_type() if (type == 0) { static const GTypeInfo info = { - sizeof(QVideoSurfaceGstSinkClass), // class_size + sizeof(QVideoSurfaceGstSinkClass), // class_size base_init, // base_init NULL, // base_finalize class_init, // class_init NULL, // class_finalize NULL, // class_data - sizeof(QVideoSurfaceGstSink), // instance_size + sizeof(QVideoSurfaceGstSink), // instance_size 0, // n_preallocs instance_init, // instance_init 0 // value_table @@ -419,7 +457,11 @@ void QVideoSurfaceGstSink::class_init(gpointer g_class, gpointer class_data) GstBaseSinkClass *base_sink_class = reinterpret_cast(g_class); base_sink_class->get_caps = QVideoSurfaceGstSink::get_caps; base_sink_class->set_caps = QVideoSurfaceGstSink::set_caps; +// FIXME: +#if GST_CHECK_VERSION(1,0,0) +#else base_sink_class->buffer_alloc = QVideoSurfaceGstSink::buffer_alloc; +#endif base_sink_class->start = QVideoSurfaceGstSink::start; base_sink_class->stop = QVideoSurfaceGstSink::stop; @@ -434,6 +476,18 @@ void QVideoSurfaceGstSink::base_init(gpointer g_class) { static GstStaticPadTemplate sink_pad_template = GST_STATIC_PAD_TEMPLATE( "sink", GST_PAD_SINK, GST_PAD_ALWAYS, GST_STATIC_CAPS( +#if GST_CHECK_VERSION(1,0,0) + "video/x-raw, " + "format = (string) RGBA," + "framerate = (fraction) [ 0, MAX ], " + "width = (int) [ 1, MAX ], " + "height = (int) [ 1, MAX ]; " + "video/x-raw, " + "format = (string) I420," + "framerate = (fraction) [ 0, MAX ], " + "width = (int) [ 1, MAX ], " + "height = (int) [ 1, MAX ]")); +#else "video/x-raw-rgb, " "framerate = (fraction) [ 0, MAX ], " "width = (int) [ 1, MAX ], " @@ -442,6 +496,7 @@ void QVideoSurfaceGstSink::base_init(gpointer g_class) "framerate = (fraction) [ 0, MAX ], " "width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]")); +#endif gst_element_class_add_pad_template( GST_ELEMENT_CLASS(g_class), gst_static_pad_template_get(&sink_pad_template)); @@ -490,7 +545,11 @@ GstStateChangeReturn QVideoSurfaceGstSink::change_state( element, transition); } -GstCaps *QVideoSurfaceGstSink::get_caps(GstBaseSink *base) +GstCaps *QVideoSurfaceGstSink::get_caps(GstBaseSink *base +#if GST_CHECK_VERSION(1,0,0) + , GstCaps* /*filterCaps*/ +#endif +) { VO_SINK(base); @@ -503,6 +562,7 @@ GstCaps *QVideoSurfaceGstSink::get_caps(GstBaseSink *base) QList poolHandleFormats; sink->delegate->poolMutex()->lock(); QGstBufferPoolInterface *pool = sink->delegate->pool(); + if (pool) poolHandleFormats = sink->delegate->supportedPixelFormats(pool->handleType()); sink->delegate->poolMutex()->unlock(); @@ -518,11 +578,19 @@ GstCaps *QVideoSurfaceGstSink::get_caps(GstBaseSink *base) if (index != -1) { gst_caps_append_structure(caps, gst_structure_new( +#if GST_CHECK_VERSION(1,0,0) + "video/x-raw", +#else "video/x-raw-yuv", +#endif "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, INT_MAX, 1, "width" , GST_TYPE_INT_RANGE, 1, INT_MAX, "height" , GST_TYPE_INT_RANGE, 1, INT_MAX, +#if GST_CHECK_VERSION(1,0,0) + "format" , G_TYPE_STRING, gst_video_format_to_string(qt_yuvColorLookup[index].vfmt), +#else "format" , GST_TYPE_FOURCC, qt_yuvColorLookup[index].fourcc, +#endif NULL)); continue; } @@ -532,7 +600,18 @@ GstCaps *QVideoSurfaceGstSink::get_caps(GstBaseSink *base) for (int i = 0; i < count; ++i) { if (qt_rgbColorLookup[i].pixelFormat == format) { GstStructure *structure = gst_structure_new( +#if GST_CHECK_VERSION(1,0,0) + "video/x-raw", + "format" , G_TYPE_STRING, gst_video_format_to_string(gst_video_format_from_masks(qt_rgbColorLookup[i].depth, + qt_rgbColorLookup[i].bitsPerPixel, + qt_rgbColorLookup[i].endianness, + qt_rgbColorLookup[i].red, + qt_rgbColorLookup[i].green, + qt_rgbColorLookup[i].blue, + qt_rgbColorLookup[i].alpha)), +#else "video/x-raw-rgb", +#endif "framerate" , GST_TYPE_FRACTION_RANGE, 0, 1, INT_MAX, 1, "width" , GST_TYPE_INT_RANGE, 1, INT_MAX, "height" , GST_TYPE_INT_RANGE, 1, INT_MAX, @@ -553,6 +632,7 @@ GstCaps *QVideoSurfaceGstSink::get_caps(GstBaseSink *base) } } +// printf("get Caps %"GST_PTR_FORMAT"\n", caps); return caps; } @@ -592,7 +672,7 @@ gboolean QVideoSurfaceGstSink::set_caps(GstBaseSink *base, GstCaps *caps) sink->lastRequestedCaps = 0; #ifdef DEBUG_VIDEO_SURFACE_SINK - qDebug() << "Staring video surface, format:"; + qDebug() << "Starting video surface, format:"; qDebug() << format; qDebug() << "bytesPerLine:" << bytesPerLine; #endif @@ -617,11 +697,49 @@ QVideoSurfaceFormat QVideoSurfaceGstSink::formatForCaps(GstCaps *caps, int *byte gst_structure_get_int(structure, "width", &size.rwidth()); gst_structure_get_int(structure, "height", &size.rheight()); +#if GST_CHECK_VERSION(1, 0, 0) + GstVideoInfo info; + gst_video_info_from_caps(&info, caps); + + if (info.finfo->format == GST_VIDEO_FORMAT_I420) { + int index = indexOfYuvColor(GST_VIDEO_FORMAT_I420); + + if (index != -1) { + pixelFormat = qt_yuvColorLookup[index].pixelFormat; + bitsPerPixel = qt_yuvColorLookup[index].bitsPerPixel; + } + } else if (info.finfo->format == GST_VIDEO_FORMAT_RGBx) { + int depth = 0; + int endianness = 0; + int red = 0; + int green = 0; + int blue = 0; + int alpha = 0; + + gst_structure_get_int(structure, "bpp", &bitsPerPixel); + gst_structure_get_int(structure, "depth", &depth); + gst_structure_get_int(structure, "endianness", &endianness); + gst_structure_get_int(structure, "red_mask", &red); + gst_structure_get_int(structure, "green_mask", &green); + gst_structure_get_int(structure, "blue_mask", &blue); + gst_structure_get_int(structure, "alpha_mask", &alpha); + + int index = indexOfRgbColor(bitsPerPixel, depth, endianness, red, green, blue, alpha); + printf("INDEX %x\n", index); + if (index != -1) + pixelFormat = qt_rgbColorLookup[index].pixelFormat; + } +#else + if (qstrcmp(gst_structure_get_name(structure), "video/x-raw-yuv") == 0) { guint32 fourcc = 0; +#if GST_CHECK_VERSION(1, 0, 0) + int index = indexOfYuvColor(gst_video_format_from_string(gst_structure_get_string(structure, "format"))); +#else gst_structure_get_fourcc(structure, "format", &fourcc); int index = indexOfYuvColor(fourcc); +#endif if (index != -1) { pixelFormat = qt_yuvColorLookup[index].pixelFormat; bitsPerPixel = qt_yuvColorLookup[index].bitsPerPixel; @@ -647,6 +765,7 @@ QVideoSurfaceFormat QVideoSurfaceGstSink::formatForCaps(GstCaps *caps, int *byte if (index != -1) pixelFormat = qt_rgbColorLookup[index].pixelFormat; } +#endif if (pixelFormat != QVideoFrame::Format_Invalid) { QVideoSurfaceFormat format(size, pixelFormat, handleType); @@ -722,7 +841,11 @@ GstFlowReturn QVideoSurfaceGstSink::buffer_alloc( poolLock.unlock(); +#if GST_CHECK_VERSION(1,0,0) + GstCaps *intersection = gst_caps_intersect(get_caps(GST_BASE_SINK(sink), NULL), caps); +#else GstCaps *intersection = gst_caps_intersect(get_caps(GST_BASE_SINK(sink)), caps); +#endif if (gst_caps_is_empty (intersection)) { gst_caps_unref(intersection); @@ -763,7 +886,7 @@ GstFlowReturn QVideoSurfaceGstSink::buffer_alloc( QVideoSurfaceFormat surfaceFormat = sink->delegate->surfaceFormat(); if (!pool->isFormatSupported(surfaceFormat)) { - //qDebug() << "sink doesn't support native pool format, skip custom buffers allocation"; + qDebug() << "sink doesn't support native pool format, skip custom buffers allocation"; return GST_FLOW_OK; } @@ -787,7 +910,6 @@ GstFlowReturn QVideoSurfaceGstSink::buffer_alloc( gboolean QVideoSurfaceGstSink::start(GstBaseSink *base) { Q_UNUSED(base); - return TRUE; } diff --git a/src/multimedia/gsttools_headers/qgstappsrc_p.h b/src/multimedia/gsttools_headers/qgstappsrc_p.h index 4af9252..0e0fc0a 100644 --- a/src/multimedia/gsttools_headers/qgstappsrc_p.h +++ b/src/multimedia/gsttools_headers/qgstappsrc_p.h @@ -39,7 +39,10 @@ #include #include + +#if GST_VERSION_MAJOR < 1 #include +#endif QT_BEGIN_NAMESPACE diff --git a/src/multimedia/gsttools_headers/qgstreameraudioprobecontrol_p.h b/src/multimedia/gsttools_headers/qgstreameraudioprobecontrol_p.h index 34669b8..0f3b165 100644 --- a/src/multimedia/gsttools_headers/qgstreameraudioprobecontrol_p.h +++ b/src/multimedia/gsttools_headers/qgstreameraudioprobecontrol_p.h @@ -47,8 +47,11 @@ class QGstreamerAudioProbeControl : public QMediaAudioProbeControl public: explicit QGstreamerAudioProbeControl(QObject *parent); virtual ~QGstreamerAudioProbeControl(); - +#if GST_CHECK_VERSION(1,0,0) + void bufferProbed(GstBuffer* buffer, GstCaps* caps); +#else void bufferProbed(GstBuffer* buffer); +#endif private slots: void bufferProbed(); diff --git a/src/multimedia/gsttools_headers/qgstreamervideoprobecontrol_p.h b/src/multimedia/gsttools_headers/qgstreamervideoprobecontrol_p.h index 49064f9..fce6309 100644 --- a/src/multimedia/gsttools_headers/qgstreamervideoprobecontrol_p.h +++ b/src/multimedia/gsttools_headers/qgstreamervideoprobecontrol_p.h @@ -48,7 +48,11 @@ public: explicit QGstreamerVideoProbeControl(QObject *parent); virtual ~QGstreamerVideoProbeControl(); +#if GST_CHECK_VERSION(1,0,0) + void bufferProbed(GstBuffer* buffer, GstCaps*); +#else void bufferProbed(GstBuffer* buffer); +#endif void startFlushing(); void stopFlushing(); diff --git a/src/multimedia/gsttools_headers/qgstreamervideowindow_p.h b/src/multimedia/gsttools_headers/qgstreamervideowindow_p.h index 81e5764..c9fdb5c 100644 --- a/src/multimedia/gsttools_headers/qgstreamervideowindow_p.h +++ b/src/multimedia/gsttools_headers/qgstreamervideowindow_p.h @@ -104,7 +104,11 @@ private slots: void updateNativeVideoSize(); private: +#if GST_CHECK_VERSION(1,0,0) + static GstPadProbeReturn padBufferProbe(GstPad *pad, GstPadProbeInfo *info, gpointer user_data); +#else static void padBufferProbe(GstPad *pad, GstBuffer *buffer, gpointer user_data); +#endif GstElement *m_videoSink; WId m_windowId; diff --git a/src/multimedia/gsttools_headers/qgstutils_p.h b/src/multimedia/gsttools_headers/qgstutils_p.h index 65ff759..6015980 100644 --- a/src/multimedia/gsttools_headers/qgstutils_p.h +++ b/src/multimedia/gsttools_headers/qgstutils_p.h @@ -73,7 +73,11 @@ namespace QGstUtils { QSize capsResolution(const GstCaps *caps); QSize capsCorrectedResolution(const GstCaps *caps); QAudioFormat audioFormatForCaps(const GstCaps *caps); +#if GST_CHECK_VERSION(1,0,0) + QAudioFormat audioFormatForSample(GstSample *sample); +#else QAudioFormat audioFormatForBuffer(GstBuffer *buffer); +#endif GstCaps *capsForAudioFormat(QAudioFormat format); void initializeGst(); QMultimedia::SupportEstimate hasSupport(const QString &mimeType, diff --git a/src/multimedia/gsttools_headers/qgstvideobuffer_p.h b/src/multimedia/gsttools_headers/qgstvideobuffer_p.h index 1e0fda8..be48820 100644 --- a/src/multimedia/gsttools_headers/qgstvideobuffer_p.h +++ b/src/multimedia/gsttools_headers/qgstvideobuffer_p.h @@ -71,6 +71,9 @@ private: int m_bytesPerLine; MapMode m_mode; QVariant m_handle; +#if GST_CHECK_VERSION(1,0,0) + GstMapInfo m_mapInfo; +#endif }; QT_END_NAMESPACE diff --git a/src/multimedia/gsttools_headers/qvideosurfacegstsink_p.h b/src/multimedia/gsttools_headers/qvideosurfacegstsink_p.h index 11b305d..01935f7 100644 --- a/src/multimedia/gsttools_headers/qvideosurfacegstsink_p.h +++ b/src/multimedia/gsttools_headers/qvideosurfacegstsink_p.h @@ -131,7 +131,11 @@ private: static GstStateChangeReturn change_state(GstElement *element, GstStateChange transition); - static GstCaps *get_caps(GstBaseSink *sink); + static GstCaps *get_caps(GstBaseSink *sink +#if GST_CHECK_VERSION(1,0,0) + , GstCaps* /*filterCaps*/ +#endif + ); static gboolean set_caps(GstBaseSink *sink, GstCaps *caps); static GstFlowReturn buffer_alloc( diff --git a/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecoderserviceplugin.cpp b/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecoderserviceplugin.cpp index 3098aab..9c54663 100644 --- a/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecoderserviceplugin.cpp +++ b/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecoderserviceplugin.cpp @@ -74,29 +74,42 @@ void QGstreamerAudioDecoderServicePlugin::updateSupportedMimeTypes() const gst_init(NULL, NULL); GList *plugins, *orig_plugins; +#if GST_CHECK_VERSION(1,0,0) + orig_plugins = plugins = gst_registry_get_plugin_list (gst_registry_get()); +#else orig_plugins = plugins = gst_default_registry_get_plugin_list (); - +#endif while (plugins) { GList *features, *orig_features; GstPlugin *plugin = (GstPlugin *) (plugins->data); plugins = g_list_next (plugins); +#if GST_CHECK_VERSION(1,0,0) + if (GST_OBJECT_FLAG_IS_SET(plugin, GST_PLUGIN_FLAG_BLACKLISTED)) + continue; +#else if (plugin->flags & (1<<1)) //GST_PLUGIN_FLAG_BLACKLISTED continue; - - orig_features = features = gst_registry_get_feature_list_by_plugin(gst_registry_get_default (), - plugin->desc.name); +#endif + orig_features = features = gst_registry_get_feature_list_by_plugin(gst_registry_get (), + gst_plugin_get_name(plugin)); while (features) { if (!G_UNLIKELY(features->data == NULL)) { GstPluginFeature *feature = GST_PLUGIN_FEATURE(features->data); if (GST_IS_ELEMENT_FACTORY (feature)) { GstElementFactory *factory = GST_ELEMENT_FACTORY(gst_plugin_feature_load(feature)); if (factory - && factory->numpadtemplates > 0 + && gst_element_factory_get_num_pad_templates(factory) > 0 +#if GST_CHECK_VERSION(1,0,0) + && (qstrcmp(gst_element_factory_get_metadata(factory, GST_ELEMENT_METADATA_KLASS), "Codec/Decoder/Audio") == 0 + || qstrcmp(gst_element_factory_get_metadata(factory, GST_ELEMENT_METADATA_KLASS), "Codec/Demux") == 0 ) +#else && (qstrcmp(factory->details.klass, "Codec/Decoder/Audio") == 0 - || qstrcmp(factory->details.klass, "Codec/Demux") == 0 )) { - const GList *pads = factory->staticpadtemplates; + || qstrcmp(factory->details.klass, "Codec/Demux") == 0 ) +#endif + ) { + const GList *pads = gst_element_factory_get_static_pad_templates(factory); while (pads) { GstStaticPadTemplate *padtemplate = (GstStaticPadTemplate*)(pads->data); pads = g_list_next (pads); diff --git a/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecodersession.cpp b/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecodersession.cpp index f944a60..72d1cf1 100644 --- a/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecodersession.cpp +++ b/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecodersession.cpp @@ -446,21 +446,40 @@ QAudioBuffer QGstreamerAudioDecoderSession::read() if (buffersAvailable == 1) emit bufferAvailableChanged(false); + const char* bufferData = 0; + int bufferSize = 0; + +#if GST_CHECK_VERSION(1,0,0) + GstSample *sample = gst_app_sink_pull_sample(m_appSink); + GstBuffer *buffer = gst_sample_get_buffer(sample); + GstMapInfo mapInfo; + gst_buffer_map(buffer, &mapInfo, GST_MAP_READ); + bufferData = (const char*)mapInfo.data; + bufferSize = mapInfo.size; + QAudioFormat format = QGstUtils::audioFormatForSample(sample); +#else GstBuffer *buffer = gst_app_sink_pull_buffer(m_appSink); - + bufferData = (const char*)buffer->data; + bufferSize = buffer->size; QAudioFormat format = QGstUtils::audioFormatForBuffer(buffer); +#endif + if (format.isValid()) { // XXX At the moment we have to copy data from GstBuffer into QAudioBuffer. // We could improve performance by implementing QAbstractAudioBuffer for GstBuffer. qint64 position = getPositionFromBuffer(buffer); - audioBuffer = QAudioBuffer(QByteArray((const char*)buffer->data, buffer->size), format, position); + audioBuffer = QAudioBuffer(QByteArray((const char*)bufferData, bufferSize), format, position); position /= 1000; // convert to milliseconds if (position != m_position) { m_position = position; emit positionChanged(m_position); } } +#if GST_CHECK_VERSION(1,0,0) + gst_sample_unref(sample); +#else gst_buffer_unref(buffer); +#endif } return audioBuffer; @@ -531,7 +550,12 @@ void QGstreamerAudioDecoderSession::addAppSink() GstAppSinkCallbacks callbacks; memset(&callbacks, 0, sizeof(callbacks)); +#if GST_CHECK_VERSION(1,0,0) + // ### Should perhaps also rename new_buffer to new_sample. + callbacks.new_sample = &new_buffer; +#else callbacks.new_buffer = &new_buffer; +#endif gst_app_sink_set_callbacks(m_appSink, &callbacks, this, NULL); gst_app_sink_set_max_buffers(m_appSink, MAX_BUFFERS_IN_QUEUE); gst_base_sink_set_sync(GST_BASE_SINK(m_appSink), FALSE); @@ -557,8 +581,13 @@ void QGstreamerAudioDecoderSession::updateDuration() gint64 gstDuration = 0; int duration = -1; +#if GST_CHECK_VERSION(1,0,0) + if (m_playbin && gst_element_query_duration(m_playbin, format, &gstDuration)) + duration = gstDuration / 1000000; +#else if (m_playbin && gst_element_query_duration(m_playbin, &format, &gstDuration)) duration = gstDuration / 1000000; +#endif if (m_duration != duration) { m_duration = duration; diff --git a/src/plugins/gstreamer/camerabin/camerabinsession.cpp b/src/plugins/gstreamer/camerabin/camerabinsession.cpp index 1ed663b..e0c6b50 100644 --- a/src/plugins/gstreamer/camerabin/camerabinsession.cpp +++ b/src/plugins/gstreamer/camerabin/camerabinsession.cpp @@ -796,7 +796,11 @@ qint64 CameraBinSession::duration() const if (fileSink) { GstFormat format = GST_FORMAT_TIME; gint64 duration = 0; +#if GST_CHECK_VERSION(1,0,0) + bool ret = gst_element_query_duration(fileSink, format, &duration); +#else bool ret = gst_element_query_position(fileSink, &format, &duration); +#endif gst_object_unref(GST_OBJECT(fileSink)); if (ret) return duration / 1000000; @@ -833,8 +837,13 @@ void CameraBinSession::setMetaData(const QMap &data) if (m_camerabin) { GstIterator *elements = gst_bin_iterate_all_by_interface(GST_BIN(m_camerabin), GST_TYPE_TAG_SETTER); +#if GST_CHECK_VERSION(1,0,0) + GValue *element = 0; + while (gst_iterator_next(elements, element) == GST_ITERATOR_OK) { +#else GstElement *element = 0; while (gst_iterator_next(elements, (void**)&element) == GST_ITERATOR_OK) { +#endif gst_tag_setter_reset_tags(GST_TAG_SETTER(element)); QMapIterator it(data); @@ -895,7 +904,11 @@ bool CameraBinSession::processSyncMessage(const QGstreamerMessage &message) if (gm && GST_MESSAGE_TYPE(gm) == GST_MESSAGE_ELEMENT) { if (m_captureMode == QCamera::CaptureStillImage && +#if GST_CHECK_VERSION(1,0,0) + gst_message_has_name (gm, "preview-image")) { +#else gst_structure_has_name(gm->structure, "preview-image")) { +#endif st = gst_message_get_structure(gm); if (gst_structure_has_field_typed(st, "buffer", GST_TYPE_BUFFER)) { @@ -905,7 +918,11 @@ bool CameraBinSession::processSyncMessage(const QGstreamerMessage &message) QImage img; +#if GST_CHECK_VERSION(1,0,0) GstCaps *caps = gst_buffer_get_caps(buffer); +#else + GstCaps *caps = gst_buffer_get_caps(buffer); +#endif if (caps) { GstStructure *structure = gst_caps_get_structure(caps, 0); gint width = 0; @@ -1178,7 +1195,11 @@ QList< QPair > CameraBinSession::supportedFrameRates(const QSize &frame gst_structure_remove_all_fields(structure); gst_structure_set_value(structure, "framerate", &rate); } +#if GST_CHECK_VERSION(1,0,0) + caps = gst_caps_simplify(caps); +#else gst_caps_do_simplify(caps); +#endif for (uint i=0; i CameraBinSession::supportedResolutions(QPair rate, gst_structure_set_value(structure, "width", &w); gst_structure_set_value(structure, "height", &h); } +#if GST_CHECK_VERSION(1,0,0) + caps = gst_caps_simplify(caps); +#else gst_caps_do_simplify(caps); +#endif for (uint i=0; ishowPrerollFrames(false); // stop showing prerolled frames in stop state } + qWarning() << "Processing EOS!"; + popAndNotifyState(); } diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamerplayerservice.cpp b/src/plugins/gstreamer/mediaplayer/qgstreamerplayerservice.cpp index ce267d7..062de07 100644 --- a/src/plugins/gstreamer/mediaplayer/qgstreamerplayerservice.cpp +++ b/src/plugins/gstreamer/mediaplayer/qgstreamerplayerservice.cpp @@ -51,7 +51,11 @@ #include #if defined(Q_WS_MAEMO_6) && defined(__arm__) -#include "qgstreamergltexturerenderer.h" +#include "private/qgstreamergltexturerenderer.h" +#endif + +#if defined(HAVE_MIR) && defined (__arm__) +#include "private/qgstreamermirtexturerenderer_p.h" #endif #include "qgstreamerstreamscontrol.h" @@ -82,6 +86,9 @@ QGstreamerPlayerService::QGstreamerPlayerService(QObject *parent): #if defined(Q_WS_MAEMO_6) && defined(__arm__) m_videoRenderer = new QGstreamerGLTextureRenderer(this); +#elif defined(HAVE_MIR) && defined (__arm__) + //m_videoRenderer = new QGstreamerVideoRenderer(this); + m_videoRenderer = new QGstreamerMirTextureRenderer(this, m_session); #else m_videoRenderer = new QGstreamerVideoRenderer(this); #endif diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamerplayerserviceplugin.cpp b/src/plugins/gstreamer/mediaplayer/qgstreamerplayerserviceplugin.cpp index 7d20b6d..bf2f9f8 100644 --- a/src/plugins/gstreamer/mediaplayer/qgstreamerplayerserviceplugin.cpp +++ b/src/plugins/gstreamer/mediaplayer/qgstreamerplayerserviceplugin.cpp @@ -87,7 +87,11 @@ void QGstreamerPlayerServicePlugin::updateSupportedMimeTypes() const gst_init(NULL, NULL); GList *plugins, *orig_plugins; +#if GST_CHECK_VERSION(1,0,0) + orig_plugins = plugins = gst_registry_get_plugin_list (gst_registry_get()); +#else orig_plugins = plugins = gst_default_registry_get_plugin_list (); +#endif while (plugins) { GList *features, *orig_features; @@ -95,22 +99,33 @@ void QGstreamerPlayerServicePlugin::updateSupportedMimeTypes() const GstPlugin *plugin = (GstPlugin *) (plugins->data); plugins = g_list_next (plugins); +#if GST_CHECK_VERSION(1,0,0) + if (GST_OBJECT_FLAG_IS_SET(plugin, GST_PLUGIN_FLAG_BLACKLISTED)) + continue; +#else if (plugin->flags & (1<<1)) //GST_PLUGIN_FLAG_BLACKLISTED continue; +#endif - orig_features = features = gst_registry_get_feature_list_by_plugin(gst_registry_get_default (), - plugin->desc.name); + orig_features = features = gst_registry_get_feature_list_by_plugin(gst_registry_get(), + gst_plugin_get_name(plugin)); while (features) { if (!G_UNLIKELY(features->data == NULL)) { GstPluginFeature *feature = GST_PLUGIN_FEATURE(features->data); if (GST_IS_ELEMENT_FACTORY (feature)) { GstElementFactory *factory = GST_ELEMENT_FACTORY(gst_plugin_feature_load(feature)); if (factory - && factory->numpadtemplates > 0 - && (qstrcmp(factory->details.klass, "Codec/Decoder/Audio") == 0 +#if GST_CHECK_VERSION(1,0,0) + && (qstrcmp(gst_element_factory_get_metadata(factory, GST_ELEMENT_METADATA_KLASS), "Codec/Decoder/Audio") == 0 + || qstrcmp(gst_element_factory_get_metadata(factory, GST_ELEMENT_METADATA_KLASS),"Codec/Decoder/Video") == 0 + || qstrcmp(gst_element_factory_get_metadata(factory, GST_ELEMENT_METADATA_KLASS), "Codec/Demux") == 0 ) +#else + && (qstrcmp(factory->details.klass, "Codec/Decoder/Audio") == 0 || qstrcmp(factory->details.klass, "Codec/Decoder/Video") == 0 - || qstrcmp(factory->details.klass, "Codec/Demux") == 0 )) { - const GList *pads = factory->staticpadtemplates; + || qstrcmp(factory->details.klass, "Codec/Demux") == 0 ) +#endif + ) { + const GList *pads = gst_element_factory_get_static_pad_templates(factory); while (pads) { GstStaticPadTemplate *padtemplate = (GstStaticPadTemplate*)(pads->data); pads = g_list_next (pads); diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp b/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp index 15924a6..8013d0d 100644 --- a/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp +++ b/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp @@ -85,6 +85,16 @@ typedef enum { GST_PLAY_FLAG_BUFFERING = 0x000000100 } GstPlayFlags; +#if GST_CHECK_VERSION(1,0,0) +#define DEFAULT_RAW_CAPS \ + "video/x-surface; " \ + "text/plain; " \ + "text/x-pango-markup; " \ + "video/x-dvd-subpicture; " \ + "subpicture/x-pgs" \ + "video/x-raw" \ + "audio/x-raw" +#else #define DEFAULT_RAW_CAPS \ "video/x-raw-yuv; " \ "video/x-raw-rgb; " \ @@ -97,6 +107,8 @@ typedef enum { "text/x-pango-markup; " \ "video/x-dvd-subpicture; " \ "subpicture/x-pgs" +#endif + static GstStaticCaps static_RawCaps = GST_STATIC_CAPS(DEFAULT_RAW_CAPS); QGstreamerPlayerSession::QGstreamerPlayerSession(QObject *parent) @@ -137,8 +149,11 @@ QGstreamerPlayerSession::QGstreamerPlayerSession(QObject *parent) gboolean result = gst_type_find_register(0, "playlist", GST_RANK_MARGINAL, playlistTypeFindFunction, 0, 0, this, 0); Q_ASSERT(result == TRUE); Q_UNUSED(result); - +#if GST_CHECK_VERSION(1,0,0) + m_playbin = gst_element_factory_make("playbin", NULL); +#else m_playbin = gst_element_factory_make("playbin2", NULL); +#endif if (m_playbin) { //GST_PLAY_FLAG_NATIVE_VIDEO omits configuration of ffmpegcolorspace and videoscale, @@ -188,7 +203,11 @@ QGstreamerPlayerSession::QGstreamerPlayerSession(QObject *parent) m_videoIdentity = GST_ELEMENT(g_object_new(gst_video_connector_get_type(), 0)); // floating ref g_signal_connect(G_OBJECT(m_videoIdentity), "connection-failed", G_CALLBACK(insertColorSpaceElement), (gpointer)this); +#if GST_CHECK_VERSION(1,0,0) + m_colorSpace = gst_element_factory_make("videoconvert", "ffmpegcolorspace-vo"); +#else m_colorSpace = gst_element_factory_make("ffmpegcolorspace", "ffmpegcolorspace-vo"); +#endif // might not get a parent, take ownership to avoid leak qt_gst_object_ref_sink(GST_OBJECT(m_colorSpace)); @@ -206,7 +225,7 @@ QGstreamerPlayerSession::QGstreamerPlayerSession(QObject *parent) // add ghostpads GstPad *pad = gst_element_get_static_pad(m_videoIdentity,"sink"); - gst_element_add_pad(GST_ELEMENT(m_videoOutputBin), gst_ghost_pad_new("videosink", pad)); + gst_element_add_pad(GST_ELEMENT(m_videoOutputBin), gst_ghost_pad_new("sink", pad)); gst_object_unref(GST_OBJECT(pad)); if (m_playbin != 0) { @@ -218,7 +237,7 @@ QGstreamerPlayerSession::QGstreamerPlayerSession(QObject *parent) g_object_set(G_OBJECT(m_playbin), "video-sink", m_videoOutputBin, NULL); g_signal_connect(G_OBJECT(m_playbin), "notify::source", G_CALLBACK(playbinNotifySource), this); - g_signal_connect(G_OBJECT(m_playbin), "element-added", G_CALLBACK(handleElementAdded), this); + //g_signal_connect(G_OBJECT(m_playbin), "element-added", G_CALLBACK(handleElementAdded), this); if (usePlaybinVolume()) { updateVolume(); @@ -342,9 +361,13 @@ qint64 QGstreamerPlayerSession::position() const GstFormat format = GST_FORMAT_TIME; gint64 position = 0; +#if GST_CHECK_VERSION(1,0,0) + if ( m_playbin && gst_element_query_position(m_playbin, format, &position)) + m_lastPosition = position / 1000000; +#else if ( m_playbin && gst_element_query_position(m_playbin, &format, &position)) m_lastPosition = position / 1000000; - +#endif return m_lastPosition; } @@ -474,9 +497,18 @@ bool QGstreamerPlayerSession::isAudioAvailable() const return m_audioAvailable; } +#if GST_CHECK_VERSION(1,0,0) +static GstPadProbeReturn block_pad_cb(GstPad *pad, GstPadProbeInfo *info, gpointer user_data) +#else static void block_pad_cb(GstPad *pad, gboolean blocked, gpointer user_data) +#endif { Q_UNUSED(pad); +#if GST_CHECK_VERSION(1,0,0) + Q_UNUSED(info); + Q_UNUSED(user_data); + return GST_PAD_PROBE_OK; +#else #ifdef DEBUG_PLAYBIN qDebug() << "block_pad_cb, blocked:" << blocked; #endif @@ -485,6 +517,7 @@ static void block_pad_cb(GstPad *pad, gboolean blocked, gpointer user_data) QGstreamerPlayerSession *session = reinterpret_cast(user_data); QMetaObject::invokeMethod(session, "finishVideoOutputChange", Qt::QueuedConnection); } +#endif } void QGstreamerPlayerSession::updateVideoRenderer() @@ -529,7 +562,7 @@ void QGstreamerPlayerSession::setVideoRenderer(QObject *videoOutput) m_renderer = renderer; #ifdef DEBUG_VO_BIN_DUMP - _gst_debug_bin_to_dot_file_with_ts(GST_BIN(m_playbin), + gst_debug_bin_to_dot_file_with_ts(GST_BIN(m_playbin), GstDebugGraphDetails(GST_DEBUG_GRAPH_SHOW_ALL /* GST_DEBUG_GRAPH_SHOW_MEDIA_TYPE | GST_DEBUG_GRAPH_SHOW_NON_DEFAULT_PARAMS | GST_DEBUG_GRAPH_SHOW_STATES*/), "playbin_set"); #endif @@ -633,7 +666,11 @@ void QGstreamerPlayerSession::setVideoRenderer(QObject *videoOutput) //block pads, async to avoid locking in paused state GstPad *srcPad = gst_element_get_static_pad(m_videoIdentity, "src"); +#if GST_CHECK_VERSION(1,0,0) + this->pad_probe_id = gst_pad_add_probe(srcPad, (GstPadProbeType)(GST_PAD_PROBE_TYPE_BUFFER | GST_PAD_PROBE_TYPE_BLOCK), block_pad_cb, this, NULL); +#else gst_pad_set_blocked_async(srcPad, true, &block_pad_cb, this); +#endif gst_object_unref(GST_OBJECT(srcPad)); //Unpause the sink to avoid waiting until the buffer is processed @@ -674,7 +711,11 @@ void QGstreamerPlayerSession::finishVideoOutputChange() //video output was change back to the current one, //no need to torment the pipeline, just unblock the pad if (gst_pad_is_blocked(srcPad)) +#if GST_CHECK_VERSION(1,0,0) + gst_pad_remove_probe(srcPad, this->pad_probe_id); +#else gst_pad_set_blocked_async(srcPad, false, &block_pad_cb, 0); +#endif m_pendingVideoSink = 0; gst_object_unref(GST_OBJECT(srcPad)); @@ -760,12 +801,17 @@ void QGstreamerPlayerSession::finishVideoOutputChange() //don't have to wait here, it will unblock eventually if (gst_pad_is_blocked(srcPad)) - gst_pad_set_blocked_async(srcPad, false, &block_pad_cb, 0); +#if GST_CHECK_VERSION(1,0,0) + gst_pad_remove_probe(srcPad, this->pad_probe_id); +#else + gst_pad_set_blocked_async(srcPad, false, &block_pad_cb, 0); +#endif + gst_object_unref(GST_OBJECT(srcPad)); #ifdef DEBUG_VO_BIN_DUMP - _gst_debug_bin_to_dot_file_with_ts(GST_BIN(m_playbin), - GstDebugGraphDetails(GST_DEBUG_GRAPH_SHOW_ALL /* GST_DEBUG_GRAPH_SHOW_MEDIA_TYPE | GST_DEBUG_GRAPH_SHOW_NON_DEFAULT_PARAMS | GST_DEBUG_GRAPH_SHOW_STATES*/), + gst_debug_bin_to_dot_file_with_ts(GST_BIN(m_playbin), + GstDebugGraphDetails(GST_DEBUG_GRAPH_SHOW_ALL /* | GST_DEBUG_GRAPH_SHOW_MEDIA_TYPE | GST_DEBUG_GRAPH_SHOW_NON_DEFAULT_PARAMS | GST_DEBUG_GRAPH_SHOW_STATES */), "playbin_finish"); #endif } @@ -830,6 +876,7 @@ bool QGstreamerPlayerSession::play() #ifdef DEBUG_PLAYBIN qDebug() << Q_FUNC_INFO; #endif + m_everPlayed = false; if (m_playbin) { m_pendingState = QMediaPlayer::PlayingState; @@ -1327,8 +1374,11 @@ void QGstreamerPlayerSession::getStreamsInfo() default: break; } - +#if GST_CHECK_VERSION(1,0,0) + if (tags && GST_IS_TAG_LIST(tags)) { +#else if (tags && gst_is_tag_list(tags)) { +#endif gchar *languageCode = 0; if (gst_tag_list_get_string(tags, GST_TAG_LANGUAGE_CODE, &languageCode)) streamProperties[QMediaMetaData::Language] = QString::fromUtf8(languageCode); @@ -1367,7 +1417,11 @@ void QGstreamerPlayerSession::updateVideoResolutionTag() QSize aspectRatio; GstPad *pad = gst_element_get_static_pad(m_videoIdentity, "src"); +#if GST_CHECK_VERSION(1,0,0) + GstCaps *caps = gst_pad_get_current_caps(pad); +#else GstCaps *caps = gst_pad_get_negotiated_caps(pad); +#endif if (caps) { const GstStructure *structure = gst_caps_get_structure(caps, 0); @@ -1411,7 +1465,11 @@ void QGstreamerPlayerSession::updateDuration() gint64 gstDuration = 0; int duration = -1; +#if GST_CHECK_VERSION(1,0,0) + if (m_playbin && gst_element_query_duration(m_playbin, format, &gstDuration)) +#else if (m_playbin && gst_element_query_duration(m_playbin, &format, &gstDuration)) +#endif duration = gstDuration / 1000000; if (m_duration != duration) { @@ -1467,7 +1525,11 @@ void QGstreamerPlayerSession::playbinNotifySource(GObject *o, GParamSpec *p, gpo // The rest if (g_object_class_find_property(G_OBJECT_GET_CLASS(source), "extra-headers") != 0) { +#if GST_CHECK_VERSION(1,0,0) + GstStructure *extras = gst_structure_new_empty("extras"); +#else GstStructure *extras = gst_structure_empty_new("extras"); +#endif foreach (const QByteArray &rawHeader, self->m_request.rawHeaderList()) { if (rawHeader == userAgentString) // Filter User-Agent @@ -1623,7 +1685,11 @@ GstAutoplugSelectResult QGstreamerPlayerSession::handleAutoplugSelect(GstBin *bi const gchar *factoryName = gst_plugin_feature_get_name(GST_PLUGIN_FEATURE(factory)); if (g_str_has_prefix(factoryName, "vaapi")) { GstPad *sinkPad = gst_element_get_static_pad(session->m_videoSink, "sink"); +#if GST_CHECK_VERSION(1,0,0) + GstCaps *sinkCaps = gst_pad_query_caps(sinkPad, NULL); +#else GstCaps *sinkCaps = gst_pad_get_caps(sinkPad); +#endif #if (GST_VERSION_MAJOR == 0) && ((GST_VERSION_MINOR < 10) || (GST_VERSION_MICRO < 33)) if (!factory_can_src_any_caps(factory, sinkCaps)) @@ -1652,14 +1718,19 @@ void QGstreamerPlayerSession::handleElementAdded(GstBin *bin, GstElement *elemen // Disable on-disk buffering. g_object_set(G_OBJECT(element), "temp-template", NULL, NULL); } else if (g_str_has_prefix(elementName, "uridecodebin") || - g_str_has_prefix(elementName, "decodebin2")) { - +#if GST_CHECK_VERSION(1,0,0) + g_str_has_prefix(elementName, "decodebin")) { +#else + g_str_has_prefix(elementName, "decodebin2")) { +#endif if (g_str_has_prefix(elementName, "uridecodebin")) { // Add video/x-surface (VAAPI) to default raw formats g_object_set(G_OBJECT(element), "caps", gst_static_caps_get(&static_RawCaps), NULL); // listen for uridecodebin autoplug-select to skip VAAPI usage when the current // video sink doesn't support it +#if !(GST_CHECK_VERSION(1,0,0)) g_signal_connect(element, "autoplug-select", G_CALLBACK(handleAutoplugSelect), session); +#endif } //listen for queue2 element added to uridecodebin/decodebin2 as well. @@ -1727,7 +1798,27 @@ void QGstreamerPlayerSession::removeProbe(QGstreamerVideoProbeControl* probe) // Assume user releases any outstanding references to video frames. } -gboolean QGstreamerPlayerSession::padVideoBufferProbe(GstPad *pad, GstBuffer *buffer, gpointer user_data) +#if GST_CHECK_VERSION(1,0,0) +GstPadProbeReturn QGstreamerPlayerSession::padVideoBufferProbe(GstPad *pad, GstPadProbeInfo *info, gpointer user_data) +{ + Q_UNUSED(pad); + GstBuffer* buffer = GST_PAD_PROBE_INFO_BUFFER(info); + + QGstreamerPlayerSession *session = reinterpret_cast(user_data); + QMutexLocker locker(&session->m_videoProbeMutex); + + if (session->m_videoProbes.isEmpty()) + return GST_PAD_PROBE_OK; + + foreach (QGstreamerVideoProbeControl* probe, session->m_videoProbes) + probe->bufferProbed(buffer, gst_pad_get_current_caps(pad)); + + return GST_PAD_PROBE_OK; +} + +#else + +static gboolean QGstreamerPlayerSession::padVideoBufferProbe(GstPad *pad, GstBuffer *buffer, gpointer user_data) { Q_UNUSED(pad); @@ -1742,6 +1833,7 @@ gboolean QGstreamerPlayerSession::padVideoBufferProbe(GstPad *pad, GstBuffer *bu return TRUE; } +#endif void QGstreamerPlayerSession::addProbe(QGstreamerAudioProbeControl* probe) { @@ -1759,6 +1851,24 @@ void QGstreamerPlayerSession::removeProbe(QGstreamerAudioProbeControl* probe) m_audioProbes.removeOne(probe); } +#if GST_CHECK_VERSION(1,0,0) +GstPadProbeReturn QGstreamerPlayerSession::padAudioBufferProbe(GstPad *pad, GstPadProbeInfo* info, gpointer user_data) +{ + Q_UNUSED(pad); + GstBuffer* buffer = GST_PAD_PROBE_INFO_BUFFER(info); + + QGstreamerPlayerSession *session = reinterpret_cast(user_data); + QMutexLocker locker(&session->m_audioProbeMutex); + + if (session->m_audioProbes.isEmpty()) + return GST_PAD_PROBE_OK; + + foreach (QGstreamerAudioProbeControl* probe, session->m_audioProbes) + probe->bufferProbed(buffer, gst_pad_get_current_caps(pad)); + + return GST_PAD_PROBE_OK; +} +#else gboolean QGstreamerPlayerSession::padAudioBufferProbe(GstPad *pad, GstBuffer *buffer, gpointer user_data) { Q_UNUSED(pad); @@ -1774,7 +1884,7 @@ gboolean QGstreamerPlayerSession::padAudioBufferProbe(GstPad *pad, GstBuffer *bu return TRUE; } - +#endif // This function is similar to stop(), // but does not set m_everPlayed, m_lastPosition, // and setSeekable() values. @@ -1807,7 +1917,11 @@ void QGstreamerPlayerSession::removeVideoBufferProbe() GstPad *pad = gst_element_get_static_pad(m_videoSink, "sink"); if (pad) { +#if GST_CHECK_VERSION(1,0,0) + gst_pad_remove_probe(pad, m_videoBufferProbeId); +#else gst_pad_remove_buffer_probe(pad, m_videoBufferProbeId); +#endif gst_object_unref(GST_OBJECT(pad)); } @@ -1822,7 +1936,11 @@ void QGstreamerPlayerSession::addVideoBufferProbe() GstPad *pad = gst_element_get_static_pad(m_videoSink, "sink"); if (pad) { +#if GST_CHECK_VERSION(1,0,0) + m_videoBufferProbeId = gst_pad_add_probe(pad, GST_PAD_PROBE_TYPE_BUFFER, padVideoBufferProbe, this, NULL); +#else m_videoBufferProbeId = gst_pad_add_buffer_probe(pad, G_CALLBACK(padVideoBufferProbe), this); +#endif gst_object_unref(GST_OBJECT(pad)); } } @@ -1839,7 +1957,11 @@ void QGstreamerPlayerSession::removeAudioBufferProbe() GstPad *pad = gst_element_get_static_pad(m_audioSink, "sink"); if (pad) { +#if GST_CHECK_VERSION(1,0,0) + gst_pad_remove_probe(pad, m_audioBufferProbeId); +#else gst_pad_remove_buffer_probe(pad, m_audioBufferProbeId); +#endif gst_object_unref(GST_OBJECT(pad)); } @@ -1854,7 +1976,11 @@ void QGstreamerPlayerSession::addAudioBufferProbe() GstPad *pad = gst_element_get_static_pad(m_audioSink, "sink"); if (pad) { +#if GST_CHECK_VERSION(1,0,0) + m_audioBufferProbeId = gst_pad_add_probe(pad, GST_PAD_PROBE_TYPE_BUFFER, padAudioBufferProbe, this, NULL); +#else m_audioBufferProbeId = gst_pad_add_buffer_probe(pad, G_CALLBACK(padAudioBufferProbe), this); +#endif gst_object_unref(GST_OBJECT(pad)); } } @@ -1887,7 +2013,7 @@ void QGstreamerPlayerSession::playlistTypeFindFunction(GstTypeFind *find, gpoint length = qMin(length, guint64(1024)); while (length > 0) { - guint8 *data = gst_type_find_peek(find, 0, length); + const guint8 *data = gst_type_find_peek(find, 0, length); if (data) { session->m_isPlaylist = (QPlaylistFileParser::findPlaylistType(QString::fromUtf8(uri), 0, data, length) != QPlaylistFileParser::UNKNOWN); return; diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.h b/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.h index f2e760a..50bda3d 100644 --- a/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.h +++ b/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.h @@ -119,11 +119,19 @@ public: void addProbe(QGstreamerVideoProbeControl* probe); void removeProbe(QGstreamerVideoProbeControl* probe); +#if GST_CHECK_VERSION(1,0,0) + static GstPadProbeReturn padVideoBufferProbe(GstPad *pad, GstPadProbeInfo *info, gpointer user_data); +#else static gboolean padVideoBufferProbe(GstPad *pad, GstBuffer *buffer, gpointer user_data); +#endif void addProbe(QGstreamerAudioProbeControl* probe); void removeProbe(QGstreamerAudioProbeControl* probe); +#if GST_CHECK_VERSION(1,0,0) + static GstPadProbeReturn padAudioBufferProbe(GstPad *pad, GstPadProbeInfo* info, gpointer user_data); +#else static gboolean padAudioBufferProbe(GstPad *pad, GstBuffer *buffer, gpointer user_data); +#endif void endOfMediaReset(); @@ -252,6 +260,7 @@ private: bool m_isLiveSource; bool m_isPlaylist; + gulong pad_probe_id; }; QT_END_NAMESPACE -- 2.3.1