summaryrefslogtreecommitdiffstats
path: root/src/plugins/gstreamer/gstvideoconnector.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/gstreamer/gstvideoconnector.c')
-rw-r--r--src/plugins/gstreamer/gstvideoconnector.c425
1 files changed, 0 insertions, 425 deletions
diff --git a/src/plugins/gstreamer/gstvideoconnector.c b/src/plugins/gstreamer/gstvideoconnector.c
deleted file mode 100644
index d5b56c7..0000000
--- a/src/plugins/gstreamer/gstvideoconnector.c
+++ /dev/null
@@ -1,425 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** GNU Lesser General Public License Usage
-** 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, Nokia gives you certain additional
-** rights. These rights are described in the Nokia 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.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "gstvideoconnector.h"
-
-/* signals */
-enum
-{
- SIGNAL_RESEND_NEW_SEGMENT,
- SIGNAL_CONNECTION_FAILED,
- LAST_SIGNAL
-};
-static guint gst_video_connector_signals[LAST_SIGNAL] = { 0 };
-
-
-GST_DEBUG_CATEGORY_STATIC (video_connector_debug);
-#define GST_CAT_DEFAULT video_connector_debug
-
-static GstStaticPadTemplate gst_video_connector_sink_factory =
-GST_STATIC_PAD_TEMPLATE ("sink",
- GST_PAD_SINK,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS_ANY);
-
-static GstStaticPadTemplate gst_video_connector_src_factory =
-GST_STATIC_PAD_TEMPLATE ("src",
- GST_PAD_SRC,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS_ANY);
-
-#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);
-
-static void gst_video_connector_dispose (GObject * object);
-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);
-static GstStateChangeReturn gst_video_connector_change_state (GstElement *
- element, GstStateChange transition);
-static gboolean gst_video_connector_handle_sink_event (GstPad * pad,
- GstEvent * event);
-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);
-
-static void
-gst_video_connector_base_init (gpointer g_class)
-{
- GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-
- gst_element_class_set_details_simple (element_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 (element_class,
- gst_static_pad_template_get (&gst_video_connector_sink_factory));
- gst_element_class_add_pad_template (element_class,
- gst_static_pad_template_get (&gst_video_connector_src_factory));
-}
-
-static void
-gst_video_connector_class_init (GstVideoConnectorClass * klass)
-{
- GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
- GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
-
- 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);
-}
-
-static void
-gst_video_connector_init (GstVideoConnector *element,
- GstVideoConnectorClass *g_class)
-{
- (void) g_class;
- 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));
- 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,
- GST_DEBUG_FUNCPTR (gst_video_connector_setcaps));
- gst_pad_set_getcaps_function(element->sinkpad,
- GST_DEBUG_FUNCPTR(gst_video_connector_getcaps));
- gst_pad_set_acceptcaps_function(element->sinkpad,
- GST_DEBUG_FUNCPTR(gst_video_connector_acceptcaps));
-
- gst_element_add_pad (GST_ELEMENT (element), element->sinkpad);
-
- element->srcpad =
- gst_pad_new_from_static_template (&gst_video_connector_src_factory,
- "src");
- gst_pad_add_buffer_probe(element->srcpad,
- G_CALLBACK(gst_video_connector_new_buffer_probe), element);
- gst_element_add_pad (GST_ELEMENT (element), element->srcpad);
-
- element->relinked = FALSE;
- element->failedSignalEmited = FALSE;
- gst_segment_init (&element->segment, GST_FORMAT_TIME);
- element->latest_buffer = NULL;
-}
-
-static void
-gst_video_connector_reset (GstVideoConnector * element)
-{
- element->relinked = FALSE;
- element->failedSignalEmited = FALSE;
- if (element->latest_buffer != NULL) {
- gst_buffer_unref (element->latest_buffer);
- element->latest_buffer = NULL;
- }
- gst_segment_init (&element->segment, GST_FORMAT_UNDEFINED);
-}
-
-static void
-gst_video_connector_dispose (GObject * object)
-{
- GstVideoConnector *element = GST_VIDEO_CONNECTOR (object);
-
- gst_video_connector_reset (element);
-
- G_OBJECT_CLASS (parent_class)->dispose (object);
-}
-
-static GstFlowReturn
-gst_video_connector_buffer_alloc (GstPad * pad, guint64 offset, guint size,
- GstCaps * caps, GstBuffer ** buf)
-{
- GstVideoConnector *element;
- GstFlowReturn res = GST_FLOW_OK;
- element = GST_VIDEO_CONNECTOR (GST_PAD_PARENT (pad));
-
- if (!buf)
- return GST_FLOW_ERROR;
- *buf = NULL;
-
- GST_OBJECT_LOCK (element);
- gst_object_ref(element->srcpad);
- GST_OBJECT_UNLOCK (element);
-
- res = gst_pad_alloc_buffer(element->srcpad, offset, size, caps, buf);
- gst_object_unref (element->srcpad);
-
- GST_DEBUG_OBJECT (element, "buffer alloc finished: %s", gst_flow_get_name (res));
-
- return res;
-}
-
-static gboolean
-gst_video_connector_setcaps (GstPad *pad, GstCaps *caps)
-{
- GstVideoConnector *element;
- element = GST_VIDEO_CONNECTOR (GST_PAD_PARENT (pad));
-
- /* forward-negotiate */
- gboolean res = gst_pad_set_caps(element->srcpad, caps);
-
- GST_DEBUG_OBJECT(element, "gst_video_connector_setcaps %s %i", gst_caps_to_string(caps), res);
-
- if (!res) {
- //if set_caps failed, emit "connection-failed" signal
- //so colorspace transformation elemnt can be inserted
- GST_INFO_OBJECT(element, "gst_video_connector_setcaps failed, emit connection-failed signal");
- g_signal_emit(G_OBJECT(element), gst_video_connector_signals[SIGNAL_CONNECTION_FAILED], 0);
-
- return gst_pad_set_caps(element->srcpad, caps);
- }
-
- return TRUE;
-}
-
-static GstCaps *gst_video_connector_getcaps (GstPad * pad)
-{
- GstVideoConnector *element;
- element = GST_VIDEO_CONNECTOR (GST_PAD_PARENT (pad));
-
-#if (GST_VERSION_MICRO > 25)
- GstCaps *caps = gst_pad_peer_get_caps_reffed(element->srcpad);
-#else
- GstCaps *caps = gst_pad_peer_get_caps(element->srcpad);
-#endif
-
- if (!caps)
- caps = gst_caps_new_any();
-
- return caps;
-}
-
-static gboolean gst_video_connector_acceptcaps (GstPad * pad, GstCaps * caps)
-{
- GstVideoConnector *element;
- element = GST_VIDEO_CONNECTOR (GST_PAD_PARENT (pad));
-
- return gst_pad_peer_accept_caps(element->srcpad, caps);
-}
-
-static void
-gst_video_connector_resend_new_segment(GstElement * element, gboolean emitFailedSignal)
-{
- GST_INFO_OBJECT(element, "New segment requested, failed signal enabled: %i", emitFailedSignal);
- GstVideoConnector *connector = GST_VIDEO_CONNECTOR(element);
- connector->relinked = TRUE;
- if (emitFailedSignal)
- connector->failedSignalEmited = FALSE;
-}
-
-
-static gboolean gst_video_connector_new_buffer_probe(GstObject *pad, GstBuffer *buffer, guint * object)
-{
- (void) pad;
- (void) buffer;
-
- GstVideoConnector *element = GST_VIDEO_CONNECTOR (object);
-
- /*
- If relinking is requested, the current buffer should be rejected and
- the new segment + previous buffer should be pushed first
- */
-
- if (element->relinked)
- GST_LOG_OBJECT(element, "rejected buffer because of new segment request");
-
- return !element->relinked;
-}
-
-
-static GstFlowReturn
-gst_video_connector_chain (GstPad * pad, GstBuffer * buf)
-{
- GstFlowReturn res;
- GstVideoConnector *element;
-
- element = GST_VIDEO_CONNECTOR (gst_pad_get_parent (pad));
-
- do {
- /*
- Resend the segment message and last buffer to preroll the new sink.
- Sinks can be changed multiple times while paused,
- while loop allows to send the segment message and preroll
- all of them with the same buffer.
- */
- while (element->relinked) {
- element->relinked = FALSE;
-
- 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);
- }
-
- //push a new segment and last buffer
- GstEvent *ev = gst_event_new_new_segment (TRUE,
- element->segment.rate,
- element->segment.format,
- pos, //start
- element->segment.stop,
- pos);
-
- GST_DEBUG_OBJECT (element, "Pushing new segment event");
- if (!gst_pad_push_event (element->srcpad, ev)) {
- GST_WARNING_OBJECT (element,
- "Newsegment handling failed in %" GST_PTR_FORMAT,
- element->srcpad);
- }
-
- if (element->latest_buffer) {
- GST_DEBUG_OBJECT (element, "Pushing latest buffer...");
- gst_buffer_ref(element->latest_buffer);
- gst_pad_push(element->srcpad, element->latest_buffer);
- }
- }
-
- gst_buffer_ref(buf);
-
- //it's possible video sink is changed during gst_pad_push blocked by
- //pad lock, in this case ( element->relinked == TRUE )
- //the buffer should be rejected by the buffer probe and
- //the new segment + prev buffer should be sent before
-
- GST_LOG_OBJECT (element, "Pushing buffer...");
- res = gst_pad_push (element->srcpad, buf);
- GST_LOG_OBJECT (element, "Pushed buffer: %s", gst_flow_get_name (res));
-
- //if gst_pad_push failed give the service another chance,
- //it may still work with the colorspace element added
- if (!element->failedSignalEmited && res == GST_FLOW_NOT_NEGOTIATED) {
- element->failedSignalEmited = TRUE;
- GST_INFO_OBJECT(element, "gst_pad_push failed, emit connection-failed signal");
- g_signal_emit(G_OBJECT(element), gst_video_connector_signals[SIGNAL_CONNECTION_FAILED], 0);
- }
-
- } while (element->relinked);
-
-
- if (element->latest_buffer) {
- gst_buffer_unref (element->latest_buffer);
- element->latest_buffer = NULL;
- }
-
- //don't save the last video buffer on maemo6 because of buffers shortage
- //with omapxvsink
-#ifndef Q_WS_MAEMO_6
- element->latest_buffer = gst_buffer_ref(buf);
-#endif
-
- gst_buffer_unref(buf);
- gst_object_unref (element);
-
- return res;
-}
-
-static GstStateChangeReturn
-gst_video_connector_change_state (GstElement * element,
- GstStateChange transition)
-{
- GstVideoConnector *connector;
- GstStateChangeReturn result;
-
- connector = GST_VIDEO_CONNECTOR(element);
- result = GST_ELEMENT_CLASS (parent_class)->change_state(element, transition);
-
- switch (transition) {
- case GST_STATE_CHANGE_PAUSED_TO_READY:
- gst_video_connector_reset (connector);
- break;
- case GST_STATE_CHANGE_READY_TO_PAUSED:
- connector->relinked = FALSE;
- break;
- default:
- break;
- }
-
- return result;
-}
-
-static gboolean
-gst_video_connector_handle_sink_event (GstPad * pad, GstEvent * event)
-{
- if (GST_EVENT_TYPE (event) == GST_EVENT_NEWSEGMENT) {
- GstVideoConnector *element = GST_VIDEO_CONNECTOR (gst_pad_get_parent (pad));
-
- gboolean update;
- GstFormat format;
- gdouble rate, arate;
- gint64 start, stop, time;
-
- 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 %"
- G_GINT64_FORMAT, update, rate, arate, format, start, stop, time);
-
- 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);
-}