diff options
author | Yoann Lopes <yoann.lopes@digia.com> | 2013-10-31 15:06:30 +0100 |
---|---|---|
committer | Tomasz Olszak <olszak.tomasz@gmail.com> | 2014-03-13 20:37:36 +0100 |
commit | d91dac090d92fdbc3a3425e8d969c62e5c79eff9 (patch) | |
tree | d08b3c1b47a54036cc5c5fe7e47a6540052e21b2 | |
parent | 4bb51fef0a5da88a75d5ba593557367b990ccab5 (diff) | |
download | qtmultimedia-d91dac090d92fdbc3a3425e8d969c62e5c79eff9.tar.gz qtmultimedia-d91dac090d92fdbc3a3425e8d969c62e5c79eff9.tar.bz2 qtmultimedia-d91dac090d92fdbc3a3425e8d969c62e5c79eff9.zip |
Initial porting effort to GStreamer 1.0.upstream/5.2.90+alpha
Imported from git@github.com:jhodapp/qtmultimedia.git
Contributions from:
Ilya Smelykh <ilya@videoexpertsgroup.com>
Jim Hodapp <jim.hodapp@canonical.com>
Sergio Schvezov <sergio.schvezov@canonical.com>
Change-Id: I10fa5e5078efa4564ce833befd417008e26a90a9
Reviewed-by: Yoann Lopes <yoann.lopes@digia.com>
38 files changed, 1378 insertions, 139 deletions
diff --git a/config.tests/gstreamer/gstreamer.pro b/config.tests/gstreamer/gstreamer.pro index 02a7e340..6b9843ac 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 9f617036..0f3ca2b1 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 7e8a9e7a..fad40b0b 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 6b530cb7..975991f9 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 1deaab2a..0b7b4fc5 100644 --- a/qtmultimedia.pro +++ b/qtmultimedia.pro @@ -21,10 +21,24 @@ win32 { } else { qtCompileTest(alsa) qtCompileTest(pulseaudio) - qtCompileTest(gstreamer) { - qtCompileTest(gstreamer_photography) - qtCompileTest(gstreamer_encodingprofiles) - qtCompileTest(gstreamer_appsrc) + !done_config_gstreamer { + gstver=1.0 + cache(GST_VERSION, set, gstver); + qtCompileTest(gstreamer) { + qtCompileTest(gstreamer_photography) + qtCompileTest(gstreamer_encodingprofiles) + qtCompileTest(gstreamer_appsrc) + } 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(resourcepolicy) qtCompileTest(gpu_vivante) diff --git a/src/gsttools/gsttools.pro b/src/gsttools/gsttools.pro index 46184965..4ca9f5a5 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 multimedia-private gui-private +QT = core multimedia-private gui-private opengl !static:DEFINES += QT_MAKEDLL @@ -14,13 +14,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 @@ -32,8 +33,10 @@ 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/ +# FIXME: Move qgstreamermirtexturerenderer_p.h and .c to section like maemo6 PRIVATE_HEADERS += \ qgstbufferpoolinterface_p.h \ qgstreamerbushelper_p.h \ @@ -89,14 +92,24 @@ maemo6 { } } +mir: { + contains(QT_CONFIG, opengles2):qtHaveModule(widgets) { + PRIVATE_HEADERS += qgstreamermirtexturerenderer_p.h + SOURCES += qgstreamermirtexturerenderer.cpp + QT += opengl quick + LIBS += -lEGL + } + DEFINES += HAVE_MIR +} + 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 } HEADERS += $$PRIVATE_HEADERS diff --git a/src/gsttools/gstvideoconnector.c b/src/gsttools/gstvideoconnector.c index 3e08fe53..ff3f9a36 100644 --- a/src/gsttools/gstvideoconnector.c +++ b/src/gsttools/gstvideoconnector.c @@ -67,26 +67,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 <dmytro.poplavskiy@nokia.com>"); + 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) @@ -128,18 +195,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, @@ -148,14 +230,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; @@ -183,9 +274,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 @@ -229,6 +327,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; } } @@ -301,6 +400,7 @@ static GstCaps *gst_video_connector_getcaps (GstPad * pad) return caps; } + static gboolean gst_video_connector_acceptcaps (GstPad * pad, GstCaps * caps) { GstVideoConnector *element; @@ -308,6 +408,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) @@ -319,11 +420,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); @@ -335,16 +464,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 { @@ -356,20 +492,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)) { @@ -432,8 +577,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); @@ -448,9 +596,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)); @@ -461,7 +632,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 %" @@ -469,9 +639,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 8917bda8..9fd090df 100644 --- a/src/gsttools/qgstappsrc.cpp +++ b/src/gsttools/qgstappsrc.cpp @@ -151,23 +151,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 94d07c9f..8c859730 100644 --- a/src/gsttools/qgstreameraudioprobecontrol.cpp +++ b/src/gsttools/qgstreameraudioprobecontrol.cpp @@ -53,9 +53,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; @@ -64,8 +69,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 da7506ec..6b4cdd29 100644 --- a/src/gsttools/qgstreamerbushelper.cpp +++ b/src/gsttools/qgstreamerbushelper.cpp @@ -162,13 +162,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/qgstreamermirtexturerenderer.cpp b/src/gsttools/qgstreamermirtexturerenderer.cpp new file mode 100644 index 00000000..51563937 --- /dev/null +++ b/src/gsttools/qgstreamermirtexturerenderer.cpp @@ -0,0 +1,360 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Canonical Ltd. +** Contact: jim.hodapp@canonical.com +** +** This file is part of the Qt Toolkit. +** +// TODO: Fix this license +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qgstreamermirtexturerenderer_p.h" + +#include <qgstreamerplayersession.h> +#include <private/qvideosurfacegstsink_p.h> +#include <private/qgstutils_p.h> +#include <qabstractvideosurface.h> + +#include <QAbstractVideoBuffer> +#include <QGuiApplication> +#include <QDebug> +#include <QtQuick/QQuickWindow> +#include <QOpenGLContext> +#include <QGLContext> +#include <QGuiApplication> +#include <qgl.h> + +#include <gst/gst.h> + +static QGstreamerMirTextureRenderer *rendererInstance = NULL; + +class QGstreamerMirTextureBuffer : public QAbstractVideoBuffer +{ +public: + QGstreamerMirTextureBuffer(GLuint textureId) : + QAbstractVideoBuffer(QAbstractVideoBuffer::GLTextureHandle), + m_textureId(textureId) + { + } + + MapMode mapMode() const { return NotMapped; } + + uchar *map(MapMode mode, int *numBytes, int *bytesPerLine) + { + qDebug() << Q_FUNC_INFO; + Q_UNUSED(mode); + Q_UNUSED(numBytes); + Q_UNUSED(bytesPerLine); + + return NULL; + } + + void unmap() { qDebug() << Q_FUNC_INFO; } + + QVariant handle() const { return QVariant::fromValue<unsigned int>(m_textureId); } + + GLuint textureId() { return m_textureId; } + +private: + GLuint m_textureId; +}; + +QGstreamerMirTextureRenderer::QGstreamerMirTextureRenderer(QObject *parent + , const QGstreamerPlayerSession *playerSession) + : QVideoRendererControl(0), m_videoSink(0), m_surface(0), + m_glSurface(0), + m_context(0), + m_glContext(0), + m_textureId(0), + m_offscreenSurface(0), + m_textureBuffer(0) +{ + Q_UNUSED(parent); + setPlayerSession(playerSession); +} + +QGstreamerMirTextureRenderer::~QGstreamerMirTextureRenderer() +{ + if (m_videoSink) + gst_object_unref(GST_OBJECT(m_videoSink)); + + delete m_glContext; + delete m_offscreenSurface; +} + +GstElement *QGstreamerMirTextureRenderer::videoSink() +{ + qDebug() << Q_FUNC_INFO; + + // FIXME: Ugly hack until I figure out why passing this segfaults in the g_signal handler + rendererInstance = const_cast<QGstreamerMirTextureRenderer*>(this); + + if (!m_videoSink && m_surface) { + qDebug() << Q_FUNC_INFO << ": using mirsink, (this: " << this << ")"; + + m_videoSink = gst_element_factory_make("mirsink", "video-output"); + + connect(QGuiApplication::instance(), SIGNAL(focusWindowChanged(QWindow*)), + this, SLOT(handleFocusWindowChanged(QWindow*)), Qt::QueuedConnection); + + g_signal_connect(G_OBJECT(m_videoSink), "frame-ready", G_CALLBACK(handleFrameReady), + (gpointer)this); + } + + if (m_videoSink) { + gst_object_ref_sink(GST_OBJECT(m_videoSink)); + + GstPad *pad = gst_element_get_static_pad(m_videoSink, "sink"); + gst_pad_add_probe(pad, GST_PAD_PROBE_TYPE_BUFFER, + padBufferProbe, this, NULL); + } + + return m_videoSink; +} + +QWindow *QGstreamerMirTextureRenderer::createOffscreenWindow(const QSurfaceFormat &format) +{ + QWindow *w = new QWindow(); + w->setSurfaceType(QWindow::OpenGLSurface); + w->setFormat(format); + w->setGeometry(0, 0, 1, 1); + w->setFlags(w->flags() | Qt::WindowTransparentForInput); + w->create(); + + return w; +} + +void QGstreamerMirTextureRenderer::handleFrameReady(gpointer userData) +{ + QGstreamerMirTextureRenderer *renderer = reinterpret_cast<QGstreamerMirTextureRenderer*>(userData); +#if 1 + QMutexLocker locker(&rendererInstance->m_mutex); + QMetaObject::invokeMethod(rendererInstance, "renderFrame", Qt::QueuedConnection); +#else + // FIXME! + //QMutexLocker locker(&renderer->m_mutex); + QMetaObject::invokeMethod(renderer, "renderFrame", Qt::QueuedConnection); +#endif +} + +void QGstreamerMirTextureRenderer::renderFrame() +{ + //qDebug() << Q_FUNC_INFO; + + if (m_context) + m_context->makeCurrent(); + + GstState pendingState = GST_STATE_NULL; + GstState newState = GST_STATE_NULL; + // Don't block and return immediately: + GstStateChangeReturn ret = gst_element_get_state(m_videoSink, &newState, + &pendingState, 0); + if (ret == GST_STATE_CHANGE_FAILURE || newState == GST_STATE_NULL|| + pendingState == GST_STATE_NULL) { + qWarning() << "Invalid state change for renderer, aborting"; + stopRenderer(); + return; + } + + if (!m_surface->isActive()) { + qDebug() << "m_surface is not active"; + GstPad *pad = gst_element_get_static_pad(m_videoSink, "sink"); + GstCaps *caps = gst_pad_get_current_caps(pad); + + if (caps) { + // Get the native video size from the video sink + QSize newNativeSize = QGstUtils::capsCorrectedResolution(caps); + if (m_nativeSize != newNativeSize) { + m_nativeSize = newNativeSize; + emit nativeSizeChanged(); + } + gst_caps_unref(caps); + } + + // Start the surface + QVideoSurfaceFormat format(m_nativeSize, QVideoFrame::Format_RGB32, QAbstractVideoBuffer::GLTextureHandle); + qDebug() << "m_nativeSize: " << m_nativeSize; + qDebug() << "format: " << format; + if (!m_surface->start(format)) { + qWarning() << Q_FUNC_INFO << ": failed to start the video surface " << format; + return; + } + } + + QGstreamerMirTextureBuffer *buffer = new QGstreamerMirTextureBuffer(m_textureId); + //qDebug() << "frameSize: " << m_surface->surfaceFormat().frameSize(); + QVideoFrame frame(buffer, m_surface->surfaceFormat().frameSize(), + m_surface->surfaceFormat().pixelFormat()); + + frame.setMetaData("TextureId", m_textureId); + + // Display the video frame on the surface: + m_surface->present(frame); +} + +GstPadProbeReturn QGstreamerMirTextureRenderer::padBufferProbe(GstPad *pad, GstPadProbeInfo *info, gpointer userData) +{ + Q_UNUSED(pad); + Q_UNUSED(info); + + QGstreamerMirTextureRenderer *control = reinterpret_cast<QGstreamerMirTextureRenderer*>(userData); + QMetaObject::invokeMethod(control, "updateNativeVideoSize", Qt::QueuedConnection); + + return GST_PAD_PROBE_REMOVE; +} + +void QGstreamerMirTextureRenderer::stopRenderer() +{ + if (m_surface) + m_surface->stop(); +} + +QAbstractVideoSurface *QGstreamerMirTextureRenderer::surface() const +{ + return m_surface; +} + +void QGstreamerMirTextureRenderer::setSurface(QAbstractVideoSurface *surface) +{ + qDebug() << Q_FUNC_INFO; + + if (m_surface != surface) { + qDebug() << "Saving current QGLContext"; + m_context = const_cast<QGLContext*>(QGLContext::currentContext()); + + if (m_videoSink) + gst_object_unref(GST_OBJECT(m_videoSink)); + + m_videoSink = 0; + + if (m_surface) { + disconnect(m_surface.data(), SIGNAL(supportedFormatsChanged()), + this, SLOT(handleFormatChange())); + } + + bool wasReady = isReady(); + + m_surface = surface; + + if (m_surface) { + connect(m_surface.data(), SIGNAL(supportedFormatsChanged()), + this, SLOT(handleFormatChange())); + } + + if (wasReady != isReady()) + emit readyChanged(isReady()); + + emit sinkChanged(); + } +} + +void QGstreamerMirTextureRenderer::setPlayerSession(const QGstreamerPlayerSession *playerSession) +{ + m_playerSession = const_cast<QGstreamerPlayerSession*>(playerSession); +} + +void QGstreamerMirTextureRenderer::handleFormatChange() +{ + qDebug() << "Supported formats list has changed, reload video output"; + + if (m_videoSink) + gst_object_unref(GST_OBJECT(m_videoSink)); + + m_videoSink = 0; + emit sinkChanged(); +} + +void QGstreamerMirTextureRenderer::updateNativeVideoSize() +{ + //qDebug() << Q_FUNC_INFO; + const QSize oldSize = m_nativeSize; + + if (m_videoSink) { + // Find video native size to update video widget size hint + GstPad *pad = gst_element_get_static_pad(m_videoSink,"sink"); + GstCaps *caps = gst_pad_get_current_caps(pad); + + if (caps) { + m_nativeSize = QGstUtils::capsCorrectedResolution(caps); + gst_caps_unref(caps); + } + } else { + m_nativeSize = QSize(); + } + qDebug() << Q_FUNC_INFO << oldSize << m_nativeSize << m_videoSink; + + if (m_nativeSize != oldSize) + emit nativeSizeChanged(); +} + +void QGstreamerMirTextureRenderer::handleFocusWindowChanged(QWindow *window) +{ + qDebug() << Q_FUNC_INFO; + + QOpenGLContext *currContext = QOpenGLContext::currentContext(); + + QQuickWindow *w = dynamic_cast<QQuickWindow*>(window); + // If we don't have a GL context in the current thread, create one and share it + // with the render thread GL context + if (!currContext && !m_glContext) { + // This emulates the new QOffscreenWindow class with Qt5.1 + m_offscreenSurface = createOffscreenWindow(w->openglContext()->surface()->format()); + m_offscreenSurface->setParent(window); + + QOpenGLContext *shareContext = 0; + if (m_surface) + shareContext = qobject_cast<QOpenGLContext*>(m_surface->property("GLContext").value<QObject*>()); + m_glContext = new QOpenGLContext; + m_glContext->setFormat(m_offscreenSurface->requestedFormat()); + + if (shareContext) + m_glContext->setShareContext(shareContext); + + if (!m_glContext->create()) + { + qWarning() << "Failed to create new shared context."; + return; + } + } + + if (m_glContext) + m_glContext->makeCurrent(m_offscreenSurface); + + if (m_textureId == 0) { + glGenTextures(1, &m_textureId); + qDebug() << "texture_id (handleFocusWindowChanged): " << m_textureId << endl; + g_object_set(G_OBJECT(m_videoSink), "texture-id", m_textureId, (char*)NULL); + } +} diff --git a/src/gsttools/qgstreamervideoprobecontrol.cpp b/src/gsttools/qgstreamervideoprobecontrol.cpp index f2e6c3f2..55632ff2 100644 --- a/src/gsttools/qgstreamervideoprobecontrol.cpp +++ b/src/gsttools/qgstreamervideoprobecontrol.cpp @@ -75,12 +75,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 5b0b0d7d..80b6e470 100644 --- a/src/gsttools/qgstreamervideorenderer.cpp +++ b/src/gsttools/qgstreamervideorenderer.cpp @@ -42,8 +42,7 @@ #include "qgstreamervideorenderer_p.h" #include <private/qvideosurfacegstsink_p.h> #include <qabstractvideosurface.h> - -#include <QDebug> +#include <QtCore/qdebug.h> #include <gst/gst.h> @@ -62,8 +61,12 @@ GstElement *QGstreamerVideoRenderer::videoSink() { if (!m_videoSink && m_surface) { m_videoSink = QVideoSurfaceGstSink::createSink(m_surface); - gst_object_ref(GST_OBJECT(m_videoSink)); //Take ownership + gst_object_ref(GST_OBJECT(m_videoSink)); // Take ownership +#if GST_CHECK_VERSION(1,0,0) + gst_object_ref_sink(GST_OBJECT(m_videoSink)); +#else gst_object_sink(GST_OBJECT(m_videoSink)); +#endif } return reinterpret_cast<GstElement*>(m_videoSink); diff --git a/src/gsttools/qgstreamervideowidget.cpp b/src/gsttools/qgstreamervideowidget.cpp index 8297040c..d4a5f187 100644 --- a/src/gsttools/qgstreamervideowidget.cpp +++ b/src/gsttools/qgstreamervideowidget.cpp @@ -48,8 +48,13 @@ #include <QtGui/qpainter.h> #include <gst/gst.h> + +#if !GST_CHECK_VERSION(1,0,0) #include <gst/interfaces/xoverlay.h> #include <gst/interfaces/propertyprobe.h> +#else +#include <gst/video/videooverlay.h> +#endif QT_BEGIN_NAMESPACE @@ -136,11 +141,12 @@ void QGstreamerVideoWidgetControl::createVideoWidget() if (!m_videoSink) m_videoSink = gst_element_factory_make ("ximagesink", NULL); - +#if !GST_CHECK_VERSION(1,0,0) gst_object_ref (GST_OBJECT (m_videoSink)); //Take ownership gst_object_sink (GST_OBJECT (m_videoSink)); - - +#else + gst_object_ref_sink(GST_OBJECT (m_videoSink)); +#endif } GstElement *QGstreamerVideoWidgetControl::videoSink() @@ -178,9 +184,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; @@ -208,17 +218,27 @@ 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); +#else + GstCaps *caps = gst_pad_get_current_caps(pad); +#endif if (caps) { m_widget->setNativeSize(QGstUtils::capsCorrectedResolution(caps)); @@ -233,8 +253,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 70d32157..8d3d6e8d 100644 --- a/src/gsttools/qgstreamervideowindow.cpp +++ b/src/gsttools/qgstreamervideowindow.cpp @@ -45,8 +45,12 @@ #include <QtCore/qdebug.h> #include <gst/gst.h> +#include <gst/video/videooverlay.h> + +#if !GST_CHECK_VERSION(1,0,0) #include <gst/interfaces/xoverlay.h> #include <gst/interfaces/propertyprobe.h> +#endif QGstreamerVideoWindow::QGstreamerVideoWindow(QObject *parent, const char *elementName) @@ -57,18 +61,29 @@ 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) { - gst_object_ref(GST_OBJECT(m_videoSink)); //Take ownership +#if GST_CHECK_VERSION(1,0,0) + gst_object_ref_sink(GST_OBJECT(m_videoSink)); + gst_object_ref_sink(GST_OBJECT(m_videoSink)); +#else + gst_object_ref(GST_OBJECT(m_videoSink)); // Take ownership gst_object_sink(GST_OBJECT(m_videoSink)); - - GstPad *pad = gst_element_get_static_pad(m_videoSink,"sink"); +#endif + 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 } + else + qDebug() << "No m_videoSink available!"; } QGstreamerVideoWindow::~QGstreamerVideoWindow() @@ -90,11 +105,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); @@ -105,7 +124,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)) { @@ -117,7 +149,7 @@ bool QGstreamerVideoWindow::processSyncMessage(const QGstreamerMessage &message) return true; } - +#endif return false; } @@ -129,7 +161,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()) @@ -143,6 +187,7 @@ void QGstreamerVideoWindow::setDisplayRect(const QRect &rect) repaint(); #endif } +#endif } Qt::AspectRatioMode QGstreamerVideoWindow::aspectRatioMode() const @@ -164,6 +209,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; @@ -172,6 +227,7 @@ void QGstreamerVideoWindow::repaint() gst_x_overlay_expose(GST_X_OVERLAY(m_videoSink)); } } +#endif } QColor QGstreamerVideoWindow::colorKey() const @@ -303,11 +359,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<QGstreamerVideoWindow*>(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() @@ -318,7 +385,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 if (caps) { m_nativeSize = QGstUtils::capsCorrectedResolution(caps); diff --git a/src/gsttools/qgstutils.cpp b/src/gsttools/qgstutils.cpp index e93b4675..5b6125d7 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. diff --git a/src/gsttools/qgstvideobuffer.cpp b/src/gsttools/qgstvideobuffer.cpp index 45556d1e..750a07f8 100644 --- a/src/gsttools/qgstvideobuffer.cpp +++ b/src/gsttools/qgstvideobuffer.cpp @@ -78,21 +78,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 81d5f606..51c41078 100644 --- a/src/gsttools/qvideosurfacegstsink.cpp +++ b/src/gsttools/qvideosurfacegstsink.cpp @@ -51,7 +51,11 @@ #include "qvideosurfacegstsink_p.h" -//#define DEBUG_VIDEO_SURFACE_SINK +#if GST_VERSION_MAJOR >=1 +#include <gst/video/video.h> +#endif + +#define DEBUG_VIDEO_SURFACE_SINK QT_BEGIN_NAMESPACE @@ -71,10 +75,12 @@ QVideoSurfaceGstDelegate::QVideoSurfaceGstDelegate( if (m_surface) { foreach (QObject *instance, bufferPoolLoader()->instances(QGstBufferPoolPluginKey)) { QGstBufferPoolInterface* plugin = qobject_cast<QGstBufferPoolInterface*>(instance); + if (plugin) { m_pools.append(plugin); } } + updateSupportedFormats(); connect(m_surface, SIGNAL(supportedFormatsChanged()), this, SLOT(updateSupportedFormats())); } @@ -208,6 +214,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); @@ -310,6 +318,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; @@ -327,6 +356,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) { @@ -339,12 +369,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; @@ -417,13 +455,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 @@ -445,7 +483,11 @@ void QVideoSurfaceGstSink::class_init(gpointer g_class, gpointer class_data) GstBaseSinkClass *base_sink_class = reinterpret_cast<GstBaseSinkClass *>(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; // base_sink_class->unlock = QVideoSurfaceGstSink::unlock; // Not implemented. @@ -464,6 +506,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 ], " @@ -472,6 +526,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)); @@ -520,7 +575,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); @@ -533,6 +592,7 @@ GstCaps *QVideoSurfaceGstSink::get_caps(GstBaseSink *base) QList<QVideoFrame::PixelFormat> poolHandleFormats; sink->delegate->poolMutex()->lock(); QGstBufferPoolInterface *pool = sink->delegate->pool(); + if (pool) poolHandleFormats = sink->delegate->supportedPixelFormats(pool->handleType()); sink->delegate->poolMutex()->unlock(); @@ -548,11 +608,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, - "format" , GST_TYPE_FOURCC, qt_yuvColorLookup[index].fourcc, +#if GST_CHECK_VERSION(1,0,0) + "format" , G_TYPE_STRING, gst_video_format_to_string(qt_yuvColorLookup[index].vfmt), +#else + "format" , G_TYPE_STRING, qt_yuvColorLookup[index].fourcc, +#endif NULL)); continue; } @@ -562,7 +630,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, @@ -583,6 +662,7 @@ GstCaps *QVideoSurfaceGstSink::get_caps(GstBaseSink *base) } } +// printf("get Caps %"GST_PTR_FORMAT"\n", caps); return caps; } @@ -622,7 +702,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 @@ -647,11 +727,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; @@ -677,6 +795,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); @@ -773,7 +892,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); @@ -814,7 +937,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; } @@ -838,7 +961,6 @@ GstFlowReturn QVideoSurfaceGstSink::buffer_alloc( gboolean QVideoSurfaceGstSink::start(GstBaseSink *base) { Q_UNUSED(base); - return TRUE; } @@ -864,8 +986,9 @@ gboolean QVideoSurfaceGstSink::event(GstBaseSink *base, GstEvent *event) VO_SINK(base); sink->delegate->setLastPrerolledBuffer(0); } - - return TRUE; +#if GST_CHECK_VERSION(1, 0, 0) + return GST_BASE_SINK_CLASS (sink_parent_class)->event (base, event); +#endif } GstFlowReturn QVideoSurfaceGstSink::preroll(GstBaseSink *base, GstBuffer *buffer) diff --git a/src/multimedia/gsttools_headers/qgstappsrc_p.h b/src/multimedia/gsttools_headers/qgstappsrc_p.h index bfb038eb..a188e18f 100644 --- a/src/multimedia/gsttools_headers/qgstappsrc_p.h +++ b/src/multimedia/gsttools_headers/qgstappsrc_p.h @@ -47,7 +47,10 @@ #include <gst/gst.h> #include <gst/app/gstappsrc.h> + +#if GST_VERSION_MAJOR < 1 #include <gst/app/gstappbuffer.h> +#endif QT_BEGIN_NAMESPACE diff --git a/src/multimedia/gsttools_headers/qgstreameraudioprobecontrol_p.h b/src/multimedia/gsttools_headers/qgstreameraudioprobecontrol_p.h index 71ea2ffb..879f071c 100644 --- a/src/multimedia/gsttools_headers/qgstreameraudioprobecontrol_p.h +++ b/src/multimedia/gsttools_headers/qgstreameraudioprobecontrol_p.h @@ -55,8 +55,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/qgstreamermirtexturerenderer_p.h b/src/multimedia/gsttools_headers/qgstreamermirtexturerenderer_p.h new file mode 100644 index 00000000..86b7ac14 --- /dev/null +++ b/src/multimedia/gsttools_headers/qgstreamermirtexturerenderer_p.h @@ -0,0 +1,111 @@ +/**************************************************************************** +** +** Copyright (C) 2013 Canonical Ltd +** Contact: jim.hodapp@canonical.com +** +** This file is part of the Qt Toolkit. +** +// TODO: Fix this license +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Digia. For licensing terms and +** conditions see http://qt.digia.com/licensing. For further information +** use the contact form at http://qt.digia.com/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Digia gives you certain additional +** rights. These rights are described in the Digia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3.0 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU General Public License version 3.0 requirements will be +** met: http://www.gnu.org/copyleft/gpl.html. +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QGSTREAMERMIRTEXTURERENDERER_H +#define QGSTREAMERMIRTEXTURERENDERER_H + +#include <qmediaplayer.h> +#include <qvideorenderercontrol.h> +#include <private/qvideosurfacegstsink_p.h> +#include <qabstractvideosurface.h> + +#include "qgstreamervideorendererinterface_p.h" + +QT_BEGIN_NAMESPACE + +class QGstreamerMirTextureBuffer; +class QGstreamerPlayerSession; +class QGLContext; +class QOpenGLContext; +class QSurfaceFormat; + +class QGstreamerMirTextureRenderer : public QVideoRendererControl, public QGstreamerVideoRendererInterface +{ + Q_OBJECT + Q_INTERFACES(QGstreamerVideoRendererInterface) +public: + QGstreamerMirTextureRenderer(QObject *parent = 0, const QGstreamerPlayerSession *playerSession = 0); + virtual ~QGstreamerMirTextureRenderer(); + + QAbstractVideoSurface *surface() const; + void setSurface(QAbstractVideoSurface *surface); + + void setPlayerSession(const QGstreamerPlayerSession *playerSession); + + GstElement *videoSink(); + + void stopRenderer(); + bool isReady() const { return m_surface != 0; } + +signals: + void sinkChanged(); + void readyChanged(bool); + void nativeSizeChanged(); + +private slots: + void handleFormatChange(); + void updateNativeVideoSize(); + void handleFocusWindowChanged(QWindow *window); + void renderFrame(); + +private: + QWindow *createOffscreenWindow(const QSurfaceFormat &format); + static void handleFrameReady(gpointer userData); + static GstPadProbeReturn padBufferProbe(GstPad *pad, GstPadProbeInfo *info, gpointer userData); + + GstElement *m_videoSink; + QPointer<QAbstractVideoSurface> m_surface; + QPointer<QAbstractVideoSurface> m_glSurface; + QGLContext *m_context; + QOpenGLContext *m_glContext; + unsigned int m_textureId; + QWindow *m_offscreenSurface; + QGstreamerPlayerSession *m_playerSession; + QGstreamerMirTextureBuffer *m_textureBuffer; + QSize m_nativeSize; + + QMutex m_mutex; +}; + +QT_END_NAMESPACE + +#endif // QGSTREAMERMIRTEXTURERENDRER_H diff --git a/src/multimedia/gsttools_headers/qgstreamervideoprobecontrol_p.h b/src/multimedia/gsttools_headers/qgstreamervideoprobecontrol_p.h index c512b48a..0a8a654e 100644 --- a/src/multimedia/gsttools_headers/qgstreamervideoprobecontrol_p.h +++ b/src/multimedia/gsttools_headers/qgstreamervideoprobecontrol_p.h @@ -56,7 +56,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 45582d6b..44403374 100644 --- a/src/multimedia/gsttools_headers/qgstreamervideowindow_p.h +++ b/src/multimedia/gsttools_headers/qgstreamervideowindow_p.h @@ -112,7 +112,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 56858026..c202ac76 100644 --- a/src/multimedia/gsttools_headers/qgstutils_p.h +++ b/src/multimedia/gsttools_headers/qgstutils_p.h @@ -70,7 +70,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 505a6c6f..9bde1e02 100644 --- a/src/multimedia/gsttools_headers/qgstvideobuffer_p.h +++ b/src/multimedia/gsttools_headers/qgstvideobuffer_p.h @@ -79,6 +79,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 7563f068..505ff39a 100644 --- a/src/multimedia/gsttools_headers/qvideosurfacegstsink_p.h +++ b/src/multimedia/gsttools_headers/qvideosurfacegstsink_p.h @@ -146,7 +146,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 d34c10e1..56c39993 100644 --- a/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecoderserviceplugin.cpp +++ b/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecoderserviceplugin.cpp @@ -95,29 +95,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 5bcf1aa5..d9138de2 100644 --- a/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecodersession.cpp +++ b/src/plugins/gstreamer/audiodecoder/qgstreameraudiodecodersession.cpp @@ -451,21 +451,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; @@ -536,7 +555,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); @@ -562,8 +586,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 8ca6bfd8..3abb0054 100644 --- a/src/plugins/gstreamer/camerabin/camerabinsession.cpp +++ b/src/plugins/gstreamer/camerabin/camerabinsession.cpp @@ -108,7 +108,11 @@ #define CAMERABIN_IMAGE_MODE 1 #define CAMERABIN_VIDEO_MODE 2 +#if GST_CHECK_VERSION(1,0,0) +#define gstRef(element) { gst_object_ref(GST_OBJECT(element)); gst_object_ref_sink(GST_OBJECT(element)); } +#else #define gstRef(element) { gst_object_ref(GST_OBJECT(element)); gst_object_sink(GST_OBJECT(element)); } +#endif #define gstUnref(element) { if (element) { gst_object_unref(GST_OBJECT(element)); element = 0; } } #define PREVIEW_CAPS_4_3 \ @@ -721,7 +725,11 @@ qint64 CameraBinSession::duration() const GstFormat format = GST_FORMAT_TIME; gint64 duration = 0; +#if GST_CHECK_VERSION(1,0,0) + if ( m_camerabin && gst_element_query_duration(m_camerabin, format, &duration)) +#else if ( m_camerabin && gst_element_query_position(m_camerabin, &format, &duration)) +#endif return duration / 1000000; else return 0; @@ -754,8 +762,13 @@ void CameraBinSession::setMetaData(const QMap<QByteArray, QVariant> &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<QByteArray, QVariant> it(data); @@ -815,7 +828,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)) { @@ -825,7 +842,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; @@ -1097,7 +1118,11 @@ QList< QPair<int,int> > 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<gst_caps_get_size(caps); i++) { @@ -1217,7 +1242,11 @@ QList<QSize> CameraBinSession::supportedResolutions(QPair<int,int> 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; i<gst_caps_get_size(caps); i++) { GstStructure *structure = gst_caps_get_structure(caps, i); diff --git a/src/plugins/gstreamer/common.pri b/src/plugins/gstreamer/common.pri index 98e427d7..c52a30ab 100644 --- a/src/plugins/gstreamer/common.pri +++ b/src/plugins/gstreamer/common.pri @@ -12,14 +12,17 @@ LIBS += -lqgsttools_p 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 -maemo*:PKGCONFIG +=gstreamer-plugins-bad-0.10 +maemo*:PKGCONFIG +=gstreamer-plugins-bad-$$GST_VERSION + +mir: { + DEFINES += HAVE_MIR +} config_resourcepolicy { DEFINES += HAVE_RESOURCE_POLICY @@ -27,8 +30,8 @@ config_resourcepolicy { } config_gstreamer_appsrc { - PKGCONFIG += gstreamer-app-0.10 + PKGCONFIG += gstreamer-app-$$GST_VERSION DEFINES += HAVE_GST_APPSRC - LIBS += -lgstapp-0.10 + LIBS += -lgstapp-$$GST_VERSION } diff --git a/src/plugins/gstreamer/gstreamer.pro b/src/plugins/gstreamer/gstreamer.pro index 76490100..fce55acd 100644 --- a/src/plugins/gstreamer/gstreamer.pro +++ b/src/plugins/gstreamer/gstreamer.pro @@ -2,11 +2,10 @@ TEMPLATE = subdirs SUBDIRS += \ audiodecoder \ - mediacapture \ mediaplayer config_gstreamer_encodingprofiles { - SUBDIRS += camerabin +# SUBDIRS += camerabin } OTHER_FILES += \ diff --git a/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.cpp b/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.cpp index d7473327..3260d9ea 100644 --- a/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.cpp +++ b/src/plugins/gstreamer/mediacapture/qgstreamercapturesession.cpp @@ -64,7 +64,11 @@ QT_BEGIN_NAMESPACE +#if GST_CHECK_VERSION(1,0,0) +#define gstRef(element) gst_object_ref_sink(GST_OBJECT(element)); +#else #define gstRef(element) { gst_object_ref(GST_OBJECT(element)); gst_object_sink(GST_OBJECT(element)); } +#endif #define gstUnref(element) { if (element) { gst_object_unref(GST_OBJECT(element)); element = 0; } } QGstreamerCaptureSession::QGstreamerCaptureSession(QGstreamerCaptureSession::CaptureMode captureMode, QObject *parent) @@ -500,8 +504,12 @@ GstElement *QGstreamerCaptureSession::buildImageCapture() GstPad *pad = gst_element_get_static_pad(queue, "src"); Q_ASSERT(pad); - gst_pad_add_buffer_probe(pad, G_CALLBACK(passImageFilter), this); +#if GST_CHECK_VERSION(1,0,0) + gst_pad_add_probe(pad, GST_PAD_PROBE_TYPE_BUFFER, passImageFilter, this); +#else + gst_pad_add_buffer_probe(pad, G_CALLBACK(passImageFilter), this); +#endif g_object_set(G_OBJECT(sink), "signal-handoffs", TRUE, NULL); g_signal_connect(G_OBJECT(sink), "handoff", G_CALLBACK(saveImageFilter), this); diff --git a/src/plugins/gstreamer/mediaplayer/mediaplayer.pro b/src/plugins/gstreamer/mediaplayer/mediaplayer.pro index 2ca9377d..b986fc78 100644 --- a/src/plugins/gstreamer/mediaplayer/mediaplayer.pro +++ b/src/plugins/gstreamer/mediaplayer/mediaplayer.pro @@ -28,4 +28,3 @@ SOURCES += \ OTHER_FILES += \ mediaplayer.json - diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamerplayercontrol.cpp b/src/plugins/gstreamer/mediaplayer/qgstreamerplayercontrol.cpp index e028e6d7..f9de6a7c 100644 --- a/src/plugins/gstreamer/mediaplayer/qgstreamerplayercontrol.cpp +++ b/src/plugins/gstreamer/mediaplayer/qgstreamerplayercontrol.cpp @@ -527,6 +527,8 @@ void QGstreamerPlayerControl::processEOS() m_session->showPrerollFrames(false); // stop showing prerolled frames in stop state } + qWarning() << "Processing EOS!"; + popAndNotifyState(); } @@ -630,7 +632,7 @@ void QGstreamerPlayerControl::popAndNotifyState() if (m_stateStack.isEmpty()) { if (m_currentState != oldState) { #ifdef DEBUG_PLAYBIN - qDebug() << "State changed:" << m_state; + qDebug() << "State changed:" << m_currentState; #endif emit stateChanged(m_currentState); } diff --git a/src/plugins/gstreamer/mediaplayer/qgstreamerplayerservice.cpp b/src/plugins/gstreamer/mediaplayer/qgstreamerplayerservice.cpp index 854da46d..2fd4345e 100644 --- a/src/plugins/gstreamer/mediaplayer/qgstreamerplayerservice.cpp +++ b/src/plugins/gstreamer/mediaplayer/qgstreamerplayerservice.cpp @@ -59,7 +59,11 @@ #include <private/qgstreamervideorenderer_p.h> #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" @@ -90,6 +94,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 b2ad2489..938e908b 100644 --- a/src/plugins/gstreamer/mediaplayer/qgstreamerplayerserviceplugin.cpp +++ b/src/plugins/gstreamer/mediaplayer/qgstreamerplayerserviceplugin.cpp @@ -109,7 +109,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; @@ -117,22 +121,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 da612018..7df72926 100644 --- a/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp +++ b/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.cpp @@ -78,6 +78,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; " \ @@ -90,6 +100,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) @@ -129,8 +141,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, @@ -162,7 +177,11 @@ QGstreamerPlayerSession::QGstreamerPlayerSession(QObject *parent) m_videoIdentity = GST_ELEMENT(g_object_new(gst_video_connector_get_type(), 0)); 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 gst_object_ref(GST_OBJECT(m_colorSpace)); m_nullVideoSink = gst_element_factory_make("fakesink", NULL); @@ -175,7 +194,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) { @@ -187,7 +206,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); // Init volume and mute state g_object_set(G_OBJECT(m_playbin), "volume", 1.0, NULL); @@ -309,9 +328,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; } @@ -441,9 +464,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 @@ -452,6 +484,7 @@ static void block_pad_cb(GstPad *pad, gboolean blocked, gpointer user_data) QGstreamerPlayerSession *session = reinterpret_cast<QGstreamerPlayerSession*>(user_data); QMetaObject::invokeMethod(session, "finishVideoOutputChange", Qt::QueuedConnection); } +#endif } void QGstreamerPlayerSession::updateVideoRenderer() @@ -496,7 +529,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 @@ -600,7 +633,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 @@ -641,7 +678,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)); @@ -727,12 +768,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 } @@ -797,6 +843,7 @@ bool QGstreamerPlayerSession::play() #ifdef DEBUG_PLAYBIN qDebug() << Q_FUNC_INFO; #endif + m_everPlayed = false; if (m_playbin) { m_pendingState = QMediaPlayer::PlayingState; @@ -1292,8 +1339,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); @@ -1332,7 +1382,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); @@ -1376,7 +1430,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) { @@ -1439,7 +1497,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 @@ -1593,7 +1655,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)) @@ -1622,14 +1688,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. @@ -1697,7 +1768,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<QGstreamerPlayerSession*>(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); @@ -1712,6 +1803,7 @@ gboolean QGstreamerPlayerSession::padVideoBufferProbe(GstPad *pad, GstBuffer *bu return TRUE; } +#endif void QGstreamerPlayerSession::addProbe(QGstreamerAudioProbeControl* probe) { @@ -1729,6 +1821,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<QGstreamerPlayerSession*>(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); @@ -1744,7 +1854,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. @@ -1777,7 +1887,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)); } @@ -1792,7 +1906,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)); } } @@ -1809,7 +1927,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)); } @@ -1824,7 +1946,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)); } } @@ -1857,7 +1983,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 94a84e5d..a17bf63c 100644 --- a/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.h +++ b/src/plugins/gstreamer/mediaplayer/qgstreamerplayersession.h @@ -127,11 +127,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(); @@ -259,6 +267,7 @@ private: bool m_isLiveSource; bool m_isPlaylist; + gulong pad_probe_id; }; QT_END_NAMESPACE |