summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog36
-rw-r--r--configure.ac4
-rw-r--r--gst/rawparse/Makefile.am8
-rw-r--r--gst/rawparse/README23
-rw-r--r--gst/rawparse/gstaudioparse.c319
-rw-r--r--gst/rawparse/gstaudioparse.h66
-rw-r--r--gst/rawparse/gstrawparse.c598
-rw-r--r--gst/rawparse/gstrawparse.h91
-rw-r--r--gst/rawparse/gstvideoparse.c422
-rw-r--r--gst/rawparse/gstvideoparse.h74
-rw-r--r--gst/rawparse/plugin.c26
11 files changed, 1665 insertions, 2 deletions
diff --git a/ChangeLog b/ChangeLog
index 1bbfe81a..6aa7694c 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,39 @@
+2007-12-23 Sebastian Dröge <slomo@circular-chaos.org>
+
+ * configure.ac:
+ * gst/rawparse/Makefile.am:
+ * gst/rawparse/README:
+ * gst/rawparse/gstaudioparse.c: (gst_audio_parse_format_get_type),
+ (gst_audio_parse_endianness_get_type), (gst_audio_parse_base_init),
+ (gst_audio_parse_class_init), (gst_audio_parse_init),
+ (gst_audio_parse_set_property), (gst_audio_parse_get_property),
+ (gst_audio_parse_update_frame_size), (gst_audio_parse_get_caps):
+ * gst/rawparse/gstaudioparse.h:
+ * gst/rawparse/gstrawparse.c: (gst_raw_parse_base_init),
+ (gst_raw_parse_class_init), (gst_raw_parse_init),
+ (gst_raw_parse_dispose),
+ (gst_raw_parse_class_set_src_pad_template),
+ (gst_raw_parse_class_set_multiple_frames_per_buffer),
+ (gst_raw_parse_reset), (gst_raw_parse_chain),
+ (gst_raw_parse_convert), (gst_raw_parse_sink_event),
+ (gst_raw_parse_src_event), (gst_raw_parse_src_query_type),
+ (gst_raw_parse_src_query), (gst_raw_parse_set_framesize),
+ (gst_raw_parse_set_fps), (gst_raw_parse_get_fps),
+ (gst_raw_parse_is_negotiated):
+ * gst/rawparse/gstrawparse.h:
+ * gst/rawparse/gstvideoparse.c: (gst_video_parse_format_get_type),
+ (gst_video_parse_endianness_get_type), (gst_video_parse_base_init),
+ (gst_video_parse_class_init), (gst_video_parse_init),
+ (gst_video_parse_set_property), (gst_video_parse_get_property),
+ (gst_video_parse_format_to_fourcc),
+ (gst_video_parse_update_frame_size), (gst_video_parse_get_caps):
+ * gst/rawparse/gstvideoparse.h:
+ * gst/rawparse/plugin.c: (plugin_init):
+ Add new plugin rawparse that contains a base class for raw data
+ parsers and the two elements audioparse and videoparse that can
+ be used to parse raw audio and video. These are inspired by the
+ old videoparse element which the new rawparse plugin deprecates.
+
2007-12-21 David Schleef <ds@schleef.org>
* sys/glsink/glextensions.c:
diff --git a/configure.ac b/configure.ac
index bea69902..bbc72834 100644
--- a/configure.ac
+++ b/configure.ac
@@ -100,6 +100,7 @@ GST_PLUGINS_ALL="\
mve \
nsf \
nuvdemux \
+ rawparse \
real \
replaygain \
rtpmanager \
@@ -110,7 +111,6 @@ GST_PLUGINS_ALL="\
stereo \
switch \
tta \
- videoparse \
videosignal \
vmnc \
xingheader \
@@ -1078,6 +1078,7 @@ gst/multifile/Makefile
gst/mve/Makefile
gst/nsf/Makefile
gst/nuvdemux/Makefile
+gst/rawparse/Makefile
gst/replaygain/Makefile
gst/rtpmanager/Makefile
gst/sdp/Makefile
@@ -1087,7 +1088,6 @@ gst/speexresample/Makefile
gst/stereo/Makefile
gst/switch/Makefile
gst/tta/Makefile
-gst/videoparse/Makefile
gst/videosignal/Makefile
gst/vmnc/Makefile
gst/xingheader/Makefile
diff --git a/gst/rawparse/Makefile.am b/gst/rawparse/Makefile.am
new file mode 100644
index 00000000..ba235ea0
--- /dev/null
+++ b/gst/rawparse/Makefile.am
@@ -0,0 +1,8 @@
+
+plugin_LTLIBRARIES = libgstrawparse.la
+
+libgstrawparse_la_SOURCES = gstrawparse.c gstaudioparse.c gstvideoparse.c plugin.c
+libgstrawparse_la_CFLAGS = $(GST_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS)
+libgstrawparse_la_LIBADD = $(GST_LIBS) $(GST_BASE_LIBS)
+libgstrawparse_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
+
diff --git a/gst/rawparse/README b/gst/rawparse/README
new file mode 100644
index 00000000..0a698c90
--- /dev/null
+++ b/gst/rawparse/README
@@ -0,0 +1,23 @@
+
+videoparse
+==========
+
+The videoparse element is used to parse a file containing raw image
+data.
+
+
+Creating example data
+=====================
+
+gst-launch videotestsrc num_buffers=300 ! \
+ video/x-raw-yuv,format=\(fourcc\)I420,width=320,height=240 ! \
+ filesink location=raw
+
+
+Reading example data
+====================
+
+gst-launch filesrc location=raw ! \
+ videoparse format=I420 width=320 height=240 framerate=30/1 ! \
+ xvimagesink
+
diff --git a/gst/rawparse/gstaudioparse.c b/gst/rawparse/gstaudioparse.c
new file mode 100644
index 00000000..b8fcd82d
--- /dev/null
+++ b/gst/rawparse/gstaudioparse.c
@@ -0,0 +1,319 @@
+/* GStreamer
+ * Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
+ *
+ * gstaudioparse.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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+/**
+ * SECTION:element-audioparse
+ * @short_description: parses a byte stream into audio frames
+ *
+ * Converts a byte stream into audio frames.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "gstaudioparse.h"
+
+typedef enum
+{
+ GST_AUDIO_PARSE_FORMAT_INT,
+ GST_AUDIO_PARSE_FORMAT_FLOAT
+} 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 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
+
+static const GstElementDetails gst_audio_parse_details =
+GST_ELEMENT_DETAILS ("Audio Parse",
+ "Filter/Audio",
+ "Converts stream into audio frames",
+ "Sebastian Dröge <slomo@circular-chaos.org>");
+
+enum
+{
+ ARG_0,
+ ARG_FORMAT,
+ ARG_RATE,
+ ARG_CHANNELS,
+ ARG_ENDIANNESS,
+ ARG_WIDTH,
+ ARG_DEPTH,
+ ARG_SIGNED,
+};
+
+
+#define GST_AUDIO_PARSE_FORMAT (gst_audio_parse_format_get_type ())
+static GType
+gst_audio_parse_format_get_type (void)
+{
+ static GType audio_parse_format_type = 0;
+ static const GEnumValue format_types[] = {
+ {GST_AUDIO_PARSE_FORMAT_INT, "Integer", "int"},
+ {GST_AUDIO_PARSE_FORMAT_FLOAT, "Floating Point", "float"},
+ {0, NULL, NULL}
+ };
+
+ if (!audio_parse_format_type) {
+ audio_parse_format_type =
+ g_enum_register_static ("GstAudioParseFormat", format_types);
+ }
+
+ return audio_parse_format_type;
+}
+
+#define GST_AUDIO_PARSE_ENDIANNESS (gst_audio_parse_endianness_get_type ())
+static GType
+gst_audio_parse_endianness_get_type (void)
+{
+ static GType audio_parse_endianness_type = 0;
+ static const GEnumValue endian_types[] = {
+ {GST_AUDIO_PARSE_ENDIANNESS_LITTLE, "Little Endian", "little"},
+ {GST_AUDIO_PARSE_ENDIANNESS_BIG, "Big Endian", "big"},
+ {0, NULL, NULL}
+ };
+
+ if (!audio_parse_endianness_type) {
+ audio_parse_endianness_type =
+ g_enum_register_static ("GstAudioParseEndianness", endian_types);
+ }
+
+ return audio_parse_endianness_type;
+}
+
+GST_BOILERPLATE (GstAudioParse, gst_audio_parse, GstRawParse,
+ GST_TYPE_RAW_PARSE);
+
+static void
+gst_audio_parse_base_init (gpointer g_class)
+{
+ GstRawParseClass *rp_class = GST_RAW_PARSE_CLASS (g_class);
+ GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
+ GstCaps *caps;
+
+ GST_DEBUG_CATEGORY_INIT (gst_audio_parse_debug, "audioparse", 0,
+ "audioparse element");
+
+ gst_element_class_set_details (gstelement_class, &gst_audio_parse_details);
+
+ caps =
+ gst_caps_from_string ("audio/x-raw-int,"
+ " depth=(int) [ 1, 32 ],"
+ " width=(int) { 8, 16, 24, 32 },"
+ " endianness=(int) { LITTLE_ENDIAN, BIG_ENDIAN }, "
+ " signed=(bool) { TRUE, FALSE },"
+ " rate=(int) [ 1, MAX ],"
+ " channels=(int) [ 1, MAX ]; "
+ "audio/x-raw-float,"
+ " width=(int) { 32, 64 },"
+ " endianness=(int) { LITTLE_ENDIAN, BIG_ENDIAN }, "
+ " 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);
+}
+
+static void
+gst_audio_parse_class_init (GstAudioParseClass * klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GstRawParseClass *rp_class = GST_RAW_PARSE_CLASS (klass);
+
+ gobject_class->set_property = gst_audio_parse_set_property;
+ gobject_class->get_property = gst_audio_parse_get_property;
+
+ rp_class->get_caps = gst_audio_parse_get_caps;
+
+ g_object_class_install_property (gobject_class, ARG_FORMAT,
+ g_param_spec_enum ("format", "Format",
+ "Format of audio samples in raw stream", GST_AUDIO_PARSE_FORMAT,
+ GST_AUDIO_PARSE_FORMAT_INT, G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, ARG_RATE,
+ g_param_spec_int ("rate", "Rate", "Rate of audio samples in raw stream",
+ 1, INT_MAX, 44100, G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, ARG_CHANNELS,
+ g_param_spec_int ("channels", "Channels",
+ "Number of channels in raw stream", 1, INT_MAX, 2,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, ARG_WIDTH,
+ g_param_spec_int ("width", "Width",
+ "Width of audio samples in raw stream", 1, INT_MAX, 16,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, ARG_DEPTH,
+ g_param_spec_int ("depth", "Depth",
+ "Depth of audio samples in raw stream", 1, INT_MAX, 16,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, ARG_SIGNED,
+ g_param_spec_boolean ("signed", "signed",
+ "Sign of audio samples in raw stream", TRUE, G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, ARG_ENDIANNESS,
+ g_param_spec_enum ("endianness", "Endianness",
+ "Endianness of audio samples in raw stream",
+ GST_AUDIO_PARSE_ENDIANNESS, G_BYTE_ORDER, G_PARAM_READWRITE));
+}
+
+static void
+gst_audio_parse_init (GstAudioParse * ap, GstAudioParseClass * g_class)
+{
+ ap->format = GST_AUDIO_PARSE_FORMAT_INT;
+ ap->channels = 2;
+ ap->width = 16;
+ ap->depth = 16;
+ ap->signedness = TRUE;
+ ap->endianness = G_BYTE_ORDER;
+
+ gst_audio_parse_update_frame_size (ap);
+ gst_raw_parse_set_fps (GST_RAW_PARSE (ap), 44100, 1);
+}
+
+static void
+gst_audio_parse_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec)
+{
+ GstAudioParse *ap = GST_AUDIO_PARSE (object);
+
+ g_return_if_fail (!gst_raw_parse_is_negotiated (GST_RAW_PARSE (ap)));
+
+ switch (prop_id) {
+ case ARG_FORMAT:
+ ap->format = g_value_get_enum (value);
+ break;
+ case ARG_RATE:
+ gst_raw_parse_set_fps (GST_RAW_PARSE (ap), g_value_get_int (value), 1);
+ break;
+ case ARG_CHANNELS:
+ ap->channels = g_value_get_int (value);
+ break;
+ case ARG_WIDTH:
+ ap->width = g_value_get_int (value);
+ break;
+ case ARG_DEPTH:
+ ap->depth = g_value_get_int (value);
+ break;
+ case ARG_SIGNED:
+ ap->signedness = g_value_get_boolean (value);
+ break;
+ case ARG_ENDIANNESS:
+ ap->endianness = g_value_get_enum (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+
+ gst_audio_parse_update_frame_size (ap);
+}
+
+static void
+gst_audio_parse_get_property (GObject * object, guint prop_id, GValue * value,
+ GParamSpec * pspec)
+{
+ GstAudioParse *ap = GST_AUDIO_PARSE (object);
+
+ switch (prop_id) {
+ case ARG_FORMAT:
+ g_value_set_enum (value, ap->format);
+ break;
+ case ARG_RATE:{
+ gint fps_n, fps_d;
+
+ gst_raw_parse_get_fps (GST_RAW_PARSE (ap), &fps_n, &fps_d);
+ g_value_set_int (value, fps_n);
+ break;
+ }
+ case ARG_CHANNELS:
+ g_value_set_int (value, ap->channels);
+ break;
+ case ARG_WIDTH:
+ g_value_set_int (value, ap->width);
+ break;
+ case ARG_DEPTH:
+ g_value_set_int (value, ap->depth);
+ break;
+ case ARG_SIGNED:
+ g_value_set_boolean (value, ap->signedness);
+ break;
+ case ARG_ENDIANNESS:
+ g_value_set_enum (value, ap->endianness);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+void
+gst_audio_parse_update_frame_size (GstAudioParse * ap)
+{
+ gint framesize;
+
+ framesize = (ap->width / 8) * ap->channels;
+
+ gst_raw_parse_set_framesize (GST_RAW_PARSE (ap), framesize);
+}
+
+static GstCaps *
+gst_audio_parse_get_caps (GstRawParse * rp)
+{
+ GstAudioParse *ap = GST_AUDIO_PARSE (rp);
+ GstCaps *caps;
+
+ gint fps_n, fps_d;
+
+ gst_raw_parse_get_fps (rp, &fps_n, &fps_d);
+
+ if (ap->format == GST_AUDIO_PARSE_FORMAT_INT) {
+ caps = gst_caps_new_simple ("audio/x-raw-int",
+ "rate", G_TYPE_INT, fps_n,
+ "channels", G_TYPE_INT, ap->channels,
+ "width", G_TYPE_INT, ap->width,
+ "depth", G_TYPE_INT, ap->depth,
+ "signed", G_TYPE_BOOLEAN, ap->signedness,
+ "endianness", G_TYPE_INT, ap->endianness, NULL);
+ } else {
+ caps = gst_caps_new_simple ("audio/x-raw-float",
+ "rate", G_TYPE_INT, fps_n,
+ "channels", G_TYPE_INT, ap->channels,
+ "width", G_TYPE_INT, ap->width,
+ "endianness", G_TYPE_INT, ap->endianness, NULL);
+ }
+ return caps;
+}
diff --git a/gst/rawparse/gstaudioparse.h b/gst/rawparse/gstaudioparse.h
new file mode 100644
index 00000000..86c8fe2a
--- /dev/null
+++ b/gst/rawparse/gstaudioparse.h
@@ -0,0 +1,66 @@
+/* GStreamer
+ * Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
+ *
+ * gstaudioparse.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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GST_AUDIO_PARSE_H__
+#define __GST_AUDIO_PARSE_H__
+
+#include <gst/gst.h>
+#include <gst/base/gstbasetransform.h>
+#include <gst/base/gstadapter.h>
+
+#include "gstrawparse.h"
+
+#define GST_TYPE_AUDIO_PARSE \
+ (gst_audio_parse_get_type())
+#define GST_AUDIO_PARSE(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_AUDIO_PARSE,GstAudioParse))
+#define GST_AUDIO_PARSE_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_AUDIO_PARSE,GstAudioParseClass))
+#define GST_IS_AUDIO_PARSE(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_AUDIO_PARSE))
+#define GST_IS_AUDIO_PARSE_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_AUDIO_PARSE))
+
+typedef struct _GstAudioParse GstAudioParse;
+typedef struct _GstAudioParseClass GstAudioParseClass;
+
+struct _GstAudioParse
+{
+ GstRawParse parent;
+
+ /* properties */
+ gint format;
+ gint channels;
+ gint width;
+ gint depth;
+ gint signedness;
+ gint endianness;
+};
+
+struct _GstAudioParseClass
+{
+ GstRawParseClass parent_class;
+};
+
+
+GType gst_audio_parse_get_type (void);
+
+#endif /* __GST_AUDIO_PARSE_H__ */
diff --git a/gst/rawparse/gstrawparse.c b/gst/rawparse/gstrawparse.c
new file mode 100644
index 00000000..9714bba2
--- /dev/null
+++ b/gst/rawparse/gstrawparse.c
@@ -0,0 +1,598 @@
+/* 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+/* TODO: - Add locking where appropiate
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#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 GstFlowReturn gst_raw_parse_chain (GstPad * pad, GstBuffer * buffer);
+static gboolean gst_raw_parse_sink_event (GstPad * pad, GstEvent * event);
+static gboolean gst_raw_parse_src_event (GstPad * pad, GstEvent * event);
+static const GstQueryType *gst_raw_parse_src_query_type (GstPad * pad);
+static gboolean gst_raw_parse_src_query (GstPad * pad, GstQuery * query);
+static gboolean gst_raw_parse_convert (GstRawParse * rp,
+ GstFormat src_format, gint64 src_value,
+ GstFormat dest_format, gint64 * dest_value);
+
+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 const GstElementDetails raw_parse_details =
+GST_ELEMENT_DETAILS ("Raw parser base class",
+ "Filter/Raw",
+ "Parses byte streams into raw frames",
+ "Sebastian Dröge <slomo@circular-chaos.org>");
+
+GST_BOILERPLATE (GstRawParse, gst_raw_parse, GstElement, GST_TYPE_ELEMENT);
+
+static void
+gst_raw_parse_base_init (gpointer g_class)
+{
+ GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
+
+ GST_DEBUG_CATEGORY_INIT (gst_raw_parse_debug, "rawparse", 0,
+ "rawparse element");
+
+ gst_element_class_add_pad_template (gstelement_class,
+ gst_static_pad_template_get (&gst_raw_parse_sink_pad_template));
+ gst_element_class_set_details (gstelement_class, &raw_parse_details);
+}
+
+static void
+gst_raw_parse_class_init (GstRawParseClass * klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->dispose = gst_raw_parse_dispose;
+}
+
+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_element_add_pad (GST_ELEMENT (rp), rp->sinkpad);
+
+ gst_pad_set_chain_function (rp->sinkpad, gst_raw_parse_chain);
+ gst_pad_set_event_function (rp->sinkpad, gst_raw_parse_sink_event);
+
+ 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 {
+ GstCaps *caps;
+
+ GST_WARNING ("Subclass didn't specify a src pad template, using ANY caps");
+ rp->srcpad = gst_pad_new ("src", GST_PAD_SRC);
+ caps = gst_caps_new_any ();
+ gst_pad_set_caps (rp->srcpad, caps);
+ gst_caps_unref (caps);
+ }
+
+ gst_element_add_pad (GST_ELEMENT (rp), rp->srcpad);
+ g_object_unref (src_pad_template);
+
+ gst_pad_set_event_function (rp->srcpad, gst_raw_parse_src_event);
+
+ gst_pad_set_query_type_function (rp->srcpad, gst_raw_parse_src_query_type);
+ gst_pad_set_query_function (rp->srcpad, gst_raw_parse_src_query);
+
+ rp->adapter = gst_adapter_new ();
+
+ rp->fps_n = 1;
+ rp->fps_d = 0;
+ rp->framesize = 1;
+}
+
+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;
+
+ gst_segment_init (&rp->segment, GST_FORMAT_TIME);
+ gst_adapter_clear (rp->adapter);
+}
+
+static GstFlowReturn
+gst_raw_parse_chain (GstPad * pad, GstBuffer * buffer)
+{
+ GstRawParse *rp = GST_RAW_PARSE (gst_pad_get_parent (pad));
+ GstFlowReturn ret = GST_FLOW_OK;
+ GstRawParseClass *rp_class = GST_RAW_PARSE_GET_CLASS (rp);
+ guint buffersize, nframes;
+
+ if (G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT))) {
+ GST_DEBUG_OBJECT (rp, "received DISCONT buffer");
+
+ rp->discont = TRUE;
+ }
+
+ if (!rp->negotiated) {
+ GstCaps *caps;
+
+ 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);
+ }
+
+ g_return_val_if_fail (rp->negotiated, GST_FLOW_ERROR);
+
+ gst_adapter_push (rp->adapter, buffer);
+
+ if (rp_class->multiple_frames_per_buffer) {
+ buffersize = gst_adapter_available (rp->adapter);
+ buffersize -= buffersize % rp->framesize;
+ nframes = buffersize / rp->framesize;
+ } else {
+ buffersize = rp->framesize;
+ nframes = 1;
+ }
+
+ while (gst_adapter_available (rp->adapter) >= buffersize) {
+ buffer = gst_adapter_take_buffer (rp->adapter, buffersize);
+
+ if (rp->fps_n) {
+ GST_BUFFER_TIMESTAMP (buffer) = rp->segment.start +
+ gst_util_uint64_scale (rp->n_frames, GST_SECOND * rp->fps_d,
+ rp->fps_n);
+ GST_BUFFER_DURATION (buffer) =
+ gst_util_uint64_scale (nframes * GST_SECOND, rp->fps_d, rp->fps_n);
+ } else {
+ GST_BUFFER_TIMESTAMP (buffer) = rp->segment.start;
+ GST_BUFFER_DURATION (buffer) = GST_CLOCK_TIME_NONE;
+ }
+ gst_buffer_set_caps (buffer, GST_PAD_CAPS (rp->srcpad));
+ if (rp->discont) {
+ GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT);
+ rp->discont = FALSE;
+ }
+
+ rp->n_frames += nframes;
+
+ ret = gst_pad_push (rp->srcpad, buffer);
+ if (ret != GST_FLOW_OK)
+ break;
+ }
+
+ gst_object_unref (rp);
+ 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 to %s",
+ src_value, gst_format_get_name (src_format),
+ gst_format_get_name (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, GstEvent * event)
+{
+ GstRawParse *rp = GST_RAW_PARSE (gst_pad_get_parent (pad));
+ gboolean ret;
+
+ switch (GST_EVENT_TYPE (event)) {
+ case GST_EVENT_FLUSH_STOP:
+ gst_raw_parse_reset (rp);
+ ret = gst_pad_push_event (rp->srcpad, event);
+ break;
+ case GST_EVENT_NEWSEGMENT:
+ {
+ GstClockTimeDiff start, stop, time;
+ gdouble rate, arate;
+ gboolean update;
+ GstFormat format;
+
+ gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format,
+ &start, &stop, &time);
+
+ if (format == GST_FORMAT_TIME) {
+ ret = gst_pad_push_event (rp->srcpad, event);
+ gst_segment_set_newsegment_full (&rp->segment, update, rate, arate,
+ GST_FORMAT_TIME, start, stop, time);
+ } else {
+
+ gst_event_unref (event);
+
+ ret =
+ gst_raw_parse_convert (rp, format, start, GST_FORMAT_TIME, &start);
+ ret &= gst_raw_parse_convert (rp, format, time, GST_FORMAT_TIME, &time);
+ ret &= gst_raw_parse_convert (rp, format, stop, GST_FORMAT_TIME, &stop);
+ if (!ret) {
+ GST_ERROR_OBJECT (rp,
+ "Failed converting to GST_FORMAT_TIME format (%d)", format);
+ break;
+ }
+
+ gst_segment_set_newsegment_full (&rp->segment, update, rate, arate,
+ GST_FORMAT_TIME, start, stop, time);
+ event = gst_event_new_new_segment (FALSE, rp->segment.rate,
+ GST_FORMAT_TIME, start, stop, time);
+
+ ret = gst_pad_push_event (rp->srcpad, event);
+ }
+
+ if (ret) {
+ rp->n_frames = 0;
+ rp->discont = TRUE;
+ gst_adapter_clear (rp->adapter);
+ }
+ break;
+ }
+ default:
+ ret = gst_pad_event_default (rp->sinkpad, event);
+ break;
+ }
+
+ gst_object_unref (rp);
+
+ return ret;
+}
+
+static gboolean
+gst_raw_parse_src_event (GstPad * pad, GstEvent * event)
+{
+ GstRawParse *rp = GST_RAW_PARSE (gst_pad_get_parent (pad));
+ gboolean ret;
+
+ switch (GST_EVENT_TYPE (event)) {
+ case GST_EVENT_SEEK:{
+ GstFormat format;
+ gdouble rate;
+ GstSeekFlags flags;
+ GstSeekType start_type, stop_type;
+ gint64 start, stop;
+
+ gst_event_parse_seek (event, &rate, &format, &flags, &start_type, &start,
+ &stop_type, &stop);
+
+ /* First try if upstream handles the seek */
+ ret = gst_pad_push_event (rp->sinkpad, event);
+ if (ret)
+ goto done;
+
+ /* Otherwise convert to bytes and push upstream */
+ if (format == GST_FORMAT_TIME || format == GST_FORMAT_DEFAULT) {
+ gst_event_unref (event);
+
+ 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) {
+ event =
+ gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, start_type,
+ start, stop_type, stop);
+
+ ret = gst_pad_push_event (rp->sinkpad, event);
+ }
+ }
+ break;
+ }
+ default:
+ ret = gst_pad_event_default (rp->srcpad, event);
+ break;
+ }
+
+done:
+ gst_object_unref (rp);
+
+ return ret;
+}
+
+static const GstQueryType *
+gst_raw_parse_src_query_type (GstPad * pad)
+{
+ static const GstQueryType types[] = {
+ GST_QUERY_POSITION,
+ GST_QUERY_DURATION,
+ GST_QUERY_CONVERT,
+ 0
+ };
+
+ return types;
+}
+
+static gboolean
+gst_raw_parse_src_query (GstPad * pad, GstQuery * query)
+{
+ GstRawParse *rp = GST_RAW_PARSE (gst_pad_get_parent (pad));
+ 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 = gst_util_uint64_scale (rp->n_frames,
+ GST_SECOND * rp->fps_d, rp->fps_n);
+ 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->srcpad, 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->srcpad, 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;
+ }
+ default:
+ /* else forward upstream */
+ ret = gst_pad_peer_query (rp->sinkpad, query);
+ break;
+ }
+
+done:
+ gst_object_unref (rp);
+ return ret;
+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);
+
+ 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));
+
+ *fps_n = rp->fps_n;
+ *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
new file mode 100644
index 00000000..dd486c34
--- /dev/null
+++ b/gst/rawparse/gstrawparse.h
@@ -0,0 +1,91 @@
+/* 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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, 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;
+
+ GstAdapter *adapter;
+
+ int framesize;
+ int fps_d;
+ int fps_n;
+
+ gboolean discont;
+ guint64 n_frames;
+
+ GstSegment segment;
+
+ gboolean negotiated;
+ gboolean have_new_segment;
+};
+
+struct _GstRawParseClass
+{
+ GstElementClass parent_class;
+
+ GstCaps * (*get_caps) (GstRawParse *rp);
+
+ 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
new file mode 100644
index 00000000..8f090f72
--- /dev/null
+++ b/gst/rawparse/gstvideoparse.c
@@ -0,0 +1,422 @@
+/* GStreamer
+ * Copyright (C) 2006 David A. Schleef <ds@schleef.org>
+ * Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
+ *
+ * gstvideoparse.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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+/**
+ * SECTION:element-videoparse
+ * @short_description: parses a byte stream into video frames
+ *
+ * Converts a byte stream into video frames.
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "gstvideoparse.h"
+
+typedef enum
+{
+ GST_VIDEO_PARSE_FORMAT_I420,
+ GST_VIDEO_PARSE_FORMAT_YV12,
+ GST_VIDEO_PARSE_FORMAT_YUY2,
+ GST_VIDEO_PARSE_FORMAT_UYVY,
+ GST_VIDEO_PARSE_FORMAT_RGB = 10,
+ GST_VIDEO_PARSE_FORMAT_GRAY
+} GstVideoParseFormat;
+
+typedef enum
+{
+ GST_VIDEO_PARSE_ENDIANNESS_LITTLE = 1234,
+ GST_VIDEO_PARSE_ENDIANNESS_BIG = 4321
+} GstVideoParseEndianness;
+
+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_update_frame_size (GstVideoParse * vp);
+
+GST_DEBUG_CATEGORY_STATIC (gst_video_parse_debug);
+#define GST_CAT_DEFAULT gst_video_parse_debug
+
+static const GstElementDetails gst_video_parse_details =
+GST_ELEMENT_DETAILS ("Video Parse",
+ "Filter/Video",
+ "Converts stream into video frames",
+ "David Schleef <ds@schleef.org>, "
+ "Sebastian Dröge <slomo@circular-chaos.org>");
+
+enum
+{
+ ARG_0,
+ ARG_WIDTH,
+ ARG_HEIGHT,
+ ARG_FORMAT,
+ ARG_PAR,
+ ARG_FRAMERATE,
+ ARG_BPP,
+ ARG_DEPTH,
+ ARG_ENDIANNESS,
+ ARG_RED_MASK,
+ ARG_GREEN_MASK,
+ ARG_BLUE_MASK,
+ ARG_ALPHA_MASK
+};
+
+
+#define GST_VIDEO_PARSE_FORMAT (gst_video_parse_format_get_type ())
+static GType
+gst_video_parse_format_get_type (void)
+{
+ static GType video_parse_format_type = 0;
+ static const GEnumValue format_types[] = {
+ {GST_VIDEO_PARSE_FORMAT_I420, "I420", "I420"},
+ {GST_VIDEO_PARSE_FORMAT_YV12, "YV12", "YV12"},
+ {GST_VIDEO_PARSE_FORMAT_YUY2, "YUY2", "YUY2"},
+ {GST_VIDEO_PARSE_FORMAT_UYVY, "UYVY", "UYVY"},
+ {GST_VIDEO_PARSE_FORMAT_RGB, "RGB", "RGB"},
+ {GST_VIDEO_PARSE_FORMAT_GRAY, "GRAY", "GRAY"},
+ {0, NULL, NULL}
+ };
+
+ if (!video_parse_format_type) {
+ video_parse_format_type =
+ g_enum_register_static ("GstVideoParseFormat", format_types);
+ }
+
+ return video_parse_format_type;
+}
+
+#define GST_VIDEO_PARSE_ENDIANNESS (gst_video_parse_endianness_get_type ())
+static GType
+gst_video_parse_endianness_get_type (void)
+{
+ static GType video_parse_endianness_type = 0;
+ static const GEnumValue endian_types[] = {
+ {GST_VIDEO_PARSE_ENDIANNESS_LITTLE, "Little Endian", "little"},
+ {GST_VIDEO_PARSE_ENDIANNESS_BIG, "Big Endian", "big"},
+ {0, NULL, NULL}
+ };
+
+ if (!video_parse_endianness_type) {
+ video_parse_endianness_type =
+ g_enum_register_static ("GstVideoParseEndianness", endian_types);
+ }
+
+ return video_parse_endianness_type;
+}
+
+GST_BOILERPLATE (GstVideoParse, gst_video_parse, GstRawParse,
+ GST_TYPE_RAW_PARSE);
+
+static void
+gst_video_parse_base_init (gpointer g_class)
+{
+ GstRawParseClass *rp_class = GST_RAW_PARSE_CLASS (g_class);
+ GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class);
+ GstCaps *caps;
+
+ GST_DEBUG_CATEGORY_INIT (gst_video_parse_debug, "videoparse", 0,
+ "videoparse element");
+
+ gst_element_class_set_details (gstelement_class, &gst_video_parse_details);
+
+ caps =
+ gst_caps_from_string (GST_VIDEO_CAPS_YUV
+ ("{ I420, YV12, YUY2, UYVY }") ";" "video/x-raw-rgb; video/x-raw-gray");
+
+ 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);
+}
+
+static void
+gst_video_parse_class_init (GstVideoParseClass * klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GstRawParseClass *rp_class = GST_RAW_PARSE_CLASS (klass);
+
+ 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;
+
+ g_object_class_install_property (gobject_class, ARG_WIDTH,
+ g_param_spec_int ("width", "Width", "Width of images in raw stream",
+ 0, INT_MAX, 320, G_PARAM_READWRITE));
+ g_object_class_install_property (gobject_class, ARG_HEIGHT,
+ g_param_spec_int ("height", "Height", "Height of images in raw stream",
+ 0, INT_MAX, 240, G_PARAM_READWRITE));
+ g_object_class_install_property (gobject_class, ARG_FORMAT,
+ g_param_spec_enum ("format", "Format", "Format of images in raw stream",
+ GST_VIDEO_PARSE_FORMAT, GST_VIDEO_PARSE_FORMAT_I420,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (gobject_class, ARG_FRAMERATE,
+ gst_param_spec_fraction ("framerate", "Frame Rate",
+ "Frame rate of images in raw stream", 0, 1, 100, 1, 25, 1,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (gobject_class, ARG_PAR,
+ gst_param_spec_fraction ("pixel_aspect_ratio", "Pixel Aspect Ratio",
+ "Pixel aspect ratio of images in raw stream", 1, 100, 100, 1, 1, 1,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (gobject_class, ARG_BPP,
+ g_param_spec_int ("bpp", "Bpp", "Bits per pixel of images in raw stream",
+ 0, INT_MAX, 24, G_PARAM_READWRITE));
+ g_object_class_install_property (gobject_class, ARG_DEPTH,
+ g_param_spec_int ("depth", "Depth", "Depth of images in raw stream",
+ 0, INT_MAX, 24, G_PARAM_READWRITE));
+ g_object_class_install_property (gobject_class, ARG_ENDIANNESS,
+ g_param_spec_enum ("endianness", "Endianness",
+ "Endianness of images in raw stream", GST_VIDEO_PARSE_ENDIANNESS,
+ G_BYTE_ORDER, G_PARAM_READWRITE));
+ g_object_class_install_property (gobject_class, ARG_RED_MASK,
+ g_param_spec_int ("red-mask", "Red mask",
+ "Red mask of images in raw stream", 0, INT_MAX,
+ GST_VIDEO_BYTE1_MASK_24_INT, G_PARAM_READWRITE));
+ g_object_class_install_property (gobject_class, ARG_GREEN_MASK,
+ g_param_spec_int ("green-mask", "Green mask",
+ "Green mask of images in raw stream", 0, INT_MAX,
+ GST_VIDEO_BYTE2_MASK_24_INT, G_PARAM_READWRITE));
+ g_object_class_install_property (gobject_class, ARG_BLUE_MASK,
+ g_param_spec_int ("blue-mask", "Blue mask",
+ "Blue mask of images in raw stream", 0, INT_MAX,
+ GST_VIDEO_BYTE3_MASK_24_INT, G_PARAM_READWRITE));
+ g_object_class_install_property (gobject_class, ARG_ALPHA_MASK,
+ g_param_spec_int ("alpha-mask", "Alpha mask",
+ "Alpha mask of images in raw stream", 0, INT_MAX, 0,
+ G_PARAM_READWRITE));
+}
+
+static void
+gst_video_parse_init (GstVideoParse * vp, GstVideoParseClass * g_class)
+{
+ vp->width = 320;
+ vp->height = 240;
+ vp->format = GST_VIDEO_PARSE_FORMAT_I420;
+ vp->par_n = 1;
+ vp->par_d = 1;
+ vp->bpp = 24;
+ vp->depth = 24;
+ vp->endianness = G_BYTE_ORDER;
+ vp->red_mask = GST_VIDEO_BYTE1_MASK_24_INT;
+ vp->green_mask = GST_VIDEO_BYTE2_MASK_24_INT;
+ vp->blue_mask = GST_VIDEO_BYTE3_MASK_24_INT;
+ vp->alpha_mask = 0;
+
+ gst_video_parse_update_frame_size (vp);
+ gst_raw_parse_set_fps (GST_RAW_PARSE (vp), 25, 1);
+}
+
+static void
+gst_video_parse_set_property (GObject * object, guint prop_id,
+ const GValue * value, GParamSpec * pspec)
+{
+ GstVideoParse *vp = GST_VIDEO_PARSE (object);
+
+ g_return_if_fail (!gst_raw_parse_is_negotiated (GST_RAW_PARSE (vp)));
+
+ switch (prop_id) {
+ case ARG_WIDTH:
+ vp->width = g_value_get_int (value);
+ break;
+ case ARG_HEIGHT:
+ vp->height = g_value_get_int (value);
+ break;
+ case ARG_FORMAT:
+ vp->format = g_value_get_enum (value);
+ break;
+ case ARG_FRAMERATE:
+ gst_raw_parse_set_fps (GST_RAW_PARSE (vp),
+ gst_value_get_fraction_numerator (value),
+ gst_value_get_fraction_denominator (value));
+ break;
+ case ARG_PAR:
+ vp->par_n = gst_value_get_fraction_numerator (value);
+ vp->par_d = gst_value_get_fraction_denominator (value);
+ break;
+ case ARG_BPP:
+ vp->bpp = g_value_get_int (value);
+ break;
+ case ARG_DEPTH:
+ vp->depth = g_value_get_int (value);
+ break;
+ case ARG_ENDIANNESS:
+ vp->endianness = g_value_get_enum (value);
+ break;
+ case ARG_RED_MASK:
+ vp->red_mask = g_value_get_int (value);
+ break;
+ case ARG_GREEN_MASK:
+ vp->green_mask = g_value_get_int (value);
+ break;
+ case ARG_BLUE_MASK:
+ vp->blue_mask = g_value_get_int (value);
+ break;
+ case ARG_ALPHA_MASK:
+ vp->alpha_mask = g_value_get_int (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+
+ gst_video_parse_update_frame_size (vp);
+}
+
+static void
+gst_video_parse_get_property (GObject * object, guint prop_id, GValue * value,
+ GParamSpec * pspec)
+{
+ GstVideoParse *vp = GST_VIDEO_PARSE (object);
+
+ switch (prop_id) {
+ case ARG_WIDTH:
+ g_value_set_int (value, vp->width);
+ break;
+ case ARG_HEIGHT:
+ g_value_set_int (value, vp->height);
+ break;
+ case ARG_FORMAT:
+ g_value_set_enum (value, vp->format);
+ break;
+ case ARG_FRAMERATE:{
+ gint fps_n, fps_d;
+
+ gst_raw_parse_get_fps (GST_RAW_PARSE (vp), &fps_n, &fps_d);
+ gst_value_set_fraction (value, fps_n, fps_d);
+ break;
+ }
+ case ARG_PAR:
+ gst_value_set_fraction (value, vp->par_n, vp->par_d);
+ break;
+ case ARG_BPP:
+ g_value_set_int (value, vp->bpp);
+ break;
+ case ARG_DEPTH:
+ g_value_set_int (value, vp->depth);
+ break;
+ case ARG_ENDIANNESS:
+ g_value_set_enum (value, vp->endianness);
+ break;
+ case ARG_RED_MASK:
+ g_value_set_int (value, vp->red_mask);
+ break;
+ case ARG_GREEN_MASK:
+ g_value_set_int (value, vp->green_mask);
+ break;
+ case ARG_BLUE_MASK:
+ g_value_set_int (value, vp->blue_mask);
+ break;
+ case ARG_ALPHA_MASK:
+ g_value_set_int (value, vp->alpha_mask);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static guint32
+gst_video_parse_format_to_fourcc (GstVideoParseFormat format)
+{
+ switch (format) {
+ case GST_VIDEO_PARSE_FORMAT_I420:
+ return GST_MAKE_FOURCC ('I', '4', '2', '0');
+ case GST_VIDEO_PARSE_FORMAT_YV12:
+ return GST_MAKE_FOURCC ('Y', 'V', '1', '2');
+ case GST_VIDEO_PARSE_FORMAT_YUY2:
+ return GST_MAKE_FOURCC ('Y', 'U', 'Y', '2');
+ case GST_VIDEO_PARSE_FORMAT_UYVY:
+ return GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y');
+ default:
+ g_assert_not_reached ();
+ }
+ return 0;
+}
+
+void
+gst_video_parse_update_frame_size (GstVideoParse * vp)
+{
+ gint framesize;
+
+ if (vp->format == GST_VIDEO_PARSE_FORMAT_I420 ||
+ vp->format == GST_VIDEO_PARSE_FORMAT_YV12) {
+ framesize = GST_ROUND_UP_4 (vp->width) * GST_ROUND_UP_2 (vp->height)
+ +
+ 2 * (GST_ROUND_UP_8 (vp->width) / 2) * (GST_ROUND_UP_2 (vp->height) /
+ 2);
+ } else if (vp->format == GST_VIDEO_PARSE_FORMAT_YUY2
+ || vp->format == GST_VIDEO_PARSE_FORMAT_UYVY) {
+ framesize = GST_ROUND_UP_4 (vp->width * 2) * vp->height;
+ } else if (vp->format == GST_VIDEO_PARSE_FORMAT_RGB) {
+ framesize = GST_ROUND_UP_4 (vp->width * vp->bpp) * vp->height;
+ } else {
+ framesize = GST_ROUND_UP_4 (vp->width * vp->bpp) * vp->height;
+ }
+
+ 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);
+ GstCaps *caps;
+
+ gint fps_n, fps_d;
+
+ gst_raw_parse_get_fps (rp, &fps_n, &fps_d);
+
+ if (vp->format < GST_VIDEO_PARSE_FORMAT_RGB) {
+ caps = gst_caps_new_simple ("video/x-raw-yuv",
+ "width", G_TYPE_INT, vp->width,
+ "height", G_TYPE_INT, vp->height,
+ "format", GST_TYPE_FOURCC,
+ gst_video_parse_format_to_fourcc (vp->format), "framerate",
+ GST_TYPE_FRACTION, fps_n, fps_d, "pixel_aspect_ratio",
+ GST_TYPE_FRACTION, vp->par_n, vp->par_d, NULL);
+ } else if (vp->format == GST_VIDEO_PARSE_FORMAT_RGB) {
+ caps = gst_caps_new_simple ("video/x-raw-rgb",
+ "width", G_TYPE_INT, vp->width,
+ "height", G_TYPE_INT, vp->height,
+ "bpp", G_TYPE_INT, vp->bpp,
+ "depth", G_TYPE_INT, vp->depth,
+ "framerate", GST_TYPE_FRACTION, fps_n, fps_d,
+ "pixel_aspect_ratio", GST_TYPE_FRACTION, vp->par_n, vp->par_d,
+ "red_mask", G_TYPE_INT, vp->red_mask,
+ "green_mask", G_TYPE_INT, vp->green_mask,
+ "blue_mask", G_TYPE_INT, vp->blue_mask,
+ "alpha_mask", G_TYPE_INT, vp->alpha_mask,
+ "endianness", G_TYPE_INT, vp->endianness, NULL);
+ } else {
+ caps = gst_caps_new_simple ("video/x-raw-gray",
+ "width", G_TYPE_INT, vp->width,
+ "height", G_TYPE_INT, vp->height,
+ "bpp", G_TYPE_INT, vp->bpp,
+ "depth", G_TYPE_INT, vp->depth,
+ "framerate", GST_TYPE_FRACTION, fps_n, fps_d,
+ "pixel_aspect_ratio", GST_TYPE_FRACTION, vp->par_n, vp->par_d, NULL);
+ }
+ return caps;
+}
diff --git a/gst/rawparse/gstvideoparse.h b/gst/rawparse/gstvideoparse.h
new file mode 100644
index 00000000..a7163161
--- /dev/null
+++ b/gst/rawparse/gstvideoparse.h
@@ -0,0 +1,74 @@
+/* GStreamer
+ * Copyright (C) 2006 David A. Schleef <ds@schleef.org>
+ * Copyright (C) 2007 Sebastian Dröge <slomo@circular-chaos.org>
+ *
+ * gstvideoparse.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., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GST_VIDEO_PARSE_H__
+#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())
+#define GST_VIDEO_PARSE(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VIDEO_PARSE,GstVideoParse))
+#define GST_VIDEO_PARSE_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VIDEO_PARSE,GstVideoParseClass))
+#define GST_IS_VIDEO_PARSE(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VIDEO_PARSE))
+#define GST_IS_VIDEO_PARSE_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VIDEO_PARSE))
+
+typedef struct _GstVideoParse GstVideoParse;
+typedef struct _GstVideoParseClass GstVideoParseClass;
+
+struct _GstVideoParse
+{
+ GstRawParse parent;
+
+ /* properties */
+ int width;
+ int height;
+ guint32 format;
+ int par_n;
+ int par_d;
+ int bpp;
+ int depth;
+ int endianness;
+ int red_mask;
+ int blue_mask;
+ int green_mask;
+ int alpha_mask;
+};
+
+struct _GstVideoParseClass
+{
+ GstRawParseClass parent_class;
+};
+
+
+GType gst_video_parse_get_type (void);
+
+#endif /* __GST_VIDEO_PARSE_H__ */
diff --git a/gst/rawparse/plugin.c b/gst/rawparse/plugin.c
new file mode 100644
index 00000000..250be6de
--- /dev/null
+++ b/gst/rawparse/plugin.c
@@ -0,0 +1,26 @@
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <gst/gst.h>
+#include "gstaudioparse.h"
+#include "gstvideoparse.h"
+
+static gboolean
+plugin_init (GstPlugin * plugin)
+{
+ gboolean ret;
+
+ ret = gst_element_register (plugin, "videoparse", GST_RANK_NONE,
+ gst_video_parse_get_type ());
+ ret &= gst_element_register (plugin, "audioparse", GST_RANK_NONE,
+ gst_audio_parse_get_type ());
+
+ return ret;
+}
+
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
+ GST_VERSION_MINOR,
+ "rawparse",
+ "Parses byte streams into raw frames",
+ plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN);