summaryrefslogtreecommitdiff
path: root/gst/rawparse
diff options
context:
space:
mode:
authorCarlos Rafael Giani <dv@pseudoterminal.org>2016-07-25 17:54:09 +0200
committerSebastian Dröge <sebastian@centricular.com>2016-07-26 13:44:39 +0300
commit403499a0c015920d367ba62531d515cfced1c3f3 (patch)
tree5db0db51c2c424ae6d0a1257c991b5b6d35d9e6c /gst/rawparse
parentd555f34562d8e477383df4d9f2b851db7de2af51 (diff)
downloadgstreamer-plugins-bad-403499a0c015920d367ba62531d515cfced1c3f3.tar.gz
rawparse: Remove old parser code and wrap new parsers in old elements
https://bugzilla.gnome.org/show_bug.cgi?id=767011
Diffstat (limited to 'gst/rawparse')
-rw-r--r--gst/rawparse/Makefile.am2
-rw-r--r--gst/rawparse/gstaudioparse.c403
-rw-r--r--gst/rawparse/gstaudioparse.h21
-rw-r--r--gst/rawparse/gstrawparse.c1105
-rw-r--r--gst/rawparse/gstrawparse.h98
-rw-r--r--gst/rawparse/gstvideoparse.c577
-rw-r--r--gst/rawparse/gstvideoparse.h27
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;
};