Search
SailfishOS Open Build Service
>
Projects
>
home:sledge
:
branches:nemo:devel:hw:ti:omap4:common
>
gstreamer
> 0014-basebarse-Add-detect-vfunc-to-allow-subclasses-to-do.patch
Log In
Username
Password
Cancel
Overview
Repositories
Revisions
Requests
Users
Advanced
Attributes
Meta
File 0014-basebarse-Add-detect-vfunc-to-allow-subclasses-to-do.patch of Package gstreamer
From 86eda4012a22dc95bcb8d0f506297c8d39f9fc44 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= <sebastian.droege@collabora.co.uk> Date: Thu, 20 Oct 2011 08:31:18 +0200 Subject: [PATCH 14/14] basebarse: Add detect vfunc to allow subclasses to do format detection before anything else API: GstBaseParseClass::detect() This is called with the first buffers until the subclass has finished detection and only afterwards the original buffers are handled as before. The vfunc allows detection of the stream format without breaking the upstream framing. --- libs/gst/base/gstbaseparse.c | 121 ++++++++++++++++++++++++++++++++++++++++++ libs/gst/base/gstbaseparse.h | 9 +++- 2 files changed, 129 insertions(+), 1 deletions(-) diff --git a/libs/gst/base/gstbaseparse.c b/libs/gst/base/gstbaseparse.c index 69a6c68..9db4065 100644 --- a/libs/gst/base/gstbaseparse.c +++ b/libs/gst/base/gstbaseparse.c @@ -2,6 +2,8 @@ * Copyright (C) 2008 Nokia Corporation. All rights reserved. * Contact: Stefan Kost <stefan.kost@nokia.com> * Copyright (C) 2008 Sebastian Dröge <sebastian.droege@collabora.co.uk>. + * Copyright (C) 2011, Hewlett-Packard Development Company, L.P. + * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -314,6 +316,12 @@ struct _GstBaseParsePrivate /* push mode helper frame */ GstBaseParseFrame frame; + + /* TRUE if we're still detecting the format, i.e. + * if ::detect() is still called for future buffers */ + gboolean detecting; + GList *detect_buffers; + guint detect_buffers_size; }; typedef struct _GstBaseParseSeek @@ -423,6 +431,11 @@ gst_base_parse_clear_queues (GstBaseParse * parse) g_slist_foreach (parse->priv->buffers_send, (GFunc) gst_buffer_unref, NULL); g_slist_free (parse->priv->buffers_send); parse->priv->buffers_send = NULL; + + g_list_foreach (parse->priv->detect_buffers, (GFunc) gst_buffer_unref, NULL); + g_list_free (parse->priv->detect_buffers); + parse->priv->detect_buffers = NULL; + parse->priv->detect_buffers_size = 0; } static void @@ -739,6 +752,11 @@ gst_base_parse_reset (GstBaseParse * parse) parse->priv->frame._private_flags |= GST_BASE_PARSE_FRAME_PRIVATE_FLAG_NOALLOC; gst_base_parse_frame_free (&parse->priv->frame); + + g_list_foreach (parse->priv->detect_buffers, (GFunc) gst_buffer_unref, NULL); + g_list_free (parse->priv->detect_buffers); + parse->priv->detect_buffers = NULL; + parse->priv->detect_buffers_size = 0; GST_OBJECT_UNLOCK (parse); } @@ -2183,6 +2201,81 @@ gst_base_parse_chain (GstPad * pad, GstBuffer * buffer) parse = GST_BASE_PARSE (GST_OBJECT_PARENT (pad)); bclass = GST_BASE_PARSE_GET_CLASS (parse); + + if (parse->priv->detecting) { + GstBuffer *detect_buf; + + if (parse->priv->detect_buffers_size == 0) { + detect_buf = gst_buffer_ref (buffer); + } else { + GList *l; + guint offset = 0; + + detect_buf = + gst_buffer_new_and_alloc (parse->priv->detect_buffers_size + + (buffer ? GST_BUFFER_SIZE (buffer) : 0)); + for (l = parse->priv->detect_buffers; l; l = l->next) { + memcpy (GST_BUFFER_DATA (detect_buf) + offset, + GST_BUFFER_DATA (l->data), GST_BUFFER_SIZE (l->data)); + offset += GST_BUFFER_SIZE (l->data); + } + if (buffer) + memcpy (GST_BUFFER_DATA (detect_buf) + offset, GST_BUFFER_DATA (buffer), + GST_BUFFER_SIZE (buffer)); + } + + ret = bclass->detect (parse, detect_buf); + gst_buffer_unref (detect_buf); + + if (ret == GST_FLOW_OK) { + GList *l; + + /* Detected something */ + parse->priv->detecting = FALSE; + + for (l = parse->priv->detect_buffers; l; l = l->next) { + if (ret == GST_FLOW_OK && !parse->priv->flushing) + ret = + gst_base_parse_chain (GST_BASE_PARSE_SINK_PAD (parse), + GST_BUFFER_CAST (l->data)); + else + gst_buffer_unref (GST_BUFFER_CAST (l->data)); + } + g_list_free (parse->priv->detect_buffers); + parse->priv->detect_buffers = NULL; + parse->priv->detect_buffers_size = 0; + + if (ret != GST_FLOW_OK) { + return ret; + } + + /* Handle the current buffer */ + } else if (ret == GST_FLOW_NOT_NEGOTIATED) { + /* Still detecting, append buffer or error out if draining */ + + if (parse->priv->drain) { + GST_DEBUG_OBJECT (parse, "Draining but did not detect format yet"); + return GST_FLOW_ERROR; + } else if (parse->priv->flushing) { + g_list_foreach (parse->priv->detect_buffers, (GFunc) gst_buffer_unref, + NULL); + g_list_free (parse->priv->detect_buffers); + parse->priv->detect_buffers = NULL; + parse->priv->detect_buffers_size = 0; + } else { + parse->priv->detect_buffers = + g_list_append (parse->priv->detect_buffers, buffer); + parse->priv->detect_buffers_size += GST_BUFFER_SIZE (buffer); + return GST_FLOW_OK; + } + } else { + /* Something went wrong, subclass responsible for error reporting */ + return ret; + } + + /* And now handle the current buffer if detection worked */ + } + frame = &parse->priv->frame; if (G_LIKELY (buffer)) { @@ -2559,6 +2652,30 @@ gst_base_parse_scan_frame (GstBaseParse * parse, GstBaseParseClass * klass, if (GST_BUFFER_SIZE (buffer) < min_size) parse->priv->drain = TRUE; + if (parse->priv->detecting) { + ret = klass->detect (parse, buffer); + if (ret == GST_FLOW_NOT_NEGOTIATED) { + /* If draining we error out, otherwise request a buffer + * with 64kb more */ + if (parse->priv->drain) { + gst_buffer_unref (buffer); + GST_ERROR_OBJECT (parse, "Failed to detect format but draining"); + return GST_FLOW_ERROR; + } else { + fsize += 64 * 1024; + gst_buffer_unref (buffer); + continue; + } + } else if (ret != GST_FLOW_OK) { + gst_buffer_unref (buffer); + GST_ERROR_OBJECT (parse, "detect() returned %s", + gst_flow_get_name (ret)); + return ret; + } + + /* Else handle this buffer normally */ + } + skip = -1; gst_base_parse_frame_update (parse, frame, buffer); res = klass->check_valid_frame (parse, frame, &fsize, &skip); @@ -2784,6 +2901,10 @@ gst_base_parse_activate (GstBaseParse * parse, gboolean active) if (active) { if (parse->priv->pad_mode == GST_ACTIVATE_NONE && klass->start) result = klass->start (parse); + + /* If the subclass implements ::detect we want to + * call it for the first buffers now */ + parse->priv->detecting = (klass->detect != NULL); } else { /* We must make sure streaming has finished before resetting things * and calling the ::stop vfunc */ diff --git a/libs/gst/base/gstbaseparse.h b/libs/gst/base/gstbaseparse.h index e7b1db5..368bfc9 100644 --- a/libs/gst/base/gstbaseparse.h +++ b/libs/gst/base/gstbaseparse.h @@ -212,6 +212,10 @@ struct _GstBaseParse { * additional actions at this time (e.g. tag sending) or to * decide whether this buffer should be dropped or not * (e.g. custom segment clipping). + * @detect: Optional. + * Called until it doesn't return GST_FLOW_OK anymore for + * the first buffers. Can be used by the subclass to detect + * the stream format. Since: 0.10.36 * * Subclasses can override any of the available virtual methods or not, as * needed. At minimum @check_valid_frame and @parse_frame needs to be @@ -255,8 +259,11 @@ struct _GstBaseParseClass { GstCaps * (*get_sink_caps) (GstBaseParse * parse); + GstFlowReturn (*detect) (GstBaseParse * parse, + GstBuffer * buffer); + /*< private >*/ - gpointer _gst_reserved[GST_PADDING_LARGE - 1]; + gpointer _gst_reserved[GST_PADDING_LARGE - 2]; }; GType gst_base_parse_get_type (void); -- 1.7.5.4