| /* GStreamer |
| * Copyright (C) 2006 David A. Schleef <ds@schleef.org> |
| * Copyright (C) 2007,2009 Sebastian Dröge <sebastian.droege@collabora.co.uk> |
| * |
| * 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., 51 Franklin St, Fifth Floor, |
| * Boston, MA 02110-1301, USA. |
| */ |
| /** |
| * SECTION:element-videoparse |
| * @title: videoparse |
| * |
| * Converts a byte stream into video frames. |
| * |
| * > This element is deprecated. Use #GstRawVideoParse instead. |
| */ |
| |
| #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/video/video.h> |
| #include "gstvideoparse.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 gboolean gst_video_parse_int_valarray_from_string (const gchar * |
| str, GValue * valarray); |
| static gchar *gst_video_parse_int_valarray_to_string (GValue * valarray); |
| |
| GST_DEBUG_CATEGORY_STATIC (gst_video_parse_debug); |
| #define GST_CAT_DEFAULT gst_video_parse_debug |
| |
| enum |
| { |
| PROP_0, |
| PROP_FORMAT, |
| PROP_WIDTH, |
| PROP_HEIGHT, |
| PROP_PAR, |
| PROP_FRAMERATE, |
| PROP_INTERLACED, |
| PROP_TOP_FIELD_FIRST, |
| PROP_STRIDES, |
| PROP_OFFSETS, |
| PROP_FRAMESIZE |
| }; |
| |
| #define gst_video_parse_parent_class parent_class |
| 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); |
| |
| gobject_class->set_property = gst_video_parse_set_property; |
| gobject_class->get_property = gst_video_parse_get_property; |
| |
| 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, |
| G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
| g_object_class_install_property (gobject_class, PROP_WIDTH, |
| g_param_spec_int ("width", "Width", "Width of images in raw stream", |
| 0, INT_MAX, 320, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
| g_object_class_install_property (gobject_class, PROP_HEIGHT, |
| g_param_spec_int ("height", "Height", "Height of images in raw stream", |
| 0, INT_MAX, 240, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
| g_object_class_install_property (gobject_class, PROP_FRAMERATE, |
| gst_param_spec_fraction ("framerate", "Frame Rate", |
| "Frame rate of images in raw stream", 0, 1, G_MAXINT, 1, 25, 1, |
| G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
| g_object_class_install_property (gobject_class, PROP_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_PARAM_STATIC_STRINGS)); |
| g_object_class_install_property (gobject_class, PROP_INTERLACED, |
| g_param_spec_boolean ("interlaced", "Interlaced flag", |
| "True if video is interlaced", FALSE, |
| G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
| g_object_class_install_property (gobject_class, PROP_TOP_FIELD_FIRST, |
| g_param_spec_boolean ("top-field-first", "Top field first", |
| "True if top field is earlier than bottom field", TRUE, |
| G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
| g_object_class_install_property (gobject_class, PROP_STRIDES, |
| g_param_spec_string ("strides", "Strides", |
| "Stride of each planes in bytes using string format: 's0,s1,s2,s3'", |
| NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
| g_object_class_install_property (gobject_class, PROP_OFFSETS, |
| g_param_spec_string ("offsets", "Offsets", |
| "Offset of each planes in bytes using string format: 'o0,o1,o2,o3'", |
| NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
| g_object_class_install_property (gobject_class, PROP_FRAMESIZE, |
| g_param_spec_uint ("framesize", "Framesize", |
| "Size of an image in raw stream (0: default)", 0, G_MAXUINT, 0, |
| G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
| |
| gst_element_class_set_static_metadata (gstelement_class, "Video Parse", |
| "Filter/Video", |
| "Converts stream into video frames (deprecated: use rawvideoparse instead)", |
| "David Schleef <ds@schleef.org>, " |
| "Sebastian Dröge <sebastian.droege@collabora.co.uk>"); |
| |
| 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"); |
| } |
| |
| static void |
| gst_video_parse_init (GstVideoParse * 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 |
| gst_video_parse_set_property (GObject * object, guint prop_id, |
| const GValue * value, GParamSpec * pspec) |
| { |
| GstVideoParse *vp = GST_VIDEO_PARSE (object); |
| |
| switch (prop_id) { |
| case PROP_FORMAT: |
| g_object_set (G_OBJECT (vp->rawvideoparse), "format", |
| g_value_get_enum (value), NULL); |
| break; |
| |
| case PROP_WIDTH: |
| g_object_set (G_OBJECT (vp->rawvideoparse), "width", |
| g_value_get_int (value), NULL); |
| break; |
| |
| case PROP_HEIGHT: |
| g_object_set (G_OBJECT (vp->rawvideoparse), "height", |
| g_value_get_int (value), NULL); |
| break; |
| |
| case PROP_FRAMERATE: |
| g_object_set (G_OBJECT (vp->rawvideoparse), "framerate", |
| gst_value_get_fraction_numerator (value), |
| gst_value_get_fraction_denominator (value), NULL); |
| break; |
| |
| case PROP_PAR: |
| 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: |
| g_object_set (G_OBJECT (vp->rawvideoparse), "interlaced", |
| g_value_get_boolean (value), NULL); |
| break; |
| |
| case PROP_TOP_FIELD_FIRST: |
| g_object_set (G_OBJECT (vp->rawvideoparse), "top-field-first", |
| g_value_get_boolean (value), NULL); |
| break; |
| |
| case PROP_STRIDES:{ |
| GValue valarray = G_VALUE_INIT; |
| |
| if (gst_video_parse_int_valarray_from_string (g_value_get_string (value), |
| &valarray)) { |
| g_object_set (G_OBJECT (vp->rawvideoparse), "plane-strides", |
| &valarray, NULL); |
| g_value_unset (&valarray); |
| } else { |
| GST_WARNING_OBJECT (vp, "failed to deserialize given strides"); |
| } |
| |
| break; |
| } |
| |
| case PROP_OFFSETS:{ |
| GValue valarray = G_VALUE_INIT; |
| |
| if (gst_video_parse_int_valarray_from_string (g_value_get_string (value), |
| &valarray)) { |
| g_object_set (G_OBJECT (vp->rawvideoparse), "plane-offsets", |
| valarray, NULL); |
| g_value_unset (&valarray); |
| } else { |
| GST_WARNING_OBJECT (vp, "failed to deserialize given offsets"); |
| } |
| |
| break; |
| } |
| |
| case PROP_FRAMESIZE: |
| g_object_set (G_OBJECT (vp->rawvideoparse), "frame-size", |
| g_value_get_uint (value), NULL); |
| break; |
| |
| default: |
| G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
| break; |
| } |
| } |
| |
| 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 PROP_FORMAT:{ |
| GstVideoFormat format; |
| g_object_get (G_OBJECT (vp->rawvideoparse), "format", &format, NULL); |
| g_value_set_enum (value, format); |
| break; |
| } |
| |
| 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:{ |
| 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; |
| 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:{ |
| 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:{ |
| gboolean interlaced; |
| g_object_get (G_OBJECT (vp->rawvideoparse), "interlaced", &interlaced, |
| NULL); |
| g_value_set_boolean (value, interlaced); |
| break; |
| } |
| |
| 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:{ |
| GValue array = { 0, }; |
| |
| g_value_init (&array, GST_TYPE_ARRAY); |
| g_object_get_property (G_OBJECT (vp->rawvideoparse), "plane-strides", |
| &array); |
| g_value_take_string (value, |
| gst_video_parse_int_valarray_to_string (&array)); |
| break; |
| } |
| |
| case PROP_OFFSETS:{ |
| GValue array = { 0, }; |
| |
| g_value_init (&array, GST_TYPE_ARRAY); |
| g_object_get_property (G_OBJECT (vp->rawvideoparse), "plane-offsets", |
| &array); |
| g_value_take_string (value, |
| gst_video_parse_int_valarray_to_string (&array)); |
| break; |
| } |
| |
| case PROP_FRAMESIZE:{ |
| guint frame_size; |
| g_object_get (G_OBJECT (vp->rawvideoparse), "frame-size", &frame_size, |
| NULL); |
| g_value_set_uint (value, frame_size); |
| break; |
| } |
| |
| default: |
| G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); |
| break; |
| } |
| } |
| |
| static gboolean |
| gst_video_parse_int_valarray_from_string (const gchar * str, GValue * valarray) |
| { |
| gchar **strv; |
| guint length; |
| guint i; |
| GValue gvalue = G_VALUE_INIT; |
| |
| if (str == NULL) |
| return FALSE; |
| |
| strv = g_strsplit (str, ",", GST_VIDEO_MAX_PLANES); |
| if (strv == NULL) |
| return FALSE; |
| |
| length = g_strv_length (strv); |
| g_value_init (valarray, GST_TYPE_ARRAY); |
| 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) { |
| goto error; |
| } |
| |
| g_value_set_uint (&gvalue, val); |
| gst_value_array_append_value (valarray, &gvalue); |
| } |
| |
| g_strfreev (strv); |
| return TRUE; |
| |
| error: |
| return FALSE; |
| } |
| |
| static gchar * |
| gst_video_parse_int_valarray_to_string (GValue * valarray) |
| { |
| /* 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; |
| |
| for (i = 0; i < gst_value_array_get_size (valarray); i++) { |
| const GValue *gvalue = gst_value_array_get_value (valarray, i); |
| guint val; |
| |
| val = g_value_get_int (gvalue); |
| g_snprintf (stride_str, sizeof (stride_str), "%u", val); |
| |
| if (str == NULL) { |
| str = g_strdup (stride_str); |
| } else { |
| gchar *new_str = g_strdup_printf ("%s,%s", str, stride_str); |
| g_free (str); |
| str = new_str; |
| } |
| } |
| |
| return str; |
| } |