diff options
-rw-r--r-- | gst/rawparse/Makefile.am | 2 | ||||
-rw-r--r-- | gst/rawparse/gstaudioparse.c | 403 | ||||
-rw-r--r-- | gst/rawparse/gstaudioparse.h | 21 | ||||
-rw-r--r-- | gst/rawparse/gstrawparse.c | 1105 | ||||
-rw-r--r-- | gst/rawparse/gstrawparse.h | 98 | ||||
-rw-r--r-- | gst/rawparse/gstvideoparse.c | 577 | ||||
-rw-r--r-- | gst/rawparse/gstvideoparse.h | 27 |
7 files changed, 362 insertions, 1871 deletions
diff --git a/gst/rawparse/Makefile.am b/gst/rawparse/Makefile.am index f3ad3c414..623dc949c 100644 --- a/gst/rawparse/Makefile.am +++ b/gst/rawparse/Makefile.am @@ -2,7 +2,6 @@ plugin_LTLIBRARIES = libgstrawparse.la libgstrawparse_la_SOURCES = \ - gstrawparse.c \ gstunalignedaudioparse.c \ gstunalignedvideoparse.c \ gstaudioparse.c \ @@ -29,7 +28,6 @@ noinst_HEADERS = \ gstunalignedaudioparse.h \ gstunalignedvideoparse.h \ gstaudioparse.h \ - gstrawparse.h \ gstvideoparse.h \ gstrawbaseparse.h \ gstrawaudioparse.h \ diff --git a/gst/rawparse/gstaudioparse.c b/gst/rawparse/gstaudioparse.c index b60118b36..4e7f6943b 100644 --- a/gst/rawparse/gstaudioparse.c +++ b/gst/rawparse/gstaudioparse.c @@ -22,6 +22,8 @@ * SECTION:element-audioparse * * Converts a byte stream into audio frames. + * + * <note>This element is deprecated. Use #GstRawAudioParse instead.</note> */ #ifdef HAVE_CONFIG_H @@ -32,11 +34,34 @@ * for now with newer GLib versions (>= 2.31.0) */ #define GLIB_DISABLE_DEPRECATION_WARNINGS +#include <gst/gst.h> +#include <gst/audio/audio.h> #include "gstaudioparse.h" +#include "gstrawaudioparse.h" #include "unalignedaudio.h" #include <string.h> + +static GstStaticPadTemplate static_sink_template = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + + +static GstStaticPadTemplate static_src_template = + GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (GST_AUDIO_CAPS_MAKE (GST_AUDIO_FORMATS_ALL) + ", layout = (string) { interleaved, non-interleaved }; " + GST_UNALIGNED_RAW_AUDIO_CAPS "; " + "audio/x-alaw, rate=(int)[1,MAX], channels=(int)[1,MAX]; " + "audio/x-mulaw, rate=(int)[1,MAX], channels=(int)[1,MAX]") + ); + + typedef enum { GST_AUDIO_PARSE_FORMAT_RAW, @@ -44,21 +69,10 @@ typedef enum GST_AUDIO_PARSE_FORMAT_ALAW } GstAudioParseFormat; -typedef enum -{ - GST_AUDIO_PARSE_ENDIANNESS_LITTLE = 1234, - GST_AUDIO_PARSE_ENDIANNESS_BIG = 4321 -} GstAudioParseEndianness; - static void gst_audio_parse_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec); static void gst_audio_parse_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); -static void gst_audio_parse_finalize (GObject * object); - -static GstCaps *gst_audio_parse_get_caps (GstRawParse * rp); - -static void gst_audio_parse_update_frame_size (GstAudioParse * ap); GST_DEBUG_CATEGORY_STATIC (gst_audio_parse_debug); #define GST_CAT_DEFAULT gst_audio_parse_debug @@ -97,21 +111,16 @@ gst_audio_parse_format_get_type (void) #define gst_audio_parse_parent_class parent_class -G_DEFINE_TYPE (GstAudioParse, gst_audio_parse, GST_TYPE_RAW_PARSE); +G_DEFINE_TYPE (GstAudioParse, gst_audio_parse, GST_TYPE_BIN); static void gst_audio_parse_class_init (GstAudioParseClass * klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); - GstRawParseClass *rp_class = GST_RAW_PARSE_CLASS (klass); - GstCaps *caps; gobject_class->set_property = gst_audio_parse_set_property; gobject_class->get_property = gst_audio_parse_get_property; - gobject_class->finalize = gst_audio_parse_finalize; - - rp_class->get_caps = gst_audio_parse_get_caps; g_object_class_install_property (gobject_class, PROP_FORMAT, g_param_spec_enum ("format", "Format", @@ -155,18 +164,13 @@ gst_audio_parse_class_init (GstAudioParseClass * klass) gst_element_class_set_static_metadata (gstelement_class, "Audio Parse", "Filter/Audio", - "Converts stream into audio frames", + "Converts stream into audio frames (deprecated: use rawaudioparse instead)", "Sebastian Dröge <sebastian.droege@collabora.co.uk>"); - caps = gst_caps_from_string (GST_AUDIO_CAPS_MAKE (GST_AUDIO_FORMATS_ALL) - ", layout = (string) { interleaved, non-interleaved }; " - GST_UNALIGNED_RAW_AUDIO_CAPS "; " - "audio/x-alaw, rate=(int)[1,MAX], channels=(int)[1,MAX]; " - "audio/x-mulaw, rate=(int)[1,MAX], channels=(int)[1,MAX]"); - - gst_raw_parse_class_set_src_pad_template (rp_class, caps); - gst_raw_parse_class_set_multiple_frames_per_buffer (rp_class, TRUE); - gst_caps_unref (caps); + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&static_sink_template)); + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&static_src_template)); GST_DEBUG_CATEGORY_INIT (gst_audio_parse_debug, "audioparse", 0, "audioparse element"); @@ -175,13 +179,28 @@ gst_audio_parse_class_init (GstAudioParseClass * klass) static void gst_audio_parse_init (GstAudioParse * ap) { - ap->format = GST_AUDIO_PARSE_FORMAT_RAW; - ap->raw_format = GST_AUDIO_FORMAT_S16; - ap->channels = 2; - ap->interleaved = TRUE; - - gst_audio_parse_update_frame_size (ap); - gst_raw_parse_set_fps (GST_RAW_PARSE (ap), 44100, 1); + GstPad *inner_pad; + GstPad *ghostpad; + + ap->rawaudioparse = + gst_element_factory_make ("rawaudioparse", "inner_rawaudioparse"); + g_assert (ap->rawaudioparse != NULL); + + gst_bin_add (GST_BIN (ap), ap->rawaudioparse); + + inner_pad = gst_element_get_static_pad (ap->rawaudioparse, "sink"); + ghostpad = + gst_ghost_pad_new_from_template ("sink", inner_pad, + gst_element_class_get_pad_template (GST_ELEMENT_GET_CLASS (ap), "sink")); + gst_element_add_pad (GST_ELEMENT (ap), ghostpad); + gst_object_unref (GST_OBJECT (inner_pad)); + + inner_pad = gst_element_get_static_pad (ap->rawaudioparse, "src"); + ghostpad = + gst_ghost_pad_new_from_template ("src", inner_pad, + gst_element_class_get_pad_template (GST_ELEMENT_GET_CLASS (ap), "src")); + gst_element_add_pad (GST_ELEMENT (ap), ghostpad); + gst_object_unref (GST_OBJECT (inner_pad)); } static void @@ -190,39 +209,68 @@ gst_audio_parse_set_property (GObject * object, guint prop_id, { GstAudioParse *ap = GST_AUDIO_PARSE (object); - g_return_if_fail (!gst_raw_parse_is_negotiated (GST_RAW_PARSE (ap))); - switch (prop_id) { - case PROP_FORMAT: - ap->format = g_value_get_enum (value); + case PROP_FORMAT:{ + GstRawAudioParseFormat raw_parse_format; + + switch (g_value_get_enum (value)) { + case GST_AUDIO_PARSE_FORMAT_RAW: + raw_parse_format = GST_RAW_AUDIO_PARSE_FORMAT_PCM; + break; + + case GST_AUDIO_PARSE_FORMAT_MULAW: + raw_parse_format = GST_RAW_AUDIO_PARSE_FORMAT_MULAW; + break; + + case GST_AUDIO_PARSE_FORMAT_ALAW: + raw_parse_format = GST_RAW_AUDIO_PARSE_FORMAT_ALAW; + break; + + default: + g_assert_not_reached (); + break; + } + + g_object_set (G_OBJECT (ap->rawaudioparse), "format", raw_parse_format, + NULL); + break; + } + case PROP_RAW_FORMAT: - ap->raw_format = g_value_get_enum (value); + g_object_set (G_OBJECT (ap->rawaudioparse), "pcm-format", + g_value_get_enum (value), NULL); break; + case PROP_RATE: - gst_raw_parse_set_fps (GST_RAW_PARSE (ap), g_value_get_int (value), 1); + g_object_set (G_OBJECT (ap->rawaudioparse), "sample-rate", + g_value_get_int (value), NULL); break; + case PROP_CHANNELS: - ap->channels = g_value_get_int (value); + g_object_set (G_OBJECT (ap->rawaudioparse), "num-channels", + g_value_get_int (value), NULL); break; + case PROP_INTERLEAVED: - ap->interleaved = g_value_get_boolean (value); + g_object_set (G_OBJECT (ap->rawaudioparse), "interleaved", + g_value_get_boolean (value), NULL); break; - case PROP_CHANNEL_POSITIONS: - if (ap->channel_positions) - g_value_array_free (ap->channel_positions); - ap->channel_positions = g_value_dup_boxed (value); + case PROP_CHANNEL_POSITIONS: + g_object_set (G_OBJECT (ap->rawaudioparse), "channel-positions", + g_value_get_boxed (value), NULL); break; + case PROP_USE_SINK_CAPS: - ap->use_sink_caps = g_value_get_boolean (value); + g_object_set (G_OBJECT (ap->rawaudioparse), "use-sink-caps", + g_value_get_boolean (value), NULL); break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } - - gst_audio_parse_update_frame_size (ap); } static void @@ -232,226 +280,85 @@ gst_audio_parse_get_property (GObject * object, guint prop_id, GValue * value, GstAudioParse *ap = GST_AUDIO_PARSE (object); switch (prop_id) { - case PROP_FORMAT: - g_value_set_enum (value, ap->format); - break; - case PROP_RAW_FORMAT: - g_value_set_enum (value, ap->raw_format); - break; - case PROP_RATE:{ - gint fps_n, fps_d; + case PROP_FORMAT:{ + GstRawAudioParseFormat raw_parse_format; + GstAudioParseFormat format; - gst_raw_parse_get_fps (GST_RAW_PARSE (ap), &fps_n, &fps_d); - g_value_set_int (value, fps_n); - break; - } - case PROP_CHANNELS: - g_value_set_int (value, ap->channels); - break; - case PROP_INTERLEAVED: - g_value_set_boolean (value, ap->interleaved); - break; - case PROP_CHANNEL_POSITIONS: - g_value_set_boxed (value, ap->channel_positions); - break; - case PROP_USE_SINK_CAPS: - g_value_set_boolean (value, ap->use_sink_caps); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} + g_object_get (G_OBJECT (ap->rawaudioparse), "format", &raw_parse_format, + NULL); -static void -gst_audio_parse_finalize (GObject * object) -{ - GstAudioParse *ap = GST_AUDIO_PARSE (object); + switch (raw_parse_format) { + case GST_RAW_AUDIO_PARSE_FORMAT_PCM: + format = GST_AUDIO_PARSE_FORMAT_RAW; + break; - if (ap->channel_positions) { - g_value_array_free (ap->channel_positions); - ap->channel_positions = NULL; - } + case GST_RAW_AUDIO_PARSE_FORMAT_MULAW: + format = GST_AUDIO_PARSE_FORMAT_MULAW; + break; - g_free (ap->channel_pos); - g_free (ap->channel_order); + case GST_RAW_AUDIO_PARSE_FORMAT_ALAW: + format = GST_AUDIO_PARSE_FORMAT_ALAW; + break; - G_OBJECT_CLASS (parent_class)->finalize (object); -} + default: + g_assert_not_reached (); + break; + } -void -gst_audio_parse_update_frame_size (GstAudioParse * ap) -{ - gint framesize, width; + g_value_set_enum (value, format); - switch (ap->format) { - case GST_AUDIO_PARSE_FORMAT_ALAW: - case GST_AUDIO_PARSE_FORMAT_MULAW: - width = 8; break; - case GST_AUDIO_PARSE_FORMAT_RAW: - default: - { - GstAudioInfo info; + } - gst_audio_info_init (&info); - /* rate, etc do not really matter here */ - gst_audio_info_set_format (&info, ap->raw_format, 44100, ap->channels, - NULL); - width = GST_AUDIO_INFO_WIDTH (&info); + case PROP_RAW_FORMAT:{ + GstAudioFormat format; + g_object_get (G_OBJECT (ap->rawaudioparse), "pcm-format", &format, NULL); + g_value_set_enum (value, format); break; } - } - - framesize = (width / 8) * ap->channels; - - gst_raw_parse_set_framesize (GST_RAW_PARSE (ap), framesize); -} -static GstAudioChannelPosition * -gst_audio_parse_get_channel_positions (GValueArray * positions) -{ - gint i; - guint channels; - GstAudioChannelPosition *pos; - - channels = positions->n_values; - pos = g_new (GstAudioChannelPosition, positions->n_values); - - for (i = 0; i < channels; i++) { - GValue *v = g_value_array_get_nth (positions, i); - - pos[i] = g_value_get_enum (v); - } - - return pos; -} - -static void -gst_audio_parse_setup_channel_positions (GstAudioParse * ap) -{ - GstAudioChannelPosition *pos, *to; - - g_free (ap->channel_pos); - g_free (ap->channel_order); - ap->channel_pos = NULL; - ap->channel_order = NULL; - - if (!ap->channel_positions) { - GST_DEBUG_OBJECT (ap, "no channel positions"); - /* implicit mapping for 1- and 2-channel audio is okay */ - /* will come up with one in other cases also */ - return; - } - - pos = gst_audio_parse_get_channel_positions (ap->channel_positions); - if (ap->channels != ap->channel_positions->n_values || - !gst_audio_check_valid_channel_positions (pos, ap->channels, FALSE)) { - GST_DEBUG_OBJECT (ap, "invalid channel position"); - g_free (pos); - return; - } - - /* ok, got something we can work with now */ - to = g_new (GstAudioChannelPosition, ap->channels); - memcpy (to, pos, ap->channels * sizeof (to[0])); - gst_audio_channel_positions_to_valid_order (to, ap->channels); - - ap->channel_pos = pos; - ap->channel_order = to; -} - -static GstCaps * -gst_audio_parse_get_caps (GstRawParse * rp) -{ - GstAudioParse *ap = GST_AUDIO_PARSE (rp); - GstCaps *caps, *ncaps; - GstAudioInfo info; - gint fps_n, fps_d; - const GValue *val; - - if (ap->use_sink_caps) { - gint rate; - GstCaps *caps = gst_pad_get_current_caps (rp->sinkpad); - GstStructure *structure; - - if (!caps) { - GST_WARNING_OBJECT (ap, - "Sink pad has no caps, but we were asked to use its caps"); - return NULL; + case PROP_RATE:{ + gint sample_rate; + g_object_get (G_OBJECT (ap->rawaudioparse), "sample-rate", &sample_rate, + NULL); + g_value_set_int (value, sample_rate); + break; } - /* For unaligned raw data, the output caps stay the same, - * except that audio/x-unaligned-raw becomes audio/x-raw, - * since audioparse aligns the sample data */ - structure = gst_caps_get_structure (caps, 0); - if (gst_structure_has_name (structure, "audio/x-unaligned-raw")) { - caps = gst_caps_make_writable (caps); - structure = gst_caps_get_structure (caps, 0); - gst_structure_set_name (structure, "audio/x-raw"); + case PROP_CHANNELS:{ + gint num_channels; + g_object_get (G_OBJECT (ap->rawaudioparse), "num-channels", &num_channels, + NULL); + g_value_set_int (value, num_channels); + break; } - if (!gst_audio_info_from_caps (&info, caps)) { - GST_WARNING_OBJECT (ap, "Failed to parse caps %" GST_PTR_FORMAT, caps); - gst_caps_unref (caps); - return NULL; + case PROP_INTERLEAVED:{ + gboolean interleaved; + g_object_get (G_OBJECT (ap->rawaudioparse), "interleaved", &interleaved, + NULL); + g_value_set_boolean (value, interleaved); + break; } - ap->format = GST_AUDIO_PARSE_FORMAT_RAW; - ap->raw_format = GST_AUDIO_INFO_FORMAT (&info); - ap->channels = GST_AUDIO_INFO_CHANNELS (&info); - ap->interleaved = info.layout == GST_AUDIO_LAYOUT_INTERLEAVED; - - rate = GST_AUDIO_INFO_RATE (&info); - gst_raw_parse_set_fps (GST_RAW_PARSE (ap), rate, 1); - gst_audio_parse_update_frame_size (ap); - - return caps; - } - - gst_raw_parse_get_fps (rp, &fps_n, &fps_d); - gst_audio_parse_setup_channel_positions (ap); - - /* yes, even when format not raw */ - gst_audio_info_init (&info); - gst_audio_info_set_format (&info, ap->raw_format, fps_n, ap->channels, - ap->channel_order); - info.layout = ap->interleaved ? GST_AUDIO_LAYOUT_INTERLEAVED : - GST_AUDIO_LAYOUT_NON_INTERLEAVED; - caps = gst_audio_info_to_caps (&info); - - switch (ap->format) { - case GST_AUDIO_PARSE_FORMAT_RAW: - break; - case GST_AUDIO_PARSE_FORMAT_ALAW: - ncaps = gst_caps_new_simple ("audio/x-alaw", - "rate", G_TYPE_INT, fps_n, - "channels", G_TYPE_INT, ap->channels, NULL); - /* pick mask stuff from faked raw format */ - val = gst_structure_get_value (gst_caps_get_structure (caps, 0), - "channel-mask"); - if (val) - gst_caps_set_value (ncaps, "channel-mask", val); - gst_caps_unref (caps); - caps = ncaps; + case PROP_CHANNEL_POSITIONS:{ + gpointer channel_positions; + g_object_get (G_OBJECT (ap->rawaudioparse), "channel-positions", + &channel_positions, NULL); + g_value_set_boxed (value, channel_positions); break; - case GST_AUDIO_PARSE_FORMAT_MULAW: - ncaps = gst_caps_new_simple ("audio/x-mulaw", - "rate", G_TYPE_INT, fps_n, - "channels", G_TYPE_INT, ap->channels, NULL); - /* pick mask stuff from faked raw format */ - val = gst_structure_get_value (gst_caps_get_structure (caps, 0), - "channel-mask"); - if (val) - gst_caps_set_value (ncaps, "channel-mask", val); - gst_caps_unref (caps); - caps = ncaps; + } + + case PROP_USE_SINK_CAPS:{ + gboolean use_sink_caps; + g_object_get (G_OBJECT (ap->rawaudioparse), "use-sink-caps", + &use_sink_caps, NULL); + g_value_set_boolean (value, use_sink_caps); break; + } + default: - caps = gst_caps_new_empty (); - GST_ERROR_OBJECT (rp, "unexpected format %d", ap->format); + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } - - return caps; } diff --git a/gst/rawparse/gstaudioparse.h b/gst/rawparse/gstaudioparse.h index 2a357d9fd..efa573079 100644 --- a/gst/rawparse/gstaudioparse.h +++ b/gst/rawparse/gstaudioparse.h @@ -23,11 +23,6 @@ #define __GST_AUDIO_PARSE_H__ #include <gst/gst.h> -#include <gst/base/gstbasetransform.h> -#include <gst/base/gstadapter.h> -#include <gst/audio/audio.h> - -#include "gstrawparse.h" #define GST_TYPE_AUDIO_PARSE \ (gst_audio_parse_get_type()) @@ -45,23 +40,13 @@ typedef struct _GstAudioParseClass GstAudioParseClass; struct _GstAudioParse { - GstRawParse parent; - - /* properties */ - gboolean use_sink_caps; - gint format; - GstAudioFormat raw_format; - gint channels; - gboolean interleaved; - GValueArray *channel_positions; - - GstAudioChannelPosition *channel_pos; - GstAudioChannelPosition *channel_order; + GstBin parent; + GstElement *rawaudioparse; }; struct _GstAudioParseClass { - GstRawParseClass parent_class; + GstBinClass parent_class; }; diff --git a/gst/rawparse/gstrawparse.c b/gst/rawparse/gstrawparse.c deleted file mode 100644 index bd2ee110b..000000000 --- a/gst/rawparse/gstrawparse.c +++ /dev/null @@ -1,1105 +0,0 @@ -/* GStreamer - * Copyright (C) 2006 David A. Schleef <ds@schleef.org> - * Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org> - * - * gstrawparse.c: - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -/* TODO: - Add locking where appropiate - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include <string.h> - -#include <gst/gst.h> -#include <gst/base/gstbasetransform.h> -#include <gst/base/gstadapter.h> - -#include "gstrawparse.h" - -static void gst_raw_parse_dispose (GObject * object); - -static gboolean gst_raw_parse_sink_activate (GstPad * sinkpad, - GstObject * parent); -static gboolean gst_raw_parse_sink_activatemode (GstPad * sinkpad, - GstObject * parent, GstPadMode mode, gboolean active); -static void gst_raw_parse_loop (GstElement * element); -static GstStateChangeReturn gst_raw_parse_change_state (GstElement * element, - GstStateChange transition); -static GstFlowReturn gst_raw_parse_chain (GstPad * pad, GstObject * parent, - GstBuffer * buffer); -static gboolean gst_raw_parse_sink_event (GstPad * pad, GstObject * parent, - GstEvent * event); -static gboolean gst_raw_parse_src_event (GstPad * pad, GstObject * parent, - GstEvent * event); -static gboolean gst_raw_parse_src_query (GstPad * pad, GstObject * parent, - GstQuery * query); -static gboolean gst_raw_parse_convert (GstRawParse * rp, GstFormat src_format, - gint64 src_value, GstFormat dest_format, gint64 * dest_value); -static gboolean gst_raw_parse_handle_seek_pull (GstRawParse * rp, - GstEvent * event); - -static void gst_raw_parse_reset (GstRawParse * rp); - -static GstStaticPadTemplate gst_raw_parse_sink_pad_template = -GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS_ANY); - -GST_DEBUG_CATEGORY_STATIC (gst_raw_parse_debug); -#define GST_CAT_DEFAULT gst_raw_parse_debug - -static void gst_raw_parse_class_init (GstRawParseClass * klass); -static void gst_raw_parse_init (GstRawParse * clip, GstRawParseClass * g_class); - -static GstElementClass *parent_class; - -/* we can't use G_DEFINE_ABSTRACT_TYPE because we need the klass in the _init - * method to get to the padtemplates */ -GType -gst_raw_parse_get_type (void) -{ - static volatile gsize raw_parse_type = 0; - - if (g_once_init_enter (&raw_parse_type)) { - GType _type; - - _type = g_type_register_static_simple (GST_TYPE_ELEMENT, - "GstRawParse", sizeof (GstRawParseClass), - (GClassInitFunc) gst_raw_parse_class_init, sizeof (GstRawParse), - (GInstanceInitFunc) gst_raw_parse_init, G_TYPE_FLAG_ABSTRACT); - - g_once_init_leave (&raw_parse_type, _type); - } - return raw_parse_type; -} - -static void -gst_raw_parse_class_init (GstRawParseClass * 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_raw_parse_dispose; - - gstelement_class->change_state = - GST_DEBUG_FUNCPTR (gst_raw_parse_change_state); - - gst_element_class_add_static_pad_template (gstelement_class, - &gst_raw_parse_sink_pad_template); - - GST_DEBUG_CATEGORY_INIT (gst_raw_parse_debug, "rawparse", 0, - "rawparse element"); -} - -static void -gst_raw_parse_init (GstRawParse * rp, GstRawParseClass * g_class) -{ - GstPadTemplate *src_pad_template; - GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); - - rp->sinkpad = - gst_pad_new_from_static_template (&gst_raw_parse_sink_pad_template, - "sink"); - gst_pad_set_chain_function (rp->sinkpad, - GST_DEBUG_FUNCPTR (gst_raw_parse_chain)); - gst_pad_set_event_function (rp->sinkpad, - GST_DEBUG_FUNCPTR (gst_raw_parse_sink_event)); - gst_pad_set_activate_function (rp->sinkpad, - GST_DEBUG_FUNCPTR (gst_raw_parse_sink_activate)); - gst_pad_set_activatemode_function (rp->sinkpad, - GST_DEBUG_FUNCPTR (gst_raw_parse_sink_activatemode)); - gst_element_add_pad (GST_ELEMENT (rp), rp->sinkpad); - - src_pad_template = gst_element_class_get_pad_template (element_class, "src"); - - if (src_pad_template) { - rp->srcpad = gst_pad_new_from_template (src_pad_template, "src"); - } else { - g_warning ("Subclass didn't specify a src pad template"); - g_assert_not_reached (); - } - - gst_pad_set_event_function (rp->srcpad, - GST_DEBUG_FUNCPTR (gst_raw_parse_src_event)); - gst_pad_set_query_function (rp->srcpad, - GST_DEBUG_FUNCPTR (gst_raw_parse_src_query)); - gst_element_add_pad (GST_ELEMENT (rp), rp->srcpad); - - rp->adapter = gst_adapter_new (); - - rp->fps_n = 1; - rp->fps_d = 0; - rp->framesize = 1; - - gst_raw_parse_reset (rp); -} - -static void -gst_raw_parse_dispose (GObject * object) -{ - GstRawParse *rp = GST_RAW_PARSE (object); - - if (rp->adapter) { - g_object_unref (rp->adapter); - rp->adapter = NULL; - } - - G_OBJECT_CLASS (parent_class)->dispose (object); -} - -void -gst_raw_parse_class_set_src_pad_template (GstRawParseClass * klass, - const GstCaps * allowed_caps) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (klass); - - g_return_if_fail (GST_IS_RAW_PARSE_CLASS (klass)); - g_return_if_fail (allowed_caps != NULL); - g_return_if_fail (GST_IS_CAPS (allowed_caps)); - - gst_element_class_add_pad_template (element_class, - gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS, - gst_caps_copy (allowed_caps))); -} - -void -gst_raw_parse_class_set_multiple_frames_per_buffer (GstRawParseClass * klass, - gboolean multiple_frames) -{ - g_return_if_fail (GST_IS_RAW_PARSE_CLASS (klass)); - - klass->multiple_frames_per_buffer = multiple_frames; -} - -static void -gst_raw_parse_reset (GstRawParse * rp) -{ - rp->n_frames = 0; - rp->discont = TRUE; - rp->negotiated = FALSE; - - gst_segment_init (&rp->segment, GST_FORMAT_TIME); - gst_adapter_clear (rp->adapter); -} - -static gboolean -gst_raw_parse_set_src_caps (GstRawParse * rp) -{ - GstRawParseClass *rp_class = GST_RAW_PARSE_GET_CLASS (rp); - GstCaps *caps; - - if (rp->negotiated) - return TRUE; - - if (rp_class->get_caps) { - caps = rp_class->get_caps (rp); - } else { - GST_WARNING - ("Subclass doesn't implement get_caps() method, using ANY caps"); - caps = gst_caps_new_any (); - } - - rp->negotiated = gst_pad_set_caps (rp->srcpad, caps); - - /* if subclass inplement decide_allocation, send an allocation - * query, pass result to subclass and let it handle allocation if needed. */ - if (rp_class->decide_allocation) { - GstQuery *query; - - query = gst_query_new_allocation (caps, TRUE); - if (!gst_pad_peer_query (rp->srcpad, query)) { - /* not a problem, just debug a little */ - GST_DEBUG_OBJECT (rp, "peer ALLOCATION query failed"); - } - - rp_class->decide_allocation (rp, query); - gst_query_unref (query); - } - - gst_caps_unref (caps); - - return rp->negotiated; -} - -static GstFlowReturn -gst_raw_parse_push_buffer (GstRawParse * rp, GstBuffer * buffer) -{ - GstFlowReturn ret; - gint nframes; - GstRawParseClass *rpclass; - gsize size; - - rpclass = GST_RAW_PARSE_GET_CLASS (rp); - - size = gst_buffer_get_size (buffer); - nframes = size / rp->framesize; - - if (rp->segment.rate < 0) { - rp->n_frames -= nframes; - rp->discont = TRUE; - } - - GST_BUFFER_OFFSET (buffer) = rp->n_frames; - GST_BUFFER_OFFSET_END (buffer) = rp->n_frames + nframes; - - if (rp->fps_n) { - GST_BUFFER_TIMESTAMP (buffer) = - gst_util_uint64_scale (rp->n_frames, GST_SECOND * rp->fps_d, rp->fps_n); - GST_BUFFER_DURATION (buffer) = - gst_util_uint64_scale ((rp->n_frames + nframes) * GST_SECOND, rp->fps_d, - rp->fps_n) - GST_BUFFER_TIMESTAMP (buffer); - } else { - GST_BUFFER_TIMESTAMP (buffer) = rp->segment.start; - GST_BUFFER_DURATION (buffer) = GST_CLOCK_TIME_NONE; - } - - if (rpclass->pre_push_buffer) { - rpclass->pre_push_buffer (rp, buffer); - } - - if (rp->discont) { - GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT); - rp->discont = FALSE; - } - - if (rp->segment.rate >= 0) { - rp->offset += size; - rp->n_frames += nframes; - } - - rp->segment.position = GST_BUFFER_TIMESTAMP (buffer); - - GST_LOG_OBJECT (rp, "Pushing buffer with time %" GST_TIME_FORMAT, - GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer))); - - ret = gst_pad_push (rp->srcpad, buffer); - - return ret; -} - -static GstFlowReturn -gst_raw_parse_chain (GstPad * pad, GstObject * parent, GstBuffer * buffer) -{ - GstRawParse *rp = GST_RAW_PARSE (parent); - GstFlowReturn ret = GST_FLOW_OK; - GstRawParseClass *rp_class = GST_RAW_PARSE_GET_CLASS (rp); - guint buffersize, available; - - if (G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT))) { - GST_DEBUG_OBJECT (rp, "received DISCONT buffer"); - gst_adapter_clear (rp->adapter); - rp->discont = TRUE; - } - - if (!gst_raw_parse_set_src_caps (rp)) - goto no_caps; - - if (rp->start_segment) { - GST_DEBUG_OBJECT (rp, "sending start segment"); - gst_pad_push_event (rp->srcpad, rp->start_segment); - rp->start_segment = NULL; - } - - gst_adapter_push (rp->adapter, buffer); - - available = gst_adapter_available (rp->adapter); - if (rp_class->multiple_frames_per_buffer) { - buffersize = available; - buffersize -= buffersize % rp->framesize; - } else { - buffersize = rp->framesize; - } - - while (buffersize > 0 && gst_adapter_available (rp->adapter) >= buffersize) { - buffer = gst_adapter_take_buffer (rp->adapter, buffersize); - - ret = gst_raw_parse_push_buffer (rp, buffer); - if (ret != GST_FLOW_OK) - break; - } -done: - - return ret; - - /* ERRORS */ -no_caps: - { - GST_ERROR_OBJECT (rp, "could not set caps"); - ret = GST_FLOW_NOT_NEGOTIATED; - goto done; - } -} - -static void -gst_raw_parse_loop (GstElement * element) -{ - GstRawParse *rp = GST_RAW_PARSE (element); - GstRawParseClass *rp_class = GST_RAW_PARSE_GET_CLASS (rp); - GstFlowReturn ret; - GstBuffer *buffer; - gint size; - - if (G_UNLIKELY (rp->push_stream_start)) { - gchar *stream_id; - GstEvent *event; - - stream_id = - gst_pad_create_stream_id (rp->srcpad, GST_ELEMENT_CAST (rp), NULL); - - event = gst_event_new_stream_start (stream_id); - gst_event_set_group_id (event, gst_util_group_id_next ()); - - GST_DEBUG_OBJECT (rp, "Pushing STREAM_START"); - gst_pad_push_event (rp->srcpad, event); - rp->push_stream_start = FALSE; - g_free (stream_id); - } - - if (!gst_raw_parse_set_src_caps (rp)) - goto no_caps; - - if (rp->start_segment) { - GST_DEBUG_OBJECT (rp, "sending start segment"); - gst_pad_push_event (rp->srcpad, rp->start_segment); - rp->start_segment = NULL; - } - - if (rp_class->multiple_frames_per_buffer && rp->framesize < 4096) - size = 4096 - (4096 % rp->framesize); - else - size = rp->framesize; - - if (rp->segment.rate >= 0) { - if (rp->offset + size > rp->upstream_length) { - GstFormat fmt = GST_FORMAT_BYTES; - - if (!gst_pad_peer_query_duration (rp->sinkpad, fmt, &rp->upstream_length)) { - GST_WARNING_OBJECT (rp, - "Could not get upstream duration, trying to pull frame by frame"); - size = rp->framesize; - } else if (rp->upstream_length < rp->offset + rp->framesize) { - ret = GST_FLOW_EOS; - goto pause; - } else if (rp->offset + size > rp->upstream_length) { - size = rp->upstream_length - rp->offset; - size -= size % rp->framesize; - } - } - } else { - if (rp->offset == 0) { - ret = GST_FLOW_EOS; - goto pause; - } else if (rp->offset < size) { - size -= rp->offset; - } - rp->offset -= size; - } - - buffer = NULL; - ret = gst_pad_pull_range (rp->sinkpad, rp->offset, size, &buffer); - - if (ret != GST_FLOW_OK) { - GST_DEBUG_OBJECT (rp, "pull_range (%" G_GINT64_FORMAT ", %u) " - "failed, flow: %s", rp->offset, size, gst_flow_get_name (ret)); - buffer = NULL; - goto pause; - } - - if (gst_buffer_get_size (buffer) < size) { - GST_DEBUG_OBJECT (rp, "Short read at offset %" G_GINT64_FORMAT - ", got only %" G_GSIZE_FORMAT " of %u bytes", rp->offset, - gst_buffer_get_size (buffer), size); - - if (size > rp->framesize) { - gst_buffer_set_size (buffer, gst_buffer_get_size (buffer) - - gst_buffer_get_size (buffer) % rp->framesize); - } else { - gst_buffer_unref (buffer); - buffer = NULL; - ret = GST_FLOW_EOS; - goto pause; - } - } - - ret = gst_raw_parse_push_buffer (rp, buffer); - if (ret != GST_FLOW_OK) - goto pause; - - return; - - /* ERRORS */ -no_caps: - { - GST_ERROR_OBJECT (rp, "could not negotiate caps"); - ret = GST_FLOW_NOT_NEGOTIATED; - goto pause; - } -pause: - { - const gchar *reason = gst_flow_get_name (ret); - - GST_LOG_OBJECT (rp, "pausing task, reason %s", reason); - gst_pad_pause_task (rp->sinkpad); - - if (ret == GST_FLOW_EOS) { - if (rp->segment.flags & GST_SEEK_FLAG_SEGMENT) { - GstClockTime stop; - - GST_LOG_OBJECT (rp, "Sending segment done"); - - if ((stop = rp->segment.stop) == -1) - stop = rp->segment.duration; - - gst_element_post_message (GST_ELEMENT_CAST (rp), - gst_message_new_segment_done (GST_OBJECT_CAST (rp), - rp->segment.format, stop)); - gst_pad_push_event (rp->srcpad, - gst_event_new_segment_done (rp->segment.format, stop)); - } else { - GST_LOG_OBJECT (rp, "Sending EOS, at end of stream"); - gst_pad_push_event (rp->srcpad, gst_event_new_eos ()); - } - } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_EOS) { - GST_ELEMENT_ERROR (rp, STREAM, FAILED, - ("Internal data stream error."), - ("stream stopped, reason %s", reason)); - gst_pad_push_event (rp->srcpad, gst_event_new_eos ()); - } - return; - } -} - -static gboolean -gst_raw_parse_sink_activate (GstPad * sinkpad, GstObject * parent) -{ - GstQuery *query; - gboolean pull_mode = FALSE; - - query = gst_query_new_scheduling (); - - if (gst_pad_peer_query (sinkpad, query)) - pull_mode = gst_query_has_scheduling_mode_with_flags (query, - GST_PAD_MODE_PULL, GST_SCHEDULING_FLAG_SEEKABLE); - - gst_query_unref (query); - - if (pull_mode) { - GST_DEBUG ("going to pull mode"); - return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PULL, TRUE); - } else { - GST_DEBUG ("going to push (streaming) mode"); - return gst_pad_activate_mode (sinkpad, GST_PAD_MODE_PUSH, TRUE); - } -} - -static gboolean -gst_raw_parse_sink_activatemode (GstPad * sinkpad, GstObject * parent, - GstPadMode mode, gboolean active) -{ - GstRawParse *rp = GST_RAW_PARSE (parent); - gboolean result; - - switch (mode) { - case GST_PAD_MODE_PULL: - if (active) { - GstFormat format; - gint64 duration; - - /* get the duration in bytes */ - format = GST_FORMAT_BYTES; - result = gst_pad_peer_query_duration (sinkpad, format, &duration); - if (result) { - GST_DEBUG_OBJECT (rp, "got duration %" GST_TIME_FORMAT, - GST_TIME_ARGS (duration)); - rp->upstream_length = duration; - /* convert to time */ - gst_raw_parse_convert (rp, format, duration, GST_FORMAT_TIME, - &duration); - } else { - rp->upstream_length = -1; - duration = -1; - } - rp->segment.duration = duration; - - rp->push_stream_start = TRUE; - - result = gst_raw_parse_handle_seek_pull (rp, NULL); - rp->mode = mode; - } else { - result = gst_pad_stop_task (sinkpad); - } - return result; - case GST_PAD_MODE_PUSH: - rp->mode = mode; - return TRUE; - default: - return FALSE; - } -} - -static GstStateChangeReturn -gst_raw_parse_change_state (GstElement * element, GstStateChange transition) -{ - GstRawParse *rp = GST_RAW_PARSE (element); - GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; - - switch (transition) { - case GST_STATE_CHANGE_READY_TO_PAUSED: - gst_segment_init (&rp->segment, GST_FORMAT_TIME); - rp->segment.position = 0; - default: - break; - } - - if (GST_ELEMENT_CLASS (parent_class)->change_state) - ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); - - switch (transition) { - case GST_STATE_CHANGE_PAUSED_TO_READY: - gst_raw_parse_reset (rp); - break; - default: - break; - } - - return ret; -} - -static gboolean -gst_raw_parse_convert (GstRawParse * rp, - GstFormat src_format, gint64 src_value, - GstFormat dest_format, gint64 * dest_value) -{ - gboolean ret = FALSE; - - GST_DEBUG ("converting value %" G_GINT64_FORMAT " from %s (%d) to %s (%d)", - src_value, gst_format_get_name (src_format), src_format, - gst_format_get_name (dest_format), dest_format); - - if (src_format == dest_format) { - *dest_value = src_value; - ret = TRUE; - goto done; - } - - if (src_value == -1) { - *dest_value = -1; - ret = TRUE; - goto done; - } - - /* bytes to frames */ - if (src_format == GST_FORMAT_BYTES && dest_format == GST_FORMAT_DEFAULT) { - if (rp->framesize != 0) { - *dest_value = gst_util_uint64_scale_int (src_value, 1, rp->framesize); - } else { - GST_ERROR ("framesize is 0"); - *dest_value = 0; - } - ret = TRUE; - goto done; - } - - /* frames to bytes */ - if (src_format == GST_FORMAT_DEFAULT && dest_format == GST_FORMAT_BYTES) { - *dest_value = gst_util_uint64_scale_int (src_value, rp->framesize, 1); - ret = TRUE; - goto done; - } - - /* time to frames */ - if (src_format == GST_FORMAT_TIME && dest_format == GST_FORMAT_DEFAULT) { - if (rp->fps_d != 0) { - *dest_value = gst_util_uint64_scale (src_value, - rp->fps_n, GST_SECOND * rp->fps_d); - } else { - GST_ERROR ("framerate denominator is 0"); - *dest_value = 0; - } - ret = TRUE; - goto done; - } - - /* frames to time */ - if (src_format == GST_FORMAT_DEFAULT && dest_format == GST_FORMAT_TIME) { - if (rp->fps_n != 0) { - *dest_value = gst_util_uint64_scale (src_value, - GST_SECOND * rp->fps_d, rp->fps_n); - } else { - GST_ERROR ("framerate numerator is 0"); - *dest_value = 0; - } - ret = TRUE; - goto done; - } - - /* time to bytes */ - if (src_format == GST_FORMAT_TIME && dest_format == GST_FORMAT_BYTES) { - if (rp->fps_d != 0) { - *dest_value = gst_util_uint64_scale (src_value, - rp->fps_n * rp->framesize, GST_SECOND * rp->fps_d); - } else { - GST_ERROR ("framerate denominator is 0"); - *dest_value = 0; - } - ret = TRUE; - goto done; - } - - /* bytes to time */ - if (src_format == GST_FORMAT_BYTES && dest_format == GST_FORMAT_TIME) { - if (rp->fps_n != 0 && rp->framesize != 0) { - *dest_value = gst_util_uint64_scale (src_value, - GST_SECOND * rp->fps_d, rp->fps_n * rp->framesize); - } else { - GST_ERROR ("framerate denominator and/or framesize is 0"); - *dest_value = 0; - } - ret = TRUE; - } - -done: - - GST_DEBUG ("ret=%d result %" G_GINT64_FORMAT, ret, *dest_value); - - return ret; -} - - -static gboolean -gst_raw_parse_sink_event (GstPad * pad, GstObject * parent, GstEvent * event) -{ - GstRawParse *rp = GST_RAW_PARSE (parent); - gboolean ret; - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_EOS: - case GST_EVENT_FLUSH_STOP: - /* Only happens in push mode */ - gst_raw_parse_reset (rp); - ret = gst_pad_push_event (rp->srcpad, event); - break; - case GST_EVENT_SEGMENT: - { - GstSegment segment; - - /* Only happens in push mode */ - - gst_event_copy_segment (event, &segment); - - if (segment.format != GST_FORMAT_TIME) { - gst_event_unref (event); - - ret = - gst_raw_parse_convert (rp, segment.format, segment.start, - GST_FORMAT_TIME, (gint64 *) & segment.start); - ret &= gst_raw_parse_convert (rp, segment.format, segment.time, - GST_FORMAT_TIME, (gint64 *) & segment.time); - ret &= gst_raw_parse_convert (rp, segment.format, segment.stop, - GST_FORMAT_TIME, (gint64 *) & segment.stop); - if (!ret) { - GST_ERROR_OBJECT (rp, - "Failed converting to GST_FORMAT_TIME format (%d)", - segment.format); - break; - } - - segment.format = GST_FORMAT_TIME; - - event = gst_event_new_segment (&segment); - } - - gst_segment_copy_into (&segment, &rp->segment); - - if (rp->start_segment) - gst_event_unref (rp->start_segment); - rp->start_segment = event; - ret = TRUE; - break; - } - default: - ret = gst_pad_event_default (pad, parent, event); - break; - } - - return ret; -} - - -static gboolean -gst_raw_parse_handle_seek_push (GstRawParse * rp, GstEvent * event) -{ - GstFormat format; - gdouble rate; - GstSeekFlags flags; - GstSeekType start_type, stop_type; - gint64 start, stop; - gboolean ret = FALSE; - - gst_event_parse_seek (event, &rate, &format, &flags, &start_type, &start, - &stop_type, &stop); - - /* can't seek backwards yet */ - if (rate <= 0.0) - goto wrong_rate; - - /* First try if upstream handles the seek */ - ret = gst_pad_push_event (rp->sinkpad, event); - if (ret) - return ret; - - /* Otherwise convert to bytes and push upstream */ - if (format == GST_FORMAT_TIME || format == GST_FORMAT_DEFAULT) { - ret = gst_raw_parse_convert (rp, format, start, GST_FORMAT_BYTES, &start); - ret &= gst_raw_parse_convert (rp, format, stop, GST_FORMAT_BYTES, &stop); - - if (ret) { - /* Seek on a frame boundary */ - start -= start % rp->framesize; - if (stop != -1) - stop += rp->framesize - stop % rp->framesize; - - event = - gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, start_type, - start, stop_type, stop); - - ret = gst_pad_push_event (rp->sinkpad, event); - } else { - GST_DEBUG_OBJECT (rp, "Seek failed: couldn't convert to byte positions"); - } - } else { - GST_DEBUG_OBJECT (rp, - "seeking is only supported in TIME or DEFAULT format"); - } - return ret; - - /* ERRORS */ -wrong_rate: - { - GST_DEBUG_OBJECT (rp, "Seek failed: negative rates not supported yet"); - return FALSE; - } -} - -static gboolean -gst_raw_parse_handle_seek_pull (GstRawParse * rp, GstEvent * event) -{ - gdouble rate; - GstFormat format; - GstSeekFlags flags; - GstSeekType start_type, stop_type; - gint64 start, stop; - gint64 last_stop; - gboolean ret = FALSE; - gboolean flush; - GstSegment seeksegment; - - if (event) { - gst_event_parse_seek (event, &rate, &format, &flags, &start_type, &start, - &stop_type, &stop); - - /* convert input offsets to time */ - ret = gst_raw_parse_convert (rp, format, start, GST_FORMAT_TIME, &start); - ret &= gst_raw_parse_convert (rp, format, stop, GST_FORMAT_TIME, &stop); - if (!ret) - goto convert_failed; - - GST_DEBUG_OBJECT (rp, "converted start - stop to time"); - - gst_event_unref (event); - } else { - flags = 0; - } - - format = GST_FORMAT_TIME; - - flush = ((flags & GST_SEEK_FLAG_FLUSH) != 0); - - /* start flushing up and downstream so that the loop function pauses and we - * can acquire the STREAM_LOCK. */ - if (flush) { - GST_LOG_OBJECT (rp, "flushing"); - gst_pad_push_event (rp->sinkpad, gst_event_new_flush_start ()); - gst_pad_push_event (rp->srcpad, gst_event_new_flush_start ()); - } else { - GST_LOG_OBJECT (rp, "pause task"); - gst_pad_pause_task (rp->sinkpad); - } - - GST_PAD_STREAM_LOCK (rp->sinkpad); - - memcpy (&seeksegment, &rp->segment, sizeof (GstSegment)); - - if (event) { - /* configure the seek values */ - gst_segment_do_seek (&seeksegment, rate, format, flags, - start_type, start, stop_type, stop, NULL); - } - - /* get the desired position */ - last_stop = seeksegment.position; - - GST_LOG_OBJECT (rp, "seeking to %" GST_TIME_FORMAT, - GST_TIME_ARGS (last_stop)); - - /* convert the desired position to bytes */ - ret = - gst_raw_parse_convert (rp, format, last_stop, GST_FORMAT_BYTES, - &last_stop); - - /* prepare for streaming */ - if (flush) { - GST_LOG_OBJECT (rp, "stop flush"); - gst_pad_push_event (rp->sinkpad, gst_event_new_flush_stop (TRUE)); - gst_pad_push_event (rp->srcpad, gst_event_new_flush_stop (TRUE)); - } - - if (ret) { - /* seek done */ - - /* Seek on a frame boundary */ - last_stop -= last_stop % rp->framesize; - - rp->offset = last_stop; - rp->n_frames = last_stop / rp->framesize; - - GST_LOG_OBJECT (rp, "seeking to bytes %" G_GINT64_FORMAT, last_stop); - - memcpy (&rp->segment, &seeksegment, sizeof (GstSegment)); - - if (rp->segment.flags & GST_SEEK_FLAG_SEGMENT) { - gst_element_post_message (GST_ELEMENT_CAST (rp), - gst_message_new_segment_start (GST_OBJECT_CAST (rp), - rp->segment.format, rp->segment.position)); - } - - /* for deriving a stop position for the playback segment from the seek - * segment, we must take the duration when the stop is not set */ - if ((stop = rp->segment.stop) == -1) - stop = rp->segment.duration; - - GST_DEBUG_OBJECT (rp, "preparing newsegment from %" G_GINT64_FORMAT - " to %" G_GINT64_FORMAT, rp->segment.start, stop); - - /* now replace the old segment so that we send it in the stream thread the - * next time it is scheduled. */ - if (rp->start_segment) - gst_event_unref (rp->start_segment); - rp->start_segment = gst_event_new_segment (&rp->segment); - } - rp->discont = TRUE; - - GST_LOG_OBJECT (rp, "start streaming"); - gst_pad_start_task (rp->sinkpad, (GstTaskFunction) gst_raw_parse_loop, rp, - NULL); - - GST_PAD_STREAM_UNLOCK (rp->sinkpad); - - return ret; - - /* ERRORS */ -convert_failed: - { - GST_DEBUG_OBJECT (rp, "Seek failed: couldn't convert to byte positions"); - return FALSE; - } -} - -static gboolean -gst_raw_parse_src_event (GstPad * pad, GstObject * parent, GstEvent * event) -{ - GstRawParse *rp = GST_RAW_PARSE (parent); - gboolean ret; - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_SEEK: - if (rp->mode == GST_PAD_MODE_PUSH) - ret = gst_raw_parse_handle_seek_push (rp, event); - else - ret = gst_raw_parse_handle_seek_pull (rp, event); - break; - default: - ret = gst_pad_event_default (pad, parent, event); - break; - } - - return ret; -} - -static gboolean -gst_raw_parse_src_query (GstPad * pad, GstObject * parent, GstQuery * query) -{ - GstRawParse *rp = GST_RAW_PARSE (parent); - gboolean ret = FALSE; - - GST_DEBUG ("src_query %s", gst_query_type_get_name (GST_QUERY_TYPE (query))); - - switch (GST_QUERY_TYPE (query)) { - case GST_QUERY_POSITION: - { - GstFormat format; - gint64 time, value; - - GST_LOG ("query position"); - - gst_query_parse_position (query, &format, NULL); - - time = rp->segment.position; - ret = gst_raw_parse_convert (rp, GST_FORMAT_TIME, time, format, &value); - - gst_query_set_position (query, format, value); - - break; - } - case GST_QUERY_DURATION:{ - gint64 duration; - GstFormat format; - GstQuery *bquery; - - GST_LOG ("query duration"); - ret = gst_pad_peer_query (rp->sinkpad, query); - if (ret) - goto done; - - gst_query_parse_duration (query, &format, NULL); - /* We only handle TIME and DEFAULT format */ - if (format != GST_FORMAT_TIME && format != GST_FORMAT_DEFAULT) - goto error; - - bquery = gst_query_new_duration (GST_FORMAT_BYTES); - ret = gst_pad_peer_query (rp->sinkpad, bquery); - if (!ret) { - gst_query_unref (bquery); - goto error; - } - - gst_query_parse_duration (bquery, NULL, &duration); - gst_query_unref (bquery); - - ret = - gst_raw_parse_convert (rp, GST_FORMAT_BYTES, duration, format, - &duration); - if (ret) - gst_query_set_duration (query, format, duration); - - break; - } - case GST_QUERY_CONVERT: - { - GstFormat src_fmt, dest_fmt; - gint64 src_val, dest_val; - - GST_LOG ("query convert"); - - gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val); - ret = gst_raw_parse_convert (rp, src_fmt, src_val, dest_fmt, &dest_val); - if (!ret) - goto error; - gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val); - break; - } - case GST_QUERY_SEEKING:{ - GstFormat fmt; - - ret = TRUE; - - /* try upstream first */ - if (gst_pad_peer_query (rp->sinkpad, query)) - break; - - gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL); - if (fmt != GST_FORMAT_TIME && fmt != GST_FORMAT_DEFAULT - && fmt != GST_FORMAT_BYTES) { - gst_query_set_seeking (query, fmt, FALSE, -1, -1); - } else if (rp->mode == GST_PAD_MODE_PUSH) { - GstQuery *peerquery = gst_query_new_seeking (GST_FORMAT_BYTES); - gboolean seekable; - - seekable = gst_pad_peer_query (rp->sinkpad, peerquery); - if (seekable) - gst_query_parse_seeking (peerquery, NULL, &seekable, NULL, NULL); - - gst_query_unref (peerquery); - gst_query_set_seeking (query, fmt, seekable, seekable ? 0 : -1, -1); - } else { - gst_query_set_seeking (query, fmt, TRUE, 0, -1); - } - break; - } - default: - /* else forward upstream */ - ret = gst_pad_query_default (pad, parent, query); - break; - } - -done: - return ret; - - /* ERRORS */ -error: - { - GST_DEBUG_OBJECT (rp, "query failed"); - goto done; - } -} - -void -gst_raw_parse_set_framesize (GstRawParse * rp, int framesize) -{ - g_return_if_fail (GST_IS_RAW_PARSE (rp)); - g_return_if_fail (!rp->negotiated); - - GST_DEBUG_OBJECT (rp, "framesize %d", framesize); - rp->framesize = framesize; -} - -void -gst_raw_parse_set_fps (GstRawParse * rp, int fps_n, int fps_d) -{ - g_return_if_fail (GST_IS_RAW_PARSE (rp)); - g_return_if_fail (!rp->negotiated); - - rp->fps_n = fps_n; - rp->fps_d = fps_d; -} - -void -gst_raw_parse_get_fps (GstRawParse * rp, int *fps_n, int *fps_d) -{ - g_return_if_fail (GST_IS_RAW_PARSE (rp)); - - if (fps_n) - *fps_n = rp->fps_n; - if (fps_d) - *fps_d = rp->fps_d; -} - -gboolean -gst_raw_parse_is_negotiated (GstRawParse * rp) -{ - g_return_val_if_fail (GST_IS_RAW_PARSE (rp), FALSE); - - return rp->negotiated; -} diff --git a/gst/rawparse/gstrawparse.h b/gst/rawparse/gstrawparse.h deleted file mode 100644 index 2327dc6fb..000000000 --- a/gst/rawparse/gstrawparse.h +++ /dev/null @@ -1,98 +0,0 @@ -/* GStreamer - * Copyright (C) 2006 David A. Schleef <ds@schleef.org> - * Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org> - * - * gstrawparse.h: - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, - * Boston, MA 02110-1301, USA. - */ - -#ifndef __GST_RAW_PARSE_H__ -#define __GST_RAW_PARSE_H__ - -#include <gst/gst.h> -#include <gst/base/gstbasetransform.h> -#include <gst/base/gstadapter.h> - -G_BEGIN_DECLS - -#define GST_TYPE_RAW_PARSE \ - (gst_raw_parse_get_type()) -#define GST_RAW_PARSE(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_RAW_PARSE,GstRawParse)) -#define GST_RAW_PARSE_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_RAW_PARSE,GstRawParseClass)) -#define GST_RAW_PARSE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),GST_TYPE_RAW_PARSE,GstRawParseClass)) -#define GST_IS_RAW_PARSE(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_RAW_PARSE)) -#define GST_IS_RAW_PARSE_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_RAW_PARSE)) - -typedef struct _GstRawParse GstRawParse; -typedef struct _GstRawParseClass GstRawParseClass; - -struct _GstRawParse -{ - GstElement parent; - - /* <private> */ - GstPad *sinkpad; - GstPad *srcpad; - - GstPadMode mode; - GstAdapter *adapter; - - gint framesize; - gint fps_d; - gint fps_n; - - gboolean discont; - guint64 n_frames; - - gint64 upstream_length; - gint64 offset; - - GstSegment segment; - GstEvent *start_segment; - - gboolean negotiated; - gboolean push_stream_start; -}; - -struct _GstRawParseClass -{ - GstElementClass parent_class; - - GstCaps * (*get_caps) (GstRawParse *rp); - void (*pre_push_buffer) (GstRawParse *rp, GstBuffer *buffer); - void (*decide_allocation) (GstRawParse *rp, GstQuery *query); - - gboolean multiple_frames_per_buffer; -}; - -GType gst_raw_parse_get_type (void); - -void gst_raw_parse_class_set_src_pad_template (GstRawParseClass *klass, const GstCaps * allowed_caps); -void gst_raw_parse_class_set_multiple_frames_per_buffer (GstRawParseClass *klass, gboolean multiple_frames); - -void gst_raw_parse_set_framesize (GstRawParse *rp, int framesize); -void gst_raw_parse_set_fps (GstRawParse *rp, int fps_n, int fps_d); -void gst_raw_parse_get_fps (GstRawParse *rp, int *fps_n, int *fps_d); -gboolean gst_raw_parse_is_negotiated (GstRawParse *rp); - -G_END_DECLS - -#endif /* __GST_RAW_PARSE_H__ */ diff --git a/gst/rawparse/gstvideoparse.c b/gst/rawparse/gstvideoparse.c index 7b5e03719..cf5c48e1f 100644 --- a/gst/rawparse/gstvideoparse.c +++ b/gst/rawparse/gstvideoparse.c @@ -23,28 +23,47 @@ * SECTION:element-videoparse * * Converts a byte stream into video frames. + * + * <note>This element is deprecated. Use #GstRawVideoParse instead.</note> */ #ifdef HAVE_CONFIG_H # include "config.h" #endif +/* FIXME 0.11: suppress warnings for deprecated API such as g_value_array stuff + * for now with newer GLib versions (>= 2.31.0) */ +#define GLIB_DISABLE_DEPRECATION_WARNINGS + +#include <gst/gst.h> +#include <gst/audio/audio.h> #include "gstvideoparse.h" +#include "gstrawvideoparse.h" + + +static GstStaticPadTemplate static_sink_template = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + + +static GstStaticPadTemplate static_src_template = +GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("video/x-raw") + ); + static void gst_video_parse_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec); static void gst_video_parse_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); -static GstCaps *gst_video_parse_get_caps (GstRawParse * rp); -static void gst_video_parse_pre_push_buffer (GstRawParse * rp, - GstBuffer * buffer); -static void gst_video_parse_decide_allocation (GstRawParse * rp, - GstQuery * query); - -static void gst_video_parse_update_info (GstVideoParse * vp); -static gboolean gst_video_parse_deserialize_int_array (const gchar * str, - gint * dest, guint n_values); +static GValueArray *gst_video_parse_int_valarray_from_string (const gchar * + str); +static gchar *gst_video_parse_int_valarray_to_string (GValueArray * valarray); GST_DEBUG_CATEGORY_STATIC (gst_video_parse_debug); #define GST_CAT_DEFAULT gst_video_parse_debug @@ -65,23 +84,17 @@ enum }; #define gst_video_parse_parent_class parent_class -G_DEFINE_TYPE (GstVideoParse, gst_video_parse, GST_TYPE_RAW_PARSE); +G_DEFINE_TYPE (GstVideoParse, gst_video_parse, GST_TYPE_BIN); static void gst_video_parse_class_init (GstVideoParseClass * klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); - GstRawParseClass *rp_class = GST_RAW_PARSE_CLASS (klass); - GstCaps *caps; gobject_class->set_property = gst_video_parse_set_property; gobject_class->get_property = gst_video_parse_get_property; - rp_class->get_caps = gst_video_parse_get_caps; - rp_class->pre_push_buffer = gst_video_parse_pre_push_buffer; - rp_class->decide_allocation = gst_video_parse_decide_allocation; - g_object_class_install_property (gobject_class, PROP_FORMAT, g_param_spec_enum ("format", "Format", "Format of images in raw stream", GST_TYPE_VIDEO_FORMAT, GST_VIDEO_FORMAT_I420, @@ -123,15 +136,14 @@ gst_video_parse_class_init (GstVideoParseClass * klass) gst_element_class_set_static_metadata (gstelement_class, "Video Parse", "Filter/Video", - "Converts stream into video frames", + "Converts stream into video frames (deprecated: use rawvideoparse instead)", "David Schleef <ds@schleef.org>, " "Sebastian Dröge <sebastian.droege@collabora.co.uk>"); - caps = gst_caps_from_string ("video/x-raw; video/x-bayer"); - - gst_raw_parse_class_set_src_pad_template (rp_class, caps); - gst_raw_parse_class_set_multiple_frames_per_buffer (rp_class, FALSE); - gst_caps_unref (caps); + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&static_sink_template)); + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&static_src_template)); GST_DEBUG_CATEGORY_INIT (gst_video_parse_debug, "videoparse", 0, "videoparse element"); @@ -140,14 +152,28 @@ gst_video_parse_class_init (GstVideoParseClass * klass) static void gst_video_parse_init (GstVideoParse * vp) { - vp->width = 320; - vp->height = 240; - vp->format = GST_VIDEO_FORMAT_I420; - vp->par_n = 1; - vp->par_d = 1; - - gst_raw_parse_set_fps (GST_RAW_PARSE (vp), 25, 1); - gst_video_parse_update_info (vp); + GstPad *inner_pad; + GstPad *ghostpad; + + vp->rawvideoparse = + gst_element_factory_make ("rawvideoparse", "inner_rawvideoparse"); + g_assert (vp->rawvideoparse != NULL); + + gst_bin_add (GST_BIN (vp), vp->rawvideoparse); + + inner_pad = gst_element_get_static_pad (vp->rawvideoparse, "sink"); + ghostpad = + gst_ghost_pad_new_from_template ("sink", inner_pad, + gst_element_class_get_pad_template (GST_ELEMENT_GET_CLASS (vp), "sink")); + gst_element_add_pad (GST_ELEMENT (vp), ghostpad); + gst_object_unref (GST_OBJECT (inner_pad)); + + inner_pad = gst_element_get_static_pad (vp->rawvideoparse, "src"); + ghostpad = + gst_ghost_pad_new_from_template ("src", inner_pad, + gst_element_class_get_pad_template (GST_ELEMENT_GET_CLASS (vp), "src")); + gst_element_add_pad (GST_ELEMENT (vp), ghostpad); + gst_object_unref (GST_OBJECT (inner_pad)); } static void @@ -156,62 +182,83 @@ gst_video_parse_set_property (GObject * object, guint prop_id, { GstVideoParse *vp = GST_VIDEO_PARSE (object); - g_return_if_fail (!gst_raw_parse_is_negotiated (GST_RAW_PARSE (vp))); - switch (prop_id) { case PROP_FORMAT: - vp->format = g_value_get_enum (value); + g_object_set (G_OBJECT (vp->rawvideoparse), "format", + g_value_get_enum (value), NULL); break; + case PROP_WIDTH: - vp->width = g_value_get_int (value); + g_object_set (G_OBJECT (vp->rawvideoparse), "width", + g_value_get_int (value), NULL); break; + case PROP_HEIGHT: - vp->height = g_value_get_int (value); + g_object_set (G_OBJECT (vp->rawvideoparse), "height", + g_value_get_int (value), NULL); break; + case PROP_FRAMERATE: - gst_raw_parse_set_fps (GST_RAW_PARSE (vp), + g_object_set (G_OBJECT (vp->rawvideoparse), "framerate", gst_value_get_fraction_numerator (value), - gst_value_get_fraction_denominator (value)); + gst_value_get_fraction_denominator (value), NULL); break; + case PROP_PAR: - vp->par_n = gst_value_get_fraction_numerator (value); - vp->par_d = gst_value_get_fraction_denominator (value); + g_object_set (G_OBJECT (vp->rawvideoparse), "pixel-aspect-ratio", + gst_value_get_fraction_numerator (value), + gst_value_get_fraction_denominator (value), NULL); break; + case PROP_INTERLACED: - vp->interlaced = g_value_get_boolean (value); + g_object_set (G_OBJECT (vp->rawvideoparse), "interlaced", + g_value_get_boolean (value), NULL); break; + case PROP_TOP_FIELD_FIRST: - vp->top_field_first = g_value_get_boolean (value); + g_object_set (G_OBJECT (vp->rawvideoparse), "top-field-first", + g_value_get_boolean (value), NULL); break; - case PROP_STRIDES: - if (gst_video_parse_deserialize_int_array (g_value_get_string (value), - vp->stride, GST_VIDEO_MAX_PLANES)) { - vp->stride_set = TRUE; + + case PROP_STRIDES:{ + GValueArray *valarray = + gst_video_parse_int_valarray_from_string (g_value_get_string (value)); + + if (valarray != NULL) { + g_object_set (G_OBJECT (vp->rawvideoparse), "plane-strides", + valarray, NULL); + g_value_array_free (valarray); } else { GST_WARNING_OBJECT (vp, "failed to deserialize given strides"); - vp->stride_set = FALSE; } break; - case PROP_OFFSETS: - if (gst_video_parse_deserialize_int_array (g_value_get_string (value), - vp->offset, GST_VIDEO_MAX_PLANES)) { - vp->offset_set = TRUE; + } + + case PROP_OFFSETS:{ + GValueArray *valarray = + gst_video_parse_int_valarray_from_string (g_value_get_string (value)); + + if (valarray != NULL) { + g_object_set (G_OBJECT (vp->rawvideoparse), "plane-offsets", + valarray, NULL); + g_value_array_free (valarray); } else { - GST_WARNING_OBJECT (vp, "failed to deserialized given offsets"); - vp->offset_set = FALSE; + GST_WARNING_OBJECT (vp, "failed to deserialize given offsets"); } break; + } + case PROP_FRAMESIZE: - vp->framesize = g_value_get_uint (value); + g_object_set (G_OBJECT (vp->rawvideoparse), "frame-stride", + g_value_get_uint (value), NULL); break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } - - gst_video_parse_update_info (vp); } static void @@ -221,377 +268,155 @@ gst_video_parse_get_property (GObject * object, guint prop_id, GValue * value, GstVideoParse *vp = GST_VIDEO_PARSE (object); switch (prop_id) { - case PROP_FORMAT: - g_value_set_enum (value, vp->format); + case PROP_FORMAT:{ + GstVideoFormat format; + g_object_get (G_OBJECT (vp->rawvideoparse), "format", &format, NULL); + g_value_set_enum (value, format); break; - case PROP_WIDTH: - g_value_set_int (value, vp->width); + } + + case PROP_WIDTH:{ + gint width; + g_object_get (G_OBJECT (vp->rawvideoparse), "width", &width, NULL); + g_value_set_int (value, width); break; - case PROP_HEIGHT: - g_value_set_int (value, vp->height); + } + + case PROP_HEIGHT:{ + gint height; + g_object_get (G_OBJECT (vp->rawvideoparse), "height", &height, NULL); + g_value_set_int (value, height); break; + } + case PROP_FRAMERATE:{ gint fps_n, fps_d; - - gst_raw_parse_get_fps (GST_RAW_PARSE (vp), &fps_n, &fps_d); + g_object_get (G_OBJECT (vp->rawvideoparse), "framerate", &fps_n, &fps_d, + NULL); gst_value_set_fraction (value, fps_n, fps_d); break; } - case PROP_PAR: - gst_value_set_fraction (value, vp->par_n, vp->par_d); + + case PROP_PAR:{ + gint par_n, par_d; + g_object_get (G_OBJECT (vp->rawvideoparse), "pixel-aspect-ratio", &par_n, + &par_d, NULL); + gst_value_set_fraction (value, par_n, par_d); break; - case PROP_INTERLACED: - g_value_set_boolean (value, vp->interlaced); + } + + case PROP_INTERLACED:{ + gboolean interlaced; + g_object_get (G_OBJECT (vp->rawvideoparse), "interlaced", &interlaced, + NULL); + g_value_set_boolean (value, interlaced); break; - case PROP_TOP_FIELD_FIRST: - g_value_set_boolean (value, vp->top_field_first); + } + + case PROP_TOP_FIELD_FIRST:{ + gboolean top_field_first; + g_object_get (G_OBJECT (vp->rawvideoparse), "top-field-first", + &top_field_first, NULL); + g_value_set_boolean (value, top_field_first); break; - case PROP_STRIDES: - { - gchar *tmp; - - tmp = g_strdup_printf ("%d,%d,%d,%d", vp->info.stride[0], - vp->info.stride[1], vp->info.stride[2], vp->info.stride[3]); - g_value_set_string (value, tmp); - g_free (tmp); + } + + case PROP_STRIDES:{ + GValueArray *array; + g_object_get (G_OBJECT (vp->rawvideoparse), "plane-strides", &array, + NULL); + g_value_take_string (value, + gst_video_parse_int_valarray_to_string (array)); break; } - case PROP_OFFSETS: - { - gchar *tmp; - - tmp = g_strdup_printf ("%" G_GSIZE_FORMAT ",%" G_GSIZE_FORMAT - ",%" G_GSIZE_FORMAT ",%" G_GSIZE_FORMAT, vp->info.offset[0], - vp->info.offset[1], vp->info.offset[2], vp->info.offset[3]); - g_value_set_string (value, tmp); - g_free (tmp); + + case PROP_OFFSETS:{ + GValueArray *array; + g_object_get (G_OBJECT (vp->rawvideoparse), "plane-offsets", &array, + NULL); + g_value_take_string (value, + gst_video_parse_int_valarray_to_string (array)); break; } - case PROP_FRAMESIZE: - g_value_set_uint (value, vp->info.size); + + case PROP_FRAMESIZE:{ + guint frame_stride; + g_object_get (G_OBJECT (vp->rawvideoparse), "frame-stride", &frame_stride, + NULL); + g_value_set_uint (value, frame_stride); break; + } + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; } } -static gboolean -gst_video_parse_deserialize_int_array (const gchar * str, gint * dest, - guint n_values) +static GValueArray * +gst_video_parse_int_valarray_from_string (const gchar * str) { gchar **strv; guint length; guint i; + GValueArray *valarray; + GValue gvalue = G_VALUE_INIT; - strv = g_strsplit (str, ",", n_values); + if (str == NULL) + return NULL; + + strv = g_strsplit (str, ",", GST_VIDEO_MAX_PLANES); if (strv == NULL) - return FALSE; + return NULL; length = g_strv_length (strv); + valarray = g_value_array_new (length); + g_value_init (&gvalue, G_TYPE_UINT); for (i = 0; i < length; i++) { gint64 val; val = g_ascii_strtoll (strv[i], NULL, 10); if (val < G_MININT || val > G_MAXINT) { - g_strfreev (strv); - return FALSE; + goto error; } - dest[i] = val; + g_value_set_uint (&gvalue, val); + g_value_array_insert (valarray, i, &gvalue); } - /* fill remaining values with 0 */ - for (i = length; i < n_values; i++) - dest[i] = 0; - +finish: g_strfreev (strv); + return valarray; - return TRUE; +error: + g_value_array_free (valarray); + valarray = NULL; + goto finish; } -static inline gsize -gst_video_parse_get_plane_size (GstVideoInfo * info, guint plane) +static gchar * +gst_video_parse_int_valarray_to_string (GValueArray * valarray) { - gsize size = 0; - - if (GST_VIDEO_FORMAT_INFO_IS_TILED (info->finfo)) { - gint tile_width, tile_height, x_tiles, y_tiles; - - tile_width = 1 << GST_VIDEO_FORMAT_INFO_TILE_WS (info->finfo); - tile_height = 1 << GST_VIDEO_FORMAT_INFO_TILE_HS (info->finfo); - x_tiles = GST_VIDEO_TILE_X_TILES (info->stride[plane]); - y_tiles = GST_VIDEO_TILE_Y_TILES (info->stride[plane]); - - /* plane size is the size of one tile multiplied by the number of tiles */ - size = tile_width * tile_height * x_tiles * y_tiles; - } else { - size = info->stride[plane] * - GST_VIDEO_FORMAT_INFO_SCALE_HEIGHT (info->finfo, plane, info->height); - } - - return size; -} - - -static gboolean -gst_video_parse_update_stride (GstVideoParse * vp) -{ - GstVideoInfo *info = &vp->info; + /* holds a 64-bit number as string, which can have max. 20 digits + * (with extra char for nullbyte) */ + gchar stride_str[21]; + gchar *str = NULL; guint i; - /* 1. check that provided strides are greater than the default ones */ - for (i = 0; i < GST_VIDEO_INFO_N_PLANES (info); i++) { - if (GST_VIDEO_FORMAT_INFO_IS_TILED (info->finfo)) { - /* for tiled format, make sure there is more tiles than default */ - gint default_x_tiles, default_y_tiles, x_tiles, y_tiles; - - x_tiles = GST_VIDEO_TILE_X_TILES (vp->stride[i]); - y_tiles = GST_VIDEO_TILE_Y_TILES (vp->stride[i]); - default_x_tiles = GST_VIDEO_TILE_X_TILES (info->stride[i]); - default_y_tiles = GST_VIDEO_TILE_Y_TILES (info->stride[i]); - - if (x_tiles < default_x_tiles) { - GST_WARNING_OBJECT (vp, - "x_tiles for plane %u is too small: got %d, min %d", i, x_tiles, - default_x_tiles); - return FALSE; - } + for (i = 0; i < valarray->n_values; i++) { + GValue *gvalue = g_value_array_get_nth (valarray, i); + guint val = g_value_get_uint (gvalue); + g_snprintf (stride_str, sizeof (stride_str), "%u", val); - if (y_tiles < default_y_tiles) { - GST_WARNING_OBJECT (vp, - "y_tiles for plane %u is too small: got %d, min %d", i, y_tiles, - default_y_tiles); - return FALSE; - } + if (str == NULL) { + str = g_strdup (stride_str); } else { - if (vp->stride[i] < info->stride[i]) { - GST_WARNING_OBJECT (vp, - "stride for plane %u is too small: got %d, min %d", i, - vp->stride[i], info->stride[i]); - return FALSE; - } + gchar *new_str = g_strdup_printf ("%s,%s", str, stride_str); + g_free (str); + str = new_str; } } - /* 2. update stride and plane offsets */ - for (i = 0; i < GST_VIDEO_INFO_N_PLANES (info); i++) { - if (vp->stride[i] != info->stride[i]) { - info->stride[i] = vp->stride[i]; - - if (i > 0) { - /* update offset to reflect stride change for plane > 0 */ - info->offset[i] = info->offset[i - 1] + - gst_video_parse_get_plane_size (info, i - 1); - } - - vp->need_videometa = TRUE; - } - } - - return TRUE; -} - -static gboolean -gst_video_parse_update_offset (GstVideoParse * vp) -{ - GstVideoInfo *info = &vp->info; - guint i; - - /* 1. check that provided offsets are greaters than the default ones and are - * consistent with plane size */ - for (i = 0; i < GST_VIDEO_INFO_N_PLANES (info); i++) { - gsize min_offset = info->offset[i]; - - if (i > 0) - min_offset = MAX (min_offset, - vp->offset[i - 1] + gst_video_parse_get_plane_size (info, i - 1)); - - if (vp->offset[i] < min_offset) { - GST_WARNING_OBJECT (vp, - "offset for plane %u is too small: got %d, min %" G_GSIZE_FORMAT, i, - vp->offset[i], min_offset); - return FALSE; - } - } - - /* 2. update offsets */ - for (i = 0; i < GST_VIDEO_INFO_N_PLANES (info); i++) { - if (vp->offset[i] != info->offset[i]) { - info->offset[i] = vp->offset[i]; - vp->need_videometa = TRUE; - } - } - - return TRUE; -} - -static void -gst_video_parse_update_info (GstVideoParse * vp) -{ - GstVideoInfo *info = &vp->info; - gint fps_n, fps_d; - gint framesize; - guint i; - gboolean update_size = FALSE; - - gst_raw_parse_get_fps (GST_RAW_PARSE (vp), &fps_n, &fps_d); - - gst_video_info_init (info); - gst_video_info_set_format (info, vp->format, vp->width, vp->height); - info->fps_n = fps_n; - info->fps_d = fps_d; - info->par_n = vp->par_n; - info->par_d = vp->par_d; - info->interlace_mode = vp->interlaced ? - GST_VIDEO_INTERLACE_MODE_INTERLEAVED : - GST_VIDEO_INTERLACE_MODE_PROGRESSIVE; - - vp->need_videometa = FALSE; - - if (vp->stride_set) { - if (gst_video_parse_update_stride (vp)) - update_size = TRUE; - else - GST_WARNING_OBJECT (vp, "invalid strides set, use default ones"); - } - - if (vp->offset_set) { - if (gst_video_parse_update_offset (vp)) - update_size = TRUE; - else - GST_WARNING_OBJECT (vp, "invalid offsets set, use default ones"); - } - - if (update_size) { - framesize = 0; - - for (i = 0; i < GST_VIDEO_INFO_N_PLANES (info); i++) { - gint planesize = info->offset[i]; - planesize += gst_video_parse_get_plane_size (info, i); - - if (planesize > framesize) - framesize = planesize; - } - - info->size = framesize; - } - - if (vp->framesize) { - /* user requires a specific framesize, just make sure it's bigger than - * the current one */ - - if (vp->framesize > vp->info.size) - vp->info.size = vp->framesize; - else - GST_WARNING_OBJECT (vp, "invalid framesize set: got %u, min: %" - G_GSIZE_FORMAT, vp->framesize, vp->info.size); - } - - GST_DEBUG_OBJECT (vp, "video info: %ux%u, format %s, size %" G_GSIZE_FORMAT - ", stride {%d,%d,%d,%d}, offset {%" G_GSIZE_FORMAT ",%" G_GSIZE_FORMAT - ",%" G_GSIZE_FORMAT ",%" G_GSIZE_FORMAT "}", - GST_VIDEO_INFO_WIDTH (info), GST_VIDEO_INFO_HEIGHT (info), - GST_VIDEO_INFO_NAME (info), GST_VIDEO_INFO_SIZE (info), - info->stride[0], info->stride[1], info->stride[2], info->stride[3], - info->offset[0], info->offset[1], info->offset[2], info->offset[3]); - - /* update base class framesize */ - framesize = GST_VIDEO_INFO_SIZE (info); - gst_raw_parse_set_framesize (GST_RAW_PARSE (vp), framesize); -} - -static GstCaps * -gst_video_parse_get_caps (GstRawParse * rp) -{ - GstVideoParse *vp = GST_VIDEO_PARSE (rp); - - return gst_video_info_to_caps (&vp->info); -} - -static gboolean -gst_video_parse_copy_frame (GstVideoParse * vp, GstBuffer * dest, - GstVideoInfo * dest_info, GstBuffer * src, GstVideoInfo * src_info) -{ - GstVideoFrame src_frame; - GstVideoFrame dest_frame; - gboolean ret; - - if (!gst_video_frame_map (&src_frame, src_info, src, GST_MAP_READ)) { - GST_ERROR_OBJECT (vp, "failed to map src frame"); - return FALSE; - } - - if (!gst_video_frame_map (&dest_frame, dest_info, dest, GST_MAP_WRITE)) { - GST_ERROR_OBJECT (vp, "failed to map dest frame"); - gst_video_frame_unmap (&src_frame); - return FALSE; - } - - ret = gst_video_frame_copy (&dest_frame, &src_frame); - - gst_video_frame_unmap (&src_frame); - gst_video_frame_unmap (&dest_frame); - - return ret; -} - -static void -gst_video_parse_pre_push_buffer (GstRawParse * rp, GstBuffer * buffer) -{ - GstVideoParse *vp = GST_VIDEO_PARSE (rp); - - if (vp->do_copy) { - GstVideoInfo info; - GstBuffer *outbuf; - - gst_video_info_init (&info); - gst_video_info_set_format (&info, vp->format, vp->width, vp->height); - - GST_DEBUG_OBJECT (vp, "copying frame to remove padding"); - - outbuf = gst_buffer_new_allocate (NULL, GST_VIDEO_INFO_SIZE (&info), NULL); - - if (!gst_video_parse_copy_frame (vp, outbuf, &info, buffer, &vp->info)) - GST_WARNING_OBJECT (vp, "failed to copy frame"); - - gst_buffer_replace_all_memory (buffer, gst_buffer_get_all_memory (outbuf)); - gst_buffer_unref (outbuf); - } else { - GstVideoInfo *info = &vp->info; - GstVideoFrameFlags flags = GST_VIDEO_FRAME_FLAG_NONE; - - if (vp->interlaced && vp->top_field_first) - flags = GST_VIDEO_FRAME_FLAG_TFF; - - gst_buffer_add_video_meta_full (buffer, flags, GST_VIDEO_INFO_FORMAT (info), - GST_VIDEO_INFO_WIDTH (info), GST_VIDEO_INFO_HEIGHT (info), - GST_VIDEO_INFO_N_PLANES (info), info->offset, info->stride); - } - - if (vp->interlaced) { - if (vp->top_field_first) { - GST_BUFFER_FLAG_SET (buffer, GST_VIDEO_BUFFER_FLAG_TFF); - } else { - GST_BUFFER_FLAG_UNSET (buffer, GST_VIDEO_BUFFER_FLAG_TFF); - } - } -} - -static void -gst_video_parse_decide_allocation (GstRawParse * rp, GstQuery * query) -{ - GstVideoParse *vp = GST_VIDEO_PARSE (rp); - gboolean has_videometa; - - has_videometa = gst_query_find_allocation_meta (query, - GST_VIDEO_META_API_TYPE, NULL); - - /* no need to copy if downstream supports videometa or if we don't need - * them */ - if (has_videometa || !vp->need_videometa) - return; - - vp->do_copy = TRUE; + return str; } diff --git a/gst/rawparse/gstvideoparse.h b/gst/rawparse/gstvideoparse.h index dd540c54d..c5d8d648e 100644 --- a/gst/rawparse/gstvideoparse.h +++ b/gst/rawparse/gstvideoparse.h @@ -24,11 +24,6 @@ #define __GST_VIDEO_PARSE_H__ #include <gst/gst.h> -#include <gst/base/gstbasetransform.h> -#include <gst/base/gstadapter.h> -#include <gst/video/video.h> - -#include "gstrawparse.h" #define GST_TYPE_VIDEO_PARSE \ (gst_video_parse_get_type()) @@ -46,29 +41,13 @@ typedef struct _GstVideoParseClass GstVideoParseClass; struct _GstVideoParse { - GstRawParse parent; - - GstVideoInfo info; - gboolean do_copy; - gboolean need_videometa; - gboolean stride_set; - gboolean offset_set; - - /* properties */ - GstVideoFormat format; - gint width; - gint height; - gint par_n, par_d; - gboolean interlaced; - gboolean top_field_first; - gint stride[GST_VIDEO_MAX_PLANES]; - gint offset[GST_VIDEO_MAX_PLANES]; - guint framesize; + GstBin parent; + GstElement *rawvideoparse; }; struct _GstVideoParseClass { - GstRawParseClass parent_class; + GstBinClass parent_class; }; |