From b31ab745a506acb17a3f70119304d43b19a76988 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Sat, 14 Mar 2009 10:43:28 +0100 Subject: add new vdpau directory --- configure.ac | 10 ++++++++++ sys/Makefile.am | 10 ++++++++-- sys/vdpau/Makefile.am | 11 +++++++++++ 3 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 sys/vdpau/Makefile.am diff --git a/configure.ac b/configure.ac index bd60b231..dde1cb81 100644 --- a/configure.ac +++ b/configure.ac @@ -1422,6 +1422,14 @@ AG_GST_CHECK_FEATURE(ACM, [Windows ACM library], acm, [ ], [HAVE_ACM="no"]) ]) +dnl *** vdpau *** +translit(dnm, m, l) AM_CONDITIONAL(USE_VDPAU, true) +AG_GST_CHECK_FEATURE(VDPAU, [VDPAU], vdpau, [ + AC_MSG_CHECKING([Checking for up to date vdpau installation]) + AC_CHECK_HEADERS([vdpau/vdpau.h vdpau/vdpau_x11.h], + [HAVE_VDPAU="yes"], [HAVE_VDPAU="no"]) +]) + else dnl not building plugins with external dependencies, @@ -1476,6 +1484,7 @@ AM_CONDITIONAL(USE_XVID, false) AM_CONDITIONAL(USE_WILDMIDI, false) AM_CONDITIONAL(USE_WININET, false) AM_CONDITIONAL(USE_ACM, false) +AM_CONDITIONAL(USE_VDPAU, false) fi dnl of EXT plugins @@ -1608,6 +1617,7 @@ sys/oss4/Makefile sys/osxvideo/Makefile sys/qtwrapper/Makefile sys/vcd/Makefile +sys/vdpau/Makefile sys/wasapi/Makefile sys/wininet/Makefile sys/winks/Makefile diff --git a/sys/Makefile.am b/sys/Makefile.am index 161f3339..15c89e17 100644 --- a/sys/Makefile.am +++ b/sys/Makefile.am @@ -70,8 +70,14 @@ else ACM_DIR= endif -SUBDIRS = $(ACM_DIR) $(DIRECTDRAW_DIR) $(DVB_DIR) $(FBDEV_DIR) $(OSS4_DIR) $(OSX_VIDEO_DIR) $(QT_DIR) $(VCD_DIR) $(WININET_DIR) +if USE_VDPAU +VDPAU_DIR=vdpau +else +VDPAU_DIR= +endif + +SUBDIRS = $(ACM_DIR) $(DIRECTDRAW_DIR) $(DVB_DIR) $(FBDEV_DIR) $(OSS4_DIR) $(OSX_VIDEO_DIR) $(QT_DIR) $(VCD_DIR) $(VDPAU_DIR) $(WININET_DIR) DIST_SUBDIRS = acmenc acmmp3dec directdraw dvb fbdev dshowdecwrapper dshowsrcwrapper dshowvideosink \ - oss4 osxvideo qtwrapper vcd wasapi wininet winks winscreencap + oss4 osxvideo qtwrapper vcd vdpau wasapi wininet winks winscreencap diff --git a/sys/vdpau/Makefile.am b/sys/vdpau/Makefile.am new file mode 100644 index 00000000..03d87758 --- /dev/null +++ b/sys/vdpau/Makefile.am @@ -0,0 +1,11 @@ + +lib_LTLIBRARIES = \ + libgstvdpau.la + +libgstvdpau_la_SOURCES = + +libgstvdpau_la_CFLAGS = $(GST_CFLAGS) +libgstvdpau_la_LIBADD = $(GST_LIBS) +libgstvdpau_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) +libgstvdpau_la_LIBTOOLFLAGS = --tag=disable-static + -- cgit v1.2.1 From b25f035fe5e02a14ae3f52912213ed6357f627f6 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Sun, 15 Mar 2009 21:21:49 +0100 Subject: vdpau: add basic base class for vdpau decoders --- sys/vdpau/Makefile.am | 15 +-- sys/vdpau/gstvdpaudecoder.c | 224 ++++++++++++++++++++++++++++++++++++++++++++ sys/vdpau/gstvdpaudecoder.h | 66 +++++++++++++ 3 files changed, 299 insertions(+), 6 deletions(-) create mode 100644 sys/vdpau/gstvdpaudecoder.c create mode 100644 sys/vdpau/gstvdpaudecoder.h diff --git a/sys/vdpau/Makefile.am b/sys/vdpau/Makefile.am index 03d87758..777a05cb 100644 --- a/sys/vdpau/Makefile.am +++ b/sys/vdpau/Makefile.am @@ -1,11 +1,14 @@ +plugin_LTLIBRARIES = libgstvdpau.la -lib_LTLIBRARIES = \ - libgstvdpau.la +libgstvdpau_la_SOURCES = \ + gstvdpaudecoder.c -libgstvdpau_la_SOURCES = - -libgstvdpau_la_CFLAGS = $(GST_CFLAGS) -libgstvdpau_la_LIBADD = $(GST_LIBS) +libgstvdpau_la_CFLAGS = $(GST_CFLAGS) $(X11_CFLAGS) -Ivdpau +libgstvdpau_la_LIBADD = $(GST_LIBS) $(X11_LIBS) -lvdpau libgstvdpau_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) libgstvdpau_la_LIBTOOLFLAGS = --tag=disable-static +noinst_HEADERS = \ + gstvdpaudecoder.h + + diff --git a/sys/vdpau/gstvdpaudecoder.c b/sys/vdpau/gstvdpaudecoder.c new file mode 100644 index 00000000..f828d2ba --- /dev/null +++ b/sys/vdpau/gstvdpaudecoder.c @@ -0,0 +1,224 @@ +/* + * GStreamer + * Copyright (C) 2006 Stefan Kost + * Copyright (C) 2009 Carl-Anton Ingmarsson + * + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include +#include +#include "gstvdpaudecoder.h" + +GST_DEBUG_CATEGORY_STATIC (gst_vdpaudecoder_debug); +#define GST_CAT_DEFAULT gst_vdpaudecoder_debug + +/* Filter signals and args */ +enum +{ + /* FILL ME */ + LAST_SIGNAL +}; + +enum +{ + PROP_0, + PROP_DISPLAY, + PROP_SILENT +}; + +static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("video/x-raw-yuv, " + "framerate = (fraction) [ 0, MAX ], " + "width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]")); + +/* debug category for fltering log messages + * + * FIXME:exchange the string 'Template vdpaudecoder' with your description + */ +#define DEBUG_INIT(bla) \ + GST_DEBUG_CATEGORY_INIT (gst_vdpaudecoder_debug, "vdpaudecoder", 0, "vdpaudecoder base class"); + +GST_BOILERPLATE_FULL (GstVDPAUDecoder, gst_vdpaudecoder, GstElement, + GST_TYPE_ELEMENT, DEBUG_INIT); + +static void gst_vdpaudecoder_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_vdpaudecoder_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +static GstStateChangeReturn gst_vdpaudecoder_change_state (GstElement * element, + GstStateChange transition); + +/* GObject vmethod implementations */ + +static void +gst_vdpaudecoder_base_init (gpointer klass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + + gst_element_class_set_details_simple (element_class, + "VDPAUDecoder", + "Generic/Filter", + "VDPAU decoder base class", + "Carl-Anton Ingmarsson "); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&src_template)); +} + +/* initialize the vdpaudecoder's class */ +static void +gst_vdpaudecoder_class_init (GstVDPAUDecoderClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + + gobject_class = (GObjectClass *) klass; + gstelement_class = (GstElementClass *) klass; + + gobject_class->set_property = gst_vdpaudecoder_set_property; + gobject_class->get_property = gst_vdpaudecoder_get_property; + + g_object_class_install_property (gobject_class, PROP_DISPLAY, + g_param_spec_string ("display", "Display", "X Display name", + NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + g_object_class_install_property (gobject_class, PROP_SILENT, + g_param_spec_boolean ("silent", "Silent", "Produce verbose output ?", + FALSE, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE)); + + gstelement_class->change_state = + GST_DEBUG_FUNCPTR (gst_vdpaudecoder_change_state); +} + +static void +gst_vdpaudecoder_init (GstVDPAUDecoder * dec, GstVDPAUDecoderClass * klass) +{ + dec->display = NULL; + dec->device = 0; + dec->silent = FALSE; + + dec->src = gst_pad_new_from_static_template (&src_template, "src"); + gst_element_add_pad (GST_ELEMENT (dec), dec->src); + + dec->sink = + gst_pad_new_from_template (gst_element_class_get_pad_template + (GST_ELEMENT_CLASS (klass), "sink"), "sink"); + gst_element_add_pad (GST_ELEMENT (dec), dec->sink); +} + +static GstStateChangeReturn +gst_vdpaudecoder_change_state (GstElement * element, GstStateChange transition) +{ + GstVDPAUDecoder *dec; + + dec = GST_VDPAUDECODER (element); + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + { + Display *display; + int screen; + VdpStatus status; + + /* FIXME: We probably want to use the same VdpDevice for every VDPAU element */ + display = XOpenDisplay (dec->display); + if (!display) { + GST_ELEMENT_ERROR (dec, RESOURCE, WRITE, ("Could not initialise VDPAU"), + ("Could not open display")); + return GST_STATE_CHANGE_FAILURE; + } + + screen = DefaultScreen (display); + status = vdp_device_create_x11 (display, screen, &dec->device, NULL); + if (status != VDP_STATUS_OK) { + GST_ELEMENT_ERROR (dec, RESOURCE, WRITE, ("Could not initialise VDPAU"), + ("Could not create VDPAU device")); + XCloseDisplay (display); + + return GST_STATE_CHANGE_FAILURE; + } + XCloseDisplay (display); + break; + } + + default: + break; + } + + return GST_STATE_CHANGE_SUCCESS; +} + +static void +gst_vdpaudecoder_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstVDPAUDecoder *dec = GST_VDPAUDECODER (object); + + switch (prop_id) { + case PROP_DISPLAY: + g_free (dec->display); + dec->display = g_value_dup_string (value); + break; + case PROP_SILENT: + dec->silent = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_vdpaudecoder_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstVDPAUDecoder *dec = GST_VDPAUDECODER (object); + + switch (prop_id) { + case PROP_DISPLAY: + g_value_set_string (value, dec->display); + break; + case PROP_SILENT: + g_value_set_boolean (value, dec->silent); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static gboolean +plugin_init (GstPlugin * plugin) +{ + return TRUE; +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "vdpau", + "vdpau elements", + plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/sys/vdpau/gstvdpaudecoder.h b/sys/vdpau/gstvdpaudecoder.h new file mode 100644 index 00000000..83506866 --- /dev/null +++ b/sys/vdpau/gstvdpaudecoder.h @@ -0,0 +1,66 @@ +/* + * GStreamer + * Copyright (C) 2006 Stefan Kost + * Copyright (C) 2009 Carl-Anton Ingmarsson + * + * 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_VDPAUDECODER_H__ +#define __GST_VDPAUDECODER_H__ + +#include +#include + +#include + +G_BEGIN_DECLS + +#define GST_TYPE_VDPAUDECODER \ + (gst_vdpaudecoder_get_type()) +#define GST_VDPAUDECODER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VDPAUDECODER,GstVDPAUDecoder)) +#define GST_VDPAUDECODER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VDPAUDECODER,GstVDPAUDecoderClass)) +#define GST_IS_VDPAUDECODER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VDPAUDECODER)) +#define GST_IS_VDPAUDECODER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VDPAUDECODER)) + +typedef struct _GstVDPAUDecoder GstVDPAUDecoder; +typedef struct _GstVDPAUDecoderClass GstVDPAUDecoderClass; + +struct _GstVDPAUDecoder { + GstElement element; + + gchar *display; + VdpDevice device; + + GstPad *src; + GstPad *sink; + + gboolean silent; +}; + +struct _GstVDPAUDecoderClass { + GstBaseTransformClass parent_class; +}; + +GType gst_vdpaudecoder_get_type (void); + +G_END_DECLS + +#endif /* __GST_VDPAUDECODER_H__ */ -- cgit v1.2.1 From 05908cd13001e62bf8416ff0d0856d9f145c415e Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Sun, 15 Mar 2009 21:23:35 +0100 Subject: vdpau: small indentation fix --- sys/vdpau/gstvdpaudecoder.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sys/vdpau/gstvdpaudecoder.c b/sys/vdpau/gstvdpaudecoder.c index f828d2ba..fe4e8796 100644 --- a/sys/vdpau/gstvdpaudecoder.c +++ b/sys/vdpau/gstvdpaudecoder.c @@ -124,8 +124,7 @@ gst_vdpaudecoder_init (GstVDPAUDecoder * dec, GstVDPAUDecoderClass * klass) dec->src = gst_pad_new_from_static_template (&src_template, "src"); gst_element_add_pad (GST_ELEMENT (dec), dec->src); - dec->sink = - gst_pad_new_from_template (gst_element_class_get_pad_template + dec->sink = gst_pad_new_from_template (gst_element_class_get_pad_template (GST_ELEMENT_CLASS (klass), "sink"), "sink"); gst_element_add_pad (GST_ELEMENT (dec), dec->sink); } -- cgit v1.2.1 From f2eea7d0ed8004d4630739b04daf27075d6834e5 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Fri, 20 Mar 2009 21:24:40 +0100 Subject: vdpau: implement downstream caps negotiation --- sys/vdpau/Makefile.am | 7 +- sys/vdpau/gstvdpaudecoder.c | 283 +++++++++++++++++++++++++++++++--------- sys/vdpau/gstvdpaudecoder.h | 34 ++--- sys/vdpau/gstvdpauh264decoder.c | 202 ++++++++++++++++++++++++++++ sys/vdpau/gstvdpauh264decoder.h | 88 +++++++++++++ sys/vdpau/vdpauvariables.h | 45 +++++++ 6 files changed, 577 insertions(+), 82 deletions(-) create mode 100644 sys/vdpau/gstvdpauh264decoder.c create mode 100644 sys/vdpau/gstvdpauh264decoder.h create mode 100644 sys/vdpau/vdpauvariables.h diff --git a/sys/vdpau/Makefile.am b/sys/vdpau/Makefile.am index 777a05cb..3e718abe 100644 --- a/sys/vdpau/Makefile.am +++ b/sys/vdpau/Makefile.am @@ -1,7 +1,8 @@ plugin_LTLIBRARIES = libgstvdpau.la libgstvdpau_la_SOURCES = \ - gstvdpaudecoder.c + gstvdpaudecoder.c\ + gstvdpauh264decoder.c libgstvdpau_la_CFLAGS = $(GST_CFLAGS) $(X11_CFLAGS) -Ivdpau libgstvdpau_la_LIBADD = $(GST_LIBS) $(X11_LIBS) -lvdpau @@ -9,6 +10,8 @@ libgstvdpau_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) libgstvdpau_la_LIBTOOLFLAGS = --tag=disable-static noinst_HEADERS = \ - gstvdpaudecoder.h + gstvdpaudecoder.h\ + vdpauvariables.h \ + gstvdpauh264decoder.h diff --git a/sys/vdpau/gstvdpaudecoder.c b/sys/vdpau/gstvdpaudecoder.c index fe4e8796..230fa80c 100644 --- a/sys/vdpau/gstvdpaudecoder.c +++ b/sys/vdpau/gstvdpaudecoder.c @@ -28,6 +28,8 @@ #include #include + +#include "vdpauvariables.h" #include "gstvdpaudecoder.h" GST_DEBUG_CATEGORY_STATIC (gst_vdpaudecoder_debug); @@ -61,7 +63,7 @@ static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src", #define DEBUG_INIT(bla) \ GST_DEBUG_CATEGORY_INIT (gst_vdpaudecoder_debug, "vdpaudecoder", 0, "vdpaudecoder base class"); -GST_BOILERPLATE_FULL (GstVDPAUDecoder, gst_vdpaudecoder, GstElement, +GST_BOILERPLATE_FULL (GstVdpauDecoder, gst_vdpaudecoder, GstElement, GST_TYPE_ELEMENT, DEBUG_INIT); static void gst_vdpaudecoder_set_property (GObject * object, guint prop_id, @@ -69,8 +71,213 @@ static void gst_vdpaudecoder_set_property (GObject * object, guint prop_id, static void gst_vdpaudecoder_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); -static GstStateChangeReturn gst_vdpaudecoder_change_state (GstElement * element, - GstStateChange transition); +typedef struct +{ + VdpChromaType chroma_type; + VdpYCbCrFormat format; + guint32 fourcc; +} VdpauFormats; + +static VdpChromaType chroma_types[3] = + { VDP_CHROMA_TYPE_420, VDP_CHROMA_TYPE_422, VDP_CHROMA_TYPE_444 }; +static VdpauFormats formats[6] = { + { + VDP_CHROMA_TYPE_420, + VDP_YCBCR_FORMAT_NV12, + GST_MAKE_FOURCC ('N', 'V', '1', '2') + }, + { + VDP_CHROMA_TYPE_422, + VDP_YCBCR_FORMAT_UYVY, + GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y') + }, + { + VDP_CHROMA_TYPE_444, + VDP_YCBCR_FORMAT_V8U8Y8A8, + GST_MAKE_FOURCC ('A', 'Y', 'U', 'V') + }, + { + VDP_CHROMA_TYPE_444, + VDP_YCBCR_FORMAT_Y8U8V8A8, + GST_MAKE_FOURCC ('A', 'V', 'U', 'Y') + }, + { + VDP_CHROMA_TYPE_422, + VDP_YCBCR_FORMAT_YUYV, + GST_MAKE_FOURCC ('Y', 'U', 'Y', 'V') + }, + { + VDP_CHROMA_TYPE_420, + VDP_YCBCR_FORMAT_YV12, + GST_MAKE_FOURCC ('Y', 'V', '1', '2') + } +}; + +static GstCaps * +gst_vdpaudecoder_get_vdpau_support (GstVdpauDecoder * dec) +{ + GstCaps *caps; + gint i; + + caps = gst_caps_new_empty (); + + for (i = 0; i < 3; i++) { + VdpStatus status; + VdpBool is_supported; + guint32 max_w, max_h; + + status = vdp_video_surface_query_capabilities (dec->device, chroma_types[i], + &is_supported, &max_w, &max_h); + + if (status != VDP_STATUS_OK && status != VDP_STATUS_INVALID_CHROMA_TYPE) { + GST_ELEMENT_ERROR (dec, RESOURCE, READ, + ("Could not get VDPAU capabilites"), + ("Could not query video surface capabilities")); + + return NULL; + } + if (is_supported) { + gint j; + + for (j = 0; j < 6; j++) { + if (formats[j].chroma_type != chroma_types[i]) + continue; + + status = + vdp_video_surface_query_ycbcr_capabilities (dec->device, + formats[j].chroma_type, formats[j].format, &is_supported); + if (status != VDP_STATUS_OK + && status != VDP_STATUS_INVALID_Y_CB_CR_FORMAT) { + GST_ELEMENT_ERROR (dec, RESOURCE, READ, + ("Could not get VDPAU capabilites"), + ("Could not query video surface ycbcr capabilities")); + + return NULL; + } + if (is_supported) { + GstCaps *format_caps; + + format_caps = gst_caps_new_simple ("video/x-raw-yuv", + "format", GST_TYPE_FOURCC, formats[j].fourcc, + "width", GST_TYPE_INT_RANGE, 1, max_w, + "height", GST_TYPE_INT_RANGE, 1, max_h, + "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL); + gst_caps_append (caps, format_caps); + GST_DEBUG ("fourcc: %" GST_FOURCC_FORMAT "\n", + GST_FOURCC_ARGS (formats[j].fourcc)); + } + } + } + } + if (gst_caps_is_empty (caps)) { + gst_caps_unref (caps); + return NULL; + } + + return caps; +} + +static gboolean +gst_vdpaudecoder_init_vdpau (GstVdpauDecoder * dec) +{ + Display *display; + int screen; + VdpStatus status; + GstCaps *caps; + + /* FIXME: We probably want to use the same VdpDevice for every VDPAU element */ + display = XOpenDisplay (dec->display); + if (!display) { + GST_ELEMENT_ERROR (dec, RESOURCE, READ, ("Could not initialise VDPAU"), + ("Could not open display")); + return GST_STATE_CHANGE_FAILURE; + } + + screen = DefaultScreen (display); + status = + vdp_device_create_x11 (display, screen, &dec->device, + &vdp_get_proc_address); + if (status != VDP_STATUS_OK) { + GST_ELEMENT_ERROR (dec, RESOURCE, READ, ("Could not initialise VDPAU"), + ("Could not create VDPAU device")); + XCloseDisplay (display); + + return FALSE; + } + XCloseDisplay (display); + + vdp_get_proc_address (dec->device, + VDP_FUNC_ID_VIDEO_SURFACE_QUERY_CAPABILITIES, + (void **) &vdp_video_surface_query_capabilities); + vdp_get_proc_address (dec->device, + VDP_FUNC_ID_VIDEO_SURFACE_QUERY_GET_PUT_BITS_Y_CB_CR_CAPABILITIES, + (void **) &vdp_video_surface_query_ycbcr_capabilities); + + caps = gst_vdpaudecoder_get_vdpau_support (dec); + if (!caps) + return FALSE; + + dec->src_caps = caps; + + return TRUE; +} + +static gboolean +gst_vdpaudecoder_sink_set_caps (GstPad * pad, GstCaps * caps) +{ + GstVdpauDecoder *dec = GST_VDPAU_DECODER (GST_OBJECT_PARENT (pad)); + + GstCaps *src_caps, *new_caps; + GstStructure *structure; + gint width, height; + gint framerate_numerator, framerate_denominator; + gboolean res; + + structure = gst_caps_get_structure (caps, 0); + gst_structure_get_int (structure, "width", &width); + gst_structure_get_int (structure, "height", &height); + gst_structure_get_fraction (structure, "framerate", + &framerate_numerator, &framerate_denominator); + + src_caps = gst_pad_get_allowed_caps (dec->src); + GST_DEBUG ("caps: %s\n\n", gst_caps_to_string (src_caps)); + + structure = gst_caps_get_structure (src_caps, 0); + gst_structure_set (structure, + "width", G_TYPE_INT, width, + "height", G_TYPE_INT, height, + "framerate", GST_TYPE_FRACTION, framerate_numerator, + framerate_denominator, NULL); + + new_caps = gst_caps_copy_nth (src_caps, 0); + gst_caps_unref (src_caps); + gst_pad_fixate_caps (dec->src, new_caps); + res = gst_pad_set_caps (dec->src, new_caps); + + gst_caps_unref (new_caps); + GST_DEBUG ("caps: %s\n\n", gst_caps_to_string (gst_pad_get_caps (dec->src))); + + if (!res) + return FALSE; + + return TRUE; +} + +static GstCaps * +gst_vdpaudecoder_src_getcaps (GstPad * pad) +{ + GstVdpauDecoder *dec; + + dec = GST_VDPAU_DECODER (GST_OBJECT_PARENT (pad)); + + if (GST_PAD_CAPS (dec->src)) + return gst_caps_ref (GST_PAD_CAPS (dec->src)); + + if (dec->src_caps) + return gst_caps_ref (dec->src_caps); + + return gst_caps_copy (gst_pad_get_pad_template_caps (dec->src)); +} /* GObject vmethod implementations */ @@ -80,7 +287,7 @@ gst_vdpaudecoder_base_init (gpointer klass) GstElementClass *element_class = GST_ELEMENT_CLASS (klass); gst_element_class_set_details_simple (element_class, - "VDPAUDecoder", + "VdpauDecoder", "Generic/Filter", "VDPAU decoder base class", "Carl-Anton Ingmarsson "); @@ -91,7 +298,7 @@ gst_vdpaudecoder_base_init (gpointer klass) /* initialize the vdpaudecoder's class */ static void -gst_vdpaudecoder_class_init (GstVDPAUDecoderClass * klass) +gst_vdpaudecoder_class_init (GstVdpauDecoderClass * klass) { GObjectClass *gobject_class; GstElementClass *gstelement_class; @@ -109,73 +316,33 @@ gst_vdpaudecoder_class_init (GstVDPAUDecoderClass * klass) g_object_class_install_property (gobject_class, PROP_SILENT, g_param_spec_boolean ("silent", "Silent", "Produce verbose output ?", FALSE, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE)); - - gstelement_class->change_state = - GST_DEBUG_FUNCPTR (gst_vdpaudecoder_change_state); } static void -gst_vdpaudecoder_init (GstVDPAUDecoder * dec, GstVDPAUDecoderClass * klass) +gst_vdpaudecoder_init (GstVdpauDecoder * dec, GstVdpauDecoderClass * klass) { dec->display = NULL; dec->device = 0; dec->silent = FALSE; + dec->src_caps = NULL; dec->src = gst_pad_new_from_static_template (&src_template, "src"); + gst_pad_set_getcaps_function (dec->src, gst_vdpaudecoder_src_getcaps); gst_element_add_pad (GST_ELEMENT (dec), dec->src); dec->sink = gst_pad_new_from_template (gst_element_class_get_pad_template (GST_ELEMENT_CLASS (klass), "sink"), "sink"); + gst_pad_set_setcaps_function (dec->sink, gst_vdpaudecoder_sink_set_caps); gst_element_add_pad (GST_ELEMENT (dec), dec->sink); -} -static GstStateChangeReturn -gst_vdpaudecoder_change_state (GstElement * element, GstStateChange transition) -{ - GstVDPAUDecoder *dec; - - dec = GST_VDPAUDECODER (element); - - switch (transition) { - case GST_STATE_CHANGE_NULL_TO_READY: - { - Display *display; - int screen; - VdpStatus status; - - /* FIXME: We probably want to use the same VdpDevice for every VDPAU element */ - display = XOpenDisplay (dec->display); - if (!display) { - GST_ELEMENT_ERROR (dec, RESOURCE, WRITE, ("Could not initialise VDPAU"), - ("Could not open display")); - return GST_STATE_CHANGE_FAILURE; - } - - screen = DefaultScreen (display); - status = vdp_device_create_x11 (display, screen, &dec->device, NULL); - if (status != VDP_STATUS_OK) { - GST_ELEMENT_ERROR (dec, RESOURCE, WRITE, ("Could not initialise VDPAU"), - ("Could not create VDPAU device")); - XCloseDisplay (display); - - return GST_STATE_CHANGE_FAILURE; - } - XCloseDisplay (display); - break; - } - - default: - break; - } - - return GST_STATE_CHANGE_SUCCESS; + gst_vdpaudecoder_init_vdpau (dec); } static void gst_vdpaudecoder_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { - GstVDPAUDecoder *dec = GST_VDPAUDECODER (object); + GstVdpauDecoder *dec = GST_VDPAU_DECODER (object); switch (prop_id) { case PROP_DISPLAY: @@ -195,7 +362,7 @@ static void gst_vdpaudecoder_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { - GstVDPAUDecoder *dec = GST_VDPAUDECODER (object); + GstVdpauDecoder *dec = GST_VDPAU_DECODER (object); switch (prop_id) { case PROP_DISPLAY: @@ -209,15 +376,3 @@ gst_vdpaudecoder_get_property (GObject * object, guint prop_id, break; } } - -static gboolean -plugin_init (GstPlugin * plugin) -{ - return TRUE; -} - -GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, - GST_VERSION_MINOR, - "vdpau", - "vdpau elements", - plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/sys/vdpau/gstvdpaudecoder.h b/sys/vdpau/gstvdpaudecoder.h index 83506866..f713b0dd 100644 --- a/sys/vdpau/gstvdpaudecoder.h +++ b/sys/vdpau/gstvdpaudecoder.h @@ -19,8 +19,8 @@ * Boston, MA 02111-1307, USA. */ -#ifndef __GST_VDPAUDECODER_H__ -#define __GST_VDPAUDECODER_H__ +#ifndef __GST_VDPAU_DECODER_H__ +#define __GST_VDPAU_DECODER_H__ #include #include @@ -29,21 +29,21 @@ G_BEGIN_DECLS -#define GST_TYPE_VDPAUDECODER \ +#define GST_TYPE_VDPAU_DECODER \ (gst_vdpaudecoder_get_type()) -#define GST_VDPAUDECODER(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VDPAUDECODER,GstVDPAUDecoder)) -#define GST_VDPAUDECODER_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VDPAUDECODER,GstVDPAUDecoderClass)) -#define GST_IS_VDPAUDECODER(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VDPAUDECODER)) -#define GST_IS_VDPAUDECODER_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VDPAUDECODER)) +#define GST_VDPAU_DECODER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VDPAU_DECODER,GstVdpauDecoder)) +#define GST_VDPAU_DECODER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VDPAU_DECODER,GstVdpauDecoderClass)) +#define GST_IS_VDPAU_DECODER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VDPAU_DECODER)) +#define GST_IS_VDPAU_DECODER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VDPAU_DECODER)) -typedef struct _GstVDPAUDecoder GstVDPAUDecoder; -typedef struct _GstVDPAUDecoderClass GstVDPAUDecoderClass; +typedef struct _GstVdpauDecoder GstVdpauDecoder; +typedef struct _GstVdpauDecoderClass GstVdpauDecoderClass; -struct _GstVDPAUDecoder { +struct _GstVdpauDecoder { GstElement element; gchar *display; @@ -52,10 +52,12 @@ struct _GstVDPAUDecoder { GstPad *src; GstPad *sink; + GstCaps *src_caps; + gboolean silent; }; -struct _GstVDPAUDecoderClass { +struct _GstVdpauDecoderClass { GstBaseTransformClass parent_class; }; @@ -63,4 +65,4 @@ GType gst_vdpaudecoder_get_type (void); G_END_DECLS -#endif /* __GST_VDPAUDECODER_H__ */ +#endif /* __GST_VDPAU_DECODER_H__ */ diff --git a/sys/vdpau/gstvdpauh264decoder.c b/sys/vdpau/gstvdpauh264decoder.c new file mode 100644 index 00000000..794f71d1 --- /dev/null +++ b/sys/vdpau/gstvdpauh264decoder.c @@ -0,0 +1,202 @@ +/* + * GStreamer + * Copyright (C) 2005 Thomas Vander Stichele + * Copyright (C) 2005 Ronald S. Bultje + * Copyright (C) 2009 Carl-Anton Ingmarsson + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Alternatively, the contents of this file may be used under the + * GNU Lesser General Public License Version 2.1 (the "LGPL"), in + * which case the following provisions apply instead of the ones + * mentioned above: + * + * 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-vdpauh264decoder + * + * FIXME:Describe vdpauh264decoder here. + * + * + * Example launch line + * |[ + * gst-launch -v -m fakesrc ! vdpauh264decoder ! fakesink silent=TRUE + * ]| + * + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#include "gstvdpauh264decoder.h" + +GST_DEBUG_CATEGORY_STATIC (gst_vdpau_h264decoder_debug); +#define GST_CAT_DEFAULT gst_vdpau_h264decoder_debug + +/* Filter signals and args */ +enum +{ + /* FILL ME */ + LAST_SIGNAL +}; + +enum +{ + PROP_0, + PROP_SILENT +}; + +/* the capabilities of the inputs and outputs. + * + * describe the real formats here. + */ +static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("video/x-h264") + ); + +GST_BOILERPLATE (GstVdpauH264Decoder, gst_vdpau_h264decoder, GstVdpauDecoder, + GST_TYPE_VDPAU_DECODER); + +static void gst_vdpau_h264decoder_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_vdpau_h264decoder_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +/* GObject vmethod implementations */ + +static void +gst_vdpau_h264decoder_base_init (gpointer gclass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (gclass); + + gst_element_class_set_details_simple (element_class, + "VdpauH264Decoder", + "FIXME:Generic", + "FIXME:Generic Template Element", + "Carl-Anton Ingmarsson "); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&sink_factory)); +} + +/* initialize the vdpauh264decoder's class */ +static void +gst_vdpau_h264decoder_class_init (GstVdpauH264DecoderClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + + gobject_class = (GObjectClass *) klass; + gstelement_class = (GstElementClass *) klass; + + gobject_class->set_property = gst_vdpau_h264decoder_set_property; + gobject_class->get_property = gst_vdpau_h264decoder_get_property; + + g_object_class_install_property (gobject_class, PROP_SILENT, + g_param_spec_boolean ("silent", "Silent", "Produce verbose output ?", + FALSE, G_PARAM_READWRITE)); +} + +static void +gst_vdpau_h264decoder_init (GstVdpauH264Decoder * filter, + GstVdpauH264DecoderClass * gclass) +{ + filter->silent = FALSE; +} + +static void +gst_vdpau_h264decoder_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstVdpauH264Decoder *filter = GST_VDPAU_H264_DECODER (object); + + switch (prop_id) { + case PROP_SILENT: + filter->silent = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_vdpau_h264decoder_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstVdpauH264Decoder *filter = GST_VDPAU_H264_DECODER (object); + + switch (prop_id) { + case PROP_SILENT: + g_value_set_boolean (value, filter->silent); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/* entry point to initialize the plug-in + * initialize the plug-in itself + * register the element factories and other features + */ +static gboolean +vdpauh264decoder_init (GstPlugin * vdpauh264decoder) +{ + /* debug category for fltering log messages + * + * exchange the string 'Template vdpauh264decoder' with your description + */ + GST_DEBUG_CATEGORY_INIT (gst_vdpau_h264decoder_debug, "vdpauh264decoder", + 0, "Template vdpauh264decoder"); + + return gst_element_register (vdpauh264decoder, "vdpauh264decoder", + GST_RANK_NONE, GST_TYPE_VDPAU_H264_DECODER); +} + +/* gstreamer looks for this structure to register vdpauh264decoders + * + * exchange the string 'Template vdpauh264decoder' with your vdpauh264decoder description + */ +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "vdpauh264decoder", + "Template vdpauh264decoder", + vdpauh264decoder_init, + VERSION, "LGPL", "GStreamer", "http://gstreamer.net/") diff --git a/sys/vdpau/gstvdpauh264decoder.h b/sys/vdpau/gstvdpauh264decoder.h new file mode 100644 index 00000000..c3972047 --- /dev/null +++ b/sys/vdpau/gstvdpauh264decoder.h @@ -0,0 +1,88 @@ +/* + * GStreamer + * Copyright (C) 2005 Thomas Vander Stichele + * Copyright (C) 2005 Ronald S. Bultje + * Copyright (C) 2009 Carl-Anton Ingmarsson + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Alternatively, the contents of this file may be used under the + * GNU Lesser General Public License Version 2.1 (the "LGPL"), in + * which case the following provisions apply instead of the ones + * mentioned above: + * + * 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_VDPAU_H264_DECODER_H__ +#define __GST_VDPAU_H264_DECODER_H__ + +#include + +#include "gstvdpaudecoder.h" + +G_BEGIN_DECLS + +/* #defines don't like whitespacey bits */ +#define GST_TYPE_VDPAU_H264_DECODER \ + (gst_vdpau_h264decoder_get_type()) +#define GST_VDPAU_H264_DECODER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VDPAU_H264_DECODER,GstVdpauH264Decoder)) +#define GST_VDPAU_H264_DECODER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VDPAU_H264_DECODER,GstVdpauH264DecoderClass)) +#define GST_IS_VDPAU_H264_DECODER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VDPAU_H264_DECODER)) +#define GST_IS_VDPAU_H264_DECODER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VDPAU_H264_DECODER)) + +typedef struct _GstVdpauH264Decoder GstVdpauH264Decoder; +typedef struct _GstVdpauH264DecoderClass GstVdpauH264DecoderClass; + +struct _GstVdpauH264Decoder +{ + GstVdpauDecoder dec; + + GstPad *sinkpad, *srcpad; + + gboolean silent; +}; + +struct _GstVdpauH264DecoderClass +{ + GstVdpauDecoderClass parent_class; +}; + +GType gst_vdpau_h264decoder_get_type (void); + +G_END_DECLS + +#endif /* __GST_VDPAU_H264_DECODER_H__ */ diff --git a/sys/vdpau/vdpauvariables.h b/sys/vdpau/vdpauvariables.h new file mode 100644 index 00000000..ab274aa8 --- /dev/null +++ b/sys/vdpau/vdpauvariables.h @@ -0,0 +1,45 @@ +#include + +static VdpVideoSurfaceQueryCapabilities *vdp_video_surface_query_capabilities; +static VdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities *vdp_video_surface_query_ycbcr_capabilities; + +static VdpGetProcAddress *vdp_get_proc_address; +#if 0 + +static VdpDeviceDestroy *vdp_device_destroy; +static VdpVideoSurfaceCreate *vdp_video_surface_create; +static VdpVideoSurfaceDestroy *vdp_video_surface_destroy; + +static VdpGetErrorString *vdp_get_error_string; + +static VdpVideoSurfacePutBitsYCbCr *vdp_video_surface_put_bits_y_cb_cr; +static VdpOutputSurfacePutBitsNative *vdp_output_surface_put_bits_native; + +static VdpOutputSurfaceCreate *vdp_output_surface_create; +static VdpOutputSurfaceDestroy *vdp_output_surface_destroy; + +static VdpVideoMixerCreate *vdp_video_mixer_create; +static VdpVideoMixerDestroy *vdp_video_mixer_destroy; +static VdpVideoMixerRender *vdp_video_mixer_render; +static VdpVideoMixerSetFeatureEnables *vdp_video_mixer_set_feature_enables; +static VdpVideoMixerSetAttributeValues *vdp_video_mixer_set_attribute_values; + +static VdpPresentationQueueTargetDestroy *vdp_presentation_queue_target_destroy; +static VdpPresentationQueueCreate *vdp_presentation_queue_create; +static VdpPresentationQueueDestroy *vdp_presentation_queue_destroy; +static VdpPresentationQueueDisplay *vdp_presentation_queue_display; +static VdpPresentationQueueBlockUntilSurfaceIdle *vdp_presentation_queue_block_until_surface_idle; +static VdpPresentationQueueTargetCreateX11 *vdp_presentation_queue_target_create_x11; + +static VdpOutputSurfaceRenderOutputSurface *vdp_output_surface_render_output_surface; +static VdpOutputSurfacePutBitsIndexed *vdp_output_surface_put_bits_indexed; +static VdpOutputSurfaceRenderBitmapSurface *vdp_output_surface_render_bitmap_surface; + +static VdpBitmapSurfaceCreate *vdp_bitmap_surface_create; +static VdpBitmapSurfaceDestroy *vdp_bitmap_surface_destroy; +static VdpBitmapSurfacePutBitsNative *vdp_bitmap_surface_putbits_native; + +static VdpDecoderCreate *vdp_decoder_create; +static VdpDecoderDestroy *vdp_decoder_destroy; +static VdpDecoderRender *vdp_decoder_render; +#endif \ No newline at end of file -- cgit v1.2.1 From c0e4cdeb615238fef871cc5a1dfceed0109e3178 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Fri, 20 Mar 2009 21:26:11 +0100 Subject: vdpau: changle gstvdpaudecoder.c classification --- sys/vdpau/gstvdpaudecoder.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/vdpau/gstvdpaudecoder.c b/sys/vdpau/gstvdpaudecoder.c index 230fa80c..0ef69654 100644 --- a/sys/vdpau/gstvdpaudecoder.c +++ b/sys/vdpau/gstvdpaudecoder.c @@ -288,7 +288,7 @@ gst_vdpaudecoder_base_init (gpointer klass) gst_element_class_set_details_simple (element_class, "VdpauDecoder", - "Generic/Filter", + "Codec/Decoder/Video", "VDPAU decoder base class", "Carl-Anton Ingmarsson "); -- cgit v1.2.1 From 46a7e8221ceab7e1a5073aeaf36994af9c29ffa3 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Sat, 21 Mar 2009 22:06:12 +0100 Subject: vdpau: update VdpauH264Decoder element description --- sys/vdpau/gstvdpauh264decoder.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/vdpau/gstvdpauh264decoder.c b/sys/vdpau/gstvdpauh264decoder.c index 794f71d1..ce6eec11 100644 --- a/sys/vdpau/gstvdpauh264decoder.c +++ b/sys/vdpau/gstvdpauh264decoder.c @@ -107,8 +107,8 @@ gst_vdpau_h264decoder_base_init (gpointer gclass) gst_element_class_set_details_simple (element_class, "VdpauH264Decoder", - "FIXME:Generic", - "FIXME:Generic Template Element", + "Decoder", + "decode h264 stream with vdpau", "Carl-Anton Ingmarsson "); gst_element_class_add_pad_template (element_class, -- cgit v1.2.1 From 24dfc72e89e73a7b6fa6015a1b9f61038a223c02 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Mon, 23 Mar 2009 20:47:00 +0100 Subject: vdpau: add stubs for pushing VdpVideoSurfaces to the src pad --- sys/vdpau/gstvdpaudecoder.c | 21 +++++++++++++++++---- sys/vdpau/gstvdpaudecoder.h | 2 ++ 2 files changed, 19 insertions(+), 4 deletions(-) diff --git a/sys/vdpau/gstvdpaudecoder.c b/sys/vdpau/gstvdpaudecoder.c index 0ef69654..bea707f5 100644 --- a/sys/vdpau/gstvdpaudecoder.c +++ b/sys/vdpau/gstvdpaudecoder.c @@ -71,6 +71,19 @@ static void gst_vdpaudecoder_set_property (GObject * object, guint prop_id, static void gst_vdpaudecoder_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); +static gboolean +gst_vdpaudecoder_push_video_surface (GstVdpauDecoder * dec, + VdpVideoSurface * surface) +{ + switch (dec->format) { + case GST_MAKE_FOURCC ('Y', 'V', '1', '2'): + /* YV12 specific code */ + break; + default: + break; + } +} + typedef struct { VdpChromaType chroma_type; @@ -163,8 +176,6 @@ gst_vdpaudecoder_get_vdpau_support (GstVdpauDecoder * dec) "height", GST_TYPE_INT_RANGE, 1, max_h, "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL); gst_caps_append (caps, format_caps); - GST_DEBUG ("fourcc: %" GST_FOURCC_FORMAT "\n", - GST_FOURCC_ARGS (formats[j].fourcc)); } } } @@ -231,6 +242,7 @@ gst_vdpaudecoder_sink_set_caps (GstPad * pad, GstCaps * caps) GstStructure *structure; gint width, height; gint framerate_numerator, framerate_denominator; + guint32 fourcc_format; gboolean res; structure = gst_caps_get_structure (caps, 0); @@ -240,9 +252,9 @@ gst_vdpaudecoder_sink_set_caps (GstPad * pad, GstCaps * caps) &framerate_numerator, &framerate_denominator); src_caps = gst_pad_get_allowed_caps (dec->src); - GST_DEBUG ("caps: %s\n\n", gst_caps_to_string (src_caps)); structure = gst_caps_get_structure (src_caps, 0); + gst_structure_get_fourcc (structure, "format", &fourcc_format); gst_structure_set (structure, "width", G_TYPE_INT, width, "height", G_TYPE_INT, height, @@ -255,11 +267,12 @@ gst_vdpaudecoder_sink_set_caps (GstPad * pad, GstCaps * caps) res = gst_pad_set_caps (dec->src, new_caps); gst_caps_unref (new_caps); - GST_DEBUG ("caps: %s\n\n", gst_caps_to_string (gst_pad_get_caps (dec->src))); if (!res) return FALSE; + dec->format = fourcc_format; + return TRUE; } diff --git a/sys/vdpau/gstvdpaudecoder.h b/sys/vdpau/gstvdpaudecoder.h index f713b0dd..7d59f2e2 100644 --- a/sys/vdpau/gstvdpaudecoder.h +++ b/sys/vdpau/gstvdpaudecoder.h @@ -54,6 +54,8 @@ struct _GstVdpauDecoder { GstCaps *src_caps; + guint32 format; + gboolean silent; }; -- cgit v1.2.1 From 3a48982235b6e97af21986e427dcaffa636acfb8 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Mon, 23 Mar 2009 21:36:55 +0100 Subject: vdpau: init vdpau in GST_STATE_CHANGE_NULL_TO_READY add gst_vdpaudecoder_push_video_surface to vdpaudecoder.h --- sys/vdpau/gstvdpaudecoder.c | 36 +++++++++++++++++++++++++++++++----- sys/vdpau/gstvdpaudecoder.h | 2 ++ sys/vdpau/vdpauvariables.h | 4 ++-- 3 files changed, 35 insertions(+), 7 deletions(-) diff --git a/sys/vdpau/gstvdpaudecoder.c b/sys/vdpau/gstvdpaudecoder.c index bea707f5..932490b9 100644 --- a/sys/vdpau/gstvdpaudecoder.c +++ b/sys/vdpau/gstvdpaudecoder.c @@ -71,7 +71,7 @@ static void gst_vdpaudecoder_set_property (GObject * object, guint prop_id, static void gst_vdpaudecoder_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); -static gboolean +gboolean gst_vdpaudecoder_push_video_surface (GstVdpauDecoder * dec, VdpVideoSurface * surface) { @@ -82,6 +82,8 @@ gst_vdpaudecoder_push_video_surface (GstVdpauDecoder * dec, default: break; } + + return TRUE; } typedef struct @@ -201,7 +203,7 @@ gst_vdpaudecoder_init_vdpau (GstVdpauDecoder * dec) if (!display) { GST_ELEMENT_ERROR (dec, RESOURCE, READ, ("Could not initialise VDPAU"), ("Could not open display")); - return GST_STATE_CHANGE_FAILURE; + return FALSE; } screen = DefaultScreen (display); @@ -223,16 +225,40 @@ gst_vdpaudecoder_init_vdpau (GstVdpauDecoder * dec) vdp_get_proc_address (dec->device, VDP_FUNC_ID_VIDEO_SURFACE_QUERY_GET_PUT_BITS_Y_CB_CR_CAPABILITIES, (void **) &vdp_video_surface_query_ycbcr_capabilities); + vdp_get_proc_address (dec->device, + VDP_FUNC_ID_DEVICE_DESTROY, (void **) &vdp_device_destroy); caps = gst_vdpaudecoder_get_vdpau_support (dec); - if (!caps) + if (!caps) { + vdp_device_destroy (dec->device); + dec->device = 0; return FALSE; + } dec->src_caps = caps; return TRUE; } +static GstStateChangeReturn +gst_vdpaudecoder_change_state (GstElement * element, GstStateChange transition) +{ + GstVdpauDecoder *dec; + + dec = GST_VDPAU_DECODER (element); + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + if (!gst_vdpaudecoder_init_vdpau (dec)) + return GST_STATE_CHANGE_FAILURE; + break; + default: + break; + } + + return GST_STATE_CHANGE_SUCCESS; +} + static gboolean gst_vdpaudecoder_sink_set_caps (GstPad * pad, GstCaps * caps) { @@ -329,6 +355,8 @@ gst_vdpaudecoder_class_init (GstVdpauDecoderClass * klass) g_object_class_install_property (gobject_class, PROP_SILENT, g_param_spec_boolean ("silent", "Silent", "Produce verbose output ?", FALSE, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE)); + + gstelement_class->change_state = gst_vdpaudecoder_change_state; } static void @@ -347,8 +375,6 @@ gst_vdpaudecoder_init (GstVdpauDecoder * dec, GstVdpauDecoderClass * klass) (GST_ELEMENT_CLASS (klass), "sink"), "sink"); gst_pad_set_setcaps_function (dec->sink, gst_vdpaudecoder_sink_set_caps); gst_element_add_pad (GST_ELEMENT (dec), dec->sink); - - gst_vdpaudecoder_init_vdpau (dec); } static void diff --git a/sys/vdpau/gstvdpaudecoder.h b/sys/vdpau/gstvdpaudecoder.h index 7d59f2e2..2c8b11f7 100644 --- a/sys/vdpau/gstvdpaudecoder.h +++ b/sys/vdpau/gstvdpaudecoder.h @@ -65,6 +65,8 @@ struct _GstVdpauDecoderClass { GType gst_vdpaudecoder_get_type (void); +gboolean gst_vdpaudecoder_push_video_surface (GstVdpauDecoder * dec, VdpVideoSurface * surface); + G_END_DECLS #endif /* __GST_VDPAU_DECODER_H__ */ diff --git a/sys/vdpau/vdpauvariables.h b/sys/vdpau/vdpauvariables.h index ab274aa8..b93a75be 100644 --- a/sys/vdpau/vdpauvariables.h +++ b/sys/vdpau/vdpauvariables.h @@ -4,9 +4,9 @@ static VdpVideoSurfaceQueryCapabilities *vdp_video_surface_query_capabilities; static VdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities *vdp_video_surface_query_ycbcr_capabilities; static VdpGetProcAddress *vdp_get_proc_address; -#if 0 - static VdpDeviceDestroy *vdp_device_destroy; + +#if 0 static VdpVideoSurfaceCreate *vdp_video_surface_create; static VdpVideoSurfaceDestroy *vdp_video_surface_destroy; -- cgit v1.2.1 From 2363032b34652ae2db9389620057e24dba1c0750 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Tue, 24 Mar 2009 22:26:56 +0100 Subject: vdpau: remove obsolete comment --- sys/vdpau/gstvdpaudecoder.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/sys/vdpau/gstvdpaudecoder.c b/sys/vdpau/gstvdpaudecoder.c index 932490b9..a647a5f9 100644 --- a/sys/vdpau/gstvdpaudecoder.c +++ b/sys/vdpau/gstvdpaudecoder.c @@ -56,10 +56,6 @@ static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src", "framerate = (fraction) [ 0, MAX ], " "width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]")); -/* debug category for fltering log messages - * - * FIXME:exchange the string 'Template vdpaudecoder' with your description - */ #define DEBUG_INIT(bla) \ GST_DEBUG_CATEGORY_INIT (gst_vdpaudecoder_debug, "vdpaudecoder", 0, "vdpaudecoder base class"); -- cgit v1.2.1 From 62757ca5b494969291b78f2b733891902b70b257 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Wed, 25 Mar 2009 19:59:06 +0100 Subject: vdpau: rough try at implementing pushinf of YV12 buffers --- sys/vdpau/gstvdpaudecoder.c | 37 +++++++++++++++++++++++++++++++++++-- sys/vdpau/gstvdpaudecoder.h | 3 ++- sys/vdpau/vdpauvariables.h | 1 + 3 files changed, 38 insertions(+), 3 deletions(-) diff --git a/sys/vdpau/gstvdpaudecoder.c b/sys/vdpau/gstvdpaudecoder.c index a647a5f9..36d6eca0 100644 --- a/sys/vdpau/gstvdpaudecoder.c +++ b/sys/vdpau/gstvdpaudecoder.c @@ -69,12 +69,36 @@ static void gst_vdpaudecoder_get_property (GObject * object, guint prop_id, gboolean gst_vdpaudecoder_push_video_surface (GstVdpauDecoder * dec, - VdpVideoSurface * surface) + VdpVideoSurface surface) { switch (dec->format) { case GST_MAKE_FOURCC ('Y', 'V', '1', '2'): - /* YV12 specific code */ + { + gint size; + GstFlowReturn result; + GstBuffer *buffer; + VdpStatus status; + guint8 *data[3]; + + size = dec->height * dec->width + dec->height * dec->width / 2; + result = + gst_pad_alloc_buffer_and_set_caps (dec->src, GST_BUFFER_OFFSET_NONE, + size, GST_PAD_CAPS (dec->src), &buffer); + if (G_UNLIKELY (result != GST_FLOW_OK)) + return FALSE; + + data[0] = GST_BUFFER_DATA (buffer); + data[1] = data[0] + dec->height * dec->width; + data[2] = data[1] + dec->height * dec->width / 4; + + status = + vdp_video_surface_get_bits_ycbcr (surface, VDP_YCBCR_FORMAT_YV12, + (void *) data, NULL); + if (G_UNLIKELY (status != VDP_STATUS_OK)) + return FALSE; + break; + } default: break; } @@ -223,6 +247,9 @@ gst_vdpaudecoder_init_vdpau (GstVdpauDecoder * dec) (void **) &vdp_video_surface_query_ycbcr_capabilities); vdp_get_proc_address (dec->device, VDP_FUNC_ID_DEVICE_DESTROY, (void **) &vdp_device_destroy); + vdp_get_proc_address (dec->device, + VDP_FUNC_ID_VIDEO_SURFACE_GET_BITS_Y_CB_CR, + (void **) &vdp_video_surface_get_bits_ycbcr); caps = gst_vdpaudecoder_get_vdpau_support (dec); if (!caps) { @@ -293,6 +320,8 @@ gst_vdpaudecoder_sink_set_caps (GstPad * pad, GstCaps * caps) if (!res) return FALSE; + dec->width = width; + dec->height = height; dec->format = fourcc_format; return TRUE; @@ -363,6 +392,10 @@ gst_vdpaudecoder_init (GstVdpauDecoder * dec, GstVdpauDecoderClass * klass) dec->silent = FALSE; dec->src_caps = NULL; + dec->height = 0; + dec->width = 0; + dec->format = 0; + dec->src = gst_pad_new_from_static_template (&src_template, "src"); gst_pad_set_getcaps_function (dec->src, gst_vdpaudecoder_src_getcaps); gst_element_add_pad (GST_ELEMENT (dec), dec->src); diff --git a/sys/vdpau/gstvdpaudecoder.h b/sys/vdpau/gstvdpaudecoder.h index 2c8b11f7..336e4b8a 100644 --- a/sys/vdpau/gstvdpaudecoder.h +++ b/sys/vdpau/gstvdpaudecoder.h @@ -54,6 +54,7 @@ struct _GstVdpauDecoder { GstCaps *src_caps; + gint width, height; guint32 format; gboolean silent; @@ -65,7 +66,7 @@ struct _GstVdpauDecoderClass { GType gst_vdpaudecoder_get_type (void); -gboolean gst_vdpaudecoder_push_video_surface (GstVdpauDecoder * dec, VdpVideoSurface * surface); +gboolean gst_vdpaudecoder_push_video_surface (GstVdpauDecoder * dec, VdpVideoSurface surface); G_END_DECLS diff --git a/sys/vdpau/vdpauvariables.h b/sys/vdpau/vdpauvariables.h index b93a75be..c0f7bb4f 100644 --- a/sys/vdpau/vdpauvariables.h +++ b/sys/vdpau/vdpauvariables.h @@ -2,6 +2,7 @@ static VdpVideoSurfaceQueryCapabilities *vdp_video_surface_query_capabilities; static VdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities *vdp_video_surface_query_ycbcr_capabilities; +static VdpVideoSurfaceGetBitsYCbCr *vdp_video_surface_get_bits_ycbcr; static VdpGetProcAddress *vdp_get_proc_address; static VdpDeviceDestroy *vdp_device_destroy; -- cgit v1.2.1 From f6ed342f197ba0d977a1203fb10db0726e7e1858 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Wed, 25 Mar 2009 20:38:27 +0100 Subject: vdpau: focus on mpeg instead of h264 --- sys/vdpau/Makefile.am | 4 +- sys/vdpau/gstvdpaumpegdecoder.c | 202 ++++++++++++++++++++++++++++++++++++++++ sys/vdpau/gstvdpaumpegdecoder.h | 88 +++++++++++++++++ 3 files changed, 292 insertions(+), 2 deletions(-) create mode 100644 sys/vdpau/gstvdpaumpegdecoder.c create mode 100644 sys/vdpau/gstvdpaumpegdecoder.h diff --git a/sys/vdpau/Makefile.am b/sys/vdpau/Makefile.am index 3e718abe..94f7efbc 100644 --- a/sys/vdpau/Makefile.am +++ b/sys/vdpau/Makefile.am @@ -2,7 +2,7 @@ plugin_LTLIBRARIES = libgstvdpau.la libgstvdpau_la_SOURCES = \ gstvdpaudecoder.c\ - gstvdpauh264decoder.c + gstvdpaumpegdecoder.c libgstvdpau_la_CFLAGS = $(GST_CFLAGS) $(X11_CFLAGS) -Ivdpau libgstvdpau_la_LIBADD = $(GST_LIBS) $(X11_LIBS) -lvdpau @@ -12,6 +12,6 @@ libgstvdpau_la_LIBTOOLFLAGS = --tag=disable-static noinst_HEADERS = \ gstvdpaudecoder.h\ vdpauvariables.h \ - gstvdpauh264decoder.h + gstvdpaumpegdecoder.h diff --git a/sys/vdpau/gstvdpaumpegdecoder.c b/sys/vdpau/gstvdpaumpegdecoder.c new file mode 100644 index 00000000..24760474 --- /dev/null +++ b/sys/vdpau/gstvdpaumpegdecoder.c @@ -0,0 +1,202 @@ +/* + * GStreamer + * Copyright (C) 2005 Thomas Vander Stichele + * Copyright (C) 2005 Ronald S. Bultje + * Copyright (C) 2009 Carl-Anton Ingmarsson + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Alternatively, the contents of this file may be used under the + * GNU Lesser General Public License Version 2.1 (the "LGPL"), in + * which case the following provisions apply instead of the ones + * mentioned above: + * + * 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-vdpaumpegdecoder + * + * FIXME:Describe vdpaumpegdecoder here. + * + * + * Example launch line + * |[ + * gst-launch -v -m fakesrc ! vdpaumpegdecoder ! fakesink silent=TRUE + * ]| + * + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include + +#include "gstvdpaumpegdecoder.h" + +GST_DEBUG_CATEGORY_STATIC (gst_vdpau_mpeg_decoder_debug); +#define GST_CAT_DEFAULT gst_vdpau_mpeg_decoder_debug + +/* Filter signals and args */ +enum +{ + /* FILL ME */ + LAST_SIGNAL +}; + +enum +{ + PROP_0, + PROP_SILENT +}; + +/* the capabilities of the inputs and outputs. + * + * describe the real formats here. + */ +static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("video/x-mpeg") + ); + +GST_BOILERPLATE (GstVdpauMpegDecoder, gst_vdpau_mpeg_decoder, GstVdpauDecoder, + GST_TYPE_VDPAU_DECODER); + +static void gst_vdpau_mpeg_decoder_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec); +static void gst_vdpau_mpeg_decoder_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec); + +/* GObject vmethod implementations */ + +static void +gst_vdpau_mpeg_decoder_base_init (gpointer gclass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (gclass); + + gst_element_class_set_details_simple (element_class, + "VdpauMpegDecoder", + "Decoder", + "decode mpeg stream with vdpau", + "Carl-Anton Ingmarsson "); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&sink_factory)); +} + +/* initialize the vdpaumpegdecoder's class */ +static void +gst_vdpau_mpeg_decoder_class_init (GstVdpauMpegDecoderClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + + gobject_class = (GObjectClass *) klass; + gstelement_class = (GstElementClass *) klass; + + gobject_class->set_property = gst_vdpau_mpeg_decoder_set_property; + gobject_class->get_property = gst_vdpau_mpeg_decoder_get_property; + + g_object_class_install_property (gobject_class, PROP_SILENT, + g_param_spec_boolean ("silent", "Silent", "Produce verbose output ?", + FALSE, G_PARAM_READWRITE)); +} + +static void +gst_vdpau_mpeg_decoder_init (GstVdpauMpegDecoder * filter, + GstVdpauMpegDecoderClass * gclass) +{ + filter->silent = FALSE; +} + +static void +gst_vdpau_mpeg_decoder_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstVdpauMpegDecoder *filter = GST_VDPAU_MPEG_DECODER (object); + + switch (prop_id) { + case PROP_SILENT: + filter->silent = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_vdpau_mpeg_decoder_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstVdpauMpegDecoder *filter = GST_VDPAU_MPEG_DECODER (object); + + switch (prop_id) { + case PROP_SILENT: + g_value_set_boolean (value, filter->silent); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +/* entry point to initialize the plug-in + * initialize the plug-in itself + * register the element factories and other features + */ +static gboolean +vdpaumpegdecoder_init (GstPlugin * vdpaumpegdecoder) +{ + /* debug category for fltering log messages + * + * exchange the string 'Template vdpaumpegdecoder' with your description + */ + GST_DEBUG_CATEGORY_INIT (gst_vdpau_mpeg_decoder_debug, "vdpaumpegdecoder", + 0, "Template vdpaumpegdecoder"); + + return gst_element_register (vdpaumpegdecoder, "vdpaumpegdecoder", + GST_RANK_NONE, GST_TYPE_VDPAU_MPEG_DECODER); +} + +/* gstreamer looks for this structure to register vdpaumpegdecoders + * + * exchange the string 'Template vdpaumpegdecoder' with your vdpaumpegdecoder description + */ +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "vdpaumpegdecoder", + "Template vdpaumpegdecoder", + vdpaumpegdecoder_init, + VERSION, "LGPL", "GStreamer", "http://gstreamer.net/") diff --git a/sys/vdpau/gstvdpaumpegdecoder.h b/sys/vdpau/gstvdpaumpegdecoder.h new file mode 100644 index 00000000..14c9a3f7 --- /dev/null +++ b/sys/vdpau/gstvdpaumpegdecoder.h @@ -0,0 +1,88 @@ +/* + * GStreamer + * Copyright (C) 2005 Thomas Vander Stichele + * Copyright (C) 2005 Ronald S. Bultje + * Copyright (C) 2009 Carl-Anton Ingmarsson + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + * + * Alternatively, the contents of this file may be used under the + * GNU Lesser General Public License Version 2.1 (the "LGPL"), in + * which case the following provisions apply instead of the ones + * mentioned above: + * + * 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_VDPAU_MPEG_DECODER_H__ +#define __GST_VDPAU_MPEG_DECODER_H__ + +#include + +#include "gstvdpaudecoder.h" + +G_BEGIN_DECLS + +/* #defines don't like whitespacey bits */ +#define GST_TYPE_VDPAU_MPEG_DECODER \ + (gst_vdpau_mpeg_decoder_get_type()) +#define GST_VDPAU_MPEG_DECODER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VDPAU_MPEG_DECODER,GstVdpauMpegDecoder)) +#define GST_VDPAU_MPEG_DECODER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VDPAU_MPEG_DECODER,GstVdpauMpegDecoderClass)) +#define GST_IS_VDPAU_MPEG_DECODER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VDPAU_MPEG_DECODER)) +#define GST_IS_VDPAU_MPEG_DECODER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VDPAU_MPEG_DECODER)) + +typedef struct _GstVdpauMpegDecoder GstVdpauMpegDecoder; +typedef struct _GstVdpauMpegDecoderClass GstVdpauMpegDecoderClass; + +struct _GstVdpauMpegDecoder +{ + GstVdpauDecoder dec; + + GstPad *sinkpad, *srcpad; + + gboolean silent; +}; + +struct _GstVdpauMpegDecoderClass +{ + GstVdpauDecoderClass parent_class; +}; + +GType gst_vdpau_mpeg_decoder_get_type (void); + +G_END_DECLS + +#endif /* __GST_VDPAU_MPEG_DECODER_H__ */ -- cgit v1.2.1 From 367708e2ae7435fab215fd93b31234e553220c77 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Wed, 25 Mar 2009 20:41:46 +0100 Subject: vdpau: add version specification to mpegdecoder caps --- sys/vdpau/gstvdpauh264decoder.c | 202 ---------------------------------------- sys/vdpau/gstvdpauh264decoder.h | 88 ----------------- sys/vdpau/gstvdpaumpegdecoder.c | 2 +- 3 files changed, 1 insertion(+), 291 deletions(-) delete mode 100644 sys/vdpau/gstvdpauh264decoder.c delete mode 100644 sys/vdpau/gstvdpauh264decoder.h diff --git a/sys/vdpau/gstvdpauh264decoder.c b/sys/vdpau/gstvdpauh264decoder.c deleted file mode 100644 index ce6eec11..00000000 --- a/sys/vdpau/gstvdpauh264decoder.c +++ /dev/null @@ -1,202 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2005 Thomas Vander Stichele - * Copyright (C) 2005 Ronald S. Bultje - * Copyright (C) 2009 Carl-Anton Ingmarsson - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Alternatively, the contents of this file may be used under the - * GNU Lesser General Public License Version 2.1 (the "LGPL"), in - * which case the following provisions apply instead of the ones - * mentioned above: - * - * 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-vdpauh264decoder - * - * FIXME:Describe vdpauh264decoder here. - * - * - * Example launch line - * |[ - * gst-launch -v -m fakesrc ! vdpauh264decoder ! fakesink silent=TRUE - * ]| - * - */ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include - -#include "gstvdpauh264decoder.h" - -GST_DEBUG_CATEGORY_STATIC (gst_vdpau_h264decoder_debug); -#define GST_CAT_DEFAULT gst_vdpau_h264decoder_debug - -/* Filter signals and args */ -enum -{ - /* FILL ME */ - LAST_SIGNAL -}; - -enum -{ - PROP_0, - PROP_SILENT -}; - -/* the capabilities of the inputs and outputs. - * - * describe the real formats here. - */ -static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS ("video/x-h264") - ); - -GST_BOILERPLATE (GstVdpauH264Decoder, gst_vdpau_h264decoder, GstVdpauDecoder, - GST_TYPE_VDPAU_DECODER); - -static void gst_vdpau_h264decoder_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec); -static void gst_vdpau_h264decoder_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec); - -/* GObject vmethod implementations */ - -static void -gst_vdpau_h264decoder_base_init (gpointer gclass) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (gclass); - - gst_element_class_set_details_simple (element_class, - "VdpauH264Decoder", - "Decoder", - "decode h264 stream with vdpau", - "Carl-Anton Ingmarsson "); - - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&sink_factory)); -} - -/* initialize the vdpauh264decoder's class */ -static void -gst_vdpau_h264decoder_class_init (GstVdpauH264DecoderClass * klass) -{ - GObjectClass *gobject_class; - GstElementClass *gstelement_class; - - gobject_class = (GObjectClass *) klass; - gstelement_class = (GstElementClass *) klass; - - gobject_class->set_property = gst_vdpau_h264decoder_set_property; - gobject_class->get_property = gst_vdpau_h264decoder_get_property; - - g_object_class_install_property (gobject_class, PROP_SILENT, - g_param_spec_boolean ("silent", "Silent", "Produce verbose output ?", - FALSE, G_PARAM_READWRITE)); -} - -static void -gst_vdpau_h264decoder_init (GstVdpauH264Decoder * filter, - GstVdpauH264DecoderClass * gclass) -{ - filter->silent = FALSE; -} - -static void -gst_vdpau_h264decoder_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstVdpauH264Decoder *filter = GST_VDPAU_H264_DECODER (object); - - switch (prop_id) { - case PROP_SILENT: - filter->silent = g_value_get_boolean (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_vdpau_h264decoder_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - GstVdpauH264Decoder *filter = GST_VDPAU_H264_DECODER (object); - - switch (prop_id) { - case PROP_SILENT: - g_value_set_boolean (value, filter->silent); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -/* entry point to initialize the plug-in - * initialize the plug-in itself - * register the element factories and other features - */ -static gboolean -vdpauh264decoder_init (GstPlugin * vdpauh264decoder) -{ - /* debug category for fltering log messages - * - * exchange the string 'Template vdpauh264decoder' with your description - */ - GST_DEBUG_CATEGORY_INIT (gst_vdpau_h264decoder_debug, "vdpauh264decoder", - 0, "Template vdpauh264decoder"); - - return gst_element_register (vdpauh264decoder, "vdpauh264decoder", - GST_RANK_NONE, GST_TYPE_VDPAU_H264_DECODER); -} - -/* gstreamer looks for this structure to register vdpauh264decoders - * - * exchange the string 'Template vdpauh264decoder' with your vdpauh264decoder description - */ -GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, - GST_VERSION_MINOR, - "vdpauh264decoder", - "Template vdpauh264decoder", - vdpauh264decoder_init, - VERSION, "LGPL", "GStreamer", "http://gstreamer.net/") diff --git a/sys/vdpau/gstvdpauh264decoder.h b/sys/vdpau/gstvdpauh264decoder.h deleted file mode 100644 index c3972047..00000000 --- a/sys/vdpau/gstvdpauh264decoder.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2005 Thomas Vander Stichele - * Copyright (C) 2005 Ronald S. Bultje - * Copyright (C) 2009 Carl-Anton Ingmarsson - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Alternatively, the contents of this file may be used under the - * GNU Lesser General Public License Version 2.1 (the "LGPL"), in - * which case the following provisions apply instead of the ones - * mentioned above: - * - * 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_VDPAU_H264_DECODER_H__ -#define __GST_VDPAU_H264_DECODER_H__ - -#include - -#include "gstvdpaudecoder.h" - -G_BEGIN_DECLS - -/* #defines don't like whitespacey bits */ -#define GST_TYPE_VDPAU_H264_DECODER \ - (gst_vdpau_h264decoder_get_type()) -#define GST_VDPAU_H264_DECODER(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VDPAU_H264_DECODER,GstVdpauH264Decoder)) -#define GST_VDPAU_H264_DECODER_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VDPAU_H264_DECODER,GstVdpauH264DecoderClass)) -#define GST_IS_VDPAU_H264_DECODER(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VDPAU_H264_DECODER)) -#define GST_IS_VDPAU_H264_DECODER_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VDPAU_H264_DECODER)) - -typedef struct _GstVdpauH264Decoder GstVdpauH264Decoder; -typedef struct _GstVdpauH264DecoderClass GstVdpauH264DecoderClass; - -struct _GstVdpauH264Decoder -{ - GstVdpauDecoder dec; - - GstPad *sinkpad, *srcpad; - - gboolean silent; -}; - -struct _GstVdpauH264DecoderClass -{ - GstVdpauDecoderClass parent_class; -}; - -GType gst_vdpau_h264decoder_get_type (void); - -G_END_DECLS - -#endif /* __GST_VDPAU_H264_DECODER_H__ */ diff --git a/sys/vdpau/gstvdpaumpegdecoder.c b/sys/vdpau/gstvdpaumpegdecoder.c index 24760474..c22c27f3 100644 --- a/sys/vdpau/gstvdpaumpegdecoder.c +++ b/sys/vdpau/gstvdpaumpegdecoder.c @@ -87,7 +87,7 @@ enum static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, - GST_STATIC_CAPS ("video/x-mpeg") + GST_STATIC_CAPS ("video/x-mpeg, mpegversion = (int) [ 1, 2 ]") ); GST_BOILERPLATE (GstVdpauMpegDecoder, gst_vdpau_mpeg_decoder, GstVdpauDecoder, -- cgit v1.2.1 From 090638ccec59cebb11327d12ebcff78015716bed Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Thu, 26 Mar 2009 21:04:48 +0100 Subject: vdpau: extract mpeg version --- sys/vdpau/gstvdpaudecoder.c | 5 +++++ sys/vdpau/gstvdpaudecoder.h | 18 ++++++++---------- sys/vdpau/gstvdpaumpegdecoder.c | 21 ++++++++++++++++++++- sys/vdpau/gstvdpaumpegdecoder.h | 19 +++++++------------ 4 files changed, 40 insertions(+), 23 deletions(-) diff --git a/sys/vdpau/gstvdpaudecoder.c b/sys/vdpau/gstvdpaudecoder.c index 36d6eca0..36a566e0 100644 --- a/sys/vdpau/gstvdpaudecoder.c +++ b/sys/vdpau/gstvdpaudecoder.c @@ -286,6 +286,7 @@ static gboolean gst_vdpaudecoder_sink_set_caps (GstPad * pad, GstCaps * caps) { GstVdpauDecoder *dec = GST_VDPAU_DECODER (GST_OBJECT_PARENT (pad)); + GstVdpauDecoderClass *dec_class = GST_VDPAU_DECODER_GET_CLASS (dec); GstCaps *src_caps, *new_caps; GstStructure *structure; @@ -324,6 +325,9 @@ gst_vdpaudecoder_sink_set_caps (GstPad * pad, GstCaps * caps) dec->height = height; dec->format = fourcc_format; + if (dec_class->set_caps && !dec_class->set_caps (dec, caps)) + return FALSE; + return TRUE; } @@ -404,6 +408,7 @@ gst_vdpaudecoder_init (GstVdpauDecoder * dec, GstVdpauDecoderClass * klass) (GST_ELEMENT_CLASS (klass), "sink"), "sink"); gst_pad_set_setcaps_function (dec->sink, gst_vdpaudecoder_sink_set_caps); gst_element_add_pad (GST_ELEMENT (dec), dec->sink); + gst_pad_set_active (dec->sink, TRUE); } static void diff --git a/sys/vdpau/gstvdpaudecoder.h b/sys/vdpau/gstvdpaudecoder.h index 336e4b8a..d8b8aa33 100644 --- a/sys/vdpau/gstvdpaudecoder.h +++ b/sys/vdpau/gstvdpaudecoder.h @@ -29,16 +29,12 @@ G_BEGIN_DECLS -#define GST_TYPE_VDPAU_DECODER \ - (gst_vdpaudecoder_get_type()) -#define GST_VDPAU_DECODER(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VDPAU_DECODER,GstVdpauDecoder)) -#define GST_VDPAU_DECODER_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VDPAU_DECODER,GstVdpauDecoderClass)) -#define GST_IS_VDPAU_DECODER(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VDPAU_DECODER)) -#define GST_IS_VDPAU_DECODER_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VDPAU_DECODER)) +#define GST_TYPE_VDPAU_DECODER (gst_vdpaudecoder_get_type()) +#define GST_VDPAU_DECODER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VDPAU_DECODER,GstVdpauDecoder)) +#define GST_VDPAU_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VDPAU_DECODER,GstVdpauDecoderClass)) +#define GST_VDPAU_DECODER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_VDPAU_DECODER, GstVdpauDecoderClass)) +#define GST_IS_VDPAU_DECODER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VDPAU_DECODER)) +#define GST_IS_VDPAU_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VDPAU_DECODER)) typedef struct _GstVdpauDecoder GstVdpauDecoder; typedef struct _GstVdpauDecoderClass GstVdpauDecoderClass; @@ -62,6 +58,8 @@ struct _GstVdpauDecoder { struct _GstVdpauDecoderClass { GstBaseTransformClass parent_class; + + gboolean (*set_caps) (GstVdpauDecoder *dec, GstCaps *caps); }; GType gst_vdpaudecoder_get_type (void); diff --git a/sys/vdpau/gstvdpaumpegdecoder.c b/sys/vdpau/gstvdpaumpegdecoder.c index c22c27f3..380cf602 100644 --- a/sys/vdpau/gstvdpaumpegdecoder.c +++ b/sys/vdpau/gstvdpaumpegdecoder.c @@ -87,7 +87,8 @@ enum static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, - GST_STATIC_CAPS ("video/x-mpeg, mpegversion = (int) [ 1, 2 ]") + GST_STATIC_CAPS ("video/mpeg, mpegversion = (int) [ 1, 2 ], " + "systemstream = (boolean) false") ); GST_BOILERPLATE (GstVdpauMpegDecoder, gst_vdpau_mpeg_decoder, GstVdpauDecoder, @@ -98,6 +99,20 @@ static void gst_vdpau_mpeg_decoder_set_property (GObject * object, static void gst_vdpau_mpeg_decoder_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); +static gboolean +gst_vdpau_mpeg_decoder_set_caps (GstVdpauDecoder * dec, GstCaps * caps) +{ + GstVdpauMpegDecoder *mpeg_dec; + GstStructure *structure; + + mpeg_dec = GST_VDPAU_MPEG_DECODER (dec); + + structure = gst_caps_get_structure (caps, 0); + gst_structure_get_int (structure, "mpegversion", &mpeg_dec->version); + + return TRUE; +} + /* GObject vmethod implementations */ static void @@ -121,9 +136,11 @@ gst_vdpau_mpeg_decoder_class_init (GstVdpauMpegDecoderClass * klass) { GObjectClass *gobject_class; GstElementClass *gstelement_class; + GstVdpauDecoderClass *vdpaudec_class; gobject_class = (GObjectClass *) klass; gstelement_class = (GstElementClass *) klass; + vdpaudec_class = (GstVdpauDecoderClass *) klass; gobject_class->set_property = gst_vdpau_mpeg_decoder_set_property; gobject_class->get_property = gst_vdpau_mpeg_decoder_get_property; @@ -131,6 +148,8 @@ gst_vdpau_mpeg_decoder_class_init (GstVdpauMpegDecoderClass * klass) g_object_class_install_property (gobject_class, PROP_SILENT, g_param_spec_boolean ("silent", "Silent", "Produce verbose output ?", FALSE, G_PARAM_READWRITE)); + + vdpaudec_class->set_caps = gst_vdpau_mpeg_decoder_set_caps; } static void diff --git a/sys/vdpau/gstvdpaumpegdecoder.h b/sys/vdpau/gstvdpaumpegdecoder.h index 14c9a3f7..97462942 100644 --- a/sys/vdpau/gstvdpaumpegdecoder.h +++ b/sys/vdpau/gstvdpaumpegdecoder.h @@ -53,16 +53,11 @@ G_BEGIN_DECLS /* #defines don't like whitespacey bits */ -#define GST_TYPE_VDPAU_MPEG_DECODER \ - (gst_vdpau_mpeg_decoder_get_type()) -#define GST_VDPAU_MPEG_DECODER(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VDPAU_MPEG_DECODER,GstVdpauMpegDecoder)) -#define GST_VDPAU_MPEG_DECODER_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VDPAU_MPEG_DECODER,GstVdpauMpegDecoderClass)) -#define GST_IS_VDPAU_MPEG_DECODER(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VDPAU_MPEG_DECODER)) -#define GST_IS_VDPAU_MPEG_DECODER_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VDPAU_MPEG_DECODER)) +#define GST_TYPE_VDPAU_MPEG_DECODER (gst_vdpau_mpeg_decoder_get_type()) +#define GST_VDPAU_MPEG_DECODER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VDPAU_MPEG_DECODER,GstVdpauMpegDecoder)) +#define GST_VDPAU_MPEG_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VDPAU_MPEG_DECODER,GstVdpauMpegDecoderClass)) +#define GST_IS_VDPAU_MPEG_DECODER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VDPAU_MPEG_DECODER)) +#define GST_IS_VDPAU_MPEG_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VDPAU_MPEG_DECODER)) typedef struct _GstVdpauMpegDecoder GstVdpauMpegDecoder; typedef struct _GstVdpauMpegDecoderClass GstVdpauMpegDecoderClass; @@ -71,9 +66,9 @@ struct _GstVdpauMpegDecoder { GstVdpauDecoder dec; - GstPad *sinkpad, *srcpad; - gboolean silent; + + gint version; }; struct _GstVdpauMpegDecoderClass -- cgit v1.2.1 From 29d0c5bdd8beeb2b1ed25e8bf37eec9a135c5422 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Fri, 27 Mar 2009 16:55:19 +0100 Subject: vdpau: extract mpeg2 profile from codec_data --- sys/vdpau/Makefile.am | 10 +- sys/vdpau/gstvdpaudecoder.c | 4 +- sys/vdpau/gstvdpaumpegdecoder.c | 29 ++++- sys/vdpau/gstvdpaumpegdecoder.h | 4 +- sys/vdpau/mpegutil.c | 227 ++++++++++++++++++++++++++++++++++++++++ sys/vdpau/mpegutil.h | 63 +++++++++++ 6 files changed, 325 insertions(+), 12 deletions(-) create mode 100644 sys/vdpau/mpegutil.c create mode 100644 sys/vdpau/mpegutil.h diff --git a/sys/vdpau/Makefile.am b/sys/vdpau/Makefile.am index 94f7efbc..f66c4aa4 100644 --- a/sys/vdpau/Makefile.am +++ b/sys/vdpau/Makefile.am @@ -1,8 +1,9 @@ plugin_LTLIBRARIES = libgstvdpau.la libgstvdpau_la_SOURCES = \ - gstvdpaudecoder.c\ - gstvdpaumpegdecoder.c + gstvdpaudecoder.c \ + gstvdpaumpegdecoder.c \ + mpegutil.c libgstvdpau_la_CFLAGS = $(GST_CFLAGS) $(X11_CFLAGS) -Ivdpau libgstvdpau_la_LIBADD = $(GST_LIBS) $(X11_LIBS) -lvdpau @@ -10,8 +11,9 @@ libgstvdpau_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) libgstvdpau_la_LIBTOOLFLAGS = --tag=disable-static noinst_HEADERS = \ - gstvdpaudecoder.h\ + gstvdpaudecoder.h \ vdpauvariables.h \ - gstvdpaumpegdecoder.h + gstvdpaumpegdecoder.h \ + mpegutil.h diff --git a/sys/vdpau/gstvdpaudecoder.c b/sys/vdpau/gstvdpaudecoder.c index 36a566e0..7d4ecb39 100644 --- a/sys/vdpau/gstvdpaudecoder.c +++ b/sys/vdpau/gstvdpaudecoder.c @@ -302,6 +302,8 @@ gst_vdpaudecoder_sink_set_caps (GstPad * pad, GstCaps * caps) &framerate_numerator, &framerate_denominator); src_caps = gst_pad_get_allowed_caps (dec->src); + if (G_UNLIKELY (!src_caps)) + return FALSE; structure = gst_caps_get_structure (src_caps, 0); gst_structure_get_fourcc (structure, "format", &fourcc_format); @@ -318,7 +320,7 @@ gst_vdpaudecoder_sink_set_caps (GstPad * pad, GstCaps * caps) gst_caps_unref (new_caps); - if (!res) + if (G_UNLIKELY (!res)) return FALSE; dec->width = width; diff --git a/sys/vdpau/gstvdpaumpegdecoder.c b/sys/vdpau/gstvdpaumpegdecoder.c index 380cf602..e5da459f 100644 --- a/sys/vdpau/gstvdpaumpegdecoder.c +++ b/sys/vdpau/gstvdpaumpegdecoder.c @@ -1,7 +1,5 @@ /* * GStreamer - * Copyright (C) 2005 Thomas Vander Stichele - * Copyright (C) 2005 Ronald S. Bultje * Copyright (C) 2009 Carl-Anton Ingmarsson * * Permission is hereby granted, free of charge, to any person obtaining a @@ -62,6 +60,7 @@ #include +#include "mpegutil.h" #include "gstvdpaumpegdecoder.h" GST_DEBUG_CATEGORY_STATIC (gst_vdpau_mpeg_decoder_debug); @@ -88,7 +87,7 @@ static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, GST_STATIC_CAPS ("video/mpeg, mpegversion = (int) [ 1, 2 ], " - "systemstream = (boolean) false") + "systemstream = (boolean) false, parsed = (boolean) true") ); GST_BOILERPLATE (GstVdpauMpegDecoder, gst_vdpau_mpeg_decoder, GstVdpauDecoder, @@ -104,11 +103,33 @@ gst_vdpau_mpeg_decoder_set_caps (GstVdpauDecoder * dec, GstCaps * caps) { GstVdpauMpegDecoder *mpeg_dec; GstStructure *structure; + gint version; mpeg_dec = GST_VDPAU_MPEG_DECODER (dec); structure = gst_caps_get_structure (caps, 0); - gst_structure_get_int (structure, "mpegversion", &mpeg_dec->version); + gst_structure_get_int (structure, "mpegversion", &version); + if (version == 1) + mpeg_dec->profile = VDP_DECODER_PROFILE_MPEG1; + + else { + const GValue *value; + GstBuffer *codec_data; + MPEGSeqHdr hdr = { 0, }; + + value = gst_structure_get_value (structure, "codec_data"); + codec_data = gst_value_get_buffer (value); + mpeg_util_parse_sequence_hdr (&hdr, GST_BUFFER_DATA (codec_data), + GST_BUFFER_DATA (codec_data) + GST_BUFFER_SIZE (codec_data)); + switch (hdr.profile) { + case 5: + mpeg_dec->profile = VDP_DECODER_PROFILE_MPEG2_SIMPLE; + break; + default: + mpeg_dec->profile = VDP_DECODER_PROFILE_MPEG2_MAIN; + break; + } + } return TRUE; } diff --git a/sys/vdpau/gstvdpaumpegdecoder.h b/sys/vdpau/gstvdpaumpegdecoder.h index 97462942..830cc671 100644 --- a/sys/vdpau/gstvdpaumpegdecoder.h +++ b/sys/vdpau/gstvdpaumpegdecoder.h @@ -1,7 +1,5 @@ /* * GStreamer - * Copyright (C) 2005 Thomas Vander Stichele - * Copyright (C) 2005 Ronald S. Bultje * Copyright (C) 2009 Carl-Anton Ingmarsson * * Permission is hereby granted, free of charge, to any person obtaining a @@ -68,7 +66,7 @@ struct _GstVdpauMpegDecoder gboolean silent; - gint version; + VdpDecoderProfile profile; }; struct _GstVdpauMpegDecoderClass diff --git a/sys/vdpau/mpegutil.c b/sys/vdpau/mpegutil.c new file mode 100644 index 00000000..274fa853 --- /dev/null +++ b/sys/vdpau/mpegutil.c @@ -0,0 +1,227 @@ +/* GStreamer + * Copyright (C) 2007 Jan Schmidt + * Copyright (C) 2009 Carl-Anton Ingmarsson + * + * 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. + */ + +#include "mpegutil.h" + +guint8 bits[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; + +guint32 +read_bits (guint8 * buf, gint start_bit, gint n_bits) +{ + gint i; + guint32 ret = 0x00; + + buf += start_bit / 8; + start_bit %= 8; + + for (i = 0; i < n_bits; i++) { + guint32 tmp; + + tmp = ((*buf & bits[start_bit]) >> (7 - start_bit)); + ret = (ret | (tmp << (n_bits - i - 1))); + if (++start_bit == 8) { + buf += 1; + start_bit = 0; + } + } + + return ret; +} + +guint8 * +mpeg_util_find_start_code (guint32 * sync_word, guint8 * cur, guint8 * end) +{ + guint32 code; + + if (G_UNLIKELY (cur == NULL)) + return NULL; + + code = *sync_word; + + while (cur < end) { + code <<= 8; + + if (code == 0x00000100) { + /* Reset the sync word accumulator */ + *sync_word = 0xffffffff; + return cur; + } + + /* Add the next available byte to the collected sync word */ + code |= *cur++; + } + + *sync_word = code; + return NULL; +} + +static void +set_fps_from_code (MPEGSeqHdr * hdr, guint8 fps_code) +{ + const gint framerates[][2] = { + {30, 1}, {24000, 1001}, {24, 1}, {25, 1}, + {30000, 1001}, {30, 1}, {50, 1}, {60000, 1001}, + {60, 1}, {30, 1} + }; + + if (fps_code < 10) { + hdr->fps_n = framerates[fps_code][0]; + hdr->fps_d = framerates[fps_code][1]; + } else { + /* Force a valid framerate */ + hdr->fps_n = 30000; + hdr->fps_d = 1001; + } +} + +/* Set the Pixel Aspect Ratio in our hdr from a DAR code in the data */ +static void +set_par_from_dar (MPEGSeqHdr * hdr, guint8 asr_code) +{ + /* Pixel_width = DAR_width * display_vertical_size */ + /* Pixel_height = DAR_height * display_horizontal_size */ + switch (asr_code) { + case 0x02: /* 3:4 DAR = 4:3 pixels */ + hdr->par_w = 4 * hdr->height; + hdr->par_h = 3 * hdr->width; + break; + case 0x03: /* 9:16 DAR */ + hdr->par_w = 16 * hdr->height; + hdr->par_h = 9 * hdr->width; + break; + case 0x04: /* 1:2.21 DAR */ + hdr->par_w = 221 * hdr->height; + hdr->par_h = 100 * hdr->width; + break; + case 0x01: /* Square pixels */ + default: + hdr->par_w = hdr->par_h = 1; + break; + } +} + +static gboolean +mpeg_util_parse_extension_packet (MPEGSeqHdr * hdr, guint8 * data, guint8 * end) +{ + guint8 ext_code; + + if (G_UNLIKELY (data >= end)) + return FALSE; /* short extension packet */ + + ext_code = data[0] >> 4; + + switch (ext_code) { + case MPEG_PACKET_EXT_SEQUENCE: + { + /* Parse a Sequence Extension */ + guint8 horiz_size_ext, vert_size_ext; + guint8 fps_n_ext, fps_d_ext; + + if (G_UNLIKELY ((end - data) < 6)) + /* need at least 10 bytes, minus 4 for the start code 000001b5 */ + return FALSE; + + horiz_size_ext = ((data[1] << 1) & 0x02) | ((data[2] >> 7) & 0x01); + vert_size_ext = (data[2] >> 5) & 0x03; + hdr->profile = read_bits (data, 7, 3); + fps_n_ext = (data[5] >> 5) & 0x03; + fps_d_ext = data[5] & 0x1f; + + hdr->fps_n *= (fps_n_ext + 1); + hdr->fps_d *= (fps_d_ext + 1); + hdr->width += (horiz_size_ext << 12); + hdr->height += (vert_size_ext << 12); + break; + } + default: + break; + } + + return TRUE; +} + +gboolean +mpeg_util_parse_sequence_hdr (MPEGSeqHdr * hdr, guint8 * data, guint8 * end) +{ + guint32 code; + guint8 dar_idx, fps_idx; + guint32 sync_word = 0xffffffff; + gboolean constrained_flag; + gboolean load_intra_flag; + gboolean load_non_intra_flag; + + if (G_UNLIKELY ((end - data) < 12)) + return FALSE; /* Too small to be a sequence header */ + + code = GST_READ_UINT32_BE (data); + if (G_UNLIKELY (code != (0x00000100 | MPEG_PACKET_SEQUENCE))) + return FALSE; + + /* Skip the sync word */ + data += 4; + + /* Parse the MPEG 1 bits */ + hdr->mpeg_version = 1; + + code = GST_READ_UINT32_BE (data); + hdr->width = (code >> 20) & 0xfff; + hdr->height = (code >> 8) & 0xfff; + + dar_idx = (code >> 4) & 0xf; + set_par_from_dar (hdr, dar_idx); + fps_idx = code & 0xf; + set_fps_from_code (hdr, fps_idx); + + constrained_flag = (data[7] >> 2) & 0x01; + load_intra_flag = (data[7] >> 1) & 0x01; + if (load_intra_flag) { + if (G_UNLIKELY ((end - data) < 64)) + return FALSE; + data += 64; + } + + load_non_intra_flag = data[7] & 0x01; + if (load_non_intra_flag) { + if (G_UNLIKELY ((end - data) < 64)) + return FALSE; + data += 64; + } + + /* Advance past the rest of the MPEG-1 header */ + data += 8; + + /* Read MPEG-2 sequence extensions */ + data = mpeg_util_find_start_code (&sync_word, data, end); + while (data != NULL) { + if (G_UNLIKELY (data >= end)) + return FALSE; + + /* data points at the last byte of the start code */ + if (data[0] == MPEG_PACKET_EXTENSION) { + if (!mpeg_util_parse_extension_packet (hdr, data + 1, end)) + return FALSE; + + hdr->mpeg_version = 2; + } + data = mpeg_util_find_start_code (&sync_word, data, end); + } + + return TRUE; +} diff --git a/sys/vdpau/mpegutil.h b/sys/vdpau/mpegutil.h new file mode 100644 index 00000000..f0f8aca0 --- /dev/null +++ b/sys/vdpau/mpegutil.h @@ -0,0 +1,63 @@ +/* GStreamer + * Copyright (C) 2007 Jan Schmidt + * Copyright (C) 2009 Carl-Anton Ingmarsson + * + * 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 __MPEGUTIL_H__ +#define __MPEGUTIL_H__ + +#include + +typedef struct MPEGSeqHdr MPEGSeqHdr; + +/* Packet ID codes for different packet types we + * care about */ +#define MPEG_PACKET_PICTURE 0x00 +#define MPEG_PACKET_SLICE_MIN 0x01 +#define MPEG_PACKET_SLICE_MAX 0xaf +#define MPEG_PACKET_SEQUENCE 0xb3 +#define MPEG_PACKET_EXTENSION 0xb5 +#define MPEG_PACKET_SEQUENCE_END 0xb7 +#define MPEG_PACKET_GOP 0xb8 +#define MPEG_PACKET_NONE 0xff + +/* Extension codes we care about */ +#define MPEG_PACKET_EXT_SEQUENCE 0x01 +#define MPEG_PACKET_EXT_SEQUENCE_DISPLAY 0x02 +#define MPEG_PACKET_EXT_QUANT_MATRIX 0x03 + +struct MPEGSeqHdr +{ + /* 0 for unknown, else 1 or 2 */ + guint8 mpeg_version; + + /* Pixel-Aspect Ratio from DAR code via set_par_from_dar */ + gint par_w, par_h; + /* Width and Height of the video */ + gint width, height; + /* Framerate */ + gint fps_n, fps_d; + + /* mpeg2 decoder profile */ + gint profile; +}; + +gboolean mpeg_util_parse_sequence_hdr (MPEGSeqHdr *hdr, + guint8 *data, guint8 *end); + +#endif -- cgit v1.2.1 From 584b000583c7050689d7a93e5d6dc7083bbdfcbd Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Fri, 27 Mar 2009 17:11:04 +0100 Subject: vdpau: store vdpau function pointers in a local structure --- sys/vdpau/Makefile.am | 1 - sys/vdpau/gstvdpaudecoder.c | 40 +++++++++++++++++++++++++-------------- sys/vdpau/gstvdpaudecoder.h | 17 +++++++++++++++++ sys/vdpau/vdpauvariables.h | 46 --------------------------------------------- 4 files changed, 43 insertions(+), 61 deletions(-) delete mode 100644 sys/vdpau/vdpauvariables.h diff --git a/sys/vdpau/Makefile.am b/sys/vdpau/Makefile.am index f66c4aa4..b786be0d 100644 --- a/sys/vdpau/Makefile.am +++ b/sys/vdpau/Makefile.am @@ -12,7 +12,6 @@ libgstvdpau_la_LIBTOOLFLAGS = --tag=disable-static noinst_HEADERS = \ gstvdpaudecoder.h \ - vdpauvariables.h \ gstvdpaumpegdecoder.h \ mpegutil.h diff --git a/sys/vdpau/gstvdpaudecoder.c b/sys/vdpau/gstvdpaudecoder.c index 7d4ecb39..007837f4 100644 --- a/sys/vdpau/gstvdpaudecoder.c +++ b/sys/vdpau/gstvdpaudecoder.c @@ -29,7 +29,6 @@ #include #include -#include "vdpauvariables.h" #include "gstvdpaudecoder.h" GST_DEBUG_CATEGORY_STATIC (gst_vdpaudecoder_debug); @@ -71,6 +70,10 @@ gboolean gst_vdpaudecoder_push_video_surface (GstVdpauDecoder * dec, VdpVideoSurface surface) { + VdpauFunctions *f; + + f = dec->functions; + switch (dec->format) { case GST_MAKE_FOURCC ('Y', 'V', '1', '2'): { @@ -92,7 +95,7 @@ gst_vdpaudecoder_push_video_surface (GstVdpauDecoder * dec, data[2] = data[1] + dec->height * dec->width / 4; status = - vdp_video_surface_get_bits_ycbcr (surface, VDP_YCBCR_FORMAT_YV12, + f->vdp_video_surface_get_bits_ycbcr (surface, VDP_YCBCR_FORMAT_YV12, (void *) data, NULL); if (G_UNLIKELY (status != VDP_STATUS_OK)) return FALSE; @@ -151,9 +154,12 @@ static VdpauFormats formats[6] = { static GstCaps * gst_vdpaudecoder_get_vdpau_support (GstVdpauDecoder * dec) { + VdpauFunctions *f; GstCaps *caps; gint i; + f = dec->functions; + caps = gst_caps_new_empty (); for (i = 0; i < 3; i++) { @@ -161,7 +167,8 @@ gst_vdpaudecoder_get_vdpau_support (GstVdpauDecoder * dec) VdpBool is_supported; guint32 max_w, max_h; - status = vdp_video_surface_query_capabilities (dec->device, chroma_types[i], + status = + f->vdp_video_surface_query_capabilities (dec->device, chroma_types[i], &is_supported, &max_w, &max_h); if (status != VDP_STATUS_OK && status != VDP_STATUS_INVALID_CHROMA_TYPE) { @@ -179,7 +186,7 @@ gst_vdpaudecoder_get_vdpau_support (GstVdpauDecoder * dec) continue; status = - vdp_video_surface_query_ycbcr_capabilities (dec->device, + f->vdp_video_surface_query_ycbcr_capabilities (dec->device, formats[j].chroma_type, formats[j].format, &is_supported); if (status != VDP_STATUS_OK && status != VDP_STATUS_INVALID_Y_CB_CR_FORMAT) { @@ -215,6 +222,7 @@ gst_vdpaudecoder_init_vdpau (GstVdpauDecoder * dec) { Display *display; int screen; + VdpauFunctions *f; VdpStatus status; GstCaps *caps; @@ -226,10 +234,12 @@ gst_vdpaudecoder_init_vdpau (GstVdpauDecoder * dec) return FALSE; } + f = dec->functions; + screen = DefaultScreen (display); status = vdp_device_create_x11 (display, screen, &dec->device, - &vdp_get_proc_address); + &f->vdp_get_proc_address); if (status != VDP_STATUS_OK) { GST_ELEMENT_ERROR (dec, RESOURCE, READ, ("Could not initialise VDPAU"), ("Could not create VDPAU device")); @@ -239,21 +249,21 @@ gst_vdpaudecoder_init_vdpau (GstVdpauDecoder * dec) } XCloseDisplay (display); - vdp_get_proc_address (dec->device, + f->vdp_get_proc_address (dec->device, VDP_FUNC_ID_VIDEO_SURFACE_QUERY_CAPABILITIES, - (void **) &vdp_video_surface_query_capabilities); - vdp_get_proc_address (dec->device, + (void **) &f->vdp_video_surface_query_capabilities); + f->vdp_get_proc_address (dec->device, VDP_FUNC_ID_VIDEO_SURFACE_QUERY_GET_PUT_BITS_Y_CB_CR_CAPABILITIES, - (void **) &vdp_video_surface_query_ycbcr_capabilities); - vdp_get_proc_address (dec->device, - VDP_FUNC_ID_DEVICE_DESTROY, (void **) &vdp_device_destroy); - vdp_get_proc_address (dec->device, + (void **) &f->vdp_video_surface_query_ycbcr_capabilities); + f->vdp_get_proc_address (dec->device, + VDP_FUNC_ID_DEVICE_DESTROY, (void **) &f->vdp_device_destroy); + f->vdp_get_proc_address (dec->device, VDP_FUNC_ID_VIDEO_SURFACE_GET_BITS_Y_CB_CR, - (void **) &vdp_video_surface_get_bits_ycbcr); + (void **) &f->vdp_video_surface_get_bits_ycbcr); caps = gst_vdpaudecoder_get_vdpau_support (dec); if (!caps) { - vdp_device_destroy (dec->device); + f->vdp_device_destroy (dec->device); dec->device = 0; return FALSE; } @@ -402,6 +412,8 @@ gst_vdpaudecoder_init (GstVdpauDecoder * dec, GstVdpauDecoderClass * klass) dec->width = 0; dec->format = 0; + dec->functions = g_slice_new0 (VdpauFunctions); + dec->src = gst_pad_new_from_static_template (&src_template, "src"); gst_pad_set_getcaps_function (dec->src, gst_vdpaudecoder_src_getcaps); gst_element_add_pad (GST_ELEMENT (dec), dec->src); diff --git a/sys/vdpau/gstvdpaudecoder.h b/sys/vdpau/gstvdpaudecoder.h index d8b8aa33..2c1a274f 100644 --- a/sys/vdpau/gstvdpaudecoder.h +++ b/sys/vdpau/gstvdpaudecoder.h @@ -38,6 +38,7 @@ G_BEGIN_DECLS typedef struct _GstVdpauDecoder GstVdpauDecoder; typedef struct _GstVdpauDecoderClass GstVdpauDecoderClass; +typedef struct _VdpauFunctions VdpauFunctions; struct _GstVdpauDecoder { GstElement element; @@ -45,6 +46,8 @@ struct _GstVdpauDecoder { gchar *display; VdpDevice device; + VdpauFunctions *functions; + GstPad *src; GstPad *sink; @@ -62,6 +65,20 @@ struct _GstVdpauDecoderClass { gboolean (*set_caps) (GstVdpauDecoder *dec, GstCaps *caps); }; +struct _VdpauFunctions { + VdpGetProcAddress *vdp_get_proc_address; + + VdpVideoSurfaceQueryCapabilities *vdp_video_surface_query_capabilities; + VdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities *vdp_video_surface_query_ycbcr_capabilities; + VdpVideoSurfaceGetBitsYCbCr *vdp_video_surface_get_bits_ycbcr; + + VdpDeviceDestroy *vdp_device_destroy; + + VdpDecoderCreate *vdp_decoder_create; + VdpDecoderDestroy *vdp_decoder_destroy; + VdpDecoderRender *vdp_decoder_render; +}; + GType gst_vdpaudecoder_get_type (void); gboolean gst_vdpaudecoder_push_video_surface (GstVdpauDecoder * dec, VdpVideoSurface surface); diff --git a/sys/vdpau/vdpauvariables.h b/sys/vdpau/vdpauvariables.h deleted file mode 100644 index c0f7bb4f..00000000 --- a/sys/vdpau/vdpauvariables.h +++ /dev/null @@ -1,46 +0,0 @@ -#include - -static VdpVideoSurfaceQueryCapabilities *vdp_video_surface_query_capabilities; -static VdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities *vdp_video_surface_query_ycbcr_capabilities; -static VdpVideoSurfaceGetBitsYCbCr *vdp_video_surface_get_bits_ycbcr; - -static VdpGetProcAddress *vdp_get_proc_address; -static VdpDeviceDestroy *vdp_device_destroy; - -#if 0 -static VdpVideoSurfaceCreate *vdp_video_surface_create; -static VdpVideoSurfaceDestroy *vdp_video_surface_destroy; - -static VdpGetErrorString *vdp_get_error_string; - -static VdpVideoSurfacePutBitsYCbCr *vdp_video_surface_put_bits_y_cb_cr; -static VdpOutputSurfacePutBitsNative *vdp_output_surface_put_bits_native; - -static VdpOutputSurfaceCreate *vdp_output_surface_create; -static VdpOutputSurfaceDestroy *vdp_output_surface_destroy; - -static VdpVideoMixerCreate *vdp_video_mixer_create; -static VdpVideoMixerDestroy *vdp_video_mixer_destroy; -static VdpVideoMixerRender *vdp_video_mixer_render; -static VdpVideoMixerSetFeatureEnables *vdp_video_mixer_set_feature_enables; -static VdpVideoMixerSetAttributeValues *vdp_video_mixer_set_attribute_values; - -static VdpPresentationQueueTargetDestroy *vdp_presentation_queue_target_destroy; -static VdpPresentationQueueCreate *vdp_presentation_queue_create; -static VdpPresentationQueueDestroy *vdp_presentation_queue_destroy; -static VdpPresentationQueueDisplay *vdp_presentation_queue_display; -static VdpPresentationQueueBlockUntilSurfaceIdle *vdp_presentation_queue_block_until_surface_idle; -static VdpPresentationQueueTargetCreateX11 *vdp_presentation_queue_target_create_x11; - -static VdpOutputSurfaceRenderOutputSurface *vdp_output_surface_render_output_surface; -static VdpOutputSurfacePutBitsIndexed *vdp_output_surface_put_bits_indexed; -static VdpOutputSurfaceRenderBitmapSurface *vdp_output_surface_render_bitmap_surface; - -static VdpBitmapSurfaceCreate *vdp_bitmap_surface_create; -static VdpBitmapSurfaceDestroy *vdp_bitmap_surface_destroy; -static VdpBitmapSurfacePutBitsNative *vdp_bitmap_surface_putbits_native; - -static VdpDecoderCreate *vdp_decoder_create; -static VdpDecoderDestroy *vdp_decoder_destroy; -static VdpDecoderRender *vdp_decoder_render; -#endif \ No newline at end of file -- cgit v1.2.1 From f70ddb66050244bdc0833d7cdc6c1b2e64f425ff Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Sun, 29 Mar 2009 15:28:06 +0200 Subject: vdpau: create VdpDecoder in set_caps add more functions for parsing mpeg --- sys/vdpau/gstvdpaudecoder.c | 128 ++++++++++++++++++++++++++++------------ sys/vdpau/gstvdpaudecoder.h | 15 +++-- sys/vdpau/gstvdpaumpegdecoder.c | 25 ++++++-- sys/vdpau/gstvdpaumpegdecoder.h | 2 +- sys/vdpau/mpegutil.c | 115 ++++++++++++++++++++++++++++++++++++ sys/vdpau/mpegutil.h | 39 +++++++++++- 6 files changed, 276 insertions(+), 48 deletions(-) diff --git a/sys/vdpau/gstvdpaudecoder.c b/sys/vdpau/gstvdpaudecoder.c index 007837f4..c13b0173 100644 --- a/sys/vdpau/gstvdpaudecoder.c +++ b/sys/vdpau/gstvdpaudecoder.c @@ -26,10 +26,8 @@ #include #include -#include -#include - #include "gstvdpaudecoder.h" +#include GST_DEBUG_CATEGORY_STATIC (gst_vdpaudecoder_debug); #define GST_CAT_DEFAULT gst_vdpaudecoder_debug @@ -173,8 +171,9 @@ gst_vdpaudecoder_get_vdpau_support (GstVdpauDecoder * dec) if (status != VDP_STATUS_OK && status != VDP_STATUS_INVALID_CHROMA_TYPE) { GST_ELEMENT_ERROR (dec, RESOURCE, READ, - ("Could not get VDPAU capabilites"), - ("Could not query video surface capabilities")); + ("Could not get query VDPAU video surface capabilites"), + ("Error returned from vdpau was: %s", + f->vdp_get_error_string (status))); return NULL; } @@ -191,8 +190,9 @@ gst_vdpaudecoder_get_vdpau_support (GstVdpauDecoder * dec) if (status != VDP_STATUS_OK && status != VDP_STATUS_INVALID_Y_CB_CR_FORMAT) { GST_ELEMENT_ERROR (dec, RESOURCE, READ, - ("Could not get VDPAU capabilites"), - ("Could not query video surface ycbcr capabilities")); + ("Could not query VDPAU YCbCr capabilites"), + ("Error returned from vdpau was: %s", + f->vdp_get_error_string (status))); return NULL; } @@ -220,15 +220,45 @@ gst_vdpaudecoder_get_vdpau_support (GstVdpauDecoder * dec) static gboolean gst_vdpaudecoder_init_vdpau (GstVdpauDecoder * dec) { - Display *display; - int screen; - VdpauFunctions *f; + gint screen; VdpStatus status; + gint i; + VdpauFunctions *f; GstCaps *caps; + typedef struct + { + int id; + void *func; + } VdpFunction; + + VdpFunction vdp_function[] = { + {VDP_FUNC_ID_DEVICE_DESTROY, &dec->functions->vdp_device_destroy}, + {VDP_FUNC_ID_VIDEO_SURFACE_CREATE, + &dec->functions->vdp_video_surface_create}, + {VDP_FUNC_ID_VIDEO_SURFACE_DESTROY, + &dec->functions->vdp_video_surface_destroy}, + {VDP_FUNC_ID_VIDEO_SURFACE_QUERY_CAPABILITIES, + &dec->functions->vdp_video_surface_query_capabilities}, + {VDP_FUNC_ID_VIDEO_SURFACE_QUERY_GET_PUT_BITS_Y_CB_CR_CAPABILITIES, + &dec->functions->vdp_video_surface_query_ycbcr_capabilities}, + {VDP_FUNC_ID_VIDEO_SURFACE_GET_BITS_Y_CB_CR, + &dec->functions->vdp_video_surface_get_bits_ycbcr}, + {VDP_FUNC_ID_VIDEO_SURFACE_GET_PARAMETERS, + &dec->functions->vdp_video_surface_get_parameters}, + {VDP_FUNC_ID_DECODER_CREATE, &dec->functions->vdp_decoder_create}, + {VDP_FUNC_ID_DECODER_RENDER, &dec->functions->vdp_decoder_render}, + {VDP_FUNC_ID_DECODER_DESTROY, &dec->functions->vdp_decoder_destroy}, + {VDP_FUNC_ID_DECODER_QUERY_CAPABILITIES, + &dec->functions->vdp_decoder_query_capabilities}, + {VDP_FUNC_ID_DECODER_GET_PARAMETERS, + &dec->functions->vdp_decoder_get_parameters}, + {0, NULL} + }; + /* FIXME: We probably want to use the same VdpDevice for every VDPAU element */ - display = XOpenDisplay (dec->display); - if (!display) { + dec->display = XOpenDisplay (dec->display_name); + if (!dec->display) { GST_ELEMENT_ERROR (dec, RESOURCE, READ, ("Could not initialise VDPAU"), ("Could not open display")); return FALSE; @@ -236,55 +266,78 @@ gst_vdpaudecoder_init_vdpau (GstVdpauDecoder * dec) f = dec->functions; - screen = DefaultScreen (display); + screen = DefaultScreen (dec->display); status = - vdp_device_create_x11 (display, screen, &dec->device, + vdp_device_create_x11 (dec->display, screen, &dec->device, &f->vdp_get_proc_address); if (status != VDP_STATUS_OK) { GST_ELEMENT_ERROR (dec, RESOURCE, READ, ("Could not initialise VDPAU"), ("Could not create VDPAU device")); - XCloseDisplay (display); + XCloseDisplay (dec->display); + dec->display = NULL; return FALSE; } - XCloseDisplay (display); - - f->vdp_get_proc_address (dec->device, - VDP_FUNC_ID_VIDEO_SURFACE_QUERY_CAPABILITIES, - (void **) &f->vdp_video_surface_query_capabilities); - f->vdp_get_proc_address (dec->device, - VDP_FUNC_ID_VIDEO_SURFACE_QUERY_GET_PUT_BITS_Y_CB_CR_CAPABILITIES, - (void **) &f->vdp_video_surface_query_ycbcr_capabilities); - f->vdp_get_proc_address (dec->device, - VDP_FUNC_ID_DEVICE_DESTROY, (void **) &f->vdp_device_destroy); - f->vdp_get_proc_address (dec->device, - VDP_FUNC_ID_VIDEO_SURFACE_GET_BITS_Y_CB_CR, - (void **) &f->vdp_video_surface_get_bits_ycbcr); - caps = gst_vdpaudecoder_get_vdpau_support (dec); - if (!caps) { - f->vdp_device_destroy (dec->device); - dec->device = 0; - return FALSE; + status = f->vdp_get_proc_address (dec->device, + VDP_FUNC_ID_GET_ERROR_STRING, (void **) &f->vdp_get_error_string); + if (status != VDP_STATUS_OK) { + GST_ELEMENT_ERROR (dec, RESOURCE, READ, + ("Could'nt get function pointer from vdpau"), + ("Couldn't get vdp_get_error_string function pointer")); + goto error; } + for (i = 0; vdp_function[i].func != NULL; i++) { + status = f->vdp_get_proc_address (dec->device, + vdp_function[i].id, vdp_function[i].func); + + if (status != VDP_STATUS_OK) { + GST_ELEMENT_ERROR (dec, RESOURCE, READ, + ("Could not get function pointer from vdpau"), + ("Error returned from vdpau was: %s", + f->vdp_get_error_string (status))); + goto error; + } + } + + caps = gst_vdpaudecoder_get_vdpau_support (dec); + if (!caps) + goto error; + dec->src_caps = caps; return TRUE; + +error: + f->vdp_device_destroy (dec->device); + dec->device = VDP_INVALID_HANDLE; + + return FALSE; + } static GstStateChangeReturn gst_vdpaudecoder_change_state (GstElement * element, GstStateChange transition) { GstVdpauDecoder *dec; + VdpauFunctions *f; dec = GST_VDPAU_DECODER (element); + f = dec->functions; switch (transition) { case GST_STATE_CHANGE_NULL_TO_READY: if (!gst_vdpaudecoder_init_vdpau (dec)) return GST_STATE_CHANGE_FAILURE; break; + case GST_STATE_CHANGE_READY_TO_NULL: + f->vdp_device_destroy (dec->device); + XCloseDisplay (dec->display); + + dec->device = VDP_INVALID_HANDLE; + dec->display = NULL; + break; default: break; } @@ -403,8 +456,9 @@ gst_vdpaudecoder_class_init (GstVdpauDecoderClass * klass) static void gst_vdpaudecoder_init (GstVdpauDecoder * dec, GstVdpauDecoderClass * klass) { + dec->display_name = NULL; dec->display = NULL; - dec->device = 0; + dec->device = VDP_INVALID_HANDLE; dec->silent = FALSE; dec->src_caps = NULL; @@ -433,8 +487,8 @@ gst_vdpaudecoder_set_property (GObject * object, guint prop_id, switch (prop_id) { case PROP_DISPLAY: - g_free (dec->display); - dec->display = g_value_dup_string (value); + g_free (dec->display_name); + dec->display_name = g_value_dup_string (value); break; case PROP_SILENT: dec->silent = g_value_get_boolean (value); @@ -453,7 +507,7 @@ gst_vdpaudecoder_get_property (GObject * object, guint prop_id, switch (prop_id) { case PROP_DISPLAY: - g_value_set_string (value, dec->display); + g_value_set_string (value, dec->display_name); break; case PROP_SILENT: g_value_set_boolean (value, dec->silent); diff --git a/sys/vdpau/gstvdpaudecoder.h b/sys/vdpau/gstvdpaudecoder.h index 2c1a274f..5cd83042 100644 --- a/sys/vdpau/gstvdpaudecoder.h +++ b/sys/vdpau/gstvdpaudecoder.h @@ -25,6 +25,7 @@ #include #include +#include #include G_BEGIN_DECLS @@ -43,7 +44,8 @@ typedef struct _VdpauFunctions VdpauFunctions; struct _GstVdpauDecoder { GstElement element; - gchar *display; + gchar *display_name; + Display *display; VdpDevice device; VdpauFunctions *functions; @@ -66,17 +68,22 @@ struct _GstVdpauDecoderClass { }; struct _VdpauFunctions { + VdpDeviceDestroy *vdp_device_destroy; VdpGetProcAddress *vdp_get_proc_address; - + VdpGetErrorString *vdp_get_error_string; + + VdpVideoSurfaceCreate *vdp_video_surface_create; + VdpVideoSurfaceDestroy *vdp_video_surface_destroy; VdpVideoSurfaceQueryCapabilities *vdp_video_surface_query_capabilities; VdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities *vdp_video_surface_query_ycbcr_capabilities; + VdpVideoSurfaceGetParameters *vdp_video_surface_get_parameters; VdpVideoSurfaceGetBitsYCbCr *vdp_video_surface_get_bits_ycbcr; - VdpDeviceDestroy *vdp_device_destroy; - VdpDecoderCreate *vdp_decoder_create; VdpDecoderDestroy *vdp_decoder_destroy; VdpDecoderRender *vdp_decoder_render; + VdpDecoderQueryCapabilities *vdp_decoder_query_capabilities; + VdpDecoderGetParameters *vdp_decoder_get_parameters; }; GType gst_vdpaudecoder_get_type (void); diff --git a/sys/vdpau/gstvdpaumpegdecoder.c b/sys/vdpau/gstvdpaumpegdecoder.c index e5da459f..6ff9b42a 100644 --- a/sys/vdpau/gstvdpaumpegdecoder.c +++ b/sys/vdpau/gstvdpaumpegdecoder.c @@ -104,13 +104,16 @@ gst_vdpau_mpeg_decoder_set_caps (GstVdpauDecoder * dec, GstCaps * caps) GstVdpauMpegDecoder *mpeg_dec; GstStructure *structure; gint version; + VdpDecoderProfile profile; + VdpauFunctions *f; + VdpStatus status; mpeg_dec = GST_VDPAU_MPEG_DECODER (dec); structure = gst_caps_get_structure (caps, 0); gst_structure_get_int (structure, "mpegversion", &version); if (version == 1) - mpeg_dec->profile = VDP_DECODER_PROFILE_MPEG1; + profile = VDP_DECODER_PROFILE_MPEG1; else { const GValue *value; @@ -123,14 +126,24 @@ gst_vdpau_mpeg_decoder_set_caps (GstVdpauDecoder * dec, GstCaps * caps) GST_BUFFER_DATA (codec_data) + GST_BUFFER_SIZE (codec_data)); switch (hdr.profile) { case 5: - mpeg_dec->profile = VDP_DECODER_PROFILE_MPEG2_SIMPLE; + profile = VDP_DECODER_PROFILE_MPEG2_SIMPLE; break; default: - mpeg_dec->profile = VDP_DECODER_PROFILE_MPEG2_MAIN; + profile = VDP_DECODER_PROFILE_MPEG2_MAIN; break; } } + f = dec->functions; + status = f->vdp_decoder_create (dec->device, profile, dec->width, + dec->height, 2, &mpeg_dec->decoder); + if (status != VDP_STATUS_OK) { + GST_ELEMENT_ERROR (mpeg_dec, RESOURCE, READ, + ("Could not create vdpau decoder"), + ("Error returned from vdpau was: %s", + f->vdp_get_error_string (status))); + return FALSE; + } return TRUE; } @@ -174,10 +187,12 @@ gst_vdpau_mpeg_decoder_class_init (GstVdpauMpegDecoderClass * klass) } static void -gst_vdpau_mpeg_decoder_init (GstVdpauMpegDecoder * filter, +gst_vdpau_mpeg_decoder_init (GstVdpauMpegDecoder * mpeg_dec, GstVdpauMpegDecoderClass * gclass) { - filter->silent = FALSE; + mpeg_dec->silent = FALSE; + + mpeg_dec->decoder = VDP_INVALID_HANDLE; } static void diff --git a/sys/vdpau/gstvdpaumpegdecoder.h b/sys/vdpau/gstvdpaumpegdecoder.h index 830cc671..0207ce31 100644 --- a/sys/vdpau/gstvdpaumpegdecoder.h +++ b/sys/vdpau/gstvdpaumpegdecoder.h @@ -66,7 +66,7 @@ struct _GstVdpauMpegDecoder gboolean silent; - VdpDecoderProfile profile; + VdpDecoder decoder; }; struct _GstVdpauMpegDecoderClass diff --git a/sys/vdpau/mpegutil.c b/sys/vdpau/mpegutil.c index 274fa853..aa77a426 100644 --- a/sys/vdpau/mpegutil.c +++ b/sys/vdpau/mpegutil.c @@ -18,8 +18,41 @@ * Boston, MA 02111-1307, USA. */ +#include + #include "mpegutil.h" +/* default intra quant matrix, in zig-zag order */ +static const guint8 default_intra_quantizer_matrix[64] = { + 8, + 16, 16, + 19, 16, 19, + 22, 22, 22, 22, + 22, 22, 26, 24, 26, + 27, 27, 27, 26, 26, 26, + 26, 27, 27, 27, 29, 29, 29, + 34, 34, 34, 29, 29, 29, 27, 27, + 29, 29, 32, 32, 34, 34, 37, + 38, 37, 35, 35, 34, 35, + 38, 38, 40, 40, 40, + 48, 48, 46, 46, + 56, 56, 58, + 69, 69, + 83 +}; + +guint8 mpeg2_scan[64] = { + /* Zig-Zag scan pattern */ + 0, 1, 8, 16, 9, 2, 3, 10, + 17, 24, 32, 25, 18, 11, 4, 5, + 12, 19, 26, 33, 40, 48, 41, 34, + 27, 20, 13, 6, 7, 14, 21, 28, + 35, 42, 49, 56, 57, 50, 43, 36, + 29, 22, 15, 23, 30, 37, 44, 51, + 58, 59, 52, 45, 38, 31, 39, 46, + 53, 60, 61, 54, 47, 55, 62, 63 +}; + guint8 bits[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; guint32 @@ -133,6 +166,7 @@ mpeg_util_parse_extension_packet (MPEGSeqHdr * hdr, guint8 * data, guint8 * end) /* Parse a Sequence Extension */ guint8 horiz_size_ext, vert_size_ext; guint8 fps_n_ext, fps_d_ext; + gint i, offset; if (G_UNLIKELY ((end - data) < 6)) /* need at least 10 bytes, minus 4 for the start code 000001b5 */ @@ -148,6 +182,23 @@ mpeg_util_parse_extension_packet (MPEGSeqHdr * hdr, guint8 * data, guint8 * end) hdr->fps_d *= (fps_d_ext + 1); hdr->width += (horiz_size_ext << 12); hdr->height += (vert_size_ext << 12); + + if (read_bits (data + 7, 6, 1)) { + for (i = 0; i < 64; i++) + hdr->intra_quantizer_matrix[mpeg2_scan[i]] = + read_bits (data + 7 + i, 7, 8); + offset = 64; + } else + memcpy (hdr->intra_quantizer_matrix, default_intra_quantizer_matrix, + 64); + + if (read_bits (data + 7 + offset, 7, 1)) { + for (i = 0; i < 64; i++) + hdr->non_intra_quantizer_matrix[mpeg2_scan[i]] = + read_bits (data + 8 + offset + i, 0, 8); + } else + memset (hdr->non_intra_quantizer_matrix, 0, 64); + break; } default: @@ -225,3 +276,67 @@ mpeg_util_parse_sequence_hdr (MPEGSeqHdr * hdr, guint8 * data, guint8 * end) return TRUE; } + +gboolean +mpeg_util_parse_picture_hdr (MPEGPictureHdr * hdr, guint8 * data, guint8 * end) +{ + guint32 code; + + if (G_UNLIKELY ((end - data) < 6)) + return FALSE; /* Packet too small */ + + code = GST_READ_UINT32_BE (data); + if (G_UNLIKELY (code != (0x00000100 | MPEG_PACKET_PICTURE))) + return FALSE; + + /* Skip the start code */ + data += 4; + + hdr->pic_type = (data[1] >> 3) & 0x07; + if (hdr->pic_type == 0 || hdr->pic_type > 4) + return FALSE; /* Corrupted picture packet */ + + if (hdr->pic_type == P_FRAME || hdr->pic_type == B_FRAME) { + if (G_UNLIKELY ((end - data) < 7)) + return FALSE; /* packet too small */ + + hdr->full_pel_forward_vector = read_bits (data + 3, 5, 1); + hdr->f_code[0][0] = hdr->f_code[0][1] = read_bits (data + 3, 6, 3); + + if (hdr->pic_type == B_FRAME) { + hdr->full_pel_backward_vector = read_bits (data + 4, 1, 1); + hdr->f_code[1][0] = hdr->f_code[1][1] = read_bits (data + 4, 2, 3); + } + } else { + hdr->full_pel_forward_vector = 0; + hdr->full_pel_backward_vector = 0; + } + + return TRUE; +} + +gboolean +mpeg_util_parse_picture_coding_extension (MPEGPictureExt * ext, guint8 * data, + guint8 * end) +{ + if (G_UNLIKELY ((end - data) < 7)) + return FALSE; /* Packet too small */ + + if (G_UNLIKELY (read_bits (data, 0, 4) != MPEG_PACKET_EXT_PICTURE_CODING)) + return FALSE; + + ext->f_code[0][0] = read_bits (data, 4, 4); + ext->f_code[0][1] = read_bits (data + 1, 0, 4); + ext->f_code[1][0] = read_bits (data + 1, 4, 4); + ext->f_code[1][1] = read_bits (data + 2, 0, 4); + + ext->intra_dc_precision = read_bits (data + 2, 4, 2); + ext->picture_structure = read_bits (data + 2, 6, 2); + ext->top_field_first = read_bits (data + 3, 0, 1); + ext->frame_pred_frame_dct = read_bits (data + 3, 1, 1); + ext->concealment_motion_vectors = read_bits (data + 3, 2, 1); + ext->q_scale_type = read_bits (data + 3, 3, 1); + ext->intra_vlc_format = read_bits (data + 3, 4, 1); + + return TRUE; +} diff --git a/sys/vdpau/mpegutil.h b/sys/vdpau/mpegutil.h index f0f8aca0..929e4fbb 100644 --- a/sys/vdpau/mpegutil.h +++ b/sys/vdpau/mpegutil.h @@ -24,6 +24,8 @@ #include typedef struct MPEGSeqHdr MPEGSeqHdr; +typedef struct MPEGPictureHdr MPEGPictureHdr; +typedef struct MPEGPictureExt MPEGPictureExt; /* Packet ID codes for different packet types we * care about */ @@ -40,6 +42,12 @@ typedef struct MPEGSeqHdr MPEGSeqHdr; #define MPEG_PACKET_EXT_SEQUENCE 0x01 #define MPEG_PACKET_EXT_SEQUENCE_DISPLAY 0x02 #define MPEG_PACKET_EXT_QUANT_MATRIX 0x03 +#define MPEG_PACKET_EXT_PICTURE_CODING 0x08 + +/* frame types */ +#define I_FRAME 1 +#define P_FRAME 2 +#define B_FRAME 3 struct MPEGSeqHdr { @@ -55,9 +63,38 @@ struct MPEGSeqHdr /* mpeg2 decoder profile */ gint profile; + + guint8 intra_quantizer_matrix[64]; + guint8 non_intra_quantizer_matrix[64]; +}; + +struct MPEGPictureHdr +{ + guint8 pic_type; + + guint8 full_pel_forward_vector, full_pel_backward_vector; + + guint8 f_code[2][2]; +}; + +struct MPEGPictureExt +{ + guint8 f_code[2][2]; + + guint8 intra_dc_precision; + guint8 picture_structure; + guint8 top_field_first; + guint8 frame_pred_frame_dct; + guint8 concealment_motion_vectors; + guint8 q_scale_type; + guint8 intra_vlc_format; }; gboolean mpeg_util_parse_sequence_hdr (MPEGSeqHdr *hdr, - guint8 *data, guint8 *end); + guint8 *data, guint8 *end); + +gboolean mpeg_util_parse_picture_hdr (MPEGPictureHdr * hdr, guint8 * data, guint8 * end); + +gboolean mpeg_util_parse_picture_coding_extension (MPEGPictureExt *ext, guint8 *data, guint8 *end); #endif -- cgit v1.2.1 From a727e6a0229823170a89ca79b9f07b79fbc7a061 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Tue, 31 Mar 2009 22:53:40 +0200 Subject: vdpau: MPEG1 decoding know gives recognizable output --- sys/vdpau/Makefile.am | 3 +- sys/vdpau/gstvdpaudecoder.c | 144 ++++++++++++++++++--- sys/vdpau/gstvdpaudecoder.h | 7 +- sys/vdpau/gstvdpaumpegdecoder.c | 272 ++++++++++++++++++++++++++++++++++++++-- sys/vdpau/gstvdpaumpegdecoder.h | 10 ++ sys/vdpau/mpegutil.c | 131 ++++++++++++++----- sys/vdpau/mpegutil.h | 23 ++++ 7 files changed, 529 insertions(+), 61 deletions(-) diff --git a/sys/vdpau/Makefile.am b/sys/vdpau/Makefile.am index b786be0d..ef43e5fd 100644 --- a/sys/vdpau/Makefile.am +++ b/sys/vdpau/Makefile.am @@ -6,7 +6,8 @@ libgstvdpau_la_SOURCES = \ mpegutil.c libgstvdpau_la_CFLAGS = $(GST_CFLAGS) $(X11_CFLAGS) -Ivdpau -libgstvdpau_la_LIBADD = $(GST_LIBS) $(X11_LIBS) -lvdpau +libgstvdpau_la_LIBADD = $(GST_LIBS) $(GST_BASE_LIBS) \ + $(GST_PLUGINS_BASE) $(X11_LIBS) -lgstvideo-$(GST_MAJORMINOR) -lvdpau libgstvdpau_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) libgstvdpau_la_LIBTOOLFLAGS = --tag=disable-static diff --git a/sys/vdpau/gstvdpaudecoder.c b/sys/vdpau/gstvdpaudecoder.c index c13b0173..fb2ce627 100644 --- a/sys/vdpau/gstvdpaudecoder.c +++ b/sys/vdpau/gstvdpaudecoder.c @@ -24,7 +24,7 @@ #endif #include -#include +#include #include "gstvdpaudecoder.h" #include @@ -64,11 +64,12 @@ static void gst_vdpaudecoder_set_property (GObject * object, guint prop_id, static void gst_vdpaudecoder_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); -gboolean -gst_vdpaudecoder_push_video_surface (GstVdpauDecoder * dec, +GstFlowReturn +gst_vdpau_decoder_push_video_surface (GstVdpauDecoder * dec, VdpVideoSurface surface) { VdpauFunctions *f; + GstBuffer *buffer; f = dec->functions; @@ -77,34 +78,98 @@ gst_vdpaudecoder_push_video_surface (GstVdpauDecoder * dec, { gint size; GstFlowReturn result; - GstBuffer *buffer; VdpStatus status; guint8 *data[3]; + guint32 stride[3]; - size = dec->height * dec->width + dec->height * dec->width / 2; + size = + gst_video_format_get_size (GST_VIDEO_FORMAT_YV12, dec->width, + dec->height); result = gst_pad_alloc_buffer_and_set_caps (dec->src, GST_BUFFER_OFFSET_NONE, size, GST_PAD_CAPS (dec->src), &buffer); if (G_UNLIKELY (result != GST_FLOW_OK)) - return FALSE; - - data[0] = GST_BUFFER_DATA (buffer); - data[1] = data[0] + dec->height * dec->width; - data[2] = data[1] + dec->height * dec->width / 4; + return result; + + + data[0] = GST_BUFFER_DATA (buffer) + + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_YV12, + 0, dec->width, dec->height); + data[1] = data[0] + + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_YV12, + 2, dec->width, dec->height); + data[2] = data[0] + + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_YV12, + 1, dec->width, dec->height); + + stride[0] = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_YV12, + 0, dec->width); + stride[1] = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_YV12, + 2, dec->width); + stride[2] = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_YV12, + 1, dec->width); status = f->vdp_video_surface_get_bits_ycbcr (surface, VDP_YCBCR_FORMAT_YV12, - (void *) data, NULL); - if (G_UNLIKELY (status != VDP_STATUS_OK)) - return FALSE; + (void *) data, stride); + if (G_UNLIKELY (status != VDP_STATUS_OK)) { + GST_ELEMENT_ERROR (dec, RESOURCE, READ, + ("Couldn't get data from vdpau"), + ("Error returned from vdpau was: %s", + f->vdp_get_error_string (status))); + return GST_FLOW_ERROR; + } + break; + } + case GST_MAKE_FOURCC ('N', 'V', '1', '2'): + { + gint size; + GstFlowReturn result; + VdpStatus status; + guint8 *data[2]; + guint32 stride[2]; + + size = dec->width * dec->height + dec->width * dec->height / 2; + result = + gst_pad_alloc_buffer_and_set_caps (dec->src, GST_BUFFER_OFFSET_NONE, + size, GST_PAD_CAPS (dec->src), &buffer); + if (G_UNLIKELY (result != GST_FLOW_OK)) + return result; + + + data[0] = GST_BUFFER_DATA (buffer); + data[1] = data[0] + dec->width * dec->height; + stride[0] = dec->width; + stride[1] = dec->width; + + status = + f->vdp_video_surface_get_bits_ycbcr (surface, VDP_YCBCR_FORMAT_NV12, + (void *) data, stride); + if (G_UNLIKELY (status != VDP_STATUS_OK)) { + GST_ELEMENT_ERROR (dec, RESOURCE, READ, + ("Couldn't get data from vdpau"), + ("Error returned from vdpau was: %s", + f->vdp_get_error_string (status))); + return GST_FLOW_ERROR; + } break; } default: break; } - return TRUE; + GST_BUFFER_TIMESTAMP (buffer) = + gst_util_uint64_scale_int (GST_SECOND * dec->frame_nr, + dec->framerate_denominator, dec->framerate_numerator); + GST_BUFFER_DURATION (buffer) = + gst_util_uint64_scale_int (GST_SECOND, dec->framerate_denominator, + dec->framerate_numerator); + GST_BUFFER_OFFSET (buffer) = dec->frame_nr; + dec->frame_nr++; + GST_BUFFER_OFFSET_END (buffer) = dec->frame_nr; + + return gst_pad_push (dec->src, buffer); } typedef struct @@ -149,6 +214,38 @@ static VdpauFormats formats[6] = { } }; +VdpVideoSurface +gst_vdpau_decoder_create_video_surface (GstVdpauDecoder * dec) +{ + VdpauFunctions *f; + VdpChromaType chroma_type; + gint i; + VdpStatus status; + VdpVideoSurface surface; + + f = dec->functions; + + chroma_type = VDP_CHROMA_TYPE_422; + for (i = 0; i < 6; i++) { + if (formats[i].fourcc == dec->format) { + chroma_type = formats[i].chroma_type; + break; + } + } + + status = f->vdp_video_surface_create (dec->device, chroma_type, dec->width, + dec->height, &surface); + if (status != VDP_STATUS_OK) { + GST_ELEMENT_ERROR (dec, RESOURCE, READ, + ("Couldn't create a VdpVideoSurface"), + ("Error returned from vdpau was: %s", + f->vdp_get_error_string (status))); + return VDP_INVALID_HANDLE; + } + + return surface; +} + static GstCaps * gst_vdpaudecoder_get_vdpau_support (GstVdpauDecoder * dec) { @@ -355,6 +452,7 @@ gst_vdpaudecoder_sink_set_caps (GstPad * pad, GstCaps * caps) GstStructure *structure; gint width, height; gint framerate_numerator, framerate_denominator; + gint par_numerator, par_denominator; guint32 fourcc_format; gboolean res; @@ -363,21 +461,25 @@ gst_vdpaudecoder_sink_set_caps (GstPad * pad, GstCaps * caps) gst_structure_get_int (structure, "height", &height); gst_structure_get_fraction (structure, "framerate", &framerate_numerator, &framerate_denominator); + gst_structure_get_fraction (structure, "pixel-aspect-ratio", + &par_numerator, &par_denominator); src_caps = gst_pad_get_allowed_caps (dec->src); if (G_UNLIKELY (!src_caps)) return FALSE; - structure = gst_caps_get_structure (src_caps, 0); + new_caps = gst_caps_copy_nth (src_caps, 0); + gst_caps_unref (src_caps); + structure = gst_caps_get_structure (new_caps, 0); gst_structure_get_fourcc (structure, "format", &fourcc_format); gst_structure_set (structure, "width", G_TYPE_INT, width, "height", G_TYPE_INT, height, "framerate", GST_TYPE_FRACTION, framerate_numerator, - framerate_denominator, NULL); + framerate_denominator, + "pixel-aspect-ratio", GST_TYPE_FRACTION, par_numerator, + par_denominator, NULL); - new_caps = gst_caps_copy_nth (src_caps, 0); - gst_caps_unref (src_caps); gst_pad_fixate_caps (dec->src, new_caps); res = gst_pad_set_caps (dec->src, new_caps); @@ -388,6 +490,8 @@ gst_vdpaudecoder_sink_set_caps (GstPad * pad, GstCaps * caps) dec->width = width; dec->height = height; + dec->framerate_numerator = framerate_numerator; + dec->framerate_denominator = framerate_denominator; dec->format = fourcc_format; if (dec_class->set_caps && !dec_class->set_caps (dec, caps)) @@ -464,8 +568,12 @@ gst_vdpaudecoder_init (GstVdpauDecoder * dec, GstVdpauDecoderClass * klass) dec->height = 0; dec->width = 0; + dec->framerate_numerator = 0; + dec->framerate_denominator = 0; dec->format = 0; + dec->frame_nr = 0; + dec->functions = g_slice_new0 (VdpauFunctions); dec->src = gst_pad_new_from_static_template (&src_template, "src"); diff --git a/sys/vdpau/gstvdpaudecoder.h b/sys/vdpau/gstvdpaudecoder.h index 5cd83042..3ab3c9f3 100644 --- a/sys/vdpau/gstvdpaudecoder.h +++ b/sys/vdpau/gstvdpaudecoder.h @@ -56,8 +56,11 @@ struct _GstVdpauDecoder { GstCaps *src_caps; gint width, height; + gint framerate_numerator, framerate_denominator; guint32 format; + gint frame_nr; + gboolean silent; }; @@ -88,7 +91,9 @@ struct _VdpauFunctions { GType gst_vdpaudecoder_get_type (void); -gboolean gst_vdpaudecoder_push_video_surface (GstVdpauDecoder * dec, VdpVideoSurface surface); +gboolean gst_vdpau_decoder_push_video_surface (GstVdpauDecoder * dec, + VdpVideoSurface surface); +VdpVideoSurface gst_vdpau_decoder_create_video_surface (GstVdpauDecoder *dec); G_END_DECLS diff --git a/sys/vdpau/gstvdpaumpegdecoder.c b/sys/vdpau/gstvdpaumpegdecoder.c index 6ff9b42a..6f75181b 100644 --- a/sys/vdpau/gstvdpaumpegdecoder.c +++ b/sys/vdpau/gstvdpaumpegdecoder.c @@ -59,6 +59,7 @@ #endif #include +#include #include "mpegutil.h" #include "gstvdpaumpegdecoder.h" @@ -103,7 +104,9 @@ gst_vdpau_mpeg_decoder_set_caps (GstVdpauDecoder * dec, GstCaps * caps) { GstVdpauMpegDecoder *mpeg_dec; GstStructure *structure; - gint version; + const GValue *value; + GstBuffer *codec_data; + MPEGSeqHdr hdr = { 0, }; VdpDecoderProfile profile; VdpauFunctions *f; VdpStatus status; @@ -111,19 +114,15 @@ gst_vdpau_mpeg_decoder_set_caps (GstVdpauDecoder * dec, GstCaps * caps) mpeg_dec = GST_VDPAU_MPEG_DECODER (dec); structure = gst_caps_get_structure (caps, 0); - gst_structure_get_int (structure, "mpegversion", &version); - if (version == 1) + gst_structure_get_int (structure, "mpegversion", &mpeg_dec->version); + if (mpeg_dec->version == 1) profile = VDP_DECODER_PROFILE_MPEG1; - else { - const GValue *value; - GstBuffer *codec_data; - MPEGSeqHdr hdr = { 0, }; - - value = gst_structure_get_value (structure, "codec_data"); - codec_data = gst_value_get_buffer (value); - mpeg_util_parse_sequence_hdr (&hdr, GST_BUFFER_DATA (codec_data), - GST_BUFFER_DATA (codec_data) + GST_BUFFER_SIZE (codec_data)); + value = gst_structure_get_value (structure, "codec_data"); + codec_data = gst_value_get_buffer (value); + mpeg_util_parse_sequence_hdr (&hdr, GST_BUFFER_DATA (codec_data), + GST_BUFFER_DATA (codec_data) + GST_BUFFER_SIZE (codec_data)); + if (mpeg_dec->version != 1) { switch (hdr.profile) { case 5: profile = VDP_DECODER_PROFILE_MPEG2_SIMPLE; @@ -133,6 +132,10 @@ gst_vdpau_mpeg_decoder_set_caps (GstVdpauDecoder * dec, GstCaps * caps) break; } } + memcpy (&mpeg_dec->vdp_info.intra_quantizer_matrix, + &hdr.intra_quantizer_matrix, 64); + memcpy (&mpeg_dec->vdp_info.non_intra_quantizer_matrix, + &hdr.non_intra_quantizer_matrix, 64); f = dec->functions; status = f->vdp_decoder_create (dec->device, profile, dec->width, @@ -147,6 +150,228 @@ gst_vdpau_mpeg_decoder_set_caps (GstVdpauDecoder * dec, GstCaps * caps) return TRUE; } +static GstFlowReturn +gst_vdpau_mpeg_decoder_decode (GstVdpauMpegDecoder * mpeg_dec) +{ + GstVdpauDecoder *dec; + GstBuffer *buffer; + VdpVideoSurface surface; + VdpauFunctions *f; + VdpBitstreamBuffer vbit[1]; + VdpStatus status; + GstFlowReturn ret; + + dec = GST_VDPAU_DECODER (mpeg_dec); + + buffer = gst_adapter_take_buffer (mpeg_dec->adapter, + gst_adapter_available (mpeg_dec->adapter)); + + if (mpeg_dec->vdp_info.picture_coding_type == P_FRAME) { + mpeg_dec->p_buffer = buffer; + } + + surface = + gst_vdpau_decoder_create_video_surface (GST_VDPAU_DECODER (mpeg_dec)); + + f = dec->functions; + + vbit[0].struct_version = VDP_BITSTREAM_BUFFER_VERSION; + vbit[0].bitstream = GST_BUFFER_DATA (buffer); + vbit[0].bitstream_bytes = GST_BUFFER_SIZE (buffer); + + status = f->vdp_decoder_render (mpeg_dec->decoder, surface, + (VdpPictureInfo *) & mpeg_dec->vdp_info, 1, vbit); + gst_buffer_unref (buffer); + mpeg_dec->vdp_info.slice_count = 0; + + if (status != VDP_STATUS_OK) { + GST_ELEMENT_ERROR (mpeg_dec, RESOURCE, READ, + ("Could not decode"), + ("Error returned from vdpau was: %s", + f->vdp_get_error_string (status))); + + if (mpeg_dec->vdp_info.forward_reference != VDP_INVALID_HANDLE) + f->vdp_video_surface_destroy (mpeg_dec->vdp_info.forward_reference); + + f->vdp_video_surface_destroy (surface); + + return GST_FLOW_ERROR; + } + + ret = + gst_vdpau_decoder_push_video_surface (GST_VDPAU_DECODER (mpeg_dec), + surface); + + if (mpeg_dec->vdp_info.forward_reference != VDP_INVALID_HANDLE) + f->vdp_video_surface_destroy (mpeg_dec->vdp_info.forward_reference); + + mpeg_dec->vdp_info.forward_reference = surface; + + return ret; +} + +static gboolean +gst_vdpau_mpeg_decoder_parse_picture_coding (GstVdpauMpegDecoder * mpeg_dec, + guint8 * data, guint8 * end) +{ + GstVdpauDecoder *dec; + MPEGPictureExt pic_ext; + VdpPictureInfoMPEG1Or2 *info; + + dec = GST_VDPAU_DECODER (mpeg_dec); + info = &mpeg_dec->vdp_info; + + if (!mpeg_util_parse_picture_coding_extension (&pic_ext, data, end)) + return FALSE; + + memcpy (&mpeg_dec->vdp_info.f_code, &pic_ext.f_code, 4); + + info->intra_dc_precision = pic_ext.intra_dc_precision; + info->picture_structure = pic_ext.picture_structure; + info->top_field_first = pic_ext.top_field_first; + info->frame_pred_frame_dct = pic_ext.frame_pred_frame_dct; + info->concealment_motion_vectors = pic_ext.concealment_motion_vectors; + info->q_scale_type = pic_ext.q_scale_type; + info->intra_vlc_format = pic_ext.intra_vlc_format; + + return TRUE; +} + +static gboolean +gst_vdpau_mpeg_decoder_parse_picture (GstVdpauMpegDecoder * mpeg_dec, + guint8 * data, guint8 * end) +{ + GstVdpauDecoder *dec; + MPEGPictureHdr pic_hdr; + + dec = GST_VDPAU_DECODER (mpeg_dec); + + if (!mpeg_util_parse_picture_hdr (&pic_hdr, data, end)) + return FALSE; + + mpeg_dec->vdp_info.picture_coding_type = pic_hdr.pic_type; + + + if (pic_hdr.pic_type == I_FRAME && + mpeg_dec->vdp_info.forward_reference != VDP_INVALID_HANDLE) { + dec->functions->vdp_video_surface_destroy (mpeg_dec->vdp_info. + forward_reference); + mpeg_dec->vdp_info.forward_reference = VDP_INVALID_HANDLE; + } + + if (mpeg_dec->version == 1) { + mpeg_dec->vdp_info.full_pel_forward_vector = + pic_hdr.full_pel_forward_vector; + mpeg_dec->vdp_info.full_pel_backward_vector = + pic_hdr.full_pel_backward_vector; + memcpy (&mpeg_dec->vdp_info.f_code, &pic_hdr.f_code, 4); + } + + return TRUE; +} + +static gboolean +gst_vdpau_mpeg_decoder_parse_gop (GstVdpauMpegDecoder * mpeg_dec, guint8 * data, + guint8 * end) +{ + MPEGPictureGOP gop; + + if (!mpeg_util_parse_picture_gop (&gop, data, end)) + return FALSE; + + return TRUE; +} + +static gboolean +gst_vdpau_mpeg_decoder_parse_quant_matrix (GstVdpauMpegDecoder * mpeg_dec, + guint8 * data, guint8 * end) +{ + MPEGQuantMatrix qm; + + if (!mpeg_util_parse_quant_matrix (&qm, data, end)) + return FALSE; + + memcpy (&mpeg_dec->vdp_info.intra_quantizer_matrix, + &qm.intra_quantizer_matrix, 64); + memcpy (&mpeg_dec->vdp_info.non_intra_quantizer_matrix, + &qm.non_intra_quantizer_matrix, 64); + return TRUE; +} + +static GstFlowReturn +gst_vdpau_mpeg_decoder_chain (GstPad * pad, GstBuffer * buffer) +{ + GstVdpauMpegDecoder *mpeg_dec; + guint8 *data, *end; + guint32 sync_word = 0xffffffff; + + mpeg_dec = GST_VDPAU_MPEG_DECODER (GST_OBJECT_PARENT (pad)); + + data = GST_BUFFER_DATA (buffer); + end = GST_BUFFER_DATA (buffer) + GST_BUFFER_SIZE (buffer); + + while ((data = mpeg_util_find_start_code (&sync_word, data, end))) { + guint8 *packet_start; + guint8 *packet_end; + + packet_start = data - 3; + packet_end = mpeg_util_find_start_code (&sync_word, data, end); + if (packet_end) + packet_end -= 3; + else + packet_end = end; + + if (data[0] >= MPEG_PACKET_SLICE_MIN && data[0] <= MPEG_PACKET_SLICE_MAX) { + GstBuffer *subbuf; + + GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_SLICE"); + subbuf = + gst_buffer_create_sub (buffer, + packet_start - GST_BUFFER_DATA (buffer), packet_end - packet_start); + gst_adapter_push (mpeg_dec->adapter, subbuf); + mpeg_dec->vdp_info.slice_count++; + } else if (mpeg_dec->vdp_info.slice_count > 0) { + if (gst_vdpau_mpeg_decoder_decode (mpeg_dec) != GST_FLOW_OK) + return GST_FLOW_ERROR; + } + + switch (data[0]) { + case MPEG_PACKET_PICTURE: + GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_PICTURE"); + gst_vdpau_mpeg_decoder_parse_picture (mpeg_dec, packet_start, + packet_end); + break; + case MPEG_PACKET_SEQUENCE: + GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_SEQUENCE"); + break; + case MPEG_PACKET_EXTENSION: + GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_EXTENSION"); + switch (read_bits (data + 1, 0, 4)) { + case MPEG_PACKET_EXT_PICTURE_CODING: + gst_vdpau_mpeg_decoder_parse_picture_coding (mpeg_dec, packet_start, + packet_end); + break; + default: + break; + } + break; + case MPEG_PACKET_EXT_QUANT_MATRIX: + GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_EXT_QUANT_MATRIX"); + gst_vdpau_mpeg_decoder_parse_quant_matrix (mpeg_dec, packet_start, + packet_end); + break; + case MPEG_PACKET_GOP: + GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_GOP"); + gst_vdpau_mpeg_decoder_parse_gop (mpeg_dec, packet_start, packet_end); + break; + default: + break; + } + } + + return GST_FLOW_OK; +} + /* GObject vmethod implementations */ static void @@ -186,13 +411,34 @@ gst_vdpau_mpeg_decoder_class_init (GstVdpauMpegDecoderClass * klass) vdpaudec_class->set_caps = gst_vdpau_mpeg_decoder_set_caps; } +static void +gst_vdpau_mpeg_decoder_init_info (VdpPictureInfoMPEG1Or2 * vdp_info) +{ + vdp_info->forward_reference = VDP_INVALID_HANDLE; + vdp_info->backward_reference = VDP_INVALID_HANDLE; + vdp_info->slice_count = 0; + vdp_info->picture_structure = 0; + vdp_info->picture_coding_type = 0; + vdp_info->intra_dc_precision = 0; + vdp_info->frame_pred_frame_dct = 0; + vdp_info->concealment_motion_vectors = 0; +} + static void gst_vdpau_mpeg_decoder_init (GstVdpauMpegDecoder * mpeg_dec, GstVdpauMpegDecoderClass * gclass) { - mpeg_dec->silent = FALSE; + GstVdpauDecoder *dec; + + dec = GST_VDPAU_DECODER (mpeg_dec); + mpeg_dec->silent = FALSE; mpeg_dec->decoder = VDP_INVALID_HANDLE; + gst_vdpau_mpeg_decoder_init_info (&mpeg_dec->vdp_info); + + mpeg_dec->adapter = gst_adapter_new (); + + gst_pad_set_chain_function (dec->sink, gst_vdpau_mpeg_decoder_chain); } static void diff --git a/sys/vdpau/gstvdpaumpegdecoder.h b/sys/vdpau/gstvdpaumpegdecoder.h index 0207ce31..36c02534 100644 --- a/sys/vdpau/gstvdpaumpegdecoder.h +++ b/sys/vdpau/gstvdpaumpegdecoder.h @@ -45,6 +45,7 @@ #define __GST_VDPAU_MPEG_DECODER_H__ #include +#include #include "gstvdpaudecoder.h" @@ -66,7 +67,16 @@ struct _GstVdpauMpegDecoder gboolean silent; + gint version; + VdpDecoder decoder; + VdpPictureInfoMPEG1Or2 vdp_info; + + GstAdapter *adapter; + gint slices; + + GstBuffer *p_buffer; + VdpPictureInfoMPEG1Or2 p_vdp_info; }; struct _GstVdpauMpegDecoderClass diff --git a/sys/vdpau/mpegutil.c b/sys/vdpau/mpegutil.c index aa77a426..8bba8d1f 100644 --- a/sys/vdpau/mpegutil.c +++ b/sys/vdpau/mpegutil.c @@ -166,7 +166,6 @@ mpeg_util_parse_extension_packet (MPEGSeqHdr * hdr, guint8 * data, guint8 * end) /* Parse a Sequence Extension */ guint8 horiz_size_ext, vert_size_ext; guint8 fps_n_ext, fps_d_ext; - gint i, offset; if (G_UNLIKELY ((end - data) < 6)) /* need at least 10 bytes, minus 4 for the start code 000001b5 */ @@ -182,23 +181,6 @@ mpeg_util_parse_extension_packet (MPEGSeqHdr * hdr, guint8 * data, guint8 * end) hdr->fps_d *= (fps_d_ext + 1); hdr->width += (horiz_size_ext << 12); hdr->height += (vert_size_ext << 12); - - if (read_bits (data + 7, 6, 1)) { - for (i = 0; i < 64; i++) - hdr->intra_quantizer_matrix[mpeg2_scan[i]] = - read_bits (data + 7 + i, 7, 8); - offset = 64; - } else - memcpy (hdr->intra_quantizer_matrix, default_intra_quantizer_matrix, - 64); - - if (read_bits (data + 7 + offset, 7, 1)) { - for (i = 0; i < 64; i++) - hdr->non_intra_quantizer_matrix[mpeg2_scan[i]] = - read_bits (data + 8 + offset + i, 0, 8); - } else - memset (hdr->non_intra_quantizer_matrix, 0, 64); - break; } default: @@ -217,6 +199,7 @@ mpeg_util_parse_sequence_hdr (MPEGSeqHdr * hdr, guint8 * data, guint8 * end) gboolean constrained_flag; gboolean load_intra_flag; gboolean load_non_intra_flag; + gint i; if (G_UNLIKELY ((end - data) < 12)) return FALSE; /* Too small to be a sequence header */ @@ -241,19 +224,29 @@ mpeg_util_parse_sequence_hdr (MPEGSeqHdr * hdr, guint8 * data, guint8 * end) set_fps_from_code (hdr, fps_idx); constrained_flag = (data[7] >> 2) & 0x01; - load_intra_flag = (data[7] >> 1) & 0x01; + + load_intra_flag = read_bits (data + 7, 6, 1); if (load_intra_flag) { if (G_UNLIKELY ((end - data) < 64)) return FALSE; + for (i = 0; i < 64; i++) { + hdr->intra_quantizer_matrix[mpeg2_scan[i]] = + read_bits (data + 7 + i, 7, 8); + } data += 64; - } - load_non_intra_flag = data[7] & 0x01; + } else + memcpy (hdr->intra_quantizer_matrix, default_intra_quantizer_matrix, 64); + + load_non_intra_flag = read_bits (data + 7, 7 + load_intra_flag, 1); if (load_non_intra_flag) { if (G_UNLIKELY ((end - data) < 64)) return FALSE; - data += 64; - } + for (i = 0; i < 64; i++) + hdr->non_intra_quantizer_matrix[mpeg2_scan[i]] = + read_bits (data + 8 + i, 1 + load_intra_flag, 8); + } else + memset (hdr->non_intra_quantizer_matrix, 16, 64); /* Advance past the rest of the MPEG-1 header */ data += 8; @@ -282,14 +275,14 @@ mpeg_util_parse_picture_hdr (MPEGPictureHdr * hdr, guint8 * data, guint8 * end) { guint32 code; - if (G_UNLIKELY ((end - data) < 6)) + if (G_UNLIKELY ((end - data) < 8)) return FALSE; /* Packet too small */ code = GST_READ_UINT32_BE (data); if (G_UNLIKELY (code != (0x00000100 | MPEG_PACKET_PICTURE))) return FALSE; - /* Skip the start code */ + /* Skip the sync word */ data += 4; hdr->pic_type = (data[1] >> 3) & 0x07; @@ -297,7 +290,7 @@ mpeg_util_parse_picture_hdr (MPEGPictureHdr * hdr, guint8 * data, guint8 * end) return FALSE; /* Corrupted picture packet */ if (hdr->pic_type == P_FRAME || hdr->pic_type == B_FRAME) { - if (G_UNLIKELY ((end - data) < 7)) + if (G_UNLIKELY ((end - data) < 5)) return FALSE; /* packet too small */ hdr->full_pel_forward_vector = read_bits (data + 3, 5, 1); @@ -319,12 +312,19 @@ gboolean mpeg_util_parse_picture_coding_extension (MPEGPictureExt * ext, guint8 * data, guint8 * end) { - if (G_UNLIKELY ((end - data) < 7)) + guint32 code; + + if (G_UNLIKELY ((end - data) < 10)) return FALSE; /* Packet too small */ - if (G_UNLIKELY (read_bits (data, 0, 4) != MPEG_PACKET_EXT_PICTURE_CODING)) + code = GST_READ_UINT32_BE (data); + + if (G_UNLIKELY (G_UNLIKELY (code != (0x00000100 | MPEG_PACKET_EXTENSION)))) return FALSE; + /* Skip the sync word */ + data += 4; + ext->f_code[0][0] = read_bits (data, 4, 4); ext->f_code[0][1] = read_bits (data + 1, 0, 4); ext->f_code[1][0] = read_bits (data + 1, 4, 4); @@ -340,3 +340,78 @@ mpeg_util_parse_picture_coding_extension (MPEGPictureExt * ext, guint8 * data, return TRUE; } + +gboolean +mpeg_util_parse_picture_gop (MPEGPictureGOP * gop, guint8 * data, guint8 * end) +{ + guint32 code; + gint hour, minute, second; + + if (G_UNLIKELY ((end - data) < 8)) + return FALSE; /* Packet too small */ + + code = GST_READ_UINT32_BE (data); + + if (G_UNLIKELY (G_UNLIKELY (code != (0x00000100 | MPEG_PACKET_GOP)))) + return FALSE; + + /* Skip the sync word */ + data += 4; + + gop->drop_frame_flag = read_bits (data, 0, 1); + + hour = read_bits (data, 1, 5); + minute = read_bits (data, 6, 6); + second = read_bits (data + 1, 4, 6); + + gop->timestamp = hour * 3600 * GST_SECOND; + gop->timestamp += minute * 60 * GST_SECOND; + gop->timestamp += second * GST_SECOND; + + gop->frame = read_bits (data + 2, 3, 6); + + return TRUE; +} + +gboolean +mpeg_util_parse_quant_matrix (MPEGQuantMatrix * qm, guint8 * data, guint8 * end) +{ + guint32 code; + gboolean load_intra_flag, load_non_intra_flag; + gint i; + + if (G_UNLIKELY ((end - data) < 5)) + return FALSE; /* Packet too small */ + + code = GST_READ_UINT32_BE (data); + + if (G_UNLIKELY (G_UNLIKELY (code != (0x00000100 | MPEG_PACKET_GOP)))) + return FALSE; + + /* Skip the sync word */ + data += 4; + + load_intra_flag = read_bits (data, 0, 1); + if (load_intra_flag) { + if (G_UNLIKELY ((end - data) < 64)) + return FALSE; + for (i = 0; i < 64; i++) { + qm->intra_quantizer_matrix[mpeg2_scan[i]] = read_bits (data + i, 1, 8); + } + data += 64; + + } else + memcpy (qm->intra_quantizer_matrix, default_intra_quantizer_matrix, 64); + + load_non_intra_flag = read_bits (data, 1 + load_intra_flag, 1); + if (load_non_intra_flag) { + if (G_UNLIKELY ((end - data) < 64)) + return FALSE; + for (i = 0; i < 64; i++) + qm->non_intra_quantizer_matrix[mpeg2_scan[i]] = + read_bits (data + i, 2 + load_intra_flag, 8); + } else + memset (qm->non_intra_quantizer_matrix, 16, 64); + + return TRUE; +} diff --git a/sys/vdpau/mpegutil.h b/sys/vdpau/mpegutil.h index 929e4fbb..5fb47290 100644 --- a/sys/vdpau/mpegutil.h +++ b/sys/vdpau/mpegutil.h @@ -26,6 +26,8 @@ typedef struct MPEGSeqHdr MPEGSeqHdr; typedef struct MPEGPictureHdr MPEGPictureHdr; typedef struct MPEGPictureExt MPEGPictureExt; +typedef struct MPEGPictureGOP MPEGPictureGOP; +typedef struct MPEGQuantMatrix MPEGQuantMatrix; /* Packet ID codes for different packet types we * care about */ @@ -90,6 +92,20 @@ struct MPEGPictureExt guint8 intra_vlc_format; }; +struct MPEGPictureGOP +{ + guint8 drop_frame_flag; + guint8 frame; + + GstClockTime timestamp; +}; + +struct MPEGQuantMatrix +{ + guint8 intra_quantizer_matrix[64]; + guint8 non_intra_quantizer_matrix[64]; +}; + gboolean mpeg_util_parse_sequence_hdr (MPEGSeqHdr *hdr, guint8 *data, guint8 *end); @@ -97,4 +113,11 @@ gboolean mpeg_util_parse_picture_hdr (MPEGPictureHdr * hdr, guint8 * data, guint gboolean mpeg_util_parse_picture_coding_extension (MPEGPictureExt *ext, guint8 *data, guint8 *end); +gboolean mpeg_util_parse_picture_gop (MPEGPictureGOP * gop, guint8 * data, guint8 * end); + +gboolean mpeg_util_parse_quant_matrix (MPEGQuantMatrix * qm, guint8 * data, guint8 * end); + +guint8 *mpeg_util_find_start_code (guint32 * sync_word, guint8 * cur, guint8 * end); +guint32 read_bits (guint8 * buf, gint start_bit, gint n_bits); + #endif -- cgit v1.2.1 From a22a18d1e7da4ceb7f655e9ea468458ae58ad904 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Tue, 31 Mar 2009 22:54:14 +0200 Subject: vdpau: remove comment --- sys/vdpau/gstvdpaumpegdecoder.h | 1 - 1 file changed, 1 deletion(-) diff --git a/sys/vdpau/gstvdpaumpegdecoder.h b/sys/vdpau/gstvdpaumpegdecoder.h index 36c02534..b7c293ab 100644 --- a/sys/vdpau/gstvdpaumpegdecoder.h +++ b/sys/vdpau/gstvdpaumpegdecoder.h @@ -51,7 +51,6 @@ G_BEGIN_DECLS -/* #defines don't like whitespacey bits */ #define GST_TYPE_VDPAU_MPEG_DECODER (gst_vdpau_mpeg_decoder_get_type()) #define GST_VDPAU_MPEG_DECODER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VDPAU_MPEG_DECODER,GstVdpauMpegDecoder)) #define GST_VDPAU_MPEG_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VDPAU_MPEG_DECODER,GstVdpauMpegDecoderClass)) -- cgit v1.2.1 From f74f44c24f97b03163b854516b025fed8e9b29a3 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Wed, 1 Apr 2009 21:19:18 +0200 Subject: vdpau: add gstvdpaudevice for abstracting vdpau initalization --- sys/vdpau/Makefile.am | 6 +- sys/vdpau/gst-vdpau-device.c | 267 ++++++++++++++++++++++++++++++++++++++++ sys/vdpau/gst-vdpau-device.h | 80 ++++++++++++ sys/vdpau/gstvdpaudecoder.c | 143 ++++----------------- sys/vdpau/gstvdpaudecoder.h | 31 +---- sys/vdpau/gstvdpaumpegdecoder.c | 53 ++------ sys/vdpau/gstvdpaumpegdecoder.h | 25 ---- 7 files changed, 392 insertions(+), 213 deletions(-) create mode 100644 sys/vdpau/gst-vdpau-device.c create mode 100644 sys/vdpau/gst-vdpau-device.h diff --git a/sys/vdpau/Makefile.am b/sys/vdpau/Makefile.am index ef43e5fd..f5a5ed1e 100644 --- a/sys/vdpau/Makefile.am +++ b/sys/vdpau/Makefile.am @@ -1,9 +1,10 @@ plugin_LTLIBRARIES = libgstvdpau.la libgstvdpau_la_SOURCES = \ + gst-vdpau-device.c \ gstvdpaudecoder.c \ gstvdpaumpegdecoder.c \ - mpegutil.c + mpegutil.c \ libgstvdpau_la_CFLAGS = $(GST_CFLAGS) $(X11_CFLAGS) -Ivdpau libgstvdpau_la_LIBADD = $(GST_LIBS) $(GST_BASE_LIBS) \ @@ -12,8 +13,9 @@ libgstvdpau_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) libgstvdpau_la_LIBTOOLFLAGS = --tag=disable-static noinst_HEADERS = \ + gst-vdpau-device.h \ gstvdpaudecoder.h \ gstvdpaumpegdecoder.h \ - mpegutil.h + mpegutil.h diff --git a/sys/vdpau/gst-vdpau-device.c b/sys/vdpau/gst-vdpau-device.c new file mode 100644 index 00000000..ec86ca4e --- /dev/null +++ b/sys/vdpau/gst-vdpau-device.c @@ -0,0 +1,267 @@ +/* + * GStreamer + * Copyright (C) 2009 Carl-Anton Ingmarsson + * + * 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. + */ + +#include +#include + +#include "gst-vdpau-device.h" + +GST_DEBUG_CATEGORY_STATIC (gst_vdpau_device_debug); +#define GST_CAT_DEFAULT gst_vdpau_device_debug + +enum +{ + PROP_0, + + PROP_DISPLAY +}; + + + +G_DEFINE_TYPE (GstVdpauDevice, gst_vdpau_device, G_TYPE_OBJECT); + +static void +gst_vdpau_device_init (GstVdpauDevice * device) +{ + device->display_name = NULL; + device->display = NULL; + device->device = VDP_INVALID_HANDLE; +} + +static void +gst_vdpau_device_finalize (GObject * object) +{ + GstVdpauDevice *device = (GstVdpauDevice *) object; + + device->vdp_device_destroy (device->device); + g_free (device->display_name); + + G_OBJECT_CLASS (gst_vdpau_device_parent_class)->finalize (object); + +} + +static void +gst_vdpau_device_constructed (GObject * object) +{ + GstVdpauDevice *device = (GstVdpauDevice *) object; + gint screen; + VdpStatus status; + gint i; + + typedef struct + { + gint id; + void *func; + } VdpFunction; + + VdpFunction vdp_function[] = { + {VDP_FUNC_ID_DEVICE_DESTROY, &device->vdp_device_destroy}, + {VDP_FUNC_ID_VIDEO_SURFACE_CREATE, + &device->vdp_video_surface_create}, + {VDP_FUNC_ID_VIDEO_SURFACE_DESTROY, + &device->vdp_video_surface_destroy}, + {VDP_FUNC_ID_VIDEO_SURFACE_QUERY_CAPABILITIES, + &device->vdp_video_surface_query_capabilities}, + {VDP_FUNC_ID_VIDEO_SURFACE_QUERY_GET_PUT_BITS_Y_CB_CR_CAPABILITIES, + &device->vdp_video_surface_query_ycbcr_capabilities}, + {VDP_FUNC_ID_VIDEO_SURFACE_GET_BITS_Y_CB_CR, + &device->vdp_video_surface_get_bits_ycbcr}, + {VDP_FUNC_ID_VIDEO_SURFACE_GET_PARAMETERS, + &device->vdp_video_surface_get_parameters}, + {VDP_FUNC_ID_DECODER_CREATE, &device->vdp_decoder_create}, + {VDP_FUNC_ID_DECODER_RENDER, &device->vdp_decoder_render}, + {VDP_FUNC_ID_DECODER_DESTROY, &device->vdp_decoder_destroy}, + {VDP_FUNC_ID_DECODER_QUERY_CAPABILITIES, + &device->vdp_decoder_query_capabilities}, + {VDP_FUNC_ID_DECODER_GET_PARAMETERS, + &device->vdp_decoder_get_parameters}, + {0, NULL} + }; + + /* FIXME: We probably want to use the same VdpDevice for every VDPAU element */ + device->display = XOpenDisplay (device->display_name); + if (!device->display) { + GST_ERROR_OBJECT (device, "Could not open X display with name: %s", + device->display_name); + return; + } + + screen = DefaultScreen (device->display); + status = + vdp_device_create_x11 (device->display, screen, &device->device, + &device->vdp_get_proc_address); + if (status != VDP_STATUS_OK) { + GST_ERROR_OBJECT (device, "Could not create VDPAU device"); + XCloseDisplay (device->display); + device->display = NULL; + + return; + } + + status = device->vdp_get_proc_address (device->device, + VDP_FUNC_ID_GET_ERROR_STRING, (void **) &device->vdp_get_error_string); + if (status != VDP_STATUS_OK) { + GST_ERROR_OBJECT (device, + "Could not get vdp_get_error_string function pointer from VDPAU"); + goto error; + } + + for (i = 0; vdp_function[i].func != NULL; i++) { + status = device->vdp_get_proc_address (device->device, + vdp_function[i].id, vdp_function[i].func); + + if (status != VDP_STATUS_OK) { + GST_ERROR_OBJECT (device, "Could not get function pointer from VDPAU," + " error returned was: %s", device->vdp_get_error_string (status)); + goto error; + } + } + + return; + +error: + XCloseDisplay (device->display); + device->display = NULL; + + if (device->device != VDP_INVALID_HANDLE) { + device->vdp_device_destroy (device->device); + device->device = VDP_INVALID_HANDLE; + } +} + +static void +gst_vdpau_device_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstVdpauDevice *device; + + g_return_if_fail (GST_IS_VDPAU_DEVICE (object)); + + device = (GstVdpauDevice *) object; + + switch (prop_id) { + case PROP_DISPLAY: + device->display_name = g_value_dup_string (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_vdpau_device_get_property (GObject * object, guint prop_id, GValue * value, + GParamSpec * pspec) +{ + GstVdpauDevice *device; + + g_return_if_fail (GST_IS_VDPAU_DEVICE (object)); + + device = (GstVdpauDevice *) object; + + switch (prop_id) { + case PROP_DISPLAY: + g_value_set_string (value, device->display_name); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_vdpau_device_class_init (GstVdpauDeviceClass * klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->constructed = gst_vdpau_device_constructed; + object_class->finalize = gst_vdpau_device_finalize; + object_class->get_property = gst_vdpau_device_get_property; + object_class->set_property = gst_vdpau_device_set_property; + + + g_object_class_install_property (object_class, + PROP_DISPLAY, + g_param_spec_string ("display", + "Display", + "X Display Name", + "", G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); + + GST_DEBUG_CATEGORY_INIT (gst_vdpau_device_debug, "vdpaudevice", + 0, "vdpaudevice"); +} + +GstVdpauDevice * +gst_vdpau_device_new (const gchar * display_name) +{ + GstVdpauDevice *device; + + device = g_object_new (GST_TYPE_VDPAU_DEVICE, "display", display_name); + + return device; +} + +static void +device_destroyed_cb (gpointer data, GObject * object) +{ + GHashTable *devices_hash = data; + GHashTableIter iter; + gpointer device; + + g_hash_table_iter_init (&iter, devices_hash); + while (g_hash_table_iter_next (&iter, NULL, &device)) { + if (device == object) { + g_hash_table_iter_remove (&iter); + break; + } + } +} + +static gpointer +create_devices_hash (gpointer data) +{ + return g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); +} + +GstVdpauDevice * +gst_vdpau_get_device (const gchar * display_name) +{ + static GOnce my_once = G_ONCE_INIT; + GHashTable *devices_hash; + GstVdpauDevice *device; + + g_once (&my_once, create_devices_hash, NULL); + devices_hash = my_once.retval; + + if (display_name) + device = g_hash_table_lookup (devices_hash, display_name); + else + device = g_hash_table_lookup (devices_hash, ""); + + if (!device) { + g_debug ("asdasd"); + device = gst_vdpau_device_new (display_name); + g_object_weak_ref (G_OBJECT (device), device_destroyed_cb, devices_hash); + } else + g_object_ref (device); + + g_debug ("HMM"); + return device; +} diff --git a/sys/vdpau/gst-vdpau-device.h b/sys/vdpau/gst-vdpau-device.h new file mode 100644 index 00000000..0a5cb5e7 --- /dev/null +++ b/sys/vdpau/gst-vdpau-device.h @@ -0,0 +1,80 @@ +/* + * GStreamer + * Copyright (C) 2009 Carl-Anton Ingmarsson + * + * 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_VDPAU_DEVICE_H_ +#define _GST_VDPAU_DEVICE_H_ + +#include +#include + +#include + +G_BEGIN_DECLS + +#define GST_TYPE_VDPAU_DEVICE (gst_vdpau_device_get_type ()) +#define GST_VDPAU_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_VDPAU_DEVICE, GstVdpauDevice)) +#define GST_VDPAU_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_VDPAU_DEVICE, GstVdpauDeviceClass)) +#define GST_IS_VDPAU_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_VDPAU_DEVICE)) +#define GST_IS_VDPAU_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_VDPAU_DEVICE)) +#define GST_VDPAU_DEVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_VDPAU_DEVICE, GstVdpauDeviceClass)) + +typedef struct _GstVdpauDeviceClass GstVdpauDeviceClass; +typedef struct _GstVdpauDevice GstVdpauDevice; + +struct _GstVdpauDeviceClass +{ + GObjectClass parent_class; +}; + +struct _GstVdpauDevice +{ + GObject object; + + gchar *display_name; + Display *display; + VdpDevice device; + + VdpDeviceDestroy *vdp_device_destroy; + VdpGetProcAddress *vdp_get_proc_address; + VdpGetErrorString *vdp_get_error_string; + + VdpVideoSurfaceCreate *vdp_video_surface_create; + VdpVideoSurfaceDestroy *vdp_video_surface_destroy; + VdpVideoSurfaceQueryCapabilities *vdp_video_surface_query_capabilities; + VdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities *vdp_video_surface_query_ycbcr_capabilities; + VdpVideoSurfaceGetParameters *vdp_video_surface_get_parameters; + VdpVideoSurfaceGetBitsYCbCr *vdp_video_surface_get_bits_ycbcr; + + VdpDecoderCreate *vdp_decoder_create; + VdpDecoderDestroy *vdp_decoder_destroy; + VdpDecoderRender *vdp_decoder_render; + VdpDecoderQueryCapabilities *vdp_decoder_query_capabilities; + VdpDecoderGetParameters *vdp_decoder_get_parameters; +}; + +GType gst_vdpau_device_get_type (void) G_GNUC_CONST; + +GstVdpauDevice *gst_vdpau_device_new (const gchar *display_name); + +GstVdpauDevice *gst_vdpau_get_device (const gchar *display_name); + +G_END_DECLS + +#endif /* _GST_VDPAU_DEVICE_H_ */ diff --git a/sys/vdpau/gstvdpaudecoder.c b/sys/vdpau/gstvdpaudecoder.c index fb2ce627..deb93c49 100644 --- a/sys/vdpau/gstvdpaudecoder.c +++ b/sys/vdpau/gstvdpaudecoder.c @@ -1,6 +1,5 @@ /* * GStreamer - * Copyright (C) 2006 Stefan Kost * Copyright (C) 2009 Carl-Anton Ingmarsson * * This library is free software; you can redistribute it and/or @@ -27,7 +26,6 @@ #include #include "gstvdpaudecoder.h" -#include GST_DEBUG_CATEGORY_STATIC (gst_vdpaudecoder_debug); #define GST_CAT_DEFAULT gst_vdpaudecoder_debug @@ -68,10 +66,10 @@ GstFlowReturn gst_vdpau_decoder_push_video_surface (GstVdpauDecoder * dec, VdpVideoSurface surface) { - VdpauFunctions *f; + GstVdpauDevice *device; GstBuffer *buffer; - f = dec->functions; + device = dec->device; switch (dec->format) { case GST_MAKE_FOURCC ('Y', 'V', '1', '2'): @@ -110,13 +108,13 @@ gst_vdpau_decoder_push_video_surface (GstVdpauDecoder * dec, 1, dec->width); status = - f->vdp_video_surface_get_bits_ycbcr (surface, VDP_YCBCR_FORMAT_YV12, - (void *) data, stride); + device->vdp_video_surface_get_bits_ycbcr (surface, + VDP_YCBCR_FORMAT_YV12, (void *) data, stride); if (G_UNLIKELY (status != VDP_STATUS_OK)) { GST_ELEMENT_ERROR (dec, RESOURCE, READ, ("Couldn't get data from vdpau"), ("Error returned from vdpau was: %s", - f->vdp_get_error_string (status))); + device->vdp_get_error_string (status))); return GST_FLOW_ERROR; } break; @@ -144,13 +142,13 @@ gst_vdpau_decoder_push_video_surface (GstVdpauDecoder * dec, stride[1] = dec->width; status = - f->vdp_video_surface_get_bits_ycbcr (surface, VDP_YCBCR_FORMAT_NV12, - (void *) data, stride); + device->vdp_video_surface_get_bits_ycbcr (surface, + VDP_YCBCR_FORMAT_NV12, (void *) data, stride); if (G_UNLIKELY (status != VDP_STATUS_OK)) { GST_ELEMENT_ERROR (dec, RESOURCE, READ, ("Couldn't get data from vdpau"), ("Error returned from vdpau was: %s", - f->vdp_get_error_string (status))); + device->vdp_get_error_string (status))); return GST_FLOW_ERROR; } break; @@ -217,13 +215,13 @@ static VdpauFormats formats[6] = { VdpVideoSurface gst_vdpau_decoder_create_video_surface (GstVdpauDecoder * dec) { - VdpauFunctions *f; + GstVdpauDevice *device; VdpChromaType chroma_type; gint i; VdpStatus status; VdpVideoSurface surface; - f = dec->functions; + device = dec->device; chroma_type = VDP_CHROMA_TYPE_422; for (i = 0; i < 6; i++) { @@ -233,13 +231,14 @@ gst_vdpau_decoder_create_video_surface (GstVdpauDecoder * dec) } } - status = f->vdp_video_surface_create (dec->device, chroma_type, dec->width, + status = + device->vdp_video_surface_create (device->device, chroma_type, dec->width, dec->height, &surface); if (status != VDP_STATUS_OK) { GST_ELEMENT_ERROR (dec, RESOURCE, READ, ("Couldn't create a VdpVideoSurface"), ("Error returned from vdpau was: %s", - f->vdp_get_error_string (status))); + device->vdp_get_error_string (status))); return VDP_INVALID_HANDLE; } @@ -249,11 +248,11 @@ gst_vdpau_decoder_create_video_surface (GstVdpauDecoder * dec) static GstCaps * gst_vdpaudecoder_get_vdpau_support (GstVdpauDecoder * dec) { - VdpauFunctions *f; + GstVdpauDevice *device; GstCaps *caps; gint i; - f = dec->functions; + device = dec->device; caps = gst_caps_new_empty (); @@ -263,14 +262,14 @@ gst_vdpaudecoder_get_vdpau_support (GstVdpauDecoder * dec) guint32 max_w, max_h; status = - f->vdp_video_surface_query_capabilities (dec->device, chroma_types[i], - &is_supported, &max_w, &max_h); + device->vdp_video_surface_query_capabilities (device->device, + chroma_types[i], &is_supported, &max_w, &max_h); if (status != VDP_STATUS_OK && status != VDP_STATUS_INVALID_CHROMA_TYPE) { GST_ELEMENT_ERROR (dec, RESOURCE, READ, ("Could not get query VDPAU video surface capabilites"), ("Error returned from vdpau was: %s", - f->vdp_get_error_string (status))); + device->vdp_get_error_string (status))); return NULL; } @@ -282,14 +281,14 @@ gst_vdpaudecoder_get_vdpau_support (GstVdpauDecoder * dec) continue; status = - f->vdp_video_surface_query_ycbcr_capabilities (dec->device, + device->vdp_video_surface_query_ycbcr_capabilities (device->device, formats[j].chroma_type, formats[j].format, &is_supported); if (status != VDP_STATUS_OK && status != VDP_STATUS_INVALID_Y_CB_CR_FORMAT) { GST_ELEMENT_ERROR (dec, RESOURCE, READ, ("Could not query VDPAU YCbCr capabilites"), ("Error returned from vdpau was: %s", - f->vdp_get_error_string (status))); + device->vdp_get_error_string (status))); return NULL; } @@ -317,111 +316,25 @@ gst_vdpaudecoder_get_vdpau_support (GstVdpauDecoder * dec) static gboolean gst_vdpaudecoder_init_vdpau (GstVdpauDecoder * dec) { - gint screen; - VdpStatus status; - gint i; - VdpauFunctions *f; GstCaps *caps; - typedef struct - { - int id; - void *func; - } VdpFunction; - - VdpFunction vdp_function[] = { - {VDP_FUNC_ID_DEVICE_DESTROY, &dec->functions->vdp_device_destroy}, - {VDP_FUNC_ID_VIDEO_SURFACE_CREATE, - &dec->functions->vdp_video_surface_create}, - {VDP_FUNC_ID_VIDEO_SURFACE_DESTROY, - &dec->functions->vdp_video_surface_destroy}, - {VDP_FUNC_ID_VIDEO_SURFACE_QUERY_CAPABILITIES, - &dec->functions->vdp_video_surface_query_capabilities}, - {VDP_FUNC_ID_VIDEO_SURFACE_QUERY_GET_PUT_BITS_Y_CB_CR_CAPABILITIES, - &dec->functions->vdp_video_surface_query_ycbcr_capabilities}, - {VDP_FUNC_ID_VIDEO_SURFACE_GET_BITS_Y_CB_CR, - &dec->functions->vdp_video_surface_get_bits_ycbcr}, - {VDP_FUNC_ID_VIDEO_SURFACE_GET_PARAMETERS, - &dec->functions->vdp_video_surface_get_parameters}, - {VDP_FUNC_ID_DECODER_CREATE, &dec->functions->vdp_decoder_create}, - {VDP_FUNC_ID_DECODER_RENDER, &dec->functions->vdp_decoder_render}, - {VDP_FUNC_ID_DECODER_DESTROY, &dec->functions->vdp_decoder_destroy}, - {VDP_FUNC_ID_DECODER_QUERY_CAPABILITIES, - &dec->functions->vdp_decoder_query_capabilities}, - {VDP_FUNC_ID_DECODER_GET_PARAMETERS, - &dec->functions->vdp_decoder_get_parameters}, - {0, NULL} - }; - - /* FIXME: We probably want to use the same VdpDevice for every VDPAU element */ - dec->display = XOpenDisplay (dec->display_name); - if (!dec->display) { - GST_ELEMENT_ERROR (dec, RESOURCE, READ, ("Could not initialise VDPAU"), - ("Could not open display")); - return FALSE; - } - - f = dec->functions; - - screen = DefaultScreen (dec->display); - status = - vdp_device_create_x11 (dec->display, screen, &dec->device, - &f->vdp_get_proc_address); - if (status != VDP_STATUS_OK) { - GST_ELEMENT_ERROR (dec, RESOURCE, READ, ("Could not initialise VDPAU"), - ("Could not create VDPAU device")); - XCloseDisplay (dec->display); - dec->display = NULL; - - return FALSE; - } - - status = f->vdp_get_proc_address (dec->device, - VDP_FUNC_ID_GET_ERROR_STRING, (void **) &f->vdp_get_error_string); - if (status != VDP_STATUS_OK) { - GST_ELEMENT_ERROR (dec, RESOURCE, READ, - ("Could'nt get function pointer from vdpau"), - ("Couldn't get vdp_get_error_string function pointer")); - goto error; - } - - for (i = 0; vdp_function[i].func != NULL; i++) { - status = f->vdp_get_proc_address (dec->device, - vdp_function[i].id, vdp_function[i].func); - - if (status != VDP_STATUS_OK) { - GST_ELEMENT_ERROR (dec, RESOURCE, READ, - ("Could not get function pointer from vdpau"), - ("Error returned from vdpau was: %s", - f->vdp_get_error_string (status))); - goto error; - } - } + dec->device = gst_vdpau_get_device (dec->display_name); caps = gst_vdpaudecoder_get_vdpau_support (dec); if (!caps) - goto error; + return FALSE; dec->src_caps = caps; return TRUE; - -error: - f->vdp_device_destroy (dec->device); - dec->device = VDP_INVALID_HANDLE; - - return FALSE; - } static GstStateChangeReturn gst_vdpaudecoder_change_state (GstElement * element, GstStateChange transition) { GstVdpauDecoder *dec; - VdpauFunctions *f; dec = GST_VDPAU_DECODER (element); - f = dec->functions; switch (transition) { case GST_STATE_CHANGE_NULL_TO_READY: @@ -429,11 +342,8 @@ gst_vdpaudecoder_change_state (GstElement * element, GstStateChange transition) return GST_STATE_CHANGE_FAILURE; break; case GST_STATE_CHANGE_READY_TO_NULL: - f->vdp_device_destroy (dec->device); - XCloseDisplay (dec->display); - - dec->device = VDP_INVALID_HANDLE; - dec->display = NULL; + g_object_unref (dec->device); + dec->device = NULL; break; default: break; @@ -561,8 +471,7 @@ static void gst_vdpaudecoder_init (GstVdpauDecoder * dec, GstVdpauDecoderClass * klass) { dec->display_name = NULL; - dec->display = NULL; - dec->device = VDP_INVALID_HANDLE; + dec->device = NULL; dec->silent = FALSE; dec->src_caps = NULL; @@ -574,8 +483,6 @@ gst_vdpaudecoder_init (GstVdpauDecoder * dec, GstVdpauDecoderClass * klass) dec->frame_nr = 0; - dec->functions = g_slice_new0 (VdpauFunctions); - dec->src = gst_pad_new_from_static_template (&src_template, "src"); gst_pad_set_getcaps_function (dec->src, gst_vdpaudecoder_src_getcaps); gst_element_add_pad (GST_ELEMENT (dec), dec->src); diff --git a/sys/vdpau/gstvdpaudecoder.h b/sys/vdpau/gstvdpaudecoder.h index 3ab3c9f3..3fcf9a74 100644 --- a/sys/vdpau/gstvdpaudecoder.h +++ b/sys/vdpau/gstvdpaudecoder.h @@ -1,6 +1,5 @@ /* * GStreamer - * Copyright (C) 2006 Stefan Kost * Copyright (C) 2009 Carl-Anton Ingmarsson * * This library is free software; you can redistribute it and/or @@ -23,10 +22,8 @@ #define __GST_VDPAU_DECODER_H__ #include -#include -#include -#include +#include "gst-vdpau-device.h" G_BEGIN_DECLS @@ -45,10 +42,7 @@ struct _GstVdpauDecoder { GstElement element; gchar *display_name; - Display *display; - VdpDevice device; - - VdpauFunctions *functions; + GstVdpauDevice *device; GstPad *src; GstPad *sink; @@ -65,30 +59,11 @@ struct _GstVdpauDecoder { }; struct _GstVdpauDecoderClass { - GstBaseTransformClass parent_class; + GstElementClass parent_class; gboolean (*set_caps) (GstVdpauDecoder *dec, GstCaps *caps); }; -struct _VdpauFunctions { - VdpDeviceDestroy *vdp_device_destroy; - VdpGetProcAddress *vdp_get_proc_address; - VdpGetErrorString *vdp_get_error_string; - - VdpVideoSurfaceCreate *vdp_video_surface_create; - VdpVideoSurfaceDestroy *vdp_video_surface_destroy; - VdpVideoSurfaceQueryCapabilities *vdp_video_surface_query_capabilities; - VdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities *vdp_video_surface_query_ycbcr_capabilities; - VdpVideoSurfaceGetParameters *vdp_video_surface_get_parameters; - VdpVideoSurfaceGetBitsYCbCr *vdp_video_surface_get_bits_ycbcr; - - VdpDecoderCreate *vdp_decoder_create; - VdpDecoderDestroy *vdp_decoder_destroy; - VdpDecoderRender *vdp_decoder_render; - VdpDecoderQueryCapabilities *vdp_decoder_query_capabilities; - VdpDecoderGetParameters *vdp_decoder_get_parameters; -}; - GType gst_vdpaudecoder_get_type (void); gboolean gst_vdpau_decoder_push_video_surface (GstVdpauDecoder * dec, diff --git a/sys/vdpau/gstvdpaumpegdecoder.c b/sys/vdpau/gstvdpaumpegdecoder.c index 6f75181b..52eec777 100644 --- a/sys/vdpau/gstvdpaumpegdecoder.c +++ b/sys/vdpau/gstvdpaumpegdecoder.c @@ -1,29 +1,6 @@ /* * GStreamer * Copyright (C) 2009 Carl-Anton Ingmarsson - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Alternatively, the contents of this file may be used under the - * GNU Lesser General Public License Version 2.1 (the "LGPL"), in - * which case the following provisions apply instead of the ones - * mentioned above: * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -108,7 +85,7 @@ gst_vdpau_mpeg_decoder_set_caps (GstVdpauDecoder * dec, GstCaps * caps) GstBuffer *codec_data; MPEGSeqHdr hdr = { 0, }; VdpDecoderProfile profile; - VdpauFunctions *f; + GstVdpauDevice *device; VdpStatus status; mpeg_dec = GST_VDPAU_MPEG_DECODER (dec); @@ -137,14 +114,14 @@ gst_vdpau_mpeg_decoder_set_caps (GstVdpauDecoder * dec, GstCaps * caps) memcpy (&mpeg_dec->vdp_info.non_intra_quantizer_matrix, &hdr.non_intra_quantizer_matrix, 64); - f = dec->functions; - status = f->vdp_decoder_create (dec->device, profile, dec->width, + device = dec->device; + status = device->vdp_decoder_create (device->device, profile, dec->width, dec->height, 2, &mpeg_dec->decoder); if (status != VDP_STATUS_OK) { GST_ELEMENT_ERROR (mpeg_dec, RESOURCE, READ, ("Could not create vdpau decoder"), ("Error returned from vdpau was: %s", - f->vdp_get_error_string (status))); + device->vdp_get_error_string (status))); return FALSE; } return TRUE; @@ -156,7 +133,7 @@ gst_vdpau_mpeg_decoder_decode (GstVdpauMpegDecoder * mpeg_dec) GstVdpauDecoder *dec; GstBuffer *buffer; VdpVideoSurface surface; - VdpauFunctions *f; + GstVdpauDevice *device; VdpBitstreamBuffer vbit[1]; VdpStatus status; GstFlowReturn ret; @@ -166,20 +143,16 @@ gst_vdpau_mpeg_decoder_decode (GstVdpauMpegDecoder * mpeg_dec) buffer = gst_adapter_take_buffer (mpeg_dec->adapter, gst_adapter_available (mpeg_dec->adapter)); - if (mpeg_dec->vdp_info.picture_coding_type == P_FRAME) { - mpeg_dec->p_buffer = buffer; - } - surface = gst_vdpau_decoder_create_video_surface (GST_VDPAU_DECODER (mpeg_dec)); - f = dec->functions; + device = dec->device; vbit[0].struct_version = VDP_BITSTREAM_BUFFER_VERSION; vbit[0].bitstream = GST_BUFFER_DATA (buffer); vbit[0].bitstream_bytes = GST_BUFFER_SIZE (buffer); - status = f->vdp_decoder_render (mpeg_dec->decoder, surface, + status = device->vdp_decoder_render (mpeg_dec->decoder, surface, (VdpPictureInfo *) & mpeg_dec->vdp_info, 1, vbit); gst_buffer_unref (buffer); mpeg_dec->vdp_info.slice_count = 0; @@ -188,12 +161,12 @@ gst_vdpau_mpeg_decoder_decode (GstVdpauMpegDecoder * mpeg_dec) GST_ELEMENT_ERROR (mpeg_dec, RESOURCE, READ, ("Could not decode"), ("Error returned from vdpau was: %s", - f->vdp_get_error_string (status))); + device->vdp_get_error_string (status))); if (mpeg_dec->vdp_info.forward_reference != VDP_INVALID_HANDLE) - f->vdp_video_surface_destroy (mpeg_dec->vdp_info.forward_reference); + device->vdp_video_surface_destroy (mpeg_dec->vdp_info.forward_reference); - f->vdp_video_surface_destroy (surface); + device->vdp_video_surface_destroy (surface); return GST_FLOW_ERROR; } @@ -203,7 +176,7 @@ gst_vdpau_mpeg_decoder_decode (GstVdpauMpegDecoder * mpeg_dec) surface); if (mpeg_dec->vdp_info.forward_reference != VDP_INVALID_HANDLE) - f->vdp_video_surface_destroy (mpeg_dec->vdp_info.forward_reference); + device->vdp_video_surface_destroy (mpeg_dec->vdp_info.forward_reference); mpeg_dec->vdp_info.forward_reference = surface; @@ -254,8 +227,8 @@ gst_vdpau_mpeg_decoder_parse_picture (GstVdpauMpegDecoder * mpeg_dec, if (pic_hdr.pic_type == I_FRAME && mpeg_dec->vdp_info.forward_reference != VDP_INVALID_HANDLE) { - dec->functions->vdp_video_surface_destroy (mpeg_dec->vdp_info. - forward_reference); + dec->device->vdp_video_surface_destroy (mpeg_dec-> + vdp_info.forward_reference); mpeg_dec->vdp_info.forward_reference = VDP_INVALID_HANDLE; } diff --git a/sys/vdpau/gstvdpaumpegdecoder.h b/sys/vdpau/gstvdpaumpegdecoder.h index b7c293ab..4b4c6550 100644 --- a/sys/vdpau/gstvdpaumpegdecoder.h +++ b/sys/vdpau/gstvdpaumpegdecoder.h @@ -1,29 +1,6 @@ /* * GStreamer * Copyright (C) 2009 Carl-Anton Ingmarsson - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Alternatively, the contents of this file may be used under the - * GNU Lesser General Public License Version 2.1 (the "LGPL"), in - * which case the following provisions apply instead of the ones - * mentioned above: * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -74,8 +51,6 @@ struct _GstVdpauMpegDecoder GstAdapter *adapter; gint slices; - GstBuffer *p_buffer; - VdpPictureInfoMPEG1Or2 p_vdp_info; }; struct _GstVdpauMpegDecoderClass -- cgit v1.2.1 From 21d774023635ecb3b261c4132a05b194b95b7f35 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Wed, 1 Apr 2009 21:26:45 +0200 Subject: vdpau: remove extra \ from Makefile.am --- sys/vdpau/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/vdpau/Makefile.am b/sys/vdpau/Makefile.am index f5a5ed1e..0ee88bf7 100644 --- a/sys/vdpau/Makefile.am +++ b/sys/vdpau/Makefile.am @@ -4,7 +4,7 @@ libgstvdpau_la_SOURCES = \ gst-vdpau-device.c \ gstvdpaudecoder.c \ gstvdpaumpegdecoder.c \ - mpegutil.c \ + mpegutil.c libgstvdpau_la_CFLAGS = $(GST_CFLAGS) $(X11_CFLAGS) -Ivdpau libgstvdpau_la_LIBADD = $(GST_LIBS) $(GST_BASE_LIBS) \ -- cgit v1.2.1 From 6fa5b4ff14b88eff42f36fb74058bdb46c6e92b4 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Wed, 1 Apr 2009 21:40:14 +0200 Subject: vdpau: make the decoder clean up after itself --- sys/vdpau/gstvdpaudecoder.c | 15 +++++++++++++++ sys/vdpau/gstvdpaumpegdecoder.c | 19 +++++++++++++++++-- 2 files changed, 32 insertions(+), 2 deletions(-) diff --git a/sys/vdpau/gstvdpaudecoder.c b/sys/vdpau/gstvdpaudecoder.c index deb93c49..8d5ed4e5 100644 --- a/sys/vdpau/gstvdpaudecoder.c +++ b/sys/vdpau/gstvdpaudecoder.c @@ -57,6 +57,7 @@ static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src", GST_BOILERPLATE_FULL (GstVdpauDecoder, gst_vdpaudecoder, GstElement, GST_TYPE_ELEMENT, DEBUG_INIT); +static void gst_vdpau_decoder_finalize (GObject * object); static void gst_vdpaudecoder_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec); static void gst_vdpaudecoder_get_property (GObject * object, guint prop_id, @@ -453,6 +454,7 @@ gst_vdpaudecoder_class_init (GstVdpauDecoderClass * klass) gobject_class = (GObjectClass *) klass; gstelement_class = (GstElementClass *) klass; + gobject_class->finalize = gst_vdpau_decoder_finalize; gobject_class->set_property = gst_vdpaudecoder_set_property; gobject_class->get_property = gst_vdpaudecoder_get_property; @@ -494,6 +496,19 @@ gst_vdpaudecoder_init (GstVdpauDecoder * dec, GstVdpauDecoderClass * klass) gst_pad_set_active (dec->sink, TRUE); } +static void +gst_vdpau_decoder_finalize (GObject * object) +{ + GstVdpauDecoder *dec = (GstVdpauDecoder *) object; + + if (dec->src_caps) + g_object_unref (dec->src_caps); + if (dec->device) + g_object_unref (dec->device); + + g_free (dec->display_name); +} + static void gst_vdpaudecoder_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) diff --git a/sys/vdpau/gstvdpaumpegdecoder.c b/sys/vdpau/gstvdpaumpegdecoder.c index 52eec777..f3e510bd 100644 --- a/sys/vdpau/gstvdpaumpegdecoder.c +++ b/sys/vdpau/gstvdpaumpegdecoder.c @@ -71,6 +71,7 @@ static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink", GST_BOILERPLATE (GstVdpauMpegDecoder, gst_vdpau_mpeg_decoder, GstVdpauDecoder, GST_TYPE_VDPAU_DECODER); +static void gst_vdpau_mpeg_decoder_finalize (GObject * object); static void gst_vdpau_mpeg_decoder_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec); static void gst_vdpau_mpeg_decoder_get_property (GObject * object, @@ -227,8 +228,8 @@ gst_vdpau_mpeg_decoder_parse_picture (GstVdpauMpegDecoder * mpeg_dec, if (pic_hdr.pic_type == I_FRAME && mpeg_dec->vdp_info.forward_reference != VDP_INVALID_HANDLE) { - dec->device->vdp_video_surface_destroy (mpeg_dec-> - vdp_info.forward_reference); + dec->device->vdp_video_surface_destroy (mpeg_dec->vdp_info. + forward_reference); mpeg_dec->vdp_info.forward_reference = VDP_INVALID_HANDLE; } @@ -374,6 +375,7 @@ gst_vdpau_mpeg_decoder_class_init (GstVdpauMpegDecoderClass * klass) gstelement_class = (GstElementClass *) klass; vdpaudec_class = (GstVdpauDecoderClass *) klass; + gobject_class->finalize = gst_vdpau_mpeg_decoder_finalize; gobject_class->set_property = gst_vdpau_mpeg_decoder_set_property; gobject_class->get_property = gst_vdpau_mpeg_decoder_get_property; @@ -414,6 +416,19 @@ gst_vdpau_mpeg_decoder_init (GstVdpauMpegDecoder * mpeg_dec, gst_pad_set_chain_function (dec->sink, gst_vdpau_mpeg_decoder_chain); } +static void +gst_vdpau_mpeg_decoder_finalize (GObject * object) +{ + GstVdpauMpegDecoder *mpeg_dec = (GstVdpauMpegDecoder *) object; + +#if 0 /* FIXME: can't free the decoder since the device already has been freed */ + if (mpeg_dec->decoder != VDP_INVALID_HANDLE) + dec->device->vdp_decoder_destroy (mpeg_dec->decoder); +#endif + + g_object_unref (mpeg_dec->adapter); +} + static void gst_vdpau_mpeg_decoder_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) -- cgit v1.2.1 From 5563c933eec3819d00f25588bad4e57c87dcb390 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Wed, 1 Apr 2009 21:42:56 +0200 Subject: vdpau: change all references of "gst_vdpaudecoder*" to "gst_vdpau_decoder" --- sys/vdpau/gstvdpaudecoder.c | 46 ++++++++++++++++++++++----------------------- sys/vdpau/gstvdpaudecoder.h | 4 ++-- 2 files changed, 25 insertions(+), 25 deletions(-) diff --git a/sys/vdpau/gstvdpaudecoder.c b/sys/vdpau/gstvdpaudecoder.c index 8d5ed4e5..5a8bbacd 100644 --- a/sys/vdpau/gstvdpaudecoder.c +++ b/sys/vdpau/gstvdpaudecoder.c @@ -27,8 +27,8 @@ #include "gstvdpaudecoder.h" -GST_DEBUG_CATEGORY_STATIC (gst_vdpaudecoder_debug); -#define GST_CAT_DEFAULT gst_vdpaudecoder_debug +GST_DEBUG_CATEGORY_STATIC (gst_vdpau_decoder_debug); +#define GST_CAT_DEFAULT gst_vdpau_decoder_debug /* Filter signals and args */ enum @@ -52,15 +52,15 @@ static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src", "width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]")); #define DEBUG_INIT(bla) \ - GST_DEBUG_CATEGORY_INIT (gst_vdpaudecoder_debug, "vdpaudecoder", 0, "vdpaudecoder base class"); + GST_DEBUG_CATEGORY_INIT (gst_vdpau_decoder_debug, "vdpaudecoder", 0, "vdpaudecoder base class"); -GST_BOILERPLATE_FULL (GstVdpauDecoder, gst_vdpaudecoder, GstElement, +GST_BOILERPLATE_FULL (GstVdpauDecoder, gst_vdpau_decoder, GstElement, GST_TYPE_ELEMENT, DEBUG_INIT); static void gst_vdpau_decoder_finalize (GObject * object); -static void gst_vdpaudecoder_set_property (GObject * object, guint prop_id, +static void gst_vdpau_decoder_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec); -static void gst_vdpaudecoder_get_property (GObject * object, guint prop_id, +static void gst_vdpau_decoder_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); GstFlowReturn @@ -247,7 +247,7 @@ gst_vdpau_decoder_create_video_surface (GstVdpauDecoder * dec) } static GstCaps * -gst_vdpaudecoder_get_vdpau_support (GstVdpauDecoder * dec) +gst_vdpau_decoder_get_vdpau_support (GstVdpauDecoder * dec) { GstVdpauDevice *device; GstCaps *caps; @@ -315,13 +315,13 @@ gst_vdpaudecoder_get_vdpau_support (GstVdpauDecoder * dec) } static gboolean -gst_vdpaudecoder_init_vdpau (GstVdpauDecoder * dec) +gst_vdpau_decoder_init_vdpau (GstVdpauDecoder * dec) { GstCaps *caps; dec->device = gst_vdpau_get_device (dec->display_name); - caps = gst_vdpaudecoder_get_vdpau_support (dec); + caps = gst_vdpau_decoder_get_vdpau_support (dec); if (!caps) return FALSE; @@ -331,7 +331,7 @@ gst_vdpaudecoder_init_vdpau (GstVdpauDecoder * dec) } static GstStateChangeReturn -gst_vdpaudecoder_change_state (GstElement * element, GstStateChange transition) +gst_vdpau_decoder_change_state (GstElement * element, GstStateChange transition) { GstVdpauDecoder *dec; @@ -339,7 +339,7 @@ gst_vdpaudecoder_change_state (GstElement * element, GstStateChange transition) switch (transition) { case GST_STATE_CHANGE_NULL_TO_READY: - if (!gst_vdpaudecoder_init_vdpau (dec)) + if (!gst_vdpau_decoder_init_vdpau (dec)) return GST_STATE_CHANGE_FAILURE; break; case GST_STATE_CHANGE_READY_TO_NULL: @@ -354,7 +354,7 @@ gst_vdpaudecoder_change_state (GstElement * element, GstStateChange transition) } static gboolean -gst_vdpaudecoder_sink_set_caps (GstPad * pad, GstCaps * caps) +gst_vdpau_decoder_sink_set_caps (GstPad * pad, GstCaps * caps) { GstVdpauDecoder *dec = GST_VDPAU_DECODER (GST_OBJECT_PARENT (pad)); GstVdpauDecoderClass *dec_class = GST_VDPAU_DECODER_GET_CLASS (dec); @@ -412,7 +412,7 @@ gst_vdpaudecoder_sink_set_caps (GstPad * pad, GstCaps * caps) } static GstCaps * -gst_vdpaudecoder_src_getcaps (GstPad * pad) +gst_vdpau_decoder_src_getcaps (GstPad * pad) { GstVdpauDecoder *dec; @@ -430,7 +430,7 @@ gst_vdpaudecoder_src_getcaps (GstPad * pad) /* GObject vmethod implementations */ static void -gst_vdpaudecoder_base_init (gpointer klass) +gst_vdpau_decoder_base_init (gpointer klass) { GstElementClass *element_class = GST_ELEMENT_CLASS (klass); @@ -446,7 +446,7 @@ gst_vdpaudecoder_base_init (gpointer klass) /* initialize the vdpaudecoder's class */ static void -gst_vdpaudecoder_class_init (GstVdpauDecoderClass * klass) +gst_vdpau_decoder_class_init (GstVdpauDecoderClass * klass) { GObjectClass *gobject_class; GstElementClass *gstelement_class; @@ -455,8 +455,8 @@ gst_vdpaudecoder_class_init (GstVdpauDecoderClass * klass) gstelement_class = (GstElementClass *) klass; gobject_class->finalize = gst_vdpau_decoder_finalize; - gobject_class->set_property = gst_vdpaudecoder_set_property; - gobject_class->get_property = gst_vdpaudecoder_get_property; + gobject_class->set_property = gst_vdpau_decoder_set_property; + gobject_class->get_property = gst_vdpau_decoder_get_property; g_object_class_install_property (gobject_class, PROP_DISPLAY, g_param_spec_string ("display", "Display", "X Display name", @@ -466,11 +466,11 @@ gst_vdpaudecoder_class_init (GstVdpauDecoderClass * klass) g_param_spec_boolean ("silent", "Silent", "Produce verbose output ?", FALSE, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE)); - gstelement_class->change_state = gst_vdpaudecoder_change_state; + gstelement_class->change_state = gst_vdpau_decoder_change_state; } static void -gst_vdpaudecoder_init (GstVdpauDecoder * dec, GstVdpauDecoderClass * klass) +gst_vdpau_decoder_init (GstVdpauDecoder * dec, GstVdpauDecoderClass * klass) { dec->display_name = NULL; dec->device = NULL; @@ -486,12 +486,12 @@ gst_vdpaudecoder_init (GstVdpauDecoder * dec, GstVdpauDecoderClass * klass) dec->frame_nr = 0; dec->src = gst_pad_new_from_static_template (&src_template, "src"); - gst_pad_set_getcaps_function (dec->src, gst_vdpaudecoder_src_getcaps); + gst_pad_set_getcaps_function (dec->src, gst_vdpau_decoder_src_getcaps); gst_element_add_pad (GST_ELEMENT (dec), dec->src); dec->sink = gst_pad_new_from_template (gst_element_class_get_pad_template (GST_ELEMENT_CLASS (klass), "sink"), "sink"); - gst_pad_set_setcaps_function (dec->sink, gst_vdpaudecoder_sink_set_caps); + gst_pad_set_setcaps_function (dec->sink, gst_vdpau_decoder_sink_set_caps); gst_element_add_pad (GST_ELEMENT (dec), dec->sink); gst_pad_set_active (dec->sink, TRUE); } @@ -510,7 +510,7 @@ gst_vdpau_decoder_finalize (GObject * object) } static void -gst_vdpaudecoder_set_property (GObject * object, guint prop_id, +gst_vdpau_decoder_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { GstVdpauDecoder *dec = GST_VDPAU_DECODER (object); @@ -530,7 +530,7 @@ gst_vdpaudecoder_set_property (GObject * object, guint prop_id, } static void -gst_vdpaudecoder_get_property (GObject * object, guint prop_id, +gst_vdpau_decoder_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { GstVdpauDecoder *dec = GST_VDPAU_DECODER (object); diff --git a/sys/vdpau/gstvdpaudecoder.h b/sys/vdpau/gstvdpaudecoder.h index 3fcf9a74..0a52f2fc 100644 --- a/sys/vdpau/gstvdpaudecoder.h +++ b/sys/vdpau/gstvdpaudecoder.h @@ -27,7 +27,7 @@ G_BEGIN_DECLS -#define GST_TYPE_VDPAU_DECODER (gst_vdpaudecoder_get_type()) +#define GST_TYPE_VDPAU_DECODER (gst_vdpau_decoder_get_type()) #define GST_VDPAU_DECODER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VDPAU_DECODER,GstVdpauDecoder)) #define GST_VDPAU_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VDPAU_DECODER,GstVdpauDecoderClass)) #define GST_VDPAU_DECODER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_VDPAU_DECODER, GstVdpauDecoderClass)) @@ -64,7 +64,7 @@ struct _GstVdpauDecoderClass { gboolean (*set_caps) (GstVdpauDecoder *dec, GstCaps *caps); }; -GType gst_vdpaudecoder_get_type (void); +GType gst_vdpau_decoder_get_type (void); gboolean gst_vdpau_decoder_push_video_surface (GstVdpauDecoder * dec, VdpVideoSurface surface); -- cgit v1.2.1 From 85acf023dff4bc48d9a043e6c8666ac36153c387 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Fri, 3 Apr 2009 17:51:16 +0200 Subject: vdpau: rename gst-vdpau-device.[ch] to gstvdpaudevice.[ch] --- sys/vdpau/Makefile.am | 4 +- sys/vdpau/gstvdpaudecoder.h | 2 +- sys/vdpau/gstvdpaudevice.c | 267 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 270 insertions(+), 3 deletions(-) create mode 100644 sys/vdpau/gstvdpaudevice.c diff --git a/sys/vdpau/Makefile.am b/sys/vdpau/Makefile.am index 0ee88bf7..0e3b578e 100644 --- a/sys/vdpau/Makefile.am +++ b/sys/vdpau/Makefile.am @@ -1,7 +1,7 @@ plugin_LTLIBRARIES = libgstvdpau.la libgstvdpau_la_SOURCES = \ - gst-vdpau-device.c \ + gstvdpaudevice.c \ gstvdpaudecoder.c \ gstvdpaumpegdecoder.c \ mpegutil.c @@ -13,7 +13,7 @@ libgstvdpau_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) libgstvdpau_la_LIBTOOLFLAGS = --tag=disable-static noinst_HEADERS = \ - gst-vdpau-device.h \ + gstvdpaudevice.h \ gstvdpaudecoder.h \ gstvdpaumpegdecoder.h \ mpegutil.h diff --git a/sys/vdpau/gstvdpaudecoder.h b/sys/vdpau/gstvdpaudecoder.h index 0a52f2fc..415d6eca 100644 --- a/sys/vdpau/gstvdpaudecoder.h +++ b/sys/vdpau/gstvdpaudecoder.h @@ -23,7 +23,7 @@ #include -#include "gst-vdpau-device.h" +#include "gstvdpaudevice.h" G_BEGIN_DECLS diff --git a/sys/vdpau/gstvdpaudevice.c b/sys/vdpau/gstvdpaudevice.c new file mode 100644 index 00000000..23a582f3 --- /dev/null +++ b/sys/vdpau/gstvdpaudevice.c @@ -0,0 +1,267 @@ +/* + * GStreamer + * Copyright (C) 2009 Carl-Anton Ingmarsson + * + * 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. + */ + +#include +#include + +#include "gstvdpaudevice.h" + +GST_DEBUG_CATEGORY_STATIC (gst_vdpau_device_debug); +#define GST_CAT_DEFAULT gst_vdpau_device_debug + +enum +{ + PROP_0, + + PROP_DISPLAY +}; + + + +G_DEFINE_TYPE (GstVdpauDevice, gst_vdpau_device, G_TYPE_OBJECT); + +static void +gst_vdpau_device_init (GstVdpauDevice * device) +{ + device->display_name = NULL; + device->display = NULL; + device->device = VDP_INVALID_HANDLE; +} + +static void +gst_vdpau_device_finalize (GObject * object) +{ + GstVdpauDevice *device = (GstVdpauDevice *) object; + + device->vdp_device_destroy (device->device); + g_free (device->display_name); + + G_OBJECT_CLASS (gst_vdpau_device_parent_class)->finalize (object); + +} + +static void +gst_vdpau_device_constructed (GObject * object) +{ + GstVdpauDevice *device = (GstVdpauDevice *) object; + gint screen; + VdpStatus status; + gint i; + + typedef struct + { + gint id; + void *func; + } VdpFunction; + + VdpFunction vdp_function[] = { + {VDP_FUNC_ID_DEVICE_DESTROY, &device->vdp_device_destroy}, + {VDP_FUNC_ID_VIDEO_SURFACE_CREATE, + &device->vdp_video_surface_create}, + {VDP_FUNC_ID_VIDEO_SURFACE_DESTROY, + &device->vdp_video_surface_destroy}, + {VDP_FUNC_ID_VIDEO_SURFACE_QUERY_CAPABILITIES, + &device->vdp_video_surface_query_capabilities}, + {VDP_FUNC_ID_VIDEO_SURFACE_QUERY_GET_PUT_BITS_Y_CB_CR_CAPABILITIES, + &device->vdp_video_surface_query_ycbcr_capabilities}, + {VDP_FUNC_ID_VIDEO_SURFACE_GET_BITS_Y_CB_CR, + &device->vdp_video_surface_get_bits_ycbcr}, + {VDP_FUNC_ID_VIDEO_SURFACE_GET_PARAMETERS, + &device->vdp_video_surface_get_parameters}, + {VDP_FUNC_ID_DECODER_CREATE, &device->vdp_decoder_create}, + {VDP_FUNC_ID_DECODER_RENDER, &device->vdp_decoder_render}, + {VDP_FUNC_ID_DECODER_DESTROY, &device->vdp_decoder_destroy}, + {VDP_FUNC_ID_DECODER_QUERY_CAPABILITIES, + &device->vdp_decoder_query_capabilities}, + {VDP_FUNC_ID_DECODER_GET_PARAMETERS, + &device->vdp_decoder_get_parameters}, + {0, NULL} + }; + + /* FIXME: We probably want to use the same VdpDevice for every VDPAU element */ + device->display = XOpenDisplay (device->display_name); + if (!device->display) { + GST_ERROR_OBJECT (device, "Could not open X display with name: %s", + device->display_name); + return; + } + + screen = DefaultScreen (device->display); + status = + vdp_device_create_x11 (device->display, screen, &device->device, + &device->vdp_get_proc_address); + if (status != VDP_STATUS_OK) { + GST_ERROR_OBJECT (device, "Could not create VDPAU device"); + XCloseDisplay (device->display); + device->display = NULL; + + return; + } + + status = device->vdp_get_proc_address (device->device, + VDP_FUNC_ID_GET_ERROR_STRING, (void **) &device->vdp_get_error_string); + if (status != VDP_STATUS_OK) { + GST_ERROR_OBJECT (device, + "Could not get vdp_get_error_string function pointer from VDPAU"); + goto error; + } + + for (i = 0; vdp_function[i].func != NULL; i++) { + status = device->vdp_get_proc_address (device->device, + vdp_function[i].id, vdp_function[i].func); + + if (status != VDP_STATUS_OK) { + GST_ERROR_OBJECT (device, "Could not get function pointer from VDPAU," + " error returned was: %s", device->vdp_get_error_string (status)); + goto error; + } + } + + return; + +error: + XCloseDisplay (device->display); + device->display = NULL; + + if (device->device != VDP_INVALID_HANDLE) { + device->vdp_device_destroy (device->device); + device->device = VDP_INVALID_HANDLE; + } +} + +static void +gst_vdpau_device_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstVdpauDevice *device; + + g_return_if_fail (GST_IS_VDPAU_DEVICE (object)); + + device = (GstVdpauDevice *) object; + + switch (prop_id) { + case PROP_DISPLAY: + device->display_name = g_value_dup_string (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_vdpau_device_get_property (GObject * object, guint prop_id, GValue * value, + GParamSpec * pspec) +{ + GstVdpauDevice *device; + + g_return_if_fail (GST_IS_VDPAU_DEVICE (object)); + + device = (GstVdpauDevice *) object; + + switch (prop_id) { + case PROP_DISPLAY: + g_value_set_string (value, device->display_name); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_vdpau_device_class_init (GstVdpauDeviceClass * klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->constructed = gst_vdpau_device_constructed; + object_class->finalize = gst_vdpau_device_finalize; + object_class->get_property = gst_vdpau_device_get_property; + object_class->set_property = gst_vdpau_device_set_property; + + + g_object_class_install_property (object_class, + PROP_DISPLAY, + g_param_spec_string ("display", + "Display", + "X Display Name", + "", G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); + + GST_DEBUG_CATEGORY_INIT (gst_vdpau_device_debug, "vdpaudevice", + 0, "vdpaudevice"); +} + +GstVdpauDevice * +gst_vdpau_device_new (const gchar * display_name) +{ + GstVdpauDevice *device; + + device = g_object_new (GST_TYPE_VDPAU_DEVICE, "display", display_name); + + return device; +} + +static void +device_destroyed_cb (gpointer data, GObject * object) +{ + GHashTable *devices_hash = data; + GHashTableIter iter; + gpointer device; + + g_hash_table_iter_init (&iter, devices_hash); + while (g_hash_table_iter_next (&iter, NULL, &device)) { + if (device == object) { + g_hash_table_iter_remove (&iter); + break; + } + } +} + +static gpointer +create_devices_hash (gpointer data) +{ + return g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); +} + +GstVdpauDevice * +gst_vdpau_get_device (const gchar * display_name) +{ + static GOnce my_once = G_ONCE_INIT; + GHashTable *devices_hash; + GstVdpauDevice *device; + + g_once (&my_once, create_devices_hash, NULL); + devices_hash = my_once.retval; + + if (display_name) + device = g_hash_table_lookup (devices_hash, display_name); + else + device = g_hash_table_lookup (devices_hash, ""); + + if (!device) { + g_debug ("asdasd"); + device = gst_vdpau_device_new (display_name); + g_object_weak_ref (G_OBJECT (device), device_destroyed_cb, devices_hash); + } else + g_object_ref (device); + + g_debug ("HMM"); + return device; +} -- cgit v1.2.1 From 4cc2a90645172a0e5ec879badffe8b620fbdf74e Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Fri, 3 Apr 2009 17:52:20 +0200 Subject: vdpau: remove gst-vdpau-device.c --- sys/vdpau/gst-vdpau-device.c | 267 ------------------------------------------- 1 file changed, 267 deletions(-) delete mode 100644 sys/vdpau/gst-vdpau-device.c diff --git a/sys/vdpau/gst-vdpau-device.c b/sys/vdpau/gst-vdpau-device.c deleted file mode 100644 index ec86ca4e..00000000 --- a/sys/vdpau/gst-vdpau-device.c +++ /dev/null @@ -1,267 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2009 Carl-Anton Ingmarsson - * - * 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. - */ - -#include -#include - -#include "gst-vdpau-device.h" - -GST_DEBUG_CATEGORY_STATIC (gst_vdpau_device_debug); -#define GST_CAT_DEFAULT gst_vdpau_device_debug - -enum -{ - PROP_0, - - PROP_DISPLAY -}; - - - -G_DEFINE_TYPE (GstVdpauDevice, gst_vdpau_device, G_TYPE_OBJECT); - -static void -gst_vdpau_device_init (GstVdpauDevice * device) -{ - device->display_name = NULL; - device->display = NULL; - device->device = VDP_INVALID_HANDLE; -} - -static void -gst_vdpau_device_finalize (GObject * object) -{ - GstVdpauDevice *device = (GstVdpauDevice *) object; - - device->vdp_device_destroy (device->device); - g_free (device->display_name); - - G_OBJECT_CLASS (gst_vdpau_device_parent_class)->finalize (object); - -} - -static void -gst_vdpau_device_constructed (GObject * object) -{ - GstVdpauDevice *device = (GstVdpauDevice *) object; - gint screen; - VdpStatus status; - gint i; - - typedef struct - { - gint id; - void *func; - } VdpFunction; - - VdpFunction vdp_function[] = { - {VDP_FUNC_ID_DEVICE_DESTROY, &device->vdp_device_destroy}, - {VDP_FUNC_ID_VIDEO_SURFACE_CREATE, - &device->vdp_video_surface_create}, - {VDP_FUNC_ID_VIDEO_SURFACE_DESTROY, - &device->vdp_video_surface_destroy}, - {VDP_FUNC_ID_VIDEO_SURFACE_QUERY_CAPABILITIES, - &device->vdp_video_surface_query_capabilities}, - {VDP_FUNC_ID_VIDEO_SURFACE_QUERY_GET_PUT_BITS_Y_CB_CR_CAPABILITIES, - &device->vdp_video_surface_query_ycbcr_capabilities}, - {VDP_FUNC_ID_VIDEO_SURFACE_GET_BITS_Y_CB_CR, - &device->vdp_video_surface_get_bits_ycbcr}, - {VDP_FUNC_ID_VIDEO_SURFACE_GET_PARAMETERS, - &device->vdp_video_surface_get_parameters}, - {VDP_FUNC_ID_DECODER_CREATE, &device->vdp_decoder_create}, - {VDP_FUNC_ID_DECODER_RENDER, &device->vdp_decoder_render}, - {VDP_FUNC_ID_DECODER_DESTROY, &device->vdp_decoder_destroy}, - {VDP_FUNC_ID_DECODER_QUERY_CAPABILITIES, - &device->vdp_decoder_query_capabilities}, - {VDP_FUNC_ID_DECODER_GET_PARAMETERS, - &device->vdp_decoder_get_parameters}, - {0, NULL} - }; - - /* FIXME: We probably want to use the same VdpDevice for every VDPAU element */ - device->display = XOpenDisplay (device->display_name); - if (!device->display) { - GST_ERROR_OBJECT (device, "Could not open X display with name: %s", - device->display_name); - return; - } - - screen = DefaultScreen (device->display); - status = - vdp_device_create_x11 (device->display, screen, &device->device, - &device->vdp_get_proc_address); - if (status != VDP_STATUS_OK) { - GST_ERROR_OBJECT (device, "Could not create VDPAU device"); - XCloseDisplay (device->display); - device->display = NULL; - - return; - } - - status = device->vdp_get_proc_address (device->device, - VDP_FUNC_ID_GET_ERROR_STRING, (void **) &device->vdp_get_error_string); - if (status != VDP_STATUS_OK) { - GST_ERROR_OBJECT (device, - "Could not get vdp_get_error_string function pointer from VDPAU"); - goto error; - } - - for (i = 0; vdp_function[i].func != NULL; i++) { - status = device->vdp_get_proc_address (device->device, - vdp_function[i].id, vdp_function[i].func); - - if (status != VDP_STATUS_OK) { - GST_ERROR_OBJECT (device, "Could not get function pointer from VDPAU," - " error returned was: %s", device->vdp_get_error_string (status)); - goto error; - } - } - - return; - -error: - XCloseDisplay (device->display); - device->display = NULL; - - if (device->device != VDP_INVALID_HANDLE) { - device->vdp_device_destroy (device->device); - device->device = VDP_INVALID_HANDLE; - } -} - -static void -gst_vdpau_device_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstVdpauDevice *device; - - g_return_if_fail (GST_IS_VDPAU_DEVICE (object)); - - device = (GstVdpauDevice *) object; - - switch (prop_id) { - case PROP_DISPLAY: - device->display_name = g_value_dup_string (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_vdpau_device_get_property (GObject * object, guint prop_id, GValue * value, - GParamSpec * pspec) -{ - GstVdpauDevice *device; - - g_return_if_fail (GST_IS_VDPAU_DEVICE (object)); - - device = (GstVdpauDevice *) object; - - switch (prop_id) { - case PROP_DISPLAY: - g_value_set_string (value, device->display_name); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_vdpau_device_class_init (GstVdpauDeviceClass * klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->constructed = gst_vdpau_device_constructed; - object_class->finalize = gst_vdpau_device_finalize; - object_class->get_property = gst_vdpau_device_get_property; - object_class->set_property = gst_vdpau_device_set_property; - - - g_object_class_install_property (object_class, - PROP_DISPLAY, - g_param_spec_string ("display", - "Display", - "X Display Name", - "", G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); - - GST_DEBUG_CATEGORY_INIT (gst_vdpau_device_debug, "vdpaudevice", - 0, "vdpaudevice"); -} - -GstVdpauDevice * -gst_vdpau_device_new (const gchar * display_name) -{ - GstVdpauDevice *device; - - device = g_object_new (GST_TYPE_VDPAU_DEVICE, "display", display_name); - - return device; -} - -static void -device_destroyed_cb (gpointer data, GObject * object) -{ - GHashTable *devices_hash = data; - GHashTableIter iter; - gpointer device; - - g_hash_table_iter_init (&iter, devices_hash); - while (g_hash_table_iter_next (&iter, NULL, &device)) { - if (device == object) { - g_hash_table_iter_remove (&iter); - break; - } - } -} - -static gpointer -create_devices_hash (gpointer data) -{ - return g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); -} - -GstVdpauDevice * -gst_vdpau_get_device (const gchar * display_name) -{ - static GOnce my_once = G_ONCE_INIT; - GHashTable *devices_hash; - GstVdpauDevice *device; - - g_once (&my_once, create_devices_hash, NULL); - devices_hash = my_once.retval; - - if (display_name) - device = g_hash_table_lookup (devices_hash, display_name); - else - device = g_hash_table_lookup (devices_hash, ""); - - if (!device) { - g_debug ("asdasd"); - device = gst_vdpau_device_new (display_name); - g_object_weak_ref (G_OBJECT (device), device_destroyed_cb, devices_hash); - } else - g_object_ref (device); - - g_debug ("HMM"); - return device; -} -- cgit v1.2.1 From 7b6cfb83c821342489bd61e02a5694fa60d2012e Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Fri, 3 Apr 2009 17:53:21 +0200 Subject: vdpau: commit rename of gst-vdpau-device.h to gstvdpaudevice.h --- sys/vdpau/gst-vdpau-device.h | 80 -------------------------------------------- sys/vdpau/gstvdpaudevice.h | 80 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+), 80 deletions(-) delete mode 100644 sys/vdpau/gst-vdpau-device.h create mode 100644 sys/vdpau/gstvdpaudevice.h diff --git a/sys/vdpau/gst-vdpau-device.h b/sys/vdpau/gst-vdpau-device.h deleted file mode 100644 index 0a5cb5e7..00000000 --- a/sys/vdpau/gst-vdpau-device.h +++ /dev/null @@ -1,80 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2009 Carl-Anton Ingmarsson - * - * 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_VDPAU_DEVICE_H_ -#define _GST_VDPAU_DEVICE_H_ - -#include -#include - -#include - -G_BEGIN_DECLS - -#define GST_TYPE_VDPAU_DEVICE (gst_vdpau_device_get_type ()) -#define GST_VDPAU_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_VDPAU_DEVICE, GstVdpauDevice)) -#define GST_VDPAU_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_VDPAU_DEVICE, GstVdpauDeviceClass)) -#define GST_IS_VDPAU_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_VDPAU_DEVICE)) -#define GST_IS_VDPAU_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_VDPAU_DEVICE)) -#define GST_VDPAU_DEVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_VDPAU_DEVICE, GstVdpauDeviceClass)) - -typedef struct _GstVdpauDeviceClass GstVdpauDeviceClass; -typedef struct _GstVdpauDevice GstVdpauDevice; - -struct _GstVdpauDeviceClass -{ - GObjectClass parent_class; -}; - -struct _GstVdpauDevice -{ - GObject object; - - gchar *display_name; - Display *display; - VdpDevice device; - - VdpDeviceDestroy *vdp_device_destroy; - VdpGetProcAddress *vdp_get_proc_address; - VdpGetErrorString *vdp_get_error_string; - - VdpVideoSurfaceCreate *vdp_video_surface_create; - VdpVideoSurfaceDestroy *vdp_video_surface_destroy; - VdpVideoSurfaceQueryCapabilities *vdp_video_surface_query_capabilities; - VdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities *vdp_video_surface_query_ycbcr_capabilities; - VdpVideoSurfaceGetParameters *vdp_video_surface_get_parameters; - VdpVideoSurfaceGetBitsYCbCr *vdp_video_surface_get_bits_ycbcr; - - VdpDecoderCreate *vdp_decoder_create; - VdpDecoderDestroy *vdp_decoder_destroy; - VdpDecoderRender *vdp_decoder_render; - VdpDecoderQueryCapabilities *vdp_decoder_query_capabilities; - VdpDecoderGetParameters *vdp_decoder_get_parameters; -}; - -GType gst_vdpau_device_get_type (void) G_GNUC_CONST; - -GstVdpauDevice *gst_vdpau_device_new (const gchar *display_name); - -GstVdpauDevice *gst_vdpau_get_device (const gchar *display_name); - -G_END_DECLS - -#endif /* _GST_VDPAU_DEVICE_H_ */ diff --git a/sys/vdpau/gstvdpaudevice.h b/sys/vdpau/gstvdpaudevice.h new file mode 100644 index 00000000..0a5cb5e7 --- /dev/null +++ b/sys/vdpau/gstvdpaudevice.h @@ -0,0 +1,80 @@ +/* + * GStreamer + * Copyright (C) 2009 Carl-Anton Ingmarsson + * + * 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_VDPAU_DEVICE_H_ +#define _GST_VDPAU_DEVICE_H_ + +#include +#include + +#include + +G_BEGIN_DECLS + +#define GST_TYPE_VDPAU_DEVICE (gst_vdpau_device_get_type ()) +#define GST_VDPAU_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_VDPAU_DEVICE, GstVdpauDevice)) +#define GST_VDPAU_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_VDPAU_DEVICE, GstVdpauDeviceClass)) +#define GST_IS_VDPAU_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_VDPAU_DEVICE)) +#define GST_IS_VDPAU_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_VDPAU_DEVICE)) +#define GST_VDPAU_DEVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_VDPAU_DEVICE, GstVdpauDeviceClass)) + +typedef struct _GstVdpauDeviceClass GstVdpauDeviceClass; +typedef struct _GstVdpauDevice GstVdpauDevice; + +struct _GstVdpauDeviceClass +{ + GObjectClass parent_class; +}; + +struct _GstVdpauDevice +{ + GObject object; + + gchar *display_name; + Display *display; + VdpDevice device; + + VdpDeviceDestroy *vdp_device_destroy; + VdpGetProcAddress *vdp_get_proc_address; + VdpGetErrorString *vdp_get_error_string; + + VdpVideoSurfaceCreate *vdp_video_surface_create; + VdpVideoSurfaceDestroy *vdp_video_surface_destroy; + VdpVideoSurfaceQueryCapabilities *vdp_video_surface_query_capabilities; + VdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities *vdp_video_surface_query_ycbcr_capabilities; + VdpVideoSurfaceGetParameters *vdp_video_surface_get_parameters; + VdpVideoSurfaceGetBitsYCbCr *vdp_video_surface_get_bits_ycbcr; + + VdpDecoderCreate *vdp_decoder_create; + VdpDecoderDestroy *vdp_decoder_destroy; + VdpDecoderRender *vdp_decoder_render; + VdpDecoderQueryCapabilities *vdp_decoder_query_capabilities; + VdpDecoderGetParameters *vdp_decoder_get_parameters; +}; + +GType gst_vdpau_device_get_type (void) G_GNUC_CONST; + +GstVdpauDevice *gst_vdpau_device_new (const gchar *display_name); + +GstVdpauDevice *gst_vdpau_get_device (const gchar *display_name); + +G_END_DECLS + +#endif /* _GST_VDPAU_DEVICE_H_ */ -- cgit v1.2.1 From f72dc12373cbb73a68fa1f8951d33472ac0940b2 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Fri, 3 Apr 2009 17:58:25 +0200 Subject: vdpau: remove obosolete FIXME and some debug prints from gstvdpaudevice.c --- sys/vdpau/gstvdpaudevice.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/sys/vdpau/gstvdpaudevice.c b/sys/vdpau/gstvdpaudevice.c index 23a582f3..8e314d6d 100644 --- a/sys/vdpau/gstvdpaudevice.c +++ b/sys/vdpau/gstvdpaudevice.c @@ -95,7 +95,6 @@ gst_vdpau_device_constructed (GObject * object) {0, NULL} }; - /* FIXME: We probably want to use the same VdpDevice for every VDPAU element */ device->display = XOpenDisplay (device->display_name); if (!device->display) { GST_ERROR_OBJECT (device, "Could not open X display with name: %s", @@ -256,12 +255,10 @@ gst_vdpau_get_device (const gchar * display_name) device = g_hash_table_lookup (devices_hash, ""); if (!device) { - g_debug ("asdasd"); device = gst_vdpau_device_new (display_name); g_object_weak_ref (G_OBJECT (device), device_destroyed_cb, devices_hash); } else g_object_ref (device); - g_debug ("HMM"); return device; } -- cgit v1.2.1 From 5e73b7272bb210427763b8d2effc68280d9493a0 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Fri, 3 Apr 2009 17:59:02 +0200 Subject: vdpau: small indent fix --- sys/vdpau/gstvdpaumpegdecoder.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/vdpau/gstvdpaumpegdecoder.c b/sys/vdpau/gstvdpaumpegdecoder.c index f3e510bd..fba52d39 100644 --- a/sys/vdpau/gstvdpaumpegdecoder.c +++ b/sys/vdpau/gstvdpaumpegdecoder.c @@ -228,8 +228,8 @@ gst_vdpau_mpeg_decoder_parse_picture (GstVdpauMpegDecoder * mpeg_dec, if (pic_hdr.pic_type == I_FRAME && mpeg_dec->vdp_info.forward_reference != VDP_INVALID_HANDLE) { - dec->device->vdp_video_surface_destroy (mpeg_dec->vdp_info. - forward_reference); + dec->device->vdp_video_surface_destroy (mpeg_dec-> + vdp_info.forward_reference); mpeg_dec->vdp_info.forward_reference = VDP_INVALID_HANDLE; } -- cgit v1.2.1 From 85158b07eabb0d8fe7e4f29b06ea447a54505ad8 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Sat, 4 Apr 2009 20:53:35 +0200 Subject: vdpau: add new GstVdpauVideoYUV element GstVdpauDecoder now pushes GstVdpauVideoBuffers instead of doing VdpSurface -> YUV conversion. To get YUV data you now put in a GstVdpauVideoYUV element which takes GstVdpauVideoBuffers and outputs YUV data. --- sys/vdpau/Makefile.am | 6 +- sys/vdpau/gstvdpaudecoder.c | 291 +------------------------ sys/vdpau/gstvdpaudecoder.h | 6 +- sys/vdpau/gstvdpaumpegdecoder.c | 37 ++-- sys/vdpau/gstvdpaumpegdecoder.h | 2 +- sys/vdpau/gstvdpauvideobuffer.c | 114 ++++++++++ sys/vdpau/gstvdpauvideobuffer.h | 55 +++++ sys/vdpau/gstvdpauvideoyuv.c | 454 ++++++++++++++++++++++++++++++++++++++++ sys/vdpau/gstvdpauvideoyuv.h | 62 ++++++ 9 files changed, 721 insertions(+), 306 deletions(-) create mode 100644 sys/vdpau/gstvdpauvideobuffer.c create mode 100644 sys/vdpau/gstvdpauvideobuffer.h create mode 100644 sys/vdpau/gstvdpauvideoyuv.c create mode 100644 sys/vdpau/gstvdpauvideoyuv.h diff --git a/sys/vdpau/Makefile.am b/sys/vdpau/Makefile.am index 0e3b578e..ba286d54 100644 --- a/sys/vdpau/Makefile.am +++ b/sys/vdpau/Makefile.am @@ -4,7 +4,9 @@ libgstvdpau_la_SOURCES = \ gstvdpaudevice.c \ gstvdpaudecoder.c \ gstvdpaumpegdecoder.c \ - mpegutil.c + mpegutil.c \ + gstvdpauvideoyuv.c \ + gstvdpauvideobuffer.c libgstvdpau_la_CFLAGS = $(GST_CFLAGS) $(X11_CFLAGS) -Ivdpau libgstvdpau_la_LIBADD = $(GST_LIBS) $(GST_BASE_LIBS) \ @@ -16,6 +18,8 @@ noinst_HEADERS = \ gstvdpaudevice.h \ gstvdpaudecoder.h \ gstvdpaumpegdecoder.h \ + gstvdpauvideoyuv.h \ + gstvdpauvideobuffer.h \ mpegutil.h diff --git a/sys/vdpau/gstvdpaudecoder.c b/sys/vdpau/gstvdpaudecoder.c index 5a8bbacd..4db93f7e 100644 --- a/sys/vdpau/gstvdpaudecoder.c +++ b/sys/vdpau/gstvdpaudecoder.c @@ -25,6 +25,7 @@ #include #include +#include "gstvdpauvideobuffer.h" #include "gstvdpaudecoder.h" GST_DEBUG_CATEGORY_STATIC (gst_vdpau_decoder_debug); @@ -47,9 +48,7 @@ enum static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, - GST_STATIC_CAPS ("video/x-raw-yuv, " - "framerate = (fraction) [ 0, MAX ], " - "width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]")); + GST_STATIC_CAPS ("video/vdpau-video, " "chroma-type = (int) 0")); #define DEBUG_INIT(bla) \ GST_DEBUG_CATEGORY_INIT (gst_vdpau_decoder_debug, "vdpaudecoder", 0, "vdpaudecoder base class"); @@ -64,100 +63,9 @@ static void gst_vdpau_decoder_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); GstFlowReturn -gst_vdpau_decoder_push_video_surface (GstVdpauDecoder * dec, - VdpVideoSurface surface) +gst_vdpau_decoder_push_video_buffer (GstVdpauDecoder * dec, + GstVdpauVideoBuffer * buffer) { - GstVdpauDevice *device; - GstBuffer *buffer; - - device = dec->device; - - switch (dec->format) { - case GST_MAKE_FOURCC ('Y', 'V', '1', '2'): - { - gint size; - GstFlowReturn result; - VdpStatus status; - guint8 *data[3]; - guint32 stride[3]; - - size = - gst_video_format_get_size (GST_VIDEO_FORMAT_YV12, dec->width, - dec->height); - result = - gst_pad_alloc_buffer_and_set_caps (dec->src, GST_BUFFER_OFFSET_NONE, - size, GST_PAD_CAPS (dec->src), &buffer); - if (G_UNLIKELY (result != GST_FLOW_OK)) - return result; - - - data[0] = GST_BUFFER_DATA (buffer) + - gst_video_format_get_component_offset (GST_VIDEO_FORMAT_YV12, - 0, dec->width, dec->height); - data[1] = data[0] + - gst_video_format_get_component_offset (GST_VIDEO_FORMAT_YV12, - 2, dec->width, dec->height); - data[2] = data[0] + - gst_video_format_get_component_offset (GST_VIDEO_FORMAT_YV12, - 1, dec->width, dec->height); - - stride[0] = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_YV12, - 0, dec->width); - stride[1] = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_YV12, - 2, dec->width); - stride[2] = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_YV12, - 1, dec->width); - - status = - device->vdp_video_surface_get_bits_ycbcr (surface, - VDP_YCBCR_FORMAT_YV12, (void *) data, stride); - if (G_UNLIKELY (status != VDP_STATUS_OK)) { - GST_ELEMENT_ERROR (dec, RESOURCE, READ, - ("Couldn't get data from vdpau"), - ("Error returned from vdpau was: %s", - device->vdp_get_error_string (status))); - return GST_FLOW_ERROR; - } - break; - } - case GST_MAKE_FOURCC ('N', 'V', '1', '2'): - { - gint size; - GstFlowReturn result; - VdpStatus status; - guint8 *data[2]; - guint32 stride[2]; - - size = dec->width * dec->height + dec->width * dec->height / 2; - result = - gst_pad_alloc_buffer_and_set_caps (dec->src, GST_BUFFER_OFFSET_NONE, - size, GST_PAD_CAPS (dec->src), &buffer); - if (G_UNLIKELY (result != GST_FLOW_OK)) - return result; - - - data[0] = GST_BUFFER_DATA (buffer); - data[1] = data[0] + dec->width * dec->height; - - stride[0] = dec->width; - stride[1] = dec->width; - - status = - device->vdp_video_surface_get_bits_ycbcr (surface, - VDP_YCBCR_FORMAT_NV12, (void *) data, stride); - if (G_UNLIKELY (status != VDP_STATUS_OK)) { - GST_ELEMENT_ERROR (dec, RESOURCE, READ, - ("Couldn't get data from vdpau"), - ("Error returned from vdpau was: %s", - device->vdp_get_error_string (status))); - return GST_FLOW_ERROR; - } - break; - } - default: - break; - } - GST_BUFFER_TIMESTAMP (buffer) = gst_util_uint64_scale_int (GST_SECOND * dec->frame_nr, dec->framerate_denominator, dec->framerate_numerator); @@ -167,167 +75,9 @@ gst_vdpau_decoder_push_video_surface (GstVdpauDecoder * dec, GST_BUFFER_OFFSET (buffer) = dec->frame_nr; dec->frame_nr++; GST_BUFFER_OFFSET_END (buffer) = dec->frame_nr; + gst_buffer_set_caps (GST_BUFFER (buffer), GST_PAD_CAPS (dec->src)); - return gst_pad_push (dec->src, buffer); -} - -typedef struct -{ - VdpChromaType chroma_type; - VdpYCbCrFormat format; - guint32 fourcc; -} VdpauFormats; - -static VdpChromaType chroma_types[3] = - { VDP_CHROMA_TYPE_420, VDP_CHROMA_TYPE_422, VDP_CHROMA_TYPE_444 }; -static VdpauFormats formats[6] = { - { - VDP_CHROMA_TYPE_420, - VDP_YCBCR_FORMAT_NV12, - GST_MAKE_FOURCC ('N', 'V', '1', '2') - }, - { - VDP_CHROMA_TYPE_422, - VDP_YCBCR_FORMAT_UYVY, - GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y') - }, - { - VDP_CHROMA_TYPE_444, - VDP_YCBCR_FORMAT_V8U8Y8A8, - GST_MAKE_FOURCC ('A', 'Y', 'U', 'V') - }, - { - VDP_CHROMA_TYPE_444, - VDP_YCBCR_FORMAT_Y8U8V8A8, - GST_MAKE_FOURCC ('A', 'V', 'U', 'Y') - }, - { - VDP_CHROMA_TYPE_422, - VDP_YCBCR_FORMAT_YUYV, - GST_MAKE_FOURCC ('Y', 'U', 'Y', 'V') - }, - { - VDP_CHROMA_TYPE_420, - VDP_YCBCR_FORMAT_YV12, - GST_MAKE_FOURCC ('Y', 'V', '1', '2') - } -}; - -VdpVideoSurface -gst_vdpau_decoder_create_video_surface (GstVdpauDecoder * dec) -{ - GstVdpauDevice *device; - VdpChromaType chroma_type; - gint i; - VdpStatus status; - VdpVideoSurface surface; - - device = dec->device; - - chroma_type = VDP_CHROMA_TYPE_422; - for (i = 0; i < 6; i++) { - if (formats[i].fourcc == dec->format) { - chroma_type = formats[i].chroma_type; - break; - } - } - - status = - device->vdp_video_surface_create (device->device, chroma_type, dec->width, - dec->height, &surface); - if (status != VDP_STATUS_OK) { - GST_ELEMENT_ERROR (dec, RESOURCE, READ, - ("Couldn't create a VdpVideoSurface"), - ("Error returned from vdpau was: %s", - device->vdp_get_error_string (status))); - return VDP_INVALID_HANDLE; - } - - return surface; -} - -static GstCaps * -gst_vdpau_decoder_get_vdpau_support (GstVdpauDecoder * dec) -{ - GstVdpauDevice *device; - GstCaps *caps; - gint i; - - device = dec->device; - - caps = gst_caps_new_empty (); - - for (i = 0; i < 3; i++) { - VdpStatus status; - VdpBool is_supported; - guint32 max_w, max_h; - - status = - device->vdp_video_surface_query_capabilities (device->device, - chroma_types[i], &is_supported, &max_w, &max_h); - - if (status != VDP_STATUS_OK && status != VDP_STATUS_INVALID_CHROMA_TYPE) { - GST_ELEMENT_ERROR (dec, RESOURCE, READ, - ("Could not get query VDPAU video surface capabilites"), - ("Error returned from vdpau was: %s", - device->vdp_get_error_string (status))); - - return NULL; - } - if (is_supported) { - gint j; - - for (j = 0; j < 6; j++) { - if (formats[j].chroma_type != chroma_types[i]) - continue; - - status = - device->vdp_video_surface_query_ycbcr_capabilities (device->device, - formats[j].chroma_type, formats[j].format, &is_supported); - if (status != VDP_STATUS_OK - && status != VDP_STATUS_INVALID_Y_CB_CR_FORMAT) { - GST_ELEMENT_ERROR (dec, RESOURCE, READ, - ("Could not query VDPAU YCbCr capabilites"), - ("Error returned from vdpau was: %s", - device->vdp_get_error_string (status))); - - return NULL; - } - if (is_supported) { - GstCaps *format_caps; - - format_caps = gst_caps_new_simple ("video/x-raw-yuv", - "format", GST_TYPE_FOURCC, formats[j].fourcc, - "width", GST_TYPE_INT_RANGE, 1, max_w, - "height", GST_TYPE_INT_RANGE, 1, max_h, - "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL); - gst_caps_append (caps, format_caps); - } - } - } - } - if (gst_caps_is_empty (caps)) { - gst_caps_unref (caps); - return NULL; - } - - return caps; -} - -static gboolean -gst_vdpau_decoder_init_vdpau (GstVdpauDecoder * dec) -{ - GstCaps *caps; - - dec->device = gst_vdpau_get_device (dec->display_name); - - caps = gst_vdpau_decoder_get_vdpau_support (dec); - if (!caps) - return FALSE; - - dec->src_caps = caps; - - return TRUE; + return gst_pad_push (dec->src, GST_BUFFER (buffer)); } static GstStateChangeReturn @@ -339,8 +89,7 @@ gst_vdpau_decoder_change_state (GstElement * element, GstStateChange transition) switch (transition) { case GST_STATE_CHANGE_NULL_TO_READY: - if (!gst_vdpau_decoder_init_vdpau (dec)) - return GST_STATE_CHANGE_FAILURE; + dec->device = gst_vdpau_get_device (dec->display_name); break; case GST_STATE_CHANGE_READY_TO_NULL: g_object_unref (dec->device); @@ -364,7 +113,6 @@ gst_vdpau_decoder_sink_set_caps (GstPad * pad, GstCaps * caps) gint width, height; gint framerate_numerator, framerate_denominator; gint par_numerator, par_denominator; - guint32 fourcc_format; gboolean res; structure = gst_caps_get_structure (caps, 0); @@ -382,8 +130,9 @@ gst_vdpau_decoder_sink_set_caps (GstPad * pad, GstCaps * caps) new_caps = gst_caps_copy_nth (src_caps, 0); gst_caps_unref (src_caps); structure = gst_caps_get_structure (new_caps, 0); - gst_structure_get_fourcc (structure, "format", &fourcc_format); gst_structure_set (structure, + "device", G_TYPE_OBJECT, dec->device, + "chroma-type", G_TYPE_INT, VDP_CHROMA_TYPE_420, "width", G_TYPE_INT, width, "height", G_TYPE_INT, height, "framerate", GST_TYPE_FRACTION, framerate_numerator, @@ -403,7 +152,6 @@ gst_vdpau_decoder_sink_set_caps (GstPad * pad, GstCaps * caps) dec->height = height; dec->framerate_numerator = framerate_numerator; dec->framerate_denominator = framerate_denominator; - dec->format = fourcc_format; if (dec_class->set_caps && !dec_class->set_caps (dec, caps)) return FALSE; @@ -411,22 +159,6 @@ gst_vdpau_decoder_sink_set_caps (GstPad * pad, GstCaps * caps) return TRUE; } -static GstCaps * -gst_vdpau_decoder_src_getcaps (GstPad * pad) -{ - GstVdpauDecoder *dec; - - dec = GST_VDPAU_DECODER (GST_OBJECT_PARENT (pad)); - - if (GST_PAD_CAPS (dec->src)) - return gst_caps_ref (GST_PAD_CAPS (dec->src)); - - if (dec->src_caps) - return gst_caps_ref (dec->src_caps); - - return gst_caps_copy (gst_pad_get_pad_template_caps (dec->src)); -} - /* GObject vmethod implementations */ static void @@ -475,18 +207,15 @@ gst_vdpau_decoder_init (GstVdpauDecoder * dec, GstVdpauDecoderClass * klass) dec->display_name = NULL; dec->device = NULL; dec->silent = FALSE; - dec->src_caps = NULL; dec->height = 0; dec->width = 0; dec->framerate_numerator = 0; dec->framerate_denominator = 0; - dec->format = 0; dec->frame_nr = 0; dec->src = gst_pad_new_from_static_template (&src_template, "src"); - gst_pad_set_getcaps_function (dec->src, gst_vdpau_decoder_src_getcaps); gst_element_add_pad (GST_ELEMENT (dec), dec->src); dec->sink = gst_pad_new_from_template (gst_element_class_get_pad_template @@ -501,8 +230,6 @@ gst_vdpau_decoder_finalize (GObject * object) { GstVdpauDecoder *dec = (GstVdpauDecoder *) object; - if (dec->src_caps) - g_object_unref (dec->src_caps); if (dec->device) g_object_unref (dec->device); diff --git a/sys/vdpau/gstvdpaudecoder.h b/sys/vdpau/gstvdpaudecoder.h index 415d6eca..ef3a6fb9 100644 --- a/sys/vdpau/gstvdpaudecoder.h +++ b/sys/vdpau/gstvdpaudecoder.h @@ -47,8 +47,6 @@ struct _GstVdpauDecoder { GstPad *src; GstPad *sink; - GstCaps *src_caps; - gint width, height; gint framerate_numerator, framerate_denominator; guint32 format; @@ -66,8 +64,8 @@ struct _GstVdpauDecoderClass { GType gst_vdpau_decoder_get_type (void); -gboolean gst_vdpau_decoder_push_video_surface (GstVdpauDecoder * dec, - VdpVideoSurface surface); +gboolean gst_vdpau_decoder_push_video_buffer (GstVdpauDecoder * dec, + GstVdpauVideoBuffer *buffer); VdpVideoSurface gst_vdpau_decoder_create_video_surface (GstVdpauDecoder *dec); G_END_DECLS diff --git a/sys/vdpau/gstvdpaumpegdecoder.c b/sys/vdpau/gstvdpaumpegdecoder.c index fba52d39..80ee13ca 100644 --- a/sys/vdpau/gstvdpaumpegdecoder.c +++ b/sys/vdpau/gstvdpaumpegdecoder.c @@ -38,6 +38,8 @@ #include #include +#include "gstvdpauvideobuffer.h" +#include "gstvdpauvideoyuv.h" #include "mpegutil.h" #include "gstvdpaumpegdecoder.h" @@ -133,19 +135,20 @@ gst_vdpau_mpeg_decoder_decode (GstVdpauMpegDecoder * mpeg_dec) { GstVdpauDecoder *dec; GstBuffer *buffer; + GstVdpauVideoBuffer *outbuf; VdpVideoSurface surface; GstVdpauDevice *device; VdpBitstreamBuffer vbit[1]; VdpStatus status; - GstFlowReturn ret; dec = GST_VDPAU_DECODER (mpeg_dec); buffer = gst_adapter_take_buffer (mpeg_dec->adapter, gst_adapter_available (mpeg_dec->adapter)); - surface = - gst_vdpau_decoder_create_video_surface (GST_VDPAU_DECODER (mpeg_dec)); + outbuf = gst_vdpau_video_buffer_new (dec->device, VDP_CHROMA_TYPE_420, + dec->width, dec->height); + surface = outbuf->surface; device = dec->device; @@ -165,23 +168,23 @@ gst_vdpau_mpeg_decoder_decode (GstVdpauMpegDecoder * mpeg_dec) device->vdp_get_error_string (status))); if (mpeg_dec->vdp_info.forward_reference != VDP_INVALID_HANDLE) - device->vdp_video_surface_destroy (mpeg_dec->vdp_info.forward_reference); + gst_buffer_unref (mpeg_dec->f_buffer); - device->vdp_video_surface_destroy (surface); + gst_buffer_unref (GST_BUFFER (outbuf)); return GST_FLOW_ERROR; } - ret = - gst_vdpau_decoder_push_video_surface (GST_VDPAU_DECODER (mpeg_dec), - surface); + gst_buffer_ref (GST_BUFFER (outbuf)); if (mpeg_dec->vdp_info.forward_reference != VDP_INVALID_HANDLE) - device->vdp_video_surface_destroy (mpeg_dec->vdp_info.forward_reference); + gst_buffer_unref (mpeg_dec->f_buffer); mpeg_dec->vdp_info.forward_reference = surface; + mpeg_dec->f_buffer = GST_BUFFER (outbuf); - return ret; + return gst_vdpau_decoder_push_video_buffer (GST_VDPAU_DECODER (mpeg_dec), + outbuf); } static gboolean @@ -228,8 +231,7 @@ gst_vdpau_mpeg_decoder_parse_picture (GstVdpauMpegDecoder * mpeg_dec, if (pic_hdr.pic_type == I_FRAME && mpeg_dec->vdp_info.forward_reference != VDP_INVALID_HANDLE) { - dec->device->vdp_video_surface_destroy (mpeg_dec-> - vdp_info.forward_reference); + gst_buffer_unref (mpeg_dec->f_buffer); mpeg_dec->vdp_info.forward_reference = VDP_INVALID_HANDLE; } @@ -421,11 +423,6 @@ gst_vdpau_mpeg_decoder_finalize (GObject * object) { GstVdpauMpegDecoder *mpeg_dec = (GstVdpauMpegDecoder *) object; -#if 0 /* FIXME: can't free the decoder since the device already has been freed */ - if (mpeg_dec->decoder != VDP_INVALID_HANDLE) - dec->device->vdp_decoder_destroy (mpeg_dec->decoder); -#endif - g_object_unref (mpeg_dec->adapter); } @@ -475,8 +472,12 @@ vdpaumpegdecoder_init (GstPlugin * vdpaumpegdecoder) GST_DEBUG_CATEGORY_INIT (gst_vdpau_mpeg_decoder_debug, "vdpaumpegdecoder", 0, "Template vdpaumpegdecoder"); - return gst_element_register (vdpaumpegdecoder, "vdpaumpegdecoder", + gst_element_register (vdpaumpegdecoder, "vdpaumpegdecoder", GST_RANK_NONE, GST_TYPE_VDPAU_MPEG_DECODER); + gst_element_register (vdpaumpegdecoder, "vdpauvideoyuv", + GST_RANK_NONE, GST_TYPE_VDPAU_VIDEO_YUV); + + return TRUE; } /* gstreamer looks for this structure to register vdpaumpegdecoders diff --git a/sys/vdpau/gstvdpaumpegdecoder.h b/sys/vdpau/gstvdpaumpegdecoder.h index 4b4c6550..d251480c 100644 --- a/sys/vdpau/gstvdpaumpegdecoder.h +++ b/sys/vdpau/gstvdpaumpegdecoder.h @@ -47,10 +47,10 @@ struct _GstVdpauMpegDecoder VdpDecoder decoder; VdpPictureInfoMPEG1Or2 vdp_info; + GstBuffer *f_buffer; GstAdapter *adapter; gint slices; - }; struct _GstVdpauMpegDecoderClass diff --git a/sys/vdpau/gstvdpauvideobuffer.c b/sys/vdpau/gstvdpauvideobuffer.c new file mode 100644 index 00000000..f7ece0eb --- /dev/null +++ b/sys/vdpau/gstvdpauvideobuffer.c @@ -0,0 +1,114 @@ +/* + * GStreamer + * Copyright (C) 2009 Carl-Anton Ingmarsson + * + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstvdpauvideobuffer.h" + +static GObjectClass *gst_vdpau_video_buffer_parent_class; + +static void +gst_vdpau_video_buffer_finalize (GstVdpauVideoBuffer * buffer) +{ + GstVdpauDevice *device = buffer->device; + VdpStatus status; + + status = device->vdp_video_surface_destroy (buffer->surface); + if (status != VDP_STATUS_OK) + GST_ERROR + ("Couldn't destroy the buffers VdpVideoSurface, error returned was: %s", + device->vdp_get_error_string (status)); + + g_object_unref (buffer->device); + + GST_MINI_OBJECT_CLASS (gst_vdpau_video_buffer_parent_class)->finalize + (GST_MINI_OBJECT (buffer)); +} + +static void +gst_vdpau_video_buffer_init (GstVdpauVideoBuffer * buffer, gpointer g_class) +{ + buffer->device = NULL; + buffer->surface = VDP_INVALID_HANDLE; +} + +static void +gst_vdpau_video_buffer_class_init (gpointer g_class, gpointer class_data) +{ + GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class); + + gst_vdpau_video_buffer_parent_class = g_type_class_peek_parent (g_class); + + mini_object_class->finalize = (GstMiniObjectFinalizeFunction) + gst_vdpau_video_buffer_finalize; +} + + +GType +gst_vdpau_video_buffer_get_type (void) +{ + static GType _gst_vdpau_video_buffer_type; + + if (G_UNLIKELY (_gst_vdpau_video_buffer_type == 0)) { + static const GTypeInfo info = { + sizeof (GstBufferClass), + NULL, + NULL, + gst_vdpau_video_buffer_class_init, + NULL, + NULL, + sizeof (GstVdpauVideoBuffer), + 0, + (GInstanceInitFunc) gst_vdpau_video_buffer_init, + NULL + }; + _gst_vdpau_video_buffer_type = g_type_register_static (GST_TYPE_BUFFER, + "GstVdpauVideoBuffer", &info, 0); + } + return _gst_vdpau_video_buffer_type; +} + + +GstVdpauVideoBuffer * +gst_vdpau_video_buffer_new (GstVdpauDevice * device, VdpChromaType chroma_type, + gint width, gint height) +{ + GstVdpauVideoBuffer *buffer; + VdpStatus status; + VdpVideoSurface surface; + + status = device->vdp_video_surface_create (device->device, chroma_type, width, + height, &surface); + if (status != VDP_STATUS_OK) { + GST_ERROR ("Couldn't create a VdpVideoSurface, error returned was: %s", + device->vdp_get_error_string (status)); + return NULL; + } + + buffer = + (GstVdpauVideoBuffer *) gst_mini_object_new (GST_TYPE_VDPAU_VIDEO_BUFFER); + + buffer->device = g_object_ref (device); + buffer->surface = surface; + + return buffer; +} diff --git a/sys/vdpau/gstvdpauvideobuffer.h b/sys/vdpau/gstvdpauvideobuffer.h new file mode 100644 index 00000000..fe2b4b7f --- /dev/null +++ b/sys/vdpau/gstvdpauvideobuffer.h @@ -0,0 +1,55 @@ +/* + * GStreamer + * Copyright (C) 2009 Carl-Anton Ingmarsson + * + * 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_VDPAU_VIDEO_BUFFER_H_ +#define _GST_VDPAU_VIDEO_BUFFER_H_ + +#include +#include + +#include "gstvdpaudevice.h" + +#include "gstvdpauvideobuffer.h" + +typedef struct _GstVdpauVideoBuffer GstVdpauVideoBuffer; + +#define GST_TYPE_VDPAU_VIDEO_BUFFER (gst_vdpau_video_buffer_get_type()) + +#define GST_IS_VDPAU_VIDEO_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_VDPAU_VIDEO_BUFFER)) +#define GST_VDPAU_VIDEO_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_VDPAU_VIDEO_BUFFER, GstVdpauVideoBuffer)) + +struct _GstVdpauVideoBuffer { + GstBuffer buffer; + + GstVdpauDevice *device; + VdpVideoSurface surface; +}; + +GType gst_vdpau_video_buffer_get_type (void); + +GstVdpauVideoBuffer* gst_vdpau_video_buffer_new (GstVdpauDevice * device, VdpChromaType chroma_type, gint width, gint height); + +#define GST_VDPAU_VIDEO_CAPS \ + "video/vdpau-video, " \ + "chroma-type = (int)[0,2], " \ + "width = (int)[1,4096], " \ + "height = (int)[1,4096]" + +#endif diff --git a/sys/vdpau/gstvdpauvideoyuv.c b/sys/vdpau/gstvdpauvideoyuv.c new file mode 100644 index 00000000..1de17045 --- /dev/null +++ b/sys/vdpau/gstvdpauvideoyuv.c @@ -0,0 +1,454 @@ +/* + * GStreamer + * Copyright (C) 2009 Carl-Anton Ingmarsson + * + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include "gstvdpauvideobuffer.h" +#include "gstvdpauvideoyuv.h" + +GST_DEBUG_CATEGORY_STATIC (gst_vdpau_video_yuv_debug); +#define GST_CAT_DEFAULT gst_vdpau_video_yuv_debug + +/* Filter signals and args */ +enum +{ + /* FILL ME */ + LAST_SIGNAL +}; + +enum +{ + PROP_0, + PROP_SILENT +}; + +static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (GST_VDPAU_VIDEO_CAPS)); + +static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("video/x-raw-yuv, " + "framerate = (fraction) [ 0, MAX ], " + "width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]")); + +#define DEBUG_INIT(bla) \ + GST_DEBUG_CATEGORY_INIT (gst_vdpau_video_yuv_debug, "vdpauvideo_yuv", 0, "vdpauvideo_yuv base class"); + +GST_BOILERPLATE_FULL (GstVdpauVideoYUV, gst_vdpau_video_yuv, GstElement, + GST_TYPE_ELEMENT, DEBUG_INIT); + +static void gst_vdpau_video_yuv_finalize (GObject * object); +static void gst_vdpau_video_yuv_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_vdpau_video_yuv_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +GstFlowReturn +gst_vdpau_video_yuv_chain (GstPad * pad, GstBuffer * buffer) +{ + GstVdpauVideoYUV *video_yuv; + GstVdpauDevice *device; + VdpVideoSurface surface; + GstBuffer *outbuf = NULL; + + video_yuv = GST_VDPAU_VIDEO_YUV (GST_OBJECT_PARENT (pad)); + device = GST_VDPAU_VIDEO_BUFFER (buffer)->device; + surface = GST_VDPAU_VIDEO_BUFFER (buffer)->surface; + + switch (video_yuv->format) { + case GST_MAKE_FOURCC ('Y', 'V', '1', '2'): + { + gint size; + GstFlowReturn result; + VdpStatus status; + guint8 *data[3]; + guint32 stride[3]; + + size = + gst_video_format_get_size (GST_VIDEO_FORMAT_YV12, video_yuv->width, + video_yuv->height); + result = + gst_pad_alloc_buffer_and_set_caps (video_yuv->src, + GST_BUFFER_OFFSET_NONE, size, GST_PAD_CAPS (video_yuv->src), &outbuf); + if (G_UNLIKELY (result != GST_FLOW_OK)) + return result; + + data[0] = GST_BUFFER_DATA (outbuf) + + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_YV12, + 0, video_yuv->width, video_yuv->height); + data[1] = data[0] + + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_YV12, + 2, video_yuv->width, video_yuv->height); + data[2] = data[0] + + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_YV12, + 1, video_yuv->width, video_yuv->height); + + stride[0] = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_YV12, + 0, video_yuv->width); + stride[1] = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_YV12, + 2, video_yuv->width); + stride[2] = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_YV12, + 1, video_yuv->width); + + status = + device->vdp_video_surface_get_bits_ycbcr (surface, + VDP_YCBCR_FORMAT_YV12, (void *) data, stride); + if (G_UNLIKELY (status != VDP_STATUS_OK)) { + GST_ELEMENT_ERROR (video_yuv, RESOURCE, READ, + ("Couldn't get data from vdpau"), + ("Error returned from vdpau was: %s", + device->vdp_get_error_string (status))); + return GST_FLOW_ERROR; + } + break; + } + case GST_MAKE_FOURCC ('N', 'V', '1', '2'): + { + gint size; + GstFlowReturn result; + VdpStatus status; + guint8 *data[2]; + guint32 stride[2]; + + size = + video_yuv->width * video_yuv->height + + video_yuv->width * video_yuv->height / 2; + result = + gst_pad_alloc_buffer_and_set_caps (video_yuv->src, + GST_BUFFER_OFFSET_NONE, size, GST_PAD_CAPS (video_yuv->src), &outbuf); + if (G_UNLIKELY (result != GST_FLOW_OK)) + return result; + + + data[0] = GST_BUFFER_DATA (outbuf); + data[1] = GST_BUFFER_DATA (outbuf) + video_yuv->width * video_yuv->height; + + stride[0] = video_yuv->width; + stride[1] = video_yuv->width; + + status = + device->vdp_video_surface_get_bits_ycbcr (surface, + VDP_YCBCR_FORMAT_NV12, (void *) data, stride); + if (G_UNLIKELY (status != VDP_STATUS_OK)) { + GST_ELEMENT_ERROR (video_yuv, RESOURCE, READ, + ("Couldn't get data from vdpau"), + ("Error returned from vdpau was: %s", + device->vdp_get_error_string (status))); + return GST_FLOW_ERROR; + } + break; + } + default: + break; + } + + if (outbuf) { + gst_buffer_copy_metadata (outbuf, buffer, GST_BUFFER_COPY_TIMESTAMPS); + + return gst_pad_push (video_yuv->src, outbuf); + } + + return GST_FLOW_ERROR; +} + +typedef struct +{ + VdpChromaType chroma_type; + VdpYCbCrFormat format; + guint32 fourcc; +} VdpauFormats; + +static VdpauFormats formats[6] = { + { + VDP_CHROMA_TYPE_420, + VDP_YCBCR_FORMAT_NV12, + GST_MAKE_FOURCC ('N', 'V', '1', '2') + }, + { + VDP_CHROMA_TYPE_422, + VDP_YCBCR_FORMAT_UYVY, + GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y') + }, + { + VDP_CHROMA_TYPE_444, + VDP_YCBCR_FORMAT_V8U8Y8A8, + GST_MAKE_FOURCC ('A', 'Y', 'U', 'V') + }, + { + VDP_CHROMA_TYPE_444, + VDP_YCBCR_FORMAT_Y8U8V8A8, + GST_MAKE_FOURCC ('A', 'V', 'U', 'Y') + }, + { + VDP_CHROMA_TYPE_422, + VDP_YCBCR_FORMAT_YUYV, + GST_MAKE_FOURCC ('Y', 'U', 'Y', 'V') + }, + { + VDP_CHROMA_TYPE_420, + VDP_YCBCR_FORMAT_YV12, + GST_MAKE_FOURCC ('Y', 'V', '1', '2') + } +}; + +static GstCaps * +gst_vdpau_video_yuv_get_caps (GstVdpauVideoYUV * video_yuv, + GstVdpauDevice * device, gint chroma_type, gint width, gint height, + gint framerate_numerator, gint framerate_denominator, gint par_numerator, + gint par_denominator) +{ + GstCaps *caps; + gint i; + + caps = gst_caps_new_empty (); + + for (i = 0; i < 6; i++) { + VdpStatus status; + VdpBool is_supported; + + if (formats[i].chroma_type != chroma_type) + continue; + + status = + device->vdp_video_surface_query_ycbcr_capabilities (device->device, + chroma_type, formats[i].format, &is_supported); + if (status != VDP_STATUS_OK && status != VDP_STATUS_INVALID_Y_CB_CR_FORMAT) { + GST_ELEMENT_ERROR (video_yuv, RESOURCE, READ, + ("Could not query VDPAU YCbCr capabilites"), + ("Error returned from vdpau was: %s", + device->vdp_get_error_string (status))); + + return NULL; + } + if (is_supported) { + GstCaps *format_caps; + + format_caps = gst_caps_new_simple ("video/x-raw-yuv", + "format", GST_TYPE_FOURCC, formats[i].fourcc, + "width", G_TYPE_INT, width, + "height", G_TYPE_INT, height, + "framerate", GST_TYPE_FRACTION, framerate_numerator, + framerate_denominator, "pixel-aspect-ratio", GST_TYPE_FRACTION, + par_numerator, par_denominator, NULL); + gst_caps_append (caps, format_caps); + } + } + + if (gst_caps_is_empty (caps)) { + gst_caps_unref (caps); + return NULL; + } + + return caps; +} + +static gboolean +gst_vdpau_video_yuv_sink_set_caps (GstPad * pad, GstCaps * caps) +{ + GstVdpauVideoYUV *video_yuv = GST_VDPAU_VIDEO_YUV (GST_OBJECT_PARENT (pad)); + + GstCaps *src_caps, *new_caps; + GstStructure *structure; + const GValue *value; + GstVdpauDevice *device; + gint chroma_type; + gint width, height; + gint framerate_numerator, framerate_denominator; + gint par_numerator, par_denominator; + guint32 fourcc_format; + gboolean res; + + structure = gst_caps_get_structure (caps, 0); + value = gst_structure_get_value (structure, "device"); + device = g_value_get_object (value); + + gst_structure_get_int (structure, "chroma-type", &chroma_type); + gst_structure_get_int (structure, "width", &width); + gst_structure_get_int (structure, "height", &height); + gst_structure_get_fraction (structure, "framerate", + &framerate_numerator, &framerate_denominator); + gst_structure_get_fraction (structure, "pixel-aspect-ratio", + &par_numerator, &par_denominator); + + src_caps = + gst_vdpau_video_yuv_get_caps (video_yuv, device, chroma_type, width, + height, framerate_numerator, framerate_denominator, par_numerator, + par_denominator); + if (G_UNLIKELY (!src_caps)) + return FALSE; + + video_yuv->src_caps = src_caps; + + src_caps = gst_pad_get_allowed_caps (video_yuv->src); + if (G_UNLIKELY (!src_caps || !gst_caps_get_size (src_caps))) + return FALSE; + + new_caps = gst_caps_copy_nth (src_caps, 0); + gst_caps_unref (src_caps); + if (G_UNLIKELY (!new_caps)) + return FALSE; + + structure = gst_caps_get_structure (new_caps, 0); + gst_structure_get_fourcc (structure, "format", &fourcc_format); + + gst_pad_fixate_caps (video_yuv->src, new_caps); + res = gst_pad_set_caps (video_yuv->src, new_caps); + + gst_caps_unref (new_caps); + + if (G_UNLIKELY (!res)) + return FALSE; + + video_yuv->width = width; + video_yuv->height = height; + video_yuv->framerate_numerator = framerate_numerator; + video_yuv->framerate_denominator = framerate_denominator; + video_yuv->format = fourcc_format; + + return TRUE; +} + +static GstCaps * +gst_vdpau_video_yuv_src_getcaps (GstPad * pad) +{ + GstVdpauVideoYUV *video_yuv; + + video_yuv = GST_VDPAU_VIDEO_YUV (GST_OBJECT_PARENT (pad)); + + if (video_yuv->src_caps) + return gst_caps_copy (video_yuv->src_caps); + + if (GST_PAD_CAPS (video_yuv->src)) + return gst_caps_copy (GST_PAD_CAPS (video_yuv->src)); + + return gst_caps_copy (gst_pad_get_pad_template_caps (video_yuv->src)); +} + +/* GObject vmethod implementations */ + +static void +gst_vdpau_video_yuv_base_init (gpointer klass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + + gst_element_class_set_details_simple (element_class, + "VdpauVideoYUV", + "Covideo_yuv/Decoder/Video", + "VDPAU video surface to YUV", + "Carl-Anton Ingmarsson "); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&sink_template)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&src_template)); +} + +static void +gst_vdpau_video_yuv_class_init (GstVdpauVideoYUVClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + + gobject_class = (GObjectClass *) klass; + gstelement_class = (GstElementClass *) klass; + + gobject_class->finalize = gst_vdpau_video_yuv_finalize; + gobject_class->set_property = gst_vdpau_video_yuv_set_property; + gobject_class->get_property = gst_vdpau_video_yuv_get_property; + + g_object_class_install_property (gobject_class, PROP_SILENT, + g_param_spec_boolean ("silent", "Silent", "Produce verbose output ?", + FALSE, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE)); +} + +static void +gst_vdpau_video_yuv_init (GstVdpauVideoYUV * video_yuv, + GstVdpauVideoYUVClass * klass) +{ + video_yuv->silent = FALSE; + video_yuv->src_caps = NULL; + + video_yuv->height = 0; + video_yuv->width = 0; + video_yuv->framerate_numerator = 0; + video_yuv->framerate_denominator = 0; + video_yuv->par_numerator = 1; + video_yuv->par_denominator = 1; + + video_yuv->src = gst_pad_new_from_static_template (&src_template, "src"); + gst_pad_set_getcaps_function (video_yuv->src, + gst_vdpau_video_yuv_src_getcaps); + gst_element_add_pad (GST_ELEMENT (video_yuv), video_yuv->src); + + video_yuv->sink = gst_pad_new_from_static_template (&sink_template, "sink"); + gst_pad_set_setcaps_function (video_yuv->sink, + gst_vdpau_video_yuv_sink_set_caps); + gst_pad_set_chain_function (video_yuv->sink, gst_vdpau_video_yuv_chain); + gst_element_add_pad (GST_ELEMENT (video_yuv), video_yuv->sink); +} + +static void +gst_vdpau_video_yuv_finalize (GObject * object) +{ + GstVdpauVideoYUV *video_yuv = (GstVdpauVideoYUV *) object; + + if (video_yuv->src_caps) + gst_caps_unref (video_yuv->src_caps); +} + +static void +gst_vdpau_video_yuv_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstVdpauVideoYUV *video_yuv = GST_VDPAU_VIDEO_YUV (object); + + switch (prop_id) { + case PROP_SILENT: + video_yuv->silent = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_vdpau_video_yuv_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstVdpauVideoYUV *video_yuv = GST_VDPAU_VIDEO_YUV (object); + + switch (prop_id) { + case PROP_SILENT: + g_value_set_boolean (value, video_yuv->silent); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} diff --git a/sys/vdpau/gstvdpauvideoyuv.h b/sys/vdpau/gstvdpauvideoyuv.h new file mode 100644 index 00000000..dd033df7 --- /dev/null +++ b/sys/vdpau/gstvdpauvideoyuv.h @@ -0,0 +1,62 @@ +/* + * GStreamer + * Copyright (C) 2009 Carl-Anton Ingmarsson + * + * 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_VDPAU_VIDEO_YUV_H__ +#define __GST_VDPAU_VIDEO_YUV_H__ + +#include + +#include "gstvdpaudevice.h" + +G_BEGIN_DECLS + +#define GST_TYPE_VDPAU_VIDEO_YUV (gst_vdpau_video_yuv_get_type()) +#define GST_VDPAU_VIDEO_YUV(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VDPAU_VIDEO_YUV,GstVdpauVideoYUV)) +#define GST_VDPAU_VIDEO_YUV_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VDPAU_VIDEO_YUV,GstVdpauVideoYUVClass)) +#define GST_VDPAU_VIDEO_YUV_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_VDPAU_VIDEO_YUV, GstVdpauVideoYUVClass)) +#define GST_IS_VDPAU_VIDEO_YUV(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VDPAU_VIDEO_YUV)) +#define GST_IS_VDPAU_VIDEO_YUV_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VDPAU_VIDEO_YUV)) + +typedef struct _GstVdpauVideoYUV GstVdpauVideoYUV; +typedef struct _GstVdpauVideoYUVClass GstVdpauVideoYUVClass; + +struct _GstVdpauVideoYUV { + GstElement element; + + GstPad *src, *sink; + GstCaps *src_caps; + + gint width, height; + gint framerate_numerator, framerate_denominator; + gint par_numerator, par_denominator; + guint format; + + gboolean silent; +}; + +struct _GstVdpauVideoYUVClass { + GstElementClass parent_class; +}; + +GType gst_vdpau_video_yuv_get_type (void); + +G_END_DECLS + +#endif /* __GST_VDPAU_VIDEO_YUV_H__ */ -- cgit v1.2.1 From 3d4a340cfa134615164af6a93b7ce9d36b84f191 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Sat, 4 Apr 2009 22:03:23 +0200 Subject: vdpau: move plugin definition to a new gstvdpau.c file fix up debug categories --- sys/vdpau/Makefile.am | 3 ++- sys/vdpau/gstvdpau.c | 25 +++++++++++++++++++++++++ sys/vdpau/gstvdpaudecoder.h | 3 ++- sys/vdpau/gstvdpaumpegdecoder.c | 40 +++++----------------------------------- sys/vdpau/gstvdpauvideoyuv.c | 2 +- 5 files changed, 35 insertions(+), 38 deletions(-) create mode 100644 sys/vdpau/gstvdpau.c diff --git a/sys/vdpau/Makefile.am b/sys/vdpau/Makefile.am index ba286d54..0b7e5e5c 100644 --- a/sys/vdpau/Makefile.am +++ b/sys/vdpau/Makefile.am @@ -6,7 +6,8 @@ libgstvdpau_la_SOURCES = \ gstvdpaumpegdecoder.c \ mpegutil.c \ gstvdpauvideoyuv.c \ - gstvdpauvideobuffer.c + gstvdpauvideobuffer.c \ + gstvdpau.c libgstvdpau_la_CFLAGS = $(GST_CFLAGS) $(X11_CFLAGS) -Ivdpau libgstvdpau_la_LIBADD = $(GST_LIBS) $(GST_BASE_LIBS) \ diff --git a/sys/vdpau/gstvdpau.c b/sys/vdpau/gstvdpau.c new file mode 100644 index 00000000..04a0ef5b --- /dev/null +++ b/sys/vdpau/gstvdpau.c @@ -0,0 +1,25 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + + +#include + +#include "gstvdpaumpegdecoder.h" +#include "gstvdpauvideoyuv.h" +static gboolean +vdpau_init (GstPlugin * vdpaumpegdecoder) +{ + gst_element_register (vdpaumpegdecoder, "vdpaumpegdecoder", + GST_RANK_NONE, GST_TYPE_VDPAU_MPEG_DECODER); + gst_element_register (vdpaumpegdecoder, "vdpauvideoyuv", + GST_RANK_NONE, GST_TYPE_VDPAU_VIDEO_YUV); + + return TRUE; +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "vdpau", + "Various elements utilizing VDPAU", + vdpau_init, VERSION, "LGPL", "GStreamer", "http://gstreamer.net/") diff --git a/sys/vdpau/gstvdpaudecoder.h b/sys/vdpau/gstvdpaudecoder.h index ef3a6fb9..3f67da68 100644 --- a/sys/vdpau/gstvdpaudecoder.h +++ b/sys/vdpau/gstvdpaudecoder.h @@ -24,6 +24,7 @@ #include #include "gstvdpaudevice.h" +#include "gstvdpauvideobuffer.h" G_BEGIN_DECLS @@ -65,7 +66,7 @@ struct _GstVdpauDecoderClass { GType gst_vdpau_decoder_get_type (void); gboolean gst_vdpau_decoder_push_video_buffer (GstVdpauDecoder * dec, - GstVdpauVideoBuffer *buffer); + GstVdpauVideoBuffer *buffer); VdpVideoSurface gst_vdpau_decoder_create_video_surface (GstVdpauDecoder *dec); G_END_DECLS diff --git a/sys/vdpau/gstvdpaumpegdecoder.c b/sys/vdpau/gstvdpaumpegdecoder.c index 80ee13ca..1c51389c 100644 --- a/sys/vdpau/gstvdpaumpegdecoder.c +++ b/sys/vdpau/gstvdpaumpegdecoder.c @@ -70,8 +70,11 @@ static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink", "systemstream = (boolean) false, parsed = (boolean) true") ); -GST_BOILERPLATE (GstVdpauMpegDecoder, gst_vdpau_mpeg_decoder, GstVdpauDecoder, - GST_TYPE_VDPAU_DECODER); +#define DEBUG_INIT(bla) \ +GST_DEBUG_CATEGORY_INIT (gst_vdpau_mpeg_decoder_debug, "vdpaumpegdecoder", 0, "VDPAU powered mpeg decoder"); + +GST_BOILERPLATE_FULL (GstVdpauMpegDecoder, gst_vdpau_mpeg_decoder, + GstVdpauDecoder, GST_TYPE_VDPAU_DECODER, DEBUG_INIT); static void gst_vdpau_mpeg_decoder_finalize (GObject * object); static void gst_vdpau_mpeg_decoder_set_property (GObject * object, @@ -457,36 +460,3 @@ gst_vdpau_mpeg_decoder_get_property (GObject * object, guint prop_id, break; } } - -/* entry point to initialize the plug-in - * initialize the plug-in itself - * register the element factories and other features - */ -static gboolean -vdpaumpegdecoder_init (GstPlugin * vdpaumpegdecoder) -{ - /* debug category for fltering log messages - * - * exchange the string 'Template vdpaumpegdecoder' with your description - */ - GST_DEBUG_CATEGORY_INIT (gst_vdpau_mpeg_decoder_debug, "vdpaumpegdecoder", - 0, "Template vdpaumpegdecoder"); - - gst_element_register (vdpaumpegdecoder, "vdpaumpegdecoder", - GST_RANK_NONE, GST_TYPE_VDPAU_MPEG_DECODER); - gst_element_register (vdpaumpegdecoder, "vdpauvideoyuv", - GST_RANK_NONE, GST_TYPE_VDPAU_VIDEO_YUV); - - return TRUE; -} - -/* gstreamer looks for this structure to register vdpaumpegdecoders - * - * exchange the string 'Template vdpaumpegdecoder' with your vdpaumpegdecoder description - */ -GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, - GST_VERSION_MINOR, - "vdpaumpegdecoder", - "Template vdpaumpegdecoder", - vdpaumpegdecoder_init, - VERSION, "LGPL", "GStreamer", "http://gstreamer.net/") diff --git a/sys/vdpau/gstvdpauvideoyuv.c b/sys/vdpau/gstvdpauvideoyuv.c index 1de17045..b9be10c1 100644 --- a/sys/vdpau/gstvdpauvideoyuv.c +++ b/sys/vdpau/gstvdpauvideoyuv.c @@ -57,7 +57,7 @@ static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src", "width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]")); #define DEBUG_INIT(bla) \ - GST_DEBUG_CATEGORY_INIT (gst_vdpau_video_yuv_debug, "vdpauvideo_yuv", 0, "vdpauvideo_yuv base class"); + GST_DEBUG_CATEGORY_INIT (gst_vdpau_video_yuv_debug, "vdpauvideoyuv", 0, "VDPAU VdpSurface to YUV"); GST_BOILERPLATE_FULL (GstVdpauVideoYUV, gst_vdpau_video_yuv, GstElement, GST_TYPE_ELEMENT, DEBUG_INIT); -- cgit v1.2.1 From 17a758ec7129976fa910b6ca0d8fd3d19c815158 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Sat, 4 Apr 2009 22:05:11 +0200 Subject: vdpau: remove some unneded includes --- sys/vdpau/gstvdpaudecoder.c | 1 - sys/vdpau/gstvdpaumpegdecoder.c | 2 -- 2 files changed, 3 deletions(-) diff --git a/sys/vdpau/gstvdpaudecoder.c b/sys/vdpau/gstvdpaudecoder.c index 4db93f7e..3d0ced34 100644 --- a/sys/vdpau/gstvdpaudecoder.c +++ b/sys/vdpau/gstvdpaudecoder.c @@ -25,7 +25,6 @@ #include #include -#include "gstvdpauvideobuffer.h" #include "gstvdpaudecoder.h" GST_DEBUG_CATEGORY_STATIC (gst_vdpau_decoder_debug); diff --git a/sys/vdpau/gstvdpaumpegdecoder.c b/sys/vdpau/gstvdpaumpegdecoder.c index 1c51389c..36b546ac 100644 --- a/sys/vdpau/gstvdpaumpegdecoder.c +++ b/sys/vdpau/gstvdpaumpegdecoder.c @@ -38,8 +38,6 @@ #include #include -#include "gstvdpauvideobuffer.h" -#include "gstvdpauvideoyuv.h" #include "mpegutil.h" #include "gstvdpaumpegdecoder.h" -- cgit v1.2.1 From 74485f6fa28ac3413ca5533f7bee695ab7670b47 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Sat, 4 Apr 2009 22:45:09 +0200 Subject: vdpau: VideoYUV unref buffer in chain so that we don't leak them MpegDecoder parse sequence headers --- sys/vdpau/gstvdpaumpegdecoder.c | 28 ++++++++++++++++++++++++++-- sys/vdpau/gstvdpauvideoyuv.c | 6 ++++-- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/sys/vdpau/gstvdpaumpegdecoder.c b/sys/vdpau/gstvdpaumpegdecoder.c index 36b546ac..1910652c 100644 --- a/sys/vdpau/gstvdpaumpegdecoder.c +++ b/sys/vdpau/gstvdpaumpegdecoder.c @@ -141,6 +141,7 @@ gst_vdpau_mpeg_decoder_decode (GstVdpauMpegDecoder * mpeg_dec) GstVdpauDevice *device; VdpBitstreamBuffer vbit[1]; VdpStatus status; + GstFlowReturn ret; dec = GST_VDPAU_DECODER (mpeg_dec); @@ -178,14 +179,16 @@ gst_vdpau_mpeg_decoder_decode (GstVdpauMpegDecoder * mpeg_dec) gst_buffer_ref (GST_BUFFER (outbuf)); + ret = gst_vdpau_decoder_push_video_buffer (GST_VDPAU_DECODER (mpeg_dec), + outbuf); + if (mpeg_dec->vdp_info.forward_reference != VDP_INVALID_HANDLE) gst_buffer_unref (mpeg_dec->f_buffer); mpeg_dec->vdp_info.forward_reference = surface; mpeg_dec->f_buffer = GST_BUFFER (outbuf); - return gst_vdpau_decoder_push_video_buffer (GST_VDPAU_DECODER (mpeg_dec), - outbuf); + return ret; } static gboolean @@ -215,6 +218,26 @@ gst_vdpau_mpeg_decoder_parse_picture_coding (GstVdpauMpegDecoder * mpeg_dec, return TRUE; } +static gboolean +gst_vdpau_mpeg_decoder_parse_sequence (GstVdpauMpegDecoder * mpeg_dec, + guint8 * data, guint8 * end) +{ + GstVdpauDecoder *dec; + MPEGSeqHdr hdr; + + dec = GST_VDPAU_DECODER (mpeg_dec); + + if (!mpeg_util_parse_sequence_hdr (&hdr, data, end)) + return FALSE; + + memcpy (&mpeg_dec->vdp_info.intra_quantizer_matrix, + &hdr.intra_quantizer_matrix, 64); + memcpy (&mpeg_dec->vdp_info.non_intra_quantizer_matrix, + &hdr.non_intra_quantizer_matrix, 64); + + return TRUE; +} + static gboolean gst_vdpau_mpeg_decoder_parse_picture (GstVdpauMpegDecoder * mpeg_dec, guint8 * data, guint8 * end) @@ -320,6 +343,7 @@ gst_vdpau_mpeg_decoder_chain (GstPad * pad, GstBuffer * buffer) break; case MPEG_PACKET_SEQUENCE: GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_SEQUENCE"); + gst_vdpau_mpeg_decoder_parse_sequence (mpeg_dec, data, end); break; case MPEG_PACKET_EXTENSION: GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_EXTENSION"); diff --git a/sys/vdpau/gstvdpauvideoyuv.c b/sys/vdpau/gstvdpauvideoyuv.c index b9be10c1..ca1ec803 100644 --- a/sys/vdpau/gstvdpauvideoyuv.c +++ b/sys/vdpau/gstvdpauvideoyuv.c @@ -123,7 +123,7 @@ gst_vdpau_video_yuv_chain (GstPad * pad, GstBuffer * buffer) ("Couldn't get data from vdpau"), ("Error returned from vdpau was: %s", device->vdp_get_error_string (status))); - return GST_FLOW_ERROR; + break; } break; } @@ -159,7 +159,7 @@ gst_vdpau_video_yuv_chain (GstPad * pad, GstBuffer * buffer) ("Couldn't get data from vdpau"), ("Error returned from vdpau was: %s", device->vdp_get_error_string (status))); - return GST_FLOW_ERROR; + break; } break; } @@ -167,6 +167,8 @@ gst_vdpau_video_yuv_chain (GstPad * pad, GstBuffer * buffer) break; } + gst_buffer_unref (buffer); + if (outbuf) { gst_buffer_copy_metadata (outbuf, buffer, GST_BUFFER_COPY_TIMESTAMPS); -- cgit v1.2.1 From f8e0c0bcc11735e14636c7ea45fd23253e6cef99 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Tue, 7 Apr 2009 20:46:49 +0200 Subject: vdpau: add new GstVdpauYUVVideo element the GstVdpauYUVVideo element takes raw YUV video and outputs GstVdpauVideoBuffers --- sys/vdpau/Makefile.am | 6 +- sys/vdpau/gstvdpau.c | 4 + sys/vdpau/gstvdpaudevice.c | 6 + sys/vdpau/gstvdpaudevice.h | 1 + sys/vdpau/gstvdpauvideoyuv.c | 1 + sys/vdpau/gstvdpauyuvvideo.c | 537 +++++++++++++++++++++++++++++++++++++++++++ sys/vdpau/gstvdpauyuvvideo.h | 64 ++++++ 7 files changed, 617 insertions(+), 2 deletions(-) create mode 100644 sys/vdpau/gstvdpauyuvvideo.c create mode 100644 sys/vdpau/gstvdpauyuvvideo.h diff --git a/sys/vdpau/Makefile.am b/sys/vdpau/Makefile.am index 0b7e5e5c..f10cae89 100644 --- a/sys/vdpau/Makefile.am +++ b/sys/vdpau/Makefile.am @@ -7,7 +7,8 @@ libgstvdpau_la_SOURCES = \ mpegutil.c \ gstvdpauvideoyuv.c \ gstvdpauvideobuffer.c \ - gstvdpau.c + gstvdpau.c \ + gstvdpauyuvvideo.c libgstvdpau_la_CFLAGS = $(GST_CFLAGS) $(X11_CFLAGS) -Ivdpau libgstvdpau_la_LIBADD = $(GST_LIBS) $(GST_BASE_LIBS) \ @@ -19,8 +20,9 @@ noinst_HEADERS = \ gstvdpaudevice.h \ gstvdpaudecoder.h \ gstvdpaumpegdecoder.h \ + mpegutil.h \ gstvdpauvideoyuv.h \ gstvdpauvideobuffer.h \ - mpegutil.h + gstvdpauyuvvideo.h diff --git a/sys/vdpau/gstvdpau.c b/sys/vdpau/gstvdpau.c index 04a0ef5b..24ed3982 100644 --- a/sys/vdpau/gstvdpau.c +++ b/sys/vdpau/gstvdpau.c @@ -7,6 +7,8 @@ #include "gstvdpaumpegdecoder.h" #include "gstvdpauvideoyuv.h" +#include "gstvdpauyuvvideo.h" + static gboolean vdpau_init (GstPlugin * vdpaumpegdecoder) { @@ -14,6 +16,8 @@ vdpau_init (GstPlugin * vdpaumpegdecoder) GST_RANK_NONE, GST_TYPE_VDPAU_MPEG_DECODER); gst_element_register (vdpaumpegdecoder, "vdpauvideoyuv", GST_RANK_NONE, GST_TYPE_VDPAU_VIDEO_YUV); + gst_element_register (vdpaumpegdecoder, "vdpauyuvvideo", + GST_RANK_NONE, GST_TYPE_VDPAU_YUV_VIDEO); return TRUE; } diff --git a/sys/vdpau/gstvdpaudevice.c b/sys/vdpau/gstvdpaudevice.c index 8e314d6d..73929444 100644 --- a/sys/vdpau/gstvdpaudevice.c +++ b/sys/vdpau/gstvdpaudevice.c @@ -83,6 +83,8 @@ gst_vdpau_device_constructed (GObject * object) &device->vdp_video_surface_query_ycbcr_capabilities}, {VDP_FUNC_ID_VIDEO_SURFACE_GET_BITS_Y_CB_CR, &device->vdp_video_surface_get_bits_ycbcr}, + {VDP_FUNC_ID_VIDEO_SURFACE_PUT_BITS_Y_CB_CR, + &device->vdp_video_surface_put_bits_ycbcr}, {VDP_FUNC_ID_VIDEO_SURFACE_GET_PARAMETERS, &device->vdp_video_surface_get_parameters}, {VDP_FUNC_ID_DECODER_CREATE, &device->vdp_decoder_create}, @@ -257,6 +259,10 @@ gst_vdpau_get_device (const gchar * display_name) if (!device) { device = gst_vdpau_device_new (display_name); g_object_weak_ref (G_OBJECT (device), device_destroyed_cb, devices_hash); + if (display_name) + g_hash_table_insert (devices_hash, g_strdup (display_name), device); + else + g_hash_table_insert (devices_hash, g_strdup (""), device); } else g_object_ref (device); diff --git a/sys/vdpau/gstvdpaudevice.h b/sys/vdpau/gstvdpaudevice.h index 0a5cb5e7..a4d147c4 100644 --- a/sys/vdpau/gstvdpaudevice.h +++ b/sys/vdpau/gstvdpaudevice.h @@ -61,6 +61,7 @@ struct _GstVdpauDevice VdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities *vdp_video_surface_query_ycbcr_capabilities; VdpVideoSurfaceGetParameters *vdp_video_surface_get_parameters; VdpVideoSurfaceGetBitsYCbCr *vdp_video_surface_get_bits_ycbcr; + VdpVideoSurfacePutBitsYCbCr *vdp_video_surface_put_bits_ycbcr; VdpDecoderCreate *vdp_decoder_create; VdpDecoderDestroy *vdp_decoder_destroy; diff --git a/sys/vdpau/gstvdpauvideoyuv.c b/sys/vdpau/gstvdpauvideoyuv.c index ca1ec803..7b2e7677 100644 --- a/sys/vdpau/gstvdpauvideoyuv.c +++ b/sys/vdpau/gstvdpauvideoyuv.c @@ -412,6 +412,7 @@ gst_vdpau_video_yuv_init (GstVdpauVideoYUV * video_yuv, gst_vdpau_video_yuv_sink_set_caps); gst_pad_set_chain_function (video_yuv->sink, gst_vdpau_video_yuv_chain); gst_element_add_pad (GST_ELEMENT (video_yuv), video_yuv->sink); + gst_pad_set_active (video_yuv->sink, TRUE); } static void diff --git a/sys/vdpau/gstvdpauyuvvideo.c b/sys/vdpau/gstvdpauyuvvideo.c new file mode 100644 index 00000000..4d78bae2 --- /dev/null +++ b/sys/vdpau/gstvdpauyuvvideo.c @@ -0,0 +1,537 @@ +/* + * GStreamer + * Copyright (C) 2009 Carl-Anton Ingmarsson + * + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include "gstvdpauvideobuffer.h" +#include "gstvdpauyuvvideo.h" + +GST_DEBUG_CATEGORY_STATIC (gst_vdpau_yuv_video_debug); +#define GST_CAT_DEFAULT gst_vdpau_yuv_video_debug + +/* Filter signals and args */ +enum +{ + /* FILL ME */ + LAST_SIGNAL +}; + +enum +{ + PROP_0, + PROP_DISPLAY, + PROP_SILENT +}; + +static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("video/x-raw-yuv, " + "framerate = (fraction) [ 0, MAX ], " + "width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]")); + +static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (GST_VDPAU_VIDEO_CAPS)); + +#define DEBUG_INIT(bla) \ + GST_DEBUG_CATEGORY_INIT (gst_vdpau_yuv_video_debug, "vdpauvideoyuv", 0, "YUV to VDPAU video surface"); + +GST_BOILERPLATE_FULL (GstVdpauYUVVideo, gst_vdpau_yuv_video, GstElement, + GST_TYPE_ELEMENT, DEBUG_INIT); + +static void gst_vdpau_yuv_video_finalize (GObject * object); +static void gst_vdpau_yuv_video_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_vdpau_yuv_video_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +GstFlowReturn +gst_vdpau_yuv_video_chain (GstPad * pad, GstBuffer * buffer) +{ + GstVdpauYUVVideo *yuv_video; + GstVdpauDevice *device; + VdpVideoSurface surface; + GstBuffer *outbuf = NULL; + + yuv_video = GST_VDPAU_YUV_VIDEO (GST_OBJECT_PARENT (pad)); + device = yuv_video->device; + + outbuf = + GST_BUFFER (gst_vdpau_video_buffer_new (device, yuv_video->chroma_type, + yuv_video->width, yuv_video->height)); + surface = GST_VDPAU_VIDEO_BUFFER (outbuf)->surface; + + switch (yuv_video->format) { + case GST_MAKE_FOURCC ('Y', 'V', '1', '2'): + { + VdpStatus status; + guint8 *data[3]; + guint32 stride[3]; + + data[0] = GST_BUFFER_DATA (buffer) + + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_YV12, + 0, yuv_video->width, yuv_video->height); + data[1] = data[0] + + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_YV12, + 2, yuv_video->width, yuv_video->height); + data[2] = data[0] + + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_YV12, + 1, yuv_video->width, yuv_video->height); + + stride[0] = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_YV12, + 0, yuv_video->width); + stride[1] = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_YV12, + 2, yuv_video->width); + stride[2] = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_YV12, + 1, yuv_video->width); + + status = + device->vdp_video_surface_put_bits_ycbcr (surface, + VDP_YCBCR_FORMAT_YV12, (void *) data, stride); + if (G_UNLIKELY (status != VDP_STATUS_OK)) { + GST_ELEMENT_ERROR (yuv_video, RESOURCE, READ, + ("Couldn't push YV12 data to VDPAU"), + ("Error returned from vdpau was: %s", + device->vdp_get_error_string (status))); + break; + } + break; + } + case GST_MAKE_FOURCC ('I', '4', '2', '0'): + { + VdpStatus status; + guint8 *data[3]; + guint32 stride[3]; + + data[0] = GST_BUFFER_DATA (buffer) + + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_I420, + 0, yuv_video->width, yuv_video->height); + data[1] = GST_BUFFER_DATA (buffer) + + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_I420, + 2, yuv_video->width, yuv_video->height); + data[2] = GST_BUFFER_DATA (buffer) + + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_I420, + 1, yuv_video->width, yuv_video->height); + + stride[0] = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_I420, + 0, yuv_video->width); + stride[1] = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_I420, + 2, yuv_video->width); + stride[2] = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_I420, + 1, yuv_video->width); + + status = + device->vdp_video_surface_put_bits_ycbcr (surface, + VDP_YCBCR_FORMAT_YV12, (void *) data, stride); + if (G_UNLIKELY (status != VDP_STATUS_OK)) { + GST_ELEMENT_ERROR (yuv_video, RESOURCE, READ, + ("Couldn't push YV12 data to VDPAU"), + ("Error returned from vdpau was: %s", + device->vdp_get_error_string (status))); + break; + } + break; + } + case GST_MAKE_FOURCC ('N', 'V', '1', '2'): + { + VdpStatus status; + guint8 *data[2]; + guint32 stride[2]; + + data[0] = GST_BUFFER_DATA (buffer); + data[1] = GST_BUFFER_DATA (buffer) + yuv_video->width * yuv_video->height; + + stride[0] = yuv_video->width; + stride[1] = yuv_video->width; + + status = + device->vdp_video_surface_put_bits_ycbcr (surface, + VDP_YCBCR_FORMAT_NV12, (void *) data, stride); + if (G_UNLIKELY (status != VDP_STATUS_OK)) { + GST_ELEMENT_ERROR (yuv_video, RESOURCE, READ, + ("Couldn't get data from vdpau"), + ("Error returned from vdpau was: %s", + device->vdp_get_error_string (status))); + break; + } + break; + } + default: + break; + } + + gst_buffer_unref (buffer); + + if (outbuf) { + gst_buffer_copy_metadata (outbuf, buffer, GST_BUFFER_COPY_TIMESTAMPS); + gst_buffer_set_caps (outbuf, GST_PAD_CAPS (yuv_video->src)); + + return gst_pad_push (yuv_video->src, outbuf); + } + + return GST_FLOW_ERROR; +} + +typedef struct +{ + VdpChromaType chroma_type; + VdpYCbCrFormat format; + guint32 fourcc; +} VdpauFormats; + +static VdpChromaType chroma_types[3] = + { VDP_CHROMA_TYPE_420, VDP_CHROMA_TYPE_422, VDP_CHROMA_TYPE_444 }; +static VdpauFormats formats[7] = { + { + VDP_CHROMA_TYPE_420, + VDP_YCBCR_FORMAT_NV12, + GST_MAKE_FOURCC ('N', 'V', '1', '2') + }, + { + VDP_CHROMA_TYPE_422, + VDP_YCBCR_FORMAT_UYVY, + GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y') + }, + { + VDP_CHROMA_TYPE_444, + VDP_YCBCR_FORMAT_V8U8Y8A8, + GST_MAKE_FOURCC ('A', 'Y', 'U', 'V') + }, + { + VDP_CHROMA_TYPE_444, + VDP_YCBCR_FORMAT_Y8U8V8A8, + GST_MAKE_FOURCC ('A', 'V', 'U', 'Y') + }, + { + VDP_CHROMA_TYPE_422, + VDP_YCBCR_FORMAT_YUYV, + GST_MAKE_FOURCC ('Y', 'U', 'Y', 'V') + }, + { + VDP_CHROMA_TYPE_420, + VDP_YCBCR_FORMAT_YV12, + GST_MAKE_FOURCC ('Y', 'V', '1', '2') + }, + { + VDP_CHROMA_TYPE_420, + VDP_YCBCR_FORMAT_YV12, + GST_MAKE_FOURCC ('I', '4', '2', '0') + } +}; + +static GstCaps * +gst_vdpau_yuv_video_get_caps (GstVdpauYUVVideo * yuv_video) +{ + GstVdpauDevice *device; + GstCaps *caps; + gint i; + + device = yuv_video->device; + + caps = gst_caps_new_empty (); + + for (i = 0; i < 3; i++) { + VdpStatus status; + VdpBool is_supported; + guint32 max_w, max_h; + + status = + device->vdp_video_surface_query_capabilities (device->device, + chroma_types[i], &is_supported, &max_w, &max_h); + + if (status != VDP_STATUS_OK && status != VDP_STATUS_INVALID_CHROMA_TYPE) { + GST_ELEMENT_ERROR (yuv_video, RESOURCE, READ, + ("Could not get query VDPAU video surface capabilites"), + ("Error returned from vdpau was: %s", + device->vdp_get_error_string (status))); + + goto error; + } + if (is_supported) { + gint j; + + for (j = 0; j < 7; j++) { + if (formats[j].chroma_type != chroma_types[i]) + continue; + + status = + device->vdp_video_surface_query_ycbcr_capabilities (device->device, + formats[j].chroma_type, formats[j].format, &is_supported); + if (status != VDP_STATUS_OK + && status != VDP_STATUS_INVALID_Y_CB_CR_FORMAT) { + GST_ELEMENT_ERROR (yuv_video, RESOURCE, READ, + ("Could not query VDPAU YCbCr capabilites"), + ("Error returned from vdpau was: %s", + device->vdp_get_error_string (status))); + + goto error; + } + if (is_supported) { + GstCaps *format_caps; + + format_caps = gst_caps_new_simple ("video/x-raw-yuv", + "format", GST_TYPE_FOURCC, formats[j].fourcc, + "width", GST_TYPE_INT_RANGE, 1, max_w, + "height", GST_TYPE_INT_RANGE, 1, max_h, + "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL); + gst_caps_append (caps, format_caps); + } + } + } + } +error: + if (gst_caps_is_empty (caps)) { + gst_caps_unref (caps); + return NULL; + } + + return caps; +} + +static gboolean +gst_vdpau_yuv_video_sink_setcaps (GstPad * pad, GstCaps * caps) +{ + GstVdpauYUVVideo *yuv_video = GST_VDPAU_YUV_VIDEO (GST_OBJECT_PARENT (pad)); + + GstStructure *structure; + guint32 fourcc; + gint chroma_type = 0; + gint width, height; + gint framerate_numerator, framerate_denominator; + gint par_numerator, par_denominator; + gint i; + GstCaps *src_caps, *new_caps; + gboolean res; + + structure = gst_caps_get_structure (caps, 0); + + gst_structure_get_fourcc (structure, "format", &fourcc); + gst_structure_get_int (structure, "width", &width); + gst_structure_get_int (structure, "height", &height); + gst_structure_get_fraction (structure, "framerate", + &framerate_numerator, &framerate_denominator); + gst_structure_get_fraction (structure, "pixel-aspect-ratio", + &par_numerator, &par_denominator); + + for (i = 0; i < 7; i++) { + if (formats[i].fourcc == fourcc) { + chroma_type = formats[i].chroma_type; + break; + } + } + + src_caps = gst_pad_get_allowed_caps (yuv_video->src); + if (G_UNLIKELY (!src_caps || !gst_caps_get_size (src_caps))) + return FALSE; + + new_caps = gst_caps_copy_nth (src_caps, 0); + gst_caps_unref (src_caps); + if (G_UNLIKELY (!new_caps)) + return FALSE; + + structure = gst_caps_get_structure (new_caps, 0); + + gst_structure_set (structure, + "device", G_TYPE_OBJECT, yuv_video->device, + "chroma-type", G_TYPE_INT, chroma_type, + "width", G_TYPE_INT, width, + "height", G_TYPE_INT, height, + "framerate", GST_TYPE_FRACTION, framerate_numerator, + framerate_denominator, "pixel-aspect-ratio", GST_TYPE_FRACTION, + par_numerator, par_denominator, NULL); + + gst_pad_fixate_caps (yuv_video->src, new_caps); + res = gst_pad_set_caps (yuv_video->src, new_caps); + + gst_caps_unref (new_caps); + + if (G_UNLIKELY (!res)) + return FALSE; + + yuv_video->width = width; + yuv_video->height = height; + yuv_video->format = fourcc; + yuv_video->chroma_type = chroma_type; + + return TRUE; +} + +static GstCaps * +gst_vdpau_yuv_video_sink_getcaps (GstPad * pad) +{ + GstVdpauYUVVideo *yuv_video; + + yuv_video = GST_VDPAU_YUV_VIDEO (GST_OBJECT_PARENT (pad)); + + if (yuv_video->sink_caps) + return gst_caps_copy (yuv_video->sink_caps); + + return gst_caps_copy (gst_pad_get_pad_template_caps (yuv_video->sink)); +} + +static GstStateChangeReturn +gst_vdpau_yuv_video_change_state (GstElement * element, + GstStateChange transition) +{ + GstVdpauYUVVideo *yuv_video; + + yuv_video = GST_VDPAU_YUV_VIDEO (element); + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + yuv_video->device = gst_vdpau_get_device (yuv_video->display); + if (!yuv_video->sink_caps) + yuv_video->sink_caps = gst_vdpau_yuv_video_get_caps (yuv_video); + break; + case GST_STATE_CHANGE_READY_TO_NULL: + g_object_unref (yuv_video->device); + yuv_video->device = NULL; + break; + default: + break; + } + + return GST_STATE_CHANGE_SUCCESS; +} + +/* GObject vmethod implementations */ + +static void +gst_vdpau_yuv_video_base_init (gpointer klass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + + gst_element_class_set_details_simple (element_class, + "VdpauYUVVideo", + "Coyuv_video/Decoder/Video", + "VDPAU video surface to YUV", + "Carl-Anton Ingmarsson "); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&sink_template)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&src_template)); +} + +static void +gst_vdpau_yuv_video_class_init (GstVdpauYUVVideoClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + + gobject_class = (GObjectClass *) klass; + gstelement_class = (GstElementClass *) klass; + + gobject_class->finalize = gst_vdpau_yuv_video_finalize; + gobject_class->set_property = gst_vdpau_yuv_video_set_property; + gobject_class->get_property = gst_vdpau_yuv_video_get_property; + + g_object_class_install_property (gobject_class, PROP_DISPLAY, + g_param_spec_string ("display", "Display", "X Display name", + NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + g_object_class_install_property (gobject_class, PROP_SILENT, + g_param_spec_boolean ("silent", "Silent", "Produce verbose output ?", + FALSE, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE)); + + gstelement_class->change_state = gst_vdpau_yuv_video_change_state; +} + +static void +gst_vdpau_yuv_video_init (GstVdpauYUVVideo * yuv_video, + GstVdpauYUVVideoClass * klass) +{ + yuv_video->silent = FALSE; + yuv_video->sink_caps = NULL; + + yuv_video->display = NULL; + yuv_video->device = NULL; + + yuv_video->height = 0; + yuv_video->width = 0; + yuv_video->format = 0; + yuv_video->chroma_type = 0; + + yuv_video->src = gst_pad_new_from_static_template (&src_template, "src"); + gst_element_add_pad (GST_ELEMENT (yuv_video), yuv_video->src); + + yuv_video->sink = gst_pad_new_from_static_template (&sink_template, "sink"); + gst_pad_set_getcaps_function (yuv_video->sink, + gst_vdpau_yuv_video_sink_getcaps); + gst_pad_set_setcaps_function (yuv_video->sink, + gst_vdpau_yuv_video_sink_setcaps); + gst_pad_set_chain_function (yuv_video->sink, gst_vdpau_yuv_video_chain); + gst_element_add_pad (GST_ELEMENT (yuv_video), yuv_video->sink); + gst_pad_set_active (yuv_video->sink, TRUE); +} + +static void +gst_vdpau_yuv_video_finalize (GObject * object) +{ + GstVdpauYUVVideo *yuv_video = (GstVdpauYUVVideo *) object; + + g_free (yuv_video->display); +} + +static void +gst_vdpau_yuv_video_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstVdpauYUVVideo *yuv_video = GST_VDPAU_YUV_VIDEO (object); + + switch (prop_id) { + case PROP_DISPLAY: + g_free (yuv_video->display); + yuv_video->display = g_value_dup_string (value); + break; + case PROP_SILENT: + yuv_video->silent = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_vdpau_yuv_video_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstVdpauYUVVideo *yuv_video = GST_VDPAU_YUV_VIDEO (object); + + switch (prop_id) { + case PROP_DISPLAY: + g_value_set_string (value, yuv_video->display); + break; + case PROP_SILENT: + g_value_set_boolean (value, yuv_video->silent); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} diff --git a/sys/vdpau/gstvdpauyuvvideo.h b/sys/vdpau/gstvdpauyuvvideo.h new file mode 100644 index 00000000..118715e6 --- /dev/null +++ b/sys/vdpau/gstvdpauyuvvideo.h @@ -0,0 +1,64 @@ +/* + * GStreamer + * Copyright (C) 2009 Carl-Anton Ingmarsson + * + * 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_VDPAU_YUV_VIDEO_H__ +#define __GST_VDPAU_YUV_VIDEO_H__ + +#include + +#include "gstvdpaudevice.h" + +G_BEGIN_DECLS + +#define GST_TYPE_VDPAU_YUV_VIDEO (gst_vdpau_yuv_video_get_type()) +#define GST_VDPAU_YUV_VIDEO(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VDPAU_YUV_VIDEO,GstVdpauYUVVideo)) +#define GST_VDPAU_YUV_VIDEO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VDPAU_YUV_VIDEO,GstVdpauYUVVideoClass)) +#define GST_VDPAU_YUV_VIDEO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_VDPAU_YUV_VIDEO, GstVdpauYUVVideoClass)) +#define GST_IS_VDPAU_YUV_VIDEO(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VDPAU_YUV_VIDEO)) +#define GST_IS_VDPAU_YUV_VIDEO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VDPAU_YUV_VIDEO)) + +typedef struct _GstVdpauYUVVideo GstVdpauYUVVideo; +typedef struct _GstVdpauYUVVideoClass GstVdpauYUVVideoClass; + +struct _GstVdpauYUVVideo { + GstElement element; + + GstPad *src, *sink; + GstCaps *sink_caps; + + gchar *display; + GstVdpauDevice *device; + + guint32 format; + gint chroma_type; + gint width, height; + + gboolean silent; +}; + +struct _GstVdpauYUVVideoClass { + GstElementClass parent_class; +}; + +GType gst_vdpau_yuv_video_get_type (void); + +G_END_DECLS + +#endif /* __GST_VDPAU_YUV_VIDEO_H__ */ -- cgit v1.2.1 From 072f8695485173d660363c1d8be3e62dacc69175 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Tue, 7 Apr 2009 21:51:48 +0200 Subject: vdpau: small fix set vdp_info.forward_reference to VDP_INVALID handle when unreffing the old buffer --- sys/vdpau/gstvdpaumpegdecoder.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sys/vdpau/gstvdpaumpegdecoder.c b/sys/vdpau/gstvdpaumpegdecoder.c index 1910652c..67af4e3f 100644 --- a/sys/vdpau/gstvdpaumpegdecoder.c +++ b/sys/vdpau/gstvdpaumpegdecoder.c @@ -169,8 +169,10 @@ gst_vdpau_mpeg_decoder_decode (GstVdpauMpegDecoder * mpeg_dec) ("Error returned from vdpau was: %s", device->vdp_get_error_string (status))); - if (mpeg_dec->vdp_info.forward_reference != VDP_INVALID_HANDLE) + if (mpeg_dec->vdp_info.forward_reference != VDP_INVALID_HANDLE) { gst_buffer_unref (mpeg_dec->f_buffer); + mpeg_dec->vdp_info.forward_reference = VDP_INVALID_HANDLE; + } gst_buffer_unref (GST_BUFFER (outbuf)); -- cgit v1.2.1 From 86cd9b20f88b55d753b050838cdd660cda07f8c3 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Thu, 9 Apr 2009 16:54:27 +0200 Subject: vdpau: move definition of the VdpChromaType array and the VdpauFormats to gstdevice.h --- sys/vdpau/gstvdpaudevice.h | 51 ++++++++++++++++++++++++++++++++++++++++++ sys/vdpau/gstvdpauvideoyuv.c | 42 +---------------------------------- sys/vdpau/gstvdpauyuvvideo.c | 53 +++----------------------------------------- 3 files changed, 55 insertions(+), 91 deletions(-) diff --git a/sys/vdpau/gstvdpaudevice.h b/sys/vdpau/gstvdpaudevice.h index a4d147c4..c1c6608a 100644 --- a/sys/vdpau/gstvdpaudevice.h +++ b/sys/vdpau/gstvdpaudevice.h @@ -70,6 +70,57 @@ struct _GstVdpauDevice VdpDecoderGetParameters *vdp_decoder_get_parameters; }; +typedef struct +{ + VdpChromaType chroma_type; + VdpYCbCrFormat format; + guint32 fourcc; +} VdpauFormats; + +#define N_CHROMA_TYPES 3 +#define N_FORMATS 7 + +static const VdpChromaType chroma_types[N_CHROMA_TYPES] = + { VDP_CHROMA_TYPE_420, VDP_CHROMA_TYPE_422, VDP_CHROMA_TYPE_444 }; + +static const VdpauFormats formats[N_FORMATS] = { + { + VDP_CHROMA_TYPE_420, + VDP_YCBCR_FORMAT_NV12, + GST_MAKE_FOURCC ('N', 'V', '1', '2') + }, + { + VDP_CHROMA_TYPE_422, + VDP_YCBCR_FORMAT_UYVY, + GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y') + }, + { + VDP_CHROMA_TYPE_444, + VDP_YCBCR_FORMAT_V8U8Y8A8, + GST_MAKE_FOURCC ('A', 'Y', 'U', 'V') + }, + { + VDP_CHROMA_TYPE_444, + VDP_YCBCR_FORMAT_Y8U8V8A8, + GST_MAKE_FOURCC ('A', 'V', 'U', 'Y') + }, + { + VDP_CHROMA_TYPE_422, + VDP_YCBCR_FORMAT_YUYV, + GST_MAKE_FOURCC ('Y', 'U', 'Y', 'V') + }, + { + VDP_CHROMA_TYPE_420, + VDP_YCBCR_FORMAT_YV12, + GST_MAKE_FOURCC ('Y', 'V', '1', '2') + }, + { + VDP_CHROMA_TYPE_420, + VDP_YCBCR_FORMAT_YV12, + GST_MAKE_FOURCC ('I', '4', '2', '0') + } +}; + GType gst_vdpau_device_get_type (void) G_GNUC_CONST; GstVdpauDevice *gst_vdpau_device_new (const gchar *display_name); diff --git a/sys/vdpau/gstvdpauvideoyuv.c b/sys/vdpau/gstvdpauvideoyuv.c index 7b2e7677..6855ba88 100644 --- a/sys/vdpau/gstvdpauvideoyuv.c +++ b/sys/vdpau/gstvdpauvideoyuv.c @@ -178,46 +178,6 @@ gst_vdpau_video_yuv_chain (GstPad * pad, GstBuffer * buffer) return GST_FLOW_ERROR; } -typedef struct -{ - VdpChromaType chroma_type; - VdpYCbCrFormat format; - guint32 fourcc; -} VdpauFormats; - -static VdpauFormats formats[6] = { - { - VDP_CHROMA_TYPE_420, - VDP_YCBCR_FORMAT_NV12, - GST_MAKE_FOURCC ('N', 'V', '1', '2') - }, - { - VDP_CHROMA_TYPE_422, - VDP_YCBCR_FORMAT_UYVY, - GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y') - }, - { - VDP_CHROMA_TYPE_444, - VDP_YCBCR_FORMAT_V8U8Y8A8, - GST_MAKE_FOURCC ('A', 'Y', 'U', 'V') - }, - { - VDP_CHROMA_TYPE_444, - VDP_YCBCR_FORMAT_Y8U8V8A8, - GST_MAKE_FOURCC ('A', 'V', 'U', 'Y') - }, - { - VDP_CHROMA_TYPE_422, - VDP_YCBCR_FORMAT_YUYV, - GST_MAKE_FOURCC ('Y', 'U', 'Y', 'V') - }, - { - VDP_CHROMA_TYPE_420, - VDP_YCBCR_FORMAT_YV12, - GST_MAKE_FOURCC ('Y', 'V', '1', '2') - } -}; - static GstCaps * gst_vdpau_video_yuv_get_caps (GstVdpauVideoYUV * video_yuv, GstVdpauDevice * device, gint chroma_type, gint width, gint height, @@ -229,7 +189,7 @@ gst_vdpau_video_yuv_get_caps (GstVdpauVideoYUV * video_yuv, caps = gst_caps_new_empty (); - for (i = 0; i < 6; i++) { + for (i = 0; i < N_FORMATS; i++) { VdpStatus status; VdpBool is_supported; diff --git a/sys/vdpau/gstvdpauyuvvideo.c b/sys/vdpau/gstvdpauyuvvideo.c index 4d78bae2..d5935a8f 100644 --- a/sys/vdpau/gstvdpauyuvvideo.c +++ b/sys/vdpau/gstvdpauyuvvideo.c @@ -196,53 +196,6 @@ gst_vdpau_yuv_video_chain (GstPad * pad, GstBuffer * buffer) return GST_FLOW_ERROR; } -typedef struct -{ - VdpChromaType chroma_type; - VdpYCbCrFormat format; - guint32 fourcc; -} VdpauFormats; - -static VdpChromaType chroma_types[3] = - { VDP_CHROMA_TYPE_420, VDP_CHROMA_TYPE_422, VDP_CHROMA_TYPE_444 }; -static VdpauFormats formats[7] = { - { - VDP_CHROMA_TYPE_420, - VDP_YCBCR_FORMAT_NV12, - GST_MAKE_FOURCC ('N', 'V', '1', '2') - }, - { - VDP_CHROMA_TYPE_422, - VDP_YCBCR_FORMAT_UYVY, - GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y') - }, - { - VDP_CHROMA_TYPE_444, - VDP_YCBCR_FORMAT_V8U8Y8A8, - GST_MAKE_FOURCC ('A', 'Y', 'U', 'V') - }, - { - VDP_CHROMA_TYPE_444, - VDP_YCBCR_FORMAT_Y8U8V8A8, - GST_MAKE_FOURCC ('A', 'V', 'U', 'Y') - }, - { - VDP_CHROMA_TYPE_422, - VDP_YCBCR_FORMAT_YUYV, - GST_MAKE_FOURCC ('Y', 'U', 'Y', 'V') - }, - { - VDP_CHROMA_TYPE_420, - VDP_YCBCR_FORMAT_YV12, - GST_MAKE_FOURCC ('Y', 'V', '1', '2') - }, - { - VDP_CHROMA_TYPE_420, - VDP_YCBCR_FORMAT_YV12, - GST_MAKE_FOURCC ('I', '4', '2', '0') - } -}; - static GstCaps * gst_vdpau_yuv_video_get_caps (GstVdpauYUVVideo * yuv_video) { @@ -254,7 +207,7 @@ gst_vdpau_yuv_video_get_caps (GstVdpauYUVVideo * yuv_video) caps = gst_caps_new_empty (); - for (i = 0; i < 3; i++) { + for (i = 0; i < N_CHROMA_TYPES; i++) { VdpStatus status; VdpBool is_supported; guint32 max_w, max_h; @@ -274,7 +227,7 @@ gst_vdpau_yuv_video_get_caps (GstVdpauYUVVideo * yuv_video) if (is_supported) { gint j; - for (j = 0; j < 7; j++) { + for (j = 0; j < N_FORMATS; j++) { if (formats[j].chroma_type != chroma_types[i]) continue; @@ -337,7 +290,7 @@ gst_vdpau_yuv_video_sink_setcaps (GstPad * pad, GstCaps * caps) gst_structure_get_fraction (structure, "pixel-aspect-ratio", &par_numerator, &par_denominator); - for (i = 0; i < 7; i++) { + for (i = 0; i < N_FORMATS; i++) { if (formats[i].fourcc == fourcc) { chroma_type = formats[i].chroma_type; break; -- cgit v1.2.1 From a7170c6ef7e1dd7d623b5a0d61a654b433b2ec2d Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Mon, 13 Apr 2009 19:36:53 +0200 Subject: vdpau: implement GstVdpauVideoBuffer -> I420 conversion --- sys/vdpau/gstvdpauvideoyuv.c | 63 +++++++++++++++++++++++++++++++++++++------- sys/vdpau/gstvdpauyuvvideo.c | 20 +++++++------- 2 files changed, 64 insertions(+), 19 deletions(-) diff --git a/sys/vdpau/gstvdpauvideoyuv.c b/sys/vdpau/gstvdpauvideoyuv.c index 6855ba88..f7ebe8a9 100644 --- a/sys/vdpau/gstvdpauvideoyuv.c +++ b/sys/vdpau/gstvdpauvideoyuv.c @@ -101,10 +101,10 @@ gst_vdpau_video_yuv_chain (GstPad * pad, GstBuffer * buffer) data[0] = GST_BUFFER_DATA (outbuf) + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_YV12, 0, video_yuv->width, video_yuv->height); - data[1] = data[0] + + data[1] = GST_BUFFER_DATA (outbuf) + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_YV12, 2, video_yuv->width, video_yuv->height); - data[2] = data[0] + + data[2] = GST_BUFFER_DATA (outbuf) + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_YV12, 1, video_yuv->width, video_yuv->height); @@ -123,7 +123,53 @@ gst_vdpau_video_yuv_chain (GstPad * pad, GstBuffer * buffer) ("Couldn't get data from vdpau"), ("Error returned from vdpau was: %s", device->vdp_get_error_string (status))); - break; + goto error; + } + break; + } + case GST_MAKE_FOURCC ('I', '4', '2', '0'): + { + gint size; + GstFlowReturn result; + VdpStatus status; + guint8 *data[3]; + guint32 stride[3]; + + size = + gst_video_format_get_size (GST_VIDEO_FORMAT_YV12, video_yuv->width, + video_yuv->height); + result = + gst_pad_alloc_buffer_and_set_caps (video_yuv->src, + GST_BUFFER_OFFSET_NONE, size, GST_PAD_CAPS (video_yuv->src), &outbuf); + if (G_UNLIKELY (result != GST_FLOW_OK)) + return result; + + data[0] = GST_BUFFER_DATA (outbuf) + + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_I420, + 0, video_yuv->width, video_yuv->height); + data[1] = GST_BUFFER_DATA (outbuf) + + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_I420, + 2, video_yuv->width, video_yuv->height); + data[2] = GST_BUFFER_DATA (outbuf) + + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_I420, + 1, video_yuv->width, video_yuv->height); + + stride[0] = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_I420, + 0, video_yuv->width); + stride[1] = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_I420, + 2, video_yuv->width); + stride[2] = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_I420, + 1, video_yuv->width); + + status = + device->vdp_video_surface_get_bits_ycbcr (surface, + VDP_YCBCR_FORMAT_YV12, (void *) data, stride); + if (G_UNLIKELY (status != VDP_STATUS_OK)) { + GST_ELEMENT_ERROR (video_yuv, RESOURCE, READ, + ("Couldn't get data from vdpau"), + ("Error returned from vdpau was: %s", + device->vdp_get_error_string (status))); + goto error; } break; } @@ -159,7 +205,7 @@ gst_vdpau_video_yuv_chain (GstPad * pad, GstBuffer * buffer) ("Couldn't get data from vdpau"), ("Error returned from vdpau was: %s", device->vdp_get_error_string (status))); - break; + goto error; } break; } @@ -169,12 +215,11 @@ gst_vdpau_video_yuv_chain (GstPad * pad, GstBuffer * buffer) gst_buffer_unref (buffer); - if (outbuf) { - gst_buffer_copy_metadata (outbuf, buffer, GST_BUFFER_COPY_TIMESTAMPS); - - return gst_pad_push (video_yuv->src, outbuf); - } + gst_buffer_copy_metadata (outbuf, buffer, GST_BUFFER_COPY_TIMESTAMPS); + return gst_pad_push (video_yuv->src, outbuf); +error: + gst_buffer_unref (outbuf); return GST_FLOW_ERROR; } diff --git a/sys/vdpau/gstvdpauyuvvideo.c b/sys/vdpau/gstvdpauyuvvideo.c index d5935a8f..51500c55 100644 --- a/sys/vdpau/gstvdpauyuvvideo.c +++ b/sys/vdpau/gstvdpauyuvvideo.c @@ -95,10 +95,10 @@ gst_vdpau_yuv_video_chain (GstPad * pad, GstBuffer * buffer) data[0] = GST_BUFFER_DATA (buffer) + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_YV12, 0, yuv_video->width, yuv_video->height); - data[1] = data[0] + + data[1] = GST_BUFFER_DATA (buffer) + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_YV12, 2, yuv_video->width, yuv_video->height); - data[2] = data[0] + + data[2] = GST_BUFFER_DATA (buffer) + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_YV12, 1, yuv_video->width, yuv_video->height); @@ -117,7 +117,7 @@ gst_vdpau_yuv_video_chain (GstPad * pad, GstBuffer * buffer) ("Couldn't push YV12 data to VDPAU"), ("Error returned from vdpau was: %s", device->vdp_get_error_string (status))); - break; + goto error; } break; } @@ -152,7 +152,7 @@ gst_vdpau_yuv_video_chain (GstPad * pad, GstBuffer * buffer) ("Couldn't push YV12 data to VDPAU"), ("Error returned from vdpau was: %s", device->vdp_get_error_string (status))); - break; + goto error; } break; } @@ -176,7 +176,7 @@ gst_vdpau_yuv_video_chain (GstPad * pad, GstBuffer * buffer) ("Couldn't get data from vdpau"), ("Error returned from vdpau was: %s", device->vdp_get_error_string (status))); - break; + goto error; } break; } @@ -186,13 +186,13 @@ gst_vdpau_yuv_video_chain (GstPad * pad, GstBuffer * buffer) gst_buffer_unref (buffer); - if (outbuf) { - gst_buffer_copy_metadata (outbuf, buffer, GST_BUFFER_COPY_TIMESTAMPS); - gst_buffer_set_caps (outbuf, GST_PAD_CAPS (yuv_video->src)); + gst_buffer_copy_metadata (outbuf, buffer, GST_BUFFER_COPY_TIMESTAMPS); + gst_buffer_set_caps (outbuf, GST_PAD_CAPS (yuv_video->src)); - return gst_pad_push (yuv_video->src, outbuf); - } + return gst_pad_push (yuv_video->src, outbuf); +error: + gst_buffer_unref (outbuf); return GST_FLOW_ERROR; } -- cgit v1.2.1 From 91ff1579f32a6c0d9769cf44f5065d2811ba01f7 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Mon, 13 Apr 2009 20:04:21 +0200 Subject: vdpau: remove unused "silent" properties --- sys/vdpau/gstvdpaudevice.c | 1 - sys/vdpau/gstvdpaumpegdecoder.c | 18 +----------------- sys/vdpau/gstvdpaumpegdecoder.h | 2 -- sys/vdpau/gstvdpauvideoyuv.c | 18 +----------------- sys/vdpau/gstvdpauvideoyuv.h | 2 -- sys/vdpau/gstvdpauyuvvideo.c | 14 +------------- sys/vdpau/gstvdpauyuvvideo.h | 2 -- 7 files changed, 3 insertions(+), 54 deletions(-) diff --git a/sys/vdpau/gstvdpaudevice.c b/sys/vdpau/gstvdpaudevice.c index 73929444..c5a5f641 100644 --- a/sys/vdpau/gstvdpaudevice.c +++ b/sys/vdpau/gstvdpaudevice.c @@ -29,7 +29,6 @@ GST_DEBUG_CATEGORY_STATIC (gst_vdpau_device_debug); enum { PROP_0, - PROP_DISPLAY }; diff --git a/sys/vdpau/gstvdpaumpegdecoder.c b/sys/vdpau/gstvdpaumpegdecoder.c index 67af4e3f..ecb801a0 100644 --- a/sys/vdpau/gstvdpaumpegdecoder.c +++ b/sys/vdpau/gstvdpaumpegdecoder.c @@ -53,8 +53,7 @@ enum enum { - PROP_0, - PROP_SILENT + PROP_0 }; /* the capabilities of the inputs and outputs. @@ -408,10 +407,6 @@ gst_vdpau_mpeg_decoder_class_init (GstVdpauMpegDecoderClass * klass) gobject_class->set_property = gst_vdpau_mpeg_decoder_set_property; gobject_class->get_property = gst_vdpau_mpeg_decoder_get_property; - g_object_class_install_property (gobject_class, PROP_SILENT, - g_param_spec_boolean ("silent", "Silent", "Produce verbose output ?", - FALSE, G_PARAM_READWRITE)); - vdpaudec_class->set_caps = gst_vdpau_mpeg_decoder_set_caps; } @@ -436,7 +431,6 @@ gst_vdpau_mpeg_decoder_init (GstVdpauMpegDecoder * mpeg_dec, dec = GST_VDPAU_DECODER (mpeg_dec); - mpeg_dec->silent = FALSE; mpeg_dec->decoder = VDP_INVALID_HANDLE; gst_vdpau_mpeg_decoder_init_info (&mpeg_dec->vdp_info); @@ -457,12 +451,7 @@ static void gst_vdpau_mpeg_decoder_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { - GstVdpauMpegDecoder *filter = GST_VDPAU_MPEG_DECODER (object); - switch (prop_id) { - case PROP_SILENT: - filter->silent = g_value_get_boolean (value); - break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -473,12 +462,7 @@ static void gst_vdpau_mpeg_decoder_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { - GstVdpauMpegDecoder *filter = GST_VDPAU_MPEG_DECODER (object); - switch (prop_id) { - case PROP_SILENT: - g_value_set_boolean (value, filter->silent); - break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; diff --git a/sys/vdpau/gstvdpaumpegdecoder.h b/sys/vdpau/gstvdpaumpegdecoder.h index d251480c..1a97c270 100644 --- a/sys/vdpau/gstvdpaumpegdecoder.h +++ b/sys/vdpau/gstvdpaumpegdecoder.h @@ -41,8 +41,6 @@ struct _GstVdpauMpegDecoder { GstVdpauDecoder dec; - gboolean silent; - gint version; VdpDecoder decoder; diff --git a/sys/vdpau/gstvdpauvideoyuv.c b/sys/vdpau/gstvdpauvideoyuv.c index f7ebe8a9..879e4562 100644 --- a/sys/vdpau/gstvdpauvideoyuv.c +++ b/sys/vdpau/gstvdpauvideoyuv.c @@ -40,8 +40,7 @@ enum enum { - PROP_0, - PROP_SILENT + PROP_0 }; static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", @@ -387,17 +386,12 @@ gst_vdpau_video_yuv_class_init (GstVdpauVideoYUVClass * klass) gobject_class->finalize = gst_vdpau_video_yuv_finalize; gobject_class->set_property = gst_vdpau_video_yuv_set_property; gobject_class->get_property = gst_vdpau_video_yuv_get_property; - - g_object_class_install_property (gobject_class, PROP_SILENT, - g_param_spec_boolean ("silent", "Silent", "Produce verbose output ?", - FALSE, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE)); } static void gst_vdpau_video_yuv_init (GstVdpauVideoYUV * video_yuv, GstVdpauVideoYUVClass * klass) { - video_yuv->silent = FALSE; video_yuv->src_caps = NULL; video_yuv->height = 0; @@ -433,12 +427,7 @@ static void gst_vdpau_video_yuv_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { - GstVdpauVideoYUV *video_yuv = GST_VDPAU_VIDEO_YUV (object); - switch (prop_id) { - case PROP_SILENT: - video_yuv->silent = g_value_get_boolean (value); - break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -449,12 +438,7 @@ static void gst_vdpau_video_yuv_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { - GstVdpauVideoYUV *video_yuv = GST_VDPAU_VIDEO_YUV (object); - switch (prop_id) { - case PROP_SILENT: - g_value_set_boolean (value, video_yuv->silent); - break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; diff --git a/sys/vdpau/gstvdpauvideoyuv.h b/sys/vdpau/gstvdpauvideoyuv.h index dd033df7..477b3067 100644 --- a/sys/vdpau/gstvdpauvideoyuv.h +++ b/sys/vdpau/gstvdpauvideoyuv.h @@ -47,8 +47,6 @@ struct _GstVdpauVideoYUV { gint framerate_numerator, framerate_denominator; gint par_numerator, par_denominator; guint format; - - gboolean silent; }; struct _GstVdpauVideoYUVClass { diff --git a/sys/vdpau/gstvdpauyuvvideo.c b/sys/vdpau/gstvdpauyuvvideo.c index 51500c55..a9ccb731 100644 --- a/sys/vdpau/gstvdpauyuvvideo.c +++ b/sys/vdpau/gstvdpauyuvvideo.c @@ -41,8 +41,7 @@ enum enum { PROP_0, - PROP_DISPLAY, - PROP_SILENT + PROP_DISPLAY }; static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", @@ -407,10 +406,6 @@ gst_vdpau_yuv_video_class_init (GstVdpauYUVVideoClass * klass) g_param_spec_string ("display", "Display", "X Display name", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - g_object_class_install_property (gobject_class, PROP_SILENT, - g_param_spec_boolean ("silent", "Silent", "Produce verbose output ?", - FALSE, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE)); - gstelement_class->change_state = gst_vdpau_yuv_video_change_state; } @@ -418,7 +413,6 @@ static void gst_vdpau_yuv_video_init (GstVdpauYUVVideo * yuv_video, GstVdpauYUVVideoClass * klass) { - yuv_video->silent = FALSE; yuv_video->sink_caps = NULL; yuv_video->display = NULL; @@ -461,9 +455,6 @@ gst_vdpau_yuv_video_set_property (GObject * object, guint prop_id, g_free (yuv_video->display); yuv_video->display = g_value_dup_string (value); break; - case PROP_SILENT: - yuv_video->silent = g_value_get_boolean (value); - break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -480,9 +471,6 @@ gst_vdpau_yuv_video_get_property (GObject * object, guint prop_id, case PROP_DISPLAY: g_value_set_string (value, yuv_video->display); break; - case PROP_SILENT: - g_value_set_boolean (value, yuv_video->silent); - break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; diff --git a/sys/vdpau/gstvdpauyuvvideo.h b/sys/vdpau/gstvdpauyuvvideo.h index 118715e6..e80eacf9 100644 --- a/sys/vdpau/gstvdpauyuvvideo.h +++ b/sys/vdpau/gstvdpauyuvvideo.h @@ -49,8 +49,6 @@ struct _GstVdpauYUVVideo { guint32 format; gint chroma_type; gint width, height; - - gboolean silent; }; struct _GstVdpauYUVVideoClass { -- cgit v1.2.1 From 1234267cb5a66dd2782ac7755ef1f998f6561da4 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Mon, 13 Apr 2009 21:11:54 +0200 Subject: vdpau: small improvement to mpeg decoder --- sys/vdpau/gstvdpaumpegdecoder.c | 28 ++++++++++++++++++++-------- sys/vdpau/gstvdpaumpegdecoder.h | 2 ++ sys/vdpau/mpegutil.c | 2 +- 3 files changed, 23 insertions(+), 9 deletions(-) diff --git a/sys/vdpau/gstvdpaumpegdecoder.c b/sys/vdpau/gstvdpaumpegdecoder.c index ecb801a0..efa89e36 100644 --- a/sys/vdpau/gstvdpaumpegdecoder.c +++ b/sys/vdpau/gstvdpaumpegdecoder.c @@ -112,6 +112,7 @@ gst_vdpau_mpeg_decoder_set_caps (GstVdpauDecoder * dec, GstCaps * caps) break; } } + memcpy (&mpeg_dec->vdp_info.intra_quantizer_matrix, &hdr.intra_quantizer_matrix, 64); memcpy (&mpeg_dec->vdp_info.non_intra_quantizer_matrix, @@ -210,12 +211,15 @@ gst_vdpau_mpeg_decoder_parse_picture_coding (GstVdpauMpegDecoder * mpeg_dec, info->intra_dc_precision = pic_ext.intra_dc_precision; info->picture_structure = pic_ext.picture_structure; + GST_DEBUG ("Picture structure %d", info->picture_structure); info->top_field_first = pic_ext.top_field_first; info->frame_pred_frame_dct = pic_ext.frame_pred_frame_dct; info->concealment_motion_vectors = pic_ext.concealment_motion_vectors; info->q_scale_type = pic_ext.q_scale_type; info->intra_vlc_format = pic_ext.intra_vlc_format; + mpeg_dec->want_slice = TRUE; + return TRUE; } @@ -266,7 +270,10 @@ gst_vdpau_mpeg_decoder_parse_picture (GstVdpauMpegDecoder * mpeg_dec, mpeg_dec->vdp_info.full_pel_backward_vector = pic_hdr.full_pel_backward_vector; memcpy (&mpeg_dec->vdp_info.f_code, &pic_hdr.f_code, 4); - } + + mpeg_dec->want_slice = TRUE; + } else + mpeg_dec->want_slice = FALSE; return TRUE; } @@ -326,12 +333,14 @@ gst_vdpau_mpeg_decoder_chain (GstPad * pad, GstBuffer * buffer) GstBuffer *subbuf; GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_SLICE"); - subbuf = - gst_buffer_create_sub (buffer, - packet_start - GST_BUFFER_DATA (buffer), packet_end - packet_start); - gst_adapter_push (mpeg_dec->adapter, subbuf); - mpeg_dec->vdp_info.slice_count++; - } else if (mpeg_dec->vdp_info.slice_count > 0) { + if (mpeg_dec->want_slice) { + subbuf = + gst_buffer_create_sub (buffer, + packet_start - GST_BUFFER_DATA (buffer), packet_end - packet_start); + gst_adapter_push (mpeg_dec->adapter, subbuf); + mpeg_dec->vdp_info.slice_count++; + } + } else if (mpeg_dec->vdp_info.slice_count > 0 && mpeg_dec->want_slice) { if (gst_vdpau_mpeg_decoder_decode (mpeg_dec) != GST_FLOW_OK) return GST_FLOW_ERROR; } @@ -344,7 +353,8 @@ gst_vdpau_mpeg_decoder_chain (GstPad * pad, GstBuffer * buffer) break; case MPEG_PACKET_SEQUENCE: GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_SEQUENCE"); - gst_vdpau_mpeg_decoder_parse_sequence (mpeg_dec, data, end); + gst_vdpau_mpeg_decoder_parse_sequence (mpeg_dec, packet_start, + packet_end); break; case MPEG_PACKET_EXTENSION: GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_EXTENSION"); @@ -436,6 +446,8 @@ gst_vdpau_mpeg_decoder_init (GstVdpauMpegDecoder * mpeg_dec, mpeg_dec->adapter = gst_adapter_new (); + mpeg_dec->want_slice = FALSE; + gst_pad_set_chain_function (dec->sink, gst_vdpau_mpeg_decoder_chain); } diff --git a/sys/vdpau/gstvdpaumpegdecoder.h b/sys/vdpau/gstvdpaumpegdecoder.h index 1a97c270..785c0c15 100644 --- a/sys/vdpau/gstvdpaumpegdecoder.h +++ b/sys/vdpau/gstvdpaumpegdecoder.h @@ -46,6 +46,8 @@ struct _GstVdpauMpegDecoder VdpDecoder decoder; VdpPictureInfoMPEG1Or2 vdp_info; GstBuffer *f_buffer; + + gboolean want_slice; GstAdapter *adapter; gint slices; diff --git a/sys/vdpau/mpegutil.c b/sys/vdpau/mpegutil.c index 8bba8d1f..3a4a63de 100644 --- a/sys/vdpau/mpegutil.c +++ b/sys/vdpau/mpegutil.c @@ -314,7 +314,7 @@ mpeg_util_parse_picture_coding_extension (MPEGPictureExt * ext, guint8 * data, { guint32 code; - if (G_UNLIKELY ((end - data) < 10)) + if (G_UNLIKELY ((end - data) < 9)) return FALSE; /* Packet too small */ code = GST_READ_UINT32_BE (data); -- cgit v1.2.1 From d2efd275a4f5c7ed853521ff9cb0e738a563b52e Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Mon, 13 Apr 2009 21:23:38 +0200 Subject: vdpau: decode slices when we get the next picture header. MPEG2 now kindof works. --- sys/vdpau/gstvdpaumpegdecoder.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sys/vdpau/gstvdpaumpegdecoder.c b/sys/vdpau/gstvdpaumpegdecoder.c index efa89e36..e13ec14c 100644 --- a/sys/vdpau/gstvdpaumpegdecoder.c +++ b/sys/vdpau/gstvdpaumpegdecoder.c @@ -211,7 +211,6 @@ gst_vdpau_mpeg_decoder_parse_picture_coding (GstVdpauMpegDecoder * mpeg_dec, info->intra_dc_precision = pic_ext.intra_dc_precision; info->picture_structure = pic_ext.picture_structure; - GST_DEBUG ("Picture structure %d", info->picture_structure); info->top_field_first = pic_ext.top_field_first; info->frame_pred_frame_dct = pic_ext.frame_pred_frame_dct; info->concealment_motion_vectors = pic_ext.concealment_motion_vectors; @@ -340,14 +339,15 @@ gst_vdpau_mpeg_decoder_chain (GstPad * pad, GstBuffer * buffer) gst_adapter_push (mpeg_dec->adapter, subbuf); mpeg_dec->vdp_info.slice_count++; } - } else if (mpeg_dec->vdp_info.slice_count > 0 && mpeg_dec->want_slice) { - if (gst_vdpau_mpeg_decoder_decode (mpeg_dec) != GST_FLOW_OK) - return GST_FLOW_ERROR; } switch (data[0]) { case MPEG_PACKET_PICTURE: GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_PICTURE"); + if (mpeg_dec->vdp_info.slice_count > 0 && mpeg_dec->want_slice) { + if (gst_vdpau_mpeg_decoder_decode (mpeg_dec) != GST_FLOW_OK) + return GST_FLOW_ERROR; + } gst_vdpau_mpeg_decoder_parse_picture (mpeg_dec, packet_start, packet_end); break; -- cgit v1.2.1 From 48143abdab828f6ea475c678bccb5a263c50e657 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Mon, 13 Apr 2009 22:19:20 +0200 Subject: vdpau: rename all files and objects from Vdpau to Vdp --- sys/vdpau/Makefile.am | 26 +-- sys/vdpau/gstvdp.c | 29 +++ sys/vdpau/gstvdpau.c | 29 --- sys/vdpau/gstvdpaudecoder.c | 275 ----------------------- sys/vdpau/gstvdpaudecoder.h | 74 ------ sys/vdpau/gstvdpaudevice.c | 269 ---------------------- sys/vdpau/gstvdpaudevice.h | 132 ----------- sys/vdpau/gstvdpaumpegdecoder.c | 482 ---------------------------------------- sys/vdpau/gstvdpaumpegdecoder.h | 65 ------ sys/vdpau/gstvdpauvideobuffer.c | 114 ---------- sys/vdpau/gstvdpauvideobuffer.h | 55 ----- sys/vdpau/gstvdpauvideoyuv.c | 446 ------------------------------------- sys/vdpau/gstvdpauvideoyuv.h | 60 ----- sys/vdpau/gstvdpauyuvvideo.c | 478 --------------------------------------- sys/vdpau/gstvdpauyuvvideo.h | 62 ------ sys/vdpau/gstvdpdecoder.c | 275 +++++++++++++++++++++++ sys/vdpau/gstvdpdecoder.h | 74 ++++++ sys/vdpau/gstvdpdevice.c | 269 ++++++++++++++++++++++ sys/vdpau/gstvdpdevice.h | 132 +++++++++++ sys/vdpau/gstvdpmpegdecoder.c | 481 +++++++++++++++++++++++++++++++++++++++ sys/vdpau/gstvdpmpegdecoder.h | 65 ++++++ sys/vdpau/gstvdpvideobuffer.c | 114 ++++++++++ sys/vdpau/gstvdpvideobuffer.h | 55 +++++ sys/vdpau/gstvdpvideoyuv.c | 444 ++++++++++++++++++++++++++++++++++++ sys/vdpau/gstvdpvideoyuv.h | 60 +++++ sys/vdpau/gstvdpyuvvideo.c | 476 +++++++++++++++++++++++++++++++++++++++ sys/vdpau/gstvdpyuvvideo.h | 62 ++++++ 27 files changed, 2549 insertions(+), 2554 deletions(-) create mode 100644 sys/vdpau/gstvdp.c delete mode 100644 sys/vdpau/gstvdpau.c delete mode 100644 sys/vdpau/gstvdpaudecoder.c delete mode 100644 sys/vdpau/gstvdpaudecoder.h delete mode 100644 sys/vdpau/gstvdpaudevice.c delete mode 100644 sys/vdpau/gstvdpaudevice.h delete mode 100644 sys/vdpau/gstvdpaumpegdecoder.c delete mode 100644 sys/vdpau/gstvdpaumpegdecoder.h delete mode 100644 sys/vdpau/gstvdpauvideobuffer.c delete mode 100644 sys/vdpau/gstvdpauvideobuffer.h delete mode 100644 sys/vdpau/gstvdpauvideoyuv.c delete mode 100644 sys/vdpau/gstvdpauvideoyuv.h delete mode 100644 sys/vdpau/gstvdpauyuvvideo.c delete mode 100644 sys/vdpau/gstvdpauyuvvideo.h create mode 100644 sys/vdpau/gstvdpdecoder.c create mode 100644 sys/vdpau/gstvdpdecoder.h create mode 100644 sys/vdpau/gstvdpdevice.c create mode 100644 sys/vdpau/gstvdpdevice.h create mode 100644 sys/vdpau/gstvdpmpegdecoder.c create mode 100644 sys/vdpau/gstvdpmpegdecoder.h create mode 100644 sys/vdpau/gstvdpvideobuffer.c create mode 100644 sys/vdpau/gstvdpvideobuffer.h create mode 100644 sys/vdpau/gstvdpvideoyuv.c create mode 100644 sys/vdpau/gstvdpvideoyuv.h create mode 100644 sys/vdpau/gstvdpyuvvideo.c create mode 100644 sys/vdpau/gstvdpyuvvideo.h diff --git a/sys/vdpau/Makefile.am b/sys/vdpau/Makefile.am index f10cae89..a603ec77 100644 --- a/sys/vdpau/Makefile.am +++ b/sys/vdpau/Makefile.am @@ -1,14 +1,14 @@ plugin_LTLIBRARIES = libgstvdpau.la libgstvdpau_la_SOURCES = \ - gstvdpaudevice.c \ - gstvdpaudecoder.c \ - gstvdpaumpegdecoder.c \ + gstvdpdevice.c \ + gstvdpdecoder.c \ + gstvdpmpegdecoder.c \ mpegutil.c \ - gstvdpauvideoyuv.c \ - gstvdpauvideobuffer.c \ - gstvdpau.c \ - gstvdpauyuvvideo.c + gstvdpvideoyuv.c \ + gstvdpvideobuffer.c \ + gstvdp.c \ + gstvdpyuvvideo.c libgstvdpau_la_CFLAGS = $(GST_CFLAGS) $(X11_CFLAGS) -Ivdpau libgstvdpau_la_LIBADD = $(GST_LIBS) $(GST_BASE_LIBS) \ @@ -17,12 +17,12 @@ libgstvdpau_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) libgstvdpau_la_LIBTOOLFLAGS = --tag=disable-static noinst_HEADERS = \ - gstvdpaudevice.h \ - gstvdpaudecoder.h \ - gstvdpaumpegdecoder.h \ + gstvdpdevice.h \ + gstvdpdecoder.h \ + gstvdpmpegdecoder.h \ mpegutil.h \ - gstvdpauvideoyuv.h \ - gstvdpauvideobuffer.h \ - gstvdpauyuvvideo.h + gstvdpvideoyuv.h \ + gstvdpvideobuffer.h \ + gstvdpyuvvideo.h diff --git a/sys/vdpau/gstvdp.c b/sys/vdpau/gstvdp.c new file mode 100644 index 00000000..2da9bdb0 --- /dev/null +++ b/sys/vdpau/gstvdp.c @@ -0,0 +1,29 @@ +#ifdef HAVE_CONFIG_H +# include +#endif + + +#include + +#include "gstvdpmpegdecoder.h" +#include "gstvdpvideoyuv.h" +#include "gstvdpyuvvideo.h" + +static gboolean +vdpau_init (GstPlugin * vdpaumpegdecoder) +{ + gst_element_register (vdpaumpegdecoder, "vdpaumpegdecoder", + GST_RANK_NONE, GST_TYPE_VDPAU_MPEG_DECODER); + gst_element_register (vdpaumpegdecoder, "vdpauvideoyuv", + GST_RANK_NONE, GST_TYPE_VDPAU_VIDEO_YUV); + gst_element_register (vdpaumpegdecoder, "vdpauyuvvideo", + GST_RANK_NONE, GST_TYPE_VDPAU_YUV_VIDEO); + + return TRUE; +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "vdpau", + "Various elements utilizing VDPAU", + vdpau_init, VERSION, "LGPL", "GStreamer", "http://gstreamer.net/") diff --git a/sys/vdpau/gstvdpau.c b/sys/vdpau/gstvdpau.c deleted file mode 100644 index 24ed3982..00000000 --- a/sys/vdpau/gstvdpau.c +++ /dev/null @@ -1,29 +0,0 @@ -#ifdef HAVE_CONFIG_H -# include -#endif - - -#include - -#include "gstvdpaumpegdecoder.h" -#include "gstvdpauvideoyuv.h" -#include "gstvdpauyuvvideo.h" - -static gboolean -vdpau_init (GstPlugin * vdpaumpegdecoder) -{ - gst_element_register (vdpaumpegdecoder, "vdpaumpegdecoder", - GST_RANK_NONE, GST_TYPE_VDPAU_MPEG_DECODER); - gst_element_register (vdpaumpegdecoder, "vdpauvideoyuv", - GST_RANK_NONE, GST_TYPE_VDPAU_VIDEO_YUV); - gst_element_register (vdpaumpegdecoder, "vdpauyuvvideo", - GST_RANK_NONE, GST_TYPE_VDPAU_YUV_VIDEO); - - return TRUE; -} - -GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, - GST_VERSION_MINOR, - "vdpau", - "Various elements utilizing VDPAU", - vdpau_init, VERSION, "LGPL", "GStreamer", "http://gstreamer.net/") diff --git a/sys/vdpau/gstvdpaudecoder.c b/sys/vdpau/gstvdpaudecoder.c deleted file mode 100644 index 3d0ced34..00000000 --- a/sys/vdpau/gstvdpaudecoder.c +++ /dev/null @@ -1,275 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2009 Carl-Anton Ingmarsson - * - * 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. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include - -#include "gstvdpaudecoder.h" - -GST_DEBUG_CATEGORY_STATIC (gst_vdpau_decoder_debug); -#define GST_CAT_DEFAULT gst_vdpau_decoder_debug - -/* Filter signals and args */ -enum -{ - /* FILL ME */ - LAST_SIGNAL -}; - -enum -{ - PROP_0, - PROP_DISPLAY, - PROP_SILENT -}; - -static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src", - GST_PAD_SRC, - GST_PAD_ALWAYS, - GST_STATIC_CAPS ("video/vdpau-video, " "chroma-type = (int) 0")); - -#define DEBUG_INIT(bla) \ - GST_DEBUG_CATEGORY_INIT (gst_vdpau_decoder_debug, "vdpaudecoder", 0, "vdpaudecoder base class"); - -GST_BOILERPLATE_FULL (GstVdpauDecoder, gst_vdpau_decoder, GstElement, - GST_TYPE_ELEMENT, DEBUG_INIT); - -static void gst_vdpau_decoder_finalize (GObject * object); -static void gst_vdpau_decoder_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec); -static void gst_vdpau_decoder_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec); - -GstFlowReturn -gst_vdpau_decoder_push_video_buffer (GstVdpauDecoder * dec, - GstVdpauVideoBuffer * buffer) -{ - GST_BUFFER_TIMESTAMP (buffer) = - gst_util_uint64_scale_int (GST_SECOND * dec->frame_nr, - dec->framerate_denominator, dec->framerate_numerator); - GST_BUFFER_DURATION (buffer) = - gst_util_uint64_scale_int (GST_SECOND, dec->framerate_denominator, - dec->framerate_numerator); - GST_BUFFER_OFFSET (buffer) = dec->frame_nr; - dec->frame_nr++; - GST_BUFFER_OFFSET_END (buffer) = dec->frame_nr; - gst_buffer_set_caps (GST_BUFFER (buffer), GST_PAD_CAPS (dec->src)); - - return gst_pad_push (dec->src, GST_BUFFER (buffer)); -} - -static GstStateChangeReturn -gst_vdpau_decoder_change_state (GstElement * element, GstStateChange transition) -{ - GstVdpauDecoder *dec; - - dec = GST_VDPAU_DECODER (element); - - switch (transition) { - case GST_STATE_CHANGE_NULL_TO_READY: - dec->device = gst_vdpau_get_device (dec->display_name); - break; - case GST_STATE_CHANGE_READY_TO_NULL: - g_object_unref (dec->device); - dec->device = NULL; - break; - default: - break; - } - - return GST_STATE_CHANGE_SUCCESS; -} - -static gboolean -gst_vdpau_decoder_sink_set_caps (GstPad * pad, GstCaps * caps) -{ - GstVdpauDecoder *dec = GST_VDPAU_DECODER (GST_OBJECT_PARENT (pad)); - GstVdpauDecoderClass *dec_class = GST_VDPAU_DECODER_GET_CLASS (dec); - - GstCaps *src_caps, *new_caps; - GstStructure *structure; - gint width, height; - gint framerate_numerator, framerate_denominator; - gint par_numerator, par_denominator; - gboolean res; - - structure = gst_caps_get_structure (caps, 0); - gst_structure_get_int (structure, "width", &width); - gst_structure_get_int (structure, "height", &height); - gst_structure_get_fraction (structure, "framerate", - &framerate_numerator, &framerate_denominator); - gst_structure_get_fraction (structure, "pixel-aspect-ratio", - &par_numerator, &par_denominator); - - src_caps = gst_pad_get_allowed_caps (dec->src); - if (G_UNLIKELY (!src_caps)) - return FALSE; - - new_caps = gst_caps_copy_nth (src_caps, 0); - gst_caps_unref (src_caps); - structure = gst_caps_get_structure (new_caps, 0); - gst_structure_set (structure, - "device", G_TYPE_OBJECT, dec->device, - "chroma-type", G_TYPE_INT, VDP_CHROMA_TYPE_420, - "width", G_TYPE_INT, width, - "height", G_TYPE_INT, height, - "framerate", GST_TYPE_FRACTION, framerate_numerator, - framerate_denominator, - "pixel-aspect-ratio", GST_TYPE_FRACTION, par_numerator, - par_denominator, NULL); - - gst_pad_fixate_caps (dec->src, new_caps); - res = gst_pad_set_caps (dec->src, new_caps); - - gst_caps_unref (new_caps); - - if (G_UNLIKELY (!res)) - return FALSE; - - dec->width = width; - dec->height = height; - dec->framerate_numerator = framerate_numerator; - dec->framerate_denominator = framerate_denominator; - - if (dec_class->set_caps && !dec_class->set_caps (dec, caps)) - return FALSE; - - return TRUE; -} - -/* GObject vmethod implementations */ - -static void -gst_vdpau_decoder_base_init (gpointer klass) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (klass); - - gst_element_class_set_details_simple (element_class, - "VdpauDecoder", - "Codec/Decoder/Video", - "VDPAU decoder base class", - "Carl-Anton Ingmarsson "); - - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&src_template)); -} - -/* initialize the vdpaudecoder's class */ -static void -gst_vdpau_decoder_class_init (GstVdpauDecoderClass * klass) -{ - GObjectClass *gobject_class; - GstElementClass *gstelement_class; - - gobject_class = (GObjectClass *) klass; - gstelement_class = (GstElementClass *) klass; - - gobject_class->finalize = gst_vdpau_decoder_finalize; - gobject_class->set_property = gst_vdpau_decoder_set_property; - gobject_class->get_property = gst_vdpau_decoder_get_property; - - g_object_class_install_property (gobject_class, PROP_DISPLAY, - g_param_spec_string ("display", "Display", "X Display name", - NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - - g_object_class_install_property (gobject_class, PROP_SILENT, - g_param_spec_boolean ("silent", "Silent", "Produce verbose output ?", - FALSE, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE)); - - gstelement_class->change_state = gst_vdpau_decoder_change_state; -} - -static void -gst_vdpau_decoder_init (GstVdpauDecoder * dec, GstVdpauDecoderClass * klass) -{ - dec->display_name = NULL; - dec->device = NULL; - dec->silent = FALSE; - - dec->height = 0; - dec->width = 0; - dec->framerate_numerator = 0; - dec->framerate_denominator = 0; - - dec->frame_nr = 0; - - dec->src = gst_pad_new_from_static_template (&src_template, "src"); - gst_element_add_pad (GST_ELEMENT (dec), dec->src); - - dec->sink = gst_pad_new_from_template (gst_element_class_get_pad_template - (GST_ELEMENT_CLASS (klass), "sink"), "sink"); - gst_pad_set_setcaps_function (dec->sink, gst_vdpau_decoder_sink_set_caps); - gst_element_add_pad (GST_ELEMENT (dec), dec->sink); - gst_pad_set_active (dec->sink, TRUE); -} - -static void -gst_vdpau_decoder_finalize (GObject * object) -{ - GstVdpauDecoder *dec = (GstVdpauDecoder *) object; - - if (dec->device) - g_object_unref (dec->device); - - g_free (dec->display_name); -} - -static void -gst_vdpau_decoder_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstVdpauDecoder *dec = GST_VDPAU_DECODER (object); - - switch (prop_id) { - case PROP_DISPLAY: - g_free (dec->display_name); - dec->display_name = g_value_dup_string (value); - break; - case PROP_SILENT: - dec->silent = g_value_get_boolean (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_vdpau_decoder_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - GstVdpauDecoder *dec = GST_VDPAU_DECODER (object); - - switch (prop_id) { - case PROP_DISPLAY: - g_value_set_string (value, dec->display_name); - break; - case PROP_SILENT: - g_value_set_boolean (value, dec->silent); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} diff --git a/sys/vdpau/gstvdpaudecoder.h b/sys/vdpau/gstvdpaudecoder.h deleted file mode 100644 index 3f67da68..00000000 --- a/sys/vdpau/gstvdpaudecoder.h +++ /dev/null @@ -1,74 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2009 Carl-Anton Ingmarsson - * - * 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_VDPAU_DECODER_H__ -#define __GST_VDPAU_DECODER_H__ - -#include - -#include "gstvdpaudevice.h" -#include "gstvdpauvideobuffer.h" - -G_BEGIN_DECLS - -#define GST_TYPE_VDPAU_DECODER (gst_vdpau_decoder_get_type()) -#define GST_VDPAU_DECODER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VDPAU_DECODER,GstVdpauDecoder)) -#define GST_VDPAU_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VDPAU_DECODER,GstVdpauDecoderClass)) -#define GST_VDPAU_DECODER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_VDPAU_DECODER, GstVdpauDecoderClass)) -#define GST_IS_VDPAU_DECODER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VDPAU_DECODER)) -#define GST_IS_VDPAU_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VDPAU_DECODER)) - -typedef struct _GstVdpauDecoder GstVdpauDecoder; -typedef struct _GstVdpauDecoderClass GstVdpauDecoderClass; -typedef struct _VdpauFunctions VdpauFunctions; - -struct _GstVdpauDecoder { - GstElement element; - - gchar *display_name; - GstVdpauDevice *device; - - GstPad *src; - GstPad *sink; - - gint width, height; - gint framerate_numerator, framerate_denominator; - guint32 format; - - gint frame_nr; - - gboolean silent; -}; - -struct _GstVdpauDecoderClass { - GstElementClass parent_class; - - gboolean (*set_caps) (GstVdpauDecoder *dec, GstCaps *caps); -}; - -GType gst_vdpau_decoder_get_type (void); - -gboolean gst_vdpau_decoder_push_video_buffer (GstVdpauDecoder * dec, - GstVdpauVideoBuffer *buffer); -VdpVideoSurface gst_vdpau_decoder_create_video_surface (GstVdpauDecoder *dec); - -G_END_DECLS - -#endif /* __GST_VDPAU_DECODER_H__ */ diff --git a/sys/vdpau/gstvdpaudevice.c b/sys/vdpau/gstvdpaudevice.c deleted file mode 100644 index c5a5f641..00000000 --- a/sys/vdpau/gstvdpaudevice.c +++ /dev/null @@ -1,269 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2009 Carl-Anton Ingmarsson - * - * 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. - */ - -#include -#include - -#include "gstvdpaudevice.h" - -GST_DEBUG_CATEGORY_STATIC (gst_vdpau_device_debug); -#define GST_CAT_DEFAULT gst_vdpau_device_debug - -enum -{ - PROP_0, - PROP_DISPLAY -}; - - - -G_DEFINE_TYPE (GstVdpauDevice, gst_vdpau_device, G_TYPE_OBJECT); - -static void -gst_vdpau_device_init (GstVdpauDevice * device) -{ - device->display_name = NULL; - device->display = NULL; - device->device = VDP_INVALID_HANDLE; -} - -static void -gst_vdpau_device_finalize (GObject * object) -{ - GstVdpauDevice *device = (GstVdpauDevice *) object; - - device->vdp_device_destroy (device->device); - g_free (device->display_name); - - G_OBJECT_CLASS (gst_vdpau_device_parent_class)->finalize (object); - -} - -static void -gst_vdpau_device_constructed (GObject * object) -{ - GstVdpauDevice *device = (GstVdpauDevice *) object; - gint screen; - VdpStatus status; - gint i; - - typedef struct - { - gint id; - void *func; - } VdpFunction; - - VdpFunction vdp_function[] = { - {VDP_FUNC_ID_DEVICE_DESTROY, &device->vdp_device_destroy}, - {VDP_FUNC_ID_VIDEO_SURFACE_CREATE, - &device->vdp_video_surface_create}, - {VDP_FUNC_ID_VIDEO_SURFACE_DESTROY, - &device->vdp_video_surface_destroy}, - {VDP_FUNC_ID_VIDEO_SURFACE_QUERY_CAPABILITIES, - &device->vdp_video_surface_query_capabilities}, - {VDP_FUNC_ID_VIDEO_SURFACE_QUERY_GET_PUT_BITS_Y_CB_CR_CAPABILITIES, - &device->vdp_video_surface_query_ycbcr_capabilities}, - {VDP_FUNC_ID_VIDEO_SURFACE_GET_BITS_Y_CB_CR, - &device->vdp_video_surface_get_bits_ycbcr}, - {VDP_FUNC_ID_VIDEO_SURFACE_PUT_BITS_Y_CB_CR, - &device->vdp_video_surface_put_bits_ycbcr}, - {VDP_FUNC_ID_VIDEO_SURFACE_GET_PARAMETERS, - &device->vdp_video_surface_get_parameters}, - {VDP_FUNC_ID_DECODER_CREATE, &device->vdp_decoder_create}, - {VDP_FUNC_ID_DECODER_RENDER, &device->vdp_decoder_render}, - {VDP_FUNC_ID_DECODER_DESTROY, &device->vdp_decoder_destroy}, - {VDP_FUNC_ID_DECODER_QUERY_CAPABILITIES, - &device->vdp_decoder_query_capabilities}, - {VDP_FUNC_ID_DECODER_GET_PARAMETERS, - &device->vdp_decoder_get_parameters}, - {0, NULL} - }; - - device->display = XOpenDisplay (device->display_name); - if (!device->display) { - GST_ERROR_OBJECT (device, "Could not open X display with name: %s", - device->display_name); - return; - } - - screen = DefaultScreen (device->display); - status = - vdp_device_create_x11 (device->display, screen, &device->device, - &device->vdp_get_proc_address); - if (status != VDP_STATUS_OK) { - GST_ERROR_OBJECT (device, "Could not create VDPAU device"); - XCloseDisplay (device->display); - device->display = NULL; - - return; - } - - status = device->vdp_get_proc_address (device->device, - VDP_FUNC_ID_GET_ERROR_STRING, (void **) &device->vdp_get_error_string); - if (status != VDP_STATUS_OK) { - GST_ERROR_OBJECT (device, - "Could not get vdp_get_error_string function pointer from VDPAU"); - goto error; - } - - for (i = 0; vdp_function[i].func != NULL; i++) { - status = device->vdp_get_proc_address (device->device, - vdp_function[i].id, vdp_function[i].func); - - if (status != VDP_STATUS_OK) { - GST_ERROR_OBJECT (device, "Could not get function pointer from VDPAU," - " error returned was: %s", device->vdp_get_error_string (status)); - goto error; - } - } - - return; - -error: - XCloseDisplay (device->display); - device->display = NULL; - - if (device->device != VDP_INVALID_HANDLE) { - device->vdp_device_destroy (device->device); - device->device = VDP_INVALID_HANDLE; - } -} - -static void -gst_vdpau_device_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstVdpauDevice *device; - - g_return_if_fail (GST_IS_VDPAU_DEVICE (object)); - - device = (GstVdpauDevice *) object; - - switch (prop_id) { - case PROP_DISPLAY: - device->display_name = g_value_dup_string (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_vdpau_device_get_property (GObject * object, guint prop_id, GValue * value, - GParamSpec * pspec) -{ - GstVdpauDevice *device; - - g_return_if_fail (GST_IS_VDPAU_DEVICE (object)); - - device = (GstVdpauDevice *) object; - - switch (prop_id) { - case PROP_DISPLAY: - g_value_set_string (value, device->display_name); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_vdpau_device_class_init (GstVdpauDeviceClass * klass) -{ - GObjectClass *object_class = G_OBJECT_CLASS (klass); - - object_class->constructed = gst_vdpau_device_constructed; - object_class->finalize = gst_vdpau_device_finalize; - object_class->get_property = gst_vdpau_device_get_property; - object_class->set_property = gst_vdpau_device_set_property; - - - g_object_class_install_property (object_class, - PROP_DISPLAY, - g_param_spec_string ("display", - "Display", - "X Display Name", - "", G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); - - GST_DEBUG_CATEGORY_INIT (gst_vdpau_device_debug, "vdpaudevice", - 0, "vdpaudevice"); -} - -GstVdpauDevice * -gst_vdpau_device_new (const gchar * display_name) -{ - GstVdpauDevice *device; - - device = g_object_new (GST_TYPE_VDPAU_DEVICE, "display", display_name); - - return device; -} - -static void -device_destroyed_cb (gpointer data, GObject * object) -{ - GHashTable *devices_hash = data; - GHashTableIter iter; - gpointer device; - - g_hash_table_iter_init (&iter, devices_hash); - while (g_hash_table_iter_next (&iter, NULL, &device)) { - if (device == object) { - g_hash_table_iter_remove (&iter); - break; - } - } -} - -static gpointer -create_devices_hash (gpointer data) -{ - return g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); -} - -GstVdpauDevice * -gst_vdpau_get_device (const gchar * display_name) -{ - static GOnce my_once = G_ONCE_INIT; - GHashTable *devices_hash; - GstVdpauDevice *device; - - g_once (&my_once, create_devices_hash, NULL); - devices_hash = my_once.retval; - - if (display_name) - device = g_hash_table_lookup (devices_hash, display_name); - else - device = g_hash_table_lookup (devices_hash, ""); - - if (!device) { - device = gst_vdpau_device_new (display_name); - g_object_weak_ref (G_OBJECT (device), device_destroyed_cb, devices_hash); - if (display_name) - g_hash_table_insert (devices_hash, g_strdup (display_name), device); - else - g_hash_table_insert (devices_hash, g_strdup (""), device); - } else - g_object_ref (device); - - return device; -} diff --git a/sys/vdpau/gstvdpaudevice.h b/sys/vdpau/gstvdpaudevice.h deleted file mode 100644 index c1c6608a..00000000 --- a/sys/vdpau/gstvdpaudevice.h +++ /dev/null @@ -1,132 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2009 Carl-Anton Ingmarsson - * - * 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_VDPAU_DEVICE_H_ -#define _GST_VDPAU_DEVICE_H_ - -#include -#include - -#include - -G_BEGIN_DECLS - -#define GST_TYPE_VDPAU_DEVICE (gst_vdpau_device_get_type ()) -#define GST_VDPAU_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_VDPAU_DEVICE, GstVdpauDevice)) -#define GST_VDPAU_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_VDPAU_DEVICE, GstVdpauDeviceClass)) -#define GST_IS_VDPAU_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_VDPAU_DEVICE)) -#define GST_IS_VDPAU_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_VDPAU_DEVICE)) -#define GST_VDPAU_DEVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_VDPAU_DEVICE, GstVdpauDeviceClass)) - -typedef struct _GstVdpauDeviceClass GstVdpauDeviceClass; -typedef struct _GstVdpauDevice GstVdpauDevice; - -struct _GstVdpauDeviceClass -{ - GObjectClass parent_class; -}; - -struct _GstVdpauDevice -{ - GObject object; - - gchar *display_name; - Display *display; - VdpDevice device; - - VdpDeviceDestroy *vdp_device_destroy; - VdpGetProcAddress *vdp_get_proc_address; - VdpGetErrorString *vdp_get_error_string; - - VdpVideoSurfaceCreate *vdp_video_surface_create; - VdpVideoSurfaceDestroy *vdp_video_surface_destroy; - VdpVideoSurfaceQueryCapabilities *vdp_video_surface_query_capabilities; - VdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities *vdp_video_surface_query_ycbcr_capabilities; - VdpVideoSurfaceGetParameters *vdp_video_surface_get_parameters; - VdpVideoSurfaceGetBitsYCbCr *vdp_video_surface_get_bits_ycbcr; - VdpVideoSurfacePutBitsYCbCr *vdp_video_surface_put_bits_ycbcr; - - VdpDecoderCreate *vdp_decoder_create; - VdpDecoderDestroy *vdp_decoder_destroy; - VdpDecoderRender *vdp_decoder_render; - VdpDecoderQueryCapabilities *vdp_decoder_query_capabilities; - VdpDecoderGetParameters *vdp_decoder_get_parameters; -}; - -typedef struct -{ - VdpChromaType chroma_type; - VdpYCbCrFormat format; - guint32 fourcc; -} VdpauFormats; - -#define N_CHROMA_TYPES 3 -#define N_FORMATS 7 - -static const VdpChromaType chroma_types[N_CHROMA_TYPES] = - { VDP_CHROMA_TYPE_420, VDP_CHROMA_TYPE_422, VDP_CHROMA_TYPE_444 }; - -static const VdpauFormats formats[N_FORMATS] = { - { - VDP_CHROMA_TYPE_420, - VDP_YCBCR_FORMAT_NV12, - GST_MAKE_FOURCC ('N', 'V', '1', '2') - }, - { - VDP_CHROMA_TYPE_422, - VDP_YCBCR_FORMAT_UYVY, - GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y') - }, - { - VDP_CHROMA_TYPE_444, - VDP_YCBCR_FORMAT_V8U8Y8A8, - GST_MAKE_FOURCC ('A', 'Y', 'U', 'V') - }, - { - VDP_CHROMA_TYPE_444, - VDP_YCBCR_FORMAT_Y8U8V8A8, - GST_MAKE_FOURCC ('A', 'V', 'U', 'Y') - }, - { - VDP_CHROMA_TYPE_422, - VDP_YCBCR_FORMAT_YUYV, - GST_MAKE_FOURCC ('Y', 'U', 'Y', 'V') - }, - { - VDP_CHROMA_TYPE_420, - VDP_YCBCR_FORMAT_YV12, - GST_MAKE_FOURCC ('Y', 'V', '1', '2') - }, - { - VDP_CHROMA_TYPE_420, - VDP_YCBCR_FORMAT_YV12, - GST_MAKE_FOURCC ('I', '4', '2', '0') - } -}; - -GType gst_vdpau_device_get_type (void) G_GNUC_CONST; - -GstVdpauDevice *gst_vdpau_device_new (const gchar *display_name); - -GstVdpauDevice *gst_vdpau_get_device (const gchar *display_name); - -G_END_DECLS - -#endif /* _GST_VDPAU_DEVICE_H_ */ diff --git a/sys/vdpau/gstvdpaumpegdecoder.c b/sys/vdpau/gstvdpaumpegdecoder.c deleted file mode 100644 index e13ec14c..00000000 --- a/sys/vdpau/gstvdpaumpegdecoder.c +++ /dev/null @@ -1,482 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2009 Carl-Anton Ingmarsson - * - * 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-vdpaumpegdecoder - * - * FIXME:Describe vdpaumpegdecoder here. - * - * - * Example launch line - * |[ - * gst-launch -v -m fakesrc ! vdpaumpegdecoder ! fakesink silent=TRUE - * ]| - * - */ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include - -#include "mpegutil.h" -#include "gstvdpaumpegdecoder.h" - -GST_DEBUG_CATEGORY_STATIC (gst_vdpau_mpeg_decoder_debug); -#define GST_CAT_DEFAULT gst_vdpau_mpeg_decoder_debug - -/* Filter signals and args */ -enum -{ - /* FILL ME */ - LAST_SIGNAL -}; - -enum -{ - PROP_0 -}; - -/* the capabilities of the inputs and outputs. - * - * describe the real formats here. - */ -static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS ("video/mpeg, mpegversion = (int) [ 1, 2 ], " - "systemstream = (boolean) false, parsed = (boolean) true") - ); - -#define DEBUG_INIT(bla) \ -GST_DEBUG_CATEGORY_INIT (gst_vdpau_mpeg_decoder_debug, "vdpaumpegdecoder", 0, "VDPAU powered mpeg decoder"); - -GST_BOILERPLATE_FULL (GstVdpauMpegDecoder, gst_vdpau_mpeg_decoder, - GstVdpauDecoder, GST_TYPE_VDPAU_DECODER, DEBUG_INIT); - -static void gst_vdpau_mpeg_decoder_finalize (GObject * object); -static void gst_vdpau_mpeg_decoder_set_property (GObject * object, - guint prop_id, const GValue * value, GParamSpec * pspec); -static void gst_vdpau_mpeg_decoder_get_property (GObject * object, - guint prop_id, GValue * value, GParamSpec * pspec); - -static gboolean -gst_vdpau_mpeg_decoder_set_caps (GstVdpauDecoder * dec, GstCaps * caps) -{ - GstVdpauMpegDecoder *mpeg_dec; - GstStructure *structure; - const GValue *value; - GstBuffer *codec_data; - MPEGSeqHdr hdr = { 0, }; - VdpDecoderProfile profile; - GstVdpauDevice *device; - VdpStatus status; - - mpeg_dec = GST_VDPAU_MPEG_DECODER (dec); - - structure = gst_caps_get_structure (caps, 0); - gst_structure_get_int (structure, "mpegversion", &mpeg_dec->version); - if (mpeg_dec->version == 1) - profile = VDP_DECODER_PROFILE_MPEG1; - - value = gst_structure_get_value (structure, "codec_data"); - codec_data = gst_value_get_buffer (value); - mpeg_util_parse_sequence_hdr (&hdr, GST_BUFFER_DATA (codec_data), - GST_BUFFER_DATA (codec_data) + GST_BUFFER_SIZE (codec_data)); - if (mpeg_dec->version != 1) { - switch (hdr.profile) { - case 5: - profile = VDP_DECODER_PROFILE_MPEG2_SIMPLE; - break; - default: - profile = VDP_DECODER_PROFILE_MPEG2_MAIN; - break; - } - } - - memcpy (&mpeg_dec->vdp_info.intra_quantizer_matrix, - &hdr.intra_quantizer_matrix, 64); - memcpy (&mpeg_dec->vdp_info.non_intra_quantizer_matrix, - &hdr.non_intra_quantizer_matrix, 64); - - device = dec->device; - status = device->vdp_decoder_create (device->device, profile, dec->width, - dec->height, 2, &mpeg_dec->decoder); - if (status != VDP_STATUS_OK) { - GST_ELEMENT_ERROR (mpeg_dec, RESOURCE, READ, - ("Could not create vdpau decoder"), - ("Error returned from vdpau was: %s", - device->vdp_get_error_string (status))); - return FALSE; - } - return TRUE; -} - -static GstFlowReturn -gst_vdpau_mpeg_decoder_decode (GstVdpauMpegDecoder * mpeg_dec) -{ - GstVdpauDecoder *dec; - GstBuffer *buffer; - GstVdpauVideoBuffer *outbuf; - VdpVideoSurface surface; - GstVdpauDevice *device; - VdpBitstreamBuffer vbit[1]; - VdpStatus status; - GstFlowReturn ret; - - dec = GST_VDPAU_DECODER (mpeg_dec); - - buffer = gst_adapter_take_buffer (mpeg_dec->adapter, - gst_adapter_available (mpeg_dec->adapter)); - - outbuf = gst_vdpau_video_buffer_new (dec->device, VDP_CHROMA_TYPE_420, - dec->width, dec->height); - surface = outbuf->surface; - - device = dec->device; - - vbit[0].struct_version = VDP_BITSTREAM_BUFFER_VERSION; - vbit[0].bitstream = GST_BUFFER_DATA (buffer); - vbit[0].bitstream_bytes = GST_BUFFER_SIZE (buffer); - - status = device->vdp_decoder_render (mpeg_dec->decoder, surface, - (VdpPictureInfo *) & mpeg_dec->vdp_info, 1, vbit); - gst_buffer_unref (buffer); - mpeg_dec->vdp_info.slice_count = 0; - - if (status != VDP_STATUS_OK) { - GST_ELEMENT_ERROR (mpeg_dec, RESOURCE, READ, - ("Could not decode"), - ("Error returned from vdpau was: %s", - device->vdp_get_error_string (status))); - - if (mpeg_dec->vdp_info.forward_reference != VDP_INVALID_HANDLE) { - gst_buffer_unref (mpeg_dec->f_buffer); - mpeg_dec->vdp_info.forward_reference = VDP_INVALID_HANDLE; - } - - gst_buffer_unref (GST_BUFFER (outbuf)); - - return GST_FLOW_ERROR; - } - - gst_buffer_ref (GST_BUFFER (outbuf)); - - ret = gst_vdpau_decoder_push_video_buffer (GST_VDPAU_DECODER (mpeg_dec), - outbuf); - - if (mpeg_dec->vdp_info.forward_reference != VDP_INVALID_HANDLE) - gst_buffer_unref (mpeg_dec->f_buffer); - - mpeg_dec->vdp_info.forward_reference = surface; - mpeg_dec->f_buffer = GST_BUFFER (outbuf); - - return ret; -} - -static gboolean -gst_vdpau_mpeg_decoder_parse_picture_coding (GstVdpauMpegDecoder * mpeg_dec, - guint8 * data, guint8 * end) -{ - GstVdpauDecoder *dec; - MPEGPictureExt pic_ext; - VdpPictureInfoMPEG1Or2 *info; - - dec = GST_VDPAU_DECODER (mpeg_dec); - info = &mpeg_dec->vdp_info; - - if (!mpeg_util_parse_picture_coding_extension (&pic_ext, data, end)) - return FALSE; - - memcpy (&mpeg_dec->vdp_info.f_code, &pic_ext.f_code, 4); - - info->intra_dc_precision = pic_ext.intra_dc_precision; - info->picture_structure = pic_ext.picture_structure; - info->top_field_first = pic_ext.top_field_first; - info->frame_pred_frame_dct = pic_ext.frame_pred_frame_dct; - info->concealment_motion_vectors = pic_ext.concealment_motion_vectors; - info->q_scale_type = pic_ext.q_scale_type; - info->intra_vlc_format = pic_ext.intra_vlc_format; - - mpeg_dec->want_slice = TRUE; - - return TRUE; -} - -static gboolean -gst_vdpau_mpeg_decoder_parse_sequence (GstVdpauMpegDecoder * mpeg_dec, - guint8 * data, guint8 * end) -{ - GstVdpauDecoder *dec; - MPEGSeqHdr hdr; - - dec = GST_VDPAU_DECODER (mpeg_dec); - - if (!mpeg_util_parse_sequence_hdr (&hdr, data, end)) - return FALSE; - - memcpy (&mpeg_dec->vdp_info.intra_quantizer_matrix, - &hdr.intra_quantizer_matrix, 64); - memcpy (&mpeg_dec->vdp_info.non_intra_quantizer_matrix, - &hdr.non_intra_quantizer_matrix, 64); - - return TRUE; -} - -static gboolean -gst_vdpau_mpeg_decoder_parse_picture (GstVdpauMpegDecoder * mpeg_dec, - guint8 * data, guint8 * end) -{ - GstVdpauDecoder *dec; - MPEGPictureHdr pic_hdr; - - dec = GST_VDPAU_DECODER (mpeg_dec); - - if (!mpeg_util_parse_picture_hdr (&pic_hdr, data, end)) - return FALSE; - - mpeg_dec->vdp_info.picture_coding_type = pic_hdr.pic_type; - - - if (pic_hdr.pic_type == I_FRAME && - mpeg_dec->vdp_info.forward_reference != VDP_INVALID_HANDLE) { - gst_buffer_unref (mpeg_dec->f_buffer); - mpeg_dec->vdp_info.forward_reference = VDP_INVALID_HANDLE; - } - - if (mpeg_dec->version == 1) { - mpeg_dec->vdp_info.full_pel_forward_vector = - pic_hdr.full_pel_forward_vector; - mpeg_dec->vdp_info.full_pel_backward_vector = - pic_hdr.full_pel_backward_vector; - memcpy (&mpeg_dec->vdp_info.f_code, &pic_hdr.f_code, 4); - - mpeg_dec->want_slice = TRUE; - } else - mpeg_dec->want_slice = FALSE; - - return TRUE; -} - -static gboolean -gst_vdpau_mpeg_decoder_parse_gop (GstVdpauMpegDecoder * mpeg_dec, guint8 * data, - guint8 * end) -{ - MPEGPictureGOP gop; - - if (!mpeg_util_parse_picture_gop (&gop, data, end)) - return FALSE; - - return TRUE; -} - -static gboolean -gst_vdpau_mpeg_decoder_parse_quant_matrix (GstVdpauMpegDecoder * mpeg_dec, - guint8 * data, guint8 * end) -{ - MPEGQuantMatrix qm; - - if (!mpeg_util_parse_quant_matrix (&qm, data, end)) - return FALSE; - - memcpy (&mpeg_dec->vdp_info.intra_quantizer_matrix, - &qm.intra_quantizer_matrix, 64); - memcpy (&mpeg_dec->vdp_info.non_intra_quantizer_matrix, - &qm.non_intra_quantizer_matrix, 64); - return TRUE; -} - -static GstFlowReturn -gst_vdpau_mpeg_decoder_chain (GstPad * pad, GstBuffer * buffer) -{ - GstVdpauMpegDecoder *mpeg_dec; - guint8 *data, *end; - guint32 sync_word = 0xffffffff; - - mpeg_dec = GST_VDPAU_MPEG_DECODER (GST_OBJECT_PARENT (pad)); - - data = GST_BUFFER_DATA (buffer); - end = GST_BUFFER_DATA (buffer) + GST_BUFFER_SIZE (buffer); - - while ((data = mpeg_util_find_start_code (&sync_word, data, end))) { - guint8 *packet_start; - guint8 *packet_end; - - packet_start = data - 3; - packet_end = mpeg_util_find_start_code (&sync_word, data, end); - if (packet_end) - packet_end -= 3; - else - packet_end = end; - - if (data[0] >= MPEG_PACKET_SLICE_MIN && data[0] <= MPEG_PACKET_SLICE_MAX) { - GstBuffer *subbuf; - - GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_SLICE"); - if (mpeg_dec->want_slice) { - subbuf = - gst_buffer_create_sub (buffer, - packet_start - GST_BUFFER_DATA (buffer), packet_end - packet_start); - gst_adapter_push (mpeg_dec->adapter, subbuf); - mpeg_dec->vdp_info.slice_count++; - } - } - - switch (data[0]) { - case MPEG_PACKET_PICTURE: - GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_PICTURE"); - if (mpeg_dec->vdp_info.slice_count > 0 && mpeg_dec->want_slice) { - if (gst_vdpau_mpeg_decoder_decode (mpeg_dec) != GST_FLOW_OK) - return GST_FLOW_ERROR; - } - gst_vdpau_mpeg_decoder_parse_picture (mpeg_dec, packet_start, - packet_end); - break; - case MPEG_PACKET_SEQUENCE: - GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_SEQUENCE"); - gst_vdpau_mpeg_decoder_parse_sequence (mpeg_dec, packet_start, - packet_end); - break; - case MPEG_PACKET_EXTENSION: - GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_EXTENSION"); - switch (read_bits (data + 1, 0, 4)) { - case MPEG_PACKET_EXT_PICTURE_CODING: - gst_vdpau_mpeg_decoder_parse_picture_coding (mpeg_dec, packet_start, - packet_end); - break; - default: - break; - } - break; - case MPEG_PACKET_EXT_QUANT_MATRIX: - GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_EXT_QUANT_MATRIX"); - gst_vdpau_mpeg_decoder_parse_quant_matrix (mpeg_dec, packet_start, - packet_end); - break; - case MPEG_PACKET_GOP: - GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_GOP"); - gst_vdpau_mpeg_decoder_parse_gop (mpeg_dec, packet_start, packet_end); - break; - default: - break; - } - } - - return GST_FLOW_OK; -} - -/* GObject vmethod implementations */ - -static void -gst_vdpau_mpeg_decoder_base_init (gpointer gclass) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (gclass); - - gst_element_class_set_details_simple (element_class, - "VdpauMpegDecoder", - "Decoder", - "decode mpeg stream with vdpau", - "Carl-Anton Ingmarsson "); - - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&sink_factory)); -} - -/* initialize the vdpaumpegdecoder's class */ -static void -gst_vdpau_mpeg_decoder_class_init (GstVdpauMpegDecoderClass * klass) -{ - GObjectClass *gobject_class; - GstElementClass *gstelement_class; - GstVdpauDecoderClass *vdpaudec_class; - - gobject_class = (GObjectClass *) klass; - gstelement_class = (GstElementClass *) klass; - vdpaudec_class = (GstVdpauDecoderClass *) klass; - - gobject_class->finalize = gst_vdpau_mpeg_decoder_finalize; - gobject_class->set_property = gst_vdpau_mpeg_decoder_set_property; - gobject_class->get_property = gst_vdpau_mpeg_decoder_get_property; - - vdpaudec_class->set_caps = gst_vdpau_mpeg_decoder_set_caps; -} - -static void -gst_vdpau_mpeg_decoder_init_info (VdpPictureInfoMPEG1Or2 * vdp_info) -{ - vdp_info->forward_reference = VDP_INVALID_HANDLE; - vdp_info->backward_reference = VDP_INVALID_HANDLE; - vdp_info->slice_count = 0; - vdp_info->picture_structure = 0; - vdp_info->picture_coding_type = 0; - vdp_info->intra_dc_precision = 0; - vdp_info->frame_pred_frame_dct = 0; - vdp_info->concealment_motion_vectors = 0; -} - -static void -gst_vdpau_mpeg_decoder_init (GstVdpauMpegDecoder * mpeg_dec, - GstVdpauMpegDecoderClass * gclass) -{ - GstVdpauDecoder *dec; - - dec = GST_VDPAU_DECODER (mpeg_dec); - - mpeg_dec->decoder = VDP_INVALID_HANDLE; - gst_vdpau_mpeg_decoder_init_info (&mpeg_dec->vdp_info); - - mpeg_dec->adapter = gst_adapter_new (); - - mpeg_dec->want_slice = FALSE; - - gst_pad_set_chain_function (dec->sink, gst_vdpau_mpeg_decoder_chain); -} - -static void -gst_vdpau_mpeg_decoder_finalize (GObject * object) -{ - GstVdpauMpegDecoder *mpeg_dec = (GstVdpauMpegDecoder *) object; - - g_object_unref (mpeg_dec->adapter); -} - -static void -gst_vdpau_mpeg_decoder_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - switch (prop_id) { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_vdpau_mpeg_decoder_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - switch (prop_id) { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} diff --git a/sys/vdpau/gstvdpaumpegdecoder.h b/sys/vdpau/gstvdpaumpegdecoder.h deleted file mode 100644 index 785c0c15..00000000 --- a/sys/vdpau/gstvdpaumpegdecoder.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2009 Carl-Anton Ingmarsson - * - * 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_VDPAU_MPEG_DECODER_H__ -#define __GST_VDPAU_MPEG_DECODER_H__ - -#include -#include - -#include "gstvdpaudecoder.h" - -G_BEGIN_DECLS - -#define GST_TYPE_VDPAU_MPEG_DECODER (gst_vdpau_mpeg_decoder_get_type()) -#define GST_VDPAU_MPEG_DECODER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VDPAU_MPEG_DECODER,GstVdpauMpegDecoder)) -#define GST_VDPAU_MPEG_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VDPAU_MPEG_DECODER,GstVdpauMpegDecoderClass)) -#define GST_IS_VDPAU_MPEG_DECODER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VDPAU_MPEG_DECODER)) -#define GST_IS_VDPAU_MPEG_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VDPAU_MPEG_DECODER)) - -typedef struct _GstVdpauMpegDecoder GstVdpauMpegDecoder; -typedef struct _GstVdpauMpegDecoderClass GstVdpauMpegDecoderClass; - -struct _GstVdpauMpegDecoder -{ - GstVdpauDecoder dec; - - gint version; - - VdpDecoder decoder; - VdpPictureInfoMPEG1Or2 vdp_info; - GstBuffer *f_buffer; - - gboolean want_slice; - - GstAdapter *adapter; - gint slices; -}; - -struct _GstVdpauMpegDecoderClass -{ - GstVdpauDecoderClass parent_class; -}; - -GType gst_vdpau_mpeg_decoder_get_type (void); - -G_END_DECLS - -#endif /* __GST_VDPAU_MPEG_DECODER_H__ */ diff --git a/sys/vdpau/gstvdpauvideobuffer.c b/sys/vdpau/gstvdpauvideobuffer.c deleted file mode 100644 index f7ece0eb..00000000 --- a/sys/vdpau/gstvdpauvideobuffer.c +++ /dev/null @@ -1,114 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2009 Carl-Anton Ingmarsson - * - * 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. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "gstvdpauvideobuffer.h" - -static GObjectClass *gst_vdpau_video_buffer_parent_class; - -static void -gst_vdpau_video_buffer_finalize (GstVdpauVideoBuffer * buffer) -{ - GstVdpauDevice *device = buffer->device; - VdpStatus status; - - status = device->vdp_video_surface_destroy (buffer->surface); - if (status != VDP_STATUS_OK) - GST_ERROR - ("Couldn't destroy the buffers VdpVideoSurface, error returned was: %s", - device->vdp_get_error_string (status)); - - g_object_unref (buffer->device); - - GST_MINI_OBJECT_CLASS (gst_vdpau_video_buffer_parent_class)->finalize - (GST_MINI_OBJECT (buffer)); -} - -static void -gst_vdpau_video_buffer_init (GstVdpauVideoBuffer * buffer, gpointer g_class) -{ - buffer->device = NULL; - buffer->surface = VDP_INVALID_HANDLE; -} - -static void -gst_vdpau_video_buffer_class_init (gpointer g_class, gpointer class_data) -{ - GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class); - - gst_vdpau_video_buffer_parent_class = g_type_class_peek_parent (g_class); - - mini_object_class->finalize = (GstMiniObjectFinalizeFunction) - gst_vdpau_video_buffer_finalize; -} - - -GType -gst_vdpau_video_buffer_get_type (void) -{ - static GType _gst_vdpau_video_buffer_type; - - if (G_UNLIKELY (_gst_vdpau_video_buffer_type == 0)) { - static const GTypeInfo info = { - sizeof (GstBufferClass), - NULL, - NULL, - gst_vdpau_video_buffer_class_init, - NULL, - NULL, - sizeof (GstVdpauVideoBuffer), - 0, - (GInstanceInitFunc) gst_vdpau_video_buffer_init, - NULL - }; - _gst_vdpau_video_buffer_type = g_type_register_static (GST_TYPE_BUFFER, - "GstVdpauVideoBuffer", &info, 0); - } - return _gst_vdpau_video_buffer_type; -} - - -GstVdpauVideoBuffer * -gst_vdpau_video_buffer_new (GstVdpauDevice * device, VdpChromaType chroma_type, - gint width, gint height) -{ - GstVdpauVideoBuffer *buffer; - VdpStatus status; - VdpVideoSurface surface; - - status = device->vdp_video_surface_create (device->device, chroma_type, width, - height, &surface); - if (status != VDP_STATUS_OK) { - GST_ERROR ("Couldn't create a VdpVideoSurface, error returned was: %s", - device->vdp_get_error_string (status)); - return NULL; - } - - buffer = - (GstVdpauVideoBuffer *) gst_mini_object_new (GST_TYPE_VDPAU_VIDEO_BUFFER); - - buffer->device = g_object_ref (device); - buffer->surface = surface; - - return buffer; -} diff --git a/sys/vdpau/gstvdpauvideobuffer.h b/sys/vdpau/gstvdpauvideobuffer.h deleted file mode 100644 index fe2b4b7f..00000000 --- a/sys/vdpau/gstvdpauvideobuffer.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2009 Carl-Anton Ingmarsson - * - * 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_VDPAU_VIDEO_BUFFER_H_ -#define _GST_VDPAU_VIDEO_BUFFER_H_ - -#include -#include - -#include "gstvdpaudevice.h" - -#include "gstvdpauvideobuffer.h" - -typedef struct _GstVdpauVideoBuffer GstVdpauVideoBuffer; - -#define GST_TYPE_VDPAU_VIDEO_BUFFER (gst_vdpau_video_buffer_get_type()) - -#define GST_IS_VDPAU_VIDEO_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_VDPAU_VIDEO_BUFFER)) -#define GST_VDPAU_VIDEO_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_VDPAU_VIDEO_BUFFER, GstVdpauVideoBuffer)) - -struct _GstVdpauVideoBuffer { - GstBuffer buffer; - - GstVdpauDevice *device; - VdpVideoSurface surface; -}; - -GType gst_vdpau_video_buffer_get_type (void); - -GstVdpauVideoBuffer* gst_vdpau_video_buffer_new (GstVdpauDevice * device, VdpChromaType chroma_type, gint width, gint height); - -#define GST_VDPAU_VIDEO_CAPS \ - "video/vdpau-video, " \ - "chroma-type = (int)[0,2], " \ - "width = (int)[1,4096], " \ - "height = (int)[1,4096]" - -#endif diff --git a/sys/vdpau/gstvdpauvideoyuv.c b/sys/vdpau/gstvdpauvideoyuv.c deleted file mode 100644 index 879e4562..00000000 --- a/sys/vdpau/gstvdpauvideoyuv.c +++ /dev/null @@ -1,446 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2009 Carl-Anton Ingmarsson - * - * 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. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include - -#include "gstvdpauvideobuffer.h" -#include "gstvdpauvideoyuv.h" - -GST_DEBUG_CATEGORY_STATIC (gst_vdpau_video_yuv_debug); -#define GST_CAT_DEFAULT gst_vdpau_video_yuv_debug - -/* Filter signals and args */ -enum -{ - /* FILL ME */ - LAST_SIGNAL -}; - -enum -{ - PROP_0 -}; - -static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS (GST_VDPAU_VIDEO_CAPS)); - -static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src", - GST_PAD_SRC, - GST_PAD_ALWAYS, - GST_STATIC_CAPS ("video/x-raw-yuv, " - "framerate = (fraction) [ 0, MAX ], " - "width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]")); - -#define DEBUG_INIT(bla) \ - GST_DEBUG_CATEGORY_INIT (gst_vdpau_video_yuv_debug, "vdpauvideoyuv", 0, "VDPAU VdpSurface to YUV"); - -GST_BOILERPLATE_FULL (GstVdpauVideoYUV, gst_vdpau_video_yuv, GstElement, - GST_TYPE_ELEMENT, DEBUG_INIT); - -static void gst_vdpau_video_yuv_finalize (GObject * object); -static void gst_vdpau_video_yuv_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec); -static void gst_vdpau_video_yuv_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec); - -GstFlowReturn -gst_vdpau_video_yuv_chain (GstPad * pad, GstBuffer * buffer) -{ - GstVdpauVideoYUV *video_yuv; - GstVdpauDevice *device; - VdpVideoSurface surface; - GstBuffer *outbuf = NULL; - - video_yuv = GST_VDPAU_VIDEO_YUV (GST_OBJECT_PARENT (pad)); - device = GST_VDPAU_VIDEO_BUFFER (buffer)->device; - surface = GST_VDPAU_VIDEO_BUFFER (buffer)->surface; - - switch (video_yuv->format) { - case GST_MAKE_FOURCC ('Y', 'V', '1', '2'): - { - gint size; - GstFlowReturn result; - VdpStatus status; - guint8 *data[3]; - guint32 stride[3]; - - size = - gst_video_format_get_size (GST_VIDEO_FORMAT_YV12, video_yuv->width, - video_yuv->height); - result = - gst_pad_alloc_buffer_and_set_caps (video_yuv->src, - GST_BUFFER_OFFSET_NONE, size, GST_PAD_CAPS (video_yuv->src), &outbuf); - if (G_UNLIKELY (result != GST_FLOW_OK)) - return result; - - data[0] = GST_BUFFER_DATA (outbuf) + - gst_video_format_get_component_offset (GST_VIDEO_FORMAT_YV12, - 0, video_yuv->width, video_yuv->height); - data[1] = GST_BUFFER_DATA (outbuf) + - gst_video_format_get_component_offset (GST_VIDEO_FORMAT_YV12, - 2, video_yuv->width, video_yuv->height); - data[2] = GST_BUFFER_DATA (outbuf) + - gst_video_format_get_component_offset (GST_VIDEO_FORMAT_YV12, - 1, video_yuv->width, video_yuv->height); - - stride[0] = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_YV12, - 0, video_yuv->width); - stride[1] = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_YV12, - 2, video_yuv->width); - stride[2] = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_YV12, - 1, video_yuv->width); - - status = - device->vdp_video_surface_get_bits_ycbcr (surface, - VDP_YCBCR_FORMAT_YV12, (void *) data, stride); - if (G_UNLIKELY (status != VDP_STATUS_OK)) { - GST_ELEMENT_ERROR (video_yuv, RESOURCE, READ, - ("Couldn't get data from vdpau"), - ("Error returned from vdpau was: %s", - device->vdp_get_error_string (status))); - goto error; - } - break; - } - case GST_MAKE_FOURCC ('I', '4', '2', '0'): - { - gint size; - GstFlowReturn result; - VdpStatus status; - guint8 *data[3]; - guint32 stride[3]; - - size = - gst_video_format_get_size (GST_VIDEO_FORMAT_YV12, video_yuv->width, - video_yuv->height); - result = - gst_pad_alloc_buffer_and_set_caps (video_yuv->src, - GST_BUFFER_OFFSET_NONE, size, GST_PAD_CAPS (video_yuv->src), &outbuf); - if (G_UNLIKELY (result != GST_FLOW_OK)) - return result; - - data[0] = GST_BUFFER_DATA (outbuf) + - gst_video_format_get_component_offset (GST_VIDEO_FORMAT_I420, - 0, video_yuv->width, video_yuv->height); - data[1] = GST_BUFFER_DATA (outbuf) + - gst_video_format_get_component_offset (GST_VIDEO_FORMAT_I420, - 2, video_yuv->width, video_yuv->height); - data[2] = GST_BUFFER_DATA (outbuf) + - gst_video_format_get_component_offset (GST_VIDEO_FORMAT_I420, - 1, video_yuv->width, video_yuv->height); - - stride[0] = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_I420, - 0, video_yuv->width); - stride[1] = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_I420, - 2, video_yuv->width); - stride[2] = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_I420, - 1, video_yuv->width); - - status = - device->vdp_video_surface_get_bits_ycbcr (surface, - VDP_YCBCR_FORMAT_YV12, (void *) data, stride); - if (G_UNLIKELY (status != VDP_STATUS_OK)) { - GST_ELEMENT_ERROR (video_yuv, RESOURCE, READ, - ("Couldn't get data from vdpau"), - ("Error returned from vdpau was: %s", - device->vdp_get_error_string (status))); - goto error; - } - break; - } - case GST_MAKE_FOURCC ('N', 'V', '1', '2'): - { - gint size; - GstFlowReturn result; - VdpStatus status; - guint8 *data[2]; - guint32 stride[2]; - - size = - video_yuv->width * video_yuv->height + - video_yuv->width * video_yuv->height / 2; - result = - gst_pad_alloc_buffer_and_set_caps (video_yuv->src, - GST_BUFFER_OFFSET_NONE, size, GST_PAD_CAPS (video_yuv->src), &outbuf); - if (G_UNLIKELY (result != GST_FLOW_OK)) - return result; - - - data[0] = GST_BUFFER_DATA (outbuf); - data[1] = GST_BUFFER_DATA (outbuf) + video_yuv->width * video_yuv->height; - - stride[0] = video_yuv->width; - stride[1] = video_yuv->width; - - status = - device->vdp_video_surface_get_bits_ycbcr (surface, - VDP_YCBCR_FORMAT_NV12, (void *) data, stride); - if (G_UNLIKELY (status != VDP_STATUS_OK)) { - GST_ELEMENT_ERROR (video_yuv, RESOURCE, READ, - ("Couldn't get data from vdpau"), - ("Error returned from vdpau was: %s", - device->vdp_get_error_string (status))); - goto error; - } - break; - } - default: - break; - } - - gst_buffer_unref (buffer); - - gst_buffer_copy_metadata (outbuf, buffer, GST_BUFFER_COPY_TIMESTAMPS); - return gst_pad_push (video_yuv->src, outbuf); - -error: - gst_buffer_unref (outbuf); - return GST_FLOW_ERROR; -} - -static GstCaps * -gst_vdpau_video_yuv_get_caps (GstVdpauVideoYUV * video_yuv, - GstVdpauDevice * device, gint chroma_type, gint width, gint height, - gint framerate_numerator, gint framerate_denominator, gint par_numerator, - gint par_denominator) -{ - GstCaps *caps; - gint i; - - caps = gst_caps_new_empty (); - - for (i = 0; i < N_FORMATS; i++) { - VdpStatus status; - VdpBool is_supported; - - if (formats[i].chroma_type != chroma_type) - continue; - - status = - device->vdp_video_surface_query_ycbcr_capabilities (device->device, - chroma_type, formats[i].format, &is_supported); - if (status != VDP_STATUS_OK && status != VDP_STATUS_INVALID_Y_CB_CR_FORMAT) { - GST_ELEMENT_ERROR (video_yuv, RESOURCE, READ, - ("Could not query VDPAU YCbCr capabilites"), - ("Error returned from vdpau was: %s", - device->vdp_get_error_string (status))); - - return NULL; - } - if (is_supported) { - GstCaps *format_caps; - - format_caps = gst_caps_new_simple ("video/x-raw-yuv", - "format", GST_TYPE_FOURCC, formats[i].fourcc, - "width", G_TYPE_INT, width, - "height", G_TYPE_INT, height, - "framerate", GST_TYPE_FRACTION, framerate_numerator, - framerate_denominator, "pixel-aspect-ratio", GST_TYPE_FRACTION, - par_numerator, par_denominator, NULL); - gst_caps_append (caps, format_caps); - } - } - - if (gst_caps_is_empty (caps)) { - gst_caps_unref (caps); - return NULL; - } - - return caps; -} - -static gboolean -gst_vdpau_video_yuv_sink_set_caps (GstPad * pad, GstCaps * caps) -{ - GstVdpauVideoYUV *video_yuv = GST_VDPAU_VIDEO_YUV (GST_OBJECT_PARENT (pad)); - - GstCaps *src_caps, *new_caps; - GstStructure *structure; - const GValue *value; - GstVdpauDevice *device; - gint chroma_type; - gint width, height; - gint framerate_numerator, framerate_denominator; - gint par_numerator, par_denominator; - guint32 fourcc_format; - gboolean res; - - structure = gst_caps_get_structure (caps, 0); - value = gst_structure_get_value (structure, "device"); - device = g_value_get_object (value); - - gst_structure_get_int (structure, "chroma-type", &chroma_type); - gst_structure_get_int (structure, "width", &width); - gst_structure_get_int (structure, "height", &height); - gst_structure_get_fraction (structure, "framerate", - &framerate_numerator, &framerate_denominator); - gst_structure_get_fraction (structure, "pixel-aspect-ratio", - &par_numerator, &par_denominator); - - src_caps = - gst_vdpau_video_yuv_get_caps (video_yuv, device, chroma_type, width, - height, framerate_numerator, framerate_denominator, par_numerator, - par_denominator); - if (G_UNLIKELY (!src_caps)) - return FALSE; - - video_yuv->src_caps = src_caps; - - src_caps = gst_pad_get_allowed_caps (video_yuv->src); - if (G_UNLIKELY (!src_caps || !gst_caps_get_size (src_caps))) - return FALSE; - - new_caps = gst_caps_copy_nth (src_caps, 0); - gst_caps_unref (src_caps); - if (G_UNLIKELY (!new_caps)) - return FALSE; - - structure = gst_caps_get_structure (new_caps, 0); - gst_structure_get_fourcc (structure, "format", &fourcc_format); - - gst_pad_fixate_caps (video_yuv->src, new_caps); - res = gst_pad_set_caps (video_yuv->src, new_caps); - - gst_caps_unref (new_caps); - - if (G_UNLIKELY (!res)) - return FALSE; - - video_yuv->width = width; - video_yuv->height = height; - video_yuv->framerate_numerator = framerate_numerator; - video_yuv->framerate_denominator = framerate_denominator; - video_yuv->format = fourcc_format; - - return TRUE; -} - -static GstCaps * -gst_vdpau_video_yuv_src_getcaps (GstPad * pad) -{ - GstVdpauVideoYUV *video_yuv; - - video_yuv = GST_VDPAU_VIDEO_YUV (GST_OBJECT_PARENT (pad)); - - if (video_yuv->src_caps) - return gst_caps_copy (video_yuv->src_caps); - - if (GST_PAD_CAPS (video_yuv->src)) - return gst_caps_copy (GST_PAD_CAPS (video_yuv->src)); - - return gst_caps_copy (gst_pad_get_pad_template_caps (video_yuv->src)); -} - -/* GObject vmethod implementations */ - -static void -gst_vdpau_video_yuv_base_init (gpointer klass) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (klass); - - gst_element_class_set_details_simple (element_class, - "VdpauVideoYUV", - "Covideo_yuv/Decoder/Video", - "VDPAU video surface to YUV", - "Carl-Anton Ingmarsson "); - - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&sink_template)); - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&src_template)); -} - -static void -gst_vdpau_video_yuv_class_init (GstVdpauVideoYUVClass * klass) -{ - GObjectClass *gobject_class; - GstElementClass *gstelement_class; - - gobject_class = (GObjectClass *) klass; - gstelement_class = (GstElementClass *) klass; - - gobject_class->finalize = gst_vdpau_video_yuv_finalize; - gobject_class->set_property = gst_vdpau_video_yuv_set_property; - gobject_class->get_property = gst_vdpau_video_yuv_get_property; -} - -static void -gst_vdpau_video_yuv_init (GstVdpauVideoYUV * video_yuv, - GstVdpauVideoYUVClass * klass) -{ - video_yuv->src_caps = NULL; - - video_yuv->height = 0; - video_yuv->width = 0; - video_yuv->framerate_numerator = 0; - video_yuv->framerate_denominator = 0; - video_yuv->par_numerator = 1; - video_yuv->par_denominator = 1; - - video_yuv->src = gst_pad_new_from_static_template (&src_template, "src"); - gst_pad_set_getcaps_function (video_yuv->src, - gst_vdpau_video_yuv_src_getcaps); - gst_element_add_pad (GST_ELEMENT (video_yuv), video_yuv->src); - - video_yuv->sink = gst_pad_new_from_static_template (&sink_template, "sink"); - gst_pad_set_setcaps_function (video_yuv->sink, - gst_vdpau_video_yuv_sink_set_caps); - gst_pad_set_chain_function (video_yuv->sink, gst_vdpau_video_yuv_chain); - gst_element_add_pad (GST_ELEMENT (video_yuv), video_yuv->sink); - gst_pad_set_active (video_yuv->sink, TRUE); -} - -static void -gst_vdpau_video_yuv_finalize (GObject * object) -{ - GstVdpauVideoYUV *video_yuv = (GstVdpauVideoYUV *) object; - - if (video_yuv->src_caps) - gst_caps_unref (video_yuv->src_caps); -} - -static void -gst_vdpau_video_yuv_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - switch (prop_id) { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_vdpau_video_yuv_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - switch (prop_id) { - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} diff --git a/sys/vdpau/gstvdpauvideoyuv.h b/sys/vdpau/gstvdpauvideoyuv.h deleted file mode 100644 index 477b3067..00000000 --- a/sys/vdpau/gstvdpauvideoyuv.h +++ /dev/null @@ -1,60 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2009 Carl-Anton Ingmarsson - * - * 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_VDPAU_VIDEO_YUV_H__ -#define __GST_VDPAU_VIDEO_YUV_H__ - -#include - -#include "gstvdpaudevice.h" - -G_BEGIN_DECLS - -#define GST_TYPE_VDPAU_VIDEO_YUV (gst_vdpau_video_yuv_get_type()) -#define GST_VDPAU_VIDEO_YUV(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VDPAU_VIDEO_YUV,GstVdpauVideoYUV)) -#define GST_VDPAU_VIDEO_YUV_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VDPAU_VIDEO_YUV,GstVdpauVideoYUVClass)) -#define GST_VDPAU_VIDEO_YUV_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_VDPAU_VIDEO_YUV, GstVdpauVideoYUVClass)) -#define GST_IS_VDPAU_VIDEO_YUV(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VDPAU_VIDEO_YUV)) -#define GST_IS_VDPAU_VIDEO_YUV_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VDPAU_VIDEO_YUV)) - -typedef struct _GstVdpauVideoYUV GstVdpauVideoYUV; -typedef struct _GstVdpauVideoYUVClass GstVdpauVideoYUVClass; - -struct _GstVdpauVideoYUV { - GstElement element; - - GstPad *src, *sink; - GstCaps *src_caps; - - gint width, height; - gint framerate_numerator, framerate_denominator; - gint par_numerator, par_denominator; - guint format; -}; - -struct _GstVdpauVideoYUVClass { - GstElementClass parent_class; -}; - -GType gst_vdpau_video_yuv_get_type (void); - -G_END_DECLS - -#endif /* __GST_VDPAU_VIDEO_YUV_H__ */ diff --git a/sys/vdpau/gstvdpauyuvvideo.c b/sys/vdpau/gstvdpauyuvvideo.c deleted file mode 100644 index a9ccb731..00000000 --- a/sys/vdpau/gstvdpauyuvvideo.c +++ /dev/null @@ -1,478 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2009 Carl-Anton Ingmarsson - * - * 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. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include - -#include "gstvdpauvideobuffer.h" -#include "gstvdpauyuvvideo.h" - -GST_DEBUG_CATEGORY_STATIC (gst_vdpau_yuv_video_debug); -#define GST_CAT_DEFAULT gst_vdpau_yuv_video_debug - -/* Filter signals and args */ -enum -{ - /* FILL ME */ - LAST_SIGNAL -}; - -enum -{ - PROP_0, - PROP_DISPLAY -}; - -static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS ("video/x-raw-yuv, " - "framerate = (fraction) [ 0, MAX ], " - "width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]")); - -static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src", - GST_PAD_SRC, - GST_PAD_ALWAYS, - GST_STATIC_CAPS (GST_VDPAU_VIDEO_CAPS)); - -#define DEBUG_INIT(bla) \ - GST_DEBUG_CATEGORY_INIT (gst_vdpau_yuv_video_debug, "vdpauvideoyuv", 0, "YUV to VDPAU video surface"); - -GST_BOILERPLATE_FULL (GstVdpauYUVVideo, gst_vdpau_yuv_video, GstElement, - GST_TYPE_ELEMENT, DEBUG_INIT); - -static void gst_vdpau_yuv_video_finalize (GObject * object); -static void gst_vdpau_yuv_video_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec); -static void gst_vdpau_yuv_video_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec); - -GstFlowReturn -gst_vdpau_yuv_video_chain (GstPad * pad, GstBuffer * buffer) -{ - GstVdpauYUVVideo *yuv_video; - GstVdpauDevice *device; - VdpVideoSurface surface; - GstBuffer *outbuf = NULL; - - yuv_video = GST_VDPAU_YUV_VIDEO (GST_OBJECT_PARENT (pad)); - device = yuv_video->device; - - outbuf = - GST_BUFFER (gst_vdpau_video_buffer_new (device, yuv_video->chroma_type, - yuv_video->width, yuv_video->height)); - surface = GST_VDPAU_VIDEO_BUFFER (outbuf)->surface; - - switch (yuv_video->format) { - case GST_MAKE_FOURCC ('Y', 'V', '1', '2'): - { - VdpStatus status; - guint8 *data[3]; - guint32 stride[3]; - - data[0] = GST_BUFFER_DATA (buffer) + - gst_video_format_get_component_offset (GST_VIDEO_FORMAT_YV12, - 0, yuv_video->width, yuv_video->height); - data[1] = GST_BUFFER_DATA (buffer) + - gst_video_format_get_component_offset (GST_VIDEO_FORMAT_YV12, - 2, yuv_video->width, yuv_video->height); - data[2] = GST_BUFFER_DATA (buffer) + - gst_video_format_get_component_offset (GST_VIDEO_FORMAT_YV12, - 1, yuv_video->width, yuv_video->height); - - stride[0] = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_YV12, - 0, yuv_video->width); - stride[1] = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_YV12, - 2, yuv_video->width); - stride[2] = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_YV12, - 1, yuv_video->width); - - status = - device->vdp_video_surface_put_bits_ycbcr (surface, - VDP_YCBCR_FORMAT_YV12, (void *) data, stride); - if (G_UNLIKELY (status != VDP_STATUS_OK)) { - GST_ELEMENT_ERROR (yuv_video, RESOURCE, READ, - ("Couldn't push YV12 data to VDPAU"), - ("Error returned from vdpau was: %s", - device->vdp_get_error_string (status))); - goto error; - } - break; - } - case GST_MAKE_FOURCC ('I', '4', '2', '0'): - { - VdpStatus status; - guint8 *data[3]; - guint32 stride[3]; - - data[0] = GST_BUFFER_DATA (buffer) + - gst_video_format_get_component_offset (GST_VIDEO_FORMAT_I420, - 0, yuv_video->width, yuv_video->height); - data[1] = GST_BUFFER_DATA (buffer) + - gst_video_format_get_component_offset (GST_VIDEO_FORMAT_I420, - 2, yuv_video->width, yuv_video->height); - data[2] = GST_BUFFER_DATA (buffer) + - gst_video_format_get_component_offset (GST_VIDEO_FORMAT_I420, - 1, yuv_video->width, yuv_video->height); - - stride[0] = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_I420, - 0, yuv_video->width); - stride[1] = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_I420, - 2, yuv_video->width); - stride[2] = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_I420, - 1, yuv_video->width); - - status = - device->vdp_video_surface_put_bits_ycbcr (surface, - VDP_YCBCR_FORMAT_YV12, (void *) data, stride); - if (G_UNLIKELY (status != VDP_STATUS_OK)) { - GST_ELEMENT_ERROR (yuv_video, RESOURCE, READ, - ("Couldn't push YV12 data to VDPAU"), - ("Error returned from vdpau was: %s", - device->vdp_get_error_string (status))); - goto error; - } - break; - } - case GST_MAKE_FOURCC ('N', 'V', '1', '2'): - { - VdpStatus status; - guint8 *data[2]; - guint32 stride[2]; - - data[0] = GST_BUFFER_DATA (buffer); - data[1] = GST_BUFFER_DATA (buffer) + yuv_video->width * yuv_video->height; - - stride[0] = yuv_video->width; - stride[1] = yuv_video->width; - - status = - device->vdp_video_surface_put_bits_ycbcr (surface, - VDP_YCBCR_FORMAT_NV12, (void *) data, stride); - if (G_UNLIKELY (status != VDP_STATUS_OK)) { - GST_ELEMENT_ERROR (yuv_video, RESOURCE, READ, - ("Couldn't get data from vdpau"), - ("Error returned from vdpau was: %s", - device->vdp_get_error_string (status))); - goto error; - } - break; - } - default: - break; - } - - gst_buffer_unref (buffer); - - gst_buffer_copy_metadata (outbuf, buffer, GST_BUFFER_COPY_TIMESTAMPS); - gst_buffer_set_caps (outbuf, GST_PAD_CAPS (yuv_video->src)); - - return gst_pad_push (yuv_video->src, outbuf); - -error: - gst_buffer_unref (outbuf); - return GST_FLOW_ERROR; -} - -static GstCaps * -gst_vdpau_yuv_video_get_caps (GstVdpauYUVVideo * yuv_video) -{ - GstVdpauDevice *device; - GstCaps *caps; - gint i; - - device = yuv_video->device; - - caps = gst_caps_new_empty (); - - for (i = 0; i < N_CHROMA_TYPES; i++) { - VdpStatus status; - VdpBool is_supported; - guint32 max_w, max_h; - - status = - device->vdp_video_surface_query_capabilities (device->device, - chroma_types[i], &is_supported, &max_w, &max_h); - - if (status != VDP_STATUS_OK && status != VDP_STATUS_INVALID_CHROMA_TYPE) { - GST_ELEMENT_ERROR (yuv_video, RESOURCE, READ, - ("Could not get query VDPAU video surface capabilites"), - ("Error returned from vdpau was: %s", - device->vdp_get_error_string (status))); - - goto error; - } - if (is_supported) { - gint j; - - for (j = 0; j < N_FORMATS; j++) { - if (formats[j].chroma_type != chroma_types[i]) - continue; - - status = - device->vdp_video_surface_query_ycbcr_capabilities (device->device, - formats[j].chroma_type, formats[j].format, &is_supported); - if (status != VDP_STATUS_OK - && status != VDP_STATUS_INVALID_Y_CB_CR_FORMAT) { - GST_ELEMENT_ERROR (yuv_video, RESOURCE, READ, - ("Could not query VDPAU YCbCr capabilites"), - ("Error returned from vdpau was: %s", - device->vdp_get_error_string (status))); - - goto error; - } - if (is_supported) { - GstCaps *format_caps; - - format_caps = gst_caps_new_simple ("video/x-raw-yuv", - "format", GST_TYPE_FOURCC, formats[j].fourcc, - "width", GST_TYPE_INT_RANGE, 1, max_w, - "height", GST_TYPE_INT_RANGE, 1, max_h, - "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL); - gst_caps_append (caps, format_caps); - } - } - } - } -error: - if (gst_caps_is_empty (caps)) { - gst_caps_unref (caps); - return NULL; - } - - return caps; -} - -static gboolean -gst_vdpau_yuv_video_sink_setcaps (GstPad * pad, GstCaps * caps) -{ - GstVdpauYUVVideo *yuv_video = GST_VDPAU_YUV_VIDEO (GST_OBJECT_PARENT (pad)); - - GstStructure *structure; - guint32 fourcc; - gint chroma_type = 0; - gint width, height; - gint framerate_numerator, framerate_denominator; - gint par_numerator, par_denominator; - gint i; - GstCaps *src_caps, *new_caps; - gboolean res; - - structure = gst_caps_get_structure (caps, 0); - - gst_structure_get_fourcc (structure, "format", &fourcc); - gst_structure_get_int (structure, "width", &width); - gst_structure_get_int (structure, "height", &height); - gst_structure_get_fraction (structure, "framerate", - &framerate_numerator, &framerate_denominator); - gst_structure_get_fraction (structure, "pixel-aspect-ratio", - &par_numerator, &par_denominator); - - for (i = 0; i < N_FORMATS; i++) { - if (formats[i].fourcc == fourcc) { - chroma_type = formats[i].chroma_type; - break; - } - } - - src_caps = gst_pad_get_allowed_caps (yuv_video->src); - if (G_UNLIKELY (!src_caps || !gst_caps_get_size (src_caps))) - return FALSE; - - new_caps = gst_caps_copy_nth (src_caps, 0); - gst_caps_unref (src_caps); - if (G_UNLIKELY (!new_caps)) - return FALSE; - - structure = gst_caps_get_structure (new_caps, 0); - - gst_structure_set (structure, - "device", G_TYPE_OBJECT, yuv_video->device, - "chroma-type", G_TYPE_INT, chroma_type, - "width", G_TYPE_INT, width, - "height", G_TYPE_INT, height, - "framerate", GST_TYPE_FRACTION, framerate_numerator, - framerate_denominator, "pixel-aspect-ratio", GST_TYPE_FRACTION, - par_numerator, par_denominator, NULL); - - gst_pad_fixate_caps (yuv_video->src, new_caps); - res = gst_pad_set_caps (yuv_video->src, new_caps); - - gst_caps_unref (new_caps); - - if (G_UNLIKELY (!res)) - return FALSE; - - yuv_video->width = width; - yuv_video->height = height; - yuv_video->format = fourcc; - yuv_video->chroma_type = chroma_type; - - return TRUE; -} - -static GstCaps * -gst_vdpau_yuv_video_sink_getcaps (GstPad * pad) -{ - GstVdpauYUVVideo *yuv_video; - - yuv_video = GST_VDPAU_YUV_VIDEO (GST_OBJECT_PARENT (pad)); - - if (yuv_video->sink_caps) - return gst_caps_copy (yuv_video->sink_caps); - - return gst_caps_copy (gst_pad_get_pad_template_caps (yuv_video->sink)); -} - -static GstStateChangeReturn -gst_vdpau_yuv_video_change_state (GstElement * element, - GstStateChange transition) -{ - GstVdpauYUVVideo *yuv_video; - - yuv_video = GST_VDPAU_YUV_VIDEO (element); - - switch (transition) { - case GST_STATE_CHANGE_NULL_TO_READY: - yuv_video->device = gst_vdpau_get_device (yuv_video->display); - if (!yuv_video->sink_caps) - yuv_video->sink_caps = gst_vdpau_yuv_video_get_caps (yuv_video); - break; - case GST_STATE_CHANGE_READY_TO_NULL: - g_object_unref (yuv_video->device); - yuv_video->device = NULL; - break; - default: - break; - } - - return GST_STATE_CHANGE_SUCCESS; -} - -/* GObject vmethod implementations */ - -static void -gst_vdpau_yuv_video_base_init (gpointer klass) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (klass); - - gst_element_class_set_details_simple (element_class, - "VdpauYUVVideo", - "Coyuv_video/Decoder/Video", - "VDPAU video surface to YUV", - "Carl-Anton Ingmarsson "); - - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&sink_template)); - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&src_template)); -} - -static void -gst_vdpau_yuv_video_class_init (GstVdpauYUVVideoClass * klass) -{ - GObjectClass *gobject_class; - GstElementClass *gstelement_class; - - gobject_class = (GObjectClass *) klass; - gstelement_class = (GstElementClass *) klass; - - gobject_class->finalize = gst_vdpau_yuv_video_finalize; - gobject_class->set_property = gst_vdpau_yuv_video_set_property; - gobject_class->get_property = gst_vdpau_yuv_video_get_property; - - g_object_class_install_property (gobject_class, PROP_DISPLAY, - g_param_spec_string ("display", "Display", "X Display name", - NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - - gstelement_class->change_state = gst_vdpau_yuv_video_change_state; -} - -static void -gst_vdpau_yuv_video_init (GstVdpauYUVVideo * yuv_video, - GstVdpauYUVVideoClass * klass) -{ - yuv_video->sink_caps = NULL; - - yuv_video->display = NULL; - yuv_video->device = NULL; - - yuv_video->height = 0; - yuv_video->width = 0; - yuv_video->format = 0; - yuv_video->chroma_type = 0; - - yuv_video->src = gst_pad_new_from_static_template (&src_template, "src"); - gst_element_add_pad (GST_ELEMENT (yuv_video), yuv_video->src); - - yuv_video->sink = gst_pad_new_from_static_template (&sink_template, "sink"); - gst_pad_set_getcaps_function (yuv_video->sink, - gst_vdpau_yuv_video_sink_getcaps); - gst_pad_set_setcaps_function (yuv_video->sink, - gst_vdpau_yuv_video_sink_setcaps); - gst_pad_set_chain_function (yuv_video->sink, gst_vdpau_yuv_video_chain); - gst_element_add_pad (GST_ELEMENT (yuv_video), yuv_video->sink); - gst_pad_set_active (yuv_video->sink, TRUE); -} - -static void -gst_vdpau_yuv_video_finalize (GObject * object) -{ - GstVdpauYUVVideo *yuv_video = (GstVdpauYUVVideo *) object; - - g_free (yuv_video->display); -} - -static void -gst_vdpau_yuv_video_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstVdpauYUVVideo *yuv_video = GST_VDPAU_YUV_VIDEO (object); - - switch (prop_id) { - case PROP_DISPLAY: - g_free (yuv_video->display); - yuv_video->display = g_value_dup_string (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_vdpau_yuv_video_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - GstVdpauYUVVideo *yuv_video = GST_VDPAU_YUV_VIDEO (object); - - switch (prop_id) { - case PROP_DISPLAY: - g_value_set_string (value, yuv_video->display); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} diff --git a/sys/vdpau/gstvdpauyuvvideo.h b/sys/vdpau/gstvdpauyuvvideo.h deleted file mode 100644 index e80eacf9..00000000 --- a/sys/vdpau/gstvdpauyuvvideo.h +++ /dev/null @@ -1,62 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2009 Carl-Anton Ingmarsson - * - * 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_VDPAU_YUV_VIDEO_H__ -#define __GST_VDPAU_YUV_VIDEO_H__ - -#include - -#include "gstvdpaudevice.h" - -G_BEGIN_DECLS - -#define GST_TYPE_VDPAU_YUV_VIDEO (gst_vdpau_yuv_video_get_type()) -#define GST_VDPAU_YUV_VIDEO(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VDPAU_YUV_VIDEO,GstVdpauYUVVideo)) -#define GST_VDPAU_YUV_VIDEO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VDPAU_YUV_VIDEO,GstVdpauYUVVideoClass)) -#define GST_VDPAU_YUV_VIDEO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_VDPAU_YUV_VIDEO, GstVdpauYUVVideoClass)) -#define GST_IS_VDPAU_YUV_VIDEO(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VDPAU_YUV_VIDEO)) -#define GST_IS_VDPAU_YUV_VIDEO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VDPAU_YUV_VIDEO)) - -typedef struct _GstVdpauYUVVideo GstVdpauYUVVideo; -typedef struct _GstVdpauYUVVideoClass GstVdpauYUVVideoClass; - -struct _GstVdpauYUVVideo { - GstElement element; - - GstPad *src, *sink; - GstCaps *sink_caps; - - gchar *display; - GstVdpauDevice *device; - - guint32 format; - gint chroma_type; - gint width, height; -}; - -struct _GstVdpauYUVVideoClass { - GstElementClass parent_class; -}; - -GType gst_vdpau_yuv_video_get_type (void); - -G_END_DECLS - -#endif /* __GST_VDPAU_YUV_VIDEO_H__ */ diff --git a/sys/vdpau/gstvdpdecoder.c b/sys/vdpau/gstvdpdecoder.c new file mode 100644 index 00000000..2e92381f --- /dev/null +++ b/sys/vdpau/gstvdpdecoder.c @@ -0,0 +1,275 @@ +/* + * GStreamer + * Copyright (C) 2009 Carl-Anton Ingmarsson + * + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include "gstvdpdecoder.h" + +GST_DEBUG_CATEGORY_STATIC (gst_vdp_decoder_debug); +#define GST_CAT_DEFAULT gst_vdp_decoder_debug + +/* Filter signals and args */ +enum +{ + /* FILL ME */ + LAST_SIGNAL +}; + +enum +{ + PROP_0, + PROP_DISPLAY, + PROP_SILENT +}; + +static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("video/vdpau-video, " "chroma-type = (int) 0")); + +#define DEBUG_INIT(bla) \ + GST_DEBUG_CATEGORY_INIT (gst_vdp_decoder_debug, "vdpaudecoder", 0, "vdpaudecoder base class"); + +GST_BOILERPLATE_FULL (GstVdpDecoder, gst_vdp_decoder, GstElement, + GST_TYPE_ELEMENT, DEBUG_INIT); + +static void gst_vdp_decoder_finalize (GObject * object); +static void gst_vdp_decoder_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_vdp_decoder_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +GstFlowReturn +gst_vdp_decoder_push_video_buffer (GstVdpDecoder * dec, + GstVdpVideoBuffer * buffer) +{ + GST_BUFFER_TIMESTAMP (buffer) = + gst_util_uint64_scale_int (GST_SECOND * dec->frame_nr, + dec->framerate_denominator, dec->framerate_numerator); + GST_BUFFER_DURATION (buffer) = + gst_util_uint64_scale_int (GST_SECOND, dec->framerate_denominator, + dec->framerate_numerator); + GST_BUFFER_OFFSET (buffer) = dec->frame_nr; + dec->frame_nr++; + GST_BUFFER_OFFSET_END (buffer) = dec->frame_nr; + gst_buffer_set_caps (GST_BUFFER (buffer), GST_PAD_CAPS (dec->src)); + + return gst_pad_push (dec->src, GST_BUFFER (buffer)); +} + +static GstStateChangeReturn +gst_vdp_decoder_change_state (GstElement * element, GstStateChange transition) +{ + GstVdpDecoder *dec; + + dec = GST_VDPAU_DECODER (element); + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + dec->device = gst_vdp_get_device (dec->display_name); + break; + case GST_STATE_CHANGE_READY_TO_NULL: + g_object_unref (dec->device); + dec->device = NULL; + break; + default: + break; + } + + return GST_STATE_CHANGE_SUCCESS; +} + +static gboolean +gst_vdp_decoder_sink_set_caps (GstPad * pad, GstCaps * caps) +{ + GstVdpDecoder *dec = GST_VDPAU_DECODER (GST_OBJECT_PARENT (pad)); + GstVdpDecoderClass *dec_class = GST_VDPAU_DECODER_GET_CLASS (dec); + + GstCaps *src_caps, *new_caps; + GstStructure *structure; + gint width, height; + gint framerate_numerator, framerate_denominator; + gint par_numerator, par_denominator; + gboolean res; + + structure = gst_caps_get_structure (caps, 0); + gst_structure_get_int (structure, "width", &width); + gst_structure_get_int (structure, "height", &height); + gst_structure_get_fraction (structure, "framerate", + &framerate_numerator, &framerate_denominator); + gst_structure_get_fraction (structure, "pixel-aspect-ratio", + &par_numerator, &par_denominator); + + src_caps = gst_pad_get_allowed_caps (dec->src); + if (G_UNLIKELY (!src_caps)) + return FALSE; + + new_caps = gst_caps_copy_nth (src_caps, 0); + gst_caps_unref (src_caps); + structure = gst_caps_get_structure (new_caps, 0); + gst_structure_set (structure, + "device", G_TYPE_OBJECT, dec->device, + "chroma-type", G_TYPE_INT, VDP_CHROMA_TYPE_420, + "width", G_TYPE_INT, width, + "height", G_TYPE_INT, height, + "framerate", GST_TYPE_FRACTION, framerate_numerator, + framerate_denominator, + "pixel-aspect-ratio", GST_TYPE_FRACTION, par_numerator, + par_denominator, NULL); + + gst_pad_fixate_caps (dec->src, new_caps); + res = gst_pad_set_caps (dec->src, new_caps); + + gst_caps_unref (new_caps); + + if (G_UNLIKELY (!res)) + return FALSE; + + dec->width = width; + dec->height = height; + dec->framerate_numerator = framerate_numerator; + dec->framerate_denominator = framerate_denominator; + + if (dec_class->set_caps && !dec_class->set_caps (dec, caps)) + return FALSE; + + return TRUE; +} + +/* GObject vmethod implementations */ + +static void +gst_vdp_decoder_base_init (gpointer klass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + + gst_element_class_set_details_simple (element_class, + "VdpauDecoder", + "Codec/Decoder/Video", + "VDPAU decoder base class", + "Carl-Anton Ingmarsson "); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&src_template)); +} + +/* initialize the vdpaudecoder's class */ +static void +gst_vdp_decoder_class_init (GstVdpDecoderClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + + gobject_class = (GObjectClass *) klass; + gstelement_class = (GstElementClass *) klass; + + gobject_class->finalize = gst_vdp_decoder_finalize; + gobject_class->set_property = gst_vdp_decoder_set_property; + gobject_class->get_property = gst_vdp_decoder_get_property; + + g_object_class_install_property (gobject_class, PROP_DISPLAY, + g_param_spec_string ("display", "Display", "X Display name", + NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + g_object_class_install_property (gobject_class, PROP_SILENT, + g_param_spec_boolean ("silent", "Silent", "Produce verbose output ?", + FALSE, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE)); + + gstelement_class->change_state = gst_vdp_decoder_change_state; +} + +static void +gst_vdp_decoder_init (GstVdpDecoder * dec, GstVdpDecoderClass * klass) +{ + dec->display_name = NULL; + dec->device = NULL; + dec->silent = FALSE; + + dec->height = 0; + dec->width = 0; + dec->framerate_numerator = 0; + dec->framerate_denominator = 0; + + dec->frame_nr = 0; + + dec->src = gst_pad_new_from_static_template (&src_template, "src"); + gst_element_add_pad (GST_ELEMENT (dec), dec->src); + + dec->sink = gst_pad_new_from_template (gst_element_class_get_pad_template + (GST_ELEMENT_CLASS (klass), "sink"), "sink"); + gst_pad_set_setcaps_function (dec->sink, gst_vdp_decoder_sink_set_caps); + gst_element_add_pad (GST_ELEMENT (dec), dec->sink); + gst_pad_set_active (dec->sink, TRUE); +} + +static void +gst_vdp_decoder_finalize (GObject * object) +{ + GstVdpDecoder *dec = (GstVdpDecoder *) object; + + if (dec->device) + g_object_unref (dec->device); + + g_free (dec->display_name); +} + +static void +gst_vdp_decoder_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstVdpDecoder *dec = GST_VDPAU_DECODER (object); + + switch (prop_id) { + case PROP_DISPLAY: + g_free (dec->display_name); + dec->display_name = g_value_dup_string (value); + break; + case PROP_SILENT: + dec->silent = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_vdp_decoder_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstVdpDecoder *dec = GST_VDPAU_DECODER (object); + + switch (prop_id) { + case PROP_DISPLAY: + g_value_set_string (value, dec->display_name); + break; + case PROP_SILENT: + g_value_set_boolean (value, dec->silent); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} diff --git a/sys/vdpau/gstvdpdecoder.h b/sys/vdpau/gstvdpdecoder.h new file mode 100644 index 00000000..f918225e --- /dev/null +++ b/sys/vdpau/gstvdpdecoder.h @@ -0,0 +1,74 @@ +/* + * GStreamer + * Copyright (C) 2009 Carl-Anton Ingmarsson + * + * 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_VDPAU_DECODER_H__ +#define __GST_VDPAU_DECODER_H__ + +#include + +#include "gstvdpdevice.h" +#include "gstvdpvideobuffer.h" + +G_BEGIN_DECLS + +#define GST_TYPE_VDPAU_DECODER (gst_vdp_decoder_get_type()) +#define GST_VDPAU_DECODER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VDPAU_DECODER,GstVdpDecoder)) +#define GST_VDPAU_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VDPAU_DECODER,GstVdpDecoderClass)) +#define GST_VDPAU_DECODER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_VDPAU_DECODER, GstVdpDecoderClass)) +#define GST_IS_VDPAU_DECODER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VDPAU_DECODER)) +#define GST_IS_VDPAU_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VDPAU_DECODER)) + +typedef struct _GstVdpDecoder GstVdpDecoder; +typedef struct _GstVdpDecoderClass GstVdpDecoderClass; +typedef struct _VdpauFunctions VdpauFunctions; + +struct _GstVdpDecoder { + GstElement element; + + gchar *display_name; + GstVdpDevice *device; + + GstPad *src; + GstPad *sink; + + gint width, height; + gint framerate_numerator, framerate_denominator; + guint32 format; + + gint frame_nr; + + gboolean silent; +}; + +struct _GstVdpDecoderClass { + GstElementClass parent_class; + + gboolean (*set_caps) (GstVdpDecoder *dec, GstCaps *caps); +}; + +GType gst_vdp_decoder_get_type (void); + +gboolean gst_vdp_decoder_push_video_buffer (GstVdpDecoder * dec, + GstVdpVideoBuffer *buffer); +VdpVideoSurface gst_vdp_decoder_create_video_surface (GstVdpDecoder *dec); + +G_END_DECLS + +#endif /* __GST_VDPAU_DECODER_H__ */ diff --git a/sys/vdpau/gstvdpdevice.c b/sys/vdpau/gstvdpdevice.c new file mode 100644 index 00000000..1dc42d68 --- /dev/null +++ b/sys/vdpau/gstvdpdevice.c @@ -0,0 +1,269 @@ +/* + * GStreamer + * Copyright (C) 2009 Carl-Anton Ingmarsson + * + * 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. + */ + +#include +#include + +#include "gstvdpdevice.h" + +GST_DEBUG_CATEGORY_STATIC (gst_vdp_device_debug); +#define GST_CAT_DEFAULT gst_vdp_device_debug + +enum +{ + PROP_0, + PROP_DISPLAY +}; + + + +G_DEFINE_TYPE (GstVdpDevice, gst_vdp_device, G_TYPE_OBJECT); + +static void +gst_vdp_device_init (GstVdpDevice * device) +{ + device->display_name = NULL; + device->display = NULL; + device->device = VDP_INVALID_HANDLE; +} + +static void +gst_vdp_device_finalize (GObject * object) +{ + GstVdpDevice *device = (GstVdpDevice *) object; + + device->vdp_device_destroy (device->device); + g_free (device->display_name); + + G_OBJECT_CLASS (gst_vdp_device_parent_class)->finalize (object); + +} + +static void +gst_vdp_device_constructed (GObject * object) +{ + GstVdpDevice *device = (GstVdpDevice *) object; + gint screen; + VdpStatus status; + gint i; + + typedef struct + { + gint id; + void *func; + } VdpFunction; + + VdpFunction vdp_function[] = { + {VDP_FUNC_ID_DEVICE_DESTROY, &device->vdp_device_destroy}, + {VDP_FUNC_ID_VIDEO_SURFACE_CREATE, + &device->vdp_video_surface_create}, + {VDP_FUNC_ID_VIDEO_SURFACE_DESTROY, + &device->vdp_video_surface_destroy}, + {VDP_FUNC_ID_VIDEO_SURFACE_QUERY_CAPABILITIES, + &device->vdp_video_surface_query_capabilities}, + {VDP_FUNC_ID_VIDEO_SURFACE_QUERY_GET_PUT_BITS_Y_CB_CR_CAPABILITIES, + &device->vdp_video_surface_query_ycbcr_capabilities}, + {VDP_FUNC_ID_VIDEO_SURFACE_GET_BITS_Y_CB_CR, + &device->vdp_video_surface_get_bits_ycbcr}, + {VDP_FUNC_ID_VIDEO_SURFACE_PUT_BITS_Y_CB_CR, + &device->vdp_video_surface_put_bits_ycbcr}, + {VDP_FUNC_ID_VIDEO_SURFACE_GET_PARAMETERS, + &device->vdp_video_surface_get_parameters}, + {VDP_FUNC_ID_DECODER_CREATE, &device->vdp_decoder_create}, + {VDP_FUNC_ID_DECODER_RENDER, &device->vdp_decoder_render}, + {VDP_FUNC_ID_DECODER_DESTROY, &device->vdp_decoder_destroy}, + {VDP_FUNC_ID_DECODER_QUERY_CAPABILITIES, + &device->vdp_decoder_query_capabilities}, + {VDP_FUNC_ID_DECODER_GET_PARAMETERS, + &device->vdp_decoder_get_parameters}, + {0, NULL} + }; + + device->display = XOpenDisplay (device->display_name); + if (!device->display) { + GST_ERROR_OBJECT (device, "Could not open X display with name: %s", + device->display_name); + return; + } + + screen = DefaultScreen (device->display); + status = + vdp_device_create_x11 (device->display, screen, &device->device, + &device->vdp_get_proc_address); + if (status != VDP_STATUS_OK) { + GST_ERROR_OBJECT (device, "Could not create VDPAU device"); + XCloseDisplay (device->display); + device->display = NULL; + + return; + } + + status = device->vdp_get_proc_address (device->device, + VDP_FUNC_ID_GET_ERROR_STRING, (void **) &device->vdp_get_error_string); + if (status != VDP_STATUS_OK) { + GST_ERROR_OBJECT (device, + "Could not get vdp_get_error_string function pointer from VDPAU"); + goto error; + } + + for (i = 0; vdp_function[i].func != NULL; i++) { + status = device->vdp_get_proc_address (device->device, + vdp_function[i].id, vdp_function[i].func); + + if (status != VDP_STATUS_OK) { + GST_ERROR_OBJECT (device, "Could not get function pointer from VDPAU," + " error returned was: %s", device->vdp_get_error_string (status)); + goto error; + } + } + + return; + +error: + XCloseDisplay (device->display); + device->display = NULL; + + if (device->device != VDP_INVALID_HANDLE) { + device->vdp_device_destroy (device->device); + device->device = VDP_INVALID_HANDLE; + } +} + +static void +gst_vdp_device_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstVdpDevice *device; + + g_return_if_fail (GST_IS_VDPAU_DEVICE (object)); + + device = (GstVdpDevice *) object; + + switch (prop_id) { + case PROP_DISPLAY: + device->display_name = g_value_dup_string (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_vdp_device_get_property (GObject * object, guint prop_id, GValue * value, + GParamSpec * pspec) +{ + GstVdpDevice *device; + + g_return_if_fail (GST_IS_VDPAU_DEVICE (object)); + + device = (GstVdpDevice *) object; + + switch (prop_id) { + case PROP_DISPLAY: + g_value_set_string (value, device->display_name); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_vdp_device_class_init (GstVdpDeviceClass * klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->constructed = gst_vdp_device_constructed; + object_class->finalize = gst_vdp_device_finalize; + object_class->get_property = gst_vdp_device_get_property; + object_class->set_property = gst_vdp_device_set_property; + + + g_object_class_install_property (object_class, + PROP_DISPLAY, + g_param_spec_string ("display", + "Display", + "X Display Name", + "", G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); + + GST_DEBUG_CATEGORY_INIT (gst_vdp_device_debug, "vdpaudevice", + 0, "vdpaudevice"); +} + +GstVdpDevice * +gst_vdp_device_new (const gchar * display_name) +{ + GstVdpDevice *device; + + device = g_object_new (GST_TYPE_VDPAU_DEVICE, "display", display_name); + + return device; +} + +static void +device_destroyed_cb (gpointer data, GObject * object) +{ + GHashTable *devices_hash = data; + GHashTableIter iter; + gpointer device; + + g_hash_table_iter_init (&iter, devices_hash); + while (g_hash_table_iter_next (&iter, NULL, &device)) { + if (device == object) { + g_hash_table_iter_remove (&iter); + break; + } + } +} + +static gpointer +create_devices_hash (gpointer data) +{ + return g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); +} + +GstVdpDevice * +gst_vdp_get_device (const gchar * display_name) +{ + static GOnce my_once = G_ONCE_INIT; + GHashTable *devices_hash; + GstVdpDevice *device; + + g_once (&my_once, create_devices_hash, NULL); + devices_hash = my_once.retval; + + if (display_name) + device = g_hash_table_lookup (devices_hash, display_name); + else + device = g_hash_table_lookup (devices_hash, ""); + + if (!device) { + device = gst_vdp_device_new (display_name); + g_object_weak_ref (G_OBJECT (device), device_destroyed_cb, devices_hash); + if (display_name) + g_hash_table_insert (devices_hash, g_strdup (display_name), device); + else + g_hash_table_insert (devices_hash, g_strdup (""), device); + } else + g_object_ref (device); + + return device; +} diff --git a/sys/vdpau/gstvdpdevice.h b/sys/vdpau/gstvdpdevice.h new file mode 100644 index 00000000..8b2f596c --- /dev/null +++ b/sys/vdpau/gstvdpdevice.h @@ -0,0 +1,132 @@ +/* + * GStreamer + * Copyright (C) 2009 Carl-Anton Ingmarsson + * + * 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_VDPAU_DEVICE_H_ +#define _GST_VDPAU_DEVICE_H_ + +#include +#include + +#include + +G_BEGIN_DECLS + +#define GST_TYPE_VDPAU_DEVICE (gst_vdp_device_get_type ()) +#define GST_VDPAU_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_VDPAU_DEVICE, GstVdpDevice)) +#define GST_VDPAU_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_VDPAU_DEVICE, GstVdpDeviceClass)) +#define GST_IS_VDPAU_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_VDPAU_DEVICE)) +#define GST_IS_VDPAU_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_VDPAU_DEVICE)) +#define GST_VDPAU_DEVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_VDPAU_DEVICE, GstVdpDeviceClass)) + +typedef struct _GstVdpDeviceClass GstVdpDeviceClass; +typedef struct _GstVdpDevice GstVdpDevice; + +struct _GstVdpDeviceClass +{ + GObjectClass parent_class; +}; + +struct _GstVdpDevice +{ + GObject object; + + gchar *display_name; + Display *display; + VdpDevice device; + + VdpDeviceDestroy *vdp_device_destroy; + VdpGetProcAddress *vdp_get_proc_address; + VdpGetErrorString *vdp_get_error_string; + + VdpVideoSurfaceCreate *vdp_video_surface_create; + VdpVideoSurfaceDestroy *vdp_video_surface_destroy; + VdpVideoSurfaceQueryCapabilities *vdp_video_surface_query_capabilities; + VdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities *vdp_video_surface_query_ycbcr_capabilities; + VdpVideoSurfaceGetParameters *vdp_video_surface_get_parameters; + VdpVideoSurfaceGetBitsYCbCr *vdp_video_surface_get_bits_ycbcr; + VdpVideoSurfacePutBitsYCbCr *vdp_video_surface_put_bits_ycbcr; + + VdpDecoderCreate *vdp_decoder_create; + VdpDecoderDestroy *vdp_decoder_destroy; + VdpDecoderRender *vdp_decoder_render; + VdpDecoderQueryCapabilities *vdp_decoder_query_capabilities; + VdpDecoderGetParameters *vdp_decoder_get_parameters; +}; + +typedef struct +{ + VdpChromaType chroma_type; + VdpYCbCrFormat format; + guint32 fourcc; +} VdpauFormats; + +#define N_CHROMA_TYPES 3 +#define N_FORMATS 7 + +static const VdpChromaType chroma_types[N_CHROMA_TYPES] = + { VDP_CHROMA_TYPE_420, VDP_CHROMA_TYPE_422, VDP_CHROMA_TYPE_444 }; + +static const VdpauFormats formats[N_FORMATS] = { + { + VDP_CHROMA_TYPE_420, + VDP_YCBCR_FORMAT_NV12, + GST_MAKE_FOURCC ('N', 'V', '1', '2') + }, + { + VDP_CHROMA_TYPE_422, + VDP_YCBCR_FORMAT_UYVY, + GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y') + }, + { + VDP_CHROMA_TYPE_444, + VDP_YCBCR_FORMAT_V8U8Y8A8, + GST_MAKE_FOURCC ('A', 'Y', 'U', 'V') + }, + { + VDP_CHROMA_TYPE_444, + VDP_YCBCR_FORMAT_Y8U8V8A8, + GST_MAKE_FOURCC ('A', 'V', 'U', 'Y') + }, + { + VDP_CHROMA_TYPE_422, + VDP_YCBCR_FORMAT_YUYV, + GST_MAKE_FOURCC ('Y', 'U', 'Y', 'V') + }, + { + VDP_CHROMA_TYPE_420, + VDP_YCBCR_FORMAT_YV12, + GST_MAKE_FOURCC ('Y', 'V', '1', '2') + }, + { + VDP_CHROMA_TYPE_420, + VDP_YCBCR_FORMAT_YV12, + GST_MAKE_FOURCC ('I', '4', '2', '0') + } +}; + +GType gst_vdp_device_get_type (void) G_GNUC_CONST; + +GstVdpDevice *gst_vdp_device_new (const gchar *display_name); + +GstVdpDevice *gst_vdp_get_device (const gchar *display_name); + +G_END_DECLS + +#endif /* _GST_VDPAU_DEVICE_H_ */ diff --git a/sys/vdpau/gstvdpmpegdecoder.c b/sys/vdpau/gstvdpmpegdecoder.c new file mode 100644 index 00000000..df8a5b67 --- /dev/null +++ b/sys/vdpau/gstvdpmpegdecoder.c @@ -0,0 +1,481 @@ +/* + * GStreamer + * Copyright (C) 2009 Carl-Anton Ingmarsson + * + * 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-vdpaumpegdecoder + * + * FIXME:Describe vdpaumpegdecoder here. + * + * + * Example launch line + * |[ + * gst-launch -v -m fakesrc ! vdpaumpegdecoder ! fakesink silent=TRUE + * ]| + * + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include + +#include "mpegutil.h" +#include "gstvdpmpegdecoder.h" + +GST_DEBUG_CATEGORY_STATIC (gst_vdp_mpeg_decoder_debug); +#define GST_CAT_DEFAULT gst_vdp_mpeg_decoder_debug + +/* Filter signals and args */ +enum +{ + /* FILL ME */ + LAST_SIGNAL +}; + +enum +{ + PROP_0 +}; + +/* the capabilities of the inputs and outputs. + * + * describe the real formats here. + */ +static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("video/mpeg, mpegversion = (int) [ 1, 2 ], " + "systemstream = (boolean) false, parsed = (boolean) true") + ); + +#define DEBUG_INIT(bla) \ +GST_DEBUG_CATEGORY_INIT (gst_vdp_mpeg_decoder_debug, "vdpaumpegdecoder", 0, "VDPAU powered mpeg decoder"); + +GST_BOILERPLATE_FULL (GstVdpMpegDecoder, gst_vdp_mpeg_decoder, + GstVdpDecoder, GST_TYPE_VDPAU_DECODER, DEBUG_INIT); + +static void gst_vdp_mpeg_decoder_finalize (GObject * object); +static void gst_vdp_mpeg_decoder_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec); +static void gst_vdp_mpeg_decoder_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec); + +static gboolean +gst_vdp_mpeg_decoder_set_caps (GstVdpDecoder * dec, GstCaps * caps) +{ + GstVdpMpegDecoder *mpeg_dec; + GstStructure *structure; + const GValue *value; + GstBuffer *codec_data; + MPEGSeqHdr hdr = { 0, }; + VdpDecoderProfile profile; + GstVdpDevice *device; + VdpStatus status; + + mpeg_dec = GST_VDPAU_MPEG_DECODER (dec); + + structure = gst_caps_get_structure (caps, 0); + gst_structure_get_int (structure, "mpegversion", &mpeg_dec->version); + if (mpeg_dec->version == 1) + profile = VDP_DECODER_PROFILE_MPEG1; + + value = gst_structure_get_value (structure, "codec_data"); + codec_data = gst_value_get_buffer (value); + mpeg_util_parse_sequence_hdr (&hdr, GST_BUFFER_DATA (codec_data), + GST_BUFFER_DATA (codec_data) + GST_BUFFER_SIZE (codec_data)); + if (mpeg_dec->version != 1) { + switch (hdr.profile) { + case 5: + profile = VDP_DECODER_PROFILE_MPEG2_SIMPLE; + break; + default: + profile = VDP_DECODER_PROFILE_MPEG2_MAIN; + break; + } + } + + memcpy (&mpeg_dec->vdp_info.intra_quantizer_matrix, + &hdr.intra_quantizer_matrix, 64); + memcpy (&mpeg_dec->vdp_info.non_intra_quantizer_matrix, + &hdr.non_intra_quantizer_matrix, 64); + + device = dec->device; + status = device->vdp_decoder_create (device->device, profile, dec->width, + dec->height, 2, &mpeg_dec->decoder); + if (status != VDP_STATUS_OK) { + GST_ELEMENT_ERROR (mpeg_dec, RESOURCE, READ, + ("Could not create vdpau decoder"), + ("Error returned from vdpau was: %s", + device->vdp_get_error_string (status))); + return FALSE; + } + return TRUE; +} + +static GstFlowReturn +gst_vdp_mpeg_decoder_decode (GstVdpMpegDecoder * mpeg_dec) +{ + GstVdpDecoder *dec; + GstBuffer *buffer; + GstVdpVideoBuffer *outbuf; + VdpVideoSurface surface; + GstVdpDevice *device; + VdpBitstreamBuffer vbit[1]; + VdpStatus status; + GstFlowReturn ret; + + dec = GST_VDPAU_DECODER (mpeg_dec); + + buffer = gst_adapter_take_buffer (mpeg_dec->adapter, + gst_adapter_available (mpeg_dec->adapter)); + + outbuf = gst_vdp_video_buffer_new (dec->device, VDP_CHROMA_TYPE_420, + dec->width, dec->height); + surface = outbuf->surface; + + device = dec->device; + + vbit[0].struct_version = VDP_BITSTREAM_BUFFER_VERSION; + vbit[0].bitstream = GST_BUFFER_DATA (buffer); + vbit[0].bitstream_bytes = GST_BUFFER_SIZE (buffer); + + status = device->vdp_decoder_render (mpeg_dec->decoder, surface, + (VdpPictureInfo *) & mpeg_dec->vdp_info, 1, vbit); + gst_buffer_unref (buffer); + mpeg_dec->vdp_info.slice_count = 0; + + if (status != VDP_STATUS_OK) { + GST_ELEMENT_ERROR (mpeg_dec, RESOURCE, READ, + ("Could not decode"), + ("Error returned from vdpau was: %s", + device->vdp_get_error_string (status))); + + if (mpeg_dec->vdp_info.forward_reference != VDP_INVALID_HANDLE) { + gst_buffer_unref (mpeg_dec->f_buffer); + mpeg_dec->vdp_info.forward_reference = VDP_INVALID_HANDLE; + } + + gst_buffer_unref (GST_BUFFER (outbuf)); + + return GST_FLOW_ERROR; + } + + gst_buffer_ref (GST_BUFFER (outbuf)); + + ret = gst_vdp_decoder_push_video_buffer (GST_VDPAU_DECODER (mpeg_dec), + outbuf); + + if (mpeg_dec->vdp_info.forward_reference != VDP_INVALID_HANDLE) + gst_buffer_unref (mpeg_dec->f_buffer); + + mpeg_dec->vdp_info.forward_reference = surface; + mpeg_dec->f_buffer = GST_BUFFER (outbuf); + + return ret; +} + +static gboolean +gst_vdp_mpeg_decoder_parse_picture_coding (GstVdpMpegDecoder * mpeg_dec, + guint8 * data, guint8 * end) +{ + GstVdpDecoder *dec; + MPEGPictureExt pic_ext; + VdpPictureInfoMPEG1Or2 *info; + + dec = GST_VDPAU_DECODER (mpeg_dec); + info = &mpeg_dec->vdp_info; + + if (!mpeg_util_parse_picture_coding_extension (&pic_ext, data, end)) + return FALSE; + + memcpy (&mpeg_dec->vdp_info.f_code, &pic_ext.f_code, 4); + + info->intra_dc_precision = pic_ext.intra_dc_precision; + info->picture_structure = pic_ext.picture_structure; + info->top_field_first = pic_ext.top_field_first; + info->frame_pred_frame_dct = pic_ext.frame_pred_frame_dct; + info->concealment_motion_vectors = pic_ext.concealment_motion_vectors; + info->q_scale_type = pic_ext.q_scale_type; + info->intra_vlc_format = pic_ext.intra_vlc_format; + + mpeg_dec->want_slice = TRUE; + + return TRUE; +} + +static gboolean +gst_vdp_mpeg_decoder_parse_sequence (GstVdpMpegDecoder * mpeg_dec, + guint8 * data, guint8 * end) +{ + GstVdpDecoder *dec; + MPEGSeqHdr hdr; + + dec = GST_VDPAU_DECODER (mpeg_dec); + + if (!mpeg_util_parse_sequence_hdr (&hdr, data, end)) + return FALSE; + + memcpy (&mpeg_dec->vdp_info.intra_quantizer_matrix, + &hdr.intra_quantizer_matrix, 64); + memcpy (&mpeg_dec->vdp_info.non_intra_quantizer_matrix, + &hdr.non_intra_quantizer_matrix, 64); + + return TRUE; +} + +static gboolean +gst_vdp_mpeg_decoder_parse_picture (GstVdpMpegDecoder * mpeg_dec, + guint8 * data, guint8 * end) +{ + GstVdpDecoder *dec; + MPEGPictureHdr pic_hdr; + + dec = GST_VDPAU_DECODER (mpeg_dec); + + if (!mpeg_util_parse_picture_hdr (&pic_hdr, data, end)) + return FALSE; + + mpeg_dec->vdp_info.picture_coding_type = pic_hdr.pic_type; + + + if (pic_hdr.pic_type == I_FRAME && + mpeg_dec->vdp_info.forward_reference != VDP_INVALID_HANDLE) { + gst_buffer_unref (mpeg_dec->f_buffer); + mpeg_dec->vdp_info.forward_reference = VDP_INVALID_HANDLE; + } + + if (mpeg_dec->version == 1) { + mpeg_dec->vdp_info.full_pel_forward_vector = + pic_hdr.full_pel_forward_vector; + mpeg_dec->vdp_info.full_pel_backward_vector = + pic_hdr.full_pel_backward_vector; + memcpy (&mpeg_dec->vdp_info.f_code, &pic_hdr.f_code, 4); + + mpeg_dec->want_slice = TRUE; + } else + mpeg_dec->want_slice = FALSE; + + return TRUE; +} + +static gboolean +gst_vdp_mpeg_decoder_parse_gop (GstVdpMpegDecoder * mpeg_dec, guint8 * data, + guint8 * end) +{ + MPEGPictureGOP gop; + + if (!mpeg_util_parse_picture_gop (&gop, data, end)) + return FALSE; + + return TRUE; +} + +static gboolean +gst_vdp_mpeg_decoder_parse_quant_matrix (GstVdpMpegDecoder * mpeg_dec, + guint8 * data, guint8 * end) +{ + MPEGQuantMatrix qm; + + if (!mpeg_util_parse_quant_matrix (&qm, data, end)) + return FALSE; + + memcpy (&mpeg_dec->vdp_info.intra_quantizer_matrix, + &qm.intra_quantizer_matrix, 64); + memcpy (&mpeg_dec->vdp_info.non_intra_quantizer_matrix, + &qm.non_intra_quantizer_matrix, 64); + return TRUE; +} + +static GstFlowReturn +gst_vdp_mpeg_decoder_chain (GstPad * pad, GstBuffer * buffer) +{ + GstVdpMpegDecoder *mpeg_dec; + guint8 *data, *end; + guint32 sync_word = 0xffffffff; + + mpeg_dec = GST_VDPAU_MPEG_DECODER (GST_OBJECT_PARENT (pad)); + + data = GST_BUFFER_DATA (buffer); + end = GST_BUFFER_DATA (buffer) + GST_BUFFER_SIZE (buffer); + + while ((data = mpeg_util_find_start_code (&sync_word, data, end))) { + guint8 *packet_start; + guint8 *packet_end; + + packet_start = data - 3; + packet_end = mpeg_util_find_start_code (&sync_word, data, end); + if (packet_end) + packet_end -= 3; + else + packet_end = end; + + if (data[0] >= MPEG_PACKET_SLICE_MIN && data[0] <= MPEG_PACKET_SLICE_MAX) { + GstBuffer *subbuf; + + GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_SLICE"); + if (mpeg_dec->want_slice) { + subbuf = + gst_buffer_create_sub (buffer, + packet_start - GST_BUFFER_DATA (buffer), packet_end - packet_start); + gst_adapter_push (mpeg_dec->adapter, subbuf); + mpeg_dec->vdp_info.slice_count++; + } + } + + switch (data[0]) { + case MPEG_PACKET_PICTURE: + GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_PICTURE"); + if (mpeg_dec->vdp_info.slice_count > 0 && mpeg_dec->want_slice) { + if (gst_vdp_mpeg_decoder_decode (mpeg_dec) != GST_FLOW_OK) + return GST_FLOW_ERROR; + } + gst_vdp_mpeg_decoder_parse_picture (mpeg_dec, packet_start, packet_end); + break; + case MPEG_PACKET_SEQUENCE: + GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_SEQUENCE"); + gst_vdp_mpeg_decoder_parse_sequence (mpeg_dec, packet_start, + packet_end); + break; + case MPEG_PACKET_EXTENSION: + GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_EXTENSION"); + switch (read_bits (data + 1, 0, 4)) { + case MPEG_PACKET_EXT_PICTURE_CODING: + gst_vdp_mpeg_decoder_parse_picture_coding (mpeg_dec, packet_start, + packet_end); + break; + default: + break; + } + break; + case MPEG_PACKET_EXT_QUANT_MATRIX: + GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_EXT_QUANT_MATRIX"); + gst_vdp_mpeg_decoder_parse_quant_matrix (mpeg_dec, packet_start, + packet_end); + break; + case MPEG_PACKET_GOP: + GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_GOP"); + gst_vdp_mpeg_decoder_parse_gop (mpeg_dec, packet_start, packet_end); + break; + default: + break; + } + } + + return GST_FLOW_OK; +} + +/* GObject vmethod implementations */ + +static void +gst_vdp_mpeg_decoder_base_init (gpointer gclass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (gclass); + + gst_element_class_set_details_simple (element_class, + "VdpauMpegDecoder", + "Decoder", + "decode mpeg stream with vdpau", + "Carl-Anton Ingmarsson "); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&sink_factory)); +} + +/* initialize the vdpaumpegdecoder's class */ +static void +gst_vdp_mpeg_decoder_class_init (GstVdpMpegDecoderClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + GstVdpDecoderClass *vdpaudec_class; + + gobject_class = (GObjectClass *) klass; + gstelement_class = (GstElementClass *) klass; + vdpaudec_class = (GstVdpDecoderClass *) klass; + + gobject_class->finalize = gst_vdp_mpeg_decoder_finalize; + gobject_class->set_property = gst_vdp_mpeg_decoder_set_property; + gobject_class->get_property = gst_vdp_mpeg_decoder_get_property; + + vdpaudec_class->set_caps = gst_vdp_mpeg_decoder_set_caps; +} + +static void +gst_vdp_mpeg_decoder_init_info (VdpPictureInfoMPEG1Or2 * vdp_info) +{ + vdp_info->forward_reference = VDP_INVALID_HANDLE; + vdp_info->backward_reference = VDP_INVALID_HANDLE; + vdp_info->slice_count = 0; + vdp_info->picture_structure = 0; + vdp_info->picture_coding_type = 0; + vdp_info->intra_dc_precision = 0; + vdp_info->frame_pred_frame_dct = 0; + vdp_info->concealment_motion_vectors = 0; +} + +static void +gst_vdp_mpeg_decoder_init (GstVdpMpegDecoder * mpeg_dec, + GstVdpMpegDecoderClass * gclass) +{ + GstVdpDecoder *dec; + + dec = GST_VDPAU_DECODER (mpeg_dec); + + mpeg_dec->decoder = VDP_INVALID_HANDLE; + gst_vdp_mpeg_decoder_init_info (&mpeg_dec->vdp_info); + + mpeg_dec->adapter = gst_adapter_new (); + + mpeg_dec->want_slice = FALSE; + + gst_pad_set_chain_function (dec->sink, gst_vdp_mpeg_decoder_chain); +} + +static void +gst_vdp_mpeg_decoder_finalize (GObject * object) +{ + GstVdpMpegDecoder *mpeg_dec = (GstVdpMpegDecoder *) object; + + g_object_unref (mpeg_dec->adapter); +} + +static void +gst_vdp_mpeg_decoder_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + switch (prop_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_vdp_mpeg_decoder_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + switch (prop_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} diff --git a/sys/vdpau/gstvdpmpegdecoder.h b/sys/vdpau/gstvdpmpegdecoder.h new file mode 100644 index 00000000..dc90764b --- /dev/null +++ b/sys/vdpau/gstvdpmpegdecoder.h @@ -0,0 +1,65 @@ +/* + * GStreamer + * Copyright (C) 2009 Carl-Anton Ingmarsson + * + * 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_VDPAU_MPEG_DECODER_H__ +#define __GST_VDPAU_MPEG_DECODER_H__ + +#include +#include + +#include "gstvdpdecoder.h" + +G_BEGIN_DECLS + +#define GST_TYPE_VDPAU_MPEG_DECODER (gst_vdp_mpeg_decoder_get_type()) +#define GST_VDPAU_MPEG_DECODER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VDPAU_MPEG_DECODER,GstVdpMpegDecoder)) +#define GST_VDPAU_MPEG_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VDPAU_MPEG_DECODER,GstVdpMpegDecoderClass)) +#define GST_IS_VDPAU_MPEG_DECODER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VDPAU_MPEG_DECODER)) +#define GST_IS_VDPAU_MPEG_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VDPAU_MPEG_DECODER)) + +typedef struct _GstVdpMpegDecoder GstVdpMpegDecoder; +typedef struct _GstVdpMpegDecoderClass GstVdpMpegDecoderClass; + +struct _GstVdpMpegDecoder +{ + GstVdpDecoder dec; + + gint version; + + VdpDecoder decoder; + VdpPictureInfoMPEG1Or2 vdp_info; + GstBuffer *f_buffer; + + gboolean want_slice; + + GstAdapter *adapter; + gint slices; +}; + +struct _GstVdpMpegDecoderClass +{ + GstVdpDecoderClass parent_class; +}; + +GType gst_vdp_mpeg_decoder_get_type (void); + +G_END_DECLS + +#endif /* __GST_VDPAU_MPEG_DECODER_H__ */ diff --git a/sys/vdpau/gstvdpvideobuffer.c b/sys/vdpau/gstvdpvideobuffer.c new file mode 100644 index 00000000..c62ac771 --- /dev/null +++ b/sys/vdpau/gstvdpvideobuffer.c @@ -0,0 +1,114 @@ +/* + * GStreamer + * Copyright (C) 2009 Carl-Anton Ingmarsson + * + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstvdpvideobuffer.h" + +static GObjectClass *gst_vdp_video_buffer_parent_class; + +static void +gst_vdp_video_buffer_finalize (GstVdpVideoBuffer * buffer) +{ + GstVdpDevice *device = buffer->device; + VdpStatus status; + + status = device->vdp_video_surface_destroy (buffer->surface); + if (status != VDP_STATUS_OK) + GST_ERROR + ("Couldn't destroy the buffers VdpVideoSurface, error returned was: %s", + device->vdp_get_error_string (status)); + + g_object_unref (buffer->device); + + GST_MINI_OBJECT_CLASS (gst_vdp_video_buffer_parent_class)->finalize + (GST_MINI_OBJECT (buffer)); +} + +static void +gst_vdp_video_buffer_init (GstVdpVideoBuffer * buffer, gpointer g_class) +{ + buffer->device = NULL; + buffer->surface = VDP_INVALID_HANDLE; +} + +static void +gst_vdp_video_buffer_class_init (gpointer g_class, gpointer class_data) +{ + GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (g_class); + + gst_vdp_video_buffer_parent_class = g_type_class_peek_parent (g_class); + + mini_object_class->finalize = (GstMiniObjectFinalizeFunction) + gst_vdp_video_buffer_finalize; +} + + +GType +gst_vdp_video_buffer_get_type (void) +{ + static GType _gst_vdp_video_buffer_type; + + if (G_UNLIKELY (_gst_vdp_video_buffer_type == 0)) { + static const GTypeInfo info = { + sizeof (GstBufferClass), + NULL, + NULL, + gst_vdp_video_buffer_class_init, + NULL, + NULL, + sizeof (GstVdpVideoBuffer), + 0, + (GInstanceInitFunc) gst_vdp_video_buffer_init, + NULL + }; + _gst_vdp_video_buffer_type = g_type_register_static (GST_TYPE_BUFFER, + "GstVdpVideoBuffer", &info, 0); + } + return _gst_vdp_video_buffer_type; +} + + +GstVdpVideoBuffer * +gst_vdp_video_buffer_new (GstVdpDevice * device, VdpChromaType chroma_type, + gint width, gint height) +{ + GstVdpVideoBuffer *buffer; + VdpStatus status; + VdpVideoSurface surface; + + status = device->vdp_video_surface_create (device->device, chroma_type, width, + height, &surface); + if (status != VDP_STATUS_OK) { + GST_ERROR ("Couldn't create a VdpVideoSurface, error returned was: %s", + device->vdp_get_error_string (status)); + return NULL; + } + + buffer = + (GstVdpVideoBuffer *) gst_mini_object_new (GST_TYPE_VDPAU_VIDEO_BUFFER); + + buffer->device = g_object_ref (device); + buffer->surface = surface; + + return buffer; +} diff --git a/sys/vdpau/gstvdpvideobuffer.h b/sys/vdpau/gstvdpvideobuffer.h new file mode 100644 index 00000000..ab4fb154 --- /dev/null +++ b/sys/vdpau/gstvdpvideobuffer.h @@ -0,0 +1,55 @@ +/* + * GStreamer + * Copyright (C) 2009 Carl-Anton Ingmarsson + * + * 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_VDPAU_VIDEO_BUFFER_H_ +#define _GST_VDPAU_VIDEO_BUFFER_H_ + +#include +#include + +#include "gstvdpdevice.h" + +#include "gstvdpvideobuffer.h" + +typedef struct _GstVdpVideoBuffer GstVdpVideoBuffer; + +#define GST_TYPE_VDPAU_VIDEO_BUFFER (gst_vdp_video_buffer_get_type()) + +#define GST_IS_VDPAU_VIDEO_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_VDPAU_VIDEO_BUFFER)) +#define GST_VDPAU_VIDEO_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_VDPAU_VIDEO_BUFFER, GstVdpVideoBuffer)) + +struct _GstVdpVideoBuffer { + GstBuffer buffer; + + GstVdpDevice *device; + VdpVideoSurface surface; +}; + +GType gst_vdp_video_buffer_get_type (void); + +GstVdpVideoBuffer* gst_vdp_video_buffer_new (GstVdpDevice * device, VdpChromaType chroma_type, gint width, gint height); + +#define GST_VDPAU_VIDEO_CAPS \ + "video/vdpau-video, " \ + "chroma-type = (int)[0,2], " \ + "width = (int)[1,4096], " \ + "height = (int)[1,4096]" + +#endif diff --git a/sys/vdpau/gstvdpvideoyuv.c b/sys/vdpau/gstvdpvideoyuv.c new file mode 100644 index 00000000..917a4edc --- /dev/null +++ b/sys/vdpau/gstvdpvideoyuv.c @@ -0,0 +1,444 @@ +/* + * GStreamer + * Copyright (C) 2009 Carl-Anton Ingmarsson + * + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include "gstvdpvideobuffer.h" +#include "gstvdpvideoyuv.h" + +GST_DEBUG_CATEGORY_STATIC (gst_vdp_video_yuv_debug); +#define GST_CAT_DEFAULT gst_vdp_video_yuv_debug + +/* Filter signals and args */ +enum +{ + /* FILL ME */ + LAST_SIGNAL +}; + +enum +{ + PROP_0 +}; + +static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (GST_VDPAU_VIDEO_CAPS)); + +static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("video/x-raw-yuv, " + "framerate = (fraction) [ 0, MAX ], " + "width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]")); + +#define DEBUG_INIT(bla) \ + GST_DEBUG_CATEGORY_INIT (gst_vdp_video_yuv_debug, "vdpauvideoyuv", 0, "VDPAU VdpSurface to YUV"); + +GST_BOILERPLATE_FULL (GstVdpVideoYUV, gst_vdp_video_yuv, GstElement, + GST_TYPE_ELEMENT, DEBUG_INIT); + +static void gst_vdp_video_yuv_finalize (GObject * object); +static void gst_vdp_video_yuv_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_vdp_video_yuv_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +GstFlowReturn +gst_vdp_video_yuv_chain (GstPad * pad, GstBuffer * buffer) +{ + GstVdpVideoYUV *video_yuv; + GstVdpDevice *device; + VdpVideoSurface surface; + GstBuffer *outbuf = NULL; + + video_yuv = GST_VDPAU_VIDEO_YUV (GST_OBJECT_PARENT (pad)); + device = GST_VDPAU_VIDEO_BUFFER (buffer)->device; + surface = GST_VDPAU_VIDEO_BUFFER (buffer)->surface; + + switch (video_yuv->format) { + case GST_MAKE_FOURCC ('Y', 'V', '1', '2'): + { + gint size; + GstFlowReturn result; + VdpStatus status; + guint8 *data[3]; + guint32 stride[3]; + + size = + gst_video_format_get_size (GST_VIDEO_FORMAT_YV12, video_yuv->width, + video_yuv->height); + result = + gst_pad_alloc_buffer_and_set_caps (video_yuv->src, + GST_BUFFER_OFFSET_NONE, size, GST_PAD_CAPS (video_yuv->src), &outbuf); + if (G_UNLIKELY (result != GST_FLOW_OK)) + return result; + + data[0] = GST_BUFFER_DATA (outbuf) + + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_YV12, + 0, video_yuv->width, video_yuv->height); + data[1] = GST_BUFFER_DATA (outbuf) + + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_YV12, + 2, video_yuv->width, video_yuv->height); + data[2] = GST_BUFFER_DATA (outbuf) + + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_YV12, + 1, video_yuv->width, video_yuv->height); + + stride[0] = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_YV12, + 0, video_yuv->width); + stride[1] = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_YV12, + 2, video_yuv->width); + stride[2] = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_YV12, + 1, video_yuv->width); + + status = + device->vdp_video_surface_get_bits_ycbcr (surface, + VDP_YCBCR_FORMAT_YV12, (void *) data, stride); + if (G_UNLIKELY (status != VDP_STATUS_OK)) { + GST_ELEMENT_ERROR (video_yuv, RESOURCE, READ, + ("Couldn't get data from vdpau"), + ("Error returned from vdpau was: %s", + device->vdp_get_error_string (status))); + goto error; + } + break; + } + case GST_MAKE_FOURCC ('I', '4', '2', '0'): + { + gint size; + GstFlowReturn result; + VdpStatus status; + guint8 *data[3]; + guint32 stride[3]; + + size = + gst_video_format_get_size (GST_VIDEO_FORMAT_YV12, video_yuv->width, + video_yuv->height); + result = + gst_pad_alloc_buffer_and_set_caps (video_yuv->src, + GST_BUFFER_OFFSET_NONE, size, GST_PAD_CAPS (video_yuv->src), &outbuf); + if (G_UNLIKELY (result != GST_FLOW_OK)) + return result; + + data[0] = GST_BUFFER_DATA (outbuf) + + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_I420, + 0, video_yuv->width, video_yuv->height); + data[1] = GST_BUFFER_DATA (outbuf) + + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_I420, + 2, video_yuv->width, video_yuv->height); + data[2] = GST_BUFFER_DATA (outbuf) + + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_I420, + 1, video_yuv->width, video_yuv->height); + + stride[0] = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_I420, + 0, video_yuv->width); + stride[1] = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_I420, + 2, video_yuv->width); + stride[2] = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_I420, + 1, video_yuv->width); + + status = + device->vdp_video_surface_get_bits_ycbcr (surface, + VDP_YCBCR_FORMAT_YV12, (void *) data, stride); + if (G_UNLIKELY (status != VDP_STATUS_OK)) { + GST_ELEMENT_ERROR (video_yuv, RESOURCE, READ, + ("Couldn't get data from vdpau"), + ("Error returned from vdpau was: %s", + device->vdp_get_error_string (status))); + goto error; + } + break; + } + case GST_MAKE_FOURCC ('N', 'V', '1', '2'): + { + gint size; + GstFlowReturn result; + VdpStatus status; + guint8 *data[2]; + guint32 stride[2]; + + size = + video_yuv->width * video_yuv->height + + video_yuv->width * video_yuv->height / 2; + result = + gst_pad_alloc_buffer_and_set_caps (video_yuv->src, + GST_BUFFER_OFFSET_NONE, size, GST_PAD_CAPS (video_yuv->src), &outbuf); + if (G_UNLIKELY (result != GST_FLOW_OK)) + return result; + + + data[0] = GST_BUFFER_DATA (outbuf); + data[1] = GST_BUFFER_DATA (outbuf) + video_yuv->width * video_yuv->height; + + stride[0] = video_yuv->width; + stride[1] = video_yuv->width; + + status = + device->vdp_video_surface_get_bits_ycbcr (surface, + VDP_YCBCR_FORMAT_NV12, (void *) data, stride); + if (G_UNLIKELY (status != VDP_STATUS_OK)) { + GST_ELEMENT_ERROR (video_yuv, RESOURCE, READ, + ("Couldn't get data from vdpau"), + ("Error returned from vdpau was: %s", + device->vdp_get_error_string (status))); + goto error; + } + break; + } + default: + break; + } + + gst_buffer_unref (buffer); + + gst_buffer_copy_metadata (outbuf, buffer, GST_BUFFER_COPY_TIMESTAMPS); + return gst_pad_push (video_yuv->src, outbuf); + +error: + gst_buffer_unref (outbuf); + return GST_FLOW_ERROR; +} + +static GstCaps * +gst_vdp_video_yuv_get_caps (GstVdpVideoYUV * video_yuv, + GstVdpDevice * device, gint chroma_type, gint width, gint height, + gint framerate_numerator, gint framerate_denominator, gint par_numerator, + gint par_denominator) +{ + GstCaps *caps; + gint i; + + caps = gst_caps_new_empty (); + + for (i = 0; i < N_FORMATS; i++) { + VdpStatus status; + VdpBool is_supported; + + if (formats[i].chroma_type != chroma_type) + continue; + + status = + device->vdp_video_surface_query_ycbcr_capabilities (device->device, + chroma_type, formats[i].format, &is_supported); + if (status != VDP_STATUS_OK && status != VDP_STATUS_INVALID_Y_CB_CR_FORMAT) { + GST_ELEMENT_ERROR (video_yuv, RESOURCE, READ, + ("Could not query VDPAU YCbCr capabilites"), + ("Error returned from vdpau was: %s", + device->vdp_get_error_string (status))); + + return NULL; + } + if (is_supported) { + GstCaps *format_caps; + + format_caps = gst_caps_new_simple ("video/x-raw-yuv", + "format", GST_TYPE_FOURCC, formats[i].fourcc, + "width", G_TYPE_INT, width, + "height", G_TYPE_INT, height, + "framerate", GST_TYPE_FRACTION, framerate_numerator, + framerate_denominator, "pixel-aspect-ratio", GST_TYPE_FRACTION, + par_numerator, par_denominator, NULL); + gst_caps_append (caps, format_caps); + } + } + + if (gst_caps_is_empty (caps)) { + gst_caps_unref (caps); + return NULL; + } + + return caps; +} + +static gboolean +gst_vdp_video_yuv_sink_set_caps (GstPad * pad, GstCaps * caps) +{ + GstVdpVideoYUV *video_yuv = GST_VDPAU_VIDEO_YUV (GST_OBJECT_PARENT (pad)); + + GstCaps *src_caps, *new_caps; + GstStructure *structure; + const GValue *value; + GstVdpDevice *device; + gint chroma_type; + gint width, height; + gint framerate_numerator, framerate_denominator; + gint par_numerator, par_denominator; + guint32 fourcc_format; + gboolean res; + + structure = gst_caps_get_structure (caps, 0); + value = gst_structure_get_value (structure, "device"); + device = g_value_get_object (value); + + gst_structure_get_int (structure, "chroma-type", &chroma_type); + gst_structure_get_int (structure, "width", &width); + gst_structure_get_int (structure, "height", &height); + gst_structure_get_fraction (structure, "framerate", + &framerate_numerator, &framerate_denominator); + gst_structure_get_fraction (structure, "pixel-aspect-ratio", + &par_numerator, &par_denominator); + + src_caps = + gst_vdp_video_yuv_get_caps (video_yuv, device, chroma_type, width, + height, framerate_numerator, framerate_denominator, par_numerator, + par_denominator); + if (G_UNLIKELY (!src_caps)) + return FALSE; + + video_yuv->src_caps = src_caps; + + src_caps = gst_pad_get_allowed_caps (video_yuv->src); + if (G_UNLIKELY (!src_caps || !gst_caps_get_size (src_caps))) + return FALSE; + + new_caps = gst_caps_copy_nth (src_caps, 0); + gst_caps_unref (src_caps); + if (G_UNLIKELY (!new_caps)) + return FALSE; + + structure = gst_caps_get_structure (new_caps, 0); + gst_structure_get_fourcc (structure, "format", &fourcc_format); + + gst_pad_fixate_caps (video_yuv->src, new_caps); + res = gst_pad_set_caps (video_yuv->src, new_caps); + + gst_caps_unref (new_caps); + + if (G_UNLIKELY (!res)) + return FALSE; + + video_yuv->width = width; + video_yuv->height = height; + video_yuv->framerate_numerator = framerate_numerator; + video_yuv->framerate_denominator = framerate_denominator; + video_yuv->format = fourcc_format; + + return TRUE; +} + +static GstCaps * +gst_vdp_video_yuv_src_getcaps (GstPad * pad) +{ + GstVdpVideoYUV *video_yuv; + + video_yuv = GST_VDPAU_VIDEO_YUV (GST_OBJECT_PARENT (pad)); + + if (video_yuv->src_caps) + return gst_caps_copy (video_yuv->src_caps); + + if (GST_PAD_CAPS (video_yuv->src)) + return gst_caps_copy (GST_PAD_CAPS (video_yuv->src)); + + return gst_caps_copy (gst_pad_get_pad_template_caps (video_yuv->src)); +} + +/* GObject vmethod implementations */ + +static void +gst_vdp_video_yuv_base_init (gpointer klass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + + gst_element_class_set_details_simple (element_class, + "VdpauVideoYUV", + "Covideo_yuv/Decoder/Video", + "VDPAU video surface to YUV", + "Carl-Anton Ingmarsson "); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&sink_template)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&src_template)); +} + +static void +gst_vdp_video_yuv_class_init (GstVdpVideoYUVClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + + gobject_class = (GObjectClass *) klass; + gstelement_class = (GstElementClass *) klass; + + gobject_class->finalize = gst_vdp_video_yuv_finalize; + gobject_class->set_property = gst_vdp_video_yuv_set_property; + gobject_class->get_property = gst_vdp_video_yuv_get_property; +} + +static void +gst_vdp_video_yuv_init (GstVdpVideoYUV * video_yuv, GstVdpVideoYUVClass * klass) +{ + video_yuv->src_caps = NULL; + + video_yuv->height = 0; + video_yuv->width = 0; + video_yuv->framerate_numerator = 0; + video_yuv->framerate_denominator = 0; + video_yuv->par_numerator = 1; + video_yuv->par_denominator = 1; + + video_yuv->src = gst_pad_new_from_static_template (&src_template, "src"); + gst_pad_set_getcaps_function (video_yuv->src, gst_vdp_video_yuv_src_getcaps); + gst_element_add_pad (GST_ELEMENT (video_yuv), video_yuv->src); + + video_yuv->sink = gst_pad_new_from_static_template (&sink_template, "sink"); + gst_pad_set_setcaps_function (video_yuv->sink, + gst_vdp_video_yuv_sink_set_caps); + gst_pad_set_chain_function (video_yuv->sink, gst_vdp_video_yuv_chain); + gst_element_add_pad (GST_ELEMENT (video_yuv), video_yuv->sink); + gst_pad_set_active (video_yuv->sink, TRUE); +} + +static void +gst_vdp_video_yuv_finalize (GObject * object) +{ + GstVdpVideoYUV *video_yuv = (GstVdpVideoYUV *) object; + + if (video_yuv->src_caps) + gst_caps_unref (video_yuv->src_caps); +} + +static void +gst_vdp_video_yuv_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + switch (prop_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_vdp_video_yuv_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + switch (prop_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} diff --git a/sys/vdpau/gstvdpvideoyuv.h b/sys/vdpau/gstvdpvideoyuv.h new file mode 100644 index 00000000..f2aa4c82 --- /dev/null +++ b/sys/vdpau/gstvdpvideoyuv.h @@ -0,0 +1,60 @@ +/* + * GStreamer + * Copyright (C) 2009 Carl-Anton Ingmarsson + * + * 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_VDPAU_VIDEO_YUV_H__ +#define __GST_VDPAU_VIDEO_YUV_H__ + +#include + +#include "gstvdpdevice.h" + +G_BEGIN_DECLS + +#define GST_TYPE_VDPAU_VIDEO_YUV (gst_vdp_video_yuv_get_type()) +#define GST_VDPAU_VIDEO_YUV(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VDPAU_VIDEO_YUV,GstVdpVideoYUV)) +#define GST_VDPAU_VIDEO_YUV_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VDPAU_VIDEO_YUV,GstVdpVideoYUVClass)) +#define GST_VDPAU_VIDEO_YUV_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_VDPAU_VIDEO_YUV, GstVdpVideoYUVClass)) +#define GST_IS_VDPAU_VIDEO_YUV(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VDPAU_VIDEO_YUV)) +#define GST_IS_VDPAU_VIDEO_YUV_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VDPAU_VIDEO_YUV)) + +typedef struct _GstVdpVideoYUV GstVdpVideoYUV; +typedef struct _GstVdpVideoYUVClass GstVdpVideoYUVClass; + +struct _GstVdpVideoYUV { + GstElement element; + + GstPad *src, *sink; + GstCaps *src_caps; + + gint width, height; + gint framerate_numerator, framerate_denominator; + gint par_numerator, par_denominator; + guint format; +}; + +struct _GstVdpVideoYUVClass { + GstElementClass parent_class; +}; + +GType gst_vdp_video_yuv_get_type (void); + +G_END_DECLS + +#endif /* __GST_VDPAU_VIDEO_YUV_H__ */ diff --git a/sys/vdpau/gstvdpyuvvideo.c b/sys/vdpau/gstvdpyuvvideo.c new file mode 100644 index 00000000..d5ed01cb --- /dev/null +++ b/sys/vdpau/gstvdpyuvvideo.c @@ -0,0 +1,476 @@ +/* + * GStreamer + * Copyright (C) 2009 Carl-Anton Ingmarsson + * + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include "gstvdpvideobuffer.h" +#include "gstvdpyuvvideo.h" + +GST_DEBUG_CATEGORY_STATIC (gst_vdp_yuv_video_debug); +#define GST_CAT_DEFAULT gst_vdp_yuv_video_debug + +/* Filter signals and args */ +enum +{ + /* FILL ME */ + LAST_SIGNAL +}; + +enum +{ + PROP_0, + PROP_DISPLAY +}; + +static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("video/x-raw-yuv, " + "framerate = (fraction) [ 0, MAX ], " + "width = (int) [ 1, MAX ], " "height = (int) [ 1, MAX ]")); + +static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (GST_VDPAU_VIDEO_CAPS)); + +#define DEBUG_INIT(bla) \ + GST_DEBUG_CATEGORY_INIT (gst_vdp_yuv_video_debug, "vdpauvideoyuv", 0, "YUV to VDPAU video surface"); + +GST_BOILERPLATE_FULL (GstVdpYUVVideo, gst_vdp_yuv_video, GstElement, + GST_TYPE_ELEMENT, DEBUG_INIT); + +static void gst_vdp_yuv_video_finalize (GObject * object); +static void gst_vdp_yuv_video_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_vdp_yuv_video_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +GstFlowReturn +gst_vdp_yuv_video_chain (GstPad * pad, GstBuffer * buffer) +{ + GstVdpYUVVideo *yuv_video; + GstVdpDevice *device; + VdpVideoSurface surface; + GstBuffer *outbuf = NULL; + + yuv_video = GST_VDPAU_YUV_VIDEO (GST_OBJECT_PARENT (pad)); + device = yuv_video->device; + + outbuf = + GST_BUFFER (gst_vdp_video_buffer_new (device, yuv_video->chroma_type, + yuv_video->width, yuv_video->height)); + surface = GST_VDPAU_VIDEO_BUFFER (outbuf)->surface; + + switch (yuv_video->format) { + case GST_MAKE_FOURCC ('Y', 'V', '1', '2'): + { + VdpStatus status; + guint8 *data[3]; + guint32 stride[3]; + + data[0] = GST_BUFFER_DATA (buffer) + + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_YV12, + 0, yuv_video->width, yuv_video->height); + data[1] = GST_BUFFER_DATA (buffer) + + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_YV12, + 2, yuv_video->width, yuv_video->height); + data[2] = GST_BUFFER_DATA (buffer) + + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_YV12, + 1, yuv_video->width, yuv_video->height); + + stride[0] = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_YV12, + 0, yuv_video->width); + stride[1] = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_YV12, + 2, yuv_video->width); + stride[2] = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_YV12, + 1, yuv_video->width); + + status = + device->vdp_video_surface_put_bits_ycbcr (surface, + VDP_YCBCR_FORMAT_YV12, (void *) data, stride); + if (G_UNLIKELY (status != VDP_STATUS_OK)) { + GST_ELEMENT_ERROR (yuv_video, RESOURCE, READ, + ("Couldn't push YV12 data to VDPAU"), + ("Error returned from vdpau was: %s", + device->vdp_get_error_string (status))); + goto error; + } + break; + } + case GST_MAKE_FOURCC ('I', '4', '2', '0'): + { + VdpStatus status; + guint8 *data[3]; + guint32 stride[3]; + + data[0] = GST_BUFFER_DATA (buffer) + + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_I420, + 0, yuv_video->width, yuv_video->height); + data[1] = GST_BUFFER_DATA (buffer) + + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_I420, + 2, yuv_video->width, yuv_video->height); + data[2] = GST_BUFFER_DATA (buffer) + + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_I420, + 1, yuv_video->width, yuv_video->height); + + stride[0] = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_I420, + 0, yuv_video->width); + stride[1] = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_I420, + 2, yuv_video->width); + stride[2] = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_I420, + 1, yuv_video->width); + + status = + device->vdp_video_surface_put_bits_ycbcr (surface, + VDP_YCBCR_FORMAT_YV12, (void *) data, stride); + if (G_UNLIKELY (status != VDP_STATUS_OK)) { + GST_ELEMENT_ERROR (yuv_video, RESOURCE, READ, + ("Couldn't push YV12 data to VDPAU"), + ("Error returned from vdpau was: %s", + device->vdp_get_error_string (status))); + goto error; + } + break; + } + case GST_MAKE_FOURCC ('N', 'V', '1', '2'): + { + VdpStatus status; + guint8 *data[2]; + guint32 stride[2]; + + data[0] = GST_BUFFER_DATA (buffer); + data[1] = GST_BUFFER_DATA (buffer) + yuv_video->width * yuv_video->height; + + stride[0] = yuv_video->width; + stride[1] = yuv_video->width; + + status = + device->vdp_video_surface_put_bits_ycbcr (surface, + VDP_YCBCR_FORMAT_NV12, (void *) data, stride); + if (G_UNLIKELY (status != VDP_STATUS_OK)) { + GST_ELEMENT_ERROR (yuv_video, RESOURCE, READ, + ("Couldn't get data from vdpau"), + ("Error returned from vdpau was: %s", + device->vdp_get_error_string (status))); + goto error; + } + break; + } + default: + break; + } + + gst_buffer_unref (buffer); + + gst_buffer_copy_metadata (outbuf, buffer, GST_BUFFER_COPY_TIMESTAMPS); + gst_buffer_set_caps (outbuf, GST_PAD_CAPS (yuv_video->src)); + + return gst_pad_push (yuv_video->src, outbuf); + +error: + gst_buffer_unref (outbuf); + return GST_FLOW_ERROR; +} + +static GstCaps * +gst_vdp_yuv_video_get_caps (GstVdpYUVVideo * yuv_video) +{ + GstVdpDevice *device; + GstCaps *caps; + gint i; + + device = yuv_video->device; + + caps = gst_caps_new_empty (); + + for (i = 0; i < N_CHROMA_TYPES; i++) { + VdpStatus status; + VdpBool is_supported; + guint32 max_w, max_h; + + status = + device->vdp_video_surface_query_capabilities (device->device, + chroma_types[i], &is_supported, &max_w, &max_h); + + if (status != VDP_STATUS_OK && status != VDP_STATUS_INVALID_CHROMA_TYPE) { + GST_ELEMENT_ERROR (yuv_video, RESOURCE, READ, + ("Could not get query VDPAU video surface capabilites"), + ("Error returned from vdpau was: %s", + device->vdp_get_error_string (status))); + + goto error; + } + if (is_supported) { + gint j; + + for (j = 0; j < N_FORMATS; j++) { + if (formats[j].chroma_type != chroma_types[i]) + continue; + + status = + device->vdp_video_surface_query_ycbcr_capabilities (device->device, + formats[j].chroma_type, formats[j].format, &is_supported); + if (status != VDP_STATUS_OK + && status != VDP_STATUS_INVALID_Y_CB_CR_FORMAT) { + GST_ELEMENT_ERROR (yuv_video, RESOURCE, READ, + ("Could not query VDPAU YCbCr capabilites"), + ("Error returned from vdpau was: %s", + device->vdp_get_error_string (status))); + + goto error; + } + if (is_supported) { + GstCaps *format_caps; + + format_caps = gst_caps_new_simple ("video/x-raw-yuv", + "format", GST_TYPE_FOURCC, formats[j].fourcc, + "width", GST_TYPE_INT_RANGE, 1, max_w, + "height", GST_TYPE_INT_RANGE, 1, max_h, + "framerate", GST_TYPE_FRACTION_RANGE, 0, 1, G_MAXINT, 1, NULL); + gst_caps_append (caps, format_caps); + } + } + } + } +error: + if (gst_caps_is_empty (caps)) { + gst_caps_unref (caps); + return NULL; + } + + return caps; +} + +static gboolean +gst_vdp_yuv_video_sink_setcaps (GstPad * pad, GstCaps * caps) +{ + GstVdpYUVVideo *yuv_video = GST_VDPAU_YUV_VIDEO (GST_OBJECT_PARENT (pad)); + + GstStructure *structure; + guint32 fourcc; + gint chroma_type = 0; + gint width, height; + gint framerate_numerator, framerate_denominator; + gint par_numerator, par_denominator; + gint i; + GstCaps *src_caps, *new_caps; + gboolean res; + + structure = gst_caps_get_structure (caps, 0); + + gst_structure_get_fourcc (structure, "format", &fourcc); + gst_structure_get_int (structure, "width", &width); + gst_structure_get_int (structure, "height", &height); + gst_structure_get_fraction (structure, "framerate", + &framerate_numerator, &framerate_denominator); + gst_structure_get_fraction (structure, "pixel-aspect-ratio", + &par_numerator, &par_denominator); + + for (i = 0; i < N_FORMATS; i++) { + if (formats[i].fourcc == fourcc) { + chroma_type = formats[i].chroma_type; + break; + } + } + + src_caps = gst_pad_get_allowed_caps (yuv_video->src); + if (G_UNLIKELY (!src_caps || !gst_caps_get_size (src_caps))) + return FALSE; + + new_caps = gst_caps_copy_nth (src_caps, 0); + gst_caps_unref (src_caps); + if (G_UNLIKELY (!new_caps)) + return FALSE; + + structure = gst_caps_get_structure (new_caps, 0); + + gst_structure_set (structure, + "device", G_TYPE_OBJECT, yuv_video->device, + "chroma-type", G_TYPE_INT, chroma_type, + "width", G_TYPE_INT, width, + "height", G_TYPE_INT, height, + "framerate", GST_TYPE_FRACTION, framerate_numerator, + framerate_denominator, "pixel-aspect-ratio", GST_TYPE_FRACTION, + par_numerator, par_denominator, NULL); + + gst_pad_fixate_caps (yuv_video->src, new_caps); + res = gst_pad_set_caps (yuv_video->src, new_caps); + + gst_caps_unref (new_caps); + + if (G_UNLIKELY (!res)) + return FALSE; + + yuv_video->width = width; + yuv_video->height = height; + yuv_video->format = fourcc; + yuv_video->chroma_type = chroma_type; + + return TRUE; +} + +static GstCaps * +gst_vdp_yuv_video_sink_getcaps (GstPad * pad) +{ + GstVdpYUVVideo *yuv_video; + + yuv_video = GST_VDPAU_YUV_VIDEO (GST_OBJECT_PARENT (pad)); + + if (yuv_video->sink_caps) + return gst_caps_copy (yuv_video->sink_caps); + + return gst_caps_copy (gst_pad_get_pad_template_caps (yuv_video->sink)); +} + +static GstStateChangeReturn +gst_vdp_yuv_video_change_state (GstElement * element, GstStateChange transition) +{ + GstVdpYUVVideo *yuv_video; + + yuv_video = GST_VDPAU_YUV_VIDEO (element); + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + yuv_video->device = gst_vdp_get_device (yuv_video->display); + if (!yuv_video->sink_caps) + yuv_video->sink_caps = gst_vdp_yuv_video_get_caps (yuv_video); + break; + case GST_STATE_CHANGE_READY_TO_NULL: + g_object_unref (yuv_video->device); + yuv_video->device = NULL; + break; + default: + break; + } + + return GST_STATE_CHANGE_SUCCESS; +} + +/* GObject vmethod implementations */ + +static void +gst_vdp_yuv_video_base_init (gpointer klass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + + gst_element_class_set_details_simple (element_class, + "VdpauYUVVideo", + "Coyuv_video/Decoder/Video", + "VDPAU video surface to YUV", + "Carl-Anton Ingmarsson "); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&sink_template)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&src_template)); +} + +static void +gst_vdp_yuv_video_class_init (GstVdpYUVVideoClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + + gobject_class = (GObjectClass *) klass; + gstelement_class = (GstElementClass *) klass; + + gobject_class->finalize = gst_vdp_yuv_video_finalize; + gobject_class->set_property = gst_vdp_yuv_video_set_property; + gobject_class->get_property = gst_vdp_yuv_video_get_property; + + g_object_class_install_property (gobject_class, PROP_DISPLAY, + g_param_spec_string ("display", "Display", "X Display name", + NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + + gstelement_class->change_state = gst_vdp_yuv_video_change_state; +} + +static void +gst_vdp_yuv_video_init (GstVdpYUVVideo * yuv_video, GstVdpYUVVideoClass * klass) +{ + yuv_video->sink_caps = NULL; + + yuv_video->display = NULL; + yuv_video->device = NULL; + + yuv_video->height = 0; + yuv_video->width = 0; + yuv_video->format = 0; + yuv_video->chroma_type = 0; + + yuv_video->src = gst_pad_new_from_static_template (&src_template, "src"); + gst_element_add_pad (GST_ELEMENT (yuv_video), yuv_video->src); + + yuv_video->sink = gst_pad_new_from_static_template (&sink_template, "sink"); + gst_pad_set_getcaps_function (yuv_video->sink, + gst_vdp_yuv_video_sink_getcaps); + gst_pad_set_setcaps_function (yuv_video->sink, + gst_vdp_yuv_video_sink_setcaps); + gst_pad_set_chain_function (yuv_video->sink, gst_vdp_yuv_video_chain); + gst_element_add_pad (GST_ELEMENT (yuv_video), yuv_video->sink); + gst_pad_set_active (yuv_video->sink, TRUE); +} + +static void +gst_vdp_yuv_video_finalize (GObject * object) +{ + GstVdpYUVVideo *yuv_video = (GstVdpYUVVideo *) object; + + g_free (yuv_video->display); +} + +static void +gst_vdp_yuv_video_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstVdpYUVVideo *yuv_video = GST_VDPAU_YUV_VIDEO (object); + + switch (prop_id) { + case PROP_DISPLAY: + g_free (yuv_video->display); + yuv_video->display = g_value_dup_string (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_vdp_yuv_video_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstVdpYUVVideo *yuv_video = GST_VDPAU_YUV_VIDEO (object); + + switch (prop_id) { + case PROP_DISPLAY: + g_value_set_string (value, yuv_video->display); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} diff --git a/sys/vdpau/gstvdpyuvvideo.h b/sys/vdpau/gstvdpyuvvideo.h new file mode 100644 index 00000000..fbb7d96d --- /dev/null +++ b/sys/vdpau/gstvdpyuvvideo.h @@ -0,0 +1,62 @@ +/* + * GStreamer + * Copyright (C) 2009 Carl-Anton Ingmarsson + * + * 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_VDPAU_YUV_VIDEO_H__ +#define __GST_VDPAU_YUV_VIDEO_H__ + +#include + +#include "gstvdpdevice.h" + +G_BEGIN_DECLS + +#define GST_TYPE_VDPAU_YUV_VIDEO (gst_vdp_yuv_video_get_type()) +#define GST_VDPAU_YUV_VIDEO(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VDPAU_YUV_VIDEO,GstVdpYUVVideo)) +#define GST_VDPAU_YUV_VIDEO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VDPAU_YUV_VIDEO,GstVdpYUVVideoClass)) +#define GST_VDPAU_YUV_VIDEO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_VDPAU_YUV_VIDEO, GstVdpYUVVideoClass)) +#define GST_IS_VDPAU_YUV_VIDEO(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VDPAU_YUV_VIDEO)) +#define GST_IS_VDPAU_YUV_VIDEO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VDPAU_YUV_VIDEO)) + +typedef struct _GstVdpYUVVideo GstVdpYUVVideo; +typedef struct _GstVdpYUVVideoClass GstVdpYUVVideoClass; + +struct _GstVdpYUVVideo { + GstElement element; + + GstPad *src, *sink; + GstCaps *sink_caps; + + gchar *display; + GstVdpDevice *device; + + guint32 format; + gint chroma_type; + gint width, height; +}; + +struct _GstVdpYUVVideoClass { + GstElementClass parent_class; +}; + +GType gst_vdp_yuv_video_get_type (void); + +G_END_DECLS + +#endif /* __GST_VDPAU_YUV_VIDEO_H__ */ -- cgit v1.2.1 From 1af393a72d675ac59f06c5751fe60ce170f9e545 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Mon, 13 Apr 2009 22:21:03 +0200 Subject: vdpau: small cosmetical fix --- sys/vdpau/gstvdp.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sys/vdpau/gstvdp.c b/sys/vdpau/gstvdp.c index 2da9bdb0..9ca0114e 100644 --- a/sys/vdpau/gstvdp.c +++ b/sys/vdpau/gstvdp.c @@ -10,13 +10,13 @@ #include "gstvdpyuvvideo.h" static gboolean -vdpau_init (GstPlugin * vdpaumpegdecoder) +vdpau_init (GstPlugin * vdpau_plugin) { - gst_element_register (vdpaumpegdecoder, "vdpaumpegdecoder", + gst_element_register (vdpau_plugin, "vdpaumpegdecoder", GST_RANK_NONE, GST_TYPE_VDPAU_MPEG_DECODER); - gst_element_register (vdpaumpegdecoder, "vdpauvideoyuv", + gst_element_register (vdpau_plugin, "vdpauvideoyuv", GST_RANK_NONE, GST_TYPE_VDPAU_VIDEO_YUV); - gst_element_register (vdpaumpegdecoder, "vdpauyuvvideo", + gst_element_register (vdpau_plugin, "vdpauyuvvideo", GST_RANK_NONE, GST_TYPE_VDPAU_YUV_VIDEO); return TRUE; -- cgit v1.2.1 From 71c398566cf9f434d9a8fd7b98224c0e1f963910 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Tue, 14 Apr 2009 19:08:53 +0200 Subject: vdpaumpegdecoder: remove unnecesary want_slice field --- sys/vdpau/gstvdpmpegdecoder.c | 23 +++++++---------------- sys/vdpau/gstvdpmpegdecoder.h | 2 -- 2 files changed, 7 insertions(+), 18 deletions(-) diff --git a/sys/vdpau/gstvdpmpegdecoder.c b/sys/vdpau/gstvdpmpegdecoder.c index df8a5b67..350414a7 100644 --- a/sys/vdpau/gstvdpmpegdecoder.c +++ b/sys/vdpau/gstvdpmpegdecoder.c @@ -217,8 +217,6 @@ gst_vdp_mpeg_decoder_parse_picture_coding (GstVdpMpegDecoder * mpeg_dec, info->q_scale_type = pic_ext.q_scale_type; info->intra_vlc_format = pic_ext.intra_vlc_format; - mpeg_dec->want_slice = TRUE; - return TRUE; } @@ -269,10 +267,7 @@ gst_vdp_mpeg_decoder_parse_picture (GstVdpMpegDecoder * mpeg_dec, mpeg_dec->vdp_info.full_pel_backward_vector = pic_hdr.full_pel_backward_vector; memcpy (&mpeg_dec->vdp_info.f_code, &pic_hdr.f_code, 4); - - mpeg_dec->want_slice = TRUE; - } else - mpeg_dec->want_slice = FALSE; + } return TRUE; } @@ -332,19 +327,17 @@ gst_vdp_mpeg_decoder_chain (GstPad * pad, GstBuffer * buffer) GstBuffer *subbuf; GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_SLICE"); - if (mpeg_dec->want_slice) { - subbuf = - gst_buffer_create_sub (buffer, - packet_start - GST_BUFFER_DATA (buffer), packet_end - packet_start); - gst_adapter_push (mpeg_dec->adapter, subbuf); - mpeg_dec->vdp_info.slice_count++; - } + subbuf = + gst_buffer_create_sub (buffer, + packet_start - GST_BUFFER_DATA (buffer), packet_end - packet_start); + gst_adapter_push (mpeg_dec->adapter, subbuf); + mpeg_dec->vdp_info.slice_count++; } switch (data[0]) { case MPEG_PACKET_PICTURE: GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_PICTURE"); - if (mpeg_dec->vdp_info.slice_count > 0 && mpeg_dec->want_slice) { + if (mpeg_dec->vdp_info.slice_count > 0) { if (gst_vdp_mpeg_decoder_decode (mpeg_dec) != GST_FLOW_OK) return GST_FLOW_ERROR; } @@ -445,8 +438,6 @@ gst_vdp_mpeg_decoder_init (GstVdpMpegDecoder * mpeg_dec, mpeg_dec->adapter = gst_adapter_new (); - mpeg_dec->want_slice = FALSE; - gst_pad_set_chain_function (dec->sink, gst_vdp_mpeg_decoder_chain); } diff --git a/sys/vdpau/gstvdpmpegdecoder.h b/sys/vdpau/gstvdpmpegdecoder.h index dc90764b..b8f01bdf 100644 --- a/sys/vdpau/gstvdpmpegdecoder.h +++ b/sys/vdpau/gstvdpmpegdecoder.h @@ -46,8 +46,6 @@ struct _GstVdpMpegDecoder VdpDecoder decoder; VdpPictureInfoMPEG1Or2 vdp_info; GstBuffer *f_buffer; - - gboolean want_slice; GstAdapter *adapter; gint slices; -- cgit v1.2.1 From 4470b61f8064758a2998d8b513304e0854170321 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Tue, 14 Apr 2009 21:04:59 +0200 Subject: vdpaumpegdecoder: rename to "vdpaumpegdec" --- sys/vdpau/gstvdp.c | 2 +- sys/vdpau/gstvdpmpegdecoder.c | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/sys/vdpau/gstvdp.c b/sys/vdpau/gstvdp.c index 9ca0114e..b18c8a02 100644 --- a/sys/vdpau/gstvdp.c +++ b/sys/vdpau/gstvdp.c @@ -12,7 +12,7 @@ static gboolean vdpau_init (GstPlugin * vdpau_plugin) { - gst_element_register (vdpau_plugin, "vdpaumpegdecoder", + gst_element_register (vdpau_plugin, "vdpaumpegdec", GST_RANK_NONE, GST_TYPE_VDPAU_MPEG_DECODER); gst_element_register (vdpau_plugin, "vdpauvideoyuv", GST_RANK_NONE, GST_TYPE_VDPAU_VIDEO_YUV); diff --git a/sys/vdpau/gstvdpmpegdecoder.c b/sys/vdpau/gstvdpmpegdecoder.c index 350414a7..e1f9e56c 100644 --- a/sys/vdpau/gstvdpmpegdecoder.c +++ b/sys/vdpau/gstvdpmpegdecoder.c @@ -19,14 +19,14 @@ */ /** - * SECTION:element-vdpaumpegdecoder + * SECTION:element-vdpaumpegdec * - * FIXME:Describe vdpaumpegdecoder here. + * FIXME:Describe vdpaumpegdec here. * * * Example launch line * |[ - * gst-launch -v -m fakesrc ! vdpaumpegdecoder ! fakesink silent=TRUE + * gst-launch -v -m fakesrc ! vdpaumpegdec ! fakesink silent=TRUE * ]| * */ @@ -68,7 +68,7 @@ static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink", ); #define DEBUG_INIT(bla) \ -GST_DEBUG_CATEGORY_INIT (gst_vdp_mpeg_decoder_debug, "vdpaumpegdecoder", 0, "VDPAU powered mpeg decoder"); +GST_DEBUG_CATEGORY_INIT (gst_vdp_mpeg_decoder_debug, "vdpaumpegdec", 0, "VDPAU powered mpeg decoder"); GST_BOILERPLATE_FULL (GstVdpMpegDecoder, gst_vdp_mpeg_decoder, GstVdpDecoder, GST_TYPE_VDPAU_DECODER, DEBUG_INIT); @@ -384,7 +384,7 @@ gst_vdp_mpeg_decoder_base_init (gpointer gclass) GstElementClass *element_class = GST_ELEMENT_CLASS (gclass); gst_element_class_set_details_simple (element_class, - "VdpauMpegDecoder", + "VDPAU Mpeg Decoder", "Decoder", "decode mpeg stream with vdpau", "Carl-Anton Ingmarsson "); -- cgit v1.2.1 From 500861d5171e3c0811a9c8bdf1b9b5631a77f7fe Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Tue, 14 Apr 2009 21:05:44 +0200 Subject: vdpau: don't set element details in GstVdpDecoder --- sys/vdpau/gstvdpdecoder.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/sys/vdpau/gstvdpdecoder.c b/sys/vdpau/gstvdpdecoder.c index 2e92381f..ba1ca7c0 100644 --- a/sys/vdpau/gstvdpdecoder.c +++ b/sys/vdpau/gstvdpdecoder.c @@ -165,12 +165,6 @@ gst_vdp_decoder_base_init (gpointer klass) { GstElementClass *element_class = GST_ELEMENT_CLASS (klass); - gst_element_class_set_details_simple (element_class, - "VdpauDecoder", - "Codec/Decoder/Video", - "VDPAU decoder base class", - "Carl-Anton Ingmarsson "); - gst_element_class_add_pad_template (element_class, gst_static_pad_template_get (&src_template)); } -- cgit v1.2.1 From 4ee4429c1ac2a1927ee71a19427a7cc9498f8cab Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Tue, 14 Apr 2009 21:07:32 +0200 Subject: vdpau: remove "silent" property from GstVdpDecoder --- sys/vdpau/gstvdpdecoder.c | 14 +------------- sys/vdpau/gstvdpdecoder.h | 2 -- 2 files changed, 1 insertion(+), 15 deletions(-) diff --git a/sys/vdpau/gstvdpdecoder.c b/sys/vdpau/gstvdpdecoder.c index ba1ca7c0..fc8beb1f 100644 --- a/sys/vdpau/gstvdpdecoder.c +++ b/sys/vdpau/gstvdpdecoder.c @@ -40,8 +40,7 @@ enum enum { PROP_0, - PROP_DISPLAY, - PROP_SILENT + PROP_DISPLAY }; static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src", @@ -187,10 +186,6 @@ gst_vdp_decoder_class_init (GstVdpDecoderClass * klass) g_param_spec_string ("display", "Display", "X Display name", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - g_object_class_install_property (gobject_class, PROP_SILENT, - g_param_spec_boolean ("silent", "Silent", "Produce verbose output ?", - FALSE, G_PARAM_READWRITE | GST_PARAM_CONTROLLABLE)); - gstelement_class->change_state = gst_vdp_decoder_change_state; } @@ -199,7 +194,6 @@ gst_vdp_decoder_init (GstVdpDecoder * dec, GstVdpDecoderClass * klass) { dec->display_name = NULL; dec->device = NULL; - dec->silent = FALSE; dec->height = 0; dec->width = 0; @@ -240,9 +234,6 @@ gst_vdp_decoder_set_property (GObject * object, guint prop_id, g_free (dec->display_name); dec->display_name = g_value_dup_string (value); break; - case PROP_SILENT: - dec->silent = g_value_get_boolean (value); - break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -259,9 +250,6 @@ gst_vdp_decoder_get_property (GObject * object, guint prop_id, case PROP_DISPLAY: g_value_set_string (value, dec->display_name); break; - case PROP_SILENT: - g_value_set_boolean (value, dec->silent); - break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; diff --git a/sys/vdpau/gstvdpdecoder.h b/sys/vdpau/gstvdpdecoder.h index f918225e..8dc4ad66 100644 --- a/sys/vdpau/gstvdpdecoder.h +++ b/sys/vdpau/gstvdpdecoder.h @@ -53,8 +53,6 @@ struct _GstVdpDecoder { guint32 format; gint frame_nr; - - gboolean silent; }; struct _GstVdpDecoderClass { -- cgit v1.2.1 From 08690f10f81b3a699c4d98a139b46b1fef1971a6 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Tue, 14 Apr 2009 23:47:40 +0200 Subject: vdpau: rename "video/vdpau-video" caps to "video/x-vdpau-video" --- sys/vdpau/gstvdpdecoder.c | 2 +- sys/vdpau/gstvdpvideobuffer.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/vdpau/gstvdpdecoder.c b/sys/vdpau/gstvdpdecoder.c index fc8beb1f..dafcec98 100644 --- a/sys/vdpau/gstvdpdecoder.c +++ b/sys/vdpau/gstvdpdecoder.c @@ -46,7 +46,7 @@ enum static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, - GST_STATIC_CAPS ("video/vdpau-video, " "chroma-type = (int) 0")); + GST_STATIC_CAPS ("video/x-vdpau-video, " "chroma-type = (int) 0")); #define DEBUG_INIT(bla) \ GST_DEBUG_CATEGORY_INIT (gst_vdp_decoder_debug, "vdpaudecoder", 0, "vdpaudecoder base class"); diff --git a/sys/vdpau/gstvdpvideobuffer.h b/sys/vdpau/gstvdpvideobuffer.h index ab4fb154..bbfc7af0 100644 --- a/sys/vdpau/gstvdpvideobuffer.h +++ b/sys/vdpau/gstvdpvideobuffer.h @@ -47,7 +47,7 @@ GType gst_vdp_video_buffer_get_type (void); GstVdpVideoBuffer* gst_vdp_video_buffer_new (GstVdpDevice * device, VdpChromaType chroma_type, gint width, gint height); #define GST_VDPAU_VIDEO_CAPS \ - "video/vdpau-video, " \ + "video/x-vdpau-video, " \ "chroma-type = (int)[0,2], " \ "width = (int)[1,4096], " \ "height = (int)[1,4096]" -- cgit v1.2.1 From 638a35eaccf3115644d3581e3877111c8f8f255e Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Wed, 15 Apr 2009 17:52:27 +0200 Subject: vdpaumpegdecoder: remove unused slice field --- sys/vdpau/gstvdpmpegdecoder.h | 1 - 1 file changed, 1 deletion(-) diff --git a/sys/vdpau/gstvdpmpegdecoder.h b/sys/vdpau/gstvdpmpegdecoder.h index b8f01bdf..3ec8244d 100644 --- a/sys/vdpau/gstvdpmpegdecoder.h +++ b/sys/vdpau/gstvdpmpegdecoder.h @@ -48,7 +48,6 @@ struct _GstVdpMpegDecoder GstBuffer *f_buffer; GstAdapter *adapter; - gint slices; }; struct _GstVdpMpegDecoderClass -- cgit v1.2.1 From ee591b9f3d01865389a7a5dc4b8381466d0096e0 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Wed, 15 Apr 2009 18:17:54 +0200 Subject: vdpaumpegdec: correct some default values mpeg1 now give nearly correct output :) --- sys/vdpau/gstvdpmpegdecoder.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/sys/vdpau/gstvdpmpegdecoder.c b/sys/vdpau/gstvdpmpegdecoder.c index e1f9e56c..7aefe73c 100644 --- a/sys/vdpau/gstvdpmpegdecoder.c +++ b/sys/vdpau/gstvdpmpegdecoder.c @@ -418,11 +418,15 @@ gst_vdp_mpeg_decoder_init_info (VdpPictureInfoMPEG1Or2 * vdp_info) vdp_info->forward_reference = VDP_INVALID_HANDLE; vdp_info->backward_reference = VDP_INVALID_HANDLE; vdp_info->slice_count = 0; - vdp_info->picture_structure = 0; + vdp_info->picture_structure = 3; vdp_info->picture_coding_type = 0; vdp_info->intra_dc_precision = 0; - vdp_info->frame_pred_frame_dct = 0; + vdp_info->frame_pred_frame_dct = 1; vdp_info->concealment_motion_vectors = 0; + vdp_info->intra_vlc_format = 0; + vdp_info->alternate_scan = 0; + vdp_info->q_scale_type = 0; + vdp_info->top_field_first = 1; } static void -- cgit v1.2.1 From 375935d9c419b90d6b82686c5ddd9be7b5637382 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Wed, 15 Apr 2009 23:31:33 +0200 Subject: vdpaumpegdec: fixup quantmatrix extension parsing --- sys/vdpau/gstvdpmpegdecoder.c | 10 +++++----- sys/vdpau/mpegutil.c | 15 +++++++-------- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/sys/vdpau/gstvdpmpegdecoder.c b/sys/vdpau/gstvdpmpegdecoder.c index 7aefe73c..be432281 100644 --- a/sys/vdpau/gstvdpmpegdecoder.c +++ b/sys/vdpau/gstvdpmpegdecoder.c @@ -355,15 +355,15 @@ gst_vdp_mpeg_decoder_chain (GstPad * pad, GstBuffer * buffer) gst_vdp_mpeg_decoder_parse_picture_coding (mpeg_dec, packet_start, packet_end); break; + case MPEG_PACKET_EXT_QUANT_MATRIX: + GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_EXT_QUANT_MATRIX"); + gst_vdp_mpeg_decoder_parse_quant_matrix (mpeg_dec, packet_start, + packet_end); + break; default: break; } break; - case MPEG_PACKET_EXT_QUANT_MATRIX: - GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_EXT_QUANT_MATRIX"); - gst_vdp_mpeg_decoder_parse_quant_matrix (mpeg_dec, packet_start, - packet_end); - break; case MPEG_PACKET_GOP: GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_GOP"); gst_vdp_mpeg_decoder_parse_gop (mpeg_dec, packet_start, packet_end); diff --git a/sys/vdpau/mpegutil.c b/sys/vdpau/mpegutil.c index 3a4a63de..7ef46fb2 100644 --- a/sys/vdpau/mpegutil.c +++ b/sys/vdpau/mpegutil.c @@ -385,31 +385,30 @@ mpeg_util_parse_quant_matrix (MPEGQuantMatrix * qm, guint8 * data, guint8 * end) code = GST_READ_UINT32_BE (data); - if (G_UNLIKELY (G_UNLIKELY (code != (0x00000100 | MPEG_PACKET_GOP)))) + if (G_UNLIKELY (G_UNLIKELY (code != (0x00000100 | MPEG_PACKET_EXTENSION)))) return FALSE; /* Skip the sync word */ data += 4; - load_intra_flag = read_bits (data, 0, 1); + load_intra_flag = read_bits (data, 4, 1); if (load_intra_flag) { if (G_UNLIKELY ((end - data) < 64)) return FALSE; - for (i = 0; i < 64; i++) { - qm->intra_quantizer_matrix[mpeg2_scan[i]] = read_bits (data + i, 1, 8); - } - data += 64; + for (i = 0; i < 64; i++) + qm->intra_quantizer_matrix[mpeg2_scan[i]] = read_bits (data + i, 5, 8); + data += 64; } else memcpy (qm->intra_quantizer_matrix, default_intra_quantizer_matrix, 64); - load_non_intra_flag = read_bits (data, 1 + load_intra_flag, 1); + load_non_intra_flag = read_bits (data, 5 + load_intra_flag, 1); if (load_non_intra_flag) { if (G_UNLIKELY ((end - data) < 64)) return FALSE; for (i = 0; i < 64; i++) qm->non_intra_quantizer_matrix[mpeg2_scan[i]] = - read_bits (data + i, 2 + load_intra_flag, 8); + read_bits (data + i, 6 + load_intra_flag, 8); } else memset (qm->non_intra_quantizer_matrix, 16, 64); -- cgit v1.2.1 From 000db36020bd6d31160bd0eb38ad27bb9687400a Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Wed, 15 Apr 2009 23:38:53 +0200 Subject: vdpaumpegdec: parse PICTURE_CODING_EXTENSION alternate_scan bit --- sys/vdpau/gstvdpmpegdecoder.c | 1 + sys/vdpau/mpegutil.c | 1 + sys/vdpau/mpegutil.h | 1 + 3 files changed, 3 insertions(+) diff --git a/sys/vdpau/gstvdpmpegdecoder.c b/sys/vdpau/gstvdpmpegdecoder.c index be432281..053cf1c0 100644 --- a/sys/vdpau/gstvdpmpegdecoder.c +++ b/sys/vdpau/gstvdpmpegdecoder.c @@ -216,6 +216,7 @@ gst_vdp_mpeg_decoder_parse_picture_coding (GstVdpMpegDecoder * mpeg_dec, info->concealment_motion_vectors = pic_ext.concealment_motion_vectors; info->q_scale_type = pic_ext.q_scale_type; info->intra_vlc_format = pic_ext.intra_vlc_format; + info->alternate_scan = pic_ext.alternate_scan; return TRUE; } diff --git a/sys/vdpau/mpegutil.c b/sys/vdpau/mpegutil.c index 7ef46fb2..929df4ab 100644 --- a/sys/vdpau/mpegutil.c +++ b/sys/vdpau/mpegutil.c @@ -337,6 +337,7 @@ mpeg_util_parse_picture_coding_extension (MPEGPictureExt * ext, guint8 * data, ext->concealment_motion_vectors = read_bits (data + 3, 2, 1); ext->q_scale_type = read_bits (data + 3, 3, 1); ext->intra_vlc_format = read_bits (data + 3, 4, 1); + ext->alternate_scan = read_bits (data + 3, 5, 1); return TRUE; } diff --git a/sys/vdpau/mpegutil.h b/sys/vdpau/mpegutil.h index 5fb47290..24a29a35 100644 --- a/sys/vdpau/mpegutil.h +++ b/sys/vdpau/mpegutil.h @@ -90,6 +90,7 @@ struct MPEGPictureExt guint8 concealment_motion_vectors; guint8 q_scale_type; guint8 intra_vlc_format; + guint8 alternate_scan; }; struct MPEGPictureGOP -- cgit v1.2.1 From 7ca750c4229e1535deb3817687deefce9d4f9b42 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Wed, 15 Apr 2009 23:49:07 +0200 Subject: vdpaumpegdec: fixup GstFlowReturn propagation a bit --- sys/vdpau/gstvdpmpegdecoder.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sys/vdpau/gstvdpmpegdecoder.c b/sys/vdpau/gstvdpmpegdecoder.c index 053cf1c0..9b4aa99d 100644 --- a/sys/vdpau/gstvdpmpegdecoder.c +++ b/sys/vdpau/gstvdpmpegdecoder.c @@ -307,6 +307,7 @@ gst_vdp_mpeg_decoder_chain (GstPad * pad, GstBuffer * buffer) GstVdpMpegDecoder *mpeg_dec; guint8 *data, *end; guint32 sync_word = 0xffffffff; + GstFlowReturn ret = GST_FLOW_OK; mpeg_dec = GST_VDPAU_MPEG_DECODER (GST_OBJECT_PARENT (pad)); @@ -338,10 +339,9 @@ gst_vdp_mpeg_decoder_chain (GstPad * pad, GstBuffer * buffer) switch (data[0]) { case MPEG_PACKET_PICTURE: GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_PICTURE"); - if (mpeg_dec->vdp_info.slice_count > 0) { - if (gst_vdp_mpeg_decoder_decode (mpeg_dec) != GST_FLOW_OK) - return GST_FLOW_ERROR; - } + if (mpeg_dec->vdp_info.slice_count > 0) + ret = gst_vdp_mpeg_decoder_decode (mpeg_dec); + gst_vdp_mpeg_decoder_parse_picture (mpeg_dec, packet_start, packet_end); break; case MPEG_PACKET_SEQUENCE: @@ -374,7 +374,7 @@ gst_vdp_mpeg_decoder_chain (GstPad * pad, GstBuffer * buffer) } } - return GST_FLOW_OK; + return ret; } /* GObject vmethod implementations */ -- cgit v1.2.1 From da191134a1a66de4b5a591a5dea29dd4c0d8e92c Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Thu, 16 Apr 2009 22:06:50 +0200 Subject: vdpaumpegdec: inital support at handling B_FRAMES --- sys/vdpau/gstvdpmpegdecoder.c | 43 +++++++++++++++++++++++++++++++++++++++++++ sys/vdpau/gstvdpmpegdecoder.h | 4 ++++ 2 files changed, 47 insertions(+) diff --git a/sys/vdpau/gstvdpmpegdecoder.c b/sys/vdpau/gstvdpmpegdecoder.c index 9b4aa99d..d2ec7fd1 100644 --- a/sys/vdpau/gstvdpmpegdecoder.c +++ b/sys/vdpau/gstvdpmpegdecoder.c @@ -148,6 +148,18 @@ gst_vdp_mpeg_decoder_decode (GstVdpMpegDecoder * mpeg_dec) buffer = gst_adapter_take_buffer (mpeg_dec->adapter, gst_adapter_available (mpeg_dec->adapter)); + /* if the frame is a B_FRAME we store it for future decoding */ + if (mpeg_dec->vdp_info.picture_coding_type == B_FRAME) { + mpeg_dec->b_buffer = buffer; + memcpy (&mpeg_dec->b_vdp_info, &mpeg_dec->vdp_info, + sizeof (VdpPictureInfoMPEG1Or2)); + + /* unset forward_reference since next frame must be an I_FRAME */ + mpeg_dec->vdp_info.forward_reference = VDP_INVALID_HANDLE; + + return GST_FLOW_OK; + } + outbuf = gst_vdp_video_buffer_new (dec->device, VDP_CHROMA_TYPE_420, dec->width, dec->height); surface = outbuf->surface; @@ -179,6 +191,35 @@ gst_vdp_mpeg_decoder_decode (GstVdpMpegDecoder * mpeg_dec) return GST_FLOW_ERROR; } + /* if we have stored away a B_FRAME we can now decode it */ + if (mpeg_dec->b_buffer) { + GstVdpVideoBuffer *b_outbuf; + + b_outbuf = gst_vdp_video_buffer_new (dec->device, VDP_CHROMA_TYPE_420, + dec->width, dec->height); + mpeg_dec->b_vdp_info.backward_reference = surface; + vbit[0].struct_version = VDP_BITSTREAM_BUFFER_VERSION; + vbit[0].bitstream = GST_BUFFER_DATA (mpeg_dec->b_buffer); + vbit[0].bitstream_bytes = GST_BUFFER_SIZE (mpeg_dec->b_buffer); + + status = device->vdp_decoder_render (mpeg_dec->decoder, b_outbuf->surface, + (VdpPictureInfo *) & mpeg_dec->b_vdp_info, 1, vbit); + gst_buffer_unref (mpeg_dec->b_buffer); + mpeg_dec->b_buffer = NULL; + + if (status != VDP_STATUS_OK) { + GST_ELEMENT_ERROR (mpeg_dec, RESOURCE, READ, + ("Could not decode B_FRAME"), + ("Error returned from vdpau was: %s", + device->vdp_get_error_string (status))); + + if (mpeg_dec->b_vdp_info.forward_reference != VDP_INVALID_HANDLE) + gst_buffer_unref (mpeg_dec->f_buffer); + } + + gst_vdp_decoder_push_video_buffer (GST_VDPAU_DECODER (mpeg_dec), b_outbuf); + } + gst_buffer_ref (GST_BUFFER (outbuf)); ret = gst_vdp_decoder_push_video_buffer (GST_VDPAU_DECODER (mpeg_dec), @@ -441,6 +482,8 @@ gst_vdp_mpeg_decoder_init (GstVdpMpegDecoder * mpeg_dec, mpeg_dec->decoder = VDP_INVALID_HANDLE; gst_vdp_mpeg_decoder_init_info (&mpeg_dec->vdp_info); + mpeg_dec->b_buffer = NULL; + mpeg_dec->adapter = gst_adapter_new (); gst_pad_set_chain_function (dec->sink, gst_vdp_mpeg_decoder_chain); diff --git a/sys/vdpau/gstvdpmpegdecoder.h b/sys/vdpau/gstvdpmpegdecoder.h index 3ec8244d..3761cff6 100644 --- a/sys/vdpau/gstvdpmpegdecoder.h +++ b/sys/vdpau/gstvdpmpegdecoder.h @@ -46,6 +46,10 @@ struct _GstVdpMpegDecoder VdpDecoder decoder; VdpPictureInfoMPEG1Or2 vdp_info; GstBuffer *f_buffer; + + /* holds B_FRAMES */ + GstBuffer *b_buffer; + VdpPictureInfoMPEG1Or2 b_vdp_info; GstAdapter *adapter; }; -- cgit v1.2.1 From a168fdc1d3dfa013c4b381dbe3914564ac79b444 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Thu, 16 Apr 2009 22:30:27 +0200 Subject: vdpaumpegdec: more B_FRAME work --- sys/vdpau/gstvdpmpegdecoder.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/sys/vdpau/gstvdpmpegdecoder.c b/sys/vdpau/gstvdpmpegdecoder.c index d2ec7fd1..7c134afa 100644 --- a/sys/vdpau/gstvdpmpegdecoder.c +++ b/sys/vdpau/gstvdpmpegdecoder.c @@ -157,6 +157,8 @@ gst_vdp_mpeg_decoder_decode (GstVdpMpegDecoder * mpeg_dec) /* unset forward_reference since next frame must be an I_FRAME */ mpeg_dec->vdp_info.forward_reference = VDP_INVALID_HANDLE; + mpeg_dec->vdp_info.slice_count = 0; + return GST_FLOW_OK; } @@ -181,11 +183,6 @@ gst_vdp_mpeg_decoder_decode (GstVdpMpegDecoder * mpeg_dec) ("Error returned from vdpau was: %s", device->vdp_get_error_string (status))); - if (mpeg_dec->vdp_info.forward_reference != VDP_INVALID_HANDLE) { - gst_buffer_unref (mpeg_dec->f_buffer); - mpeg_dec->vdp_info.forward_reference = VDP_INVALID_HANDLE; - } - gst_buffer_unref (GST_BUFFER (outbuf)); return GST_FLOW_ERROR; @@ -197,7 +194,9 @@ gst_vdp_mpeg_decoder_decode (GstVdpMpegDecoder * mpeg_dec) b_outbuf = gst_vdp_video_buffer_new (dec->device, VDP_CHROMA_TYPE_420, dec->width, dec->height); - mpeg_dec->b_vdp_info.backward_reference = surface; + mpeg_dec->b_vdp_info.backward_reference = + mpeg_dec->b_vdp_info.forward_reference; + mpeg_dec->b_vdp_info.forward_reference = surface; vbit[0].struct_version = VDP_BITSTREAM_BUFFER_VERSION; vbit[0].bitstream = GST_BUFFER_DATA (mpeg_dec->b_buffer); vbit[0].bitstream_bytes = GST_BUFFER_SIZE (mpeg_dec->b_buffer); @@ -212,12 +211,12 @@ gst_vdp_mpeg_decoder_decode (GstVdpMpegDecoder * mpeg_dec) ("Could not decode B_FRAME"), ("Error returned from vdpau was: %s", device->vdp_get_error_string (status))); - - if (mpeg_dec->b_vdp_info.forward_reference != VDP_INVALID_HANDLE) - gst_buffer_unref (mpeg_dec->f_buffer); } gst_vdp_decoder_push_video_buffer (GST_VDPAU_DECODER (mpeg_dec), b_outbuf); + + if (mpeg_dec->b_vdp_info.forward_reference != VDP_INVALID_HANDLE) + gst_buffer_unref (mpeg_dec->f_buffer); } gst_buffer_ref (GST_BUFFER (outbuf)); -- cgit v1.2.1 From e0ddcabd7ab63c8060b7259e4075a0e88e5bcf66 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Thu, 16 Apr 2009 23:43:24 +0200 Subject: vdpaumpegdec: handle multiple B_FRAMEs in a row --- sys/vdpau/gstvdpmpegdecoder.c | 81 ++++++++++++++++++++++++++----------------- sys/vdpau/gstvdpmpegdecoder.h | 3 +- sys/vdpau/mpegutil.c | 5 +-- 3 files changed, 51 insertions(+), 38 deletions(-) diff --git a/sys/vdpau/gstvdpmpegdecoder.c b/sys/vdpau/gstvdpmpegdecoder.c index 7c134afa..c40aee81 100644 --- a/sys/vdpau/gstvdpmpegdecoder.c +++ b/sys/vdpau/gstvdpmpegdecoder.c @@ -131,6 +131,12 @@ gst_vdp_mpeg_decoder_set_caps (GstVdpDecoder * dec, GstCaps * caps) return TRUE; } +typedef struct +{ + GstBuffer *buffer; + VdpPictureInfoMPEG1Or2 vdp_info; +} GstVdpBFrame; + static GstFlowReturn gst_vdp_mpeg_decoder_decode (GstVdpMpegDecoder * mpeg_dec) { @@ -150,13 +156,17 @@ gst_vdp_mpeg_decoder_decode (GstVdpMpegDecoder * mpeg_dec) /* if the frame is a B_FRAME we store it for future decoding */ if (mpeg_dec->vdp_info.picture_coding_type == B_FRAME) { - mpeg_dec->b_buffer = buffer; - memcpy (&mpeg_dec->b_vdp_info, &mpeg_dec->vdp_info, + GstVdpBFrame *b_frame; + + b_frame = g_slice_new (GstVdpBFrame); + + b_frame->buffer = buffer; + memcpy (&b_frame->vdp_info, &mpeg_dec->vdp_info, sizeof (VdpPictureInfoMPEG1Or2)); - /* unset forward_reference since next frame must be an I_FRAME */ - mpeg_dec->vdp_info.forward_reference = VDP_INVALID_HANDLE; + mpeg_dec->b_frames = g_slist_append (mpeg_dec->b_frames, b_frame); + gst_buffer_ref (mpeg_dec->f_buffer); mpeg_dec->vdp_info.slice_count = 0; return GST_FLOW_OK; @@ -188,35 +198,43 @@ gst_vdp_mpeg_decoder_decode (GstVdpMpegDecoder * mpeg_dec) return GST_FLOW_ERROR; } - /* if we have stored away a B_FRAME we can now decode it */ - if (mpeg_dec->b_buffer) { - GstVdpVideoBuffer *b_outbuf; - - b_outbuf = gst_vdp_video_buffer_new (dec->device, VDP_CHROMA_TYPE_420, - dec->width, dec->height); - mpeg_dec->b_vdp_info.backward_reference = - mpeg_dec->b_vdp_info.forward_reference; - mpeg_dec->b_vdp_info.forward_reference = surface; - vbit[0].struct_version = VDP_BITSTREAM_BUFFER_VERSION; - vbit[0].bitstream = GST_BUFFER_DATA (mpeg_dec->b_buffer); - vbit[0].bitstream_bytes = GST_BUFFER_SIZE (mpeg_dec->b_buffer); - - status = device->vdp_decoder_render (mpeg_dec->decoder, b_outbuf->surface, - (VdpPictureInfo *) & mpeg_dec->b_vdp_info, 1, vbit); - gst_buffer_unref (mpeg_dec->b_buffer); - mpeg_dec->b_buffer = NULL; - - if (status != VDP_STATUS_OK) { - GST_ELEMENT_ERROR (mpeg_dec, RESOURCE, READ, - ("Could not decode B_FRAME"), - ("Error returned from vdpau was: %s", - device->vdp_get_error_string (status))); - } + /* if we have stored away some B_FRAMEs we can now decode them */ + if (mpeg_dec->b_frames) { + GSList *iter; + + for (iter = mpeg_dec->b_frames; iter; iter = g_slist_next (iter)) { + GstVdpBFrame *b_frame; + GstVdpVideoBuffer *b_outbuf; - gst_vdp_decoder_push_video_buffer (GST_VDPAU_DECODER (mpeg_dec), b_outbuf); + b_frame = (GstVdpBFrame *) iter->data; + + b_outbuf = gst_vdp_video_buffer_new (dec->device, VDP_CHROMA_TYPE_420, + dec->width, dec->height); + + b_frame->vdp_info.forward_reference = surface; + vbit[0].struct_version = VDP_BITSTREAM_BUFFER_VERSION; + vbit[0].bitstream = GST_BUFFER_DATA (b_frame->buffer); + vbit[0].bitstream_bytes = GST_BUFFER_SIZE (b_frame->buffer); + + status = device->vdp_decoder_render (mpeg_dec->decoder, b_outbuf->surface, + (VdpPictureInfo *) & b_frame->vdp_info, 1, vbit); + gst_buffer_unref (b_frame->buffer); + g_slice_free (GstVdpBFrame, b_frame); + + if (status != VDP_STATUS_OK) { + GST_ELEMENT_ERROR (mpeg_dec, RESOURCE, READ, + ("Could not decode B_FRAME"), + ("Error returned from vdpau was: %s", + device->vdp_get_error_string (status))); + } + + gst_vdp_decoder_push_video_buffer (GST_VDPAU_DECODER (mpeg_dec), + b_outbuf); - if (mpeg_dec->b_vdp_info.forward_reference != VDP_INVALID_HANDLE) gst_buffer_unref (mpeg_dec->f_buffer); + } + g_slist_free (mpeg_dec->b_frames); + mpeg_dec->b_frames = NULL; } gst_buffer_ref (GST_BUFFER (outbuf)); @@ -295,7 +313,6 @@ gst_vdp_mpeg_decoder_parse_picture (GstVdpMpegDecoder * mpeg_dec, mpeg_dec->vdp_info.picture_coding_type = pic_hdr.pic_type; - if (pic_hdr.pic_type == I_FRAME && mpeg_dec->vdp_info.forward_reference != VDP_INVALID_HANDLE) { gst_buffer_unref (mpeg_dec->f_buffer); @@ -481,7 +498,7 @@ gst_vdp_mpeg_decoder_init (GstVdpMpegDecoder * mpeg_dec, mpeg_dec->decoder = VDP_INVALID_HANDLE; gst_vdp_mpeg_decoder_init_info (&mpeg_dec->vdp_info); - mpeg_dec->b_buffer = NULL; + mpeg_dec->b_frames = NULL; mpeg_dec->adapter = gst_adapter_new (); diff --git a/sys/vdpau/gstvdpmpegdecoder.h b/sys/vdpau/gstvdpmpegdecoder.h index 3761cff6..a03c17c2 100644 --- a/sys/vdpau/gstvdpmpegdecoder.h +++ b/sys/vdpau/gstvdpmpegdecoder.h @@ -48,8 +48,7 @@ struct _GstVdpMpegDecoder GstBuffer *f_buffer; /* holds B_FRAMES */ - GstBuffer *b_buffer; - VdpPictureInfoMPEG1Or2 b_vdp_info; + GSList *b_frames; GstAdapter *adapter; }; diff --git a/sys/vdpau/mpegutil.c b/sys/vdpau/mpegutil.c index 929df4ab..4586cd7d 100644 --- a/sys/vdpau/mpegutil.c +++ b/sys/vdpau/mpegutil.c @@ -285,14 +285,11 @@ mpeg_util_parse_picture_hdr (MPEGPictureHdr * hdr, guint8 * data, guint8 * end) /* Skip the sync word */ data += 4; - hdr->pic_type = (data[1] >> 3) & 0x07; + hdr->pic_type = read_bits (data + 1, 2, 3); if (hdr->pic_type == 0 || hdr->pic_type > 4) return FALSE; /* Corrupted picture packet */ if (hdr->pic_type == P_FRAME || hdr->pic_type == B_FRAME) { - if (G_UNLIKELY ((end - data) < 5)) - return FALSE; /* packet too small */ - hdr->full_pel_forward_vector = read_bits (data + 3, 5, 1); hdr->f_code[0][0] = hdr->f_code[0][1] = read_bits (data + 3, 6, 3); -- cgit v1.2.1 From fc3c9dba95e18647ab097edc7f2ba5dfecddb787 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Wed, 22 Apr 2009 20:25:55 +0200 Subject: vdpaumpegdec: fixup error where we set forward_reference instead of backward_reference --- sys/vdpau/gstvdpmpegdecoder.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/vdpau/gstvdpmpegdecoder.c b/sys/vdpau/gstvdpmpegdecoder.c index c40aee81..bbd5403f 100644 --- a/sys/vdpau/gstvdpmpegdecoder.c +++ b/sys/vdpau/gstvdpmpegdecoder.c @@ -211,7 +211,7 @@ gst_vdp_mpeg_decoder_decode (GstVdpMpegDecoder * mpeg_dec) b_outbuf = gst_vdp_video_buffer_new (dec->device, VDP_CHROMA_TYPE_420, dec->width, dec->height); - b_frame->vdp_info.forward_reference = surface; + b_frame->vdp_info.backward_reference = surface; vbit[0].struct_version = VDP_BITSTREAM_BUFFER_VERSION; vbit[0].bitstream = GST_BUFFER_DATA (b_frame->buffer); vbit[0].bitstream_bytes = GST_BUFFER_SIZE (b_frame->buffer); -- cgit v1.2.1 From 806d4ced04098470b92c3ff53fe82456f26682bc Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Wed, 22 Apr 2009 20:28:19 +0200 Subject: vdpaumpegdec: remove unneded gst_buffer_ref and the accompanying gst_buffer_unref --- sys/vdpau/gstvdpmpegdecoder.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/sys/vdpau/gstvdpmpegdecoder.c b/sys/vdpau/gstvdpmpegdecoder.c index bbd5403f..978d0497 100644 --- a/sys/vdpau/gstvdpmpegdecoder.c +++ b/sys/vdpau/gstvdpmpegdecoder.c @@ -166,7 +166,6 @@ gst_vdp_mpeg_decoder_decode (GstVdpMpegDecoder * mpeg_dec) mpeg_dec->b_frames = g_slist_append (mpeg_dec->b_frames, b_frame); - gst_buffer_ref (mpeg_dec->f_buffer); mpeg_dec->vdp_info.slice_count = 0; return GST_FLOW_OK; @@ -230,8 +229,6 @@ gst_vdp_mpeg_decoder_decode (GstVdpMpegDecoder * mpeg_dec) gst_vdp_decoder_push_video_buffer (GST_VDPAU_DECODER (mpeg_dec), b_outbuf); - - gst_buffer_unref (mpeg_dec->f_buffer); } g_slist_free (mpeg_dec->b_frames); mpeg_dec->b_frames = NULL; -- cgit v1.2.1 From 17102ad0fadef83a0d8b0d807d698a104bc428b5 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Wed, 22 Apr 2009 21:04:58 +0200 Subject: vdpaumpegdec: convert all manual parsing to use read_bits instead --- sys/vdpau/mpegutil.c | 27 ++++++++++++++++----------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/sys/vdpau/mpegutil.c b/sys/vdpau/mpegutil.c index 4586cd7d..a1323f68 100644 --- a/sys/vdpau/mpegutil.c +++ b/sys/vdpau/mpegutil.c @@ -158,7 +158,7 @@ mpeg_util_parse_extension_packet (MPEGSeqHdr * hdr, guint8 * data, guint8 * end) if (G_UNLIKELY (data >= end)) return FALSE; /* short extension packet */ - ext_code = data[0] >> 4; + ext_code = read_bits (data, 0, 4); switch (ext_code) { case MPEG_PACKET_EXT_SEQUENCE: @@ -171,11 +171,13 @@ mpeg_util_parse_extension_packet (MPEGSeqHdr * hdr, guint8 * data, guint8 * end) /* need at least 10 bytes, minus 4 for the start code 000001b5 */ return FALSE; - horiz_size_ext = ((data[1] << 1) & 0x02) | ((data[2] >> 7) & 0x01); - vert_size_ext = (data[2] >> 5) & 0x03; hdr->profile = read_bits (data, 7, 3); - fps_n_ext = (data[5] >> 5) & 0x03; - fps_d_ext = data[5] & 0x1f; + + horiz_size_ext = read_bits (data + 1, 7, 2); + vert_size_ext = read_bits (data + 2, 1, 2); + + fps_n_ext = read_bits (data + 5, 1, 2); + fps_d_ext = read_bits (data + 5, 3, 5); hdr->fps_n *= (fps_n_ext + 1); hdr->fps_d *= (fps_d_ext + 1); @@ -215,15 +217,15 @@ mpeg_util_parse_sequence_hdr (MPEGSeqHdr * hdr, guint8 * data, guint8 * end) hdr->mpeg_version = 1; code = GST_READ_UINT32_BE (data); - hdr->width = (code >> 20) & 0xfff; - hdr->height = (code >> 8) & 0xfff; + hdr->width = read_bits (data, 0, 12); + hdr->height = read_bits (data + 1, 4, 12); - dar_idx = (code >> 4) & 0xf; + dar_idx = read_bits (data + 3, 0, 4); set_par_from_dar (hdr, dar_idx); - fps_idx = code & 0xf; + fps_idx = read_bits (data + 3, 4, 4); set_fps_from_code (hdr, fps_idx); - constrained_flag = (data[7] >> 2) & 0x01; + constrained_flag = read_bits (data + 7, 5, 1); load_intra_flag = read_bits (data + 7, 6, 1); if (load_intra_flag) { @@ -285,11 +287,14 @@ mpeg_util_parse_picture_hdr (MPEGPictureHdr * hdr, guint8 * data, guint8 * end) /* Skip the sync word */ data += 4; - hdr->pic_type = read_bits (data + 1, 2, 3); + hdr->pic_type = (data[1] >> 3) & 0x07; if (hdr->pic_type == 0 || hdr->pic_type > 4) return FALSE; /* Corrupted picture packet */ if (hdr->pic_type == P_FRAME || hdr->pic_type == B_FRAME) { + if (G_UNLIKELY ((end - data) < 5)) + return FALSE; /* packet too small */ + hdr->full_pel_forward_vector = read_bits (data + 3, 5, 1); hdr->f_code[0][0] = hdr->f_code[0][1] = read_bits (data + 3, 6, 3); -- cgit v1.2.1 From 035b5f4efb4d57fccf2a5fa220c0d034f4d777a3 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Wed, 22 Apr 2009 23:35:07 +0200 Subject: vdpaumpegdec: handle broken_gop field --- sys/vdpau/gstvdpmpegdecoder.c | 10 ++++++++++ sys/vdpau/gstvdpmpegdecoder.h | 2 ++ sys/vdpau/mpegutil.c | 15 ++++++--------- sys/vdpau/mpegutil.h | 6 ++++-- 4 files changed, 22 insertions(+), 11 deletions(-) diff --git a/sys/vdpau/gstvdpmpegdecoder.c b/sys/vdpau/gstvdpmpegdecoder.c index 978d0497..d9b74706 100644 --- a/sys/vdpau/gstvdpmpegdecoder.c +++ b/sys/vdpau/gstvdpmpegdecoder.c @@ -158,6 +158,12 @@ gst_vdp_mpeg_decoder_decode (GstVdpMpegDecoder * mpeg_dec) if (mpeg_dec->vdp_info.picture_coding_type == B_FRAME) { GstVdpBFrame *b_frame; + if (mpeg_dec->broken_gop) { + gst_buffer_unref (buffer); + mpeg_dec->broken_gop = FALSE; + return GST_FLOW_OK; + } + b_frame = g_slice_new (GstVdpBFrame); b_frame->buffer = buffer; @@ -336,6 +342,8 @@ gst_vdp_mpeg_decoder_parse_gop (GstVdpMpegDecoder * mpeg_dec, guint8 * data, if (!mpeg_util_parse_picture_gop (&gop, data, end)) return FALSE; + mpeg_dec->broken_gop = gop.broken_gop; + return TRUE; } @@ -497,6 +505,8 @@ gst_vdp_mpeg_decoder_init (GstVdpMpegDecoder * mpeg_dec, mpeg_dec->b_frames = NULL; + mpeg_dec->broken_gop = FALSE; + mpeg_dec->adapter = gst_adapter_new (); gst_pad_set_chain_function (dec->sink, gst_vdp_mpeg_decoder_chain); diff --git a/sys/vdpau/gstvdpmpegdecoder.h b/sys/vdpau/gstvdpmpegdecoder.h index a03c17c2..aac79f31 100644 --- a/sys/vdpau/gstvdpmpegdecoder.h +++ b/sys/vdpau/gstvdpmpegdecoder.h @@ -49,6 +49,8 @@ struct _GstVdpMpegDecoder /* holds B_FRAMES */ GSList *b_frames; + + gboolean broken_gop; GstAdapter *adapter; }; diff --git a/sys/vdpau/mpegutil.c b/sys/vdpau/mpegutil.c index a1323f68..6f59b841 100644 --- a/sys/vdpau/mpegutil.c +++ b/sys/vdpau/mpegutil.c @@ -348,7 +348,6 @@ gboolean mpeg_util_parse_picture_gop (MPEGPictureGOP * gop, guint8 * data, guint8 * end) { guint32 code; - gint hour, minute, second; if (G_UNLIKELY ((end - data) < 8)) return FALSE; /* Packet too small */ @@ -363,16 +362,14 @@ mpeg_util_parse_picture_gop (MPEGPictureGOP * gop, guint8 * data, guint8 * end) gop->drop_frame_flag = read_bits (data, 0, 1); - hour = read_bits (data, 1, 5); - minute = read_bits (data, 6, 6); - second = read_bits (data + 1, 4, 6); - - gop->timestamp = hour * 3600 * GST_SECOND; - gop->timestamp += minute * 60 * GST_SECOND; - gop->timestamp += second * GST_SECOND; - + gop->hour = read_bits (data, 1, 5); + gop->minute = read_bits (data, 6, 6); + gop->second = read_bits (data + 1, 4, 6); gop->frame = read_bits (data + 2, 3, 6); + gop->closed_gop = read_bits (data + 3, 1, 1); + gop->broken_gop = read_bits (data + 3, 2, 1); + return TRUE; } diff --git a/sys/vdpau/mpegutil.h b/sys/vdpau/mpegutil.h index 24a29a35..43f34a59 100644 --- a/sys/vdpau/mpegutil.h +++ b/sys/vdpau/mpegutil.h @@ -96,9 +96,11 @@ struct MPEGPictureExt struct MPEGPictureGOP { guint8 drop_frame_flag; - guint8 frame; - GstClockTime timestamp; + guint8 hour, minute, second, frame; + + guint8 closed_gop; + guint8 broken_gop; }; struct MPEGQuantMatrix -- cgit v1.2.1 From 8b3261f91ac49530495cb7527eab923fcb59ab91 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Sun, 26 Apr 2009 20:40:45 +0200 Subject: vdpaumpegdec: add "MPEG_PACKET_EXT_PICTURE_CODING" debug statement --- sys/vdpau/gstvdpmpegdecoder.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sys/vdpau/gstvdpmpegdecoder.c b/sys/vdpau/gstvdpmpegdecoder.c index d9b74706..863e3bb3 100644 --- a/sys/vdpau/gstvdpmpegdecoder.c +++ b/sys/vdpau/gstvdpmpegdecoder.c @@ -415,6 +415,7 @@ gst_vdp_mpeg_decoder_chain (GstPad * pad, GstBuffer * buffer) GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_EXTENSION"); switch (read_bits (data + 1, 0, 4)) { case MPEG_PACKET_EXT_PICTURE_CODING: + GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_EXT_PICTURE_CODING"); gst_vdp_mpeg_decoder_parse_picture_coding (mpeg_dec, packet_start, packet_end); break; -- cgit v1.2.1 From 4d69d761d24e5b8320efa680402055ec785417bf Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Sun, 26 Apr 2009 22:05:11 +0200 Subject: vdpaumpegdec: reset decoder when we get a discont buffer --- sys/vdpau/gstvdpmpegdecoder.c | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/sys/vdpau/gstvdpmpegdecoder.c b/sys/vdpau/gstvdpmpegdecoder.c index 863e3bb3..86f65fee 100644 --- a/sys/vdpau/gstvdpmpegdecoder.c +++ b/sys/vdpau/gstvdpmpegdecoder.c @@ -73,6 +73,7 @@ GST_DEBUG_CATEGORY_INIT (gst_vdp_mpeg_decoder_debug, "vdpaumpegdec", 0, "VDPAU p GST_BOILERPLATE_FULL (GstVdpMpegDecoder, gst_vdp_mpeg_decoder, GstVdpDecoder, GST_TYPE_VDPAU_DECODER, DEBUG_INIT); +static void gst_vdp_mpeg_decoder_init_info (VdpPictureInfoMPEG1Or2 * vdp_info); static void gst_vdp_mpeg_decoder_finalize (GObject * object); static void gst_vdp_mpeg_decoder_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec); @@ -363,6 +364,26 @@ gst_vdp_mpeg_decoder_parse_quant_matrix (GstVdpMpegDecoder * mpeg_dec, return TRUE; } +static void +gst_vdp_mpeg_decoder_reset (GstVdpMpegDecoder * mpeg_dec) +{ + GSList *iter; + + for (iter = mpeg_dec->b_frames; iter; iter = iter->next) { + GstVdpBFrame *b_frame = (GstVdpBFrame *) iter->data; + + gst_buffer_unref (b_frame->buffer); + g_slice_free (GstVdpBFrame, b_frame); + } + g_slist_free (mpeg_dec->b_frames); + mpeg_dec->b_frames = NULL; + + if (mpeg_dec->vdp_info.forward_reference != VDP_INVALID_HANDLE) + gst_buffer_unref (mpeg_dec->f_buffer); + + gst_vdp_mpeg_decoder_init_info (&mpeg_dec->vdp_info); +} + static GstFlowReturn gst_vdp_mpeg_decoder_chain (GstPad * pad, GstBuffer * buffer) { @@ -373,6 +394,12 @@ gst_vdp_mpeg_decoder_chain (GstPad * pad, GstBuffer * buffer) mpeg_dec = GST_VDPAU_MPEG_DECODER (GST_OBJECT_PARENT (pad)); + if (G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT))) { + GST_DEBUG_OBJECT (mpeg_dec, "Received discont buffer"); + gst_vdp_mpeg_decoder_reset (mpeg_dec); + return GST_FLOW_OK; + } + data = GST_BUFFER_DATA (buffer); end = GST_BUFFER_DATA (buffer) + GST_BUFFER_SIZE (buffer); -- cgit v1.2.1 From 8bbd79496187baabe6ad754e493cb167bbc3a8dc Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Sun, 26 Apr 2009 23:20:30 +0200 Subject: vdpaumpegdec: reset decoder on GST_EVENT_FLUSH_STOP --- sys/vdpau/gstvdpmpegdecoder.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/sys/vdpau/gstvdpmpegdecoder.c b/sys/vdpau/gstvdpmpegdecoder.c index 86f65fee..42c89a32 100644 --- a/sys/vdpau/gstvdpmpegdecoder.c +++ b/sys/vdpau/gstvdpmpegdecoder.c @@ -467,6 +467,33 @@ gst_vdp_mpeg_decoder_chain (GstPad * pad, GstBuffer * buffer) return ret; } +static gboolean +gst_vdp_mpeg_decoder_sink_event (GstPad * pad, GstEvent * event) +{ + GstVdpMpegDecoder *mpeg_dec; + GstVdpDecoder *dec; + gboolean res; + + mpeg_dec = GST_VDPAU_MPEG_DECODER (GST_OBJECT_PARENT (pad)); + dec = GST_VDPAU_DECODER (mpeg_dec); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_FLUSH_STOP: + { + GST_DEBUG_OBJECT (mpeg_dec, "flush stop"); + + gst_vdp_mpeg_decoder_reset (mpeg_dec); + res = gst_pad_push_event (dec->src, event); + + break; + } + default: + res = gst_pad_event_default (pad, event); + } + + return res; +} + /* GObject vmethod implementations */ static void @@ -538,6 +565,7 @@ gst_vdp_mpeg_decoder_init (GstVdpMpegDecoder * mpeg_dec, mpeg_dec->adapter = gst_adapter_new (); gst_pad_set_chain_function (dec->sink, gst_vdp_mpeg_decoder_chain); + gst_pad_set_event_function (dec->sink, gst_vdp_mpeg_decoder_sink_event); } static void -- cgit v1.2.1 From 8c78a4850fa5bc1323fee6d47e6a9bd31d024f0e Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Sun, 26 Apr 2009 23:25:33 +0200 Subject: vdpau: fixup renaming the rename work done in commit 24cf84d06b2f4b2edec3383b198441a07829618b didn't include typecasts. This commit fixes this. --- sys/vdpau/gstvdpdecoder.c | 10 +++++----- sys/vdpau/gstvdpdecoder.h | 12 ++++++------ sys/vdpau/gstvdpdevice.h | 12 ++++++------ sys/vdpau/gstvdpmpegdecoder.c | 24 +++++++++++------------- sys/vdpau/gstvdpmpegdecoder.h | 10 +++++----- sys/vdpau/gstvdpvideobuffer.h | 8 ++++---- sys/vdpau/gstvdpvideoyuv.c | 12 ++++++------ sys/vdpau/gstvdpvideoyuv.h | 12 ++++++------ sys/vdpau/gstvdpyuvvideo.c | 16 ++++++++-------- sys/vdpau/gstvdpyuvvideo.h | 12 ++++++------ 10 files changed, 63 insertions(+), 65 deletions(-) diff --git a/sys/vdpau/gstvdpdecoder.c b/sys/vdpau/gstvdpdecoder.c index dafcec98..3f71ab40 100644 --- a/sys/vdpau/gstvdpdecoder.c +++ b/sys/vdpau/gstvdpdecoder.c @@ -83,7 +83,7 @@ gst_vdp_decoder_change_state (GstElement * element, GstStateChange transition) { GstVdpDecoder *dec; - dec = GST_VDPAU_DECODER (element); + dec = GST_VDP_DECODER (element); switch (transition) { case GST_STATE_CHANGE_NULL_TO_READY: @@ -103,8 +103,8 @@ gst_vdp_decoder_change_state (GstElement * element, GstStateChange transition) static gboolean gst_vdp_decoder_sink_set_caps (GstPad * pad, GstCaps * caps) { - GstVdpDecoder *dec = GST_VDPAU_DECODER (GST_OBJECT_PARENT (pad)); - GstVdpDecoderClass *dec_class = GST_VDPAU_DECODER_GET_CLASS (dec); + GstVdpDecoder *dec = GST_VDP_DECODER (GST_OBJECT_PARENT (pad)); + GstVdpDecoderClass *dec_class = GST_VDP_DECODER_GET_CLASS (dec); GstCaps *src_caps, *new_caps; GstStructure *structure; @@ -227,7 +227,7 @@ static void gst_vdp_decoder_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { - GstVdpDecoder *dec = GST_VDPAU_DECODER (object); + GstVdpDecoder *dec = GST_VDP_DECODER (object); switch (prop_id) { case PROP_DISPLAY: @@ -244,7 +244,7 @@ static void gst_vdp_decoder_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { - GstVdpDecoder *dec = GST_VDPAU_DECODER (object); + GstVdpDecoder *dec = GST_VDP_DECODER (object); switch (prop_id) { case PROP_DISPLAY: diff --git a/sys/vdpau/gstvdpdecoder.h b/sys/vdpau/gstvdpdecoder.h index 8dc4ad66..dfc63fd9 100644 --- a/sys/vdpau/gstvdpdecoder.h +++ b/sys/vdpau/gstvdpdecoder.h @@ -18,8 +18,8 @@ * Boston, MA 02111-1307, USA. */ -#ifndef __GST_VDPAU_DECODER_H__ -#define __GST_VDPAU_DECODER_H__ +#ifndef __GST_VDP_DECODER_H__ +#define __GST_VDP_DECODER_H__ #include @@ -29,9 +29,9 @@ G_BEGIN_DECLS #define GST_TYPE_VDPAU_DECODER (gst_vdp_decoder_get_type()) -#define GST_VDPAU_DECODER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VDPAU_DECODER,GstVdpDecoder)) -#define GST_VDPAU_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VDPAU_DECODER,GstVdpDecoderClass)) -#define GST_VDPAU_DECODER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_VDPAU_DECODER, GstVdpDecoderClass)) +#define GST_VDP_DECODER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VDPAU_DECODER,GstVdpDecoder)) +#define GST_VDP_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VDPAU_DECODER,GstVdpDecoderClass)) +#define GST_VDP_DECODER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_VDPAU_DECODER, GstVdpDecoderClass)) #define GST_IS_VDPAU_DECODER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VDPAU_DECODER)) #define GST_IS_VDPAU_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VDPAU_DECODER)) @@ -69,4 +69,4 @@ VdpVideoSurface gst_vdp_decoder_create_video_surface (GstVdpDecoder *dec); G_END_DECLS -#endif /* __GST_VDPAU_DECODER_H__ */ +#endif /* __GST_VDP_DECODER_H__ */ diff --git a/sys/vdpau/gstvdpdevice.h b/sys/vdpau/gstvdpdevice.h index 8b2f596c..26e7fa72 100644 --- a/sys/vdpau/gstvdpdevice.h +++ b/sys/vdpau/gstvdpdevice.h @@ -18,8 +18,8 @@ * Boston, MA 02111-1307, USA. */ -#ifndef _GST_VDPAU_DEVICE_H_ -#define _GST_VDPAU_DEVICE_H_ +#ifndef _GST_VDP_DEVICE_H_ +#define _GST_VDP_DEVICE_H_ #include #include @@ -29,11 +29,11 @@ G_BEGIN_DECLS #define GST_TYPE_VDPAU_DEVICE (gst_vdp_device_get_type ()) -#define GST_VDPAU_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_VDPAU_DEVICE, GstVdpDevice)) -#define GST_VDPAU_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_VDPAU_DEVICE, GstVdpDeviceClass)) +#define GST_VDP_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_VDPAU_DEVICE, GstVdpDevice)) +#define GST_VDP_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_VDPAU_DEVICE, GstVdpDeviceClass)) #define GST_IS_VDPAU_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_VDPAU_DEVICE)) #define GST_IS_VDPAU_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_VDPAU_DEVICE)) -#define GST_VDPAU_DEVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_VDPAU_DEVICE, GstVdpDeviceClass)) +#define GST_VDP_DEVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_VDPAU_DEVICE, GstVdpDeviceClass)) typedef struct _GstVdpDeviceClass GstVdpDeviceClass; typedef struct _GstVdpDevice GstVdpDevice; @@ -129,4 +129,4 @@ GstVdpDevice *gst_vdp_get_device (const gchar *display_name); G_END_DECLS -#endif /* _GST_VDPAU_DEVICE_H_ */ +#endif /* _GST_VDP_DEVICE_H_ */ diff --git a/sys/vdpau/gstvdpmpegdecoder.c b/sys/vdpau/gstvdpmpegdecoder.c index 42c89a32..f13db895 100644 --- a/sys/vdpau/gstvdpmpegdecoder.c +++ b/sys/vdpau/gstvdpmpegdecoder.c @@ -92,7 +92,7 @@ gst_vdp_mpeg_decoder_set_caps (GstVdpDecoder * dec, GstCaps * caps) GstVdpDevice *device; VdpStatus status; - mpeg_dec = GST_VDPAU_MPEG_DECODER (dec); + mpeg_dec = GST_VDP_MPEG_DECODER (dec); structure = gst_caps_get_structure (caps, 0); gst_structure_get_int (structure, "mpegversion", &mpeg_dec->version); @@ -150,7 +150,7 @@ gst_vdp_mpeg_decoder_decode (GstVdpMpegDecoder * mpeg_dec) VdpStatus status; GstFlowReturn ret; - dec = GST_VDPAU_DECODER (mpeg_dec); + dec = GST_VDP_DECODER (mpeg_dec); buffer = gst_adapter_take_buffer (mpeg_dec->adapter, gst_adapter_available (mpeg_dec->adapter)); @@ -234,8 +234,7 @@ gst_vdp_mpeg_decoder_decode (GstVdpMpegDecoder * mpeg_dec) device->vdp_get_error_string (status))); } - gst_vdp_decoder_push_video_buffer (GST_VDPAU_DECODER (mpeg_dec), - b_outbuf); + gst_vdp_decoder_push_video_buffer (GST_VDP_DECODER (mpeg_dec), b_outbuf); } g_slist_free (mpeg_dec->b_frames); mpeg_dec->b_frames = NULL; @@ -243,8 +242,7 @@ gst_vdp_mpeg_decoder_decode (GstVdpMpegDecoder * mpeg_dec) gst_buffer_ref (GST_BUFFER (outbuf)); - ret = gst_vdp_decoder_push_video_buffer (GST_VDPAU_DECODER (mpeg_dec), - outbuf); + ret = gst_vdp_decoder_push_video_buffer (GST_VDP_DECODER (mpeg_dec), outbuf); if (mpeg_dec->vdp_info.forward_reference != VDP_INVALID_HANDLE) gst_buffer_unref (mpeg_dec->f_buffer); @@ -263,7 +261,7 @@ gst_vdp_mpeg_decoder_parse_picture_coding (GstVdpMpegDecoder * mpeg_dec, MPEGPictureExt pic_ext; VdpPictureInfoMPEG1Or2 *info; - dec = GST_VDPAU_DECODER (mpeg_dec); + dec = GST_VDP_DECODER (mpeg_dec); info = &mpeg_dec->vdp_info; if (!mpeg_util_parse_picture_coding_extension (&pic_ext, data, end)) @@ -290,7 +288,7 @@ gst_vdp_mpeg_decoder_parse_sequence (GstVdpMpegDecoder * mpeg_dec, GstVdpDecoder *dec; MPEGSeqHdr hdr; - dec = GST_VDPAU_DECODER (mpeg_dec); + dec = GST_VDP_DECODER (mpeg_dec); if (!mpeg_util_parse_sequence_hdr (&hdr, data, end)) return FALSE; @@ -310,7 +308,7 @@ gst_vdp_mpeg_decoder_parse_picture (GstVdpMpegDecoder * mpeg_dec, GstVdpDecoder *dec; MPEGPictureHdr pic_hdr; - dec = GST_VDPAU_DECODER (mpeg_dec); + dec = GST_VDP_DECODER (mpeg_dec); if (!mpeg_util_parse_picture_hdr (&pic_hdr, data, end)) return FALSE; @@ -392,7 +390,7 @@ gst_vdp_mpeg_decoder_chain (GstPad * pad, GstBuffer * buffer) guint32 sync_word = 0xffffffff; GstFlowReturn ret = GST_FLOW_OK; - mpeg_dec = GST_VDPAU_MPEG_DECODER (GST_OBJECT_PARENT (pad)); + mpeg_dec = GST_VDP_MPEG_DECODER (GST_OBJECT_PARENT (pad)); if (G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT))) { GST_DEBUG_OBJECT (mpeg_dec, "Received discont buffer"); @@ -474,8 +472,8 @@ gst_vdp_mpeg_decoder_sink_event (GstPad * pad, GstEvent * event) GstVdpDecoder *dec; gboolean res; - mpeg_dec = GST_VDPAU_MPEG_DECODER (GST_OBJECT_PARENT (pad)); - dec = GST_VDPAU_DECODER (mpeg_dec); + mpeg_dec = GST_VDP_MPEG_DECODER (GST_OBJECT_PARENT (pad)); + dec = GST_VDP_DECODER (mpeg_dec); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_FLUSH_STOP: @@ -553,7 +551,7 @@ gst_vdp_mpeg_decoder_init (GstVdpMpegDecoder * mpeg_dec, { GstVdpDecoder *dec; - dec = GST_VDPAU_DECODER (mpeg_dec); + dec = GST_VDP_DECODER (mpeg_dec); mpeg_dec->decoder = VDP_INVALID_HANDLE; gst_vdp_mpeg_decoder_init_info (&mpeg_dec->vdp_info); diff --git a/sys/vdpau/gstvdpmpegdecoder.h b/sys/vdpau/gstvdpmpegdecoder.h index aac79f31..ee7086c5 100644 --- a/sys/vdpau/gstvdpmpegdecoder.h +++ b/sys/vdpau/gstvdpmpegdecoder.h @@ -18,8 +18,8 @@ * Boston, MA 02111-1307, USA. */ -#ifndef __GST_VDPAU_MPEG_DECODER_H__ -#define __GST_VDPAU_MPEG_DECODER_H__ +#ifndef __GST_VDP_MPEG_DECODER_H__ +#define __GST_VDP_MPEG_DECODER_H__ #include #include @@ -29,8 +29,8 @@ G_BEGIN_DECLS #define GST_TYPE_VDPAU_MPEG_DECODER (gst_vdp_mpeg_decoder_get_type()) -#define GST_VDPAU_MPEG_DECODER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VDPAU_MPEG_DECODER,GstVdpMpegDecoder)) -#define GST_VDPAU_MPEG_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VDPAU_MPEG_DECODER,GstVdpMpegDecoderClass)) +#define GST_VDP_MPEG_DECODER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VDPAU_MPEG_DECODER,GstVdpMpegDecoder)) +#define GST_VDP_MPEG_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VDPAU_MPEG_DECODER,GstVdpMpegDecoderClass)) #define GST_IS_VDPAU_MPEG_DECODER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VDPAU_MPEG_DECODER)) #define GST_IS_VDPAU_MPEG_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VDPAU_MPEG_DECODER)) @@ -64,4 +64,4 @@ GType gst_vdp_mpeg_decoder_get_type (void); G_END_DECLS -#endif /* __GST_VDPAU_MPEG_DECODER_H__ */ +#endif /* __GST_VDP_MPEG_DECODER_H__ */ diff --git a/sys/vdpau/gstvdpvideobuffer.h b/sys/vdpau/gstvdpvideobuffer.h index bbfc7af0..92a077f8 100644 --- a/sys/vdpau/gstvdpvideobuffer.h +++ b/sys/vdpau/gstvdpvideobuffer.h @@ -18,8 +18,8 @@ * Boston, MA 02111-1307, USA. */ -#ifndef _GST_VDPAU_VIDEO_BUFFER_H_ -#define _GST_VDPAU_VIDEO_BUFFER_H_ +#ifndef _GST_VDP_VIDEO_BUFFER_H_ +#define _GST_VDP_VIDEO_BUFFER_H_ #include #include @@ -33,7 +33,7 @@ typedef struct _GstVdpVideoBuffer GstVdpVideoBuffer; #define GST_TYPE_VDPAU_VIDEO_BUFFER (gst_vdp_video_buffer_get_type()) #define GST_IS_VDPAU_VIDEO_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_VDPAU_VIDEO_BUFFER)) -#define GST_VDPAU_VIDEO_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_VDPAU_VIDEO_BUFFER, GstVdpVideoBuffer)) +#define GST_VDP_VIDEO_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_VDPAU_VIDEO_BUFFER, GstVdpVideoBuffer)) struct _GstVdpVideoBuffer { GstBuffer buffer; @@ -46,7 +46,7 @@ GType gst_vdp_video_buffer_get_type (void); GstVdpVideoBuffer* gst_vdp_video_buffer_new (GstVdpDevice * device, VdpChromaType chroma_type, gint width, gint height); -#define GST_VDPAU_VIDEO_CAPS \ +#define GST_VDP_VIDEO_CAPS \ "video/x-vdpau-video, " \ "chroma-type = (int)[0,2], " \ "width = (int)[1,4096], " \ diff --git a/sys/vdpau/gstvdpvideoyuv.c b/sys/vdpau/gstvdpvideoyuv.c index 917a4edc..a1f5b6ed 100644 --- a/sys/vdpau/gstvdpvideoyuv.c +++ b/sys/vdpau/gstvdpvideoyuv.c @@ -46,7 +46,7 @@ enum static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, - GST_STATIC_CAPS (GST_VDPAU_VIDEO_CAPS)); + GST_STATIC_CAPS (GST_VDP_VIDEO_CAPS)); static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, @@ -75,9 +75,9 @@ gst_vdp_video_yuv_chain (GstPad * pad, GstBuffer * buffer) VdpVideoSurface surface; GstBuffer *outbuf = NULL; - video_yuv = GST_VDPAU_VIDEO_YUV (GST_OBJECT_PARENT (pad)); - device = GST_VDPAU_VIDEO_BUFFER (buffer)->device; - surface = GST_VDPAU_VIDEO_BUFFER (buffer)->surface; + video_yuv = GST_VDP_VIDEO_YUV (GST_OBJECT_PARENT (pad)); + device = GST_VDP_VIDEO_BUFFER (buffer)->device; + surface = GST_VDP_VIDEO_BUFFER (buffer)->surface; switch (video_yuv->format) { case GST_MAKE_FOURCC ('Y', 'V', '1', '2'): @@ -276,7 +276,7 @@ gst_vdp_video_yuv_get_caps (GstVdpVideoYUV * video_yuv, static gboolean gst_vdp_video_yuv_sink_set_caps (GstPad * pad, GstCaps * caps) { - GstVdpVideoYUV *video_yuv = GST_VDPAU_VIDEO_YUV (GST_OBJECT_PARENT (pad)); + GstVdpVideoYUV *video_yuv = GST_VDP_VIDEO_YUV (GST_OBJECT_PARENT (pad)); GstCaps *src_caps, *new_caps; GstStructure *structure; @@ -344,7 +344,7 @@ gst_vdp_video_yuv_src_getcaps (GstPad * pad) { GstVdpVideoYUV *video_yuv; - video_yuv = GST_VDPAU_VIDEO_YUV (GST_OBJECT_PARENT (pad)); + video_yuv = GST_VDP_VIDEO_YUV (GST_OBJECT_PARENT (pad)); if (video_yuv->src_caps) return gst_caps_copy (video_yuv->src_caps); diff --git a/sys/vdpau/gstvdpvideoyuv.h b/sys/vdpau/gstvdpvideoyuv.h index f2aa4c82..eb628352 100644 --- a/sys/vdpau/gstvdpvideoyuv.h +++ b/sys/vdpau/gstvdpvideoyuv.h @@ -18,8 +18,8 @@ * Boston, MA 02111-1307, USA. */ -#ifndef __GST_VDPAU_VIDEO_YUV_H__ -#define __GST_VDPAU_VIDEO_YUV_H__ +#ifndef __GST_VDP_VIDEO_YUV_H__ +#define __GST_VDP_VIDEO_YUV_H__ #include @@ -28,9 +28,9 @@ G_BEGIN_DECLS #define GST_TYPE_VDPAU_VIDEO_YUV (gst_vdp_video_yuv_get_type()) -#define GST_VDPAU_VIDEO_YUV(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VDPAU_VIDEO_YUV,GstVdpVideoYUV)) -#define GST_VDPAU_VIDEO_YUV_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VDPAU_VIDEO_YUV,GstVdpVideoYUVClass)) -#define GST_VDPAU_VIDEO_YUV_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_VDPAU_VIDEO_YUV, GstVdpVideoYUVClass)) +#define GST_VDP_VIDEO_YUV(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VDPAU_VIDEO_YUV,GstVdpVideoYUV)) +#define GST_VDP_VIDEO_YUV_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VDPAU_VIDEO_YUV,GstVdpVideoYUVClass)) +#define GST_VDP_VIDEO_YUV_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_VDPAU_VIDEO_YUV, GstVdpVideoYUVClass)) #define GST_IS_VDPAU_VIDEO_YUV(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VDPAU_VIDEO_YUV)) #define GST_IS_VDPAU_VIDEO_YUV_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VDPAU_VIDEO_YUV)) @@ -57,4 +57,4 @@ GType gst_vdp_video_yuv_get_type (void); G_END_DECLS -#endif /* __GST_VDPAU_VIDEO_YUV_H__ */ +#endif /* __GST_VDP_VIDEO_YUV_H__ */ diff --git a/sys/vdpau/gstvdpyuvvideo.c b/sys/vdpau/gstvdpyuvvideo.c index d5ed01cb..72c053e6 100644 --- a/sys/vdpau/gstvdpyuvvideo.c +++ b/sys/vdpau/gstvdpyuvvideo.c @@ -54,7 +54,7 @@ static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, - GST_STATIC_CAPS (GST_VDPAU_VIDEO_CAPS)); + GST_STATIC_CAPS (GST_VDP_VIDEO_CAPS)); #define DEBUG_INIT(bla) \ GST_DEBUG_CATEGORY_INIT (gst_vdp_yuv_video_debug, "vdpauvideoyuv", 0, "YUV to VDPAU video surface"); @@ -76,13 +76,13 @@ gst_vdp_yuv_video_chain (GstPad * pad, GstBuffer * buffer) VdpVideoSurface surface; GstBuffer *outbuf = NULL; - yuv_video = GST_VDPAU_YUV_VIDEO (GST_OBJECT_PARENT (pad)); + yuv_video = GST_VDP_YUV_VIDEO (GST_OBJECT_PARENT (pad)); device = yuv_video->device; outbuf = GST_BUFFER (gst_vdp_video_buffer_new (device, yuv_video->chroma_type, yuv_video->width, yuv_video->height)); - surface = GST_VDPAU_VIDEO_BUFFER (outbuf)->surface; + surface = GST_VDP_VIDEO_BUFFER (outbuf)->surface; switch (yuv_video->format) { case GST_MAKE_FOURCC ('Y', 'V', '1', '2'): @@ -267,7 +267,7 @@ error: static gboolean gst_vdp_yuv_video_sink_setcaps (GstPad * pad, GstCaps * caps) { - GstVdpYUVVideo *yuv_video = GST_VDPAU_YUV_VIDEO (GST_OBJECT_PARENT (pad)); + GstVdpYUVVideo *yuv_video = GST_VDP_YUV_VIDEO (GST_OBJECT_PARENT (pad)); GstStructure *structure; guint32 fourcc; @@ -337,7 +337,7 @@ gst_vdp_yuv_video_sink_getcaps (GstPad * pad) { GstVdpYUVVideo *yuv_video; - yuv_video = GST_VDPAU_YUV_VIDEO (GST_OBJECT_PARENT (pad)); + yuv_video = GST_VDP_YUV_VIDEO (GST_OBJECT_PARENT (pad)); if (yuv_video->sink_caps) return gst_caps_copy (yuv_video->sink_caps); @@ -350,7 +350,7 @@ gst_vdp_yuv_video_change_state (GstElement * element, GstStateChange transition) { GstVdpYUVVideo *yuv_video; - yuv_video = GST_VDPAU_YUV_VIDEO (element); + yuv_video = GST_VDP_YUV_VIDEO (element); switch (transition) { case GST_STATE_CHANGE_NULL_TO_READY: @@ -446,7 +446,7 @@ static void gst_vdp_yuv_video_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { - GstVdpYUVVideo *yuv_video = GST_VDPAU_YUV_VIDEO (object); + GstVdpYUVVideo *yuv_video = GST_VDP_YUV_VIDEO (object); switch (prop_id) { case PROP_DISPLAY: @@ -463,7 +463,7 @@ static void gst_vdp_yuv_video_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { - GstVdpYUVVideo *yuv_video = GST_VDPAU_YUV_VIDEO (object); + GstVdpYUVVideo *yuv_video = GST_VDP_YUV_VIDEO (object); switch (prop_id) { case PROP_DISPLAY: diff --git a/sys/vdpau/gstvdpyuvvideo.h b/sys/vdpau/gstvdpyuvvideo.h index fbb7d96d..0c063929 100644 --- a/sys/vdpau/gstvdpyuvvideo.h +++ b/sys/vdpau/gstvdpyuvvideo.h @@ -18,8 +18,8 @@ * Boston, MA 02111-1307, USA. */ -#ifndef __GST_VDPAU_YUV_VIDEO_H__ -#define __GST_VDPAU_YUV_VIDEO_H__ +#ifndef __GST_VDP_YUV_VIDEO_H__ +#define __GST_VDP_YUV_VIDEO_H__ #include @@ -28,9 +28,9 @@ G_BEGIN_DECLS #define GST_TYPE_VDPAU_YUV_VIDEO (gst_vdp_yuv_video_get_type()) -#define GST_VDPAU_YUV_VIDEO(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VDPAU_YUV_VIDEO,GstVdpYUVVideo)) -#define GST_VDPAU_YUV_VIDEO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VDPAU_YUV_VIDEO,GstVdpYUVVideoClass)) -#define GST_VDPAU_YUV_VIDEO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_VDPAU_YUV_VIDEO, GstVdpYUVVideoClass)) +#define GST_VDP_YUV_VIDEO(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VDPAU_YUV_VIDEO,GstVdpYUVVideo)) +#define GST_VDP_YUV_VIDEO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VDPAU_YUV_VIDEO,GstVdpYUVVideoClass)) +#define GST_VDP_YUV_VIDEO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_VDPAU_YUV_VIDEO, GstVdpYUVVideoClass)) #define GST_IS_VDPAU_YUV_VIDEO(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VDPAU_YUV_VIDEO)) #define GST_IS_VDPAU_YUV_VIDEO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VDPAU_YUV_VIDEO)) @@ -59,4 +59,4 @@ GType gst_vdp_yuv_video_get_type (void); G_END_DECLS -#endif /* __GST_VDPAU_YUV_VIDEO_H__ */ +#endif /* __GST_VDP_YUV_VIDEO_H__ */ -- cgit v1.2.1 From 2d996a3ff49757e299ec6218604f19e499ac0782 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Mon, 27 Apr 2009 15:12:26 +0200 Subject: vdpaumpegdec: clear the adapter when we reset the decoder --- sys/vdpau/gstvdpmpegdecoder.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sys/vdpau/gstvdpmpegdecoder.c b/sys/vdpau/gstvdpmpegdecoder.c index f13db895..5cc913b0 100644 --- a/sys/vdpau/gstvdpmpegdecoder.c +++ b/sys/vdpau/gstvdpmpegdecoder.c @@ -380,6 +380,8 @@ gst_vdp_mpeg_decoder_reset (GstVdpMpegDecoder * mpeg_dec) gst_buffer_unref (mpeg_dec->f_buffer); gst_vdp_mpeg_decoder_init_info (&mpeg_dec->vdp_info); + + gst_adapter_clear (mpeg_dec->adapter); } static GstFlowReturn -- cgit v1.2.1 From 2eb479f825c3d1f02f9b91cc3f1964945be5d647 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Mon, 27 Apr 2009 18:34:53 +0200 Subject: vdpaumpegdec: if available use incoming buffer timestamp as output timestamp --- sys/vdpau/gstvdpdecoder.c | 14 +++++--------- sys/vdpau/gstvdpmpegdecoder.c | 11 ++++++++--- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/sys/vdpau/gstvdpdecoder.c b/sys/vdpau/gstvdpdecoder.c index 3f71ab40..b3faf837 100644 --- a/sys/vdpau/gstvdpdecoder.c +++ b/sys/vdpau/gstvdpdecoder.c @@ -64,15 +64,11 @@ GstFlowReturn gst_vdp_decoder_push_video_buffer (GstVdpDecoder * dec, GstVdpVideoBuffer * buffer) { - GST_BUFFER_TIMESTAMP (buffer) = - gst_util_uint64_scale_int (GST_SECOND * dec->frame_nr, - dec->framerate_denominator, dec->framerate_numerator); - GST_BUFFER_DURATION (buffer) = - gst_util_uint64_scale_int (GST_SECOND, dec->framerate_denominator, - dec->framerate_numerator); - GST_BUFFER_OFFSET (buffer) = dec->frame_nr; - dec->frame_nr++; - GST_BUFFER_OFFSET_END (buffer) = dec->frame_nr; + if (GST_BUFFER_TIMESTAMP (buffer) == GST_CLOCK_TIME_NONE) { + GST_BUFFER_TIMESTAMP (buffer) = + gst_util_uint64_scale_int (GST_SECOND * dec->frame_nr, + dec->framerate_denominator, dec->framerate_numerator); + } gst_buffer_set_caps (GST_BUFFER (buffer), GST_PAD_CAPS (dec->src)); return gst_pad_push (dec->src, GST_BUFFER (buffer)); diff --git a/sys/vdpau/gstvdpmpegdecoder.c b/sys/vdpau/gstvdpmpegdecoder.c index 5cc913b0..5b461268 100644 --- a/sys/vdpau/gstvdpmpegdecoder.c +++ b/sys/vdpau/gstvdpmpegdecoder.c @@ -139,7 +139,8 @@ typedef struct } GstVdpBFrame; static GstFlowReturn -gst_vdp_mpeg_decoder_decode (GstVdpMpegDecoder * mpeg_dec) +gst_vdp_mpeg_decoder_decode (GstVdpMpegDecoder * mpeg_dec, + GstClockTime timestamp) { GstVdpDecoder *dec; GstBuffer *buffer; @@ -167,6 +168,7 @@ gst_vdp_mpeg_decoder_decode (GstVdpMpegDecoder * mpeg_dec) b_frame = g_slice_new (GstVdpBFrame); + GST_BUFFER_TIMESTAMP (buffer) = timestamp; b_frame->buffer = buffer; memcpy (&b_frame->vdp_info, &mpeg_dec->vdp_info, sizeof (VdpPictureInfoMPEG1Or2)); @@ -180,6 +182,7 @@ gst_vdp_mpeg_decoder_decode (GstVdpMpegDecoder * mpeg_dec) outbuf = gst_vdp_video_buffer_new (dec->device, VDP_CHROMA_TYPE_420, dec->width, dec->height); + GST_BUFFER_TIMESTAMP (outbuf) = timestamp; surface = outbuf->surface; device = dec->device; @@ -216,6 +219,7 @@ gst_vdp_mpeg_decoder_decode (GstVdpMpegDecoder * mpeg_dec) b_outbuf = gst_vdp_video_buffer_new (dec->device, VDP_CHROMA_TYPE_420, dec->width, dec->height); + GST_BUFFER_TIMESTAMP (b_outbuf) = GST_BUFFER_TIMESTAMP (b_frame->buffer); b_frame->vdp_info.backward_reference = surface; vbit[0].struct_version = VDP_BITSTREAM_BUFFER_VERSION; @@ -428,8 +432,6 @@ gst_vdp_mpeg_decoder_chain (GstPad * pad, GstBuffer * buffer) switch (data[0]) { case MPEG_PACKET_PICTURE: GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_PICTURE"); - if (mpeg_dec->vdp_info.slice_count > 0) - ret = gst_vdp_mpeg_decoder_decode (mpeg_dec); gst_vdp_mpeg_decoder_parse_picture (mpeg_dec, packet_start, packet_end); break; @@ -464,6 +466,9 @@ gst_vdp_mpeg_decoder_chain (GstPad * pad, GstBuffer * buffer) } } + if (mpeg_dec->vdp_info.slice_count > 0) + ret = gst_vdp_mpeg_decoder_decode (mpeg_dec, GST_BUFFER_TIMESTAMP (buffer)); + return ret; } -- cgit v1.2.1 From a94f5fe520260991206850f13bc4df578ccbbc97 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Mon, 27 Apr 2009 20:15:07 +0200 Subject: vdpau: use g_once_init_enter instead of g_once --- sys/vdpau/gstvdpdevice.c | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/sys/vdpau/gstvdpdevice.c b/sys/vdpau/gstvdpdevice.c index 1dc42d68..d7a074a7 100644 --- a/sys/vdpau/gstvdpdevice.c +++ b/sys/vdpau/gstvdpdevice.c @@ -53,7 +53,6 @@ gst_vdp_device_finalize (GObject * object) g_free (device->display_name); G_OBJECT_CLASS (gst_vdp_device_parent_class)->finalize (object); - } static void @@ -234,21 +233,18 @@ device_destroyed_cb (gpointer data, GObject * object) } } -static gpointer -create_devices_hash (gpointer data) -{ - return g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); -} - GstVdpDevice * gst_vdp_get_device (const gchar * display_name) { - static GOnce my_once = G_ONCE_INIT; - GHashTable *devices_hash; + static gsize once = 0; + static GHashTable *devices_hash; GstVdpDevice *device; - g_once (&my_once, create_devices_hash, NULL); - devices_hash = my_once.retval; + if (g_once_init_enter (&once)) { + devices_hash = + g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); + g_once_init_leave (&once, 1); + } if (display_name) device = g_hash_table_lookup (devices_hash, display_name); -- cgit v1.2.1 From f16aa7271ef571bd260c2a820d0ee0af09c94d11 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Mon, 27 Apr 2009 20:18:52 +0200 Subject: vdpau: small fixes init create GstVdpDevice on GST_STATE_CHANGE_READY_TO_PAUSED instead of on GST_STATE_CHANGE_NULL_TO READY add back incrementing of frame_nr --- sys/vdpau/gstvdpdecoder.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sys/vdpau/gstvdpdecoder.c b/sys/vdpau/gstvdpdecoder.c index b3faf837..8b79dff0 100644 --- a/sys/vdpau/gstvdpdecoder.c +++ b/sys/vdpau/gstvdpdecoder.c @@ -68,6 +68,7 @@ gst_vdp_decoder_push_video_buffer (GstVdpDecoder * dec, GST_BUFFER_TIMESTAMP (buffer) = gst_util_uint64_scale_int (GST_SECOND * dec->frame_nr, dec->framerate_denominator, dec->framerate_numerator); + dec->frame_nr++; } gst_buffer_set_caps (GST_BUFFER (buffer), GST_PAD_CAPS (dec->src)); @@ -82,10 +83,10 @@ gst_vdp_decoder_change_state (GstElement * element, GstStateChange transition) dec = GST_VDP_DECODER (element); switch (transition) { - case GST_STATE_CHANGE_NULL_TO_READY: + case GST_STATE_CHANGE_READY_TO_PAUSED: dec->device = gst_vdp_get_device (dec->display_name); break; - case GST_STATE_CHANGE_READY_TO_NULL: + case GST_STATE_CHANGE_PAUSED_TO_READY: g_object_unref (dec->device); dec->device = NULL; break; -- cgit v1.2.1 From 612a46a565851760db417d2d1399795d7bcb3193 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Mon, 27 Apr 2009 20:21:44 +0200 Subject: vdpau: close display on finalize --- sys/vdpau/gstvdpdevice.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sys/vdpau/gstvdpdevice.c b/sys/vdpau/gstvdpdevice.c index d7a074a7..84fe8922 100644 --- a/sys/vdpau/gstvdpdevice.c +++ b/sys/vdpau/gstvdpdevice.c @@ -50,6 +50,7 @@ gst_vdp_device_finalize (GObject * object) GstVdpDevice *device = (GstVdpDevice *) object; device->vdp_device_destroy (device->device); + XCloseDisplay (device->display); g_free (device->display_name); G_OBJECT_CLASS (gst_vdp_device_parent_class)->finalize (object); -- cgit v1.2.1 From fb70c1e7b5b187f329261b3a26717e621b39de71 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Mon, 27 Apr 2009 20:45:11 +0200 Subject: vdpau: fix error where we forgot to pass a trailing NULL to g_object_new --- sys/vdpau/gstvdpdevice.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/vdpau/gstvdpdevice.c b/sys/vdpau/gstvdpdevice.c index 84fe8922..c80b8ac7 100644 --- a/sys/vdpau/gstvdpdevice.c +++ b/sys/vdpau/gstvdpdevice.c @@ -213,7 +213,7 @@ gst_vdp_device_new (const gchar * display_name) { GstVdpDevice *device; - device = g_object_new (GST_TYPE_VDPAU_DEVICE, "display", display_name); + device = g_object_new (GST_TYPE_VDPAU_DEVICE, "display", display_name, NULL); return device; } -- cgit v1.2.1 From e737b9a916d8641b6ac0cc6ea8fd4f3326b9d004 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Mon, 27 Apr 2009 20:50:11 +0200 Subject: vdpaumpegdec: destroy the VdpDecoder and reset the decoder on state change --- sys/vdpau/gstvdpdecoder.c | 27 --------------------------- sys/vdpau/gstvdpmpegdecoder.c | 38 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 27 deletions(-) diff --git a/sys/vdpau/gstvdpdecoder.c b/sys/vdpau/gstvdpdecoder.c index 8b79dff0..7aca6c2f 100644 --- a/sys/vdpau/gstvdpdecoder.c +++ b/sys/vdpau/gstvdpdecoder.c @@ -75,28 +75,6 @@ gst_vdp_decoder_push_video_buffer (GstVdpDecoder * dec, return gst_pad_push (dec->src, GST_BUFFER (buffer)); } -static GstStateChangeReturn -gst_vdp_decoder_change_state (GstElement * element, GstStateChange transition) -{ - GstVdpDecoder *dec; - - dec = GST_VDP_DECODER (element); - - switch (transition) { - case GST_STATE_CHANGE_READY_TO_PAUSED: - dec->device = gst_vdp_get_device (dec->display_name); - break; - case GST_STATE_CHANGE_PAUSED_TO_READY: - g_object_unref (dec->device); - dec->device = NULL; - break; - default: - break; - } - - return GST_STATE_CHANGE_SUCCESS; -} - static gboolean gst_vdp_decoder_sink_set_caps (GstPad * pad, GstCaps * caps) { @@ -182,8 +160,6 @@ gst_vdp_decoder_class_init (GstVdpDecoderClass * klass) g_object_class_install_property (gobject_class, PROP_DISPLAY, g_param_spec_string ("display", "Display", "X Display name", NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); - - gstelement_class->change_state = gst_vdp_decoder_change_state; } static void @@ -214,9 +190,6 @@ gst_vdp_decoder_finalize (GObject * object) { GstVdpDecoder *dec = (GstVdpDecoder *) object; - if (dec->device) - g_object_unref (dec->device); - g_free (dec->display_name); } diff --git a/sys/vdpau/gstvdpmpegdecoder.c b/sys/vdpau/gstvdpmpegdecoder.c index 5b461268..1f15feaf 100644 --- a/sys/vdpau/gstvdpmpegdecoder.c +++ b/sys/vdpau/gstvdpmpegdecoder.c @@ -120,6 +120,12 @@ gst_vdp_mpeg_decoder_set_caps (GstVdpDecoder * dec, GstCaps * caps) &hdr.non_intra_quantizer_matrix, 64); device = dec->device; + + if (mpeg_dec->decoder != VDP_INVALID_HANDLE) { + device->vdp_decoder_destroy (mpeg_dec->decoder); + mpeg_dec->decoder = VDP_INVALID_HANDLE; + } + status = device->vdp_decoder_create (device->device, profile, dec->width, dec->height, 2, &mpeg_dec->decoder); if (status != VDP_STATUS_OK) { @@ -499,6 +505,36 @@ gst_vdp_mpeg_decoder_sink_event (GstPad * pad, GstEvent * event) return res; } +static GstStateChangeReturn +gst_vdp_mpeg_decoder_change_state (GstElement * element, + GstStateChange transition) +{ + GstVdpMpegDecoder *mpeg_dec; + GstVdpDecoder *dec; + + mpeg_dec = GST_VDP_MPEG_DECODER (element); + dec = GST_VDP_DECODER (mpeg_dec); + + switch (transition) { + case GST_STATE_CHANGE_READY_TO_PAUSED: + dec->device = gst_vdp_get_device (dec->display_name); + break; + case GST_STATE_CHANGE_PAUSED_TO_READY: + gst_vdp_mpeg_decoder_reset (mpeg_dec); + + dec->device->vdp_decoder_destroy (mpeg_dec->decoder); + mpeg_dec->decoder = VDP_INVALID_HANDLE; + + g_object_unref (dec->device); + dec->device = NULL; + break; + default: + break; + } + + return GST_STATE_CHANGE_SUCCESS; +} + /* GObject vmethod implementations */ static void @@ -533,6 +569,8 @@ gst_vdp_mpeg_decoder_class_init (GstVdpMpegDecoderClass * klass) gobject_class->get_property = gst_vdp_mpeg_decoder_get_property; vdpaudec_class->set_caps = gst_vdp_mpeg_decoder_set_caps; + + gstelement_class->change_state = gst_vdp_mpeg_decoder_change_state; } static void -- cgit v1.2.1 From 66231a619a2963551102a66c6afe177b8cd0491f Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Mon, 27 Apr 2009 20:57:12 +0200 Subject: vdpau: set vdpauvideoyuv and vdpauyuvvideo to GST_RANK_PRIMARY --- sys/vdpau/gstvdp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/vdpau/gstvdp.c b/sys/vdpau/gstvdp.c index b18c8a02..27a96a82 100644 --- a/sys/vdpau/gstvdp.c +++ b/sys/vdpau/gstvdp.c @@ -15,9 +15,9 @@ vdpau_init (GstPlugin * vdpau_plugin) gst_element_register (vdpau_plugin, "vdpaumpegdec", GST_RANK_NONE, GST_TYPE_VDPAU_MPEG_DECODER); gst_element_register (vdpau_plugin, "vdpauvideoyuv", - GST_RANK_NONE, GST_TYPE_VDPAU_VIDEO_YUV); + GST_RANK_PRIMARY, GST_TYPE_VDPAU_VIDEO_YUV); gst_element_register (vdpau_plugin, "vdpauyuvvideo", - GST_RANK_NONE, GST_TYPE_VDPAU_YUV_VIDEO); + GST_RANK_PRIMARY, GST_TYPE_VDPAU_YUV_VIDEO); return TRUE; } -- cgit v1.2.1 From 3a7a2af1faf00ec3c2cc47fb03dfc01c9dab9eed Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Mon, 27 Apr 2009 21:30:59 +0200 Subject: vdpaumpegdec: drop frames if we haven't got an I_FRAME yet --- sys/vdpau/gstvdpmpegdecoder.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/sys/vdpau/gstvdpmpegdecoder.c b/sys/vdpau/gstvdpmpegdecoder.c index 1f15feaf..1a8402e4 100644 --- a/sys/vdpau/gstvdpmpegdecoder.c +++ b/sys/vdpau/gstvdpmpegdecoder.c @@ -325,10 +325,14 @@ gst_vdp_mpeg_decoder_parse_picture (GstVdpMpegDecoder * mpeg_dec, mpeg_dec->vdp_info.picture_coding_type = pic_hdr.pic_type; - if (pic_hdr.pic_type == I_FRAME && - mpeg_dec->vdp_info.forward_reference != VDP_INVALID_HANDLE) { - gst_buffer_unref (mpeg_dec->f_buffer); - mpeg_dec->vdp_info.forward_reference = VDP_INVALID_HANDLE; + if (pic_hdr.pic_type == I_FRAME) { + if (mpeg_dec->vdp_info.forward_reference != VDP_INVALID_HANDLE) { + gst_buffer_unref (mpeg_dec->f_buffer); + mpeg_dec->vdp_info.forward_reference = VDP_INVALID_HANDLE; + } + } else if (mpeg_dec->vdp_info.forward_reference == VDP_INVALID_HANDLE) { + GST_DEBUG_OBJECT (mpeg_dec, "Drop frame since we've got no I_FRAME yet"); + return FALSE; } if (mpeg_dec->version == 1) { @@ -439,7 +443,9 @@ gst_vdp_mpeg_decoder_chain (GstPad * pad, GstBuffer * buffer) case MPEG_PACKET_PICTURE: GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_PICTURE"); - gst_vdp_mpeg_decoder_parse_picture (mpeg_dec, packet_start, packet_end); + if (!gst_vdp_mpeg_decoder_parse_picture (mpeg_dec, packet_start, + packet_end)) + return GST_FLOW_OK; break; case MPEG_PACKET_SEQUENCE: GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_SEQUENCE"); -- cgit v1.2.1 From b8a79867754e5ac7fcd66b0172db675297554451 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Thu, 30 Apr 2009 21:58:01 +0200 Subject: vdpaumpegdec: set full_pel_forward_vector to 0 when pic_type == P_FRAME --- sys/vdpau/mpegutil.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sys/vdpau/mpegutil.c b/sys/vdpau/mpegutil.c index 6f59b841..08ae5c53 100644 --- a/sys/vdpau/mpegutil.c +++ b/sys/vdpau/mpegutil.c @@ -301,7 +301,8 @@ mpeg_util_parse_picture_hdr (MPEGPictureHdr * hdr, guint8 * data, guint8 * end) if (hdr->pic_type == B_FRAME) { hdr->full_pel_backward_vector = read_bits (data + 4, 1, 1); hdr->f_code[1][0] = hdr->f_code[1][1] = read_bits (data + 4, 2, 3); - } + } else + hdr->full_pel_backward_vector = 0; } else { hdr->full_pel_forward_vector = 0; hdr->full_pel_backward_vector = 0; -- cgit v1.2.1 From 6b05d01898b44cf4d4081df6be34eb69721967b1 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Sun, 3 May 2009 21:52:49 +0200 Subject: vdpaumpegdec: the B_FRAME decoding was completely wrong, fix it the buffers don't come in output order so fix the decoder to handle this add new gst_vdp_video_buffer_add_reference method to GstVdpVideoBuffer to be able to keep buffers alive. Ie. a B_FRAME need to have both the forward reference and the backward reference alive during it's lifetime. add mutex to protect for threadsafety issues when we reset the decoder in FLUSH_STOP --- sys/vdpau/gstvdpmpegdecoder.c | 143 ++++++++++++++++-------------------------- sys/vdpau/gstvdpmpegdecoder.h | 6 +- sys/vdpau/gstvdpvideobuffer.c | 78 +++++++++++++++-------- sys/vdpau/gstvdpvideobuffer.h | 4 ++ 4 files changed, 113 insertions(+), 118 deletions(-) diff --git a/sys/vdpau/gstvdpmpegdecoder.c b/sys/vdpau/gstvdpmpegdecoder.c index 1a8402e4..413eefd4 100644 --- a/sys/vdpau/gstvdpmpegdecoder.c +++ b/sys/vdpau/gstvdpmpegdecoder.c @@ -155,40 +155,41 @@ gst_vdp_mpeg_decoder_decode (GstVdpMpegDecoder * mpeg_dec, GstVdpDevice *device; VdpBitstreamBuffer vbit[1]; VdpStatus status; - GstFlowReturn ret; dec = GST_VDP_DECODER (mpeg_dec); buffer = gst_adapter_take_buffer (mpeg_dec->adapter, gst_adapter_available (mpeg_dec->adapter)); - /* if the frame is a B_FRAME we store it for future decoding */ - if (mpeg_dec->vdp_info.picture_coding_type == B_FRAME) { - GstVdpBFrame *b_frame; - - if (mpeg_dec->broken_gop) { - gst_buffer_unref (buffer); - mpeg_dec->broken_gop = FALSE; - return GST_FLOW_OK; + if (mpeg_dec->vdp_info.picture_coding_type != B_FRAME) { + if (mpeg_dec->vdp_info.backward_reference != VDP_INVALID_HANDLE) { + GST_BUFFER_TIMESTAMP (mpeg_dec->b_buffer) = timestamp; + gst_buffer_ref (mpeg_dec->b_buffer); + gst_vdp_decoder_push_video_buffer (dec, + GST_VDP_VIDEO_BUFFER (mpeg_dec->b_buffer)); } - b_frame = g_slice_new (GstVdpBFrame); - - GST_BUFFER_TIMESTAMP (buffer) = timestamp; - b_frame->buffer = buffer; - memcpy (&b_frame->vdp_info, &mpeg_dec->vdp_info, - sizeof (VdpPictureInfoMPEG1Or2)); - - mpeg_dec->b_frames = g_slist_append (mpeg_dec->b_frames, b_frame); + if (mpeg_dec->vdp_info.forward_reference != VDP_INVALID_HANDLE) { + gst_buffer_unref (mpeg_dec->f_buffer); + mpeg_dec->vdp_info.forward_reference = VDP_INVALID_HANDLE; + } - mpeg_dec->vdp_info.slice_count = 0; + mpeg_dec->vdp_info.forward_reference = + mpeg_dec->vdp_info.backward_reference; + mpeg_dec->f_buffer = mpeg_dec->b_buffer; - return GST_FLOW_OK; + mpeg_dec->vdp_info.backward_reference = VDP_INVALID_HANDLE; } outbuf = gst_vdp_video_buffer_new (dec->device, VDP_CHROMA_TYPE_420, dec->width, dec->height); - GST_BUFFER_TIMESTAMP (outbuf) = timestamp; + if (mpeg_dec->vdp_info.forward_reference != VDP_INVALID_HANDLE) + gst_vdp_video_buffer_add_reference (outbuf, + GST_VDP_VIDEO_BUFFER (mpeg_dec->f_buffer)); + if (mpeg_dec->vdp_info.backward_reference != VDP_INVALID_HANDLE) + gst_vdp_video_buffer_add_reference (outbuf, + GST_VDP_VIDEO_BUFFER (mpeg_dec->b_buffer)); + surface = outbuf->surface; device = dec->device; @@ -213,54 +214,15 @@ gst_vdp_mpeg_decoder_decode (GstVdpMpegDecoder * mpeg_dec, return GST_FLOW_ERROR; } - /* if we have stored away some B_FRAMEs we can now decode them */ - if (mpeg_dec->b_frames) { - GSList *iter; - - for (iter = mpeg_dec->b_frames; iter; iter = g_slist_next (iter)) { - GstVdpBFrame *b_frame; - GstVdpVideoBuffer *b_outbuf; - - b_frame = (GstVdpBFrame *) iter->data; - - b_outbuf = gst_vdp_video_buffer_new (dec->device, VDP_CHROMA_TYPE_420, - dec->width, dec->height); - GST_BUFFER_TIMESTAMP (b_outbuf) = GST_BUFFER_TIMESTAMP (b_frame->buffer); - - b_frame->vdp_info.backward_reference = surface; - vbit[0].struct_version = VDP_BITSTREAM_BUFFER_VERSION; - vbit[0].bitstream = GST_BUFFER_DATA (b_frame->buffer); - vbit[0].bitstream_bytes = GST_BUFFER_SIZE (b_frame->buffer); - - status = device->vdp_decoder_render (mpeg_dec->decoder, b_outbuf->surface, - (VdpPictureInfo *) & b_frame->vdp_info, 1, vbit); - gst_buffer_unref (b_frame->buffer); - g_slice_free (GstVdpBFrame, b_frame); - - if (status != VDP_STATUS_OK) { - GST_ELEMENT_ERROR (mpeg_dec, RESOURCE, READ, - ("Could not decode B_FRAME"), - ("Error returned from vdpau was: %s", - device->vdp_get_error_string (status))); - } - - gst_vdp_decoder_push_video_buffer (GST_VDP_DECODER (mpeg_dec), b_outbuf); - } - g_slist_free (mpeg_dec->b_frames); - mpeg_dec->b_frames = NULL; + if (mpeg_dec->vdp_info.picture_coding_type == B_FRAME) { + GST_BUFFER_TIMESTAMP (outbuf) = timestamp; + gst_vdp_decoder_push_video_buffer (dec, GST_VDP_VIDEO_BUFFER (outbuf)); + } else { + mpeg_dec->vdp_info.backward_reference = surface; + mpeg_dec->b_buffer = GST_BUFFER (outbuf); } - gst_buffer_ref (GST_BUFFER (outbuf)); - - ret = gst_vdp_decoder_push_video_buffer (GST_VDP_DECODER (mpeg_dec), outbuf); - - if (mpeg_dec->vdp_info.forward_reference != VDP_INVALID_HANDLE) - gst_buffer_unref (mpeg_dec->f_buffer); - - mpeg_dec->vdp_info.forward_reference = surface; - mpeg_dec->f_buffer = GST_BUFFER (outbuf); - - return ret; + return GST_FLOW_OK; } static gboolean @@ -323,18 +285,21 @@ gst_vdp_mpeg_decoder_parse_picture (GstVdpMpegDecoder * mpeg_dec, if (!mpeg_util_parse_picture_hdr (&pic_hdr, data, end)) return FALSE; - mpeg_dec->vdp_info.picture_coding_type = pic_hdr.pic_type; - - if (pic_hdr.pic_type == I_FRAME) { - if (mpeg_dec->vdp_info.forward_reference != VDP_INVALID_HANDLE) { - gst_buffer_unref (mpeg_dec->f_buffer); - mpeg_dec->vdp_info.forward_reference = VDP_INVALID_HANDLE; - } - } else if (mpeg_dec->vdp_info.forward_reference == VDP_INVALID_HANDLE) { - GST_DEBUG_OBJECT (mpeg_dec, "Drop frame since we've got no I_FRAME yet"); + if (pic_hdr.pic_type != I_FRAME + && mpeg_dec->vdp_info.backward_reference == VDP_INVALID_HANDLE) { + GST_DEBUG_OBJECT (mpeg_dec, + "Drop frame since we haven't got an I_FRAME yet"); + return FALSE; + } + if (pic_hdr.pic_type == B_FRAME + && mpeg_dec->vdp_info.forward_reference == VDP_INVALID_HANDLE) { + GST_DEBUG_OBJECT (mpeg_dec, + "Drop frame since we haven't got two non B_FRAMES yet"); return FALSE; } + mpeg_dec->vdp_info.picture_coding_type = pic_hdr.pic_type; + if (mpeg_dec->version == 1) { mpeg_dec->vdp_info.full_pel_forward_vector = pic_hdr.full_pel_forward_vector; @@ -379,19 +344,10 @@ gst_vdp_mpeg_decoder_parse_quant_matrix (GstVdpMpegDecoder * mpeg_dec, static void gst_vdp_mpeg_decoder_reset (GstVdpMpegDecoder * mpeg_dec) { - GSList *iter; - - for (iter = mpeg_dec->b_frames; iter; iter = iter->next) { - GstVdpBFrame *b_frame = (GstVdpBFrame *) iter->data; - - gst_buffer_unref (b_frame->buffer); - g_slice_free (GstVdpBFrame, b_frame); - } - g_slist_free (mpeg_dec->b_frames); - mpeg_dec->b_frames = NULL; - if (mpeg_dec->vdp_info.forward_reference != VDP_INVALID_HANDLE) gst_buffer_unref (mpeg_dec->f_buffer); + if (mpeg_dec->vdp_info.backward_reference != VDP_INVALID_HANDLE) + gst_buffer_unref (mpeg_dec->b_buffer); gst_vdp_mpeg_decoder_init_info (&mpeg_dec->vdp_info); @@ -408,9 +364,12 @@ gst_vdp_mpeg_decoder_chain (GstPad * pad, GstBuffer * buffer) mpeg_dec = GST_VDP_MPEG_DECODER (GST_OBJECT_PARENT (pad)); + g_mutex_lock (mpeg_dec->mutex); + if (G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT))) { GST_DEBUG_OBJECT (mpeg_dec, "Received discont buffer"); gst_vdp_mpeg_decoder_reset (mpeg_dec); + g_mutex_unlock (mpeg_dec->mutex); return GST_FLOW_OK; } @@ -444,8 +403,10 @@ gst_vdp_mpeg_decoder_chain (GstPad * pad, GstBuffer * buffer) GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_PICTURE"); if (!gst_vdp_mpeg_decoder_parse_picture (mpeg_dec, packet_start, - packet_end)) + packet_end)) { + g_mutex_unlock (mpeg_dec->mutex); return GST_FLOW_OK; + } break; case MPEG_PACKET_SEQUENCE: GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_SEQUENCE"); @@ -481,6 +442,8 @@ gst_vdp_mpeg_decoder_chain (GstPad * pad, GstBuffer * buffer) if (mpeg_dec->vdp_info.slice_count > 0) ret = gst_vdp_mpeg_decoder_decode (mpeg_dec, GST_BUFFER_TIMESTAMP (buffer)); + g_mutex_unlock (mpeg_dec->mutex); + return ret; } @@ -499,7 +462,10 @@ gst_vdp_mpeg_decoder_sink_event (GstPad * pad, GstEvent * event) { GST_DEBUG_OBJECT (mpeg_dec, "flush stop"); + g_mutex_lock (mpeg_dec->mutex); gst_vdp_mpeg_decoder_reset (mpeg_dec); + g_mutex_unlock (mpeg_dec->mutex); + res = gst_pad_push_event (dec->src, event); break; @@ -607,7 +573,7 @@ gst_vdp_mpeg_decoder_init (GstVdpMpegDecoder * mpeg_dec, mpeg_dec->decoder = VDP_INVALID_HANDLE; gst_vdp_mpeg_decoder_init_info (&mpeg_dec->vdp_info); - mpeg_dec->b_frames = NULL; + mpeg_dec->mutex = g_mutex_new (); mpeg_dec->broken_gop = FALSE; @@ -622,6 +588,7 @@ gst_vdp_mpeg_decoder_finalize (GObject * object) { GstVdpMpegDecoder *mpeg_dec = (GstVdpMpegDecoder *) object; + g_mutex_free (mpeg_dec->mutex); g_object_unref (mpeg_dec->adapter); } diff --git a/sys/vdpau/gstvdpmpegdecoder.h b/sys/vdpau/gstvdpmpegdecoder.h index ee7086c5..547b0f94 100644 --- a/sys/vdpau/gstvdpmpegdecoder.h +++ b/sys/vdpau/gstvdpmpegdecoder.h @@ -46,10 +46,10 @@ struct _GstVdpMpegDecoder VdpDecoder decoder; VdpPictureInfoMPEG1Or2 vdp_info; GstBuffer *f_buffer; + GstBuffer *b_buffer; - /* holds B_FRAMES */ - GSList *b_frames; - + GMutex *mutex; + gboolean broken_gop; GstAdapter *adapter; diff --git a/sys/vdpau/gstvdpvideobuffer.c b/sys/vdpau/gstvdpvideobuffer.c index c62ac771..82f7dba7 100644 --- a/sys/vdpau/gstvdpvideobuffer.c +++ b/sys/vdpau/gstvdpvideobuffer.c @@ -24,14 +24,54 @@ #include "gstvdpvideobuffer.h" + +void +gst_vdp_video_buffer_add_reference (GstVdpVideoBuffer * buffer, + GstVdpVideoBuffer * buf) +{ + g_assert (GST_IS_VDPAU_VIDEO_BUFFER (buffer)); + g_assert (GST_IS_VDPAU_VIDEO_BUFFER (buf)); + + gst_buffer_ref (GST_BUFFER (buf)); + buffer->refs = g_slist_prepend (buffer->refs, buf); +} + +GstVdpVideoBuffer * +gst_vdp_video_buffer_new (GstVdpDevice * device, VdpChromaType chroma_type, + gint width, gint height) +{ + GstVdpVideoBuffer *buffer; + VdpStatus status; + VdpVideoSurface surface; + + status = device->vdp_video_surface_create (device->device, chroma_type, width, + height, &surface); + if (status != VDP_STATUS_OK) { + GST_ERROR ("Couldn't create a VdpVideoSurface, error returned was: %s", + device->vdp_get_error_string (status)); + return NULL; + } + + buffer = + (GstVdpVideoBuffer *) gst_mini_object_new (GST_TYPE_VDPAU_VIDEO_BUFFER); + + buffer->device = g_object_ref (device); + buffer->surface = surface; + + return buffer; +} + static GObjectClass *gst_vdp_video_buffer_parent_class; static void gst_vdp_video_buffer_finalize (GstVdpVideoBuffer * buffer) { - GstVdpDevice *device = buffer->device; + GSList *iter; + GstVdpDevice *device; VdpStatus status; + device = buffer->device; + status = device->vdp_video_surface_destroy (buffer->surface); if (status != VDP_STATUS_OK) GST_ERROR @@ -40,6 +80,14 @@ gst_vdp_video_buffer_finalize (GstVdpVideoBuffer * buffer) g_object_unref (buffer->device); + for (iter = buffer->refs; iter; iter = g_slist_next (iter)) { + GstBuffer *buf; + + buf = (GstBuffer *) (iter->data); + gst_buffer_unref (buf); + } + g_slist_free (buffer->refs); + GST_MINI_OBJECT_CLASS (gst_vdp_video_buffer_parent_class)->finalize (GST_MINI_OBJECT (buffer)); } @@ -49,6 +97,8 @@ gst_vdp_video_buffer_init (GstVdpVideoBuffer * buffer, gpointer g_class) { buffer->device = NULL; buffer->surface = VDP_INVALID_HANDLE; + + buffer->refs = NULL; } static void @@ -86,29 +136,3 @@ gst_vdp_video_buffer_get_type (void) } return _gst_vdp_video_buffer_type; } - - -GstVdpVideoBuffer * -gst_vdp_video_buffer_new (GstVdpDevice * device, VdpChromaType chroma_type, - gint width, gint height) -{ - GstVdpVideoBuffer *buffer; - VdpStatus status; - VdpVideoSurface surface; - - status = device->vdp_video_surface_create (device->device, chroma_type, width, - height, &surface); - if (status != VDP_STATUS_OK) { - GST_ERROR ("Couldn't create a VdpVideoSurface, error returned was: %s", - device->vdp_get_error_string (status)); - return NULL; - } - - buffer = - (GstVdpVideoBuffer *) gst_mini_object_new (GST_TYPE_VDPAU_VIDEO_BUFFER); - - buffer->device = g_object_ref (device); - buffer->surface = surface; - - return buffer; -} diff --git a/sys/vdpau/gstvdpvideobuffer.h b/sys/vdpau/gstvdpvideobuffer.h index 92a077f8..abc8c99e 100644 --- a/sys/vdpau/gstvdpvideobuffer.h +++ b/sys/vdpau/gstvdpvideobuffer.h @@ -40,12 +40,16 @@ struct _GstVdpVideoBuffer { GstVdpDevice *device; VdpVideoSurface surface; + + GSList *refs; }; GType gst_vdp_video_buffer_get_type (void); GstVdpVideoBuffer* gst_vdp_video_buffer_new (GstVdpDevice * device, VdpChromaType chroma_type, gint width, gint height); +void gst_vdp_video_buffer_add_reference (GstVdpVideoBuffer *buffer, GstVdpVideoBuffer *buf); + #define GST_VDP_VIDEO_CAPS \ "video/x-vdpau-video, " \ "chroma-type = (int)[0,2], " \ -- cgit v1.2.1 From de7fb2006e6bad7dba369bcd2d2fc89c965bf5f3 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Tue, 5 May 2009 08:11:03 +0200 Subject: vdpaumpegdec: hold the lock in change_state --- sys/vdpau/gstvdpmpegdecoder.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sys/vdpau/gstvdpmpegdecoder.c b/sys/vdpau/gstvdpmpegdecoder.c index 413eefd4..bf3ea423 100644 --- a/sys/vdpau/gstvdpmpegdecoder.c +++ b/sys/vdpau/gstvdpmpegdecoder.c @@ -489,9 +489,12 @@ gst_vdp_mpeg_decoder_change_state (GstElement * element, switch (transition) { case GST_STATE_CHANGE_READY_TO_PAUSED: + g_mutex_lock (mpeg_dec->mutex); dec->device = gst_vdp_get_device (dec->display_name); + g_mutex_unlock (mpeg_dec->mutex); break; case GST_STATE_CHANGE_PAUSED_TO_READY: + g_mutex_lock (mpeg_dec->mutex); gst_vdp_mpeg_decoder_reset (mpeg_dec); dec->device->vdp_decoder_destroy (mpeg_dec->decoder); @@ -499,6 +502,7 @@ gst_vdp_mpeg_decoder_change_state (GstElement * element, g_object_unref (dec->device); dec->device = NULL; + g_mutex_unlock (mpeg_dec->mutex); break; default: break; -- cgit v1.2.1 From e417b2eea0256d5a4a8355f2472e3af3777a2d0c Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Tue, 5 May 2009 16:29:24 +0200 Subject: vdpau: init "vdpaudevice" debug catoegory in gst_vdp_get_device --- sys/vdpau/gstvdpdevice.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/sys/vdpau/gstvdpdevice.c b/sys/vdpau/gstvdpdevice.c index c80b8ac7..ff8b6510 100644 --- a/sys/vdpau/gstvdpdevice.c +++ b/sys/vdpau/gstvdpdevice.c @@ -196,16 +196,12 @@ gst_vdp_device_class_init (GstVdpDeviceClass * klass) object_class->get_property = gst_vdp_device_get_property; object_class->set_property = gst_vdp_device_set_property; - g_object_class_install_property (object_class, PROP_DISPLAY, g_param_spec_string ("display", "Display", "X Display Name", "", G_PARAM_READABLE | G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)); - - GST_DEBUG_CATEGORY_INIT (gst_vdp_device_debug, "vdpaudevice", - 0, "vdpaudevice"); } GstVdpDevice * @@ -242,6 +238,8 @@ gst_vdp_get_device (const gchar * display_name) GstVdpDevice *device; if (g_once_init_enter (&once)) { + GST_DEBUG_CATEGORY_INIT (gst_vdp_device_debug, "vdpaudevice", + 0, "vdpaudevice"); devices_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); g_once_init_leave (&once, 1); -- cgit v1.2.1 From 323b563c24027d8f657c998c56458014ac97da46 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Tue, 5 May 2009 17:15:33 +0200 Subject: vdpaumpegdec: fixup state change --- sys/vdpau/gstvdpdecoder.c | 1 - sys/vdpau/gstvdpmpegdecoder.c | 14 +++++++++----- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/sys/vdpau/gstvdpdecoder.c b/sys/vdpau/gstvdpdecoder.c index 7aca6c2f..2b0c888e 100644 --- a/sys/vdpau/gstvdpdecoder.c +++ b/sys/vdpau/gstvdpdecoder.c @@ -182,7 +182,6 @@ gst_vdp_decoder_init (GstVdpDecoder * dec, GstVdpDecoderClass * klass) (GST_ELEMENT_CLASS (klass), "sink"), "sink"); gst_pad_set_setcaps_function (dec->sink, gst_vdp_decoder_sink_set_caps); gst_element_add_pad (GST_ELEMENT (dec), dec->sink); - gst_pad_set_active (dec->sink, TRUE); } static void diff --git a/sys/vdpau/gstvdpmpegdecoder.c b/sys/vdpau/gstvdpmpegdecoder.c index bf3ea423..c63b6c0d 100644 --- a/sys/vdpau/gstvdpmpegdecoder.c +++ b/sys/vdpau/gstvdpmpegdecoder.c @@ -483,18 +483,23 @@ gst_vdp_mpeg_decoder_change_state (GstElement * element, { GstVdpMpegDecoder *mpeg_dec; GstVdpDecoder *dec; + GstStateChangeReturn ret; mpeg_dec = GST_VDP_MPEG_DECODER (element); dec = GST_VDP_DECODER (mpeg_dec); switch (transition) { case GST_STATE_CHANGE_READY_TO_PAUSED: - g_mutex_lock (mpeg_dec->mutex); dec->device = gst_vdp_get_device (dec->display_name); - g_mutex_unlock (mpeg_dec->mutex); break; + default: + break; + } + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + + switch (transition) { case GST_STATE_CHANGE_PAUSED_TO_READY: - g_mutex_lock (mpeg_dec->mutex); gst_vdp_mpeg_decoder_reset (mpeg_dec); dec->device->vdp_decoder_destroy (mpeg_dec->decoder); @@ -502,13 +507,12 @@ gst_vdp_mpeg_decoder_change_state (GstElement * element, g_object_unref (dec->device); dec->device = NULL; - g_mutex_unlock (mpeg_dec->mutex); break; default: break; } - return GST_STATE_CHANGE_SUCCESS; + return ret; } /* GObject vmethod implementations */ -- cgit v1.2.1 From 824cf29cdc9399d72ce5f9ad88040cde7ce7de12 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Tue, 5 May 2009 17:20:16 +0200 Subject: vdpau: s/GST_TYPE_VDPAU/GST_TYPE_VDP/g --- sys/vdpau/gstvdpdevice.h | 12 ++++++------ sys/vdpau/gstvdpvideoyuv.h | 12 ++++++------ sys/vdpau/gstvdpyuvvideo.h | 12 ++++++------ 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/sys/vdpau/gstvdpdevice.h b/sys/vdpau/gstvdpdevice.h index 26e7fa72..70758a2d 100644 --- a/sys/vdpau/gstvdpdevice.h +++ b/sys/vdpau/gstvdpdevice.h @@ -28,12 +28,12 @@ G_BEGIN_DECLS -#define GST_TYPE_VDPAU_DEVICE (gst_vdp_device_get_type ()) -#define GST_VDP_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_VDPAU_DEVICE, GstVdpDevice)) -#define GST_VDP_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_VDPAU_DEVICE, GstVdpDeviceClass)) -#define GST_IS_VDPAU_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_VDPAU_DEVICE)) -#define GST_IS_VDPAU_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_VDPAU_DEVICE)) -#define GST_VDP_DEVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_VDPAU_DEVICE, GstVdpDeviceClass)) +#define GST_TYPE_VDP_DEVICE (gst_vdp_device_get_type ()) +#define GST_VDP_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_VDP_DEVICE, GstVdpDevice)) +#define GST_VDP_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_VDP_DEVICE, GstVdpDeviceClass)) +#define GST_IS_VDPAU_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_VDP_DEVICE)) +#define GST_IS_VDPAU_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_VDP_DEVICE)) +#define GST_VDP_DEVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_VDP_DEVICE, GstVdpDeviceClass)) typedef struct _GstVdpDeviceClass GstVdpDeviceClass; typedef struct _GstVdpDevice GstVdpDevice; diff --git a/sys/vdpau/gstvdpvideoyuv.h b/sys/vdpau/gstvdpvideoyuv.h index eb628352..07955ed8 100644 --- a/sys/vdpau/gstvdpvideoyuv.h +++ b/sys/vdpau/gstvdpvideoyuv.h @@ -27,12 +27,12 @@ G_BEGIN_DECLS -#define GST_TYPE_VDPAU_VIDEO_YUV (gst_vdp_video_yuv_get_type()) -#define GST_VDP_VIDEO_YUV(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VDPAU_VIDEO_YUV,GstVdpVideoYUV)) -#define GST_VDP_VIDEO_YUV_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VDPAU_VIDEO_YUV,GstVdpVideoYUVClass)) -#define GST_VDP_VIDEO_YUV_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_VDPAU_VIDEO_YUV, GstVdpVideoYUVClass)) -#define GST_IS_VDPAU_VIDEO_YUV(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VDPAU_VIDEO_YUV)) -#define GST_IS_VDPAU_VIDEO_YUV_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VDPAU_VIDEO_YUV)) +#define GST_TYPE_VDP_VIDEO_YUV (gst_vdp_video_yuv_get_type()) +#define GST_VDP_VIDEO_YUV(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VDP_VIDEO_YUV,GstVdpVideoYUV)) +#define GST_VDP_VIDEO_YUV_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VDP_VIDEO_YUV,GstVdpVideoYUVClass)) +#define GST_VDP_VIDEO_YUV_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_VDP_VIDEO_YUV, GstVdpVideoYUVClass)) +#define GST_IS_VDPAU_VIDEO_YUV(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VDP_VIDEO_YUV)) +#define GST_IS_VDPAU_VIDEO_YUV_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VDP_VIDEO_YUV)) typedef struct _GstVdpVideoYUV GstVdpVideoYUV; typedef struct _GstVdpVideoYUVClass GstVdpVideoYUVClass; diff --git a/sys/vdpau/gstvdpyuvvideo.h b/sys/vdpau/gstvdpyuvvideo.h index 0c063929..ba3a3b01 100644 --- a/sys/vdpau/gstvdpyuvvideo.h +++ b/sys/vdpau/gstvdpyuvvideo.h @@ -27,12 +27,12 @@ G_BEGIN_DECLS -#define GST_TYPE_VDPAU_YUV_VIDEO (gst_vdp_yuv_video_get_type()) -#define GST_VDP_YUV_VIDEO(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VDPAU_YUV_VIDEO,GstVdpYUVVideo)) -#define GST_VDP_YUV_VIDEO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VDPAU_YUV_VIDEO,GstVdpYUVVideoClass)) -#define GST_VDP_YUV_VIDEO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_VDPAU_YUV_VIDEO, GstVdpYUVVideoClass)) -#define GST_IS_VDPAU_YUV_VIDEO(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VDPAU_YUV_VIDEO)) -#define GST_IS_VDPAU_YUV_VIDEO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VDPAU_YUV_VIDEO)) +#define GST_TYPE_VDP_YUV_VIDEO (gst_vdp_yuv_video_get_type()) +#define GST_VDP_YUV_VIDEO(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VDP_YUV_VIDEO,GstVdpYUVVideo)) +#define GST_VDP_YUV_VIDEO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VDP_YUV_VIDEO,GstVdpYUVVideoClass)) +#define GST_VDP_YUV_VIDEO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_VDP_YUV_VIDEO, GstVdpYUVVideoClass)) +#define GST_IS_VDPAU_YUV_VIDEO(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VDP_YUV_VIDEO)) +#define GST_IS_VDPAU_YUV_VIDEO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VDP_YUV_VIDEO)) typedef struct _GstVdpYUVVideo GstVdpYUVVideo; typedef struct _GstVdpYUVVideoClass GstVdpYUVVideoClass; -- cgit v1.2.1 From 02884b0356edfef0db34d7acc11530673fb41db1 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Tue, 5 May 2009 17:28:19 +0200 Subject: s/GST_TYPE_VDPAU/GST_TYPE_VDP/g --- sys/vdpau/gstvdp.c | 6 +++--- sys/vdpau/gstvdpdecoder.h | 12 ++++++------ sys/vdpau/gstvdpdevice.c | 2 +- sys/vdpau/gstvdpmpegdecoder.c | 2 +- sys/vdpau/gstvdpmpegdecoder.h | 10 +++++----- sys/vdpau/gstvdpvideobuffer.c | 2 +- sys/vdpau/gstvdpvideobuffer.h | 6 +++--- 7 files changed, 20 insertions(+), 20 deletions(-) diff --git a/sys/vdpau/gstvdp.c b/sys/vdpau/gstvdp.c index 27a96a82..64ebf37e 100644 --- a/sys/vdpau/gstvdp.c +++ b/sys/vdpau/gstvdp.c @@ -13,11 +13,11 @@ static gboolean vdpau_init (GstPlugin * vdpau_plugin) { gst_element_register (vdpau_plugin, "vdpaumpegdec", - GST_RANK_NONE, GST_TYPE_VDPAU_MPEG_DECODER); + GST_RANK_NONE, GST_TYPE_VDP_MPEG_DECODER); gst_element_register (vdpau_plugin, "vdpauvideoyuv", - GST_RANK_PRIMARY, GST_TYPE_VDPAU_VIDEO_YUV); + GST_RANK_PRIMARY, GST_TYPE_VDP_VIDEO_YUV); gst_element_register (vdpau_plugin, "vdpauyuvvideo", - GST_RANK_PRIMARY, GST_TYPE_VDPAU_YUV_VIDEO); + GST_RANK_PRIMARY, GST_TYPE_VDP_YUV_VIDEO); return TRUE; } diff --git a/sys/vdpau/gstvdpdecoder.h b/sys/vdpau/gstvdpdecoder.h index dfc63fd9..ae53657c 100644 --- a/sys/vdpau/gstvdpdecoder.h +++ b/sys/vdpau/gstvdpdecoder.h @@ -28,12 +28,12 @@ G_BEGIN_DECLS -#define GST_TYPE_VDPAU_DECODER (gst_vdp_decoder_get_type()) -#define GST_VDP_DECODER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VDPAU_DECODER,GstVdpDecoder)) -#define GST_VDP_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VDPAU_DECODER,GstVdpDecoderClass)) -#define GST_VDP_DECODER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_VDPAU_DECODER, GstVdpDecoderClass)) -#define GST_IS_VDPAU_DECODER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VDPAU_DECODER)) -#define GST_IS_VDPAU_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VDPAU_DECODER)) +#define GST_TYPE_VDP_DECODER (gst_vdp_decoder_get_type()) +#define GST_VDP_DECODER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VDP_DECODER,GstVdpDecoder)) +#define GST_VDP_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VDP_DECODER,GstVdpDecoderClass)) +#define GST_VDP_DECODER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_VDP_DECODER, GstVdpDecoderClass)) +#define GST_IS_VDPAU_DECODER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VDP_DECODER)) +#define GST_IS_VDPAU_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VDP_DECODER)) typedef struct _GstVdpDecoder GstVdpDecoder; typedef struct _GstVdpDecoderClass GstVdpDecoderClass; diff --git a/sys/vdpau/gstvdpdevice.c b/sys/vdpau/gstvdpdevice.c index ff8b6510..ad771906 100644 --- a/sys/vdpau/gstvdpdevice.c +++ b/sys/vdpau/gstvdpdevice.c @@ -209,7 +209,7 @@ gst_vdp_device_new (const gchar * display_name) { GstVdpDevice *device; - device = g_object_new (GST_TYPE_VDPAU_DEVICE, "display", display_name, NULL); + device = g_object_new (GST_TYPE_VDP_DEVICE, "display", display_name, NULL); return device; } diff --git a/sys/vdpau/gstvdpmpegdecoder.c b/sys/vdpau/gstvdpmpegdecoder.c index c63b6c0d..4bcbf534 100644 --- a/sys/vdpau/gstvdpmpegdecoder.c +++ b/sys/vdpau/gstvdpmpegdecoder.c @@ -71,7 +71,7 @@ static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink", GST_DEBUG_CATEGORY_INIT (gst_vdp_mpeg_decoder_debug, "vdpaumpegdec", 0, "VDPAU powered mpeg decoder"); GST_BOILERPLATE_FULL (GstVdpMpegDecoder, gst_vdp_mpeg_decoder, - GstVdpDecoder, GST_TYPE_VDPAU_DECODER, DEBUG_INIT); + GstVdpDecoder, GST_TYPE_VDP_DECODER, DEBUG_INIT); static void gst_vdp_mpeg_decoder_init_info (VdpPictureInfoMPEG1Or2 * vdp_info); static void gst_vdp_mpeg_decoder_finalize (GObject * object); diff --git a/sys/vdpau/gstvdpmpegdecoder.h b/sys/vdpau/gstvdpmpegdecoder.h index 547b0f94..57ab66ab 100644 --- a/sys/vdpau/gstvdpmpegdecoder.h +++ b/sys/vdpau/gstvdpmpegdecoder.h @@ -28,11 +28,11 @@ G_BEGIN_DECLS -#define GST_TYPE_VDPAU_MPEG_DECODER (gst_vdp_mpeg_decoder_get_type()) -#define GST_VDP_MPEG_DECODER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VDPAU_MPEG_DECODER,GstVdpMpegDecoder)) -#define GST_VDP_MPEG_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VDPAU_MPEG_DECODER,GstVdpMpegDecoderClass)) -#define GST_IS_VDPAU_MPEG_DECODER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VDPAU_MPEG_DECODER)) -#define GST_IS_VDPAU_MPEG_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VDPAU_MPEG_DECODER)) +#define GST_TYPE_VDP_MPEG_DECODER (gst_vdp_mpeg_decoder_get_type()) +#define GST_VDP_MPEG_DECODER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VDP_MPEG_DECODER,GstVdpMpegDecoder)) +#define GST_VDP_MPEG_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VDP_MPEG_DECODER,GstVdpMpegDecoderClass)) +#define GST_IS_VDPAU_MPEG_DECODER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VDP_MPEG_DECODER)) +#define GST_IS_VDPAU_MPEG_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VDP_MPEG_DECODER)) typedef struct _GstVdpMpegDecoder GstVdpMpegDecoder; typedef struct _GstVdpMpegDecoderClass GstVdpMpegDecoderClass; diff --git a/sys/vdpau/gstvdpvideobuffer.c b/sys/vdpau/gstvdpvideobuffer.c index 82f7dba7..dac62c1b 100644 --- a/sys/vdpau/gstvdpvideobuffer.c +++ b/sys/vdpau/gstvdpvideobuffer.c @@ -53,7 +53,7 @@ gst_vdp_video_buffer_new (GstVdpDevice * device, VdpChromaType chroma_type, } buffer = - (GstVdpVideoBuffer *) gst_mini_object_new (GST_TYPE_VDPAU_VIDEO_BUFFER); + (GstVdpVideoBuffer *) gst_mini_object_new (GST_TYPE_VDP_VIDEO_BUFFER); buffer->device = g_object_ref (device); buffer->surface = surface; diff --git a/sys/vdpau/gstvdpvideobuffer.h b/sys/vdpau/gstvdpvideobuffer.h index abc8c99e..77ccf8ed 100644 --- a/sys/vdpau/gstvdpvideobuffer.h +++ b/sys/vdpau/gstvdpvideobuffer.h @@ -30,10 +30,10 @@ typedef struct _GstVdpVideoBuffer GstVdpVideoBuffer; -#define GST_TYPE_VDPAU_VIDEO_BUFFER (gst_vdp_video_buffer_get_type()) +#define GST_TYPE_VDP_VIDEO_BUFFER (gst_vdp_video_buffer_get_type()) -#define GST_IS_VDPAU_VIDEO_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_VDPAU_VIDEO_BUFFER)) -#define GST_VDP_VIDEO_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_VDPAU_VIDEO_BUFFER, GstVdpVideoBuffer)) +#define GST_IS_VDPAU_VIDEO_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_VDP_VIDEO_BUFFER)) +#define GST_VDP_VIDEO_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_VDP_VIDEO_BUFFER, GstVdpVideoBuffer)) struct _GstVdpVideoBuffer { GstBuffer buffer; -- cgit v1.2.1 From fda9c56a590659323c0e503933dea946a42bf8f6 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Tue, 5 May 2009 17:30:33 +0200 Subject: vdpaumpegdec: remove unneeded locking since we know do StateChange correctly --- sys/vdpau/gstvdpmpegdecoder.c | 12 ------------ sys/vdpau/gstvdpmpegdecoder.h | 2 -- 2 files changed, 14 deletions(-) diff --git a/sys/vdpau/gstvdpmpegdecoder.c b/sys/vdpau/gstvdpmpegdecoder.c index 4bcbf534..eda32c60 100644 --- a/sys/vdpau/gstvdpmpegdecoder.c +++ b/sys/vdpau/gstvdpmpegdecoder.c @@ -364,12 +364,9 @@ gst_vdp_mpeg_decoder_chain (GstPad * pad, GstBuffer * buffer) mpeg_dec = GST_VDP_MPEG_DECODER (GST_OBJECT_PARENT (pad)); - g_mutex_lock (mpeg_dec->mutex); - if (G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT))) { GST_DEBUG_OBJECT (mpeg_dec, "Received discont buffer"); gst_vdp_mpeg_decoder_reset (mpeg_dec); - g_mutex_unlock (mpeg_dec->mutex); return GST_FLOW_OK; } @@ -404,7 +401,6 @@ gst_vdp_mpeg_decoder_chain (GstPad * pad, GstBuffer * buffer) if (!gst_vdp_mpeg_decoder_parse_picture (mpeg_dec, packet_start, packet_end)) { - g_mutex_unlock (mpeg_dec->mutex); return GST_FLOW_OK; } break; @@ -442,8 +438,6 @@ gst_vdp_mpeg_decoder_chain (GstPad * pad, GstBuffer * buffer) if (mpeg_dec->vdp_info.slice_count > 0) ret = gst_vdp_mpeg_decoder_decode (mpeg_dec, GST_BUFFER_TIMESTAMP (buffer)); - g_mutex_unlock (mpeg_dec->mutex); - return ret; } @@ -462,10 +456,7 @@ gst_vdp_mpeg_decoder_sink_event (GstPad * pad, GstEvent * event) { GST_DEBUG_OBJECT (mpeg_dec, "flush stop"); - g_mutex_lock (mpeg_dec->mutex); gst_vdp_mpeg_decoder_reset (mpeg_dec); - g_mutex_unlock (mpeg_dec->mutex); - res = gst_pad_push_event (dec->src, event); break; @@ -581,8 +572,6 @@ gst_vdp_mpeg_decoder_init (GstVdpMpegDecoder * mpeg_dec, mpeg_dec->decoder = VDP_INVALID_HANDLE; gst_vdp_mpeg_decoder_init_info (&mpeg_dec->vdp_info); - mpeg_dec->mutex = g_mutex_new (); - mpeg_dec->broken_gop = FALSE; mpeg_dec->adapter = gst_adapter_new (); @@ -596,7 +585,6 @@ gst_vdp_mpeg_decoder_finalize (GObject * object) { GstVdpMpegDecoder *mpeg_dec = (GstVdpMpegDecoder *) object; - g_mutex_free (mpeg_dec->mutex); g_object_unref (mpeg_dec->adapter); } diff --git a/sys/vdpau/gstvdpmpegdecoder.h b/sys/vdpau/gstvdpmpegdecoder.h index 57ab66ab..06bed84b 100644 --- a/sys/vdpau/gstvdpmpegdecoder.h +++ b/sys/vdpau/gstvdpmpegdecoder.h @@ -47,8 +47,6 @@ struct _GstVdpMpegDecoder VdpPictureInfoMPEG1Or2 vdp_info; GstBuffer *f_buffer; GstBuffer *b_buffer; - - GMutex *mutex; gboolean broken_gop; -- cgit v1.2.1 From e416f5f5e095300d41d7bd22cdc517df29924bf4 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Tue, 5 May 2009 18:37:50 +0200 Subject: vdpaumpegdec: set correct timestamps --- sys/vdpau/gstvdpmpegdecoder.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sys/vdpau/gstvdpmpegdecoder.c b/sys/vdpau/gstvdpmpegdecoder.c index eda32c60..838b4e5a 100644 --- a/sys/vdpau/gstvdpmpegdecoder.c +++ b/sys/vdpau/gstvdpmpegdecoder.c @@ -163,7 +163,6 @@ gst_vdp_mpeg_decoder_decode (GstVdpMpegDecoder * mpeg_dec, if (mpeg_dec->vdp_info.picture_coding_type != B_FRAME) { if (mpeg_dec->vdp_info.backward_reference != VDP_INVALID_HANDLE) { - GST_BUFFER_TIMESTAMP (mpeg_dec->b_buffer) = timestamp; gst_buffer_ref (mpeg_dec->b_buffer); gst_vdp_decoder_push_video_buffer (dec, GST_VDP_VIDEO_BUFFER (mpeg_dec->b_buffer)); @@ -183,6 +182,7 @@ gst_vdp_mpeg_decoder_decode (GstVdpMpegDecoder * mpeg_dec, outbuf = gst_vdp_video_buffer_new (dec->device, VDP_CHROMA_TYPE_420, dec->width, dec->height); + GST_BUFFER_TIMESTAMP (outbuf) = timestamp; if (mpeg_dec->vdp_info.forward_reference != VDP_INVALID_HANDLE) gst_vdp_video_buffer_add_reference (outbuf, GST_VDP_VIDEO_BUFFER (mpeg_dec->f_buffer)); @@ -215,7 +215,6 @@ gst_vdp_mpeg_decoder_decode (GstVdpMpegDecoder * mpeg_dec, } if (mpeg_dec->vdp_info.picture_coding_type == B_FRAME) { - GST_BUFFER_TIMESTAMP (outbuf) = timestamp; gst_vdp_decoder_push_video_buffer (dec, GST_VDP_VIDEO_BUFFER (outbuf)); } else { mpeg_dec->vdp_info.backward_reference = surface; -- cgit v1.2.1 From 42d90ddfa3b25222ed9b37d7e0ba2030715ee8be Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Tue, 5 May 2009 18:45:07 +0200 Subject: vdpaumpegdec: don't add forward_reference if the frame is an I_FRAME --- sys/vdpau/gstvdpmpegdecoder.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sys/vdpau/gstvdpmpegdecoder.c b/sys/vdpau/gstvdpmpegdecoder.c index 838b4e5a..cf8bfe54 100644 --- a/sys/vdpau/gstvdpmpegdecoder.c +++ b/sys/vdpau/gstvdpmpegdecoder.c @@ -183,7 +183,8 @@ gst_vdp_mpeg_decoder_decode (GstVdpMpegDecoder * mpeg_dec, outbuf = gst_vdp_video_buffer_new (dec->device, VDP_CHROMA_TYPE_420, dec->width, dec->height); GST_BUFFER_TIMESTAMP (outbuf) = timestamp; - if (mpeg_dec->vdp_info.forward_reference != VDP_INVALID_HANDLE) + if (mpeg_dec->vdp_info.forward_reference != VDP_INVALID_HANDLE && + mpeg_dec->vdp_info.picture_coding_type != I_FRAME) gst_vdp_video_buffer_add_reference (outbuf, GST_VDP_VIDEO_BUFFER (mpeg_dec->f_buffer)); if (mpeg_dec->vdp_info.backward_reference != VDP_INVALID_HANDLE) -- cgit v1.2.1 From 616038423f2a43091fd9e889435751860b009599 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Tue, 5 May 2009 18:54:31 +0200 Subject: vdpaumpegdec: fixup timestamping of outgoing buffers --- sys/vdpau/gstvdpdecoder.c | 11 +++++++---- sys/vdpau/gstvdpdecoder.h | 2 +- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/sys/vdpau/gstvdpdecoder.c b/sys/vdpau/gstvdpdecoder.c index 2b0c888e..12ab6cfc 100644 --- a/sys/vdpau/gstvdpdecoder.c +++ b/sys/vdpau/gstvdpdecoder.c @@ -65,13 +65,16 @@ gst_vdp_decoder_push_video_buffer (GstVdpDecoder * dec, GstVdpVideoBuffer * buffer) { if (GST_BUFFER_TIMESTAMP (buffer) == GST_CLOCK_TIME_NONE) { - GST_BUFFER_TIMESTAMP (buffer) = - gst_util_uint64_scale_int (GST_SECOND * dec->frame_nr, + GST_BUFFER_TIMESTAMP (buffer) = dec->time + + gst_util_uint64_scale_int (GST_SECOND, dec->framerate_denominator, dec->framerate_numerator); - dec->frame_nr++; } gst_buffer_set_caps (GST_BUFFER (buffer), GST_PAD_CAPS (dec->src)); + GST_DEBUG_OBJECT (dec, "Pushin buffer with timestamp: %" GST_TIME_FORMAT, + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer))); + dec->time = GST_BUFFER_TIMESTAMP (buffer); + return gst_pad_push (dec->src, GST_BUFFER (buffer)); } @@ -173,7 +176,7 @@ gst_vdp_decoder_init (GstVdpDecoder * dec, GstVdpDecoderClass * klass) dec->framerate_numerator = 0; dec->framerate_denominator = 0; - dec->frame_nr = 0; + dec->time = 0; dec->src = gst_pad_new_from_static_template (&src_template, "src"); gst_element_add_pad (GST_ELEMENT (dec), dec->src); diff --git a/sys/vdpau/gstvdpdecoder.h b/sys/vdpau/gstvdpdecoder.h index ae53657c..f20db20c 100644 --- a/sys/vdpau/gstvdpdecoder.h +++ b/sys/vdpau/gstvdpdecoder.h @@ -52,7 +52,7 @@ struct _GstVdpDecoder { gint framerate_numerator, framerate_denominator; guint32 format; - gint frame_nr; + GstClockTime time; }; struct _GstVdpDecoderClass { -- cgit v1.2.1 From f4fda3f617fad6e09d3ca66a25ebb9f67ab302f5 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Tue, 5 May 2009 23:07:06 +0200 Subject: vdpaumpegdec: fix small typo in debug print --- sys/vdpau/gstvdpdecoder.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/vdpau/gstvdpdecoder.c b/sys/vdpau/gstvdpdecoder.c index 12ab6cfc..b6a28cc7 100644 --- a/sys/vdpau/gstvdpdecoder.c +++ b/sys/vdpau/gstvdpdecoder.c @@ -71,7 +71,7 @@ gst_vdp_decoder_push_video_buffer (GstVdpDecoder * dec, } gst_buffer_set_caps (GST_BUFFER (buffer), GST_PAD_CAPS (dec->src)); - GST_DEBUG_OBJECT (dec, "Pushin buffer with timestamp: %" GST_TIME_FORMAT, + GST_DEBUG_OBJECT (dec, "Pushing buffer with timestamp: %" GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer))); dec->time = GST_BUFFER_TIMESTAMP (buffer); -- cgit v1.2.1 From c7c60ad02931019bd5d50f2a01852f63364868b2 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Tue, 5 May 2009 23:08:51 +0200 Subject: vdpaumpegdec: remove unnused GstVdpBFrame struct --- sys/vdpau/gstvdpmpegdecoder.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/sys/vdpau/gstvdpmpegdecoder.c b/sys/vdpau/gstvdpmpegdecoder.c index cf8bfe54..680a5496 100644 --- a/sys/vdpau/gstvdpmpegdecoder.c +++ b/sys/vdpau/gstvdpmpegdecoder.c @@ -138,12 +138,6 @@ gst_vdp_mpeg_decoder_set_caps (GstVdpDecoder * dec, GstCaps * caps) return TRUE; } -typedef struct -{ - GstBuffer *buffer; - VdpPictureInfoMPEG1Or2 vdp_info; -} GstVdpBFrame; - static GstFlowReturn gst_vdp_mpeg_decoder_decode (GstVdpMpegDecoder * mpeg_dec, GstClockTime timestamp) -- cgit v1.2.1 From 0ffaf06a9ab7dd780a85f0072e3d3571a5e8639e Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Tue, 5 May 2009 23:13:25 +0200 Subject: vdpaumpegdec: small code cleanup --- sys/vdpau/gstvdpmpegdecoder.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/sys/vdpau/gstvdpmpegdecoder.c b/sys/vdpau/gstvdpmpegdecoder.c index 680a5496..fe9b3e7c 100644 --- a/sys/vdpau/gstvdpmpegdecoder.c +++ b/sys/vdpau/gstvdpmpegdecoder.c @@ -143,6 +143,7 @@ gst_vdp_mpeg_decoder_decode (GstVdpMpegDecoder * mpeg_dec, GstClockTime timestamp) { GstVdpDecoder *dec; + VdpPictureInfoMPEG1Or2 *info; GstBuffer *buffer; GstVdpVideoBuffer *outbuf; VdpVideoSurface surface; @@ -151,37 +152,37 @@ gst_vdp_mpeg_decoder_decode (GstVdpMpegDecoder * mpeg_dec, VdpStatus status; dec = GST_VDP_DECODER (mpeg_dec); + info = &mpeg_dec->vdp_info; buffer = gst_adapter_take_buffer (mpeg_dec->adapter, gst_adapter_available (mpeg_dec->adapter)); - if (mpeg_dec->vdp_info.picture_coding_type != B_FRAME) { - if (mpeg_dec->vdp_info.backward_reference != VDP_INVALID_HANDLE) { + if (info->picture_coding_type != B_FRAME) { + if (info->backward_reference != VDP_INVALID_HANDLE) { gst_buffer_ref (mpeg_dec->b_buffer); gst_vdp_decoder_push_video_buffer (dec, GST_VDP_VIDEO_BUFFER (mpeg_dec->b_buffer)); } - if (mpeg_dec->vdp_info.forward_reference != VDP_INVALID_HANDLE) { + if (info->forward_reference != VDP_INVALID_HANDLE) { gst_buffer_unref (mpeg_dec->f_buffer); - mpeg_dec->vdp_info.forward_reference = VDP_INVALID_HANDLE; + info->forward_reference = VDP_INVALID_HANDLE; } - mpeg_dec->vdp_info.forward_reference = - mpeg_dec->vdp_info.backward_reference; + info->forward_reference = info->backward_reference; mpeg_dec->f_buffer = mpeg_dec->b_buffer; - mpeg_dec->vdp_info.backward_reference = VDP_INVALID_HANDLE; + info->backward_reference = VDP_INVALID_HANDLE; } outbuf = gst_vdp_video_buffer_new (dec->device, VDP_CHROMA_TYPE_420, dec->width, dec->height); GST_BUFFER_TIMESTAMP (outbuf) = timestamp; - if (mpeg_dec->vdp_info.forward_reference != VDP_INVALID_HANDLE && - mpeg_dec->vdp_info.picture_coding_type != I_FRAME) + if (info->forward_reference != VDP_INVALID_HANDLE && + info->picture_coding_type != I_FRAME) gst_vdp_video_buffer_add_reference (outbuf, GST_VDP_VIDEO_BUFFER (mpeg_dec->f_buffer)); - if (mpeg_dec->vdp_info.backward_reference != VDP_INVALID_HANDLE) + if (info->backward_reference != VDP_INVALID_HANDLE) gst_vdp_video_buffer_add_reference (outbuf, GST_VDP_VIDEO_BUFFER (mpeg_dec->b_buffer)); @@ -194,9 +195,9 @@ gst_vdp_mpeg_decoder_decode (GstVdpMpegDecoder * mpeg_dec, vbit[0].bitstream_bytes = GST_BUFFER_SIZE (buffer); status = device->vdp_decoder_render (mpeg_dec->decoder, surface, - (VdpPictureInfo *) & mpeg_dec->vdp_info, 1, vbit); + (VdpPictureInfo *) info, 1, vbit); gst_buffer_unref (buffer); - mpeg_dec->vdp_info.slice_count = 0; + info->slice_count = 0; if (status != VDP_STATUS_OK) { GST_ELEMENT_ERROR (mpeg_dec, RESOURCE, READ, @@ -209,10 +210,10 @@ gst_vdp_mpeg_decoder_decode (GstVdpMpegDecoder * mpeg_dec, return GST_FLOW_ERROR; } - if (mpeg_dec->vdp_info.picture_coding_type == B_FRAME) { + if (info->picture_coding_type == B_FRAME) { gst_vdp_decoder_push_video_buffer (dec, GST_VDP_VIDEO_BUFFER (outbuf)); } else { - mpeg_dec->vdp_info.backward_reference = surface; + info->backward_reference = surface; mpeg_dec->b_buffer = GST_BUFFER (outbuf); } -- cgit v1.2.1 From 8e66a1783092da8c171b1d10273eda91e590e732 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Tue, 5 May 2009 23:19:56 +0200 Subject: vdpau: add debug on GstVdpDevice destroy --- sys/vdpau/gstvdpdevice.c | 2 ++ sys/vdpau/gstvdpmpegdecoder.c | 2 ++ 2 files changed, 4 insertions(+) diff --git a/sys/vdpau/gstvdpdevice.c b/sys/vdpau/gstvdpdevice.c index ad771906..f920f973 100644 --- a/sys/vdpau/gstvdpdevice.c +++ b/sys/vdpau/gstvdpdevice.c @@ -221,6 +221,8 @@ device_destroyed_cb (gpointer data, GObject * object) GHashTableIter iter; gpointer device; + GST_DEBUG ("Removing object from hash table"); + g_hash_table_iter_init (&iter, devices_hash); while (g_hash_table_iter_next (&iter, NULL, &device)) { if (device == object) { diff --git a/sys/vdpau/gstvdpmpegdecoder.c b/sys/vdpau/gstvdpmpegdecoder.c index fe9b3e7c..006e6d41 100644 --- a/sys/vdpau/gstvdpmpegdecoder.c +++ b/sys/vdpau/gstvdpmpegdecoder.c @@ -178,10 +178,12 @@ gst_vdp_mpeg_decoder_decode (GstVdpMpegDecoder * mpeg_dec, outbuf = gst_vdp_video_buffer_new (dec->device, VDP_CHROMA_TYPE_420, dec->width, dec->height); GST_BUFFER_TIMESTAMP (outbuf) = timestamp; + if (info->forward_reference != VDP_INVALID_HANDLE && info->picture_coding_type != I_FRAME) gst_vdp_video_buffer_add_reference (outbuf, GST_VDP_VIDEO_BUFFER (mpeg_dec->f_buffer)); + if (info->backward_reference != VDP_INVALID_HANDLE) gst_vdp_video_buffer_add_reference (outbuf, GST_VDP_VIDEO_BUFFER (mpeg_dec->b_buffer)); -- cgit v1.2.1 From 426a6eaba9776157f43da280d37b81ac49cccd72 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Wed, 6 May 2009 23:07:00 +0200 Subject: vdpau: change element rank for testing purposes set mpegvideoparse rank to primary and vdpaumpegdec to primary - 1 to get vdpaumpegdec correctly plugged into playbin --- gst/mpegvideoparse/mpegvideoparse.c | 2 +- sys/vdpau/gstvdp.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gst/mpegvideoparse/mpegvideoparse.c b/gst/mpegvideoparse/mpegvideoparse.c index d0badbfc..eefa6843 100644 --- a/gst/mpegvideoparse/mpegvideoparse.c +++ b/gst/mpegvideoparse/mpegvideoparse.c @@ -961,7 +961,7 @@ plugin_init (GstPlugin * plugin) "MPEG Video Parser"); return gst_element_register (plugin, "mpegvideoparse", - GST_RANK_SECONDARY - 1, GST_TYPE_MPEGVIDEOPARSE); + GST_RANK_PRIMARY, GST_TYPE_MPEGVIDEOPARSE); } GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, diff --git a/sys/vdpau/gstvdp.c b/sys/vdpau/gstvdp.c index 64ebf37e..8d5be3dc 100644 --- a/sys/vdpau/gstvdp.c +++ b/sys/vdpau/gstvdp.c @@ -13,7 +13,7 @@ static gboolean vdpau_init (GstPlugin * vdpau_plugin) { gst_element_register (vdpau_plugin, "vdpaumpegdec", - GST_RANK_NONE, GST_TYPE_VDP_MPEG_DECODER); + GST_RANK_PRIMARY - 1, GST_TYPE_VDP_MPEG_DECODER); gst_element_register (vdpau_plugin, "vdpauvideoyuv", GST_RANK_PRIMARY, GST_TYPE_VDP_VIDEO_YUV); gst_element_register (vdpau_plugin, "vdpauyuvvideo", -- cgit v1.2.1 From 127765d19c268724de21ea97038e380acdefd2a2 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Thu, 4 Jun 2009 18:11:06 +0200 Subject: vdpaumpegdec: use GstBitReader to parse bitstream --- sys/vdpau/gstvdpmpegdecoder.c | 213 +++++++++++++++------ sys/vdpau/mpegutil.c | 426 +++++++++++++++++++++--------------------- sys/vdpau/mpegutil.h | 59 ++++-- 3 files changed, 405 insertions(+), 293 deletions(-) diff --git a/sys/vdpau/gstvdpmpegdecoder.c b/sys/vdpau/gstvdpmpegdecoder.c index 006e6d41..fc7aa5a6 100644 --- a/sys/vdpau/gstvdpmpegdecoder.c +++ b/sys/vdpau/gstvdpmpegdecoder.c @@ -36,6 +36,8 @@ #endif #include +#include +#include #include #include "mpegutil.h" @@ -80,14 +82,82 @@ static void gst_vdp_mpeg_decoder_set_property (GObject * object, static void gst_vdp_mpeg_decoder_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); +guint8 * +mpeg_util_find_start_code (guint32 * sync_word, guint8 * cur, guint8 * end) +{ + guint32 code; + + if (G_UNLIKELY (cur == NULL)) + return NULL; + + code = *sync_word; + + while (cur < end) { + code <<= 8; + + if (code == 0x00000100) { + /* Reset the sync word accumulator */ + *sync_word = 0xffffffff; + return cur; + } + + /* Add the next available byte to the collected sync word */ + code |= *cur++; + } + + *sync_word = code; + return NULL; +} + +typedef struct +{ + GstBuffer *buffer; + guint8 *cur; + guint8 *end; +} GstVdpMpegPacketizer; + +static GstBuffer * +gst_vdp_mpeg_packetizer_get_next_packet (GstVdpMpegPacketizer * packetizer) +{ + guint32 sync_word = 0xffffff; + guint8 *packet_start; + guint8 *packet_end; + + if (!packetizer->cur) + return NULL; + + packet_start = packetizer->cur - 3; + packetizer->cur = packet_end = mpeg_util_find_start_code (&sync_word, + packetizer->cur, packetizer->end); + + if (packet_end) + packet_end -= 3; + else + packet_end = packetizer->end; + + return gst_buffer_create_sub (packetizer->buffer, + packet_start - GST_BUFFER_DATA (packetizer->buffer), + packet_end - packet_start); +} + +static void +gst_vdp_mpeg_packetizer_init (GstVdpMpegPacketizer * packetizer, + GstBuffer * buffer) +{ + guint32 sync_word = 0xffffffff; + + packetizer->buffer = buffer; + packetizer->end = GST_BUFFER_DATA (buffer) + GST_BUFFER_SIZE (buffer); + packetizer->cur = mpeg_util_find_start_code (&sync_word, + GST_BUFFER_DATA (buffer), packetizer->end); +} + static gboolean gst_vdp_mpeg_decoder_set_caps (GstVdpDecoder * dec, GstCaps * caps) { GstVdpMpegDecoder *mpeg_dec; GstStructure *structure; const GValue *value; - GstBuffer *codec_data; - MPEGSeqHdr hdr = { 0, }; VdpDecoderProfile profile; GstVdpDevice *device; VdpStatus status; @@ -100,25 +170,44 @@ gst_vdp_mpeg_decoder_set_caps (GstVdpDecoder * dec, GstCaps * caps) profile = VDP_DECODER_PROFILE_MPEG1; value = gst_structure_get_value (structure, "codec_data"); - codec_data = gst_value_get_buffer (value); - mpeg_util_parse_sequence_hdr (&hdr, GST_BUFFER_DATA (codec_data), - GST_BUFFER_DATA (codec_data) + GST_BUFFER_SIZE (codec_data)); - if (mpeg_dec->version != 1) { - switch (hdr.profile) { - case 5: - profile = VDP_DECODER_PROFILE_MPEG2_SIMPLE; - break; - default: - profile = VDP_DECODER_PROFILE_MPEG2_MAIN; - break; + if (value) { + GstBuffer *codec_data, *buf; + GstVdpMpegPacketizer packetizer; + + codec_data = gst_value_get_buffer (value); + gst_vdp_mpeg_packetizer_init (&packetizer, codec_data); + if ((buf = gst_vdp_mpeg_packetizer_get_next_packet (&packetizer))) { + MPEGSeqHdr hdr; + + mpeg_util_parse_sequence_hdr (&hdr, buf); + + memcpy (&mpeg_dec->vdp_info.intra_quantizer_matrix, + &hdr.intra_quantizer_matrix, 64); + memcpy (&mpeg_dec->vdp_info.non_intra_quantizer_matrix, + &hdr.non_intra_quantizer_matrix, 64); + + gst_buffer_unref (buf); + + if ((buf = gst_vdp_mpeg_packetizer_get_next_packet (&packetizer))) { + MPEGSeqExtHdr ext; + + mpeg_util_parse_sequence_extension (&ext, buf); + if (mpeg_dec->version != 1) { + switch (ext.profile) { + case 5: + profile = VDP_DECODER_PROFILE_MPEG2_SIMPLE; + break; + default: + profile = VDP_DECODER_PROFILE_MPEG2_MAIN; + break; + } + } + + gst_buffer_unref (buf); + } } } - memcpy (&mpeg_dec->vdp_info.intra_quantizer_matrix, - &hdr.intra_quantizer_matrix, 64); - memcpy (&mpeg_dec->vdp_info.non_intra_quantizer_matrix, - &hdr.non_intra_quantizer_matrix, 64); - device = dec->device; if (mpeg_dec->decoder != VDP_INVALID_HANDLE) { @@ -224,7 +313,7 @@ gst_vdp_mpeg_decoder_decode (GstVdpMpegDecoder * mpeg_dec, static gboolean gst_vdp_mpeg_decoder_parse_picture_coding (GstVdpMpegDecoder * mpeg_dec, - guint8 * data, guint8 * end) + GstBuffer * buffer) { GstVdpDecoder *dec; MPEGPictureExt pic_ext; @@ -233,7 +322,7 @@ gst_vdp_mpeg_decoder_parse_picture_coding (GstVdpMpegDecoder * mpeg_dec, dec = GST_VDP_DECODER (mpeg_dec); info = &mpeg_dec->vdp_info; - if (!mpeg_util_parse_picture_coding_extension (&pic_ext, data, end)) + if (!mpeg_util_parse_picture_coding_extension (&pic_ext, buffer)) return FALSE; memcpy (&mpeg_dec->vdp_info.f_code, &pic_ext.f_code, 4); @@ -252,16 +341,17 @@ gst_vdp_mpeg_decoder_parse_picture_coding (GstVdpMpegDecoder * mpeg_dec, static gboolean gst_vdp_mpeg_decoder_parse_sequence (GstVdpMpegDecoder * mpeg_dec, - guint8 * data, guint8 * end) + GstBuffer * buffer) { GstVdpDecoder *dec; MPEGSeqHdr hdr; dec = GST_VDP_DECODER (mpeg_dec); - if (!mpeg_util_parse_sequence_hdr (&hdr, data, end)) + if (!mpeg_util_parse_sequence_hdr (&hdr, buffer)) return FALSE; + g_debug ("här"); memcpy (&mpeg_dec->vdp_info.intra_quantizer_matrix, &hdr.intra_quantizer_matrix, 64); memcpy (&mpeg_dec->vdp_info.non_intra_quantizer_matrix, @@ -272,14 +362,14 @@ gst_vdp_mpeg_decoder_parse_sequence (GstVdpMpegDecoder * mpeg_dec, static gboolean gst_vdp_mpeg_decoder_parse_picture (GstVdpMpegDecoder * mpeg_dec, - guint8 * data, guint8 * end) + GstBuffer * buffer) { GstVdpDecoder *dec; MPEGPictureHdr pic_hdr; dec = GST_VDP_DECODER (mpeg_dec); - if (!mpeg_util_parse_picture_hdr (&pic_hdr, data, end)) + if (!mpeg_util_parse_picture_hdr (&pic_hdr, buffer)) return FALSE; if (pic_hdr.pic_type != I_FRAME @@ -309,12 +399,12 @@ gst_vdp_mpeg_decoder_parse_picture (GstVdpMpegDecoder * mpeg_dec, } static gboolean -gst_vdp_mpeg_decoder_parse_gop (GstVdpMpegDecoder * mpeg_dec, guint8 * data, - guint8 * end) +gst_vdp_mpeg_decoder_parse_gop (GstVdpMpegDecoder * mpeg_dec, + GstBuffer * buffer) { - MPEGPictureGOP gop; + MPEGGop gop; - if (!mpeg_util_parse_picture_gop (&gop, data, end)) + if (!mpeg_util_parse_gop (&gop, buffer)) return FALSE; mpeg_dec->broken_gop = gop.broken_gop; @@ -324,11 +414,11 @@ gst_vdp_mpeg_decoder_parse_gop (GstVdpMpegDecoder * mpeg_dec, guint8 * data, static gboolean gst_vdp_mpeg_decoder_parse_quant_matrix (GstVdpMpegDecoder * mpeg_dec, - guint8 * data, guint8 * end) + GstBuffer * buffer) { MPEGQuantMatrix qm; - if (!mpeg_util_parse_quant_matrix (&qm, data, end)) + if (!mpeg_util_parse_quant_matrix (&qm, buffer)) return FALSE; memcpy (&mpeg_dec->vdp_info.intra_quantizer_matrix, @@ -355,8 +445,8 @@ static GstFlowReturn gst_vdp_mpeg_decoder_chain (GstPad * pad, GstBuffer * buffer) { GstVdpMpegDecoder *mpeg_dec; - guint8 *data, *end; - guint32 sync_word = 0xffffffff; + GstVdpMpegPacketizer packetizer; + GstBuffer *buf; GstFlowReturn ret = GST_FLOW_OK; mpeg_dec = GST_VDP_MPEG_DECODER (GST_OBJECT_PARENT (pad)); @@ -367,69 +457,70 @@ gst_vdp_mpeg_decoder_chain (GstPad * pad, GstBuffer * buffer) return GST_FLOW_OK; } - data = GST_BUFFER_DATA (buffer); - end = GST_BUFFER_DATA (buffer) + GST_BUFFER_SIZE (buffer); + gst_vdp_mpeg_packetizer_init (&packetizer, buffer); + while ((buf = gst_vdp_mpeg_packetizer_get_next_packet (&packetizer))) { + GstBitReader b_reader = GST_BIT_READER_INIT_FROM_BUFFER (buf); + guint32 sync_code; + guint8 start_code; - while ((data = mpeg_util_find_start_code (&sync_word, data, end))) { - guint8 *packet_start; - guint8 *packet_end; + /* skip sync_code */ + gst_bit_reader_get_bits_uint32 (&b_reader, &sync_code, 8 * 3); - packet_start = data - 3; - packet_end = mpeg_util_find_start_code (&sync_word, data, end); - if (packet_end) - packet_end -= 3; - else - packet_end = end; - - if (data[0] >= MPEG_PACKET_SLICE_MIN && data[0] <= MPEG_PACKET_SLICE_MAX) { - GstBuffer *subbuf; + /* start_code */ + gst_bit_reader_get_bits_uint8 (&b_reader, &start_code, 8); + if (start_code >= MPEG_PACKET_SLICE_MIN + && start_code <= MPEG_PACKET_SLICE_MAX) { GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_SLICE"); - subbuf = - gst_buffer_create_sub (buffer, - packet_start - GST_BUFFER_DATA (buffer), packet_end - packet_start); - gst_adapter_push (mpeg_dec->adapter, subbuf); + + gst_buffer_ref (buf); + gst_adapter_push (mpeg_dec->adapter, buf); mpeg_dec->vdp_info.slice_count++; } - switch (data[0]) { + switch (start_code) { case MPEG_PACKET_PICTURE: GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_PICTURE"); - if (!gst_vdp_mpeg_decoder_parse_picture (mpeg_dec, packet_start, - packet_end)) { + if (!gst_vdp_mpeg_decoder_parse_picture (mpeg_dec, buf)) { return GST_FLOW_OK; } break; case MPEG_PACKET_SEQUENCE: GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_SEQUENCE"); - gst_vdp_mpeg_decoder_parse_sequence (mpeg_dec, packet_start, - packet_end); + gst_vdp_mpeg_decoder_parse_sequence (mpeg_dec, buf); break; case MPEG_PACKET_EXTENSION: + { + guint8 ext_code; + GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_EXTENSION"); - switch (read_bits (data + 1, 0, 4)) { + + /* ext_code */ + gst_bit_reader_get_bits_uint8 (&b_reader, &ext_code, 4); + switch (ext_code) { case MPEG_PACKET_EXT_PICTURE_CODING: GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_EXT_PICTURE_CODING"); - gst_vdp_mpeg_decoder_parse_picture_coding (mpeg_dec, packet_start, - packet_end); + gst_vdp_mpeg_decoder_parse_picture_coding (mpeg_dec, buf); break; case MPEG_PACKET_EXT_QUANT_MATRIX: GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_EXT_QUANT_MATRIX"); - gst_vdp_mpeg_decoder_parse_quant_matrix (mpeg_dec, packet_start, - packet_end); + gst_vdp_mpeg_decoder_parse_quant_matrix (mpeg_dec, buf); break; default: break; } break; + } case MPEG_PACKET_GOP: GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_GOP"); - gst_vdp_mpeg_decoder_parse_gop (mpeg_dec, packet_start, packet_end); + gst_vdp_mpeg_decoder_parse_gop (mpeg_dec, buf); break; default: break; } + + gst_buffer_unref (buf); } if (mpeg_dec->vdp_info.slice_count > 0) diff --git a/sys/vdpau/mpegutil.c b/sys/vdpau/mpegutil.c index 08ae5c53..c35ad9fb 100644 --- a/sys/vdpau/mpegutil.c +++ b/sys/vdpau/mpegutil.c @@ -18,6 +18,7 @@ * Boston, MA 02111-1307, USA. */ +#include #include #include "mpegutil.h" @@ -53,58 +54,6 @@ guint8 mpeg2_scan[64] = { 53, 60, 61, 54, 47, 55, 62, 63 }; -guint8 bits[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 }; - -guint32 -read_bits (guint8 * buf, gint start_bit, gint n_bits) -{ - gint i; - guint32 ret = 0x00; - - buf += start_bit / 8; - start_bit %= 8; - - for (i = 0; i < n_bits; i++) { - guint32 tmp; - - tmp = ((*buf & bits[start_bit]) >> (7 - start_bit)); - ret = (ret | (tmp << (n_bits - i - 1))); - if (++start_bit == 8) { - buf += 1; - start_bit = 0; - } - } - - return ret; -} - -guint8 * -mpeg_util_find_start_code (guint32 * sync_word, guint8 * cur, guint8 * end) -{ - guint32 code; - - if (G_UNLIKELY (cur == NULL)) - return NULL; - - code = *sync_word; - - while (cur < end) { - code <<= 8; - - if (code == 0x00000100) { - /* Reset the sync word accumulator */ - *sync_word = 0xffffffff; - return cur; - } - - /* Add the next available byte to the collected sync word */ - code |= *cur++; - } - - *sync_word = code; - return NULL; -} - static void set_fps_from_code (MPEGSeqHdr * hdr, guint8 fps_code) { @@ -150,157 +99,169 @@ set_par_from_dar (MPEGSeqHdr * hdr, guint8 asr_code) } } -static gboolean -mpeg_util_parse_extension_packet (MPEGSeqHdr * hdr, guint8 * data, guint8 * end) +gboolean +mpeg_util_parse_sequence_extension (MPEGSeqExtHdr * hdr, GstBuffer * buffer) { - guint8 ext_code; + GstBitReader reader = GST_BIT_READER_INIT_FROM_BUFFER (buffer);; - if (G_UNLIKELY (data >= end)) - return FALSE; /* short extension packet */ + /* skip sync word */ + if (!gst_bit_reader_skip (&reader, 8 * 4)) + return FALSE; - ext_code = read_bits (data, 0, 4); + /* skip extension code */ + if (!gst_bit_reader_skip (&reader, 4)) + return FALSE; - switch (ext_code) { - case MPEG_PACKET_EXT_SEQUENCE: - { - /* Parse a Sequence Extension */ - guint8 horiz_size_ext, vert_size_ext; - guint8 fps_n_ext, fps_d_ext; + /* skip profile and level escape bit */ + if (!gst_bit_reader_skip (&reader, 1)) + return FALSE; - if (G_UNLIKELY ((end - data) < 6)) - /* need at least 10 bytes, minus 4 for the start code 000001b5 */ - return FALSE; + if (!gst_bit_reader_get_bits_uint8 (&reader, &hdr->profile, 3)) + return FALSE; + if (!gst_bit_reader_get_bits_uint8 (&reader, &hdr->level, 4)) + return FALSE; - hdr->profile = read_bits (data, 7, 3); + /* progressive */ + if (!gst_bit_reader_get_bits_uint8 (&reader, &hdr->progressive, 1)) + return FALSE; + + /* chroma format */ + if (!gst_bit_reader_get_bits_uint8 (&reader, &hdr->chroma_format, 2)) + return FALSE; - horiz_size_ext = read_bits (data + 1, 7, 2); - vert_size_ext = read_bits (data + 2, 1, 2); + /* resolution extension */ + if (!gst_bit_reader_get_bits_uint8 (&reader, &hdr->horiz_size_ext, 2)) + return FALSE; + if (!gst_bit_reader_get_bits_uint8 (&reader, &hdr->vert_size_ext, 2)) + return FALSE; - fps_n_ext = read_bits (data + 5, 1, 2); - fps_d_ext = read_bits (data + 5, 3, 5); + /* skip to framerate extension */ + if (!gst_bit_reader_skip (&reader, 22)) + return FALSE; - hdr->fps_n *= (fps_n_ext + 1); - hdr->fps_d *= (fps_d_ext + 1); - hdr->width += (horiz_size_ext << 12); - hdr->height += (vert_size_ext << 12); - break; - } - default: - break; - } + /* framerate extension */ + if (!gst_bit_reader_get_bits_uint8 (&reader, &hdr->fps_n_ext, 2)) + return FALSE; + if (!gst_bit_reader_get_bits_uint8 (&reader, &hdr->fps_d_ext, 2)) + return FALSE; return TRUE; } gboolean -mpeg_util_parse_sequence_hdr (MPEGSeqHdr * hdr, guint8 * data, guint8 * end) +mpeg_util_parse_sequence_hdr (MPEGSeqHdr * hdr, GstBuffer * buffer) { - guint32 code; - guint8 dar_idx, fps_idx; - guint32 sync_word = 0xffffffff; - gboolean constrained_flag; - gboolean load_intra_flag; - gboolean load_non_intra_flag; - gint i; + GstBitReader reader = GST_BIT_READER_INIT_FROM_BUFFER (buffer); + guint8 dar_idx, par_idx; + guint8 load_intra_flag, load_non_intra_flag; - if (G_UNLIKELY ((end - data) < 12)) - return FALSE; /* Too small to be a sequence header */ + /* skip sync word */ + if (!gst_bit_reader_skip (&reader, 8 * 4)) + return FALSE; - code = GST_READ_UINT32_BE (data); - if (G_UNLIKELY (code != (0x00000100 | MPEG_PACKET_SEQUENCE))) + /* resolution */ + if (!gst_bit_reader_get_bits_uint16 (&reader, &hdr->width, 12)) + return FALSE; + if (!gst_bit_reader_get_bits_uint16 (&reader, &hdr->height, 12)) return FALSE; - /* Skip the sync word */ - data += 4; + /* aspect ratio */ + if (!gst_bit_reader_get_bits_uint8 (&reader, &dar_idx, 4)) + return FALSE; + set_par_from_dar (hdr, dar_idx); - /* Parse the MPEG 1 bits */ - hdr->mpeg_version = 1; + /* framerate */ + if (!gst_bit_reader_get_bits_uint8 (&reader, &par_idx, 4)) + return FALSE; + set_fps_from_code (hdr, par_idx); - code = GST_READ_UINT32_BE (data); - hdr->width = read_bits (data, 0, 12); - hdr->height = read_bits (data + 1, 4, 12); + /* bitrate */ + if (!gst_bit_reader_get_bits_uint32 (&reader, &hdr->bitrate, 18)) + return FALSE; - dar_idx = read_bits (data + 3, 0, 4); - set_par_from_dar (hdr, dar_idx); - fps_idx = read_bits (data + 3, 4, 4); - set_fps_from_code (hdr, fps_idx); + if (!gst_bit_reader_skip (&reader, 1)) + return FALSE; + + /* VBV buffer size */ + if (!gst_bit_reader_get_bits_uint16 (&reader, &hdr->vbv_buffer, 10)) + return FALSE; - constrained_flag = read_bits (data + 7, 5, 1); + /* constrained parameters flag */ + if (!gst_bit_reader_get_bits_uint8 (&reader, + &hdr->constrained_parameters_flag, 1)) + return FALSE; - load_intra_flag = read_bits (data + 7, 6, 1); + /* intra quantizer matrix */ + if (!gst_bit_reader_get_bits_uint8 (&reader, &load_intra_flag, 1)) + return FALSE; if (load_intra_flag) { - if (G_UNLIKELY ((end - data) < 64)) - return FALSE; + gint i; for (i = 0; i < 64; i++) { - hdr->intra_quantizer_matrix[mpeg2_scan[i]] = - read_bits (data + 7 + i, 7, 8); + if (!gst_bit_reader_get_bits_uint8 (&reader, + &hdr->intra_quantizer_matrix[mpeg2_scan[i]], 8)) + return FALSE; } - data += 64; - } else memcpy (hdr->intra_quantizer_matrix, default_intra_quantizer_matrix, 64); - load_non_intra_flag = read_bits (data + 7, 7 + load_intra_flag, 1); + /* non intra quantizer matrix */ + if (!gst_bit_reader_get_bits_uint8 (&reader, &load_non_intra_flag, 1)) + return FALSE; if (load_non_intra_flag) { - if (G_UNLIKELY ((end - data) < 64)) - return FALSE; - for (i = 0; i < 64; i++) - hdr->non_intra_quantizer_matrix[mpeg2_scan[i]] = - read_bits (data + 8 + i, 1 + load_intra_flag, 8); - } else - memset (hdr->non_intra_quantizer_matrix, 16, 64); - - /* Advance past the rest of the MPEG-1 header */ - data += 8; - - /* Read MPEG-2 sequence extensions */ - data = mpeg_util_find_start_code (&sync_word, data, end); - while (data != NULL) { - if (G_UNLIKELY (data >= end)) - return FALSE; - - /* data points at the last byte of the start code */ - if (data[0] == MPEG_PACKET_EXTENSION) { - if (!mpeg_util_parse_extension_packet (hdr, data + 1, end)) + gint i; + for (i = 0; i < 64; i++) { + if (!gst_bit_reader_get_bits_uint8 (&reader, + &hdr->non_intra_quantizer_matrix[mpeg2_scan[i]], 8)) return FALSE; - - hdr->mpeg_version = 2; } - data = mpeg_util_find_start_code (&sync_word, data, end); - } + } else + memset (hdr->non_intra_quantizer_matrix, 16, 64); return TRUE; } gboolean -mpeg_util_parse_picture_hdr (MPEGPictureHdr * hdr, guint8 * data, guint8 * end) +mpeg_util_parse_picture_hdr (MPEGPictureHdr * hdr, GstBuffer * buffer) { - guint32 code; + GstBitReader reader = GST_BIT_READER_INIT_FROM_BUFFER (buffer); - if (G_UNLIKELY ((end - data) < 8)) - return FALSE; /* Packet too small */ + /* skip sync word */ + if (!gst_bit_reader_skip (&reader, 8 * 4)) + return FALSE; - code = GST_READ_UINT32_BE (data); - if (G_UNLIKELY (code != (0x00000100 | MPEG_PACKET_PICTURE))) + /* temperal sequence number */ + if (!gst_bit_reader_get_bits_uint16 (&reader, &hdr->tsn, 10)) return FALSE; - /* Skip the sync word */ - data += 4; + /* frame type */ + if (!gst_bit_reader_get_bits_uint8 (&reader, &hdr->pic_type, 3)) + return FALSE; - hdr->pic_type = (data[1] >> 3) & 0x07; if (hdr->pic_type == 0 || hdr->pic_type > 4) return FALSE; /* Corrupted picture packet */ + /* VBV delay */ + if (!gst_bit_reader_get_bits_uint16 (&reader, &hdr->vbv_delay, 16)) + return FALSE; + if (hdr->pic_type == P_FRAME || hdr->pic_type == B_FRAME) { - if (G_UNLIKELY ((end - data) < 5)) - return FALSE; /* packet too small */ - hdr->full_pel_forward_vector = read_bits (data + 3, 5, 1); - hdr->f_code[0][0] = hdr->f_code[0][1] = read_bits (data + 3, 6, 3); + if (!gst_bit_reader_get_bits_uint8 (&reader, &hdr->full_pel_forward_vector, + 1)) + return FALSE; + + if (!gst_bit_reader_get_bits_uint8 (&reader, &hdr->f_code[0][0], 3)) + return FALSE; + hdr->f_code[0][1] = hdr->f_code[0][0]; if (hdr->pic_type == B_FRAME) { - hdr->full_pel_backward_vector = read_bits (data + 4, 1, 1); - hdr->f_code[1][0] = hdr->f_code[1][1] = read_bits (data + 4, 2, 3); + if (!gst_bit_reader_get_bits_uint8 (&reader, + &hdr->full_pel_backward_vector, 1)) + return FALSE; + + if (!gst_bit_reader_get_bits_uint8 (&reader, &hdr->f_code[1][0], 3)) + return FALSE; + hdr->f_code[1][1] = hdr->f_code[1][0]; } else hdr->full_pel_backward_vector = 0; } else { @@ -312,104 +273,143 @@ mpeg_util_parse_picture_hdr (MPEGPictureHdr * hdr, guint8 * data, guint8 * end) } gboolean -mpeg_util_parse_picture_coding_extension (MPEGPictureExt * ext, guint8 * data, - guint8 * end) +mpeg_util_parse_picture_coding_extension (MPEGPictureExt * ext, + GstBuffer * buffer) { - guint32 code; + GstBitReader reader = GST_BIT_READER_INIT_FROM_BUFFER (buffer); - if (G_UNLIKELY ((end - data) < 9)) - return FALSE; /* Packet too small */ + /* skip sync word */ + if (!gst_bit_reader_skip (&reader, 8 * 4)) + return FALSE; - code = GST_READ_UINT32_BE (data); + /* skip extension code */ + if (!gst_bit_reader_skip (&reader, 4)) + return FALSE; - if (G_UNLIKELY (G_UNLIKELY (code != (0x00000100 | MPEG_PACKET_EXTENSION)))) + /* f_code */ + if (!gst_bit_reader_get_bits_uint8 (&reader, &ext->f_code[0][0], 4)) + return FALSE; + if (!gst_bit_reader_get_bits_uint8 (&reader, &ext->f_code[0][1], 4)) + return FALSE; + if (!gst_bit_reader_get_bits_uint8 (&reader, &ext->f_code[1][0], 4)) + return FALSE; + if (!gst_bit_reader_get_bits_uint8 (&reader, &ext->f_code[1][1], 4)) return FALSE; - /* Skip the sync word */ - data += 4; + /* intra DC precision */ + if (!gst_bit_reader_get_bits_uint8 (&reader, &ext->intra_dc_precision, 2)) + return FALSE; - ext->f_code[0][0] = read_bits (data, 4, 4); - ext->f_code[0][1] = read_bits (data + 1, 0, 4); - ext->f_code[1][0] = read_bits (data + 1, 4, 4); - ext->f_code[1][1] = read_bits (data + 2, 0, 4); + /* picture structure */ + if (!gst_bit_reader_get_bits_uint8 (&reader, &ext->picture_structure, 2)) + return FALSE; - ext->intra_dc_precision = read_bits (data + 2, 4, 2); - ext->picture_structure = read_bits (data + 2, 6, 2); - ext->top_field_first = read_bits (data + 3, 0, 1); - ext->frame_pred_frame_dct = read_bits (data + 3, 1, 1); - ext->concealment_motion_vectors = read_bits (data + 3, 2, 1); - ext->q_scale_type = read_bits (data + 3, 3, 1); - ext->intra_vlc_format = read_bits (data + 3, 4, 1); - ext->alternate_scan = read_bits (data + 3, 5, 1); + /* top field first */ + if (!gst_bit_reader_get_bits_uint8 (&reader, &ext->top_field_first, 1)) + return FALSE; + + /* frame pred frame dct */ + if (!gst_bit_reader_get_bits_uint8 (&reader, &ext->frame_pred_frame_dct, 1)) + return FALSE; + + /* concealment motion vectors */ + if (!gst_bit_reader_get_bits_uint8 (&reader, &ext->concealment_motion_vectors, + 1)) + return FALSE; + + /* q scale type */ + if (!gst_bit_reader_get_bits_uint8 (&reader, &ext->q_scale_type, 1)) + return FALSE; + + /* intra vlc format */ + if (!gst_bit_reader_get_bits_uint8 (&reader, &ext->intra_vlc_format, 1)) + return FALSE; + + /* alternate scan */ + if (!gst_bit_reader_get_bits_uint8 (&reader, &ext->alternate_scan, 1)) + return FALSE; + + /* repeat first field */ + if (!gst_bit_reader_get_bits_uint8 (&reader, &ext->repeat_first_field, 1)) + return FALSE; return TRUE; } gboolean -mpeg_util_parse_picture_gop (MPEGPictureGOP * gop, guint8 * data, guint8 * end) +mpeg_util_parse_gop (MPEGGop * gop, GstBuffer * buffer) { - guint32 code; + GstBitReader reader = GST_BIT_READER_INIT_FROM_BUFFER (buffer); - if (G_UNLIKELY ((end - data) < 8)) - return FALSE; /* Packet too small */ + /* skip sync word */ + if (!gst_bit_reader_skip (&reader, 8 * 4)) + return FALSE; - code = GST_READ_UINT32_BE (data); + if (!gst_bit_reader_get_bits_uint8 (&reader, &gop->drop_frame_flag, 1)) + return FALSE; - if (G_UNLIKELY (G_UNLIKELY (code != (0x00000100 | MPEG_PACKET_GOP)))) + if (!gst_bit_reader_get_bits_uint8 (&reader, &gop->hour, 5)) return FALSE; - /* Skip the sync word */ - data += 4; + if (!gst_bit_reader_get_bits_uint8 (&reader, &gop->minute, 6)) + return FALSE; + + /* skip unused bit */ + if (!gst_bit_reader_skip (&reader, 1)) + return FALSE; - gop->drop_frame_flag = read_bits (data, 0, 1); + if (!gst_bit_reader_get_bits_uint8 (&reader, &gop->second, 6)) + return FALSE; - gop->hour = read_bits (data, 1, 5); - gop->minute = read_bits (data, 6, 6); - gop->second = read_bits (data + 1, 4, 6); - gop->frame = read_bits (data + 2, 3, 6); + if (!gst_bit_reader_get_bits_uint8 (&reader, &gop->frame, 6)) + return FALSE; + + if (!gst_bit_reader_get_bits_uint8 (&reader, &gop->closed_gop, 1)) + return FALSE; - gop->closed_gop = read_bits (data + 3, 1, 1); - gop->broken_gop = read_bits (data + 3, 2, 1); + if (!gst_bit_reader_get_bits_uint8 (&reader, &gop->broken_gop, 1)) + return FALSE; return TRUE; } gboolean -mpeg_util_parse_quant_matrix (MPEGQuantMatrix * qm, guint8 * data, guint8 * end) +mpeg_util_parse_quant_matrix (MPEGQuantMatrix * qm, GstBuffer * buffer) { - guint32 code; - gboolean load_intra_flag, load_non_intra_flag; - gint i; - - if (G_UNLIKELY ((end - data) < 5)) - return FALSE; /* Packet too small */ + GstBitReader reader = GST_BIT_READER_INIT_FROM_BUFFER (buffer); + guint8 load_intra_flag, load_non_intra_flag; - code = GST_READ_UINT32_BE (data); - - if (G_UNLIKELY (G_UNLIKELY (code != (0x00000100 | MPEG_PACKET_EXTENSION)))) + /* skip sync word */ + if (!gst_bit_reader_skip (&reader, 8 * 4)) return FALSE; - /* Skip the sync word */ - data += 4; + /* skip extension code */ + if (!gst_bit_reader_skip (&reader, 4)) + return FALSE; - load_intra_flag = read_bits (data, 4, 1); + /* intra quantizer matrix */ + if (!gst_bit_reader_get_bits_uint8 (&reader, &load_intra_flag, 1)) + return FALSE; if (load_intra_flag) { - if (G_UNLIKELY ((end - data) < 64)) - return FALSE; - for (i = 0; i < 64; i++) - qm->intra_quantizer_matrix[mpeg2_scan[i]] = read_bits (data + i, 5, 8); - - data += 64; + gint i; + for (i = 0; i < 64; i++) { + if (!gst_bit_reader_get_bits_uint8 (&reader, + &qm->intra_quantizer_matrix[mpeg2_scan[i]], 8)) + return FALSE; + } } else memcpy (qm->intra_quantizer_matrix, default_intra_quantizer_matrix, 64); - load_non_intra_flag = read_bits (data, 5 + load_intra_flag, 1); + /* non intra quantizer matrix */ + if (!gst_bit_reader_get_bits_uint8 (&reader, &load_non_intra_flag, 1)) + return FALSE; if (load_non_intra_flag) { - if (G_UNLIKELY ((end - data) < 64)) - return FALSE; - for (i = 0; i < 64; i++) - qm->non_intra_quantizer_matrix[mpeg2_scan[i]] = - read_bits (data + i, 6 + load_intra_flag, 8); + gint i; + for (i = 0; i < 64; i++) { + if (!gst_bit_reader_get_bits_uint8 (&reader, + &qm->non_intra_quantizer_matrix[mpeg2_scan[i]], 8)) + return FALSE; + } } else memset (qm->non_intra_quantizer_matrix, 16, 64); diff --git a/sys/vdpau/mpegutil.h b/sys/vdpau/mpegutil.h index 43f34a59..4e5a656a 100644 --- a/sys/vdpau/mpegutil.h +++ b/sys/vdpau/mpegutil.h @@ -24,9 +24,10 @@ #include typedef struct MPEGSeqHdr MPEGSeqHdr; +typedef struct MPEGSeqExtHdr MPEGSeqExtHdr; typedef struct MPEGPictureHdr MPEGPictureHdr; typedef struct MPEGPictureExt MPEGPictureExt; -typedef struct MPEGPictureGOP MPEGPictureGOP; +typedef struct MPEGGop MPEGGop; typedef struct MPEGQuantMatrix MPEGQuantMatrix; /* Packet ID codes for different packet types we @@ -53,27 +54,45 @@ typedef struct MPEGQuantMatrix MPEGQuantMatrix; struct MPEGSeqHdr { - /* 0 for unknown, else 1 or 2 */ - guint8 mpeg_version; - /* Pixel-Aspect Ratio from DAR code via set_par_from_dar */ - gint par_w, par_h; + guint par_w, par_h; /* Width and Height of the video */ - gint width, height; + guint16 width, height; /* Framerate */ - gint fps_n, fps_d; + guint fps_n, fps_d; - /* mpeg2 decoder profile */ - gint profile; + guint32 bitrate; + guint16 vbv_buffer; + guint8 constrained_parameters_flag; + guint8 intra_quantizer_matrix[64]; guint8 non_intra_quantizer_matrix[64]; }; +struct MPEGSeqExtHdr +{ + + /* mpeg2 decoder profile */ + guint8 profile; + /* mpeg2 decoder level */ + guint8 level; + + guint8 progressive; + guint8 chroma_format; + + guint8 horiz_size_ext, vert_size_ext; + + guint8 fps_n_ext, fps_d_ext; + +}; + struct MPEGPictureHdr { + guint16 tsn; guint8 pic_type; - + guint16 vbv_delay; + guint8 full_pel_forward_vector, full_pel_backward_vector; guint8 f_code[2][2]; @@ -91,9 +110,10 @@ struct MPEGPictureExt guint8 q_scale_type; guint8 intra_vlc_format; guint8 alternate_scan; + guint8 repeat_first_field; }; -struct MPEGPictureGOP +struct MPEGGop { guint8 drop_frame_flag; @@ -109,18 +129,19 @@ struct MPEGQuantMatrix guint8 non_intra_quantizer_matrix[64]; }; -gboolean mpeg_util_parse_sequence_hdr (MPEGSeqHdr *hdr, - guint8 *data, guint8 *end); +gboolean mpeg_util_parse_sequence_hdr (MPEGSeqHdr *hdr, GstBuffer *buffer); -gboolean mpeg_util_parse_picture_hdr (MPEGPictureHdr * hdr, guint8 * data, guint8 * end); +gboolean mpeg_util_parse_sequence_extension (MPEGSeqExtHdr *hdr, + GstBuffer *buffer); -gboolean mpeg_util_parse_picture_coding_extension (MPEGPictureExt *ext, guint8 *data, guint8 *end); +gboolean mpeg_util_parse_picture_hdr (MPEGPictureHdr * hdr, GstBuffer *buffer); -gboolean mpeg_util_parse_picture_gop (MPEGPictureGOP * gop, guint8 * data, guint8 * end); +gboolean mpeg_util_parse_picture_coding_extension (MPEGPictureExt *ext, + GstBuffer *buffer); -gboolean mpeg_util_parse_quant_matrix (MPEGQuantMatrix * qm, guint8 * data, guint8 * end); +gboolean mpeg_util_parse_gop (MPEGGop * gop, GstBuffer *buffer); -guint8 *mpeg_util_find_start_code (guint32 * sync_word, guint8 * cur, guint8 * end); -guint32 read_bits (guint8 * buf, gint start_bit, gint n_bits); +gboolean mpeg_util_parse_quant_matrix (MPEGQuantMatrix * qm, GstBuffer *buffer); #endif + -- cgit v1.2.1 From 27606d4e104ec0f78f8ef3c4171d68f5069c7c91 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Thu, 4 Jun 2009 19:17:14 +0200 Subject: vpdaumpegdec: remove useless GstVdpDecoder baseclass --- sys/vdpau/Makefile.am | 2 - sys/vdpau/gstvdpdecoder.c | 229 ------------------------------------------ sys/vdpau/gstvdpdecoder.h | 72 ------------- sys/vdpau/gstvdpmpegdecoder.c | 159 ++++++++++++++++++++--------- sys/vdpau/gstvdpmpegdecoder.h | 18 +++- 5 files changed, 127 insertions(+), 353 deletions(-) delete mode 100644 sys/vdpau/gstvdpdecoder.c delete mode 100644 sys/vdpau/gstvdpdecoder.h diff --git a/sys/vdpau/Makefile.am b/sys/vdpau/Makefile.am index a603ec77..053332b0 100644 --- a/sys/vdpau/Makefile.am +++ b/sys/vdpau/Makefile.am @@ -2,7 +2,6 @@ plugin_LTLIBRARIES = libgstvdpau.la libgstvdpau_la_SOURCES = \ gstvdpdevice.c \ - gstvdpdecoder.c \ gstvdpmpegdecoder.c \ mpegutil.c \ gstvdpvideoyuv.c \ @@ -18,7 +17,6 @@ libgstvdpau_la_LIBTOOLFLAGS = --tag=disable-static noinst_HEADERS = \ gstvdpdevice.h \ - gstvdpdecoder.h \ gstvdpmpegdecoder.h \ mpegutil.h \ gstvdpvideoyuv.h \ diff --git a/sys/vdpau/gstvdpdecoder.c b/sys/vdpau/gstvdpdecoder.c deleted file mode 100644 index b6a28cc7..00000000 --- a/sys/vdpau/gstvdpdecoder.c +++ /dev/null @@ -1,229 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2009 Carl-Anton Ingmarsson - * - * 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. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include - -#include "gstvdpdecoder.h" - -GST_DEBUG_CATEGORY_STATIC (gst_vdp_decoder_debug); -#define GST_CAT_DEFAULT gst_vdp_decoder_debug - -/* Filter signals and args */ -enum -{ - /* FILL ME */ - LAST_SIGNAL -}; - -enum -{ - PROP_0, - PROP_DISPLAY -}; - -static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src", - GST_PAD_SRC, - GST_PAD_ALWAYS, - GST_STATIC_CAPS ("video/x-vdpau-video, " "chroma-type = (int) 0")); - -#define DEBUG_INIT(bla) \ - GST_DEBUG_CATEGORY_INIT (gst_vdp_decoder_debug, "vdpaudecoder", 0, "vdpaudecoder base class"); - -GST_BOILERPLATE_FULL (GstVdpDecoder, gst_vdp_decoder, GstElement, - GST_TYPE_ELEMENT, DEBUG_INIT); - -static void gst_vdp_decoder_finalize (GObject * object); -static void gst_vdp_decoder_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec); -static void gst_vdp_decoder_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec); - -GstFlowReturn -gst_vdp_decoder_push_video_buffer (GstVdpDecoder * dec, - GstVdpVideoBuffer * buffer) -{ - if (GST_BUFFER_TIMESTAMP (buffer) == GST_CLOCK_TIME_NONE) { - GST_BUFFER_TIMESTAMP (buffer) = dec->time + - gst_util_uint64_scale_int (GST_SECOND, - dec->framerate_denominator, dec->framerate_numerator); - } - gst_buffer_set_caps (GST_BUFFER (buffer), GST_PAD_CAPS (dec->src)); - - GST_DEBUG_OBJECT (dec, "Pushing buffer with timestamp: %" GST_TIME_FORMAT, - GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer))); - dec->time = GST_BUFFER_TIMESTAMP (buffer); - - return gst_pad_push (dec->src, GST_BUFFER (buffer)); -} - -static gboolean -gst_vdp_decoder_sink_set_caps (GstPad * pad, GstCaps * caps) -{ - GstVdpDecoder *dec = GST_VDP_DECODER (GST_OBJECT_PARENT (pad)); - GstVdpDecoderClass *dec_class = GST_VDP_DECODER_GET_CLASS (dec); - - GstCaps *src_caps, *new_caps; - GstStructure *structure; - gint width, height; - gint framerate_numerator, framerate_denominator; - gint par_numerator, par_denominator; - gboolean res; - - structure = gst_caps_get_structure (caps, 0); - gst_structure_get_int (structure, "width", &width); - gst_structure_get_int (structure, "height", &height); - gst_structure_get_fraction (structure, "framerate", - &framerate_numerator, &framerate_denominator); - gst_structure_get_fraction (structure, "pixel-aspect-ratio", - &par_numerator, &par_denominator); - - src_caps = gst_pad_get_allowed_caps (dec->src); - if (G_UNLIKELY (!src_caps)) - return FALSE; - - new_caps = gst_caps_copy_nth (src_caps, 0); - gst_caps_unref (src_caps); - structure = gst_caps_get_structure (new_caps, 0); - gst_structure_set (structure, - "device", G_TYPE_OBJECT, dec->device, - "chroma-type", G_TYPE_INT, VDP_CHROMA_TYPE_420, - "width", G_TYPE_INT, width, - "height", G_TYPE_INT, height, - "framerate", GST_TYPE_FRACTION, framerate_numerator, - framerate_denominator, - "pixel-aspect-ratio", GST_TYPE_FRACTION, par_numerator, - par_denominator, NULL); - - gst_pad_fixate_caps (dec->src, new_caps); - res = gst_pad_set_caps (dec->src, new_caps); - - gst_caps_unref (new_caps); - - if (G_UNLIKELY (!res)) - return FALSE; - - dec->width = width; - dec->height = height; - dec->framerate_numerator = framerate_numerator; - dec->framerate_denominator = framerate_denominator; - - if (dec_class->set_caps && !dec_class->set_caps (dec, caps)) - return FALSE; - - return TRUE; -} - -/* GObject vmethod implementations */ - -static void -gst_vdp_decoder_base_init (gpointer klass) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (klass); - - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&src_template)); -} - -/* initialize the vdpaudecoder's class */ -static void -gst_vdp_decoder_class_init (GstVdpDecoderClass * klass) -{ - GObjectClass *gobject_class; - GstElementClass *gstelement_class; - - gobject_class = (GObjectClass *) klass; - gstelement_class = (GstElementClass *) klass; - - gobject_class->finalize = gst_vdp_decoder_finalize; - gobject_class->set_property = gst_vdp_decoder_set_property; - gobject_class->get_property = gst_vdp_decoder_get_property; - - g_object_class_install_property (gobject_class, PROP_DISPLAY, - g_param_spec_string ("display", "Display", "X Display name", - NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); -} - -static void -gst_vdp_decoder_init (GstVdpDecoder * dec, GstVdpDecoderClass * klass) -{ - dec->display_name = NULL; - dec->device = NULL; - - dec->height = 0; - dec->width = 0; - dec->framerate_numerator = 0; - dec->framerate_denominator = 0; - - dec->time = 0; - - dec->src = gst_pad_new_from_static_template (&src_template, "src"); - gst_element_add_pad (GST_ELEMENT (dec), dec->src); - - dec->sink = gst_pad_new_from_template (gst_element_class_get_pad_template - (GST_ELEMENT_CLASS (klass), "sink"), "sink"); - gst_pad_set_setcaps_function (dec->sink, gst_vdp_decoder_sink_set_caps); - gst_element_add_pad (GST_ELEMENT (dec), dec->sink); -} - -static void -gst_vdp_decoder_finalize (GObject * object) -{ - GstVdpDecoder *dec = (GstVdpDecoder *) object; - - g_free (dec->display_name); -} - -static void -gst_vdp_decoder_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstVdpDecoder *dec = GST_VDP_DECODER (object); - - switch (prop_id) { - case PROP_DISPLAY: - g_free (dec->display_name); - dec->display_name = g_value_dup_string (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_vdp_decoder_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - GstVdpDecoder *dec = GST_VDP_DECODER (object); - - switch (prop_id) { - case PROP_DISPLAY: - g_value_set_string (value, dec->display_name); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} diff --git a/sys/vdpau/gstvdpdecoder.h b/sys/vdpau/gstvdpdecoder.h deleted file mode 100644 index f20db20c..00000000 --- a/sys/vdpau/gstvdpdecoder.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2009 Carl-Anton Ingmarsson - * - * 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_VDP_DECODER_H__ -#define __GST_VDP_DECODER_H__ - -#include - -#include "gstvdpdevice.h" -#include "gstvdpvideobuffer.h" - -G_BEGIN_DECLS - -#define GST_TYPE_VDP_DECODER (gst_vdp_decoder_get_type()) -#define GST_VDP_DECODER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VDP_DECODER,GstVdpDecoder)) -#define GST_VDP_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VDP_DECODER,GstVdpDecoderClass)) -#define GST_VDP_DECODER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_VDP_DECODER, GstVdpDecoderClass)) -#define GST_IS_VDPAU_DECODER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VDP_DECODER)) -#define GST_IS_VDPAU_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VDP_DECODER)) - -typedef struct _GstVdpDecoder GstVdpDecoder; -typedef struct _GstVdpDecoderClass GstVdpDecoderClass; -typedef struct _VdpauFunctions VdpauFunctions; - -struct _GstVdpDecoder { - GstElement element; - - gchar *display_name; - GstVdpDevice *device; - - GstPad *src; - GstPad *sink; - - gint width, height; - gint framerate_numerator, framerate_denominator; - guint32 format; - - GstClockTime time; -}; - -struct _GstVdpDecoderClass { - GstElementClass parent_class; - - gboolean (*set_caps) (GstVdpDecoder *dec, GstCaps *caps); -}; - -GType gst_vdp_decoder_get_type (void); - -gboolean gst_vdp_decoder_push_video_buffer (GstVdpDecoder * dec, - GstVdpVideoBuffer *buffer); -VdpVideoSurface gst_vdp_decoder_create_video_surface (GstVdpDecoder *dec); - -G_END_DECLS - -#endif /* __GST_VDP_DECODER_H__ */ diff --git a/sys/vdpau/gstvdpmpegdecoder.c b/sys/vdpau/gstvdpmpegdecoder.c index fc7aa5a6..a501d533 100644 --- a/sys/vdpau/gstvdpmpegdecoder.c +++ b/sys/vdpau/gstvdpmpegdecoder.c @@ -55,25 +55,31 @@ enum enum { - PROP_0 + PROP_0, + PROP_DISPLAY }; /* the capabilities of the inputs and outputs. * * describe the real formats here. */ -static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink", +static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, GST_STATIC_CAPS ("video/mpeg, mpegversion = (int) [ 1, 2 ], " "systemstream = (boolean) false, parsed = (boolean) true") ); +static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("video/x-vdpau-video, " "chroma-type = (int) 0") + ); #define DEBUG_INIT(bla) \ GST_DEBUG_CATEGORY_INIT (gst_vdp_mpeg_decoder_debug, "vdpaumpegdec", 0, "VDPAU powered mpeg decoder"); GST_BOILERPLATE_FULL (GstVdpMpegDecoder, gst_vdp_mpeg_decoder, - GstVdpDecoder, GST_TYPE_VDP_DECODER, DEBUG_INIT); + GstElement, GST_TYPE_ELEMENT, DEBUG_INIT); static void gst_vdp_mpeg_decoder_init_info (VdpPictureInfoMPEG1Or2 * vdp_info); static void gst_vdp_mpeg_decoder_finalize (GObject * object); @@ -153,18 +159,54 @@ gst_vdp_mpeg_packetizer_init (GstVdpMpegPacketizer * packetizer, } static gboolean -gst_vdp_mpeg_decoder_set_caps (GstVdpDecoder * dec, GstCaps * caps) +gst_vdp_mpeg_decoder_set_caps (GstPad * pad, GstCaps * caps) { - GstVdpMpegDecoder *mpeg_dec; + GstVdpMpegDecoder *mpeg_dec = GST_VDP_MPEG_DECODER (GST_OBJECT_PARENT (pad)); GstStructure *structure; + + gint width, height; + gint fps_n, fps_d; + gint par_n, par_d; + gboolean interlaced; + + GstCaps *src_caps; + gboolean res; + const GValue *value; VdpDecoderProfile profile; GstVdpDevice *device; VdpStatus status; - mpeg_dec = GST_VDP_MPEG_DECODER (dec); - structure = gst_caps_get_structure (caps, 0); + + /* create src_pad caps */ + gst_structure_get_int (structure, "width", &width); + gst_structure_get_int (structure, "height", &height); + gst_structure_get_fraction (structure, "framerate", &fps_d, &fps_d); + gst_structure_get_fraction (structure, "pixel-aspect-ratio", &par_n, &par_d); + gst_structure_get_boolean (structure, "interlaced", &interlaced); + + src_caps = gst_caps_new_simple ("video/x-vdpau-video", + "device", G_TYPE_OBJECT, mpeg_dec->device, + "chroma_type", G_TYPE_INT, VDP_CHROMA_TYPE_420, + "width", G_TYPE_INT, width, + "height", G_TYPE_INT, height, + "framerate", GST_TYPE_FRACTION, fps_n, fps_d, + "pixel-aspect-ratio", GST_TYPE_FRACTION, par_n, par_d, + "interlaced", G_TYPE_BOOLEAN, interlaced, NULL); + + res = gst_pad_set_caps (mpeg_dec->src, src_caps); + gst_caps_unref (src_caps); + if (!res) + return FALSE; + + mpeg_dec->width = width; + mpeg_dec->height = height; + mpeg_dec->fps_n = fps_n; + mpeg_dec->fps_d = fps_d; + mpeg_dec->interlaced = interlaced; + + /* parse caps to setup decoder */ gst_structure_get_int (structure, "mpegversion", &mpeg_dec->version); if (mpeg_dec->version == 1) profile = VDP_DECODER_PROFILE_MPEG1; @@ -208,15 +250,15 @@ gst_vdp_mpeg_decoder_set_caps (GstVdpDecoder * dec, GstCaps * caps) } } - device = dec->device; + device = mpeg_dec->device; if (mpeg_dec->decoder != VDP_INVALID_HANDLE) { device->vdp_decoder_destroy (mpeg_dec->decoder); mpeg_dec->decoder = VDP_INVALID_HANDLE; } - status = device->vdp_decoder_create (device->device, profile, dec->width, - dec->height, 2, &mpeg_dec->decoder); + status = device->vdp_decoder_create (device->device, profile, mpeg_dec->width, + mpeg_dec->height, 2, &mpeg_dec->decoder); if (status != VDP_STATUS_OK) { GST_ELEMENT_ERROR (mpeg_dec, RESOURCE, READ, ("Could not create vdpau decoder"), @@ -227,11 +269,29 @@ gst_vdp_mpeg_decoder_set_caps (GstVdpDecoder * dec, GstCaps * caps) return TRUE; } +GstFlowReturn +gst_vdp_mpeg_decoder_push_video_buffer (GstVdpMpegDecoder * mpeg_dec, + GstVdpVideoBuffer * buffer) +{ + if (GST_BUFFER_TIMESTAMP (buffer) == GST_CLOCK_TIME_NONE) { + GST_BUFFER_TIMESTAMP (buffer) = mpeg_dec->time + + gst_util_uint64_scale_int (GST_SECOND, + mpeg_dec->fps_d, mpeg_dec->fps_n); + } + gst_buffer_set_caps (GST_BUFFER (buffer), GST_PAD_CAPS (mpeg_dec->src)); + + GST_DEBUG_OBJECT (mpeg_dec, + "Pushing buffer with timestamp: %" GST_TIME_FORMAT, + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer))); + mpeg_dec->time = GST_BUFFER_TIMESTAMP (buffer); + + return gst_pad_push (mpeg_dec->src, GST_BUFFER (buffer)); +} + static GstFlowReturn gst_vdp_mpeg_decoder_decode (GstVdpMpegDecoder * mpeg_dec, GstClockTime timestamp) { - GstVdpDecoder *dec; VdpPictureInfoMPEG1Or2 *info; GstBuffer *buffer; GstVdpVideoBuffer *outbuf; @@ -240,7 +300,6 @@ gst_vdp_mpeg_decoder_decode (GstVdpMpegDecoder * mpeg_dec, VdpBitstreamBuffer vbit[1]; VdpStatus status; - dec = GST_VDP_DECODER (mpeg_dec); info = &mpeg_dec->vdp_info; buffer = gst_adapter_take_buffer (mpeg_dec->adapter, @@ -249,7 +308,7 @@ gst_vdp_mpeg_decoder_decode (GstVdpMpegDecoder * mpeg_dec, if (info->picture_coding_type != B_FRAME) { if (info->backward_reference != VDP_INVALID_HANDLE) { gst_buffer_ref (mpeg_dec->b_buffer); - gst_vdp_decoder_push_video_buffer (dec, + gst_vdp_mpeg_decoder_push_video_buffer (mpeg_dec, GST_VDP_VIDEO_BUFFER (mpeg_dec->b_buffer)); } @@ -264,8 +323,8 @@ gst_vdp_mpeg_decoder_decode (GstVdpMpegDecoder * mpeg_dec, info->backward_reference = VDP_INVALID_HANDLE; } - outbuf = gst_vdp_video_buffer_new (dec->device, VDP_CHROMA_TYPE_420, - dec->width, dec->height); + outbuf = gst_vdp_video_buffer_new (mpeg_dec->device, VDP_CHROMA_TYPE_420, + mpeg_dec->width, mpeg_dec->height); GST_BUFFER_TIMESTAMP (outbuf) = timestamp; if (info->forward_reference != VDP_INVALID_HANDLE && @@ -279,7 +338,7 @@ gst_vdp_mpeg_decoder_decode (GstVdpMpegDecoder * mpeg_dec, surface = outbuf->surface; - device = dec->device; + device = mpeg_dec->device; vbit[0].struct_version = VDP_BITSTREAM_BUFFER_VERSION; vbit[0].bitstream = GST_BUFFER_DATA (buffer); @@ -302,7 +361,8 @@ gst_vdp_mpeg_decoder_decode (GstVdpMpegDecoder * mpeg_dec, } if (info->picture_coding_type == B_FRAME) { - gst_vdp_decoder_push_video_buffer (dec, GST_VDP_VIDEO_BUFFER (outbuf)); + gst_vdp_mpeg_decoder_push_video_buffer (mpeg_dec, + GST_VDP_VIDEO_BUFFER (outbuf)); } else { info->backward_reference = surface; mpeg_dec->b_buffer = GST_BUFFER (outbuf); @@ -315,11 +375,9 @@ static gboolean gst_vdp_mpeg_decoder_parse_picture_coding (GstVdpMpegDecoder * mpeg_dec, GstBuffer * buffer) { - GstVdpDecoder *dec; MPEGPictureExt pic_ext; VdpPictureInfoMPEG1Or2 *info; - dec = GST_VDP_DECODER (mpeg_dec); info = &mpeg_dec->vdp_info; if (!mpeg_util_parse_picture_coding_extension (&pic_ext, buffer)) @@ -343,11 +401,8 @@ static gboolean gst_vdp_mpeg_decoder_parse_sequence (GstVdpMpegDecoder * mpeg_dec, GstBuffer * buffer) { - GstVdpDecoder *dec; MPEGSeqHdr hdr; - dec = GST_VDP_DECODER (mpeg_dec); - if (!mpeg_util_parse_sequence_hdr (&hdr, buffer)) return FALSE; @@ -364,11 +419,8 @@ static gboolean gst_vdp_mpeg_decoder_parse_picture (GstVdpMpegDecoder * mpeg_dec, GstBuffer * buffer) { - GstVdpDecoder *dec; MPEGPictureHdr pic_hdr; - dec = GST_VDP_DECODER (mpeg_dec); - if (!mpeg_util_parse_picture_hdr (&pic_hdr, buffer)) return FALSE; @@ -532,20 +584,16 @@ gst_vdp_mpeg_decoder_chain (GstPad * pad, GstBuffer * buffer) static gboolean gst_vdp_mpeg_decoder_sink_event (GstPad * pad, GstEvent * event) { - GstVdpMpegDecoder *mpeg_dec; - GstVdpDecoder *dec; + GstVdpMpegDecoder *mpeg_dec = GST_VDP_MPEG_DECODER (GST_OBJECT_PARENT (pad)); gboolean res; - mpeg_dec = GST_VDP_MPEG_DECODER (GST_OBJECT_PARENT (pad)); - dec = GST_VDP_DECODER (mpeg_dec); - switch (GST_EVENT_TYPE (event)) { case GST_EVENT_FLUSH_STOP: { GST_DEBUG_OBJECT (mpeg_dec, "flush stop"); gst_vdp_mpeg_decoder_reset (mpeg_dec); - res = gst_pad_push_event (dec->src, event); + res = gst_pad_push_event (mpeg_dec->src, event); break; } @@ -561,15 +609,13 @@ gst_vdp_mpeg_decoder_change_state (GstElement * element, GstStateChange transition) { GstVdpMpegDecoder *mpeg_dec; - GstVdpDecoder *dec; GstStateChangeReturn ret; mpeg_dec = GST_VDP_MPEG_DECODER (element); - dec = GST_VDP_DECODER (mpeg_dec); switch (transition) { case GST_STATE_CHANGE_READY_TO_PAUSED: - dec->device = gst_vdp_get_device (dec->display_name); + mpeg_dec->device = gst_vdp_get_device (mpeg_dec->display_name); break; default: break; @@ -581,11 +627,11 @@ gst_vdp_mpeg_decoder_change_state (GstElement * element, case GST_STATE_CHANGE_PAUSED_TO_READY: gst_vdp_mpeg_decoder_reset (mpeg_dec); - dec->device->vdp_decoder_destroy (mpeg_dec->decoder); + mpeg_dec->device->vdp_decoder_destroy (mpeg_dec->decoder); mpeg_dec->decoder = VDP_INVALID_HANDLE; - g_object_unref (dec->device); - dec->device = NULL; + g_object_unref (mpeg_dec->device); + mpeg_dec->device = NULL; break; default: break; @@ -608,7 +654,9 @@ gst_vdp_mpeg_decoder_base_init (gpointer gclass) "Carl-Anton Ingmarsson "); gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&sink_factory)); + gst_static_pad_template_get (&sink_template)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&src_template)); } /* initialize the vdpaumpegdecoder's class */ @@ -617,19 +665,19 @@ gst_vdp_mpeg_decoder_class_init (GstVdpMpegDecoderClass * klass) { GObjectClass *gobject_class; GstElementClass *gstelement_class; - GstVdpDecoderClass *vdpaudec_class; gobject_class = (GObjectClass *) klass; gstelement_class = (GstElementClass *) klass; - vdpaudec_class = (GstVdpDecoderClass *) klass; gobject_class->finalize = gst_vdp_mpeg_decoder_finalize; gobject_class->set_property = gst_vdp_mpeg_decoder_set_property; gobject_class->get_property = gst_vdp_mpeg_decoder_get_property; - vdpaudec_class->set_caps = gst_vdp_mpeg_decoder_set_caps; - gstelement_class->change_state = gst_vdp_mpeg_decoder_change_state; + + g_object_class_install_property (gobject_class, PROP_DISPLAY, + g_param_spec_string ("display", "Display", "X Display name", + NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); } static void @@ -653,19 +701,25 @@ static void gst_vdp_mpeg_decoder_init (GstVdpMpegDecoder * mpeg_dec, GstVdpMpegDecoderClass * gclass) { - GstVdpDecoder *dec; + mpeg_dec->src = gst_pad_new_from_static_template (&src_template, "src"); + gst_element_add_pad (GST_ELEMENT (mpeg_dec), mpeg_dec->src); - dec = GST_VDP_DECODER (mpeg_dec); + mpeg_dec->sink = gst_pad_new_from_static_template (&sink_template, "sink"); + gst_pad_set_setcaps_function (mpeg_dec->sink, gst_vdp_mpeg_decoder_set_caps); + gst_pad_set_chain_function (mpeg_dec->sink, gst_vdp_mpeg_decoder_chain); + gst_pad_set_event_function (mpeg_dec->sink, gst_vdp_mpeg_decoder_sink_event); + gst_element_add_pad (GST_ELEMENT (mpeg_dec), mpeg_dec->sink); + + mpeg_dec->display_name = NULL; + mpeg_dec->device = NULL; mpeg_dec->decoder = VDP_INVALID_HANDLE; gst_vdp_mpeg_decoder_init_info (&mpeg_dec->vdp_info); mpeg_dec->broken_gop = FALSE; + mpeg_dec->time = 0; mpeg_dec->adapter = gst_adapter_new (); - - gst_pad_set_chain_function (dec->sink, gst_vdp_mpeg_decoder_chain); - gst_pad_set_event_function (dec->sink, gst_vdp_mpeg_decoder_sink_event); } static void @@ -680,7 +734,13 @@ static void gst_vdp_mpeg_decoder_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { + GstVdpMpegDecoder *mpeg_dec = GST_VDP_MPEG_DECODER (object); + switch (prop_id) { + case PROP_DISPLAY: + g_free (mpeg_dec->display_name); + mpeg_dec->display_name = g_value_dup_string (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -691,7 +751,12 @@ static void gst_vdp_mpeg_decoder_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { + GstVdpMpegDecoder *mpeg_dec = GST_VDP_MPEG_DECODER (object); + switch (prop_id) { + case PROP_DISPLAY: + g_value_set_string (value, mpeg_dec->display_name); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; diff --git a/sys/vdpau/gstvdpmpegdecoder.h b/sys/vdpau/gstvdpmpegdecoder.h index 06bed84b..a48e0c97 100644 --- a/sys/vdpau/gstvdpmpegdecoder.h +++ b/sys/vdpau/gstvdpmpegdecoder.h @@ -24,7 +24,8 @@ #include #include -#include "gstvdpdecoder.h" +#include "gstvdpdevice.h" +#include "gstvdpvideobuffer.h" G_BEGIN_DECLS @@ -39,8 +40,18 @@ typedef struct _GstVdpMpegDecoderClass GstVdpMpegDecoderClass; struct _GstVdpMpegDecoder { - GstVdpDecoder dec; + GstElement element; + gchar *display_name; + GstVdpDevice *device; + + GstPad *src; + GstPad *sink; + + gint width, height; + gint fps_n, fps_d; + gboolean interlaced; + gint version; VdpDecoder decoder; @@ -49,13 +60,14 @@ struct _GstVdpMpegDecoder GstBuffer *b_buffer; gboolean broken_gop; + GstClockTime time; GstAdapter *adapter; }; struct _GstVdpMpegDecoderClass { - GstVdpDecoderClass parent_class; + GstElementClass element_class; }; GType gst_vdp_mpeg_decoder_get_type (void); -- cgit v1.2.1 From aee19375793395486b07679f30e3bed5e85119ea Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Thu, 4 Jun 2009 19:30:02 +0200 Subject: vdpaumpegdec: fix so that the first frame in a raw mpegvideo stream get timestamp 0 --- sys/vdpau/gstvdpmpegdecoder.c | 11 ++++++----- sys/vdpau/gstvdpmpegdecoder.h | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/sys/vdpau/gstvdpmpegdecoder.c b/sys/vdpau/gstvdpmpegdecoder.c index a501d533..dbb87c38 100644 --- a/sys/vdpau/gstvdpmpegdecoder.c +++ b/sys/vdpau/gstvdpmpegdecoder.c @@ -274,16 +274,17 @@ gst_vdp_mpeg_decoder_push_video_buffer (GstVdpMpegDecoder * mpeg_dec, GstVdpVideoBuffer * buffer) { if (GST_BUFFER_TIMESTAMP (buffer) == GST_CLOCK_TIME_NONE) { - GST_BUFFER_TIMESTAMP (buffer) = mpeg_dec->time + - gst_util_uint64_scale_int (GST_SECOND, - mpeg_dec->fps_d, mpeg_dec->fps_n); + GST_BUFFER_TIMESTAMP (buffer) = mpeg_dec->next_timestamp; } + + mpeg_dec->next_timestamp = GST_BUFFER_TIMESTAMP (buffer) + + gst_util_uint64_scale_int (GST_SECOND, mpeg_dec->fps_d, mpeg_dec->fps_n); + gst_buffer_set_caps (GST_BUFFER (buffer), GST_PAD_CAPS (mpeg_dec->src)); GST_DEBUG_OBJECT (mpeg_dec, "Pushing buffer with timestamp: %" GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer))); - mpeg_dec->time = GST_BUFFER_TIMESTAMP (buffer); return gst_pad_push (mpeg_dec->src, GST_BUFFER (buffer)); } @@ -717,7 +718,7 @@ gst_vdp_mpeg_decoder_init (GstVdpMpegDecoder * mpeg_dec, gst_vdp_mpeg_decoder_init_info (&mpeg_dec->vdp_info); mpeg_dec->broken_gop = FALSE; - mpeg_dec->time = 0; + mpeg_dec->next_timestamp = 0; mpeg_dec->adapter = gst_adapter_new (); } diff --git a/sys/vdpau/gstvdpmpegdecoder.h b/sys/vdpau/gstvdpmpegdecoder.h index a48e0c97..3e1bc731 100644 --- a/sys/vdpau/gstvdpmpegdecoder.h +++ b/sys/vdpau/gstvdpmpegdecoder.h @@ -60,7 +60,7 @@ struct _GstVdpMpegDecoder GstBuffer *b_buffer; gboolean broken_gop; - GstClockTime time; + GstClockTime next_timestamp; GstAdapter *adapter; }; -- cgit v1.2.1 From df3c59a48286f242649aa3279b1c522b2b1fb1c7 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Thu, 4 Jun 2009 21:17:40 +0200 Subject: vdpaumpegdec: calculate correct duration from data in MPEG_PACKET_EXT_PICTURE_CODING --- sys/vdpau/gstvdpmpegdecoder.c | 40 +++++++++++++++++++++++++++++++++++++--- sys/vdpau/gstvdpmpegdecoder.h | 1 + sys/vdpau/mpegutil.c | 8 ++++++++ sys/vdpau/mpegutil.h | 2 ++ 4 files changed, 48 insertions(+), 3 deletions(-) diff --git a/sys/vdpau/gstvdpmpegdecoder.c b/sys/vdpau/gstvdpmpegdecoder.c index dbb87c38..008a2428 100644 --- a/sys/vdpau/gstvdpmpegdecoder.c +++ b/sys/vdpau/gstvdpmpegdecoder.c @@ -182,7 +182,7 @@ gst_vdp_mpeg_decoder_set_caps (GstPad * pad, GstCaps * caps) /* create src_pad caps */ gst_structure_get_int (structure, "width", &width); gst_structure_get_int (structure, "height", &height); - gst_structure_get_fraction (structure, "framerate", &fps_d, &fps_d); + gst_structure_get_fraction (structure, "framerate", &fps_n, &fps_d); gst_structure_get_fraction (structure, "pixel-aspect-ratio", &par_n, &par_d); gst_structure_get_boolean (structure, "interlaced", &interlaced); @@ -278,7 +278,7 @@ gst_vdp_mpeg_decoder_push_video_buffer (GstVdpMpegDecoder * mpeg_dec, } mpeg_dec->next_timestamp = GST_BUFFER_TIMESTAMP (buffer) + - gst_util_uint64_scale_int (GST_SECOND, mpeg_dec->fps_d, mpeg_dec->fps_n); + GST_BUFFER_DURATION (buffer); gst_buffer_set_caps (GST_BUFFER (buffer), GST_PAD_CAPS (mpeg_dec->src)); @@ -327,6 +327,7 @@ gst_vdp_mpeg_decoder_decode (GstVdpMpegDecoder * mpeg_dec, outbuf = gst_vdp_video_buffer_new (mpeg_dec->device, VDP_CHROMA_TYPE_420, mpeg_dec->width, mpeg_dec->height); GST_BUFFER_TIMESTAMP (outbuf) = timestamp; + GST_BUFFER_DURATION (outbuf) = mpeg_dec->duration; if (info->forward_reference != VDP_INVALID_HANDLE && info->picture_coding_type != I_FRAME) @@ -378,6 +379,7 @@ gst_vdp_mpeg_decoder_parse_picture_coding (GstVdpMpegDecoder * mpeg_dec, { MPEGPictureExt pic_ext; VdpPictureInfoMPEG1Or2 *info; + gint fields; info = &mpeg_dec->vdp_info; @@ -395,6 +397,36 @@ gst_vdp_mpeg_decoder_parse_picture_coding (GstVdpMpegDecoder * mpeg_dec, info->intra_vlc_format = pic_ext.intra_vlc_format; info->alternate_scan = pic_ext.alternate_scan; + fields = 0; + if (pic_ext.picture_structure == 3) { + if (mpeg_dec->interlaced) { + if (pic_ext.progressive_frame == 0) + fields = 2; + if (pic_ext.progressive_frame == 0 && pic_ext.repeat_first_field == 0) + fields = 2; + if (pic_ext.progressive_frame == 1 && pic_ext.repeat_first_field == 1) + fields = 3; + } else { + if (pic_ext.repeat_first_field == 0) + fields = 2; + if (pic_ext.repeat_first_field == 1 && pic_ext.top_field_first == 0) + fields = 4; + if (pic_ext.repeat_first_field == 1 && pic_ext.top_field_first == 1) + fields = 6; + } + } else + fields = 1; + + GST_DEBUG ("fields: %d", fields); + + if (!fields) { + GST_DEBUG ("Invalid Picture Extension packet"); + return FALSE; + } + + mpeg_dec->duration = gst_util_uint64_scale (fields, + GST_SECOND * mpeg_dec->fps_d, 2 * mpeg_dec->fps_n); + return TRUE; } @@ -407,7 +439,6 @@ gst_vdp_mpeg_decoder_parse_sequence (GstVdpMpegDecoder * mpeg_dec, if (!mpeg_util_parse_sequence_hdr (&hdr, buffer)) return FALSE; - g_debug ("här"); memcpy (&mpeg_dec->vdp_info.intra_quantizer_matrix, &hdr.intra_quantizer_matrix, 64); memcpy (&mpeg_dec->vdp_info.non_intra_quantizer_matrix, @@ -448,6 +479,9 @@ gst_vdp_mpeg_decoder_parse_picture (GstVdpMpegDecoder * mpeg_dec, memcpy (&mpeg_dec->vdp_info.f_code, &pic_hdr.f_code, 4); } + mpeg_dec->duration = gst_util_uint64_scale (1, GST_SECOND * mpeg_dec->fps_d, + mpeg_dec->fps_n); + return TRUE; } diff --git a/sys/vdpau/gstvdpmpegdecoder.h b/sys/vdpau/gstvdpmpegdecoder.h index 3e1bc731..facc791b 100644 --- a/sys/vdpau/gstvdpmpegdecoder.h +++ b/sys/vdpau/gstvdpmpegdecoder.h @@ -60,6 +60,7 @@ struct _GstVdpMpegDecoder GstBuffer *b_buffer; gboolean broken_gop; + GstClockTime duration; GstClockTime next_timestamp; GstAdapter *adapter; diff --git a/sys/vdpau/mpegutil.c b/sys/vdpau/mpegutil.c index c35ad9fb..bba84f2b 100644 --- a/sys/vdpau/mpegutil.c +++ b/sys/vdpau/mpegutil.c @@ -333,6 +333,14 @@ mpeg_util_parse_picture_coding_extension (MPEGPictureExt * ext, if (!gst_bit_reader_get_bits_uint8 (&reader, &ext->repeat_first_field, 1)) return FALSE; + /* chroma_420_type */ + if (!gst_bit_reader_get_bits_uint8 (&reader, &ext->chroma_420_type, 1)) + return FALSE; + + /* progressive_frame */ + if (!gst_bit_reader_get_bits_uint8 (&reader, &ext->progressive_frame, 1)) + return FALSE; + return TRUE; } diff --git a/sys/vdpau/mpegutil.h b/sys/vdpau/mpegutil.h index 4e5a656a..08f6cc2f 100644 --- a/sys/vdpau/mpegutil.h +++ b/sys/vdpau/mpegutil.h @@ -111,6 +111,8 @@ struct MPEGPictureExt guint8 intra_vlc_format; guint8 alternate_scan; guint8 repeat_first_field; + guint8 chroma_420_type; + guint8 progressive_frame; }; struct MPEGGop -- cgit v1.2.1 From adeddd0118cf4506247d9589cca8c14cd35df4a5 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Fri, 5 Jun 2009 11:17:16 +0200 Subject: vdpaumpegdec: handle GST_QUERY_POSITION and GST_QUERY_DURATION --- sys/vdpau/gstvdpmpegdecoder.c | 110 ++++++++++++++++++++++++++++++++++++++++++ sys/vdpau/gstvdpmpegdecoder.h | 2 + sys/vdpau/mpegutil.c | 5 +- sys/vdpau/mpegutil.h | 1 + 4 files changed, 117 insertions(+), 1 deletion(-) diff --git a/sys/vdpau/gstvdpmpegdecoder.c b/sys/vdpau/gstvdpmpegdecoder.c index 008a2428..19c096f6 100644 --- a/sys/vdpau/gstvdpmpegdecoder.c +++ b/sys/vdpau/gstvdpmpegdecoder.c @@ -220,6 +220,7 @@ gst_vdp_mpeg_decoder_set_caps (GstPad * pad, GstCaps * caps) gst_vdp_mpeg_packetizer_init (&packetizer, codec_data); if ((buf = gst_vdp_mpeg_packetizer_get_next_packet (&packetizer))) { MPEGSeqHdr hdr; + guint32 bitrate; mpeg_util_parse_sequence_hdr (&hdr, buf); @@ -228,6 +229,7 @@ gst_vdp_mpeg_decoder_set_caps (GstPad * pad, GstCaps * caps) memcpy (&mpeg_dec->vdp_info.non_intra_quantizer_matrix, &hdr.non_intra_quantizer_matrix, 64); + bitrate = hdr.bitrate; gst_buffer_unref (buf); if ((buf = gst_vdp_mpeg_packetizer_get_next_packet (&packetizer))) { @@ -245,8 +247,12 @@ gst_vdp_mpeg_decoder_set_caps (GstPad * pad, GstCaps * caps) } } + bitrate += (ext.bitrate_ext << 18);; gst_buffer_unref (buf); } + + mpeg_dec->byterate = bitrate * 50; + GST_DEBUG ("byterate: %" G_GINT64_FORMAT, mpeg_dec->byterate); } } @@ -526,6 +532,8 @@ gst_vdp_mpeg_decoder_reset (GstVdpMpegDecoder * mpeg_dec) gst_vdp_mpeg_decoder_init_info (&mpeg_dec->vdp_info); gst_adapter_clear (mpeg_dec->adapter); + + //mpeg_dec->byterate = -1; } static GstFlowReturn @@ -616,6 +624,105 @@ gst_vdp_mpeg_decoder_chain (GstPad * pad, GstBuffer * buffer) return ret; } +static gboolean +gst_vdp_mpeg_decoder_convert (GstVdpMpegDecoder * mpeg_dec, + GstFormat src_format, gint64 src_value, + GstFormat dest_format, gint64 * dest_value) +{ + + if (src_format == dest_format) { + *dest_value = src_value; + return TRUE; + } + + if (mpeg_dec->byterate == -1) + return FALSE; + + if (src_format == GST_FORMAT_BYTES && dest_format == GST_FORMAT_TIME) { + *dest_value = gst_util_uint64_scale (GST_SECOND, src_value, + mpeg_dec->byterate); + return TRUE; + } + + if (src_format == GST_FORMAT_TIME && dest_format == GST_FORMAT_BYTES) { + *dest_value = + gst_util_uint64_scale_int (src_value, mpeg_dec->byterate, GST_SECOND); + return TRUE; + } + + return FALSE; +} + +static const GstQueryType * +gst_mpeg_decoder_get_querytypes (GstPad * pad) +{ + static const GstQueryType list[] = { + GST_QUERY_POSITION, + GST_QUERY_DURATION, + 0 + }; + + return list; +} + +static gboolean +gst_vdp_mpeg_decoder_src_query (GstPad * pad, GstQuery * query) +{ + GstVdpMpegDecoder *mpeg_dec = GST_VDP_MPEG_DECODER (GST_OBJECT_PARENT (pad)); + gboolean res = FALSE; + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_POSITION: + { + GstFormat format; + + if (gst_pad_query_default (pad, query)) + return TRUE; + + gst_query_parse_position (query, &format, NULL); + if (format == GST_FORMAT_TIME && + GST_CLOCK_TIME_IS_VALID (mpeg_dec->next_timestamp)) { + gst_query_set_position (query, GST_FORMAT_TIME, + mpeg_dec->next_timestamp); + res = TRUE; + } + break; + } + + case GST_QUERY_DURATION: + { + GstFormat format; + + if (gst_pad_query_default (pad, query)) + return TRUE; + + gst_query_parse_duration (query, &format, NULL); + if (format == GST_FORMAT_TIME) { + gint64 bytes; + + format = GST_FORMAT_BYTES; + if (gst_pad_query_duration (pad, &format, &bytes) + && format == GST_FORMAT_BYTES) { + gint64 duration; + + if (gst_vdp_mpeg_decoder_convert (mpeg_dec, GST_FORMAT_BYTES, + bytes, GST_FORMAT_TIME, &duration)) { + GST_DEBUG ("duration: %" GST_TIME_FORMAT, GST_TIME_ARGS (duration)); + gst_query_set_duration (query, GST_FORMAT_TIME, duration); + res = TRUE; + } + } + } + break; + } + + default: + res = gst_pad_query_default (pad, query); + } + + return res; +} + static gboolean gst_vdp_mpeg_decoder_sink_event (GstPad * pad, GstEvent * event) { @@ -737,6 +844,9 @@ gst_vdp_mpeg_decoder_init (GstVdpMpegDecoder * mpeg_dec, GstVdpMpegDecoderClass * gclass) { mpeg_dec->src = gst_pad_new_from_static_template (&src_template, "src"); + gst_pad_set_query_function (mpeg_dec->src, gst_vdp_mpeg_decoder_src_query); + gst_pad_set_query_type_function (mpeg_dec->src, + gst_mpeg_decoder_get_querytypes); gst_element_add_pad (GST_ELEMENT (mpeg_dec), mpeg_dec->src); mpeg_dec->sink = gst_pad_new_from_static_template (&sink_template, "sink"); diff --git a/sys/vdpau/gstvdpmpegdecoder.h b/sys/vdpau/gstvdpmpegdecoder.h index facc791b..597101f8 100644 --- a/sys/vdpau/gstvdpmpegdecoder.h +++ b/sys/vdpau/gstvdpmpegdecoder.h @@ -62,6 +62,8 @@ struct _GstVdpMpegDecoder gboolean broken_gop; GstClockTime duration; GstClockTime next_timestamp; + + gint64 byterate; GstAdapter *adapter; }; diff --git a/sys/vdpau/mpegutil.c b/sys/vdpau/mpegutil.c index bba84f2b..5348bd6a 100644 --- a/sys/vdpau/mpegutil.c +++ b/sys/vdpau/mpegutil.c @@ -135,8 +135,11 @@ mpeg_util_parse_sequence_extension (MPEGSeqExtHdr * hdr, GstBuffer * buffer) if (!gst_bit_reader_get_bits_uint8 (&reader, &hdr->vert_size_ext, 2)) return FALSE; + if (!gst_bit_reader_get_bits_uint16 (&reader, &hdr->bitrate_ext, 12)) + return FALSE; + /* skip to framerate extension */ - if (!gst_bit_reader_skip (&reader, 22)) + if (!gst_bit_reader_skip (&reader, 9)) return FALSE; /* framerate extension */ diff --git a/sys/vdpau/mpegutil.h b/sys/vdpau/mpegutil.h index 08f6cc2f..aaaa15f8 100644 --- a/sys/vdpau/mpegutil.h +++ b/sys/vdpau/mpegutil.h @@ -83,6 +83,7 @@ struct MPEGSeqExtHdr guint8 horiz_size_ext, vert_size_ext; + guint16 bitrate_ext; guint8 fps_n_ext, fps_d_ext; }; -- cgit v1.2.1 From 92335b1a12ff49f9da5050bd8a842a11dd94907e Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Fri, 5 Jun 2009 11:20:56 +0200 Subject: vdpaumpegdec: don't drop discont buffers --- sys/vdpau/gstvdpmpegdecoder.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sys/vdpau/gstvdpmpegdecoder.c b/sys/vdpau/gstvdpmpegdecoder.c index 19c096f6..c4c5c54f 100644 --- a/sys/vdpau/gstvdpmpegdecoder.c +++ b/sys/vdpau/gstvdpmpegdecoder.c @@ -549,7 +549,6 @@ gst_vdp_mpeg_decoder_chain (GstPad * pad, GstBuffer * buffer) if (G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT))) { GST_DEBUG_OBJECT (mpeg_dec, "Received discont buffer"); gst_vdp_mpeg_decoder_reset (mpeg_dec); - return GST_FLOW_OK; } gst_vdp_mpeg_packetizer_init (&packetizer, buffer); -- cgit v1.2.1 From f80a7279579850ec2e8ceb0d1e5f56ccb7110f66 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Fri, 5 Jun 2009 11:24:34 +0200 Subject: vdpaumpegdec: use GSE_DEBUG_FUNCPTR --- sys/vdpau/gstvdpmpegdecoder.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/sys/vdpau/gstvdpmpegdecoder.c b/sys/vdpau/gstvdpmpegdecoder.c index c4c5c54f..3a161c3a 100644 --- a/sys/vdpau/gstvdpmpegdecoder.c +++ b/sys/vdpau/gstvdpmpegdecoder.c @@ -814,7 +814,8 @@ gst_vdp_mpeg_decoder_class_init (GstVdpMpegDecoderClass * klass) gobject_class->set_property = gst_vdp_mpeg_decoder_set_property; gobject_class->get_property = gst_vdp_mpeg_decoder_get_property; - gstelement_class->change_state = gst_vdp_mpeg_decoder_change_state; + gstelement_class->change_state = + GST_DEBUG_FUNCPTR (gst_vdp_mpeg_decoder_change_state); g_object_class_install_property (gobject_class, PROP_DISPLAY, g_param_spec_string ("display", "Display", "X Display name", @@ -843,15 +844,19 @@ gst_vdp_mpeg_decoder_init (GstVdpMpegDecoder * mpeg_dec, GstVdpMpegDecoderClass * gclass) { mpeg_dec->src = gst_pad_new_from_static_template (&src_template, "src"); - gst_pad_set_query_function (mpeg_dec->src, gst_vdp_mpeg_decoder_src_query); + gst_pad_set_query_function (mpeg_dec->src, + GST_DEBUG_FUNCPTR (gst_vdp_mpeg_decoder_src_query)); gst_pad_set_query_type_function (mpeg_dec->src, - gst_mpeg_decoder_get_querytypes); + GST_DEBUG_FUNCPTR (gst_mpeg_decoder_get_querytypes)); gst_element_add_pad (GST_ELEMENT (mpeg_dec), mpeg_dec->src); mpeg_dec->sink = gst_pad_new_from_static_template (&sink_template, "sink"); - gst_pad_set_setcaps_function (mpeg_dec->sink, gst_vdp_mpeg_decoder_set_caps); - gst_pad_set_chain_function (mpeg_dec->sink, gst_vdp_mpeg_decoder_chain); - gst_pad_set_event_function (mpeg_dec->sink, gst_vdp_mpeg_decoder_sink_event); + gst_pad_set_setcaps_function (mpeg_dec->sink, + GST_DEBUG_FUNCPTR (gst_vdp_mpeg_decoder_set_caps)); + gst_pad_set_chain_function (mpeg_dec->sink, + GST_DEBUG_FUNCPTR (gst_vdp_mpeg_decoder_chain)); + gst_pad_set_event_function (mpeg_dec->sink, + GST_DEBUG_FUNCPTR (gst_vdp_mpeg_decoder_sink_event)); gst_element_add_pad (GST_ELEMENT (mpeg_dec), mpeg_dec->sink); mpeg_dec->display_name = NULL; -- cgit v1.2.1 From e2d8cc99b0436adba5503e3679e4ba21877aee23 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Fri, 5 Jun 2009 11:51:41 +0200 Subject: vdpaumpegdec: add new gst_vdp_mpeg_decoder_flush for flushing the decoder --- sys/vdpau/gstvdpmpegdecoder.c | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/sys/vdpau/gstvdpmpegdecoder.c b/sys/vdpau/gstvdpmpegdecoder.c index 3a161c3a..bee76f1f 100644 --- a/sys/vdpau/gstvdpmpegdecoder.c +++ b/sys/vdpau/gstvdpmpegdecoder.c @@ -522,7 +522,7 @@ gst_vdp_mpeg_decoder_parse_quant_matrix (GstVdpMpegDecoder * mpeg_dec, } static void -gst_vdp_mpeg_decoder_reset (GstVdpMpegDecoder * mpeg_dec) +gst_vdp_mpeg_decoder_flush (GstVdpMpegDecoder * mpeg_dec) { if (mpeg_dec->vdp_info.forward_reference != VDP_INVALID_HANDLE) gst_buffer_unref (mpeg_dec->f_buffer); @@ -532,8 +532,22 @@ gst_vdp_mpeg_decoder_reset (GstVdpMpegDecoder * mpeg_dec) gst_vdp_mpeg_decoder_init_info (&mpeg_dec->vdp_info); gst_adapter_clear (mpeg_dec->adapter); +} + +static void +gst_vdp_mpeg_decoder_reset (GstVdpMpegDecoder * mpeg_dec) +{ + gst_vdp_mpeg_decoder_flush (mpeg_dec); - //mpeg_dec->byterate = -1; + if (mpeg_dec->decoder != VDP_INVALID_HANDLE) + mpeg_dec->device->vdp_decoder_destroy (mpeg_dec->decoder); + mpeg_dec->decoder = VDP_INVALID_HANDLE; + if (mpeg_dec->device) + g_object_unref (mpeg_dec->device); + mpeg_dec->device = NULL; + + mpeg_dec->broken_gop = FALSE; + mpeg_dec->next_timestamp = 0; } static GstFlowReturn @@ -548,7 +562,7 @@ gst_vdp_mpeg_decoder_chain (GstPad * pad, GstBuffer * buffer) if (G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT))) { GST_DEBUG_OBJECT (mpeg_dec, "Received discont buffer"); - gst_vdp_mpeg_decoder_reset (mpeg_dec); + gst_vdp_mpeg_decoder_flush (mpeg_dec); } gst_vdp_mpeg_packetizer_init (&packetizer, buffer); @@ -733,7 +747,7 @@ gst_vdp_mpeg_decoder_sink_event (GstPad * pad, GstEvent * event) { GST_DEBUG_OBJECT (mpeg_dec, "flush stop"); - gst_vdp_mpeg_decoder_reset (mpeg_dec); + gst_vdp_mpeg_decoder_flush (mpeg_dec); res = gst_pad_push_event (mpeg_dec->src, event); break; @@ -767,12 +781,6 @@ gst_vdp_mpeg_decoder_change_state (GstElement * element, switch (transition) { case GST_STATE_CHANGE_PAUSED_TO_READY: gst_vdp_mpeg_decoder_reset (mpeg_dec); - - mpeg_dec->device->vdp_decoder_destroy (mpeg_dec->decoder); - mpeg_dec->decoder = VDP_INVALID_HANDLE; - - g_object_unref (mpeg_dec->device); - mpeg_dec->device = NULL; break; default: break; @@ -860,15 +868,14 @@ gst_vdp_mpeg_decoder_init (GstVdpMpegDecoder * mpeg_dec, gst_element_add_pad (GST_ELEMENT (mpeg_dec), mpeg_dec->sink); mpeg_dec->display_name = NULL; - mpeg_dec->device = NULL; - - mpeg_dec->decoder = VDP_INVALID_HANDLE; - gst_vdp_mpeg_decoder_init_info (&mpeg_dec->vdp_info); + mpeg_dec->adapter = gst_adapter_new (); mpeg_dec->broken_gop = FALSE; mpeg_dec->next_timestamp = 0; - mpeg_dec->adapter = gst_adapter_new (); + mpeg_dec->device = NULL; + mpeg_dec->decoder = VDP_INVALID_HANDLE; + gst_vdp_mpeg_decoder_init_info (&mpeg_dec->vdp_info); } static void -- cgit v1.2.1 From f4c0de5a678a7d81c7caf963b8b67a0a102c5f3a Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Fri, 5 Jun 2009 11:52:32 +0200 Subject: vdpaumpegdec: remove unused broken_gop field --- sys/vdpau/gstvdpmpegdecoder.c | 4 ---- sys/vdpau/gstvdpmpegdecoder.h | 1 - 2 files changed, 5 deletions(-) diff --git a/sys/vdpau/gstvdpmpegdecoder.c b/sys/vdpau/gstvdpmpegdecoder.c index bee76f1f..b2c59344 100644 --- a/sys/vdpau/gstvdpmpegdecoder.c +++ b/sys/vdpau/gstvdpmpegdecoder.c @@ -500,8 +500,6 @@ gst_vdp_mpeg_decoder_parse_gop (GstVdpMpegDecoder * mpeg_dec, if (!mpeg_util_parse_gop (&gop, buffer)) return FALSE; - mpeg_dec->broken_gop = gop.broken_gop; - return TRUE; } @@ -546,7 +544,6 @@ gst_vdp_mpeg_decoder_reset (GstVdpMpegDecoder * mpeg_dec) g_object_unref (mpeg_dec->device); mpeg_dec->device = NULL; - mpeg_dec->broken_gop = FALSE; mpeg_dec->next_timestamp = 0; } @@ -870,7 +867,6 @@ gst_vdp_mpeg_decoder_init (GstVdpMpegDecoder * mpeg_dec, mpeg_dec->display_name = NULL; mpeg_dec->adapter = gst_adapter_new (); - mpeg_dec->broken_gop = FALSE; mpeg_dec->next_timestamp = 0; mpeg_dec->device = NULL; diff --git a/sys/vdpau/gstvdpmpegdecoder.h b/sys/vdpau/gstvdpmpegdecoder.h index 597101f8..37b7ead3 100644 --- a/sys/vdpau/gstvdpmpegdecoder.h +++ b/sys/vdpau/gstvdpmpegdecoder.h @@ -59,7 +59,6 @@ struct _GstVdpMpegDecoder GstBuffer *f_buffer; GstBuffer *b_buffer; - gboolean broken_gop; GstClockTime duration; GstClockTime next_timestamp; -- cgit v1.2.1 From 016f24f8be5a441e070a8e0c941ab050079f3ec9 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Fri, 5 Jun 2009 11:54:17 +0200 Subject: vdpaumpegdec: change a GST_DEBUG to GST_WARNING --- sys/vdpau/gstvdpmpegdecoder.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sys/vdpau/gstvdpmpegdecoder.c b/sys/vdpau/gstvdpmpegdecoder.c index b2c59344..3e817185 100644 --- a/sys/vdpau/gstvdpmpegdecoder.c +++ b/sys/vdpau/gstvdpmpegdecoder.c @@ -426,7 +426,7 @@ gst_vdp_mpeg_decoder_parse_picture_coding (GstVdpMpegDecoder * mpeg_dec, GST_DEBUG ("fields: %d", fields); if (!fields) { - GST_DEBUG ("Invalid Picture Extension packet"); + GST_WARNING ("Invalid Picture Extension packet"); return FALSE; } -- cgit v1.2.1 From 7316cfa186322a4b3c2e6df558a41e1ecc8c6e91 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Fri, 5 Jun 2009 17:43:49 +0200 Subject: vdpaumpegdec: implement seeking --- sys/vdpau/gstvdpmpegdecoder.c | 169 ++++++++++++++++++++++++++++++++++++++++-- sys/vdpau/gstvdpmpegdecoder.h | 5 ++ 2 files changed, 166 insertions(+), 8 deletions(-) diff --git a/sys/vdpau/gstvdpmpegdecoder.c b/sys/vdpau/gstvdpmpegdecoder.c index 3e817185..b6964175 100644 --- a/sys/vdpau/gstvdpmpegdecoder.c +++ b/sys/vdpau/gstvdpmpegdecoder.c @@ -279,10 +279,25 @@ GstFlowReturn gst_vdp_mpeg_decoder_push_video_buffer (GstVdpMpegDecoder * mpeg_dec, GstVdpVideoBuffer * buffer) { - if (GST_BUFFER_TIMESTAMP (buffer) == GST_CLOCK_TIME_NONE) { + if (GST_BUFFER_TIMESTAMP (buffer) == GST_CLOCK_TIME_NONE + && GST_CLOCK_TIME_IS_VALID (mpeg_dec->next_timestamp)) { GST_BUFFER_TIMESTAMP (buffer) = mpeg_dec->next_timestamp; + } else if (GST_BUFFER_TIMESTAMP (buffer) == GST_CLOCK_TIME_NONE) { + GST_BUFFER_TIMESTAMP (buffer) = gst_util_uint64_scale (mpeg_dec->frame_nr, + GST_SECOND * mpeg_dec->fps_d, mpeg_dec->fps_n); } + if (mpeg_dec->seeking) { + GstEvent *event; + + event = gst_event_new_new_segment (FALSE, + mpeg_dec->segment.rate, GST_FORMAT_TIME, GST_BUFFER_TIMESTAMP (buffer), + mpeg_dec->segment.stop, GST_BUFFER_TIMESTAMP (buffer)); + + gst_pad_push_event (mpeg_dec->src, event); + } + mpeg_dec->seeking = FALSE; + mpeg_dec->next_timestamp = GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer); @@ -334,6 +349,7 @@ gst_vdp_mpeg_decoder_decode (GstVdpMpegDecoder * mpeg_dec, mpeg_dec->width, mpeg_dec->height); GST_BUFFER_TIMESTAMP (outbuf) = timestamp; GST_BUFFER_DURATION (outbuf) = mpeg_dec->duration; + GST_BUFFER_OFFSET (outbuf) = mpeg_dec->frame_nr; if (info->forward_reference != VDP_INVALID_HANDLE && info->picture_coding_type != I_FRAME) @@ -403,7 +419,7 @@ gst_vdp_mpeg_decoder_parse_picture_coding (GstVdpMpegDecoder * mpeg_dec, info->intra_vlc_format = pic_ext.intra_vlc_format; info->alternate_scan = pic_ext.alternate_scan; - fields = 0; + fields = 2; if (pic_ext.picture_structure == 3) { if (mpeg_dec->interlaced) { if (pic_ext.progressive_frame == 0) @@ -425,11 +441,6 @@ gst_vdp_mpeg_decoder_parse_picture_coding (GstVdpMpegDecoder * mpeg_dec, GST_DEBUG ("fields: %d", fields); - if (!fields) { - GST_WARNING ("Invalid Picture Extension packet"); - return FALSE; - } - mpeg_dec->duration = gst_util_uint64_scale (fields, GST_SECOND * mpeg_dec->fps_d, 2 * mpeg_dec->fps_n); @@ -488,6 +499,8 @@ gst_vdp_mpeg_decoder_parse_picture (GstVdpMpegDecoder * mpeg_dec, mpeg_dec->duration = gst_util_uint64_scale (1, GST_SECOND * mpeg_dec->fps_d, mpeg_dec->fps_n); + mpeg_dec->frame_nr = mpeg_dec->gop_frame + pic_hdr.tsn; + return TRUE; } @@ -496,10 +509,19 @@ gst_vdp_mpeg_decoder_parse_gop (GstVdpMpegDecoder * mpeg_dec, GstBuffer * buffer) { MPEGGop gop; + GstClockTime time; if (!mpeg_util_parse_gop (&gop, buffer)) return FALSE; + time = GST_SECOND * (gop.hour * 3600 + gop.minute * 60 + gop.second); + + GST_DEBUG ("gop timestamp: %" GST_TIME_FORMAT, GST_TIME_ARGS (time)); + + mpeg_dec->gop_frame = + gst_util_uint64_scale (time, mpeg_dec->fps_n, + mpeg_dec->fps_d * GST_SECOND) + gop.frame; + return TRUE; } @@ -530,6 +552,8 @@ gst_vdp_mpeg_decoder_flush (GstVdpMpegDecoder * mpeg_dec) gst_vdp_mpeg_decoder_init_info (&mpeg_dec->vdp_info); gst_adapter_clear (mpeg_dec->adapter); + + mpeg_dec->next_timestamp = GST_CLOCK_TIME_NONE; } static void @@ -544,7 +568,8 @@ gst_vdp_mpeg_decoder_reset (GstVdpMpegDecoder * mpeg_dec) g_object_unref (mpeg_dec->device); mpeg_dec->device = NULL; - mpeg_dec->next_timestamp = 0; + gst_segment_init (&mpeg_dec->segment, GST_FORMAT_TIME); + mpeg_dec->seeking = FALSE; } static GstFlowReturn @@ -733,6 +758,94 @@ gst_vdp_mpeg_decoder_src_query (GstPad * pad, GstQuery * query) return res; } +static gboolean +normal_seek (GstPad * pad, GstEvent * event) +{ + GstVdpMpegDecoder *mpeg_dec = GST_VDP_MPEG_DECODER (GST_OBJECT_PARENT (pad)); + gdouble rate; + GstFormat format, conv; + GstSeekFlags flags; + GstSeekType cur_type, stop_type; + gint64 cur, stop; + gint64 time_cur, bytes_cur; + gint64 time_stop, bytes_stop; + gboolean res; + GstEvent *peer_event; + + GST_DEBUG ("normal seek"); + + gst_event_parse_seek (event, &rate, &format, &flags, + &cur_type, &cur, &stop_type, &stop); + + conv = GST_FORMAT_TIME; + if (!gst_vdp_mpeg_decoder_convert (mpeg_dec, format, cur, conv, &time_cur)) + goto convert_failed; + if (!gst_vdp_mpeg_decoder_convert (mpeg_dec, format, stop, conv, &time_stop)) + goto convert_failed; + + GST_DEBUG ("seek to time %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT, + GST_TIME_ARGS (time_cur), GST_TIME_ARGS (time_stop)); + + peer_event = gst_event_new_seek (rate, GST_FORMAT_TIME, flags, + cur_type, time_cur, stop_type, time_stop); + + /* try seek on time then */ + if ((res = gst_pad_push_event (mpeg_dec->sink, peer_event))) + goto done; + + /* else we try to seek on bytes */ + conv = GST_FORMAT_BYTES; + if (!gst_vdp_mpeg_decoder_convert (mpeg_dec, GST_FORMAT_TIME, time_cur, + conv, &bytes_cur)) + goto convert_failed; + if (!gst_vdp_mpeg_decoder_convert (mpeg_dec, GST_FORMAT_TIME, time_stop, + conv, &bytes_stop)) + goto convert_failed; + + /* conversion succeeded, create the seek */ + peer_event = + gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, + cur_type, bytes_cur, stop_type, bytes_stop); + + /* do the seek */ + res = gst_pad_push_event (mpeg_dec->sink, peer_event); + + mpeg_dec->seeking = TRUE; + +done: + return res; + + /* ERRORS */ +convert_failed: + { + /* probably unsupported seek format */ + GST_DEBUG_OBJECT (mpeg_dec, + "failed to convert format %u into GST_FORMAT_TIME", format); + return FALSE; + } +} + +static gboolean +gst_vdp_mpeg_decoder_src_event (GstPad * pad, GstEvent * event) +{ + gboolean res; + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_SEEK: + { + if (gst_pad_event_default (pad, event)) + return TRUE; + + res = normal_seek (pad, event); + break; + } + default: + res = gst_pad_event_default (pad, event); + } + + return res; +} + static gboolean gst_vdp_mpeg_decoder_sink_event (GstPad * pad, GstEvent * event) { @@ -749,6 +862,42 @@ gst_vdp_mpeg_decoder_sink_event (GstPad * pad, GstEvent * event) break; } + case GST_EVENT_NEWSEGMENT: + { + gboolean update; + gdouble rate; + GstFormat format; + gint64 start; + gint64 stop; + gint64 position; + + gst_event_parse_new_segment (event, &update, &rate, &format, + &start, &stop, &position); + + if (format != GST_FORMAT_TIME) { + if (!gst_vdp_mpeg_decoder_convert (mpeg_dec, format, start, + GST_FORMAT_TIME, &start)) + goto convert_error; + if (!gst_vdp_mpeg_decoder_convert (mpeg_dec, format, stop, + GST_FORMAT_TIME, &stop)) + goto convert_error; + if (!gst_vdp_mpeg_decoder_convert (mpeg_dec, format, position, + GST_FORMAT_TIME, &position)) + goto convert_error; + + gst_segment_set_newsegment (&mpeg_dec->segment, update, rate, + GST_FORMAT_TIME, start, stop, position); + + gst_event_unref (event); + event = gst_event_new_new_segment (update, rate, GST_FORMAT_TIME, start, + stop, position); + } + + convert_error: + gst_pad_push_event (mpeg_dec->src, event); + + break; + } default: res = gst_pad_event_default (pad, event); } @@ -849,6 +998,8 @@ gst_vdp_mpeg_decoder_init (GstVdpMpegDecoder * mpeg_dec, GstVdpMpegDecoderClass * gclass) { mpeg_dec->src = gst_pad_new_from_static_template (&src_template, "src"); + gst_pad_set_event_function (mpeg_dec->src, + GST_DEBUG_FUNCPTR (gst_vdp_mpeg_decoder_src_event)); gst_pad_set_query_function (mpeg_dec->src, GST_DEBUG_FUNCPTR (gst_vdp_mpeg_decoder_src_query)); gst_pad_set_query_type_function (mpeg_dec->src, @@ -872,6 +1023,8 @@ gst_vdp_mpeg_decoder_init (GstVdpMpegDecoder * mpeg_dec, mpeg_dec->device = NULL; mpeg_dec->decoder = VDP_INVALID_HANDLE; gst_vdp_mpeg_decoder_init_info (&mpeg_dec->vdp_info); + + gst_segment_init (&mpeg_dec->segment, GST_FORMAT_TIME); } static void diff --git a/sys/vdpau/gstvdpmpegdecoder.h b/sys/vdpau/gstvdpmpegdecoder.h index 37b7ead3..9a57e283 100644 --- a/sys/vdpau/gstvdpmpegdecoder.h +++ b/sys/vdpau/gstvdpmpegdecoder.h @@ -62,6 +62,11 @@ struct _GstVdpMpegDecoder GstClockTime duration; GstClockTime next_timestamp; + guint64 gop_frame; + guint64 frame_nr; + + GstSegment segment; + gboolean seeking; gint64 byterate; GstAdapter *adapter; -- cgit v1.2.1 From 3864e0349bb29a7a5bb4ff5961c2e72a14500811 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Fri, 5 Jun 2009 17:53:16 +0200 Subject: vdpaumpegdec: don't send the EVENT_NEWSEGMENT downstream if we're seeking --- sys/vdpau/gstvdpmpegdecoder.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/sys/vdpau/gstvdpmpegdecoder.c b/sys/vdpau/gstvdpmpegdecoder.c index b6964175..db01527d 100644 --- a/sys/vdpau/gstvdpmpegdecoder.c +++ b/sys/vdpau/gstvdpmpegdecoder.c @@ -893,8 +893,15 @@ gst_vdp_mpeg_decoder_sink_event (GstPad * pad, GstEvent * event) stop, position); } + /* if we seek ourselves we don't push out a newsegment now since we + * use the calculated timestamp of the first frame for this */ + if (mpeg_dec->seeking) { + gst_event_unref (event); + return TRUE; + } + convert_error: - gst_pad_push_event (mpeg_dec->src, event); + res = gst_pad_push_event (mpeg_dec->src, event); break; } -- cgit v1.2.1 From 757086e3fa0b034b1b9b145f65a0512acc21f4d2 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Fri, 5 Jun 2009 18:18:38 +0200 Subject: vdpaumpegdec: only set base duration once --- sys/vdpau/gstvdpmpegdecoder.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/sys/vdpau/gstvdpmpegdecoder.c b/sys/vdpau/gstvdpmpegdecoder.c index db01527d..9475a948 100644 --- a/sys/vdpau/gstvdpmpegdecoder.c +++ b/sys/vdpau/gstvdpmpegdecoder.c @@ -251,6 +251,10 @@ gst_vdp_mpeg_decoder_set_caps (GstPad * pad, GstCaps * caps) gst_buffer_unref (buf); } + mpeg_dec->duration = + gst_util_uint64_scale (1, GST_SECOND * mpeg_dec->fps_d, + mpeg_dec->fps_n); + mpeg_dec->byterate = bitrate * 50; GST_DEBUG ("byterate: %" G_GINT64_FORMAT, mpeg_dec->byterate); } @@ -496,9 +500,6 @@ gst_vdp_mpeg_decoder_parse_picture (GstVdpMpegDecoder * mpeg_dec, memcpy (&mpeg_dec->vdp_info.f_code, &pic_hdr.f_code, 4); } - mpeg_dec->duration = gst_util_uint64_scale (1, GST_SECOND * mpeg_dec->fps_d, - mpeg_dec->fps_n); - mpeg_dec->frame_nr = mpeg_dec->gop_frame + pic_hdr.tsn; return TRUE; @@ -1025,13 +1026,12 @@ gst_vdp_mpeg_decoder_init (GstVdpMpegDecoder * mpeg_dec, mpeg_dec->display_name = NULL; mpeg_dec->adapter = gst_adapter_new (); - mpeg_dec->next_timestamp = 0; - mpeg_dec->device = NULL; mpeg_dec->decoder = VDP_INVALID_HANDLE; - gst_vdp_mpeg_decoder_init_info (&mpeg_dec->vdp_info); + mpeg_dec->vdp_info.forward_reference = VDP_INVALID_HANDLE; + mpeg_dec->vdp_info.backward_reference = VDP_INVALID_HANDLE; - gst_segment_init (&mpeg_dec->segment, GST_FORMAT_TIME); + gst_vdp_mpeg_decoder_reset (mpeg_dec); } static void -- cgit v1.2.1 From b2aa8ae9454cf0b57c98b11c3909759e1968490e Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Fri, 5 Jun 2009 18:28:17 +0200 Subject: vdpaumpegdec: interlaced fixes --- sys/vdpau/gstvdpmpegdecoder.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sys/vdpau/gstvdpmpegdecoder.c b/sys/vdpau/gstvdpmpegdecoder.c index 9475a948..fd06ea3b 100644 --- a/sys/vdpau/gstvdpmpegdecoder.c +++ b/sys/vdpau/gstvdpmpegdecoder.c @@ -167,7 +167,7 @@ gst_vdp_mpeg_decoder_set_caps (GstPad * pad, GstCaps * caps) gint width, height; gint fps_n, fps_d; gint par_n, par_d; - gboolean interlaced; + gboolean interlaced = FALSE; GstCaps *src_caps; gboolean res; @@ -354,6 +354,8 @@ gst_vdp_mpeg_decoder_decode (GstVdpMpegDecoder * mpeg_dec, GST_BUFFER_TIMESTAMP (outbuf) = timestamp; GST_BUFFER_DURATION (outbuf) = mpeg_dec->duration; GST_BUFFER_OFFSET (outbuf) = mpeg_dec->frame_nr; + if (info->top_field_first) + GST_BUFFER_FLAG_SET (outbuf, GST_VIDEO_BUFFER_TFF); if (info->forward_reference != VDP_INVALID_HANDLE && info->picture_coding_type != I_FRAME) -- cgit v1.2.1 From c9464b98604dd6023f5985f4d29e1bb4051d58ee Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Fri, 5 Jun 2009 19:08:24 +0200 Subject: vdpaumpegdec: print frame_nr in debug print --- sys/vdpau/gstvdpmpegdecoder.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sys/vdpau/gstvdpmpegdecoder.c b/sys/vdpau/gstvdpmpegdecoder.c index fd06ea3b..04bebb8a 100644 --- a/sys/vdpau/gstvdpmpegdecoder.c +++ b/sys/vdpau/gstvdpmpegdecoder.c @@ -308,8 +308,10 @@ gst_vdp_mpeg_decoder_push_video_buffer (GstVdpMpegDecoder * mpeg_dec, gst_buffer_set_caps (GST_BUFFER (buffer), GST_PAD_CAPS (mpeg_dec->src)); GST_DEBUG_OBJECT (mpeg_dec, - "Pushing buffer with timestamp: %" GST_TIME_FORMAT, - GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer))); + "Pushing buffer with timestamp: %" GST_TIME_FORMAT + " frame_nr: %" G_GINT64_FORMAT, + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)), + GST_BUFFER_OFFSET (buffer)); return gst_pad_push (mpeg_dec->src, GST_BUFFER (buffer)); } -- cgit v1.2.1 From c4276ae568934f5f14beab02199849f6aeb757ac Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Fri, 5 Jun 2009 21:16:48 +0200 Subject: vdpaumpegdec: calculate byterate from the size of the incoming data --- sys/vdpau/gstvdpmpegdecoder.c | 16 ++++++++++++++++ sys/vdpau/gstvdpmpegdecoder.h | 34 ++++++++++++++++++++++------------ 2 files changed, 38 insertions(+), 12 deletions(-) diff --git a/sys/vdpau/gstvdpmpegdecoder.c b/sys/vdpau/gstvdpmpegdecoder.c index 04bebb8a..53e99a5f 100644 --- a/sys/vdpau/gstvdpmpegdecoder.c +++ b/sys/vdpau/gstvdpmpegdecoder.c @@ -283,6 +283,8 @@ GstFlowReturn gst_vdp_mpeg_decoder_push_video_buffer (GstVdpMpegDecoder * mpeg_dec, GstVdpVideoBuffer * buffer) { + gint64 byterate; + if (GST_BUFFER_TIMESTAMP (buffer) == GST_CLOCK_TIME_NONE && GST_CLOCK_TIME_IS_VALID (mpeg_dec->next_timestamp)) { GST_BUFFER_TIMESTAMP (buffer) = mpeg_dec->next_timestamp; @@ -305,6 +307,14 @@ gst_vdp_mpeg_decoder_push_video_buffer (GstVdpMpegDecoder * mpeg_dec, mpeg_dec->next_timestamp = GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer); + mpeg_dec->accumulated_duration += GST_BUFFER_DURATION (buffer); + mpeg_dec->accumulated_size += GST_BUFFER_SIZE (buffer); + byterate = gst_util_uint64_scale (mpeg_dec->accumulated_size, GST_SECOND, + mpeg_dec->accumulated_duration); + GST_DEBUG ("byterate: %" G_GINT64_FORMAT, mpeg_dec->byterate); + + mpeg_dec->byterate = (mpeg_dec->byterate + byterate) / 2; + gst_buffer_set_caps (GST_BUFFER (buffer), GST_PAD_CAPS (mpeg_dec->src)); GST_DEBUG_OBJECT (mpeg_dec, @@ -356,6 +366,8 @@ gst_vdp_mpeg_decoder_decode (GstVdpMpegDecoder * mpeg_dec, GST_BUFFER_TIMESTAMP (outbuf) = timestamp; GST_BUFFER_DURATION (outbuf) = mpeg_dec->duration; GST_BUFFER_OFFSET (outbuf) = mpeg_dec->frame_nr; + GST_BUFFER_SIZE (outbuf) = mpeg_dec->size; + if (info->top_field_first) GST_BUFFER_FLAG_SET (outbuf, GST_VIDEO_BUFFER_TFF); @@ -575,6 +587,9 @@ gst_vdp_mpeg_decoder_reset (GstVdpMpegDecoder * mpeg_dec) gst_segment_init (&mpeg_dec->segment, GST_FORMAT_TIME); mpeg_dec->seeking = FALSE; + + mpeg_dec->accumulated_size = 0; + mpeg_dec->accumulated_duration = 0; } static GstFlowReturn @@ -592,6 +607,7 @@ gst_vdp_mpeg_decoder_chain (GstPad * pad, GstBuffer * buffer) gst_vdp_mpeg_decoder_flush (mpeg_dec); } + mpeg_dec->size = GST_BUFFER_SIZE (buffer); gst_vdp_mpeg_packetizer_init (&packetizer, buffer); while ((buf = gst_vdp_mpeg_packetizer_get_next_packet (&packetizer))) { GstBitReader b_reader = GST_BIT_READER_INIT_FROM_BUFFER (buf); diff --git a/sys/vdpau/gstvdpmpegdecoder.h b/sys/vdpau/gstvdpmpegdecoder.h index 9a57e283..3cd521ba 100644 --- a/sys/vdpau/gstvdpmpegdecoder.h +++ b/sys/vdpau/gstvdpmpegdecoder.h @@ -42,34 +42,44 @@ struct _GstVdpMpegDecoder { GstElement element; - gchar *display_name; - GstVdpDevice *device; - + /* pads */ GstPad *src; GstPad *sink; + + gchar *display_name; + GstVdpDevice *device; + VdpDecoder decoder; + /* stream info */ gint width, height; gint fps_n, fps_d; gboolean interlaced; - gint version; - - VdpDecoder decoder; + + /* currently decoded frame info */ + GstAdapter *adapter; VdpPictureInfoMPEG1Or2 vdp_info; - GstBuffer *f_buffer; - GstBuffer *b_buffer; - + guint64 size; + guint64 frame_nr; GstClockTime duration; - GstClockTime next_timestamp; + /* frame_nr from GOP */ guint64 gop_frame; - guint64 frame_nr; + + /* forward and backward reference */ + GstBuffer *f_buffer; + GstBuffer *b_buffer; + /* calculated timestamp, size and duration */ + GstClockTime next_timestamp; + guint64 accumulated_size; + guint64 accumulated_duration; + + /* seek data */ GstSegment segment; gboolean seeking; gint64 byterate; - GstAdapter *adapter; }; struct _GstVdpMpegDecoderClass -- cgit v1.2.1 From 7c0e5b5c22e0556567978d13b2c00b9c758d3513 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Fri, 5 Jun 2009 21:18:47 +0200 Subject: vdpaumpegdec: small cleanup --- sys/vdpau/gstvdpmpegdecoder.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sys/vdpau/gstvdpmpegdecoder.c b/sys/vdpau/gstvdpmpegdecoder.c index 53e99a5f..da4f63ec 100644 --- a/sys/vdpau/gstvdpmpegdecoder.c +++ b/sys/vdpau/gstvdpmpegdecoder.c @@ -301,8 +301,9 @@ gst_vdp_mpeg_decoder_push_video_buffer (GstVdpMpegDecoder * mpeg_dec, mpeg_dec->segment.stop, GST_BUFFER_TIMESTAMP (buffer)); gst_pad_push_event (mpeg_dec->src, event); + + mpeg_dec->seeking = FALSE; } - mpeg_dec->seeking = FALSE; mpeg_dec->next_timestamp = GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer); -- cgit v1.2.1 From 5956df5338d0f3f3763bd8aa9e0e4b7b501a8469 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Fri, 5 Jun 2009 21:42:30 +0200 Subject: vdpaumpegdec: pass buffer size directly to gst_vdp_mpeg_decoder_decode --- sys/vdpau/gstvdpmpegdecoder.c | 8 ++++---- sys/vdpau/gstvdpmpegdecoder.h | 1 - 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/sys/vdpau/gstvdpmpegdecoder.c b/sys/vdpau/gstvdpmpegdecoder.c index da4f63ec..6968c347 100644 --- a/sys/vdpau/gstvdpmpegdecoder.c +++ b/sys/vdpau/gstvdpmpegdecoder.c @@ -329,7 +329,7 @@ gst_vdp_mpeg_decoder_push_video_buffer (GstVdpMpegDecoder * mpeg_dec, static GstFlowReturn gst_vdp_mpeg_decoder_decode (GstVdpMpegDecoder * mpeg_dec, - GstClockTime timestamp) + GstClockTime timestamp, gint64 size) { VdpPictureInfoMPEG1Or2 *info; GstBuffer *buffer; @@ -367,7 +367,7 @@ gst_vdp_mpeg_decoder_decode (GstVdpMpegDecoder * mpeg_dec, GST_BUFFER_TIMESTAMP (outbuf) = timestamp; GST_BUFFER_DURATION (outbuf) = mpeg_dec->duration; GST_BUFFER_OFFSET (outbuf) = mpeg_dec->frame_nr; - GST_BUFFER_SIZE (outbuf) = mpeg_dec->size; + GST_BUFFER_SIZE (outbuf) = size; if (info->top_field_first) GST_BUFFER_FLAG_SET (outbuf, GST_VIDEO_BUFFER_TFF); @@ -608,7 +608,6 @@ gst_vdp_mpeg_decoder_chain (GstPad * pad, GstBuffer * buffer) gst_vdp_mpeg_decoder_flush (mpeg_dec); } - mpeg_dec->size = GST_BUFFER_SIZE (buffer); gst_vdp_mpeg_packetizer_init (&packetizer, buffer); while ((buf = gst_vdp_mpeg_packetizer_get_next_packet (&packetizer))) { GstBitReader b_reader = GST_BIT_READER_INIT_FROM_BUFFER (buf); @@ -676,7 +675,8 @@ gst_vdp_mpeg_decoder_chain (GstPad * pad, GstBuffer * buffer) } if (mpeg_dec->vdp_info.slice_count > 0) - ret = gst_vdp_mpeg_decoder_decode (mpeg_dec, GST_BUFFER_TIMESTAMP (buffer)); + ret = gst_vdp_mpeg_decoder_decode (mpeg_dec, GST_BUFFER_TIMESTAMP (buffer), + GST_BUFFER_SIZE (buffer)); return ret; } diff --git a/sys/vdpau/gstvdpmpegdecoder.h b/sys/vdpau/gstvdpmpegdecoder.h index 3cd521ba..e1300862 100644 --- a/sys/vdpau/gstvdpmpegdecoder.h +++ b/sys/vdpau/gstvdpmpegdecoder.h @@ -59,7 +59,6 @@ struct _GstVdpMpegDecoder /* currently decoded frame info */ GstAdapter *adapter; VdpPictureInfoMPEG1Or2 vdp_info; - guint64 size; guint64 frame_nr; GstClockTime duration; -- cgit v1.2.1 From f0134f18472a55581383f15a32d692cb5adf0e53 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Fri, 5 Jun 2009 21:46:08 +0200 Subject: vdpaumpegdec: rename GstVdpMpegDecoder to GstVdpMpegDec --- sys/vdpau/gstvdp.c | 2 +- sys/vdpau/gstvdpmpegdecoder.c | 156 ++++++++++++++++++++---------------------- sys/vdpau/gstvdpmpegdecoder.h | 26 +++---- 3 files changed, 90 insertions(+), 94 deletions(-) diff --git a/sys/vdpau/gstvdp.c b/sys/vdpau/gstvdp.c index 8d5be3dc..43360483 100644 --- a/sys/vdpau/gstvdp.c +++ b/sys/vdpau/gstvdp.c @@ -13,7 +13,7 @@ static gboolean vdpau_init (GstPlugin * vdpau_plugin) { gst_element_register (vdpau_plugin, "vdpaumpegdec", - GST_RANK_PRIMARY - 1, GST_TYPE_VDP_MPEG_DECODER); + GST_RANK_PRIMARY - 1, GST_TYPE_VDP_MPEG_DEC); gst_element_register (vdpau_plugin, "vdpauvideoyuv", GST_RANK_PRIMARY, GST_TYPE_VDP_VIDEO_YUV); gst_element_register (vdpau_plugin, "vdpauyuvvideo", diff --git a/sys/vdpau/gstvdpmpegdecoder.c b/sys/vdpau/gstvdpmpegdecoder.c index 6968c347..3c4d7480 100644 --- a/sys/vdpau/gstvdpmpegdecoder.c +++ b/sys/vdpau/gstvdpmpegdecoder.c @@ -43,8 +43,8 @@ #include "mpegutil.h" #include "gstvdpmpegdecoder.h" -GST_DEBUG_CATEGORY_STATIC (gst_vdp_mpeg_decoder_debug); -#define GST_CAT_DEFAULT gst_vdp_mpeg_decoder_debug +GST_DEBUG_CATEGORY_STATIC (gst_vdp_mpeg_dec_debug); +#define GST_CAT_DEFAULT gst_vdp_mpeg_dec_debug /* Filter signals and args */ enum @@ -76,16 +76,16 @@ static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src", ); #define DEBUG_INIT(bla) \ -GST_DEBUG_CATEGORY_INIT (gst_vdp_mpeg_decoder_debug, "vdpaumpegdec", 0, "VDPAU powered mpeg decoder"); +GST_DEBUG_CATEGORY_INIT (gst_vdp_mpeg_dec_debug, "vdpaumpegdec", 0, "VDPAU powered mpeg decoder"); -GST_BOILERPLATE_FULL (GstVdpMpegDecoder, gst_vdp_mpeg_decoder, +GST_BOILERPLATE_FULL (GstVdpMpegDec, gst_vdp_mpeg_dec, GstElement, GST_TYPE_ELEMENT, DEBUG_INIT); -static void gst_vdp_mpeg_decoder_init_info (VdpPictureInfoMPEG1Or2 * vdp_info); -static void gst_vdp_mpeg_decoder_finalize (GObject * object); -static void gst_vdp_mpeg_decoder_set_property (GObject * object, +static void gst_vdp_mpeg_dec_init_info (VdpPictureInfoMPEG1Or2 * vdp_info); +static void gst_vdp_mpeg_dec_finalize (GObject * object); +static void gst_vdp_mpeg_dec_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec); -static void gst_vdp_mpeg_decoder_get_property (GObject * object, +static void gst_vdp_mpeg_dec_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); guint8 * @@ -159,9 +159,9 @@ gst_vdp_mpeg_packetizer_init (GstVdpMpegPacketizer * packetizer, } static gboolean -gst_vdp_mpeg_decoder_set_caps (GstPad * pad, GstCaps * caps) +gst_vdp_mpeg_dec_set_caps (GstPad * pad, GstCaps * caps) { - GstVdpMpegDecoder *mpeg_dec = GST_VDP_MPEG_DECODER (GST_OBJECT_PARENT (pad)); + GstVdpMpegDec *mpeg_dec = GST_VDP_MPEG_DEC (GST_OBJECT_PARENT (pad)); GstStructure *structure; gint width, height; @@ -280,7 +280,7 @@ gst_vdp_mpeg_decoder_set_caps (GstPad * pad, GstCaps * caps) } GstFlowReturn -gst_vdp_mpeg_decoder_push_video_buffer (GstVdpMpegDecoder * mpeg_dec, +gst_vdp_mpeg_dec_push_video_buffer (GstVdpMpegDec * mpeg_dec, GstVdpVideoBuffer * buffer) { gint64 byterate; @@ -328,7 +328,7 @@ gst_vdp_mpeg_decoder_push_video_buffer (GstVdpMpegDecoder * mpeg_dec, } static GstFlowReturn -gst_vdp_mpeg_decoder_decode (GstVdpMpegDecoder * mpeg_dec, +gst_vdp_mpeg_dec_decode (GstVdpMpegDec * mpeg_dec, GstClockTime timestamp, gint64 size) { VdpPictureInfoMPEG1Or2 *info; @@ -347,7 +347,7 @@ gst_vdp_mpeg_decoder_decode (GstVdpMpegDecoder * mpeg_dec, if (info->picture_coding_type != B_FRAME) { if (info->backward_reference != VDP_INVALID_HANDLE) { gst_buffer_ref (mpeg_dec->b_buffer); - gst_vdp_mpeg_decoder_push_video_buffer (mpeg_dec, + gst_vdp_mpeg_dec_push_video_buffer (mpeg_dec, GST_VDP_VIDEO_BUFFER (mpeg_dec->b_buffer)); } @@ -406,7 +406,7 @@ gst_vdp_mpeg_decoder_decode (GstVdpMpegDecoder * mpeg_dec, } if (info->picture_coding_type == B_FRAME) { - gst_vdp_mpeg_decoder_push_video_buffer (mpeg_dec, + gst_vdp_mpeg_dec_push_video_buffer (mpeg_dec, GST_VDP_VIDEO_BUFFER (outbuf)); } else { info->backward_reference = surface; @@ -417,7 +417,7 @@ gst_vdp_mpeg_decoder_decode (GstVdpMpegDecoder * mpeg_dec, } static gboolean -gst_vdp_mpeg_decoder_parse_picture_coding (GstVdpMpegDecoder * mpeg_dec, +gst_vdp_mpeg_dec_parse_picture_coding (GstVdpMpegDec * mpeg_dec, GstBuffer * buffer) { MPEGPictureExt pic_ext; @@ -469,8 +469,7 @@ gst_vdp_mpeg_decoder_parse_picture_coding (GstVdpMpegDecoder * mpeg_dec, } static gboolean -gst_vdp_mpeg_decoder_parse_sequence (GstVdpMpegDecoder * mpeg_dec, - GstBuffer * buffer) +gst_vdp_mpeg_dec_parse_sequence (GstVdpMpegDec * mpeg_dec, GstBuffer * buffer) { MPEGSeqHdr hdr; @@ -486,8 +485,7 @@ gst_vdp_mpeg_decoder_parse_sequence (GstVdpMpegDecoder * mpeg_dec, } static gboolean -gst_vdp_mpeg_decoder_parse_picture (GstVdpMpegDecoder * mpeg_dec, - GstBuffer * buffer) +gst_vdp_mpeg_dec_parse_picture (GstVdpMpegDec * mpeg_dec, GstBuffer * buffer) { MPEGPictureHdr pic_hdr; @@ -523,8 +521,7 @@ gst_vdp_mpeg_decoder_parse_picture (GstVdpMpegDecoder * mpeg_dec, } static gboolean -gst_vdp_mpeg_decoder_parse_gop (GstVdpMpegDecoder * mpeg_dec, - GstBuffer * buffer) +gst_vdp_mpeg_dec_parse_gop (GstVdpMpegDec * mpeg_dec, GstBuffer * buffer) { MPEGGop gop; GstClockTime time; @@ -544,7 +541,7 @@ gst_vdp_mpeg_decoder_parse_gop (GstVdpMpegDecoder * mpeg_dec, } static gboolean -gst_vdp_mpeg_decoder_parse_quant_matrix (GstVdpMpegDecoder * mpeg_dec, +gst_vdp_mpeg_dec_parse_quant_matrix (GstVdpMpegDec * mpeg_dec, GstBuffer * buffer) { MPEGQuantMatrix qm; @@ -560,14 +557,14 @@ gst_vdp_mpeg_decoder_parse_quant_matrix (GstVdpMpegDecoder * mpeg_dec, } static void -gst_vdp_mpeg_decoder_flush (GstVdpMpegDecoder * mpeg_dec) +gst_vdp_mpeg_dec_flush (GstVdpMpegDec * mpeg_dec) { if (mpeg_dec->vdp_info.forward_reference != VDP_INVALID_HANDLE) gst_buffer_unref (mpeg_dec->f_buffer); if (mpeg_dec->vdp_info.backward_reference != VDP_INVALID_HANDLE) gst_buffer_unref (mpeg_dec->b_buffer); - gst_vdp_mpeg_decoder_init_info (&mpeg_dec->vdp_info); + gst_vdp_mpeg_dec_init_info (&mpeg_dec->vdp_info); gst_adapter_clear (mpeg_dec->adapter); @@ -575,9 +572,9 @@ gst_vdp_mpeg_decoder_flush (GstVdpMpegDecoder * mpeg_dec) } static void -gst_vdp_mpeg_decoder_reset (GstVdpMpegDecoder * mpeg_dec) +gst_vdp_mpeg_dec_reset (GstVdpMpegDec * mpeg_dec) { - gst_vdp_mpeg_decoder_flush (mpeg_dec); + gst_vdp_mpeg_dec_flush (mpeg_dec); if (mpeg_dec->decoder != VDP_INVALID_HANDLE) mpeg_dec->device->vdp_decoder_destroy (mpeg_dec->decoder); @@ -594,20 +591,21 @@ gst_vdp_mpeg_decoder_reset (GstVdpMpegDecoder * mpeg_dec) } static GstFlowReturn -gst_vdp_mpeg_decoder_chain (GstPad * pad, GstBuffer * buffer) +gst_vdp_mpeg_dec_chain (GstPad * pad, GstBuffer * buffer) { - GstVdpMpegDecoder *mpeg_dec; + GstVdpMpegDec *mpeg_dec; GstVdpMpegPacketizer packetizer; GstBuffer *buf; GstFlowReturn ret = GST_FLOW_OK; - mpeg_dec = GST_VDP_MPEG_DECODER (GST_OBJECT_PARENT (pad)); + mpeg_dec = GST_VDP_MPEG_DEC (GST_OBJECT_PARENT (pad)); if (G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT))) { GST_DEBUG_OBJECT (mpeg_dec, "Received discont buffer"); - gst_vdp_mpeg_decoder_flush (mpeg_dec); + gst_vdp_mpeg_dec_flush (mpeg_dec); } + gst_vdp_mpeg_packetizer_init (&packetizer, buffer); while ((buf = gst_vdp_mpeg_packetizer_get_next_packet (&packetizer))) { GstBitReader b_reader = GST_BIT_READER_INIT_FROM_BUFFER (buf); @@ -633,13 +631,13 @@ gst_vdp_mpeg_decoder_chain (GstPad * pad, GstBuffer * buffer) case MPEG_PACKET_PICTURE: GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_PICTURE"); - if (!gst_vdp_mpeg_decoder_parse_picture (mpeg_dec, buf)) { + if (!gst_vdp_mpeg_dec_parse_picture (mpeg_dec, buf)) { return GST_FLOW_OK; } break; case MPEG_PACKET_SEQUENCE: GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_SEQUENCE"); - gst_vdp_mpeg_decoder_parse_sequence (mpeg_dec, buf); + gst_vdp_mpeg_dec_parse_sequence (mpeg_dec, buf); break; case MPEG_PACKET_EXTENSION: { @@ -652,11 +650,11 @@ gst_vdp_mpeg_decoder_chain (GstPad * pad, GstBuffer * buffer) switch (ext_code) { case MPEG_PACKET_EXT_PICTURE_CODING: GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_EXT_PICTURE_CODING"); - gst_vdp_mpeg_decoder_parse_picture_coding (mpeg_dec, buf); + gst_vdp_mpeg_dec_parse_picture_coding (mpeg_dec, buf); break; case MPEG_PACKET_EXT_QUANT_MATRIX: GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_EXT_QUANT_MATRIX"); - gst_vdp_mpeg_decoder_parse_quant_matrix (mpeg_dec, buf); + gst_vdp_mpeg_dec_parse_quant_matrix (mpeg_dec, buf); break; default: break; @@ -665,7 +663,7 @@ gst_vdp_mpeg_decoder_chain (GstPad * pad, GstBuffer * buffer) } case MPEG_PACKET_GOP: GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_GOP"); - gst_vdp_mpeg_decoder_parse_gop (mpeg_dec, buf); + gst_vdp_mpeg_dec_parse_gop (mpeg_dec, buf); break; default: break; @@ -675,14 +673,14 @@ gst_vdp_mpeg_decoder_chain (GstPad * pad, GstBuffer * buffer) } if (mpeg_dec->vdp_info.slice_count > 0) - ret = gst_vdp_mpeg_decoder_decode (mpeg_dec, GST_BUFFER_TIMESTAMP (buffer), + ret = gst_vdp_mpeg_dec_decode (mpeg_dec, GST_BUFFER_TIMESTAMP (buffer), GST_BUFFER_SIZE (buffer)); return ret; } static gboolean -gst_vdp_mpeg_decoder_convert (GstVdpMpegDecoder * mpeg_dec, +gst_vdp_mpeg_dec_convert (GstVdpMpegDec * mpeg_dec, GstFormat src_format, gint64 src_value, GstFormat dest_format, gint64 * dest_value) { @@ -711,7 +709,7 @@ gst_vdp_mpeg_decoder_convert (GstVdpMpegDecoder * mpeg_dec, } static const GstQueryType * -gst_mpeg_decoder_get_querytypes (GstPad * pad) +gst_mpeg_dec_get_querytypes (GstPad * pad) { static const GstQueryType list[] = { GST_QUERY_POSITION, @@ -723,9 +721,9 @@ gst_mpeg_decoder_get_querytypes (GstPad * pad) } static gboolean -gst_vdp_mpeg_decoder_src_query (GstPad * pad, GstQuery * query) +gst_vdp_mpeg_dec_src_query (GstPad * pad, GstQuery * query) { - GstVdpMpegDecoder *mpeg_dec = GST_VDP_MPEG_DECODER (GST_OBJECT_PARENT (pad)); + GstVdpMpegDec *mpeg_dec = GST_VDP_MPEG_DEC (GST_OBJECT_PARENT (pad)); gboolean res = FALSE; switch (GST_QUERY_TYPE (query)) { @@ -762,7 +760,7 @@ gst_vdp_mpeg_decoder_src_query (GstPad * pad, GstQuery * query) && format == GST_FORMAT_BYTES) { gint64 duration; - if (gst_vdp_mpeg_decoder_convert (mpeg_dec, GST_FORMAT_BYTES, + if (gst_vdp_mpeg_dec_convert (mpeg_dec, GST_FORMAT_BYTES, bytes, GST_FORMAT_TIME, &duration)) { GST_DEBUG ("duration: %" GST_TIME_FORMAT, GST_TIME_ARGS (duration)); gst_query_set_duration (query, GST_FORMAT_TIME, duration); @@ -783,7 +781,7 @@ gst_vdp_mpeg_decoder_src_query (GstPad * pad, GstQuery * query) static gboolean normal_seek (GstPad * pad, GstEvent * event) { - GstVdpMpegDecoder *mpeg_dec = GST_VDP_MPEG_DECODER (GST_OBJECT_PARENT (pad)); + GstVdpMpegDec *mpeg_dec = GST_VDP_MPEG_DEC (GST_OBJECT_PARENT (pad)); gdouble rate; GstFormat format, conv; GstSeekFlags flags; @@ -800,9 +798,9 @@ normal_seek (GstPad * pad, GstEvent * event) &cur_type, &cur, &stop_type, &stop); conv = GST_FORMAT_TIME; - if (!gst_vdp_mpeg_decoder_convert (mpeg_dec, format, cur, conv, &time_cur)) + if (!gst_vdp_mpeg_dec_convert (mpeg_dec, format, cur, conv, &time_cur)) goto convert_failed; - if (!gst_vdp_mpeg_decoder_convert (mpeg_dec, format, stop, conv, &time_stop)) + if (!gst_vdp_mpeg_dec_convert (mpeg_dec, format, stop, conv, &time_stop)) goto convert_failed; GST_DEBUG ("seek to time %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT, @@ -817,10 +815,10 @@ normal_seek (GstPad * pad, GstEvent * event) /* else we try to seek on bytes */ conv = GST_FORMAT_BYTES; - if (!gst_vdp_mpeg_decoder_convert (mpeg_dec, GST_FORMAT_TIME, time_cur, + if (!gst_vdp_mpeg_dec_convert (mpeg_dec, GST_FORMAT_TIME, time_cur, conv, &bytes_cur)) goto convert_failed; - if (!gst_vdp_mpeg_decoder_convert (mpeg_dec, GST_FORMAT_TIME, time_stop, + if (!gst_vdp_mpeg_dec_convert (mpeg_dec, GST_FORMAT_TIME, time_stop, conv, &bytes_stop)) goto convert_failed; @@ -848,7 +846,7 @@ convert_failed: } static gboolean -gst_vdp_mpeg_decoder_src_event (GstPad * pad, GstEvent * event) +gst_vdp_mpeg_dec_src_event (GstPad * pad, GstEvent * event) { gboolean res; @@ -869,9 +867,9 @@ gst_vdp_mpeg_decoder_src_event (GstPad * pad, GstEvent * event) } static gboolean -gst_vdp_mpeg_decoder_sink_event (GstPad * pad, GstEvent * event) +gst_vdp_mpeg_dec_sink_event (GstPad * pad, GstEvent * event) { - GstVdpMpegDecoder *mpeg_dec = GST_VDP_MPEG_DECODER (GST_OBJECT_PARENT (pad)); + GstVdpMpegDec *mpeg_dec = GST_VDP_MPEG_DEC (GST_OBJECT_PARENT (pad)); gboolean res; switch (GST_EVENT_TYPE (event)) { @@ -879,7 +877,7 @@ gst_vdp_mpeg_decoder_sink_event (GstPad * pad, GstEvent * event) { GST_DEBUG_OBJECT (mpeg_dec, "flush stop"); - gst_vdp_mpeg_decoder_flush (mpeg_dec); + gst_vdp_mpeg_dec_flush (mpeg_dec); res = gst_pad_push_event (mpeg_dec->src, event); break; @@ -897,13 +895,13 @@ gst_vdp_mpeg_decoder_sink_event (GstPad * pad, GstEvent * event) &start, &stop, &position); if (format != GST_FORMAT_TIME) { - if (!gst_vdp_mpeg_decoder_convert (mpeg_dec, format, start, + if (!gst_vdp_mpeg_dec_convert (mpeg_dec, format, start, GST_FORMAT_TIME, &start)) goto convert_error; - if (!gst_vdp_mpeg_decoder_convert (mpeg_dec, format, stop, + if (!gst_vdp_mpeg_dec_convert (mpeg_dec, format, stop, GST_FORMAT_TIME, &stop)) goto convert_error; - if (!gst_vdp_mpeg_decoder_convert (mpeg_dec, format, position, + if (!gst_vdp_mpeg_dec_convert (mpeg_dec, format, position, GST_FORMAT_TIME, &position)) goto convert_error; @@ -935,13 +933,12 @@ gst_vdp_mpeg_decoder_sink_event (GstPad * pad, GstEvent * event) } static GstStateChangeReturn -gst_vdp_mpeg_decoder_change_state (GstElement * element, - GstStateChange transition) +gst_vdp_mpeg_dec_change_state (GstElement * element, GstStateChange transition) { - GstVdpMpegDecoder *mpeg_dec; + GstVdpMpegDec *mpeg_dec; GstStateChangeReturn ret; - mpeg_dec = GST_VDP_MPEG_DECODER (element); + mpeg_dec = GST_VDP_MPEG_DEC (element); switch (transition) { case GST_STATE_CHANGE_READY_TO_PAUSED: @@ -955,7 +952,7 @@ gst_vdp_mpeg_decoder_change_state (GstElement * element, switch (transition) { case GST_STATE_CHANGE_PAUSED_TO_READY: - gst_vdp_mpeg_decoder_reset (mpeg_dec); + gst_vdp_mpeg_dec_reset (mpeg_dec); break; default: break; @@ -967,7 +964,7 @@ gst_vdp_mpeg_decoder_change_state (GstElement * element, /* GObject vmethod implementations */ static void -gst_vdp_mpeg_decoder_base_init (gpointer gclass) +gst_vdp_mpeg_dec_base_init (gpointer gclass) { GstElementClass *element_class = GST_ELEMENT_CLASS (gclass); @@ -985,7 +982,7 @@ gst_vdp_mpeg_decoder_base_init (gpointer gclass) /* initialize the vdpaumpegdecoder's class */ static void -gst_vdp_mpeg_decoder_class_init (GstVdpMpegDecoderClass * klass) +gst_vdp_mpeg_dec_class_init (GstVdpMpegDecClass * klass) { GObjectClass *gobject_class; GstElementClass *gstelement_class; @@ -993,12 +990,12 @@ gst_vdp_mpeg_decoder_class_init (GstVdpMpegDecoderClass * klass) gobject_class = (GObjectClass *) klass; gstelement_class = (GstElementClass *) klass; - gobject_class->finalize = gst_vdp_mpeg_decoder_finalize; - gobject_class->set_property = gst_vdp_mpeg_decoder_set_property; - gobject_class->get_property = gst_vdp_mpeg_decoder_get_property; + gobject_class->finalize = gst_vdp_mpeg_dec_finalize; + gobject_class->set_property = gst_vdp_mpeg_dec_set_property; + gobject_class->get_property = gst_vdp_mpeg_dec_get_property; gstelement_class->change_state = - GST_DEBUG_FUNCPTR (gst_vdp_mpeg_decoder_change_state); + GST_DEBUG_FUNCPTR (gst_vdp_mpeg_dec_change_state); g_object_class_install_property (gobject_class, PROP_DISPLAY, g_param_spec_string ("display", "Display", "X Display name", @@ -1006,7 +1003,7 @@ gst_vdp_mpeg_decoder_class_init (GstVdpMpegDecoderClass * klass) } static void -gst_vdp_mpeg_decoder_init_info (VdpPictureInfoMPEG1Or2 * vdp_info) +gst_vdp_mpeg_dec_init_info (VdpPictureInfoMPEG1Or2 * vdp_info) { vdp_info->forward_reference = VDP_INVALID_HANDLE; vdp_info->backward_reference = VDP_INVALID_HANDLE; @@ -1023,25 +1020,24 @@ gst_vdp_mpeg_decoder_init_info (VdpPictureInfoMPEG1Or2 * vdp_info) } static void -gst_vdp_mpeg_decoder_init (GstVdpMpegDecoder * mpeg_dec, - GstVdpMpegDecoderClass * gclass) +gst_vdp_mpeg_dec_init (GstVdpMpegDec * mpeg_dec, GstVdpMpegDecClass * gclass) { mpeg_dec->src = gst_pad_new_from_static_template (&src_template, "src"); gst_pad_set_event_function (mpeg_dec->src, - GST_DEBUG_FUNCPTR (gst_vdp_mpeg_decoder_src_event)); + GST_DEBUG_FUNCPTR (gst_vdp_mpeg_dec_src_event)); gst_pad_set_query_function (mpeg_dec->src, - GST_DEBUG_FUNCPTR (gst_vdp_mpeg_decoder_src_query)); + GST_DEBUG_FUNCPTR (gst_vdp_mpeg_dec_src_query)); gst_pad_set_query_type_function (mpeg_dec->src, - GST_DEBUG_FUNCPTR (gst_mpeg_decoder_get_querytypes)); + GST_DEBUG_FUNCPTR (gst_mpeg_dec_get_querytypes)); gst_element_add_pad (GST_ELEMENT (mpeg_dec), mpeg_dec->src); mpeg_dec->sink = gst_pad_new_from_static_template (&sink_template, "sink"); gst_pad_set_setcaps_function (mpeg_dec->sink, - GST_DEBUG_FUNCPTR (gst_vdp_mpeg_decoder_set_caps)); + GST_DEBUG_FUNCPTR (gst_vdp_mpeg_dec_set_caps)); gst_pad_set_chain_function (mpeg_dec->sink, - GST_DEBUG_FUNCPTR (gst_vdp_mpeg_decoder_chain)); + GST_DEBUG_FUNCPTR (gst_vdp_mpeg_dec_chain)); gst_pad_set_event_function (mpeg_dec->sink, - GST_DEBUG_FUNCPTR (gst_vdp_mpeg_decoder_sink_event)); + GST_DEBUG_FUNCPTR (gst_vdp_mpeg_dec_sink_event)); gst_element_add_pad (GST_ELEMENT (mpeg_dec), mpeg_dec->sink); mpeg_dec->display_name = NULL; @@ -1052,22 +1048,22 @@ gst_vdp_mpeg_decoder_init (GstVdpMpegDecoder * mpeg_dec, mpeg_dec->vdp_info.forward_reference = VDP_INVALID_HANDLE; mpeg_dec->vdp_info.backward_reference = VDP_INVALID_HANDLE; - gst_vdp_mpeg_decoder_reset (mpeg_dec); + gst_vdp_mpeg_dec_reset (mpeg_dec); } static void -gst_vdp_mpeg_decoder_finalize (GObject * object) +gst_vdp_mpeg_dec_finalize (GObject * object) { - GstVdpMpegDecoder *mpeg_dec = (GstVdpMpegDecoder *) object; + GstVdpMpegDec *mpeg_dec = (GstVdpMpegDec *) object; g_object_unref (mpeg_dec->adapter); } static void -gst_vdp_mpeg_decoder_set_property (GObject * object, guint prop_id, +gst_vdp_mpeg_dec_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { - GstVdpMpegDecoder *mpeg_dec = GST_VDP_MPEG_DECODER (object); + GstVdpMpegDec *mpeg_dec = GST_VDP_MPEG_DEC (object); switch (prop_id) { case PROP_DISPLAY: @@ -1081,10 +1077,10 @@ gst_vdp_mpeg_decoder_set_property (GObject * object, guint prop_id, } static void -gst_vdp_mpeg_decoder_get_property (GObject * object, guint prop_id, +gst_vdp_mpeg_dec_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { - GstVdpMpegDecoder *mpeg_dec = GST_VDP_MPEG_DECODER (object); + GstVdpMpegDec *mpeg_dec = GST_VDP_MPEG_DEC (object); switch (prop_id) { case PROP_DISPLAY: diff --git a/sys/vdpau/gstvdpmpegdecoder.h b/sys/vdpau/gstvdpmpegdecoder.h index e1300862..b60c9f59 100644 --- a/sys/vdpau/gstvdpmpegdecoder.h +++ b/sys/vdpau/gstvdpmpegdecoder.h @@ -18,8 +18,8 @@ * Boston, MA 02111-1307, USA. */ -#ifndef __GST_VDP_MPEG_DECODER_H__ -#define __GST_VDP_MPEG_DECODER_H__ +#ifndef __GST_VDP_MPEG_DEC_H__ +#define __GST_VDP_MPEG_DEC_H__ #include #include @@ -29,16 +29,16 @@ G_BEGIN_DECLS -#define GST_TYPE_VDP_MPEG_DECODER (gst_vdp_mpeg_decoder_get_type()) -#define GST_VDP_MPEG_DECODER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VDP_MPEG_DECODER,GstVdpMpegDecoder)) -#define GST_VDP_MPEG_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VDP_MPEG_DECODER,GstVdpMpegDecoderClass)) -#define GST_IS_VDPAU_MPEG_DECODER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VDP_MPEG_DECODER)) -#define GST_IS_VDPAU_MPEG_DECODER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VDP_MPEG_DECODER)) +#define GST_TYPE_VDP_MPEG_DEC (gst_vdp_mpeg_dec_get_type()) +#define GST_VDP_MPEG_DEC(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VDP_MPEG_DEC,GstVdpMpegDec)) +#define GST_VDP_MPEG_DEC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VDP_MPEG_DEC,GstVdpMpegDecClass)) +#define GST_IS_VDPAU_MPEG_DEC(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VDP_MPEG_DEC)) +#define GST_IS_VDPAU_MPEG_DEC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VDP_MPEG_DEC)) -typedef struct _GstVdpMpegDecoder GstVdpMpegDecoder; -typedef struct _GstVdpMpegDecoderClass GstVdpMpegDecoderClass; +typedef struct _GstVdpMpegDec GstVdpMpegDec; +typedef struct _GstVdpMpegDecClass GstVdpMpegDecClass; -struct _GstVdpMpegDecoder +struct _GstVdpMpegDec { GstElement element; @@ -81,13 +81,13 @@ struct _GstVdpMpegDecoder }; -struct _GstVdpMpegDecoderClass +struct _GstVdpMpegDecClass { GstElementClass element_class; }; -GType gst_vdp_mpeg_decoder_get_type (void); +GType gst_vdp_mpeg_dec_get_type (void); G_END_DECLS -#endif /* __GST_VDP_MPEG_DECODER_H__ */ +#endif /* __GST_VDP_MPEG_DEC_H__ */ -- cgit v1.2.1 From 8619160ec89ac7c8aed300f1f644fc0f50a294e8 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Fri, 5 Jun 2009 21:48:28 +0200 Subject: vdpaumpegdec: rename gstvdpmpegdecoder.[ch] to gstvdpmpegdec.[ch] --- sys/vdpau/Makefile.am | 4 +- sys/vdpau/gstvdp.c | 2 +- sys/vdpau/gstvdpmpegdec.c | 1093 +++++++++++++++++++++++++++++++++++++++++ sys/vdpau/gstvdpmpegdec.h | 93 ++++ sys/vdpau/gstvdpmpegdecoder.c | 1093 ----------------------------------------- sys/vdpau/gstvdpmpegdecoder.h | 93 ---- 6 files changed, 1189 insertions(+), 1189 deletions(-) create mode 100644 sys/vdpau/gstvdpmpegdec.c create mode 100644 sys/vdpau/gstvdpmpegdec.h delete mode 100644 sys/vdpau/gstvdpmpegdecoder.c delete mode 100644 sys/vdpau/gstvdpmpegdecoder.h diff --git a/sys/vdpau/Makefile.am b/sys/vdpau/Makefile.am index 053332b0..f4380aff 100644 --- a/sys/vdpau/Makefile.am +++ b/sys/vdpau/Makefile.am @@ -2,7 +2,7 @@ plugin_LTLIBRARIES = libgstvdpau.la libgstvdpau_la_SOURCES = \ gstvdpdevice.c \ - gstvdpmpegdecoder.c \ + gstvdpmpegdec.c \ mpegutil.c \ gstvdpvideoyuv.c \ gstvdpvideobuffer.c \ @@ -17,7 +17,7 @@ libgstvdpau_la_LIBTOOLFLAGS = --tag=disable-static noinst_HEADERS = \ gstvdpdevice.h \ - gstvdpmpegdecoder.h \ + gstvdpmpegdec.h \ mpegutil.h \ gstvdpvideoyuv.h \ gstvdpvideobuffer.h \ diff --git a/sys/vdpau/gstvdp.c b/sys/vdpau/gstvdp.c index 43360483..5c524968 100644 --- a/sys/vdpau/gstvdp.c +++ b/sys/vdpau/gstvdp.c @@ -5,7 +5,7 @@ #include -#include "gstvdpmpegdecoder.h" +#include "gstvdpmpegdec.h" #include "gstvdpvideoyuv.h" #include "gstvdpyuvvideo.h" diff --git a/sys/vdpau/gstvdpmpegdec.c b/sys/vdpau/gstvdpmpegdec.c new file mode 100644 index 00000000..b011833e --- /dev/null +++ b/sys/vdpau/gstvdpmpegdec.c @@ -0,0 +1,1093 @@ +/* + * GStreamer + * Copyright (C) 2009 Carl-Anton Ingmarsson + * + * 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-vdpaumpegdec + * + * FIXME:Describe vdpaumpegdec here. + * + * + * Example launch line + * |[ + * gst-launch -v -m fakesrc ! vdpaumpegdec ! fakesink silent=TRUE + * ]| + * + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include +#include +#include +#include + +#include "mpegutil.h" +#include "gstvdpmpegdec.h" + +GST_DEBUG_CATEGORY_STATIC (gst_vdp_mpeg_dec_debug); +#define GST_CAT_DEFAULT gst_vdp_mpeg_dec_debug + +/* Filter signals and args */ +enum +{ + /* FILL ME */ + LAST_SIGNAL +}; + +enum +{ + PROP_0, + PROP_DISPLAY +}; + +/* the capabilities of the inputs and outputs. + * + * describe the real formats here. + */ +static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("video/mpeg, mpegversion = (int) [ 1, 2 ], " + "systemstream = (boolean) false, parsed = (boolean) true") + ); +static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("video/x-vdpau-video, " "chroma-type = (int) 0") + ); + +#define DEBUG_INIT(bla) \ +GST_DEBUG_CATEGORY_INIT (gst_vdp_mpeg_dec_debug, "vdpaumpegdec", 0, "VDPAU powered mpeg decoder"); + +GST_BOILERPLATE_FULL (GstVdpMpegDec, gst_vdp_mpeg_dec, + GstElement, GST_TYPE_ELEMENT, DEBUG_INIT); + +static void gst_vdp_mpeg_dec_init_info (VdpPictureInfoMPEG1Or2 * vdp_info); +static void gst_vdp_mpeg_dec_finalize (GObject * object); +static void gst_vdp_mpeg_dec_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec); +static void gst_vdp_mpeg_dec_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec); + +guint8 * +mpeg_util_find_start_code (guint32 * sync_word, guint8 * cur, guint8 * end) +{ + guint32 code; + + if (G_UNLIKELY (cur == NULL)) + return NULL; + + code = *sync_word; + + while (cur < end) { + code <<= 8; + + if (code == 0x00000100) { + /* Reset the sync word accumulator */ + *sync_word = 0xffffffff; + return cur; + } + + /* Add the next available byte to the collected sync word */ + code |= *cur++; + } + + *sync_word = code; + return NULL; +} + +typedef struct +{ + GstBuffer *buffer; + guint8 *cur; + guint8 *end; +} GstVdpMpegPacketizer; + +static GstBuffer * +gst_vdp_mpeg_packetizer_get_next_packet (GstVdpMpegPacketizer * packetizer) +{ + guint32 sync_word = 0xffffff; + guint8 *packet_start; + guint8 *packet_end; + + if (!packetizer->cur) + return NULL; + + packet_start = packetizer->cur - 3; + packetizer->cur = packet_end = mpeg_util_find_start_code (&sync_word, + packetizer->cur, packetizer->end); + + if (packet_end) + packet_end -= 3; + else + packet_end = packetizer->end; + + return gst_buffer_create_sub (packetizer->buffer, + packet_start - GST_BUFFER_DATA (packetizer->buffer), + packet_end - packet_start); +} + +static void +gst_vdp_mpeg_packetizer_init (GstVdpMpegPacketizer * packetizer, + GstBuffer * buffer) +{ + guint32 sync_word = 0xffffffff; + + packetizer->buffer = buffer; + packetizer->end = GST_BUFFER_DATA (buffer) + GST_BUFFER_SIZE (buffer); + packetizer->cur = mpeg_util_find_start_code (&sync_word, + GST_BUFFER_DATA (buffer), packetizer->end); +} + +static gboolean +gst_vdp_mpeg_dec_set_caps (GstPad * pad, GstCaps * caps) +{ + GstVdpMpegDec *mpeg_dec = GST_VDP_MPEG_DEC (GST_OBJECT_PARENT (pad)); + GstStructure *structure; + + gint width, height; + gint fps_n, fps_d; + gint par_n, par_d; + gboolean interlaced = FALSE; + + GstCaps *src_caps; + gboolean res; + + const GValue *value; + VdpDecoderProfile profile; + GstVdpDevice *device; + VdpStatus status; + + structure = gst_caps_get_structure (caps, 0); + + /* create src_pad caps */ + gst_structure_get_int (structure, "width", &width); + gst_structure_get_int (structure, "height", &height); + gst_structure_get_fraction (structure, "framerate", &fps_n, &fps_d); + gst_structure_get_fraction (structure, "pixel-aspect-ratio", &par_n, &par_d); + gst_structure_get_boolean (structure, "interlaced", &interlaced); + + src_caps = gst_caps_new_simple ("video/x-vdpau-video", + "device", G_TYPE_OBJECT, mpeg_dec->device, + "chroma_type", G_TYPE_INT, VDP_CHROMA_TYPE_420, + "width", G_TYPE_INT, width, + "height", G_TYPE_INT, height, + "framerate", GST_TYPE_FRACTION, fps_n, fps_d, + "pixel-aspect-ratio", GST_TYPE_FRACTION, par_n, par_d, + "interlaced", G_TYPE_BOOLEAN, interlaced, NULL); + + res = gst_pad_set_caps (mpeg_dec->src, src_caps); + gst_caps_unref (src_caps); + if (!res) + return FALSE; + + mpeg_dec->width = width; + mpeg_dec->height = height; + mpeg_dec->fps_n = fps_n; + mpeg_dec->fps_d = fps_d; + mpeg_dec->interlaced = interlaced; + + /* parse caps to setup decoder */ + gst_structure_get_int (structure, "mpegversion", &mpeg_dec->version); + if (mpeg_dec->version == 1) + profile = VDP_DECODER_PROFILE_MPEG1; + + value = gst_structure_get_value (structure, "codec_data"); + if (value) { + GstBuffer *codec_data, *buf; + GstVdpMpegPacketizer packetizer; + + codec_data = gst_value_get_buffer (value); + gst_vdp_mpeg_packetizer_init (&packetizer, codec_data); + if ((buf = gst_vdp_mpeg_packetizer_get_next_packet (&packetizer))) { + MPEGSeqHdr hdr; + guint32 bitrate; + + mpeg_util_parse_sequence_hdr (&hdr, buf); + + memcpy (&mpeg_dec->vdp_info.intra_quantizer_matrix, + &hdr.intra_quantizer_matrix, 64); + memcpy (&mpeg_dec->vdp_info.non_intra_quantizer_matrix, + &hdr.non_intra_quantizer_matrix, 64); + + bitrate = hdr.bitrate; + gst_buffer_unref (buf); + + if ((buf = gst_vdp_mpeg_packetizer_get_next_packet (&packetizer))) { + MPEGSeqExtHdr ext; + + mpeg_util_parse_sequence_extension (&ext, buf); + if (mpeg_dec->version != 1) { + switch (ext.profile) { + case 5: + profile = VDP_DECODER_PROFILE_MPEG2_SIMPLE; + break; + default: + profile = VDP_DECODER_PROFILE_MPEG2_MAIN; + break; + } + } + + bitrate += (ext.bitrate_ext << 18);; + gst_buffer_unref (buf); + } + + mpeg_dec->duration = + gst_util_uint64_scale (1, GST_SECOND * mpeg_dec->fps_d, + mpeg_dec->fps_n); + + mpeg_dec->byterate = bitrate * 50; + GST_DEBUG ("byterate: %" G_GINT64_FORMAT, mpeg_dec->byterate); + } + } + + device = mpeg_dec->device; + + if (mpeg_dec->decoder != VDP_INVALID_HANDLE) { + device->vdp_decoder_destroy (mpeg_dec->decoder); + mpeg_dec->decoder = VDP_INVALID_HANDLE; + } + + status = device->vdp_decoder_create (device->device, profile, mpeg_dec->width, + mpeg_dec->height, 2, &mpeg_dec->decoder); + if (status != VDP_STATUS_OK) { + GST_ELEMENT_ERROR (mpeg_dec, RESOURCE, READ, + ("Could not create vdpau decoder"), + ("Error returned from vdpau was: %s", + device->vdp_get_error_string (status))); + return FALSE; + } + return TRUE; +} + +GstFlowReturn +gst_vdp_mpeg_dec_push_video_buffer (GstVdpMpegDec * mpeg_dec, + GstVdpVideoBuffer * buffer) +{ + gint64 byterate; + + if (GST_BUFFER_TIMESTAMP (buffer) == GST_CLOCK_TIME_NONE + && GST_CLOCK_TIME_IS_VALID (mpeg_dec->next_timestamp)) { + GST_BUFFER_TIMESTAMP (buffer) = mpeg_dec->next_timestamp; + } else if (GST_BUFFER_TIMESTAMP (buffer) == GST_CLOCK_TIME_NONE) { + GST_BUFFER_TIMESTAMP (buffer) = gst_util_uint64_scale (mpeg_dec->frame_nr, + GST_SECOND * mpeg_dec->fps_d, mpeg_dec->fps_n); + } + + if (mpeg_dec->seeking) { + GstEvent *event; + + event = gst_event_new_new_segment (FALSE, + mpeg_dec->segment.rate, GST_FORMAT_TIME, GST_BUFFER_TIMESTAMP (buffer), + mpeg_dec->segment.stop, GST_BUFFER_TIMESTAMP (buffer)); + + gst_pad_push_event (mpeg_dec->src, event); + + mpeg_dec->seeking = FALSE; + } + + mpeg_dec->next_timestamp = GST_BUFFER_TIMESTAMP (buffer) + + GST_BUFFER_DURATION (buffer); + + mpeg_dec->accumulated_duration += GST_BUFFER_DURATION (buffer); + mpeg_dec->accumulated_size += GST_BUFFER_SIZE (buffer); + byterate = gst_util_uint64_scale (mpeg_dec->accumulated_size, GST_SECOND, + mpeg_dec->accumulated_duration); + GST_DEBUG ("byterate: %" G_GINT64_FORMAT, mpeg_dec->byterate); + + mpeg_dec->byterate = (mpeg_dec->byterate + byterate) / 2; + + gst_buffer_set_caps (GST_BUFFER (buffer), GST_PAD_CAPS (mpeg_dec->src)); + + GST_DEBUG_OBJECT (mpeg_dec, + "Pushing buffer with timestamp: %" GST_TIME_FORMAT + " frame_nr: %" G_GINT64_FORMAT, + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)), + GST_BUFFER_OFFSET (buffer)); + + return gst_pad_push (mpeg_dec->src, GST_BUFFER (buffer)); +} + +static GstFlowReturn +gst_vdp_mpeg_dec_decode (GstVdpMpegDec * mpeg_dec, + GstClockTime timestamp, gint64 size) +{ + VdpPictureInfoMPEG1Or2 *info; + GstBuffer *buffer; + GstVdpVideoBuffer *outbuf; + VdpVideoSurface surface; + GstVdpDevice *device; + VdpBitstreamBuffer vbit[1]; + VdpStatus status; + + info = &mpeg_dec->vdp_info; + + buffer = gst_adapter_take_buffer (mpeg_dec->adapter, + gst_adapter_available (mpeg_dec->adapter)); + + if (info->picture_coding_type != B_FRAME) { + if (info->backward_reference != VDP_INVALID_HANDLE) { + gst_buffer_ref (mpeg_dec->b_buffer); + gst_vdp_mpeg_dec_push_video_buffer (mpeg_dec, + GST_VDP_VIDEO_BUFFER (mpeg_dec->b_buffer)); + } + + if (info->forward_reference != VDP_INVALID_HANDLE) { + gst_buffer_unref (mpeg_dec->f_buffer); + info->forward_reference = VDP_INVALID_HANDLE; + } + + info->forward_reference = info->backward_reference; + mpeg_dec->f_buffer = mpeg_dec->b_buffer; + + info->backward_reference = VDP_INVALID_HANDLE; + } + + outbuf = gst_vdp_video_buffer_new (mpeg_dec->device, VDP_CHROMA_TYPE_420, + mpeg_dec->width, mpeg_dec->height); + GST_BUFFER_TIMESTAMP (outbuf) = timestamp; + GST_BUFFER_DURATION (outbuf) = mpeg_dec->duration; + GST_BUFFER_OFFSET (outbuf) = mpeg_dec->frame_nr; + GST_BUFFER_SIZE (outbuf) = size; + + if (info->top_field_first) + GST_BUFFER_FLAG_SET (outbuf, GST_VIDEO_BUFFER_TFF); + + if (info->forward_reference != VDP_INVALID_HANDLE && + info->picture_coding_type != I_FRAME) + gst_vdp_video_buffer_add_reference (outbuf, + GST_VDP_VIDEO_BUFFER (mpeg_dec->f_buffer)); + + if (info->backward_reference != VDP_INVALID_HANDLE) + gst_vdp_video_buffer_add_reference (outbuf, + GST_VDP_VIDEO_BUFFER (mpeg_dec->b_buffer)); + + surface = outbuf->surface; + + device = mpeg_dec->device; + + vbit[0].struct_version = VDP_BITSTREAM_BUFFER_VERSION; + vbit[0].bitstream = GST_BUFFER_DATA (buffer); + vbit[0].bitstream_bytes = GST_BUFFER_SIZE (buffer); + + status = device->vdp_decoder_render (mpeg_dec->decoder, surface, + (VdpPictureInfo *) info, 1, vbit); + gst_buffer_unref (buffer); + info->slice_count = 0; + + if (status != VDP_STATUS_OK) { + GST_ELEMENT_ERROR (mpeg_dec, RESOURCE, READ, + ("Could not decode"), + ("Error returned from vdpau was: %s", + device->vdp_get_error_string (status))); + + gst_buffer_unref (GST_BUFFER (outbuf)); + + return GST_FLOW_ERROR; + } + + if (info->picture_coding_type == B_FRAME) { + gst_vdp_mpeg_dec_push_video_buffer (mpeg_dec, + GST_VDP_VIDEO_BUFFER (outbuf)); + } else { + info->backward_reference = surface; + mpeg_dec->b_buffer = GST_BUFFER (outbuf); + } + + return GST_FLOW_OK; +} + +static gboolean +gst_vdp_mpeg_dec_parse_picture_coding (GstVdpMpegDec * mpeg_dec, + GstBuffer * buffer) +{ + MPEGPictureExt pic_ext; + VdpPictureInfoMPEG1Or2 *info; + gint fields; + + info = &mpeg_dec->vdp_info; + + if (!mpeg_util_parse_picture_coding_extension (&pic_ext, buffer)) + return FALSE; + + memcpy (&mpeg_dec->vdp_info.f_code, &pic_ext.f_code, 4); + + info->intra_dc_precision = pic_ext.intra_dc_precision; + info->picture_structure = pic_ext.picture_structure; + info->top_field_first = pic_ext.top_field_first; + info->frame_pred_frame_dct = pic_ext.frame_pred_frame_dct; + info->concealment_motion_vectors = pic_ext.concealment_motion_vectors; + info->q_scale_type = pic_ext.q_scale_type; + info->intra_vlc_format = pic_ext.intra_vlc_format; + info->alternate_scan = pic_ext.alternate_scan; + + fields = 2; + if (pic_ext.picture_structure == 3) { + if (mpeg_dec->interlaced) { + if (pic_ext.progressive_frame == 0) + fields = 2; + if (pic_ext.progressive_frame == 0 && pic_ext.repeat_first_field == 0) + fields = 2; + if (pic_ext.progressive_frame == 1 && pic_ext.repeat_first_field == 1) + fields = 3; + } else { + if (pic_ext.repeat_first_field == 0) + fields = 2; + if (pic_ext.repeat_first_field == 1 && pic_ext.top_field_first == 0) + fields = 4; + if (pic_ext.repeat_first_field == 1 && pic_ext.top_field_first == 1) + fields = 6; + } + } else + fields = 1; + + GST_DEBUG ("fields: %d", fields); + + mpeg_dec->duration = gst_util_uint64_scale (fields, + GST_SECOND * mpeg_dec->fps_d, 2 * mpeg_dec->fps_n); + + return TRUE; +} + +static gboolean +gst_vdp_mpeg_dec_parse_sequence (GstVdpMpegDec * mpeg_dec, GstBuffer * buffer) +{ + MPEGSeqHdr hdr; + + if (!mpeg_util_parse_sequence_hdr (&hdr, buffer)) + return FALSE; + + memcpy (&mpeg_dec->vdp_info.intra_quantizer_matrix, + &hdr.intra_quantizer_matrix, 64); + memcpy (&mpeg_dec->vdp_info.non_intra_quantizer_matrix, + &hdr.non_intra_quantizer_matrix, 64); + + return TRUE; +} + +static gboolean +gst_vdp_mpeg_dec_parse_picture (GstVdpMpegDec * mpeg_dec, GstBuffer * buffer) +{ + MPEGPictureHdr pic_hdr; + + if (!mpeg_util_parse_picture_hdr (&pic_hdr, buffer)) + return FALSE; + + if (pic_hdr.pic_type != I_FRAME + && mpeg_dec->vdp_info.backward_reference == VDP_INVALID_HANDLE) { + GST_DEBUG_OBJECT (mpeg_dec, + "Drop frame since we haven't got an I_FRAME yet"); + return FALSE; + } + if (pic_hdr.pic_type == B_FRAME + && mpeg_dec->vdp_info.forward_reference == VDP_INVALID_HANDLE) { + GST_DEBUG_OBJECT (mpeg_dec, + "Drop frame since we haven't got two non B_FRAMES yet"); + return FALSE; + } + + mpeg_dec->vdp_info.picture_coding_type = pic_hdr.pic_type; + + if (mpeg_dec->version == 1) { + mpeg_dec->vdp_info.full_pel_forward_vector = + pic_hdr.full_pel_forward_vector; + mpeg_dec->vdp_info.full_pel_backward_vector = + pic_hdr.full_pel_backward_vector; + memcpy (&mpeg_dec->vdp_info.f_code, &pic_hdr.f_code, 4); + } + + mpeg_dec->frame_nr = mpeg_dec->gop_frame + pic_hdr.tsn; + + return TRUE; +} + +static gboolean +gst_vdp_mpeg_dec_parse_gop (GstVdpMpegDec * mpeg_dec, GstBuffer * buffer) +{ + MPEGGop gop; + GstClockTime time; + + if (!mpeg_util_parse_gop (&gop, buffer)) + return FALSE; + + time = GST_SECOND * (gop.hour * 3600 + gop.minute * 60 + gop.second); + + GST_DEBUG ("gop timestamp: %" GST_TIME_FORMAT, GST_TIME_ARGS (time)); + + mpeg_dec->gop_frame = + gst_util_uint64_scale (time, mpeg_dec->fps_n, + mpeg_dec->fps_d * GST_SECOND) + gop.frame; + + return TRUE; +} + +static gboolean +gst_vdp_mpeg_dec_parse_quant_matrix (GstVdpMpegDec * mpeg_dec, + GstBuffer * buffer) +{ + MPEGQuantMatrix qm; + + if (!mpeg_util_parse_quant_matrix (&qm, buffer)) + return FALSE; + + memcpy (&mpeg_dec->vdp_info.intra_quantizer_matrix, + &qm.intra_quantizer_matrix, 64); + memcpy (&mpeg_dec->vdp_info.non_intra_quantizer_matrix, + &qm.non_intra_quantizer_matrix, 64); + return TRUE; +} + +static void +gst_vdp_mpeg_dec_flush (GstVdpMpegDec * mpeg_dec) +{ + if (mpeg_dec->vdp_info.forward_reference != VDP_INVALID_HANDLE) + gst_buffer_unref (mpeg_dec->f_buffer); + if (mpeg_dec->vdp_info.backward_reference != VDP_INVALID_HANDLE) + gst_buffer_unref (mpeg_dec->b_buffer); + + gst_vdp_mpeg_dec_init_info (&mpeg_dec->vdp_info); + + gst_adapter_clear (mpeg_dec->adapter); + + mpeg_dec->next_timestamp = GST_CLOCK_TIME_NONE; +} + +static void +gst_vdp_mpeg_dec_reset (GstVdpMpegDec * mpeg_dec) +{ + gst_vdp_mpeg_dec_flush (mpeg_dec); + + if (mpeg_dec->decoder != VDP_INVALID_HANDLE) + mpeg_dec->device->vdp_decoder_destroy (mpeg_dec->decoder); + mpeg_dec->decoder = VDP_INVALID_HANDLE; + if (mpeg_dec->device) + g_object_unref (mpeg_dec->device); + mpeg_dec->device = NULL; + + gst_segment_init (&mpeg_dec->segment, GST_FORMAT_TIME); + mpeg_dec->seeking = FALSE; + + mpeg_dec->accumulated_size = 0; + mpeg_dec->accumulated_duration = 0; +} + +static GstFlowReturn +gst_vdp_mpeg_dec_chain (GstPad * pad, GstBuffer * buffer) +{ + GstVdpMpegDec *mpeg_dec; + GstVdpMpegPacketizer packetizer; + GstBuffer *buf; + GstFlowReturn ret = GST_FLOW_OK; + + mpeg_dec = GST_VDP_MPEG_DEC (GST_OBJECT_PARENT (pad)); + + if (G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT))) { + GST_DEBUG_OBJECT (mpeg_dec, "Received discont buffer"); + gst_vdp_mpeg_dec_flush (mpeg_dec); + } + + + gst_vdp_mpeg_packetizer_init (&packetizer, buffer); + while ((buf = gst_vdp_mpeg_packetizer_get_next_packet (&packetizer))) { + GstBitReader b_reader = GST_BIT_READER_INIT_FROM_BUFFER (buf); + guint32 sync_code; + guint8 start_code; + + /* skip sync_code */ + gst_bit_reader_get_bits_uint32 (&b_reader, &sync_code, 8 * 3); + + /* start_code */ + gst_bit_reader_get_bits_uint8 (&b_reader, &start_code, 8); + + if (start_code >= MPEG_PACKET_SLICE_MIN + && start_code <= MPEG_PACKET_SLICE_MAX) { + GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_SLICE"); + + gst_buffer_ref (buf); + gst_adapter_push (mpeg_dec->adapter, buf); + mpeg_dec->vdp_info.slice_count++; + } + + switch (start_code) { + case MPEG_PACKET_PICTURE: + GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_PICTURE"); + + if (!gst_vdp_mpeg_dec_parse_picture (mpeg_dec, buf)) { + return GST_FLOW_OK; + } + break; + case MPEG_PACKET_SEQUENCE: + GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_SEQUENCE"); + gst_vdp_mpeg_dec_parse_sequence (mpeg_dec, buf); + break; + case MPEG_PACKET_EXTENSION: + { + guint8 ext_code; + + GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_EXTENSION"); + + /* ext_code */ + gst_bit_reader_get_bits_uint8 (&b_reader, &ext_code, 4); + switch (ext_code) { + case MPEG_PACKET_EXT_PICTURE_CODING: + GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_EXT_PICTURE_CODING"); + gst_vdp_mpeg_dec_parse_picture_coding (mpeg_dec, buf); + break; + case MPEG_PACKET_EXT_QUANT_MATRIX: + GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_EXT_QUANT_MATRIX"); + gst_vdp_mpeg_dec_parse_quant_matrix (mpeg_dec, buf); + break; + default: + break; + } + break; + } + case MPEG_PACKET_GOP: + GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_GOP"); + gst_vdp_mpeg_dec_parse_gop (mpeg_dec, buf); + break; + default: + break; + } + + gst_buffer_unref (buf); + } + + if (mpeg_dec->vdp_info.slice_count > 0) + ret = gst_vdp_mpeg_dec_decode (mpeg_dec, GST_BUFFER_TIMESTAMP (buffer), + GST_BUFFER_SIZE (buffer)); + + return ret; +} + +static gboolean +gst_vdp_mpeg_dec_convert (GstVdpMpegDec * mpeg_dec, + GstFormat src_format, gint64 src_value, + GstFormat dest_format, gint64 * dest_value) +{ + + if (src_format == dest_format) { + *dest_value = src_value; + return TRUE; + } + + if (mpeg_dec->byterate == -1) + return FALSE; + + if (src_format == GST_FORMAT_BYTES && dest_format == GST_FORMAT_TIME) { + *dest_value = gst_util_uint64_scale (GST_SECOND, src_value, + mpeg_dec->byterate); + return TRUE; + } + + if (src_format == GST_FORMAT_TIME && dest_format == GST_FORMAT_BYTES) { + *dest_value = + gst_util_uint64_scale_int (src_value, mpeg_dec->byterate, GST_SECOND); + return TRUE; + } + + return FALSE; +} + +static const GstQueryType * +gst_mpeg_dec_get_querytypes (GstPad * pad) +{ + static const GstQueryType list[] = { + GST_QUERY_POSITION, + GST_QUERY_DURATION, + 0 + }; + + return list; +} + +static gboolean +gst_vdp_mpeg_dec_src_query (GstPad * pad, GstQuery * query) +{ + GstVdpMpegDec *mpeg_dec = GST_VDP_MPEG_DEC (GST_OBJECT_PARENT (pad)); + gboolean res = FALSE; + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_POSITION: + { + GstFormat format; + + if (gst_pad_query_default (pad, query)) + return TRUE; + + gst_query_parse_position (query, &format, NULL); + if (format == GST_FORMAT_TIME && + GST_CLOCK_TIME_IS_VALID (mpeg_dec->next_timestamp)) { + gst_query_set_position (query, GST_FORMAT_TIME, + mpeg_dec->next_timestamp); + res = TRUE; + } + break; + } + + case GST_QUERY_DURATION: + { + GstFormat format; + + if (gst_pad_query_default (pad, query)) + return TRUE; + + gst_query_parse_duration (query, &format, NULL); + if (format == GST_FORMAT_TIME) { + gint64 bytes; + + format = GST_FORMAT_BYTES; + if (gst_pad_query_duration (pad, &format, &bytes) + && format == GST_FORMAT_BYTES) { + gint64 duration; + + if (gst_vdp_mpeg_dec_convert (mpeg_dec, GST_FORMAT_BYTES, + bytes, GST_FORMAT_TIME, &duration)) { + GST_DEBUG ("duration: %" GST_TIME_FORMAT, GST_TIME_ARGS (duration)); + gst_query_set_duration (query, GST_FORMAT_TIME, duration); + res = TRUE; + } + } + } + break; + } + + default: + res = gst_pad_query_default (pad, query); + } + + return res; +} + +static gboolean +normal_seek (GstPad * pad, GstEvent * event) +{ + GstVdpMpegDec *mpeg_dec = GST_VDP_MPEG_DEC (GST_OBJECT_PARENT (pad)); + gdouble rate; + GstFormat format, conv; + GstSeekFlags flags; + GstSeekType cur_type, stop_type; + gint64 cur, stop; + gint64 time_cur, bytes_cur; + gint64 time_stop, bytes_stop; + gboolean res; + GstEvent *peer_event; + + GST_DEBUG ("normal seek"); + + gst_event_parse_seek (event, &rate, &format, &flags, + &cur_type, &cur, &stop_type, &stop); + + conv = GST_FORMAT_TIME; + if (!gst_vdp_mpeg_dec_convert (mpeg_dec, format, cur, conv, &time_cur)) + goto convert_failed; + if (!gst_vdp_mpeg_dec_convert (mpeg_dec, format, stop, conv, &time_stop)) + goto convert_failed; + + GST_DEBUG ("seek to time %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT, + GST_TIME_ARGS (time_cur), GST_TIME_ARGS (time_stop)); + + peer_event = gst_event_new_seek (rate, GST_FORMAT_TIME, flags, + cur_type, time_cur, stop_type, time_stop); + + /* try seek on time then */ + if ((res = gst_pad_push_event (mpeg_dec->sink, peer_event))) + goto done; + + /* else we try to seek on bytes */ + conv = GST_FORMAT_BYTES; + if (!gst_vdp_mpeg_dec_convert (mpeg_dec, GST_FORMAT_TIME, time_cur, + conv, &bytes_cur)) + goto convert_failed; + if (!gst_vdp_mpeg_dec_convert (mpeg_dec, GST_FORMAT_TIME, time_stop, + conv, &bytes_stop)) + goto convert_failed; + + /* conversion succeeded, create the seek */ + peer_event = + gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, + cur_type, bytes_cur, stop_type, bytes_stop); + + /* do the seek */ + res = gst_pad_push_event (mpeg_dec->sink, peer_event); + + mpeg_dec->seeking = TRUE; + +done: + return res; + + /* ERRORS */ +convert_failed: + { + /* probably unsupported seek format */ + GST_DEBUG_OBJECT (mpeg_dec, + "failed to convert format %u into GST_FORMAT_TIME", format); + return FALSE; + } +} + +static gboolean +gst_vdp_mpeg_dec_src_event (GstPad * pad, GstEvent * event) +{ + gboolean res; + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_SEEK: + { + if (gst_pad_event_default (pad, event)) + return TRUE; + + res = normal_seek (pad, event); + break; + } + default: + res = gst_pad_event_default (pad, event); + } + + return res; +} + +static gboolean +gst_vdp_mpeg_dec_sink_event (GstPad * pad, GstEvent * event) +{ + GstVdpMpegDec *mpeg_dec = GST_VDP_MPEG_DEC (GST_OBJECT_PARENT (pad)); + gboolean res; + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_FLUSH_STOP: + { + GST_DEBUG_OBJECT (mpeg_dec, "flush stop"); + + gst_vdp_mpeg_dec_flush (mpeg_dec); + res = gst_pad_push_event (mpeg_dec->src, event); + + break; + } + case GST_EVENT_NEWSEGMENT: + { + gboolean update; + gdouble rate; + GstFormat format; + gint64 start; + gint64 stop; + gint64 position; + + gst_event_parse_new_segment (event, &update, &rate, &format, + &start, &stop, &position); + + if (format != GST_FORMAT_TIME) { + if (!gst_vdp_mpeg_dec_convert (mpeg_dec, format, start, + GST_FORMAT_TIME, &start)) + goto convert_error; + if (!gst_vdp_mpeg_dec_convert (mpeg_dec, format, stop, + GST_FORMAT_TIME, &stop)) + goto convert_error; + if (!gst_vdp_mpeg_dec_convert (mpeg_dec, format, position, + GST_FORMAT_TIME, &position)) + goto convert_error; + + gst_segment_set_newsegment (&mpeg_dec->segment, update, rate, + GST_FORMAT_TIME, start, stop, position); + + gst_event_unref (event); + event = gst_event_new_new_segment (update, rate, GST_FORMAT_TIME, start, + stop, position); + } + + /* if we seek ourselves we don't push out a newsegment now since we + * use the calculated timestamp of the first frame for this */ + if (mpeg_dec->seeking) { + gst_event_unref (event); + return TRUE; + } + + convert_error: + res = gst_pad_push_event (mpeg_dec->src, event); + + break; + } + default: + res = gst_pad_event_default (pad, event); + } + + return res; +} + +static GstStateChangeReturn +gst_vdp_mpeg_dec_change_state (GstElement * element, GstStateChange transition) +{ + GstVdpMpegDec *mpeg_dec; + GstStateChangeReturn ret; + + mpeg_dec = GST_VDP_MPEG_DEC (element); + + switch (transition) { + case GST_STATE_CHANGE_READY_TO_PAUSED: + mpeg_dec->device = gst_vdp_get_device (mpeg_dec->display_name); + break; + default: + break; + } + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + + switch (transition) { + case GST_STATE_CHANGE_PAUSED_TO_READY: + gst_vdp_mpeg_dec_reset (mpeg_dec); + break; + default: + break; + } + + return ret; +} + +/* GObject vmethod implementations */ + +static void +gst_vdp_mpeg_dec_base_init (gpointer gclass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (gclass); + + gst_element_class_set_details_simple (element_class, + "VDPAU Mpeg Decoder", + "Decoder", + "decode mpeg stream with vdpau", + "Carl-Anton Ingmarsson "); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&sink_template)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&src_template)); +} + +/* initialize the vdpaumpegdecoder's class */ +static void +gst_vdp_mpeg_dec_class_init (GstVdpMpegDecClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + + gobject_class = (GObjectClass *) klass; + gstelement_class = (GstElementClass *) klass; + + gobject_class->finalize = gst_vdp_mpeg_dec_finalize; + gobject_class->set_property = gst_vdp_mpeg_dec_set_property; + gobject_class->get_property = gst_vdp_mpeg_dec_get_property; + + gstelement_class->change_state = + GST_DEBUG_FUNCPTR (gst_vdp_mpeg_dec_change_state); + + g_object_class_install_property (gobject_class, PROP_DISPLAY, + g_param_spec_string ("display", "Display", "X Display name", + NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); +} + +static void +gst_vdp_mpeg_dec_init_info (VdpPictureInfoMPEG1Or2 * vdp_info) +{ + vdp_info->forward_reference = VDP_INVALID_HANDLE; + vdp_info->backward_reference = VDP_INVALID_HANDLE; + vdp_info->slice_count = 0; + vdp_info->picture_structure = 3; + vdp_info->picture_coding_type = 0; + vdp_info->intra_dc_precision = 0; + vdp_info->frame_pred_frame_dct = 1; + vdp_info->concealment_motion_vectors = 0; + vdp_info->intra_vlc_format = 0; + vdp_info->alternate_scan = 0; + vdp_info->q_scale_type = 0; + vdp_info->top_field_first = 1; +} + +static void +gst_vdp_mpeg_dec_init (GstVdpMpegDec * mpeg_dec, GstVdpMpegDecClass * gclass) +{ + mpeg_dec->src = gst_pad_new_from_static_template (&src_template, "src"); + gst_pad_set_event_function (mpeg_dec->src, + GST_DEBUG_FUNCPTR (gst_vdp_mpeg_dec_src_event)); + gst_pad_set_query_function (mpeg_dec->src, + GST_DEBUG_FUNCPTR (gst_vdp_mpeg_dec_src_query)); + gst_pad_set_query_type_function (mpeg_dec->src, + GST_DEBUG_FUNCPTR (gst_mpeg_dec_get_querytypes)); + gst_element_add_pad (GST_ELEMENT (mpeg_dec), mpeg_dec->src); + + mpeg_dec->sink = gst_pad_new_from_static_template (&sink_template, "sink"); + gst_pad_set_setcaps_function (mpeg_dec->sink, + GST_DEBUG_FUNCPTR (gst_vdp_mpeg_dec_set_caps)); + gst_pad_set_chain_function (mpeg_dec->sink, + GST_DEBUG_FUNCPTR (gst_vdp_mpeg_dec_chain)); + gst_pad_set_event_function (mpeg_dec->sink, + GST_DEBUG_FUNCPTR (gst_vdp_mpeg_dec_sink_event)); + gst_element_add_pad (GST_ELEMENT (mpeg_dec), mpeg_dec->sink); + + mpeg_dec->display_name = NULL; + mpeg_dec->adapter = gst_adapter_new (); + + mpeg_dec->device = NULL; + mpeg_dec->decoder = VDP_INVALID_HANDLE; + mpeg_dec->vdp_info.forward_reference = VDP_INVALID_HANDLE; + mpeg_dec->vdp_info.backward_reference = VDP_INVALID_HANDLE; + + gst_vdp_mpeg_dec_reset (mpeg_dec); +} + +static void +gst_vdp_mpeg_dec_finalize (GObject * object) +{ + GstVdpMpegDec *mpeg_dec = (GstVdpMpegDec *) object; + + g_object_unref (mpeg_dec->adapter); +} + +static void +gst_vdp_mpeg_dec_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstVdpMpegDec *mpeg_dec = GST_VDP_MPEG_DEC (object); + + switch (prop_id) { + case PROP_DISPLAY: + g_free (mpeg_dec->display_name); + mpeg_dec->display_name = g_value_dup_string (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_vdp_mpeg_dec_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstVdpMpegDec *mpeg_dec = GST_VDP_MPEG_DEC (object); + + switch (prop_id) { + case PROP_DISPLAY: + g_value_set_string (value, mpeg_dec->display_name); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} diff --git a/sys/vdpau/gstvdpmpegdec.h b/sys/vdpau/gstvdpmpegdec.h new file mode 100644 index 00000000..b60c9f59 --- /dev/null +++ b/sys/vdpau/gstvdpmpegdec.h @@ -0,0 +1,93 @@ +/* + * GStreamer + * Copyright (C) 2009 Carl-Anton Ingmarsson + * + * 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_VDP_MPEG_DEC_H__ +#define __GST_VDP_MPEG_DEC_H__ + +#include +#include + +#include "gstvdpdevice.h" +#include "gstvdpvideobuffer.h" + +G_BEGIN_DECLS + +#define GST_TYPE_VDP_MPEG_DEC (gst_vdp_mpeg_dec_get_type()) +#define GST_VDP_MPEG_DEC(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VDP_MPEG_DEC,GstVdpMpegDec)) +#define GST_VDP_MPEG_DEC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VDP_MPEG_DEC,GstVdpMpegDecClass)) +#define GST_IS_VDPAU_MPEG_DEC(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VDP_MPEG_DEC)) +#define GST_IS_VDPAU_MPEG_DEC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VDP_MPEG_DEC)) + +typedef struct _GstVdpMpegDec GstVdpMpegDec; +typedef struct _GstVdpMpegDecClass GstVdpMpegDecClass; + +struct _GstVdpMpegDec +{ + GstElement element; + + /* pads */ + GstPad *src; + GstPad *sink; + + gchar *display_name; + GstVdpDevice *device; + VdpDecoder decoder; + + /* stream info */ + gint width, height; + gint fps_n, fps_d; + gboolean interlaced; + gint version; + + /* currently decoded frame info */ + GstAdapter *adapter; + VdpPictureInfoMPEG1Or2 vdp_info; + guint64 frame_nr; + GstClockTime duration; + + /* frame_nr from GOP */ + guint64 gop_frame; + + /* forward and backward reference */ + GstBuffer *f_buffer; + GstBuffer *b_buffer; + + /* calculated timestamp, size and duration */ + GstClockTime next_timestamp; + guint64 accumulated_size; + guint64 accumulated_duration; + + /* seek data */ + GstSegment segment; + gboolean seeking; + gint64 byterate; + +}; + +struct _GstVdpMpegDecClass +{ + GstElementClass element_class; +}; + +GType gst_vdp_mpeg_dec_get_type (void); + +G_END_DECLS + +#endif /* __GST_VDP_MPEG_DEC_H__ */ diff --git a/sys/vdpau/gstvdpmpegdecoder.c b/sys/vdpau/gstvdpmpegdecoder.c deleted file mode 100644 index 3c4d7480..00000000 --- a/sys/vdpau/gstvdpmpegdecoder.c +++ /dev/null @@ -1,1093 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2009 Carl-Anton Ingmarsson - * - * 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-vdpaumpegdec - * - * FIXME:Describe vdpaumpegdec here. - * - * - * Example launch line - * |[ - * gst-launch -v -m fakesrc ! vdpaumpegdec ! fakesink silent=TRUE - * ]| - * - */ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include -#include -#include -#include - -#include "mpegutil.h" -#include "gstvdpmpegdecoder.h" - -GST_DEBUG_CATEGORY_STATIC (gst_vdp_mpeg_dec_debug); -#define GST_CAT_DEFAULT gst_vdp_mpeg_dec_debug - -/* Filter signals and args */ -enum -{ - /* FILL ME */ - LAST_SIGNAL -}; - -enum -{ - PROP_0, - PROP_DISPLAY -}; - -/* the capabilities of the inputs and outputs. - * - * describe the real formats here. - */ -static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS ("video/mpeg, mpegversion = (int) [ 1, 2 ], " - "systemstream = (boolean) false, parsed = (boolean) true") - ); -static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src", - GST_PAD_SRC, - GST_PAD_ALWAYS, - GST_STATIC_CAPS ("video/x-vdpau-video, " "chroma-type = (int) 0") - ); - -#define DEBUG_INIT(bla) \ -GST_DEBUG_CATEGORY_INIT (gst_vdp_mpeg_dec_debug, "vdpaumpegdec", 0, "VDPAU powered mpeg decoder"); - -GST_BOILERPLATE_FULL (GstVdpMpegDec, gst_vdp_mpeg_dec, - GstElement, GST_TYPE_ELEMENT, DEBUG_INIT); - -static void gst_vdp_mpeg_dec_init_info (VdpPictureInfoMPEG1Or2 * vdp_info); -static void gst_vdp_mpeg_dec_finalize (GObject * object); -static void gst_vdp_mpeg_dec_set_property (GObject * object, - guint prop_id, const GValue * value, GParamSpec * pspec); -static void gst_vdp_mpeg_dec_get_property (GObject * object, - guint prop_id, GValue * value, GParamSpec * pspec); - -guint8 * -mpeg_util_find_start_code (guint32 * sync_word, guint8 * cur, guint8 * end) -{ - guint32 code; - - if (G_UNLIKELY (cur == NULL)) - return NULL; - - code = *sync_word; - - while (cur < end) { - code <<= 8; - - if (code == 0x00000100) { - /* Reset the sync word accumulator */ - *sync_word = 0xffffffff; - return cur; - } - - /* Add the next available byte to the collected sync word */ - code |= *cur++; - } - - *sync_word = code; - return NULL; -} - -typedef struct -{ - GstBuffer *buffer; - guint8 *cur; - guint8 *end; -} GstVdpMpegPacketizer; - -static GstBuffer * -gst_vdp_mpeg_packetizer_get_next_packet (GstVdpMpegPacketizer * packetizer) -{ - guint32 sync_word = 0xffffff; - guint8 *packet_start; - guint8 *packet_end; - - if (!packetizer->cur) - return NULL; - - packet_start = packetizer->cur - 3; - packetizer->cur = packet_end = mpeg_util_find_start_code (&sync_word, - packetizer->cur, packetizer->end); - - if (packet_end) - packet_end -= 3; - else - packet_end = packetizer->end; - - return gst_buffer_create_sub (packetizer->buffer, - packet_start - GST_BUFFER_DATA (packetizer->buffer), - packet_end - packet_start); -} - -static void -gst_vdp_mpeg_packetizer_init (GstVdpMpegPacketizer * packetizer, - GstBuffer * buffer) -{ - guint32 sync_word = 0xffffffff; - - packetizer->buffer = buffer; - packetizer->end = GST_BUFFER_DATA (buffer) + GST_BUFFER_SIZE (buffer); - packetizer->cur = mpeg_util_find_start_code (&sync_word, - GST_BUFFER_DATA (buffer), packetizer->end); -} - -static gboolean -gst_vdp_mpeg_dec_set_caps (GstPad * pad, GstCaps * caps) -{ - GstVdpMpegDec *mpeg_dec = GST_VDP_MPEG_DEC (GST_OBJECT_PARENT (pad)); - GstStructure *structure; - - gint width, height; - gint fps_n, fps_d; - gint par_n, par_d; - gboolean interlaced = FALSE; - - GstCaps *src_caps; - gboolean res; - - const GValue *value; - VdpDecoderProfile profile; - GstVdpDevice *device; - VdpStatus status; - - structure = gst_caps_get_structure (caps, 0); - - /* create src_pad caps */ - gst_structure_get_int (structure, "width", &width); - gst_structure_get_int (structure, "height", &height); - gst_structure_get_fraction (structure, "framerate", &fps_n, &fps_d); - gst_structure_get_fraction (structure, "pixel-aspect-ratio", &par_n, &par_d); - gst_structure_get_boolean (structure, "interlaced", &interlaced); - - src_caps = gst_caps_new_simple ("video/x-vdpau-video", - "device", G_TYPE_OBJECT, mpeg_dec->device, - "chroma_type", G_TYPE_INT, VDP_CHROMA_TYPE_420, - "width", G_TYPE_INT, width, - "height", G_TYPE_INT, height, - "framerate", GST_TYPE_FRACTION, fps_n, fps_d, - "pixel-aspect-ratio", GST_TYPE_FRACTION, par_n, par_d, - "interlaced", G_TYPE_BOOLEAN, interlaced, NULL); - - res = gst_pad_set_caps (mpeg_dec->src, src_caps); - gst_caps_unref (src_caps); - if (!res) - return FALSE; - - mpeg_dec->width = width; - mpeg_dec->height = height; - mpeg_dec->fps_n = fps_n; - mpeg_dec->fps_d = fps_d; - mpeg_dec->interlaced = interlaced; - - /* parse caps to setup decoder */ - gst_structure_get_int (structure, "mpegversion", &mpeg_dec->version); - if (mpeg_dec->version == 1) - profile = VDP_DECODER_PROFILE_MPEG1; - - value = gst_structure_get_value (structure, "codec_data"); - if (value) { - GstBuffer *codec_data, *buf; - GstVdpMpegPacketizer packetizer; - - codec_data = gst_value_get_buffer (value); - gst_vdp_mpeg_packetizer_init (&packetizer, codec_data); - if ((buf = gst_vdp_mpeg_packetizer_get_next_packet (&packetizer))) { - MPEGSeqHdr hdr; - guint32 bitrate; - - mpeg_util_parse_sequence_hdr (&hdr, buf); - - memcpy (&mpeg_dec->vdp_info.intra_quantizer_matrix, - &hdr.intra_quantizer_matrix, 64); - memcpy (&mpeg_dec->vdp_info.non_intra_quantizer_matrix, - &hdr.non_intra_quantizer_matrix, 64); - - bitrate = hdr.bitrate; - gst_buffer_unref (buf); - - if ((buf = gst_vdp_mpeg_packetizer_get_next_packet (&packetizer))) { - MPEGSeqExtHdr ext; - - mpeg_util_parse_sequence_extension (&ext, buf); - if (mpeg_dec->version != 1) { - switch (ext.profile) { - case 5: - profile = VDP_DECODER_PROFILE_MPEG2_SIMPLE; - break; - default: - profile = VDP_DECODER_PROFILE_MPEG2_MAIN; - break; - } - } - - bitrate += (ext.bitrate_ext << 18);; - gst_buffer_unref (buf); - } - - mpeg_dec->duration = - gst_util_uint64_scale (1, GST_SECOND * mpeg_dec->fps_d, - mpeg_dec->fps_n); - - mpeg_dec->byterate = bitrate * 50; - GST_DEBUG ("byterate: %" G_GINT64_FORMAT, mpeg_dec->byterate); - } - } - - device = mpeg_dec->device; - - if (mpeg_dec->decoder != VDP_INVALID_HANDLE) { - device->vdp_decoder_destroy (mpeg_dec->decoder); - mpeg_dec->decoder = VDP_INVALID_HANDLE; - } - - status = device->vdp_decoder_create (device->device, profile, mpeg_dec->width, - mpeg_dec->height, 2, &mpeg_dec->decoder); - if (status != VDP_STATUS_OK) { - GST_ELEMENT_ERROR (mpeg_dec, RESOURCE, READ, - ("Could not create vdpau decoder"), - ("Error returned from vdpau was: %s", - device->vdp_get_error_string (status))); - return FALSE; - } - return TRUE; -} - -GstFlowReturn -gst_vdp_mpeg_dec_push_video_buffer (GstVdpMpegDec * mpeg_dec, - GstVdpVideoBuffer * buffer) -{ - gint64 byterate; - - if (GST_BUFFER_TIMESTAMP (buffer) == GST_CLOCK_TIME_NONE - && GST_CLOCK_TIME_IS_VALID (mpeg_dec->next_timestamp)) { - GST_BUFFER_TIMESTAMP (buffer) = mpeg_dec->next_timestamp; - } else if (GST_BUFFER_TIMESTAMP (buffer) == GST_CLOCK_TIME_NONE) { - GST_BUFFER_TIMESTAMP (buffer) = gst_util_uint64_scale (mpeg_dec->frame_nr, - GST_SECOND * mpeg_dec->fps_d, mpeg_dec->fps_n); - } - - if (mpeg_dec->seeking) { - GstEvent *event; - - event = gst_event_new_new_segment (FALSE, - mpeg_dec->segment.rate, GST_FORMAT_TIME, GST_BUFFER_TIMESTAMP (buffer), - mpeg_dec->segment.stop, GST_BUFFER_TIMESTAMP (buffer)); - - gst_pad_push_event (mpeg_dec->src, event); - - mpeg_dec->seeking = FALSE; - } - - mpeg_dec->next_timestamp = GST_BUFFER_TIMESTAMP (buffer) + - GST_BUFFER_DURATION (buffer); - - mpeg_dec->accumulated_duration += GST_BUFFER_DURATION (buffer); - mpeg_dec->accumulated_size += GST_BUFFER_SIZE (buffer); - byterate = gst_util_uint64_scale (mpeg_dec->accumulated_size, GST_SECOND, - mpeg_dec->accumulated_duration); - GST_DEBUG ("byterate: %" G_GINT64_FORMAT, mpeg_dec->byterate); - - mpeg_dec->byterate = (mpeg_dec->byterate + byterate) / 2; - - gst_buffer_set_caps (GST_BUFFER (buffer), GST_PAD_CAPS (mpeg_dec->src)); - - GST_DEBUG_OBJECT (mpeg_dec, - "Pushing buffer with timestamp: %" GST_TIME_FORMAT - " frame_nr: %" G_GINT64_FORMAT, - GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)), - GST_BUFFER_OFFSET (buffer)); - - return gst_pad_push (mpeg_dec->src, GST_BUFFER (buffer)); -} - -static GstFlowReturn -gst_vdp_mpeg_dec_decode (GstVdpMpegDec * mpeg_dec, - GstClockTime timestamp, gint64 size) -{ - VdpPictureInfoMPEG1Or2 *info; - GstBuffer *buffer; - GstVdpVideoBuffer *outbuf; - VdpVideoSurface surface; - GstVdpDevice *device; - VdpBitstreamBuffer vbit[1]; - VdpStatus status; - - info = &mpeg_dec->vdp_info; - - buffer = gst_adapter_take_buffer (mpeg_dec->adapter, - gst_adapter_available (mpeg_dec->adapter)); - - if (info->picture_coding_type != B_FRAME) { - if (info->backward_reference != VDP_INVALID_HANDLE) { - gst_buffer_ref (mpeg_dec->b_buffer); - gst_vdp_mpeg_dec_push_video_buffer (mpeg_dec, - GST_VDP_VIDEO_BUFFER (mpeg_dec->b_buffer)); - } - - if (info->forward_reference != VDP_INVALID_HANDLE) { - gst_buffer_unref (mpeg_dec->f_buffer); - info->forward_reference = VDP_INVALID_HANDLE; - } - - info->forward_reference = info->backward_reference; - mpeg_dec->f_buffer = mpeg_dec->b_buffer; - - info->backward_reference = VDP_INVALID_HANDLE; - } - - outbuf = gst_vdp_video_buffer_new (mpeg_dec->device, VDP_CHROMA_TYPE_420, - mpeg_dec->width, mpeg_dec->height); - GST_BUFFER_TIMESTAMP (outbuf) = timestamp; - GST_BUFFER_DURATION (outbuf) = mpeg_dec->duration; - GST_BUFFER_OFFSET (outbuf) = mpeg_dec->frame_nr; - GST_BUFFER_SIZE (outbuf) = size; - - if (info->top_field_first) - GST_BUFFER_FLAG_SET (outbuf, GST_VIDEO_BUFFER_TFF); - - if (info->forward_reference != VDP_INVALID_HANDLE && - info->picture_coding_type != I_FRAME) - gst_vdp_video_buffer_add_reference (outbuf, - GST_VDP_VIDEO_BUFFER (mpeg_dec->f_buffer)); - - if (info->backward_reference != VDP_INVALID_HANDLE) - gst_vdp_video_buffer_add_reference (outbuf, - GST_VDP_VIDEO_BUFFER (mpeg_dec->b_buffer)); - - surface = outbuf->surface; - - device = mpeg_dec->device; - - vbit[0].struct_version = VDP_BITSTREAM_BUFFER_VERSION; - vbit[0].bitstream = GST_BUFFER_DATA (buffer); - vbit[0].bitstream_bytes = GST_BUFFER_SIZE (buffer); - - status = device->vdp_decoder_render (mpeg_dec->decoder, surface, - (VdpPictureInfo *) info, 1, vbit); - gst_buffer_unref (buffer); - info->slice_count = 0; - - if (status != VDP_STATUS_OK) { - GST_ELEMENT_ERROR (mpeg_dec, RESOURCE, READ, - ("Could not decode"), - ("Error returned from vdpau was: %s", - device->vdp_get_error_string (status))); - - gst_buffer_unref (GST_BUFFER (outbuf)); - - return GST_FLOW_ERROR; - } - - if (info->picture_coding_type == B_FRAME) { - gst_vdp_mpeg_dec_push_video_buffer (mpeg_dec, - GST_VDP_VIDEO_BUFFER (outbuf)); - } else { - info->backward_reference = surface; - mpeg_dec->b_buffer = GST_BUFFER (outbuf); - } - - return GST_FLOW_OK; -} - -static gboolean -gst_vdp_mpeg_dec_parse_picture_coding (GstVdpMpegDec * mpeg_dec, - GstBuffer * buffer) -{ - MPEGPictureExt pic_ext; - VdpPictureInfoMPEG1Or2 *info; - gint fields; - - info = &mpeg_dec->vdp_info; - - if (!mpeg_util_parse_picture_coding_extension (&pic_ext, buffer)) - return FALSE; - - memcpy (&mpeg_dec->vdp_info.f_code, &pic_ext.f_code, 4); - - info->intra_dc_precision = pic_ext.intra_dc_precision; - info->picture_structure = pic_ext.picture_structure; - info->top_field_first = pic_ext.top_field_first; - info->frame_pred_frame_dct = pic_ext.frame_pred_frame_dct; - info->concealment_motion_vectors = pic_ext.concealment_motion_vectors; - info->q_scale_type = pic_ext.q_scale_type; - info->intra_vlc_format = pic_ext.intra_vlc_format; - info->alternate_scan = pic_ext.alternate_scan; - - fields = 2; - if (pic_ext.picture_structure == 3) { - if (mpeg_dec->interlaced) { - if (pic_ext.progressive_frame == 0) - fields = 2; - if (pic_ext.progressive_frame == 0 && pic_ext.repeat_first_field == 0) - fields = 2; - if (pic_ext.progressive_frame == 1 && pic_ext.repeat_first_field == 1) - fields = 3; - } else { - if (pic_ext.repeat_first_field == 0) - fields = 2; - if (pic_ext.repeat_first_field == 1 && pic_ext.top_field_first == 0) - fields = 4; - if (pic_ext.repeat_first_field == 1 && pic_ext.top_field_first == 1) - fields = 6; - } - } else - fields = 1; - - GST_DEBUG ("fields: %d", fields); - - mpeg_dec->duration = gst_util_uint64_scale (fields, - GST_SECOND * mpeg_dec->fps_d, 2 * mpeg_dec->fps_n); - - return TRUE; -} - -static gboolean -gst_vdp_mpeg_dec_parse_sequence (GstVdpMpegDec * mpeg_dec, GstBuffer * buffer) -{ - MPEGSeqHdr hdr; - - if (!mpeg_util_parse_sequence_hdr (&hdr, buffer)) - return FALSE; - - memcpy (&mpeg_dec->vdp_info.intra_quantizer_matrix, - &hdr.intra_quantizer_matrix, 64); - memcpy (&mpeg_dec->vdp_info.non_intra_quantizer_matrix, - &hdr.non_intra_quantizer_matrix, 64); - - return TRUE; -} - -static gboolean -gst_vdp_mpeg_dec_parse_picture (GstVdpMpegDec * mpeg_dec, GstBuffer * buffer) -{ - MPEGPictureHdr pic_hdr; - - if (!mpeg_util_parse_picture_hdr (&pic_hdr, buffer)) - return FALSE; - - if (pic_hdr.pic_type != I_FRAME - && mpeg_dec->vdp_info.backward_reference == VDP_INVALID_HANDLE) { - GST_DEBUG_OBJECT (mpeg_dec, - "Drop frame since we haven't got an I_FRAME yet"); - return FALSE; - } - if (pic_hdr.pic_type == B_FRAME - && mpeg_dec->vdp_info.forward_reference == VDP_INVALID_HANDLE) { - GST_DEBUG_OBJECT (mpeg_dec, - "Drop frame since we haven't got two non B_FRAMES yet"); - return FALSE; - } - - mpeg_dec->vdp_info.picture_coding_type = pic_hdr.pic_type; - - if (mpeg_dec->version == 1) { - mpeg_dec->vdp_info.full_pel_forward_vector = - pic_hdr.full_pel_forward_vector; - mpeg_dec->vdp_info.full_pel_backward_vector = - pic_hdr.full_pel_backward_vector; - memcpy (&mpeg_dec->vdp_info.f_code, &pic_hdr.f_code, 4); - } - - mpeg_dec->frame_nr = mpeg_dec->gop_frame + pic_hdr.tsn; - - return TRUE; -} - -static gboolean -gst_vdp_mpeg_dec_parse_gop (GstVdpMpegDec * mpeg_dec, GstBuffer * buffer) -{ - MPEGGop gop; - GstClockTime time; - - if (!mpeg_util_parse_gop (&gop, buffer)) - return FALSE; - - time = GST_SECOND * (gop.hour * 3600 + gop.minute * 60 + gop.second); - - GST_DEBUG ("gop timestamp: %" GST_TIME_FORMAT, GST_TIME_ARGS (time)); - - mpeg_dec->gop_frame = - gst_util_uint64_scale (time, mpeg_dec->fps_n, - mpeg_dec->fps_d * GST_SECOND) + gop.frame; - - return TRUE; -} - -static gboolean -gst_vdp_mpeg_dec_parse_quant_matrix (GstVdpMpegDec * mpeg_dec, - GstBuffer * buffer) -{ - MPEGQuantMatrix qm; - - if (!mpeg_util_parse_quant_matrix (&qm, buffer)) - return FALSE; - - memcpy (&mpeg_dec->vdp_info.intra_quantizer_matrix, - &qm.intra_quantizer_matrix, 64); - memcpy (&mpeg_dec->vdp_info.non_intra_quantizer_matrix, - &qm.non_intra_quantizer_matrix, 64); - return TRUE; -} - -static void -gst_vdp_mpeg_dec_flush (GstVdpMpegDec * mpeg_dec) -{ - if (mpeg_dec->vdp_info.forward_reference != VDP_INVALID_HANDLE) - gst_buffer_unref (mpeg_dec->f_buffer); - if (mpeg_dec->vdp_info.backward_reference != VDP_INVALID_HANDLE) - gst_buffer_unref (mpeg_dec->b_buffer); - - gst_vdp_mpeg_dec_init_info (&mpeg_dec->vdp_info); - - gst_adapter_clear (mpeg_dec->adapter); - - mpeg_dec->next_timestamp = GST_CLOCK_TIME_NONE; -} - -static void -gst_vdp_mpeg_dec_reset (GstVdpMpegDec * mpeg_dec) -{ - gst_vdp_mpeg_dec_flush (mpeg_dec); - - if (mpeg_dec->decoder != VDP_INVALID_HANDLE) - mpeg_dec->device->vdp_decoder_destroy (mpeg_dec->decoder); - mpeg_dec->decoder = VDP_INVALID_HANDLE; - if (mpeg_dec->device) - g_object_unref (mpeg_dec->device); - mpeg_dec->device = NULL; - - gst_segment_init (&mpeg_dec->segment, GST_FORMAT_TIME); - mpeg_dec->seeking = FALSE; - - mpeg_dec->accumulated_size = 0; - mpeg_dec->accumulated_duration = 0; -} - -static GstFlowReturn -gst_vdp_mpeg_dec_chain (GstPad * pad, GstBuffer * buffer) -{ - GstVdpMpegDec *mpeg_dec; - GstVdpMpegPacketizer packetizer; - GstBuffer *buf; - GstFlowReturn ret = GST_FLOW_OK; - - mpeg_dec = GST_VDP_MPEG_DEC (GST_OBJECT_PARENT (pad)); - - if (G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT))) { - GST_DEBUG_OBJECT (mpeg_dec, "Received discont buffer"); - gst_vdp_mpeg_dec_flush (mpeg_dec); - } - - - gst_vdp_mpeg_packetizer_init (&packetizer, buffer); - while ((buf = gst_vdp_mpeg_packetizer_get_next_packet (&packetizer))) { - GstBitReader b_reader = GST_BIT_READER_INIT_FROM_BUFFER (buf); - guint32 sync_code; - guint8 start_code; - - /* skip sync_code */ - gst_bit_reader_get_bits_uint32 (&b_reader, &sync_code, 8 * 3); - - /* start_code */ - gst_bit_reader_get_bits_uint8 (&b_reader, &start_code, 8); - - if (start_code >= MPEG_PACKET_SLICE_MIN - && start_code <= MPEG_PACKET_SLICE_MAX) { - GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_SLICE"); - - gst_buffer_ref (buf); - gst_adapter_push (mpeg_dec->adapter, buf); - mpeg_dec->vdp_info.slice_count++; - } - - switch (start_code) { - case MPEG_PACKET_PICTURE: - GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_PICTURE"); - - if (!gst_vdp_mpeg_dec_parse_picture (mpeg_dec, buf)) { - return GST_FLOW_OK; - } - break; - case MPEG_PACKET_SEQUENCE: - GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_SEQUENCE"); - gst_vdp_mpeg_dec_parse_sequence (mpeg_dec, buf); - break; - case MPEG_PACKET_EXTENSION: - { - guint8 ext_code; - - GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_EXTENSION"); - - /* ext_code */ - gst_bit_reader_get_bits_uint8 (&b_reader, &ext_code, 4); - switch (ext_code) { - case MPEG_PACKET_EXT_PICTURE_CODING: - GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_EXT_PICTURE_CODING"); - gst_vdp_mpeg_dec_parse_picture_coding (mpeg_dec, buf); - break; - case MPEG_PACKET_EXT_QUANT_MATRIX: - GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_EXT_QUANT_MATRIX"); - gst_vdp_mpeg_dec_parse_quant_matrix (mpeg_dec, buf); - break; - default: - break; - } - break; - } - case MPEG_PACKET_GOP: - GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_GOP"); - gst_vdp_mpeg_dec_parse_gop (mpeg_dec, buf); - break; - default: - break; - } - - gst_buffer_unref (buf); - } - - if (mpeg_dec->vdp_info.slice_count > 0) - ret = gst_vdp_mpeg_dec_decode (mpeg_dec, GST_BUFFER_TIMESTAMP (buffer), - GST_BUFFER_SIZE (buffer)); - - return ret; -} - -static gboolean -gst_vdp_mpeg_dec_convert (GstVdpMpegDec * mpeg_dec, - GstFormat src_format, gint64 src_value, - GstFormat dest_format, gint64 * dest_value) -{ - - if (src_format == dest_format) { - *dest_value = src_value; - return TRUE; - } - - if (mpeg_dec->byterate == -1) - return FALSE; - - if (src_format == GST_FORMAT_BYTES && dest_format == GST_FORMAT_TIME) { - *dest_value = gst_util_uint64_scale (GST_SECOND, src_value, - mpeg_dec->byterate); - return TRUE; - } - - if (src_format == GST_FORMAT_TIME && dest_format == GST_FORMAT_BYTES) { - *dest_value = - gst_util_uint64_scale_int (src_value, mpeg_dec->byterate, GST_SECOND); - return TRUE; - } - - return FALSE; -} - -static const GstQueryType * -gst_mpeg_dec_get_querytypes (GstPad * pad) -{ - static const GstQueryType list[] = { - GST_QUERY_POSITION, - GST_QUERY_DURATION, - 0 - }; - - return list; -} - -static gboolean -gst_vdp_mpeg_dec_src_query (GstPad * pad, GstQuery * query) -{ - GstVdpMpegDec *mpeg_dec = GST_VDP_MPEG_DEC (GST_OBJECT_PARENT (pad)); - gboolean res = FALSE; - - switch (GST_QUERY_TYPE (query)) { - case GST_QUERY_POSITION: - { - GstFormat format; - - if (gst_pad_query_default (pad, query)) - return TRUE; - - gst_query_parse_position (query, &format, NULL); - if (format == GST_FORMAT_TIME && - GST_CLOCK_TIME_IS_VALID (mpeg_dec->next_timestamp)) { - gst_query_set_position (query, GST_FORMAT_TIME, - mpeg_dec->next_timestamp); - res = TRUE; - } - break; - } - - case GST_QUERY_DURATION: - { - GstFormat format; - - if (gst_pad_query_default (pad, query)) - return TRUE; - - gst_query_parse_duration (query, &format, NULL); - if (format == GST_FORMAT_TIME) { - gint64 bytes; - - format = GST_FORMAT_BYTES; - if (gst_pad_query_duration (pad, &format, &bytes) - && format == GST_FORMAT_BYTES) { - gint64 duration; - - if (gst_vdp_mpeg_dec_convert (mpeg_dec, GST_FORMAT_BYTES, - bytes, GST_FORMAT_TIME, &duration)) { - GST_DEBUG ("duration: %" GST_TIME_FORMAT, GST_TIME_ARGS (duration)); - gst_query_set_duration (query, GST_FORMAT_TIME, duration); - res = TRUE; - } - } - } - break; - } - - default: - res = gst_pad_query_default (pad, query); - } - - return res; -} - -static gboolean -normal_seek (GstPad * pad, GstEvent * event) -{ - GstVdpMpegDec *mpeg_dec = GST_VDP_MPEG_DEC (GST_OBJECT_PARENT (pad)); - gdouble rate; - GstFormat format, conv; - GstSeekFlags flags; - GstSeekType cur_type, stop_type; - gint64 cur, stop; - gint64 time_cur, bytes_cur; - gint64 time_stop, bytes_stop; - gboolean res; - GstEvent *peer_event; - - GST_DEBUG ("normal seek"); - - gst_event_parse_seek (event, &rate, &format, &flags, - &cur_type, &cur, &stop_type, &stop); - - conv = GST_FORMAT_TIME; - if (!gst_vdp_mpeg_dec_convert (mpeg_dec, format, cur, conv, &time_cur)) - goto convert_failed; - if (!gst_vdp_mpeg_dec_convert (mpeg_dec, format, stop, conv, &time_stop)) - goto convert_failed; - - GST_DEBUG ("seek to time %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT, - GST_TIME_ARGS (time_cur), GST_TIME_ARGS (time_stop)); - - peer_event = gst_event_new_seek (rate, GST_FORMAT_TIME, flags, - cur_type, time_cur, stop_type, time_stop); - - /* try seek on time then */ - if ((res = gst_pad_push_event (mpeg_dec->sink, peer_event))) - goto done; - - /* else we try to seek on bytes */ - conv = GST_FORMAT_BYTES; - if (!gst_vdp_mpeg_dec_convert (mpeg_dec, GST_FORMAT_TIME, time_cur, - conv, &bytes_cur)) - goto convert_failed; - if (!gst_vdp_mpeg_dec_convert (mpeg_dec, GST_FORMAT_TIME, time_stop, - conv, &bytes_stop)) - goto convert_failed; - - /* conversion succeeded, create the seek */ - peer_event = - gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, - cur_type, bytes_cur, stop_type, bytes_stop); - - /* do the seek */ - res = gst_pad_push_event (mpeg_dec->sink, peer_event); - - mpeg_dec->seeking = TRUE; - -done: - return res; - - /* ERRORS */ -convert_failed: - { - /* probably unsupported seek format */ - GST_DEBUG_OBJECT (mpeg_dec, - "failed to convert format %u into GST_FORMAT_TIME", format); - return FALSE; - } -} - -static gboolean -gst_vdp_mpeg_dec_src_event (GstPad * pad, GstEvent * event) -{ - gboolean res; - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_SEEK: - { - if (gst_pad_event_default (pad, event)) - return TRUE; - - res = normal_seek (pad, event); - break; - } - default: - res = gst_pad_event_default (pad, event); - } - - return res; -} - -static gboolean -gst_vdp_mpeg_dec_sink_event (GstPad * pad, GstEvent * event) -{ - GstVdpMpegDec *mpeg_dec = GST_VDP_MPEG_DEC (GST_OBJECT_PARENT (pad)); - gboolean res; - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_FLUSH_STOP: - { - GST_DEBUG_OBJECT (mpeg_dec, "flush stop"); - - gst_vdp_mpeg_dec_flush (mpeg_dec); - res = gst_pad_push_event (mpeg_dec->src, event); - - break; - } - case GST_EVENT_NEWSEGMENT: - { - gboolean update; - gdouble rate; - GstFormat format; - gint64 start; - gint64 stop; - gint64 position; - - gst_event_parse_new_segment (event, &update, &rate, &format, - &start, &stop, &position); - - if (format != GST_FORMAT_TIME) { - if (!gst_vdp_mpeg_dec_convert (mpeg_dec, format, start, - GST_FORMAT_TIME, &start)) - goto convert_error; - if (!gst_vdp_mpeg_dec_convert (mpeg_dec, format, stop, - GST_FORMAT_TIME, &stop)) - goto convert_error; - if (!gst_vdp_mpeg_dec_convert (mpeg_dec, format, position, - GST_FORMAT_TIME, &position)) - goto convert_error; - - gst_segment_set_newsegment (&mpeg_dec->segment, update, rate, - GST_FORMAT_TIME, start, stop, position); - - gst_event_unref (event); - event = gst_event_new_new_segment (update, rate, GST_FORMAT_TIME, start, - stop, position); - } - - /* if we seek ourselves we don't push out a newsegment now since we - * use the calculated timestamp of the first frame for this */ - if (mpeg_dec->seeking) { - gst_event_unref (event); - return TRUE; - } - - convert_error: - res = gst_pad_push_event (mpeg_dec->src, event); - - break; - } - default: - res = gst_pad_event_default (pad, event); - } - - return res; -} - -static GstStateChangeReturn -gst_vdp_mpeg_dec_change_state (GstElement * element, GstStateChange transition) -{ - GstVdpMpegDec *mpeg_dec; - GstStateChangeReturn ret; - - mpeg_dec = GST_VDP_MPEG_DEC (element); - - switch (transition) { - case GST_STATE_CHANGE_READY_TO_PAUSED: - mpeg_dec->device = gst_vdp_get_device (mpeg_dec->display_name); - break; - default: - break; - } - - ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); - - switch (transition) { - case GST_STATE_CHANGE_PAUSED_TO_READY: - gst_vdp_mpeg_dec_reset (mpeg_dec); - break; - default: - break; - } - - return ret; -} - -/* GObject vmethod implementations */ - -static void -gst_vdp_mpeg_dec_base_init (gpointer gclass) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (gclass); - - gst_element_class_set_details_simple (element_class, - "VDPAU Mpeg Decoder", - "Decoder", - "decode mpeg stream with vdpau", - "Carl-Anton Ingmarsson "); - - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&sink_template)); - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&src_template)); -} - -/* initialize the vdpaumpegdecoder's class */ -static void -gst_vdp_mpeg_dec_class_init (GstVdpMpegDecClass * klass) -{ - GObjectClass *gobject_class; - GstElementClass *gstelement_class; - - gobject_class = (GObjectClass *) klass; - gstelement_class = (GstElementClass *) klass; - - gobject_class->finalize = gst_vdp_mpeg_dec_finalize; - gobject_class->set_property = gst_vdp_mpeg_dec_set_property; - gobject_class->get_property = gst_vdp_mpeg_dec_get_property; - - gstelement_class->change_state = - GST_DEBUG_FUNCPTR (gst_vdp_mpeg_dec_change_state); - - g_object_class_install_property (gobject_class, PROP_DISPLAY, - g_param_spec_string ("display", "Display", "X Display name", - NULL, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); -} - -static void -gst_vdp_mpeg_dec_init_info (VdpPictureInfoMPEG1Or2 * vdp_info) -{ - vdp_info->forward_reference = VDP_INVALID_HANDLE; - vdp_info->backward_reference = VDP_INVALID_HANDLE; - vdp_info->slice_count = 0; - vdp_info->picture_structure = 3; - vdp_info->picture_coding_type = 0; - vdp_info->intra_dc_precision = 0; - vdp_info->frame_pred_frame_dct = 1; - vdp_info->concealment_motion_vectors = 0; - vdp_info->intra_vlc_format = 0; - vdp_info->alternate_scan = 0; - vdp_info->q_scale_type = 0; - vdp_info->top_field_first = 1; -} - -static void -gst_vdp_mpeg_dec_init (GstVdpMpegDec * mpeg_dec, GstVdpMpegDecClass * gclass) -{ - mpeg_dec->src = gst_pad_new_from_static_template (&src_template, "src"); - gst_pad_set_event_function (mpeg_dec->src, - GST_DEBUG_FUNCPTR (gst_vdp_mpeg_dec_src_event)); - gst_pad_set_query_function (mpeg_dec->src, - GST_DEBUG_FUNCPTR (gst_vdp_mpeg_dec_src_query)); - gst_pad_set_query_type_function (mpeg_dec->src, - GST_DEBUG_FUNCPTR (gst_mpeg_dec_get_querytypes)); - gst_element_add_pad (GST_ELEMENT (mpeg_dec), mpeg_dec->src); - - mpeg_dec->sink = gst_pad_new_from_static_template (&sink_template, "sink"); - gst_pad_set_setcaps_function (mpeg_dec->sink, - GST_DEBUG_FUNCPTR (gst_vdp_mpeg_dec_set_caps)); - gst_pad_set_chain_function (mpeg_dec->sink, - GST_DEBUG_FUNCPTR (gst_vdp_mpeg_dec_chain)); - gst_pad_set_event_function (mpeg_dec->sink, - GST_DEBUG_FUNCPTR (gst_vdp_mpeg_dec_sink_event)); - gst_element_add_pad (GST_ELEMENT (mpeg_dec), mpeg_dec->sink); - - mpeg_dec->display_name = NULL; - mpeg_dec->adapter = gst_adapter_new (); - - mpeg_dec->device = NULL; - mpeg_dec->decoder = VDP_INVALID_HANDLE; - mpeg_dec->vdp_info.forward_reference = VDP_INVALID_HANDLE; - mpeg_dec->vdp_info.backward_reference = VDP_INVALID_HANDLE; - - gst_vdp_mpeg_dec_reset (mpeg_dec); -} - -static void -gst_vdp_mpeg_dec_finalize (GObject * object) -{ - GstVdpMpegDec *mpeg_dec = (GstVdpMpegDec *) object; - - g_object_unref (mpeg_dec->adapter); -} - -static void -gst_vdp_mpeg_dec_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstVdpMpegDec *mpeg_dec = GST_VDP_MPEG_DEC (object); - - switch (prop_id) { - case PROP_DISPLAY: - g_free (mpeg_dec->display_name); - mpeg_dec->display_name = g_value_dup_string (value); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_vdp_mpeg_dec_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - GstVdpMpegDec *mpeg_dec = GST_VDP_MPEG_DEC (object); - - switch (prop_id) { - case PROP_DISPLAY: - g_value_set_string (value, mpeg_dec->display_name); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} diff --git a/sys/vdpau/gstvdpmpegdecoder.h b/sys/vdpau/gstvdpmpegdecoder.h deleted file mode 100644 index b60c9f59..00000000 --- a/sys/vdpau/gstvdpmpegdecoder.h +++ /dev/null @@ -1,93 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2009 Carl-Anton Ingmarsson - * - * 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_VDP_MPEG_DEC_H__ -#define __GST_VDP_MPEG_DEC_H__ - -#include -#include - -#include "gstvdpdevice.h" -#include "gstvdpvideobuffer.h" - -G_BEGIN_DECLS - -#define GST_TYPE_VDP_MPEG_DEC (gst_vdp_mpeg_dec_get_type()) -#define GST_VDP_MPEG_DEC(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VDP_MPEG_DEC,GstVdpMpegDec)) -#define GST_VDP_MPEG_DEC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VDP_MPEG_DEC,GstVdpMpegDecClass)) -#define GST_IS_VDPAU_MPEG_DEC(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VDP_MPEG_DEC)) -#define GST_IS_VDPAU_MPEG_DEC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VDP_MPEG_DEC)) - -typedef struct _GstVdpMpegDec GstVdpMpegDec; -typedef struct _GstVdpMpegDecClass GstVdpMpegDecClass; - -struct _GstVdpMpegDec -{ - GstElement element; - - /* pads */ - GstPad *src; - GstPad *sink; - - gchar *display_name; - GstVdpDevice *device; - VdpDecoder decoder; - - /* stream info */ - gint width, height; - gint fps_n, fps_d; - gboolean interlaced; - gint version; - - /* currently decoded frame info */ - GstAdapter *adapter; - VdpPictureInfoMPEG1Or2 vdp_info; - guint64 frame_nr; - GstClockTime duration; - - /* frame_nr from GOP */ - guint64 gop_frame; - - /* forward and backward reference */ - GstBuffer *f_buffer; - GstBuffer *b_buffer; - - /* calculated timestamp, size and duration */ - GstClockTime next_timestamp; - guint64 accumulated_size; - guint64 accumulated_duration; - - /* seek data */ - GstSegment segment; - gboolean seeking; - gint64 byterate; - -}; - -struct _GstVdpMpegDecClass -{ - GstElementClass element_class; -}; - -GType gst_vdp_mpeg_dec_get_type (void); - -G_END_DECLS - -#endif /* __GST_VDP_MPEG_DEC_H__ */ -- cgit v1.2.1 From e9f028957d6036c5fc51f6111340e917554d3eff Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Fri, 5 Jun 2009 22:28:02 +0200 Subject: vdpaumpegdec: set GST_BUFFER_FLAG_DELTA_UNIT on non I_FRAME's --- sys/vdpau/gstvdpmpegdec.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sys/vdpau/gstvdpmpegdec.c b/sys/vdpau/gstvdpmpegdec.c index b011833e..7eb05afa 100644 --- a/sys/vdpau/gstvdpmpegdec.c +++ b/sys/vdpau/gstvdpmpegdec.c @@ -369,8 +369,16 @@ gst_vdp_mpeg_dec_decode (GstVdpMpegDec * mpeg_dec, GST_BUFFER_OFFSET (outbuf) = mpeg_dec->frame_nr; GST_BUFFER_SIZE (outbuf) = size; + if (info->picture_coding_type == I_FRAME) + GST_BUFFER_FLAG_UNSET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT); + else + GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DELTA_UNIT); + if (info->top_field_first) GST_BUFFER_FLAG_SET (outbuf, GST_VIDEO_BUFFER_TFF); + else + GST_BUFFER_FLAG_UNSET (outbuf, GST_VIDEO_BUFFER_TFF); + if (info->forward_reference != VDP_INVALID_HANDLE && info->picture_coding_type != I_FRAME) -- cgit v1.2.1 From d65d4c40f5bc3d883ac934284b07f564eadebd71 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Fri, 5 Jun 2009 23:11:18 +0200 Subject: vdpaumpegdec: small cleanups --- sys/vdpau/gstvdpmpegdec.c | 39 ++++++++++++++++++++------------------- sys/vdpau/mpegutil.c | 22 ++++++++++++---------- 2 files changed, 32 insertions(+), 29 deletions(-) diff --git a/sys/vdpau/gstvdpmpegdec.c b/sys/vdpau/gstvdpmpegdec.c index 7eb05afa..e85b1ec3 100644 --- a/sys/vdpau/gstvdpmpegdec.c +++ b/sys/vdpau/gstvdpmpegdec.c @@ -344,24 +344,6 @@ gst_vdp_mpeg_dec_decode (GstVdpMpegDec * mpeg_dec, buffer = gst_adapter_take_buffer (mpeg_dec->adapter, gst_adapter_available (mpeg_dec->adapter)); - if (info->picture_coding_type != B_FRAME) { - if (info->backward_reference != VDP_INVALID_HANDLE) { - gst_buffer_ref (mpeg_dec->b_buffer); - gst_vdp_mpeg_dec_push_video_buffer (mpeg_dec, - GST_VDP_VIDEO_BUFFER (mpeg_dec->b_buffer)); - } - - if (info->forward_reference != VDP_INVALID_HANDLE) { - gst_buffer_unref (mpeg_dec->f_buffer); - info->forward_reference = VDP_INVALID_HANDLE; - } - - info->forward_reference = info->backward_reference; - mpeg_dec->f_buffer = mpeg_dec->b_buffer; - - info->backward_reference = VDP_INVALID_HANDLE; - } - outbuf = gst_vdp_video_buffer_new (mpeg_dec->device, VDP_CHROMA_TYPE_420, mpeg_dec->width, mpeg_dec->height); GST_BUFFER_TIMESTAMP (outbuf) = timestamp; @@ -380,12 +362,31 @@ gst_vdp_mpeg_dec_decode (GstVdpMpegDec * mpeg_dec, GST_BUFFER_FLAG_UNSET (outbuf, GST_VIDEO_BUFFER_TFF); + if (info->picture_coding_type != B_FRAME) { + if (info->backward_reference != VDP_INVALID_HANDLE) { + gst_buffer_ref (mpeg_dec->b_buffer); + gst_vdp_mpeg_dec_push_video_buffer (mpeg_dec, + GST_VDP_VIDEO_BUFFER (mpeg_dec->b_buffer)); + } + + if (info->forward_reference != VDP_INVALID_HANDLE) { + gst_buffer_unref (mpeg_dec->f_buffer); + info->forward_reference = VDP_INVALID_HANDLE; + } + + info->forward_reference = info->backward_reference; + mpeg_dec->f_buffer = mpeg_dec->b_buffer; + + info->backward_reference = VDP_INVALID_HANDLE; + } + if (info->forward_reference != VDP_INVALID_HANDLE && info->picture_coding_type != I_FRAME) gst_vdp_video_buffer_add_reference (outbuf, GST_VDP_VIDEO_BUFFER (mpeg_dec->f_buffer)); - if (info->backward_reference != VDP_INVALID_HANDLE) + if (info->backward_reference != VDP_INVALID_HANDLE + && info->picture_coding_type == B_FRAME) gst_vdp_video_buffer_add_reference (outbuf, GST_VDP_VIDEO_BUFFER (mpeg_dec->b_buffer)); diff --git a/sys/vdpau/mpegutil.c b/sys/vdpau/mpegutil.c index 5348bd6a..b52ab6f8 100644 --- a/sys/vdpau/mpegutil.c +++ b/sys/vdpau/mpegutil.c @@ -256,20 +256,22 @@ mpeg_util_parse_picture_hdr (MPEGPictureHdr * hdr, GstBuffer * buffer) if (!gst_bit_reader_get_bits_uint8 (&reader, &hdr->f_code[0][0], 3)) return FALSE; hdr->f_code[0][1] = hdr->f_code[0][0]; + } else { + hdr->full_pel_forward_vector = 0; + hdr->f_code[0][0] = hdr->f_code[0][1] = 0; + } - if (hdr->pic_type == B_FRAME) { - if (!gst_bit_reader_get_bits_uint8 (&reader, - &hdr->full_pel_backward_vector, 1)) - return FALSE; + if (hdr->pic_type == B_FRAME) { + if (!gst_bit_reader_get_bits_uint8 (&reader, + &hdr->full_pel_backward_vector, 1)) + return FALSE; - if (!gst_bit_reader_get_bits_uint8 (&reader, &hdr->f_code[1][0], 3)) - return FALSE; - hdr->f_code[1][1] = hdr->f_code[1][0]; - } else - hdr->full_pel_backward_vector = 0; + if (!gst_bit_reader_get_bits_uint8 (&reader, &hdr->f_code[1][0], 3)) + return FALSE; + hdr->f_code[1][1] = hdr->f_code[1][0]; } else { - hdr->full_pel_forward_vector = 0; hdr->full_pel_backward_vector = 0; + hdr->f_code[1][0] = hdr->f_code[1][1] = 0; } return TRUE; -- cgit v1.2.1 From 702cc4a03f26267b562eade5fb2b4f1889015b95 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Sat, 6 Jun 2009 21:27:52 +0200 Subject: vdpaumpegdec: further work on seeking --- sys/vdpau/gstvdpmpegdec.c | 61 +++++++++++++++++++++-------------------------- 1 file changed, 27 insertions(+), 34 deletions(-) diff --git a/sys/vdpau/gstvdpmpegdec.c b/sys/vdpau/gstvdpmpegdec.c index e85b1ec3..c5d6fde5 100644 --- a/sys/vdpau/gstvdpmpegdec.c +++ b/sys/vdpau/gstvdpmpegdec.c @@ -308,6 +308,9 @@ gst_vdp_mpeg_dec_push_video_buffer (GstVdpMpegDec * mpeg_dec, mpeg_dec->next_timestamp = GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer); + gst_segment_set_last_stop (&mpeg_dec->segment, GST_FORMAT_TIME, + GST_BUFFER_TIMESTAMP (buffer)); + mpeg_dec->accumulated_duration += GST_BUFFER_DURATION (buffer); mpeg_dec->accumulated_size += GST_BUFFER_SIZE (buffer); byterate = gst_util_uint64_scale (mpeg_dec->accumulated_size, GST_SECOND, @@ -795,53 +798,46 @@ normal_seek (GstPad * pad, GstEvent * event) GstFormat format, conv; GstSeekFlags flags; GstSeekType cur_type, stop_type; - gint64 cur, stop; gint64 time_cur, bytes_cur; gint64 time_stop, bytes_stop; gboolean res; + gboolean update; GstEvent *peer_event; GST_DEBUG ("normal seek"); gst_event_parse_seek (event, &rate, &format, &flags, - &cur_type, &cur, &stop_type, &stop); - - conv = GST_FORMAT_TIME; - if (!gst_vdp_mpeg_dec_convert (mpeg_dec, format, cur, conv, &time_cur)) - goto convert_failed; - if (!gst_vdp_mpeg_dec_convert (mpeg_dec, format, stop, conv, &time_stop)) - goto convert_failed; + &cur_type, &time_cur, &stop_type, &time_stop); - GST_DEBUG ("seek to time %" GST_TIME_FORMAT "-%" GST_TIME_FORMAT, - GST_TIME_ARGS (time_cur), GST_TIME_ARGS (time_stop)); + if (format != GST_FORMAT_TIME) + return FALSE; - peer_event = gst_event_new_seek (rate, GST_FORMAT_TIME, flags, - cur_type, time_cur, stop_type, time_stop); + gst_segment_set_seek (&mpeg_dec->segment, rate, GST_FORMAT_TIME, flags, + cur_type, time_cur, stop_type, time_stop, &update); - /* try seek on time then */ - if ((res = gst_pad_push_event (mpeg_dec->sink, peer_event))) - goto done; + if (update) { - /* else we try to seek on bytes */ - conv = GST_FORMAT_BYTES; - if (!gst_vdp_mpeg_dec_convert (mpeg_dec, GST_FORMAT_TIME, time_cur, - conv, &bytes_cur)) - goto convert_failed; - if (!gst_vdp_mpeg_dec_convert (mpeg_dec, GST_FORMAT_TIME, time_stop, - conv, &bytes_stop)) - goto convert_failed; + /* seek on bytes */ + conv = GST_FORMAT_BYTES; + if (!gst_vdp_mpeg_dec_convert (mpeg_dec, GST_FORMAT_TIME, time_cur, + conv, &bytes_cur)) + goto convert_failed; + if (!gst_vdp_mpeg_dec_convert (mpeg_dec, GST_FORMAT_TIME, time_stop, + conv, &bytes_stop)) + goto convert_failed; - /* conversion succeeded, create the seek */ - peer_event = - gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, - cur_type, bytes_cur, stop_type, bytes_stop); + /* conversion succeeded, create the seek */ + peer_event = + gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, + cur_type, bytes_cur, stop_type, bytes_stop); - /* do the seek */ - res = gst_pad_push_event (mpeg_dec->sink, peer_event); + mpeg_dec->seeking = TRUE; - mpeg_dec->seeking = TRUE; + /* do the seek */ + res = gst_pad_push_event (mpeg_dec->sink, peer_event); + } else + res = FALSE; -done: return res; /* ERRORS */ @@ -914,9 +910,6 @@ gst_vdp_mpeg_dec_sink_event (GstPad * pad, GstEvent * event) GST_FORMAT_TIME, &position)) goto convert_error; - gst_segment_set_newsegment (&mpeg_dec->segment, update, rate, - GST_FORMAT_TIME, start, stop, position); - gst_event_unref (event); event = gst_event_new_new_segment (update, rate, GST_FORMAT_TIME, start, stop, position); -- cgit v1.2.1 From 3fa60712f2f86591d7ab7b0c454e1676ad72b751 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Sun, 7 Jun 2009 00:55:55 +0200 Subject: vdpaumpegdec: use gst_pad_get_parent for threadsafety --- sys/vdpau/gstvdpmpegdec.c | 64 ++++++++++++++++++++++++++++++----------------- 1 file changed, 41 insertions(+), 23 deletions(-) diff --git a/sys/vdpau/gstvdpmpegdec.c b/sys/vdpau/gstvdpmpegdec.c index c5d6fde5..bcff055f 100644 --- a/sys/vdpau/gstvdpmpegdec.c +++ b/sys/vdpau/gstvdpmpegdec.c @@ -161,7 +161,7 @@ gst_vdp_mpeg_packetizer_init (GstVdpMpegPacketizer * packetizer, static gboolean gst_vdp_mpeg_dec_set_caps (GstPad * pad, GstCaps * caps) { - GstVdpMpegDec *mpeg_dec = GST_VDP_MPEG_DEC (GST_OBJECT_PARENT (pad)); + GstVdpMpegDec *mpeg_dec = GST_VDP_MPEG_DEC (gst_pad_get_parent (pad)); GstStructure *structure; gint width, height; @@ -198,7 +198,7 @@ gst_vdp_mpeg_dec_set_caps (GstPad * pad, GstCaps * caps) res = gst_pad_set_caps (mpeg_dec->src, src_caps); gst_caps_unref (src_caps); if (!res) - return FALSE; + goto done; mpeg_dec->width = width; mpeg_dec->height = height; @@ -274,9 +274,15 @@ gst_vdp_mpeg_dec_set_caps (GstPad * pad, GstCaps * caps) ("Could not create vdpau decoder"), ("Error returned from vdpau was: %s", device->vdp_get_error_string (status))); - return FALSE; + res = FALSE; + goto done; } - return TRUE; + res = TRUE; + +done: + gst_object_unref (mpeg_dec); + + return res; } GstFlowReturn @@ -605,13 +611,11 @@ gst_vdp_mpeg_dec_reset (GstVdpMpegDec * mpeg_dec) static GstFlowReturn gst_vdp_mpeg_dec_chain (GstPad * pad, GstBuffer * buffer) { - GstVdpMpegDec *mpeg_dec; + GstVdpMpegDec *mpeg_dec = GST_VDP_MPEG_DEC (gst_pad_get_parent (pad)); GstVdpMpegPacketizer packetizer; GstBuffer *buf; GstFlowReturn ret = GST_FLOW_OK; - mpeg_dec = GST_VDP_MPEG_DEC (GST_OBJECT_PARENT (pad)); - if (G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT))) { GST_DEBUG_OBJECT (mpeg_dec, "Received discont buffer"); gst_vdp_mpeg_dec_flush (mpeg_dec); @@ -643,9 +647,9 @@ gst_vdp_mpeg_dec_chain (GstPad * pad, GstBuffer * buffer) case MPEG_PACKET_PICTURE: GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_PICTURE"); - if (!gst_vdp_mpeg_dec_parse_picture (mpeg_dec, buf)) { - return GST_FLOW_OK; - } + if (!gst_vdp_mpeg_dec_parse_picture (mpeg_dec, buf)) + goto done; + break; case MPEG_PACKET_SEQUENCE: GST_DEBUG_OBJECT (mpeg_dec, "MPEG_PACKET_SEQUENCE"); @@ -688,6 +692,9 @@ gst_vdp_mpeg_dec_chain (GstPad * pad, GstBuffer * buffer) ret = gst_vdp_mpeg_dec_decode (mpeg_dec, GST_BUFFER_TIMESTAMP (buffer), GST_BUFFER_SIZE (buffer)); +done: + gst_object_unref (mpeg_dec); + return ret; } @@ -735,16 +742,16 @@ gst_mpeg_dec_get_querytypes (GstPad * pad) static gboolean gst_vdp_mpeg_dec_src_query (GstPad * pad, GstQuery * query) { - GstVdpMpegDec *mpeg_dec = GST_VDP_MPEG_DEC (GST_OBJECT_PARENT (pad)); - gboolean res = FALSE; + GstVdpMpegDec *mpeg_dec = GST_VDP_MPEG_DEC (gst_pad_get_parent (pad)); + gboolean res; switch (GST_QUERY_TYPE (query)) { case GST_QUERY_POSITION: { GstFormat format; - if (gst_pad_query_default (pad, query)) - return TRUE; + if ((res = gst_pad_query_default (pad, query))) + goto done; gst_query_parse_position (query, &format, NULL); if (format == GST_FORMAT_TIME && @@ -760,8 +767,8 @@ gst_vdp_mpeg_dec_src_query (GstPad * pad, GstQuery * query) { GstFormat format; - if (gst_pad_query_default (pad, query)) - return TRUE; + if ((res = gst_pad_query_default (pad, query))) + goto done; gst_query_parse_duration (query, &format, NULL); if (format == GST_FORMAT_TIME) { @@ -787,13 +794,15 @@ gst_vdp_mpeg_dec_src_query (GstPad * pad, GstQuery * query) res = gst_pad_query_default (pad, query); } +done: + gst_object_unref (mpeg_dec); + return res; } static gboolean -normal_seek (GstPad * pad, GstEvent * event) +normal_seek (GstVdpMpegDec * mpeg_dec, GstEvent * event) { - GstVdpMpegDec *mpeg_dec = GST_VDP_MPEG_DEC (GST_OBJECT_PARENT (pad)); gdouble rate; GstFormat format, conv; GstSeekFlags flags; @@ -853,28 +862,33 @@ convert_failed: static gboolean gst_vdp_mpeg_dec_src_event (GstPad * pad, GstEvent * event) { + GstVdpMpegDec *mpeg_dec = GST_VDP_MPEG_DEC (gst_pad_get_parent (pad)); gboolean res; switch (GST_EVENT_TYPE (event)) { case GST_EVENT_SEEK: { - if (gst_pad_event_default (pad, event)) - return TRUE; + if ((res = gst_pad_event_default (pad, event))) + goto done; + + res = normal_seek (mpeg_dec, event); - res = normal_seek (pad, event); break; } default: res = gst_pad_event_default (pad, event); } +done: + gst_object_unref (mpeg_dec); + return res; } static gboolean gst_vdp_mpeg_dec_sink_event (GstPad * pad, GstEvent * event) { - GstVdpMpegDec *mpeg_dec = GST_VDP_MPEG_DEC (GST_OBJECT_PARENT (pad)); + GstVdpMpegDec *mpeg_dec = GST_VDP_MPEG_DEC (gst_pad_get_parent (pad)); gboolean res; switch (GST_EVENT_TYPE (event)) { @@ -919,7 +933,8 @@ gst_vdp_mpeg_dec_sink_event (GstPad * pad, GstEvent * event) * use the calculated timestamp of the first frame for this */ if (mpeg_dec->seeking) { gst_event_unref (event); - return TRUE; + res = TRUE; + goto done; } convert_error: @@ -931,6 +946,9 @@ gst_vdp_mpeg_dec_sink_event (GstPad * pad, GstEvent * event) res = gst_pad_event_default (pad, event); } +done: + gst_object_unref (mpeg_dec); + return res; } -- cgit v1.2.1 From 636ae49bee677ee56f6c480c78f6f4eda8eeab51 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Sun, 7 Jun 2009 01:12:50 +0200 Subject: vdpaumpegdec: use mutex to protect mpeg_dec->seeking from concurrent access --- sys/vdpau/gstvdpmpegdec.c | 14 +++++++++++++- sys/vdpau/gstvdpmpegdec.h | 3 +++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/sys/vdpau/gstvdpmpegdec.c b/sys/vdpau/gstvdpmpegdec.c index bcff055f..759eb7f9 100644 --- a/sys/vdpau/gstvdpmpegdec.c +++ b/sys/vdpau/gstvdpmpegdec.c @@ -840,10 +840,16 @@ normal_seek (GstVdpMpegDec * mpeg_dec, GstEvent * event) gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, cur_type, bytes_cur, stop_type, bytes_stop); - mpeg_dec->seeking = TRUE; + g_mutex_lock (mpeg_dec->mutex); /* do the seek */ res = gst_pad_push_event (mpeg_dec->sink, peer_event); + + if (res) + mpeg_dec->seeking = TRUE; + + g_mutex_unlock (mpeg_dec->mutex); + } else res = FALSE; @@ -929,13 +935,16 @@ gst_vdp_mpeg_dec_sink_event (GstPad * pad, GstEvent * event) stop, position); } + g_mutex_lock (mpeg_dec->mutex); /* if we seek ourselves we don't push out a newsegment now since we * use the calculated timestamp of the first frame for this */ if (mpeg_dec->seeking) { gst_event_unref (event); res = TRUE; + g_mutex_unlock (mpeg_dec->mutex); goto done; } + g_mutex_unlock (mpeg_dec->mutex); convert_error: res = gst_pad_push_event (mpeg_dec->src, event); @@ -1069,6 +1078,8 @@ gst_vdp_mpeg_dec_init (GstVdpMpegDec * mpeg_dec, GstVdpMpegDecClass * gclass) mpeg_dec->vdp_info.backward_reference = VDP_INVALID_HANDLE; gst_vdp_mpeg_dec_reset (mpeg_dec); + + mpeg_dec->mutex = g_mutex_new (); } static void @@ -1077,6 +1088,7 @@ gst_vdp_mpeg_dec_finalize (GObject * object) GstVdpMpegDec *mpeg_dec = (GstVdpMpegDec *) object; g_object_unref (mpeg_dec->adapter); + g_mutex_free (mpeg_dec->mutex); } static void diff --git a/sys/vdpau/gstvdpmpegdec.h b/sys/vdpau/gstvdpmpegdec.h index b60c9f59..66a41805 100644 --- a/sys/vdpau/gstvdpmpegdec.h +++ b/sys/vdpau/gstvdpmpegdec.h @@ -78,6 +78,9 @@ struct _GstVdpMpegDec GstSegment segment; gboolean seeking; gint64 byterate; + + /* mutex */ + GMutex *mutex; }; -- cgit v1.2.1 From 64100e473754c70cfba76f1ba1ff7eb297c954db Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Sun, 7 Jun 2009 01:25:01 +0200 Subject: vdpaumpegdec: send newsegment event if only the rate has been updated --- sys/vdpau/gstvdpmpegdec.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/sys/vdpau/gstvdpmpegdec.c b/sys/vdpau/gstvdpmpegdec.c index 759eb7f9..931de5a4 100644 --- a/sys/vdpau/gstvdpmpegdec.c +++ b/sys/vdpau/gstvdpmpegdec.c @@ -825,7 +825,6 @@ normal_seek (GstVdpMpegDec * mpeg_dec, GstEvent * event) cur_type, time_cur, stop_type, time_stop, &update); if (update) { - /* seek on bytes */ conv = GST_FORMAT_BYTES; if (!gst_vdp_mpeg_dec_convert (mpeg_dec, GST_FORMAT_TIME, time_cur, @@ -850,8 +849,17 @@ normal_seek (GstVdpMpegDec * mpeg_dec, GstEvent * event) g_mutex_unlock (mpeg_dec->mutex); - } else - res = FALSE; + } else { + GstEvent *event; + + /* send segment with new rate */ + event = gst_event_new_new_segment (TRUE, + mpeg_dec->segment.rate, GST_FORMAT_TIME, mpeg_dec->segment.start, + mpeg_dec->segment.stop, mpeg_dec->segment.time); + + gst_pad_push_event (mpeg_dec->src, event); + res = TRUE; + } return res; -- cgit v1.2.1 From cee2394a0d60857ff0015a62bb8888ec18e40755 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Sun, 7 Jun 2009 23:46:38 +0200 Subject: vdpau: s/IS_VDPAU/IS_VDP --- sys/vdpau/gstvdpdevice.c | 4 ++-- sys/vdpau/gstvdpdevice.h | 4 ++-- sys/vdpau/gstvdpmpegdec.h | 4 ++-- sys/vdpau/gstvdpvideobuffer.c | 4 ++-- sys/vdpau/gstvdpvideobuffer.h | 2 +- sys/vdpau/gstvdpvideoyuv.h | 4 ++-- sys/vdpau/gstvdpyuvvideo.h | 4 ++-- 7 files changed, 13 insertions(+), 13 deletions(-) diff --git a/sys/vdpau/gstvdpdevice.c b/sys/vdpau/gstvdpdevice.c index f920f973..4ed1b177 100644 --- a/sys/vdpau/gstvdpdevice.c +++ b/sys/vdpau/gstvdpdevice.c @@ -152,7 +152,7 @@ gst_vdp_device_set_property (GObject * object, guint prop_id, { GstVdpDevice *device; - g_return_if_fail (GST_IS_VDPAU_DEVICE (object)); + g_return_if_fail (GST_IS_VDP_DEVICE (object)); device = (GstVdpDevice *) object; @@ -172,7 +172,7 @@ gst_vdp_device_get_property (GObject * object, guint prop_id, GValue * value, { GstVdpDevice *device; - g_return_if_fail (GST_IS_VDPAU_DEVICE (object)); + g_return_if_fail (GST_IS_VDP_DEVICE (object)); device = (GstVdpDevice *) object; diff --git a/sys/vdpau/gstvdpdevice.h b/sys/vdpau/gstvdpdevice.h index 70758a2d..ac036d73 100644 --- a/sys/vdpau/gstvdpdevice.h +++ b/sys/vdpau/gstvdpdevice.h @@ -31,8 +31,8 @@ G_BEGIN_DECLS #define GST_TYPE_VDP_DEVICE (gst_vdp_device_get_type ()) #define GST_VDP_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_VDP_DEVICE, GstVdpDevice)) #define GST_VDP_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_VDP_DEVICE, GstVdpDeviceClass)) -#define GST_IS_VDPAU_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_VDP_DEVICE)) -#define GST_IS_VDPAU_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_VDP_DEVICE)) +#define GST_IS_VDP_DEVICE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_VDP_DEVICE)) +#define GST_IS_VDP_DEVICE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_VDP_DEVICE)) #define GST_VDP_DEVICE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_VDP_DEVICE, GstVdpDeviceClass)) typedef struct _GstVdpDeviceClass GstVdpDeviceClass; diff --git a/sys/vdpau/gstvdpmpegdec.h b/sys/vdpau/gstvdpmpegdec.h index 66a41805..9d4c791f 100644 --- a/sys/vdpau/gstvdpmpegdec.h +++ b/sys/vdpau/gstvdpmpegdec.h @@ -32,8 +32,8 @@ G_BEGIN_DECLS #define GST_TYPE_VDP_MPEG_DEC (gst_vdp_mpeg_dec_get_type()) #define GST_VDP_MPEG_DEC(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VDP_MPEG_DEC,GstVdpMpegDec)) #define GST_VDP_MPEG_DEC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VDP_MPEG_DEC,GstVdpMpegDecClass)) -#define GST_IS_VDPAU_MPEG_DEC(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VDP_MPEG_DEC)) -#define GST_IS_VDPAU_MPEG_DEC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VDP_MPEG_DEC)) +#define GST_IS_VDP_MPEG_DEC(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VDP_MPEG_DEC)) +#define GST_IS_VDP_MPEG_DEC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VDP_MPEG_DEC)) typedef struct _GstVdpMpegDec GstVdpMpegDec; typedef struct _GstVdpMpegDecClass GstVdpMpegDecClass; diff --git a/sys/vdpau/gstvdpvideobuffer.c b/sys/vdpau/gstvdpvideobuffer.c index dac62c1b..8ae14e98 100644 --- a/sys/vdpau/gstvdpvideobuffer.c +++ b/sys/vdpau/gstvdpvideobuffer.c @@ -29,8 +29,8 @@ void gst_vdp_video_buffer_add_reference (GstVdpVideoBuffer * buffer, GstVdpVideoBuffer * buf) { - g_assert (GST_IS_VDPAU_VIDEO_BUFFER (buffer)); - g_assert (GST_IS_VDPAU_VIDEO_BUFFER (buf)); + g_assert (GST_IS_VDP_VIDEO_BUFFER (buffer)); + g_assert (GST_IS_VDP_VIDEO_BUFFER (buf)); gst_buffer_ref (GST_BUFFER (buf)); buffer->refs = g_slist_prepend (buffer->refs, buf); diff --git a/sys/vdpau/gstvdpvideobuffer.h b/sys/vdpau/gstvdpvideobuffer.h index 77ccf8ed..36eddcbd 100644 --- a/sys/vdpau/gstvdpvideobuffer.h +++ b/sys/vdpau/gstvdpvideobuffer.h @@ -32,7 +32,7 @@ typedef struct _GstVdpVideoBuffer GstVdpVideoBuffer; #define GST_TYPE_VDP_VIDEO_BUFFER (gst_vdp_video_buffer_get_type()) -#define GST_IS_VDPAU_VIDEO_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_VDP_VIDEO_BUFFER)) +#define GST_IS_VDP_VIDEO_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_VDP_VIDEO_BUFFER)) #define GST_VDP_VIDEO_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_VDP_VIDEO_BUFFER, GstVdpVideoBuffer)) struct _GstVdpVideoBuffer { diff --git a/sys/vdpau/gstvdpvideoyuv.h b/sys/vdpau/gstvdpvideoyuv.h index 07955ed8..935fe700 100644 --- a/sys/vdpau/gstvdpvideoyuv.h +++ b/sys/vdpau/gstvdpvideoyuv.h @@ -31,8 +31,8 @@ G_BEGIN_DECLS #define GST_VDP_VIDEO_YUV(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VDP_VIDEO_YUV,GstVdpVideoYUV)) #define GST_VDP_VIDEO_YUV_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VDP_VIDEO_YUV,GstVdpVideoYUVClass)) #define GST_VDP_VIDEO_YUV_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_VDP_VIDEO_YUV, GstVdpVideoYUVClass)) -#define GST_IS_VDPAU_VIDEO_YUV(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VDP_VIDEO_YUV)) -#define GST_IS_VDPAU_VIDEO_YUV_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VDP_VIDEO_YUV)) +#define GST_IS_VDP_VIDEO_YUV(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VDP_VIDEO_YUV)) +#define GST_IS_VDP_VIDEO_YUV_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VDP_VIDEO_YUV)) typedef struct _GstVdpVideoYUV GstVdpVideoYUV; typedef struct _GstVdpVideoYUVClass GstVdpVideoYUVClass; diff --git a/sys/vdpau/gstvdpyuvvideo.h b/sys/vdpau/gstvdpyuvvideo.h index ba3a3b01..2349e1ba 100644 --- a/sys/vdpau/gstvdpyuvvideo.h +++ b/sys/vdpau/gstvdpyuvvideo.h @@ -31,8 +31,8 @@ G_BEGIN_DECLS #define GST_VDP_YUV_VIDEO(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VDP_YUV_VIDEO,GstVdpYUVVideo)) #define GST_VDP_YUV_VIDEO_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VDP_YUV_VIDEO,GstVdpYUVVideoClass)) #define GST_VDP_YUV_VIDEO_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_VDP_YUV_VIDEO, GstVdpYUVVideoClass)) -#define GST_IS_VDPAU_YUV_VIDEO(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VDP_YUV_VIDEO)) -#define GST_IS_VDPAU_YUV_VIDEO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VDP_YUV_VIDEO)) +#define GST_IS_VDP_YUV_VIDEO(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VDP_YUV_VIDEO)) +#define GST_IS_VDP_YUV_VIDEO_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VDP_YUV_VIDEO)) typedef struct _GstVdpYUVVideo GstVdpYUVVideo; typedef struct _GstVdpYUVVideoClass GstVdpYUVVideoClass; -- cgit v1.2.1 From aff91bb89acaa2528ad2ed8f696cc93eb254325a Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Mon, 8 Jun 2009 14:15:03 +0200 Subject: vdpaumpegdec: small cleanup --- sys/vdpau/gstvdpmpegdec.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/sys/vdpau/gstvdpmpegdec.c b/sys/vdpau/gstvdpmpegdec.c index 931de5a4..fbd53ae9 100644 --- a/sys/vdpau/gstvdpmpegdec.c +++ b/sys/vdpau/gstvdpmpegdec.c @@ -804,7 +804,7 @@ static gboolean normal_seek (GstVdpMpegDec * mpeg_dec, GstEvent * event) { gdouble rate; - GstFormat format, conv; + GstFormat format; GstSeekFlags flags; GstSeekType cur_type, stop_type; gint64 time_cur, bytes_cur; @@ -826,12 +826,11 @@ normal_seek (GstVdpMpegDec * mpeg_dec, GstEvent * event) if (update) { /* seek on bytes */ - conv = GST_FORMAT_BYTES; if (!gst_vdp_mpeg_dec_convert (mpeg_dec, GST_FORMAT_TIME, time_cur, - conv, &bytes_cur)) + GST_FORMAT_BYTES, &bytes_cur)) goto convert_failed; if (!gst_vdp_mpeg_dec_convert (mpeg_dec, GST_FORMAT_TIME, time_stop, - conv, &bytes_stop)) + GST_FORMAT_BYTES, &bytes_stop)) goto convert_failed; /* conversion succeeded, create the seek */ -- cgit v1.2.1 From 53a5272f73beaf87d33f99dc4a0d0dd0770934cc Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Mon, 8 Jun 2009 14:35:29 +0200 Subject: vdpaumpegdec: drop all frames before a GOP when we seek --- sys/vdpau/gstvdpmpegdec.c | 18 +++++++++++++++++- sys/vdpau/gstvdpmpegdec.h | 9 +++++++++ 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/sys/vdpau/gstvdpmpegdec.c b/sys/vdpau/gstvdpmpegdec.c index fbd53ae9..a4c2f687 100644 --- a/sys/vdpau/gstvdpmpegdec.c +++ b/sys/vdpau/gstvdpmpegdec.c @@ -499,6 +499,9 @@ gst_vdp_mpeg_dec_parse_sequence (GstVdpMpegDec * mpeg_dec, GstBuffer * buffer) memcpy (&mpeg_dec->vdp_info.non_intra_quantizer_matrix, &hdr.non_intra_quantizer_matrix, 64); + if (mpeg_dec->state == GST_VDP_MPEG_DEC_NEED_SEQUENCE) + mpeg_dec->state = GST_VDP_MPEG_DEC_NEED_DATA; + return TRUE; } @@ -555,6 +558,9 @@ gst_vdp_mpeg_dec_parse_gop (GstVdpMpegDec * mpeg_dec, GstBuffer * buffer) gst_util_uint64_scale (time, mpeg_dec->fps_n, mpeg_dec->fps_d * GST_SECOND) + gop.frame; + if (mpeg_dec->state == GST_VDP_MPEG_DEC_NEED_GOP) + mpeg_dec->state = GST_VDP_MPEG_DEC_NEED_DATA; + return TRUE; } @@ -601,6 +607,8 @@ gst_vdp_mpeg_dec_reset (GstVdpMpegDec * mpeg_dec) g_object_unref (mpeg_dec->device); mpeg_dec->device = NULL; + mpeg_dec->state = GST_VDP_MPEG_DEC_NEED_SEQUENCE; + gst_segment_init (&mpeg_dec->segment, GST_FORMAT_TIME); mpeg_dec->seeking = FALSE; @@ -688,6 +696,12 @@ gst_vdp_mpeg_dec_chain (GstPad * pad, GstBuffer * buffer) gst_buffer_unref (buf); } + if (mpeg_dec->state == GST_VDP_MPEG_DEC_NEED_SEQUENCE || + mpeg_dec->state == GST_VDP_MPEG_DEC_NEED_GOP) { + gst_adapter_clear (mpeg_dec->adapter); + goto done; + } + if (mpeg_dec->vdp_info.slice_count > 0) ret = gst_vdp_mpeg_dec_decode (mpeg_dec, GST_BUFFER_TIMESTAMP (buffer), GST_BUFFER_SIZE (buffer)); @@ -843,8 +857,10 @@ normal_seek (GstVdpMpegDec * mpeg_dec, GstEvent * event) /* do the seek */ res = gst_pad_push_event (mpeg_dec->sink, peer_event); - if (res) + if (res) { + mpeg_dec->state = GST_VDP_MPEG_DEC_NEED_GOP; mpeg_dec->seeking = TRUE; + } g_mutex_unlock (mpeg_dec->mutex); diff --git a/sys/vdpau/gstvdpmpegdec.h b/sys/vdpau/gstvdpmpegdec.h index 9d4c791f..fc36df5b 100644 --- a/sys/vdpau/gstvdpmpegdec.h +++ b/sys/vdpau/gstvdpmpegdec.h @@ -35,6 +35,12 @@ G_BEGIN_DECLS #define GST_IS_VDP_MPEG_DEC(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VDP_MPEG_DEC)) #define GST_IS_VDP_MPEG_DEC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VDP_MPEG_DEC)) +typedef enum { + GST_VDP_MPEG_DEC_NEED_SEQUENCE, + GST_VDP_MPEG_DEC_NEED_GOP, + GST_VDP_MPEG_DEC_NEED_DATA +} GstVdpMpegDecState; + typedef struct _GstVdpMpegDec GstVdpMpegDec; typedef struct _GstVdpMpegDecClass GstVdpMpegDecClass; @@ -56,6 +62,9 @@ struct _GstVdpMpegDec gboolean interlaced; gint version; + /* decoder state */ + GstVdpMpegDecState state; + /* currently decoded frame info */ GstAdapter *adapter; VdpPictureInfoMPEG1Or2 vdp_info; -- cgit v1.2.1 From b4fa8a4ef01a78638f5bc16a14802acfa1c11106 Mon Sep 17 00:00:00 2001 From: Carl-Anton Ingmarsson Date: Tue, 9 Jun 2009 23:14:26 +0200 Subject: vdpaumpegdec: use fixed src caps --- sys/vdpau/gstvdpmpegdec.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sys/vdpau/gstvdpmpegdec.c b/sys/vdpau/gstvdpmpegdec.c index a4c2f687..b720217d 100644 --- a/sys/vdpau/gstvdpmpegdec.c +++ b/sys/vdpau/gstvdpmpegdec.c @@ -1075,6 +1075,7 @@ static void gst_vdp_mpeg_dec_init (GstVdpMpegDec * mpeg_dec, GstVdpMpegDecClass * gclass) { mpeg_dec->src = gst_pad_new_from_static_template (&src_template, "src"); + gst_pad_use_fixed_caps (mpeg_dec->src); gst_pad_set_event_function (mpeg_dec->src, GST_DEBUG_FUNCPTR (gst_vdp_mpeg_dec_src_event)); gst_pad_set_query_function (mpeg_dec->src, -- cgit v1.2.1 From f45f87709c7da9105024b0ceedda0e3155526240 Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Fri, 12 Jun 2009 16:39:39 +0100 Subject: VDPAU: Enhance the configure tests Check for the VDPAU headers in /usr/include/nvidia as they are on some platforms (Fedora/rpmfusion). Also check that the libvdpau library is available. --- configure.ac | 36 +++++++++++++++++++++++++++++++++--- sys/vdpau/Makefile.am | 5 +++-- 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/configure.ac b/configure.ac index dde1cb81..900d8342 100644 --- a/configure.ac +++ b/configure.ac @@ -1425,9 +1425,39 @@ AG_GST_CHECK_FEATURE(ACM, [Windows ACM library], acm, [ dnl *** vdpau *** translit(dnm, m, l) AM_CONDITIONAL(USE_VDPAU, true) AG_GST_CHECK_FEATURE(VDPAU, [VDPAU], vdpau, [ - AC_MSG_CHECKING([Checking for up to date vdpau installation]) - AC_CHECK_HEADERS([vdpau/vdpau.h vdpau/vdpau_x11.h], - [HAVE_VDPAU="yes"], [HAVE_VDPAU="no"]) + VDPAU_CFLAGS= + VDPAU_LIBS=-lvdpau + HAVE_VDPAU=no + + saved_CPPFLAGS="$CPPFLAGS" + AC_CHECK_HEADER([vdpau/vdpau.h], [HAVE_VDPAU_H=yes]) + if test -z "$HAVE_VDPAU_H"; then + dnl Didn't find VDPAU header straight away. + dnl Try /usr/include/nvidia. Need to clear caching vars first + AC_MSG_NOTICE([VDPAU header not in standard path. Checking /usr/include/nvidia]) + unset ac_cv_header_vdpau_vdpau_h + unset ac_cv_header_vdpau_vdpau_x11_h + VDPAU_CFLAGS="-I/usr/include/nvidia" + VDPAU_LIBS="-L/usr/lib/nvidia -lvdpau" + CPPFLAGS="$VDPAU_CFLAGS $saved_CPPFLAGS" + AC_CHECK_HEADER([vdpau/vdpau.h], [HAVE_VDPAU_H=yes]) + fi + AC_CHECK_HEADER([vdpau/vdpau_x11.h], [HAVE_VDPAU_X11_H=yes]) + CPPFLAGS="$saved_CPPFLAGS" + + if test "x$HAVE_VDPAU_H" = "xyes" -a "x$HAVE_VDPAU_X11_H" = "xyes"; then + dnl Found the headers - look for the lib + AC_MSG_NOTICE([VDPAU headers found. Checking libraries]) + saved_LIBS="$LIBS" + LIBS="$VDPAU_LIBS $saved_LIBS" + AC_CHECK_LIB(vdpau,vdp_device_create_x11,[HAVE_VDPAU="yes"]) + LIBS="$saved_LIBS" + fi + if test "$HAVE_VDPAU" = "yes"; then + AC_MSG_NOTICE([Found up to date VDPAU installation]) + AC_SUBST(VDPAU_CFLAGS) + AC_SUBST(VDPAU_LIBS) + fi ]) else diff --git a/sys/vdpau/Makefile.am b/sys/vdpau/Makefile.am index f4380aff..f62ee0b4 100644 --- a/sys/vdpau/Makefile.am +++ b/sys/vdpau/Makefile.am @@ -9,9 +9,10 @@ libgstvdpau_la_SOURCES = \ gstvdp.c \ gstvdpyuvvideo.c -libgstvdpau_la_CFLAGS = $(GST_CFLAGS) $(X11_CFLAGS) -Ivdpau +libgstvdpau_la_CFLAGS = $(GST_CFLAGS) $(X11_CFLAGS) $(VDPAU_CFLAGS) libgstvdpau_la_LIBADD = $(GST_LIBS) $(GST_BASE_LIBS) \ - $(GST_PLUGINS_BASE) $(X11_LIBS) -lgstvideo-$(GST_MAJORMINOR) -lvdpau + $(GST_PLUGINS_BASE) $(X11_LIBS) -lgstvideo-$(GST_MAJORMINOR) \ + $(VDPAU_LIBS) libgstvdpau_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) libgstvdpau_la_LIBTOOLFLAGS = --tag=disable-static -- cgit v1.2.1 From 8ded28b1260c6cf956f6029f74bccca51ce7fd73 Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Mon, 15 Jun 2009 18:29:56 +0100 Subject: VDPAU: Fix up caps in vdpaumpegdec. Remove extra semicolon Fix a typo in the caps for the VDPAU mpeg decoder (chroma_type->chroma-type) and use the GST_VDP_VIDEO_CAPS for the pad template. Remove a stray semicolon. --- sys/vdpau/gstvdpmpegdec.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/sys/vdpau/gstvdpmpegdec.c b/sys/vdpau/gstvdpmpegdec.c index b720217d..872348c6 100644 --- a/sys/vdpau/gstvdpmpegdec.c +++ b/sys/vdpau/gstvdpmpegdec.c @@ -72,8 +72,7 @@ static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, - GST_STATIC_CAPS ("video/x-vdpau-video, " "chroma-type = (int) 0") - ); + GST_STATIC_CAPS (GST_VDP_VIDEO_CAPS)); #define DEBUG_INIT(bla) \ GST_DEBUG_CATEGORY_INIT (gst_vdp_mpeg_dec_debug, "vdpaumpegdec", 0, "VDPAU powered mpeg decoder"); @@ -188,7 +187,7 @@ gst_vdp_mpeg_dec_set_caps (GstPad * pad, GstCaps * caps) src_caps = gst_caps_new_simple ("video/x-vdpau-video", "device", G_TYPE_OBJECT, mpeg_dec->device, - "chroma_type", G_TYPE_INT, VDP_CHROMA_TYPE_420, + "chroma-type", G_TYPE_INT, VDP_CHROMA_TYPE_420, "width", G_TYPE_INT, width, "height", G_TYPE_INT, height, "framerate", GST_TYPE_FRACTION, fps_n, fps_d, @@ -247,7 +246,7 @@ gst_vdp_mpeg_dec_set_caps (GstPad * pad, GstCaps * caps) } } - bitrate += (ext.bitrate_ext << 18);; + bitrate += (ext.bitrate_ext << 18); gst_buffer_unref (buf); } -- cgit v1.2.1 From 0d94e5a656e971f0aab2713d02e9b191d013e831 Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Mon, 15 Jun 2009 18:33:06 +0100 Subject: VDPAU: Refactor the error path to a common output, and fix a leak. Don't leak the input buffer on errors. Add some debug statements. --- sys/vdpau/gstvdpvideoyuv.c | 40 ++++++++++++++++++++++++---------------- 1 file changed, 24 insertions(+), 16 deletions(-) diff --git a/sys/vdpau/gstvdpvideoyuv.c b/sys/vdpau/gstvdpvideoyuv.c index a1f5b6ed..8f98f12e 100644 --- a/sys/vdpau/gstvdpvideoyuv.c +++ b/sys/vdpau/gstvdpvideoyuv.c @@ -74,16 +74,19 @@ gst_vdp_video_yuv_chain (GstPad * pad, GstBuffer * buffer) GstVdpDevice *device; VdpVideoSurface surface; GstBuffer *outbuf = NULL; + GstFlowReturn result = GST_FLOW_ERROR; video_yuv = GST_VDP_VIDEO_YUV (GST_OBJECT_PARENT (pad)); device = GST_VDP_VIDEO_BUFFER (buffer)->device; surface = GST_VDP_VIDEO_BUFFER (buffer)->surface; + GST_LOG_OBJECT (video_yuv, "Received buffer format %" GST_FOURCC_FORMAT, + GST_FOURCC_ARGS (video_yuv->format)); + switch (video_yuv->format) { case GST_MAKE_FOURCC ('Y', 'V', '1', '2'): { gint size; - GstFlowReturn result; VdpStatus status; guint8 *data[3]; guint32 stride[3]; @@ -94,8 +97,10 @@ gst_vdp_video_yuv_chain (GstPad * pad, GstBuffer * buffer) result = gst_pad_alloc_buffer_and_set_caps (video_yuv->src, GST_BUFFER_OFFSET_NONE, size, GST_PAD_CAPS (video_yuv->src), &outbuf); - if (G_UNLIKELY (result != GST_FLOW_OK)) - return result; + if (G_UNLIKELY (result != GST_FLOW_OK)) { + GST_DEBUG_OBJECT (video_yuv, "Pad alloc_buffer returned %d", result); + goto done; + } data[0] = GST_BUFFER_DATA (outbuf) + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_YV12, @@ -122,14 +127,13 @@ gst_vdp_video_yuv_chain (GstPad * pad, GstBuffer * buffer) ("Couldn't get data from vdpau"), ("Error returned from vdpau was: %s", device->vdp_get_error_string (status))); - goto error; + goto done; } break; } case GST_MAKE_FOURCC ('I', '4', '2', '0'): { gint size; - GstFlowReturn result; VdpStatus status; guint8 *data[3]; guint32 stride[3]; @@ -140,8 +144,10 @@ gst_vdp_video_yuv_chain (GstPad * pad, GstBuffer * buffer) result = gst_pad_alloc_buffer_and_set_caps (video_yuv->src, GST_BUFFER_OFFSET_NONE, size, GST_PAD_CAPS (video_yuv->src), &outbuf); - if (G_UNLIKELY (result != GST_FLOW_OK)) - return result; + if (G_UNLIKELY (result != GST_FLOW_OK)) { + GST_DEBUG_OBJECT (video_yuv, "Pad alloc_buffer returned %d", result); + goto done; + } data[0] = GST_BUFFER_DATA (outbuf) + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_I420, @@ -168,14 +174,13 @@ gst_vdp_video_yuv_chain (GstPad * pad, GstBuffer * buffer) ("Couldn't get data from vdpau"), ("Error returned from vdpau was: %s", device->vdp_get_error_string (status))); - goto error; + goto done; } break; } case GST_MAKE_FOURCC ('N', 'V', '1', '2'): { gint size; - GstFlowReturn result; VdpStatus status; guint8 *data[2]; guint32 stride[2]; @@ -186,9 +191,10 @@ gst_vdp_video_yuv_chain (GstPad * pad, GstBuffer * buffer) result = gst_pad_alloc_buffer_and_set_caps (video_yuv->src, GST_BUFFER_OFFSET_NONE, size, GST_PAD_CAPS (video_yuv->src), &outbuf); - if (G_UNLIKELY (result != GST_FLOW_OK)) - return result; - + if (G_UNLIKELY (result != GST_FLOW_OK)) { + GST_DEBUG_OBJECT (video_yuv, "Pad alloc_buffer returned %d", result); + goto done; + } data[0] = GST_BUFFER_DATA (outbuf); data[1] = GST_BUFFER_DATA (outbuf) + video_yuv->width * video_yuv->height; @@ -204,7 +210,7 @@ gst_vdp_video_yuv_chain (GstPad * pad, GstBuffer * buffer) ("Couldn't get data from vdpau"), ("Error returned from vdpau was: %s", device->vdp_get_error_string (status))); - goto error; + goto done; } break; } @@ -217,9 +223,11 @@ gst_vdp_video_yuv_chain (GstPad * pad, GstBuffer * buffer) gst_buffer_copy_metadata (outbuf, buffer, GST_BUFFER_COPY_TIMESTAMPS); return gst_pad_push (video_yuv->src, outbuf); -error: - gst_buffer_unref (outbuf); - return GST_FLOW_ERROR; +done: + if (outbuf) + gst_buffer_unref (outbuf); + gst_buffer_unref (buffer); + return result; } static GstCaps * -- cgit v1.2.1 From 8c89eb9a5be9307867c836f9072ecaf0cdee2e42 Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Thu, 18 Jun 2009 17:06:23 +0100 Subject: VDPAU: Fix build flags to pull in gst-plugins-base libs --- sys/vdpau/Makefile.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sys/vdpau/Makefile.am b/sys/vdpau/Makefile.am index f62ee0b4..93a7513a 100644 --- a/sys/vdpau/Makefile.am +++ b/sys/vdpau/Makefile.am @@ -9,9 +9,9 @@ libgstvdpau_la_SOURCES = \ gstvdp.c \ gstvdpyuvvideo.c -libgstvdpau_la_CFLAGS = $(GST_CFLAGS) $(X11_CFLAGS) $(VDPAU_CFLAGS) +libgstvdpau_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) $(X11_CFLAGS) $(VDPAU_CFLAGS) libgstvdpau_la_LIBADD = $(GST_LIBS) $(GST_BASE_LIBS) \ - $(GST_PLUGINS_BASE) $(X11_LIBS) -lgstvideo-$(GST_MAJORMINOR) \ + $(GST_PLUGINS_BASE_LIBS) $(X11_LIBS) -lgstvideo-$(GST_MAJORMINOR) \ $(VDPAU_LIBS) libgstvdpau_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) libgstvdpau_la_LIBTOOLFLAGS = --tag=disable-static -- cgit v1.2.1 From deb03ee2ca1b50cc7d5010625def11b057d693cf Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Fri, 19 Jun 2009 21:20:26 +0100 Subject: VDPAU: Add some debug statements --- sys/vdpau/gstvdpmpegdec.c | 8 ++++++++ sys/vdpau/gstvdpvideoyuv.c | 10 ++++++++++ 2 files changed, 18 insertions(+) diff --git a/sys/vdpau/gstvdpmpegdec.c b/sys/vdpau/gstvdpmpegdec.c index 872348c6..674146c4 100644 --- a/sys/vdpau/gstvdpmpegdec.c +++ b/sys/vdpau/gstvdpmpegdec.c @@ -194,6 +194,9 @@ gst_vdp_mpeg_dec_set_caps (GstPad * pad, GstCaps * caps) "pixel-aspect-ratio", GST_TYPE_FRACTION, par_n, par_d, "interlaced", G_TYPE_BOOLEAN, interlaced, NULL); + GST_DEBUG_OBJECT (mpeg_dec, "Setting source caps to %" GST_PTR_FORMAT, + src_caps); + res = gst_pad_set_caps (mpeg_dec->src, src_caps); gst_caps_unref (src_caps); if (!res) @@ -968,6 +971,11 @@ gst_vdp_mpeg_dec_sink_event (GstPad * pad, GstEvent * event) } g_mutex_unlock (mpeg_dec->mutex); + GST_DEBUG_OBJECT (mpeg_dec, + "Pushing new segment update %d format %d start %" + GST_TIME_FORMAT " stop %" GST_TIME_FORMAT " position %" + GST_TIME_FORMAT, update, format, GST_TIME_ARGS (start), + GST_TIME_ARGS (stop), GST_TIME_ARGS (position)); convert_error: res = gst_pad_push_event (mpeg_dec->src, event); diff --git a/sys/vdpau/gstvdpvideoyuv.c b/sys/vdpau/gstvdpvideoyuv.c index 8f98f12e..2318cd40 100644 --- a/sys/vdpau/gstvdpvideoyuv.c +++ b/sys/vdpau/gstvdpvideoyuv.c @@ -122,6 +122,8 @@ gst_vdp_video_yuv_chain (GstPad * pad, GstBuffer * buffer) status = device->vdp_video_surface_get_bits_ycbcr (surface, VDP_YCBCR_FORMAT_YV12, (void *) data, stride); + GST_LOG_OBJECT (video_yuv, + "Got status %d from vdp_video_surface_get_bits_ycbcr", status); if (G_UNLIKELY (status != VDP_STATUS_OK)) { GST_ELEMENT_ERROR (video_yuv, RESOURCE, READ, ("Couldn't get data from vdpau"), @@ -169,6 +171,8 @@ gst_vdp_video_yuv_chain (GstPad * pad, GstBuffer * buffer) status = device->vdp_video_surface_get_bits_ycbcr (surface, VDP_YCBCR_FORMAT_YV12, (void *) data, stride); + GST_LOG_OBJECT (video_yuv, + "Got status %d from vdp_video_surface_get_bits_ycbcr", status); if (G_UNLIKELY (status != VDP_STATUS_OK)) { GST_ELEMENT_ERROR (video_yuv, RESOURCE, READ, ("Couldn't get data from vdpau"), @@ -188,6 +192,7 @@ gst_vdp_video_yuv_chain (GstPad * pad, GstBuffer * buffer) size = video_yuv->width * video_yuv->height + video_yuv->width * video_yuv->height / 2; + GST_LOG_OBJECT (video_yuv, "Entering buffer_alloc"); result = gst_pad_alloc_buffer_and_set_caps (video_yuv->src, GST_BUFFER_OFFSET_NONE, size, GST_PAD_CAPS (video_yuv->src), &outbuf); @@ -202,9 +207,12 @@ gst_vdp_video_yuv_chain (GstPad * pad, GstBuffer * buffer) stride[0] = video_yuv->width; stride[1] = video_yuv->width; + GST_LOG_OBJECT (video_yuv, "Entering vdp_video_surface_get_bits_ycbcr"); status = device->vdp_video_surface_get_bits_ycbcr (surface, VDP_YCBCR_FORMAT_NV12, (void *) data, stride); + GST_LOG_OBJECT (video_yuv, + "Got status %d from vdp_video_surface_get_bits_ycbcr", status); if (G_UNLIKELY (status != VDP_STATUS_OK)) { GST_ELEMENT_ERROR (video_yuv, RESOURCE, READ, ("Couldn't get data from vdpau"), @@ -221,6 +229,8 @@ gst_vdp_video_yuv_chain (GstPad * pad, GstBuffer * buffer) gst_buffer_unref (buffer); gst_buffer_copy_metadata (outbuf, buffer, GST_BUFFER_COPY_TIMESTAMPS); + GST_LOG_OBJECT (video_yuv, "Pushing buffer with ts %" GST_TIME_FORMAT, + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf))); return gst_pad_push (video_yuv->src, outbuf); done: -- cgit v1.2.1 From 1cf9f2d497cf882a179cdfd677900c690cef58ee Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Mon, 22 Jun 2009 11:19:07 +0200 Subject: h264parse: detect and fix for bad NALU sizes when in AVC mode a nalu size seems invalid, assume the NALU has the size of the available data instead of looping forever. Fixes #586354 --- gst/h264parse/gsth264parse.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/gst/h264parse/gsth264parse.c b/gst/h264parse/gsth264parse.c index bea4a600..ebc4360d 100644 --- a/gst/h264parse/gsth264parse.c +++ b/gst/h264parse/gsth264parse.c @@ -464,6 +464,16 @@ gst_h264_parse_chain_forward (GstH264Parse * h264parse, gboolean discont, for (i = 0; i < h264parse->nal_length_size; i++) nalu_size = (nalu_size << 8) | data[i]; + GST_LOG_OBJECT (h264parse, "got NALU size %u", nalu_size); + + /* check for invalid NALU sizes, assume the size if the available bytes + * when something is fishy */ + if (nalu_size <= 1 || nalu_size + h264parse->nal_length_size > avail) { + nalu_size = avail - h264parse->nal_length_size; + GST_DEBUG_OBJECT (h264parse, "fixing invalid NALU size to %u", + nalu_size); + } + /* Packetized format, see if we have to split it, usually splitting is not * a good idea as decoders have no way of handling it. */ if (h264parse->split_packetized) { -- cgit v1.2.1 From f096d6406e9b5e00fa21390224c2bfcc3be8f135 Mon Sep 17 00:00:00 2001 From: Stefan Kost Date: Wed, 10 Jun 2009 11:15:01 +0300 Subject: metadata: fix conversion of geo coordinates Coordinate conversion has been verified with exiv2 and some webpages. Minutes wher totally off and seconds were not used at all. --- ext/metadata/metadataexif.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/ext/metadata/metadataexif.c b/ext/metadata/metadataexif.c index 58d83e2d..0769dab4 100644 --- a/ext/metadata/metadataexif.c +++ b/ext/metadata/metadataexif.c @@ -694,16 +694,16 @@ metadataparse_exif_content_foreach_entry_func (ExifEntry * entry, /* DDD - degrees */ value = (gdouble) rt->numerator / (gdouble) rt->denominator; + GST_DEBUG ("deg: %lu / %lu", rt->numerator, rt->denominator); rt++; /* MM - minutes and SS - seconds */ - if (rt->numerator % rt->denominator) { - value += (gdouble) rt->numerator / (gdouble) rt->denominator; - } else { - value += rt->numerator / rt->denominator; - rt++; - value += rt->numerator / rt->denominator; - } + GST_DEBUG ("min: %lu / %lu", rt->numerator, rt->denominator); + value += (gdouble) rt->numerator / ((gdouble) rt->denominator * 60.0); + rt++; + GST_DEBUG ("sec: %lu / %lu", rt->numerator, rt->denominator); + value += + (gdouble) rt->numerator / ((gdouble) rt->denominator * 3600.0); /* apply sign */ if (entry->tag == EXIF_TAG_GPS_LATITUDE) { @@ -1049,17 +1049,24 @@ metadatamux_exif_for_each_tag_in_list (const GstTagList * list, const ExifTag ref_tag = entry->tag == EXIF_TAG_GPS_LATITUDE ? EXIF_TAG_GPS_LATITUDE_REF : EXIF_TAG_GPS_LONGITUDE_REF; + /* DDD - degrees */ rt->numerator = (gulong) v; rt->denominator = 1; + GST_DEBUG ("deg: %lf : %lu / %lu", v, rt->numerator, rt->denominator); v -= rt->numerator; rt++; - rt->numerator = (gulong) (0.5 + v * 100.0); - rt->denominator = 100; + /* MM - minutes */ + rt->numerator = (gulong) (v * 60.0); + rt->denominator = 1; + GST_DEBUG ("min: %lf : %lu / %lu", v, rt->numerator, rt->denominator); + v -= ((gdouble) rt->numerator / 60.0); rt++; - rt->numerator = 0; + /* SS - seconds */ + rt->numerator = (gulong) (0.5 + v * 3600.0); rt->denominator = 1; + GST_DEBUG ("sec: %lf : %lu / %lu", v, rt->numerator, rt->denominator); if (entry->tag == EXIF_TAG_GPS_LONGITUDE) { GST_DEBUG ("longitude : %lf", value); -- cgit v1.2.1 From 11a78399d8f81a48c8d16dcee1cadc63f9df68ef Mon Sep 17 00:00:00 2001 From: Stefan Kost Date: Fri, 12 Jun 2009 10:40:48 +0300 Subject: camerabin: add camerabin examples gst-camera is a gtk-test app to play with the imagecapture and videorecording. gst-camera-perf is a tool to run various scenarios and take time meassurements (e.g. shot-to-shot). Also sort the output files in configure.ac a bit to be in alphabetical order. --- configure.ac | 25 +- tests/examples/Makefile.am | 6 +- tests/examples/camerabin/.gitignore | 3 + tests/examples/camerabin/Makefile.am | 39 + tests/examples/camerabin/gst-camera-perf.c | 726 ++++++++++ tests/examples/camerabin/gst-camera-perf.glade | 120 ++ tests/examples/camerabin/gst-camera.c | 1756 ++++++++++++++++++++++++ tests/examples/camerabin/gst-camera.glade | 397 ++++++ 8 files changed, 3057 insertions(+), 15 deletions(-) create mode 100644 tests/examples/camerabin/.gitignore create mode 100644 tests/examples/camerabin/Makefile.am create mode 100644 tests/examples/camerabin/gst-camera-perf.c create mode 100644 tests/examples/camerabin/gst-camera-perf.glade create mode 100644 tests/examples/camerabin/gst-camera.c create mode 100644 tests/examples/camerabin/gst-camera.glade diff --git a/configure.ac b/configure.ac index 900d8342..13559944 100644 --- a/configure.ac +++ b/configure.ac @@ -1577,8 +1577,10 @@ dnl po/Makefile.in AC_CONFIG_FILES( Makefile +common/Makefile common/shave common/shave-libtool +common/m4/Makefile gst-plugins-bad.spec gst/Makefile gst/aacparse/Makefile @@ -1586,8 +1588,6 @@ gst/adpcmdec/Makefile gst/aiffparse/Makefile gst/amrparse/Makefile gst/autoconvert/Makefile -gst/legacyresample/Makefile -gst/liveadder/Makefile gst/bayer/Makefile gst/camerabin/Makefile gst/cdxaparse/Makefile @@ -1601,7 +1601,9 @@ gst/frei0r/Makefile gst/h264parse/Makefile gst/hdvparse/Makefile gst/id3tag/Makefile +gst/legacyresample/Makefile gst/librfb/Makefile +gst/liveadder/Makefile gst/mpegdemux/Makefile gst/mpegtsmux/Makefile gst/mpegtsmux/tsmux/Makefile @@ -1614,6 +1616,7 @@ gst/nuvdemux/Makefile gst/pcapparse/Makefile gst/qtmux/Makefile gst/rawparse/Makefile +gst/real/Makefile gst/rtpmanager/Makefile gst/rtpmux/Makefile gst/scaletempo/Makefile @@ -1628,7 +1631,6 @@ gst/tta/Makefile gst/valve/Makefile gst/videosignal/Makefile gst/vmnc/Makefile -gst/real/Makefile gst/xdgmime/Makefile gst-libs/Makefile gst-libs/gst/Makefile @@ -1652,14 +1654,18 @@ sys/wasapi/Makefile sys/wininet/Makefile sys/winks/Makefile sys/winscreencap/Makefile +tests/Makefile +tests/check/Makefile tests/examples/Makefile +tests/examples/camerabin/Makefile tests/examples/directfb/Makefile tests/examples/mxf/Makefile -tests/examples/shapewipe/Makefile tests/examples/scaletempo/Makefile +tests/examples/shapewipe/Makefile tests/examples/switch/Makefile -ext/amrwb/Makefile +tests/icles/Makefile ext/alsaspdif/Makefile +ext/amrwb/Makefile ext/assrender/Makefile ext/apexsink/Makefile ext/bz2/Makefile @@ -1670,7 +1676,6 @@ ext/dirac/Makefile ext/directfb/Makefile ext/divx/Makefile ext/dts/Makefile -ext/metadata/Makefile ext/faac/Makefile ext/faad/Makefile ext/gsm/Makefile @@ -1680,7 +1685,7 @@ ext/jp2k/Makefile ext/ladspa/Makefile ext/libmms/Makefile ext/Makefile -ext/nas/Makefile +ext/metadata/Makefile ext/modplug/Makefile ext/mpeg2enc/Makefile ext/mimic/Makefile @@ -1688,6 +1693,7 @@ ext/mplex/Makefile ext/musepack/Makefile ext/musicbrainz/Makefile ext/mythtv/Makefile +ext/nas/Makefile ext/neon/Makefile ext/ofa/Makefile ext/resindvd/Makefile @@ -1704,12 +1710,7 @@ docs/Makefile docs/plugins/Makefile docs/plugins/figures/Makefile docs/version.entities -common/Makefile -common/m4/Makefile m4/Makefile -tests/Makefile -tests/check/Makefile -tests/icles/Makefile win32/common/config.h ) AC_OUTPUT diff --git a/tests/examples/Makefile.am b/tests/examples/Makefile.am index e68204e3..45d94378 100644 --- a/tests/examples/Makefile.am +++ b/tests/examples/Makefile.am @@ -1,5 +1,5 @@ if HAVE_GTK -GTK_EXAMPLES=scaletempo mxf +GTK_EXAMPLES=camerabin mxf scaletempo else GTK_EXAMPLES= endif @@ -10,5 +10,5 @@ else DIRECTFB_DIR= endif -SUBDIRS= $(DIRECTFB_DIR) $(GTK_EXAMPLES) switch shapewipe -DIST_SUBDIRS= directfb switch scaletempo shapewipe mxf +SUBDIRS= $(DIRECTFB_DIR) $(GTK_EXAMPLES) shapewipe switch +DIST_SUBDIRS= directfb mxf scaletempo shapewipe switch diff --git a/tests/examples/camerabin/.gitignore b/tests/examples/camerabin/.gitignore new file mode 100644 index 00000000..eaedc096 --- /dev/null +++ b/tests/examples/camerabin/.gitignore @@ -0,0 +1,3 @@ +gst-camera +gst-camera-perf + diff --git a/tests/examples/camerabin/Makefile.am b/tests/examples/camerabin/Makefile.am new file mode 100644 index 00000000..df88cf14 --- /dev/null +++ b/tests/examples/camerabin/Makefile.am @@ -0,0 +1,39 @@ +GST_CAMERABIN_GLADE_FILES = gst-camera.glade + +if HAVE_GLADE +if HAVE_GTK + +GST_CAMERABIN_GTK_EXAMPLES = gst-camera + +gst_camera_SOURCES = gst-camera.c +gst_camera_CFLAGS = \ + -I$(top_builddir)/gst-libs \ + $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) $(GLADE_CFLAGS) \ + -DGST_USE_UNSTABLE_API +gst_camera_LDADD = \ + $(top_builddir)/gst-libs/gst/interfaces/libgstphotography-@GST_MAJORMINOR@.la \ + $(GST_PLUGINS_BASE_LIBS) \ + -lgstinterfaces-@GST_MAJORMINOR@ \ + $(GST_LIBS) \ + $(GLADE_LIBS) + +gladedir = $(datadir)/gstreamer-@GST_MAJORMINOR@/camera-apps +glade_DATA = $(GST_CAMERABIN_GLADE_FILES) + +INCLUDES = -DCAMERA_APPS_GLADEDIR=\""$(gladedir)"\" + +else +GST_CAMERABIN_GTK_EXAMPLES = +endif +else +GST_CAMERABIN_GTK_EXAMPLES = +endif + +gst_camera_perf_SOURCES = gst-camera-perf.c +gst_camera_perf_CFLAGS = $(GST_CFLAGS) +gst_camera_perf_LDADD = $(GST_LIBS) + +bin_PROGRAMS = gst-camera-perf $(GST_CAMERABIN_GTK_EXAMPLES) + +EXTRA_DIST = $(GST_CAMERABIN_GLADE_FILES) + diff --git a/tests/examples/camerabin/gst-camera-perf.c b/tests/examples/camerabin/gst-camera-perf.c new file mode 100644 index 00000000..ece3d935 --- /dev/null +++ b/tests/examples/camerabin/gst-camera-perf.c @@ -0,0 +1,726 @@ +/* + * GStreamer + * Copyright (C) 2008 Nokia Corporation + * + * 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. + */ +/* + * This application runs various tests and messures how long it takes. + * FIXME: It needs to figure sane defaults for different hardware or support + * we could use GOption for specifying the parameters + * The config should have: + * - target times + * - filter-caps + * - preview-caps + * - user-res-fps + * - element-names: videoenc, audioenc, videomux, imageenc, videosrc, audiosrc + * Most of it is interpreted in setup_pipeline() + * + * gcc `pkg-config --cflags --libs gstreamer-0.10` gst-camera-perf.c -ogst-camera-perf + * + * plain linux: + * ./gst-camera-perf --src-colorspace=YUY2 --image-width=320 --image-height=240 --view-framerate-num=15 --view-framerate-den=1 + * + * maemo: + * ./gst-camera-perf --src-colorspace=UYVY --image-width=640 --image-height=480 --view-framerate-num=1491 --view-framerate-den=100 --video-src=v4l2camsrc --audio-enc=nokiaaacenc --video-enc=omx_mpeg4enc --video-mux=hantromp4mux + * ./gst-camera-perf --src-colorspace=UYVY --image-width=640 --image-height=480 --view-framerate-num=2999 --view-framerate-den=100 --video-src=v4l2camsrc --audio-enc=nokiaaacenc --video-enc=omx_mpeg4enc --video-mux=hantromp4mux + * ./gst-camera-perf --src-colorspace=UYVY --image-width=2592 --image-height=1968 --view-framerate-num=399 --view-framerate-den=100 --video-src=v4l2camsrc --audio-enc=nokiaaacenc --video-enc=omx_mpeg4enc --video-mux=hantromp4mux + * ./gst-camera-perf --src-colorspace=UYVY --image-width=2592 --image-height=1968 --view-framerate-num=325 --view-framerate-den=25 --video-src=v4l2camsrc --audio-enc=nokiaaacenc --video-enc=omx_mpeg4enc --video-mux=hantromp4mux --image-enc=dspjpegenc + */ + +/* + * Includes + */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include + +/* + * enums, typedefs and defines + */ + +#define GET_TIME(t) \ +do { \ + t = gst_util_get_timestamp (); \ + GST_INFO("%2d ----------------------------------------", test_ix); \ +} while(0) + +#define DIFF_TIME(e,s,d) d=GST_CLOCK_DIFF(s,e) + +#define CONT_SHOTS 10 +#define TEST_CASES 9 + +typedef struct _ResultType +{ + GstClockTime avg; + GstClockTime min; + GstClockTime max; + guint32 times; +} ResultType; + +/* + * Global vars + */ +static GstElement *camera_bin = NULL; +static GMainLoop *loop = NULL; + +/* commandline options */ +static gchar *audiosrc_name = NULL; +static gchar *videosrc_name = NULL; +static gchar *audioenc_name = NULL; +static gchar *videoenc_name = NULL; +static gchar *imageenc_name = NULL; +static gchar *videomux_name = NULL; +static gchar *src_csp = NULL; +static gint image_width = 0; +static gint image_height = 0; +static gint view_framerate_num = 0; +static gint view_framerate_den = 0; + +/* test configuration for common callbacks */ +static GString *filename = NULL; +static guint32 num_pics = 0; +static guint32 num_pics_cont = 0; +//static guint32 num_vids = 0; +static guint test_ix = 0; +static gboolean signal_sink = FALSE; +static gboolean signal_shot = FALSE; +static gboolean signal_cont = FALSE; +//static gboolean signal_save = FALSE; + +/* time samples and test results */ +static GstClockTime t_initial = G_GUINT64_CONSTANT (0); +static GstClockTime t_final[CONT_SHOTS] = { G_GUINT64_CONSTANT (0), }; + +static GstClockTimeDiff diff; +static ResultType result; + +static const GstClockTime target[TEST_CASES] = { + 1000 * GST_MSECOND, + 0, /* 1500 * GST_MSECOND, not tested */ + 1500 * GST_MSECOND, + 2000 * GST_MSECOND, /* this should be shorter, as we can take next picture before preview is ready */ + 500 * GST_MSECOND, + 0, /* 2000 * GST_MSECOND, not tested */ + 3500 * GST_MSECOND, + 1000 * GST_MSECOND, + 0 /* 1000 * GST_MSECOND, not tested */ +}; + +static const gchar *test_names[TEST_CASES] = { + "Camera OFF to VF on", + "(3A latency)", + "Shot to snapshot", + "Shot to shot", + "Serial shooting", + "(Shutter lag)", + "Image saved", + "Mode change", + "(Video recording)" +}; + +/* + * Prototypes + */ + +static void print_result (void); +static gboolean run_test (gpointer user_data); + +/* + * Callbacks + */ + +static gboolean +img_sink_has_buffer (GstPad * pad, GstBuffer * buf, gpointer user_data) +{ + if (signal_sink) { + signal_sink = FALSE; + GET_TIME (t_final[0]); + } + return TRUE; +} + +static gboolean +img_capture_done (GstElement * camera, GString * fname, gpointer user_data) +{ + gboolean ret = FALSE; + gboolean print_and_restart = FALSE; + + GST_INFO ("shot %d, cont %d, num %d", signal_shot, signal_cont, + num_pics_cont); + + if (signal_shot) { + GET_TIME (t_final[num_pics_cont]); + signal_shot = FALSE; + switch (test_ix) { + case 6: + DIFF_TIME (t_final[num_pics_cont], t_initial, diff); + result.avg = result.min = result.max = diff; + print_and_restart = TRUE; + break; + } + GST_INFO ("%2d shot done", test_ix); + } + + if (signal_cont) { + gint i; + + if (num_pics_cont < CONT_SHOTS) { + gchar tmp[6]; + + GET_TIME (t_final[num_pics_cont]); + num_pics_cont++; + for (i = filename->len - 1; i > 0; --i) { + if (filename->str[i] == '_') + break; + } + snprintf (tmp, 6, "_%04d", num_pics_cont); + memcpy (filename->str + i, tmp, 5); + GST_INFO ("%2d cont new filename '%s'", test_ix, filename->str); + g_object_set (camera_bin, "filename", filename->str, NULL); + // FIXME: is burst capture broken? new filename and return TRUE should be enough + g_signal_emit_by_name (camera_bin, "user-start", NULL); + ret = TRUE; + } else { + GstClockTime max = 0; + GstClockTime min = -1; + GstClockTime total = 0; + GstClockTime first_shot = 0; + GstClockTime snd_shot = 0; + + num_pics_cont = 0; + signal_cont = FALSE; + + DIFF_TIME (t_final[0], t_initial, diff); + max < diff ? max = diff : max; + min > diff ? min = diff : min; + first_shot = diff; + total += diff; + + DIFF_TIME (t_final[1], t_final[0], diff); + max < diff ? max = diff : max; + min > diff ? min = diff : min; + snd_shot = diff; + total += diff; + + for (i = 2; i < CONT_SHOTS; ++i) { + DIFF_TIME (t_final[i], t_final[i - 1], diff); + + max < diff ? max = diff : max; + min > diff ? min = diff : min; + total += diff; + } + + result.avg = total / CONT_SHOTS; + result.min = min; + result.max = max; + print_and_restart = TRUE; + GST_INFO ("%2d cont done", test_ix); + } + } + + switch (test_ix) { + case 2: + case 3: + print_and_restart = TRUE; + break; + } + + if (print_and_restart) { + print_result (); + g_idle_add ((GSourceFunc) run_test, NULL); + return FALSE; + } + return ret; +} + +static gboolean +bus_callback (GstBus * bus, GstMessage * message, gpointer data) +{ + const GstStructure *st; + + switch (GST_MESSAGE_TYPE (message)) { + case GST_MESSAGE_ERROR:{ + GError *err; + gchar *debug; + + gst_message_parse_error (message, &err, &debug); + g_print ("Error: %s\n", err->message); + g_error_free (err); + g_free (debug); + + /* Write debug graph to file */ + GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (camera_bin), + GST_DEBUG_GRAPH_SHOW_ALL, "camerabin.error"); + + g_main_loop_quit (loop); + break; + } + case GST_MESSAGE_EOS: + /* end-of-stream */ + g_main_loop_quit (loop); + break; + default: + st = gst_message_get_structure (message); + if (st) { + if (gst_structure_has_name (st, "image-captured")) { + GST_INFO ("%2d image-captured", test_ix); + switch (test_ix) { + case 3: + GET_TIME (t_final[num_pics_cont]); + DIFF_TIME (t_final[num_pics_cont], t_initial, diff); + result.avg = result.min = result.max = diff; + break; + } + } else if (gst_structure_has_name (st, "preview-image")) { + GST_INFO ("%2d preview-image", test_ix); + switch (test_ix) { + case 2: + GET_TIME (t_final[num_pics_cont]); + DIFF_TIME (t_final[num_pics_cont], t_initial, diff); + result.avg = result.min = result.max = diff; + break; + } + } + } + /* unhandled message */ + break; + } + return TRUE; +} + + +/* + * Helpers + */ + +static void +cleanup_pipeline (void) +{ + if (camera_bin) { + gst_element_set_state (camera_bin, GST_STATE_NULL); + gst_element_get_state (camera_bin, NULL, NULL, GST_CLOCK_TIME_NONE); + gst_object_unref (camera_bin); + camera_bin = NULL; + } +} + +static gboolean +setup_pipeline_video_sink (void) +{ + GstElement *sink = NULL; + GstPad *pad = NULL; + + sink = gst_element_factory_make ("fakesink", NULL); + if (NULL == sink) { + g_warning ("failed to create sink\n"); + goto error; + } + + pad = gst_element_get_static_pad (sink, "sink"); + if (NULL == pad) { + g_warning ("sink has no pad named 'sink'\n"); + goto error; + } + + g_object_set (sink, "sync", TRUE, NULL); + gst_pad_add_buffer_probe (pad, (GCallback) img_sink_has_buffer, NULL); + gst_object_unref (pad); + + g_object_set (camera_bin, "vfsink", sink, NULL); + + return TRUE; +error: + if (sink) + gst_object_unref (sink); + return FALSE; +} + +static gboolean +setup_pipeline_element (const gchar * property_name, const gchar * element_name) +{ + gboolean res = TRUE; + + GstElement *elem; + if (element_name) { + elem = gst_element_factory_make (element_name, NULL); + if (elem) { + g_object_set (camera_bin, property_name, elem, NULL); + } else { + g_warning ("can't create element '%s' for property '%s'", element_name, + property_name); + res = FALSE; + } + } + return res; +} + +static gboolean +setup_pipeline (void) +{ + GstBus *bus; + gboolean res = TRUE; + + g_string_printf (filename, "test_%04u.jpg", num_pics); + + camera_bin = gst_element_factory_make ("camerabin", NULL); + if (NULL == camera_bin) { + g_warning ("can't create camerabin element\n"); + goto error; + } + + g_signal_connect (camera_bin, "img-done", (GCallback) img_capture_done, NULL); + + bus = gst_pipeline_get_bus (GST_PIPELINE (camera_bin)); + gst_bus_add_watch (bus, bus_callback, NULL); + gst_object_unref (bus); + + if (!setup_pipeline_video_sink ()) { + goto error; + } + + /* set properties */ + + if (src_csp && strlen (src_csp) == 4) { + GstCaps *filter_caps; + + /* FIXME: why do we need to set this? */ + filter_caps = gst_caps_new_simple ("video/x-raw-yuv", + "format", GST_TYPE_FOURCC, + GST_MAKE_FOURCC (src_csp[0], src_csp[1], src_csp[2], src_csp[3]), NULL); + if (filter_caps) { + g_object_set (camera_bin, "filename", filename->str, + "filter-caps", filter_caps, NULL); + gst_caps_unref (filter_caps); + } else { + g_warning ("can't make filter-caps with format=%s\n", src_csp); + goto error; + } + } + + /* configure used elements */ + res &= setup_pipeline_element ("audiosrc", audiosrc_name); + res &= setup_pipeline_element ("videosrc", videosrc_name); + res &= setup_pipeline_element ("audioenc", audioenc_name); + res &= setup_pipeline_element ("videoenc", videoenc_name); + res &= setup_pipeline_element ("imageenc", imageenc_name); + res &= setup_pipeline_element ("videomux", videomux_name); + if (!res) { + goto error; + } + + /* configure a resolution and framerate */ + if (image_width && image_height && view_framerate_num && view_framerate_den) { + g_signal_emit_by_name (camera_bin, "user-res-fps", image_width, + image_height, view_framerate_num, view_framerate_den, NULL); + } + + if (GST_STATE_CHANGE_FAILURE == + gst_element_set_state (camera_bin, GST_STATE_READY)) { + g_warning ("can't set camerabin to ready\n"); + goto error; + } + + if (GST_STATE_CHANGE_FAILURE == + gst_element_set_state (camera_bin, GST_STATE_PLAYING)) { + g_warning ("can't set camerabin to playing\n"); + goto error; + } + return TRUE; +error: + cleanup_pipeline (); + return FALSE; +} + +/* + * Tests + */ + +/* 01) Camera OFF to VF On + * + * This only tests the time it takes to create the pipeline and CameraBin + * element and have the first video frame available in ViewFinder. + * It is not testing the real init time. To do it, the timer must start before + * the app. + */ +static gboolean +test_01 (void) +{ + GET_TIME (t_initial); + if (setup_pipeline ()) { + /* MAKE SURE THE PIPELINE IS IN PLAYING STATE BEFORE START TAKING PICTURES + AND SO ON (otherwise it will deadlock) */ + gst_element_get_state (camera_bin, NULL, NULL, GST_CLOCK_TIME_NONE); + } + + GET_TIME (t_final[0]); + DIFF_TIME (t_final[0], t_initial, diff); + + result.avg = result.min = result.max = diff; + result.times = 1; + return TRUE; +} + + +/* 03) Shot to snapshot + * + * It tests the time between pressing the Shot button and having the photo shown + * in ViewFinder + */ +static gboolean +test_03 (void) +{ + GstCaps *snap_caps; + + /* FIXME: add options */ + snap_caps = gst_caps_from_string ("video/x-raw-rgb,width=320,height=240"); + g_object_set (camera_bin, "preview-caps", snap_caps, NULL); + gst_caps_unref (snap_caps); + + GET_TIME (t_initial); + g_signal_emit_by_name (camera_bin, "user-start", 0); + + /* the actual results are fetched in bus_callback::preview-image */ + result.times = 1; + return FALSE; +} + + +/* 04) Shot to shot + * It tests the time for being able to take a second shot after the first one. + */ +static gboolean +test_04 (void) +{ + GET_TIME (t_initial); + g_signal_emit_by_name (camera_bin, "user-start", 0); + + /* the actual results are fetched in bus_callback::image-captured */ + result.times = 1; + return FALSE; +} + +/* 05) Serial shooting + * + * It tests the time between shots in continuous mode. + */ +static gboolean +test_05 (void) +{ + signal_cont = TRUE; + GET_TIME (t_initial); + g_signal_emit_by_name (camera_bin, "user-start", 0); + + /* the actual results are fetched in img_capture_done */ + result.times = CONT_SHOTS; + return FALSE; +} + + +/* 07) Image saved + * + * It tests the time between pressing the Shot and the final image is saved to + * file system. + */ +static gboolean +test_07 (void) +{ + // signal_save = TRUE; + signal_shot = TRUE; + + GET_TIME (t_initial); + g_signal_emit_by_name (camera_bin, "user-start", 0); + /* call "user-stop" just to go back to initial state (view-finder) again */ + g_signal_emit_by_name (camera_bin, "user-stop", 0); + /* the actual results are fetched in img_capture_done */ + result.times = 1; + return FALSE; +} + + +/* 08) Mode change + * + * It tests the time it takes to change between still image and video recording + * mode (In this test we change the mode few times). + */ +static gboolean +test_08 (void) +{ + GstClockTime total = 0; + GstClockTime max = 0; + GstClockTime min = -1; + const gint count = 6; + gint i; + + for (i = 0; i < count; ++i) { + GET_TIME (t_final[i]); + g_object_set (camera_bin, "mode", (i + 1) & 1, NULL); + GET_TIME (t_final[i + 1]); + } + + for (i = 0; i < count; ++i) { + DIFF_TIME (t_final[i + 1], t_final[i], diff); + total += diff; + if (diff > max) + max = diff; + if (diff < min) + min = diff; + } + + result.avg = total / count; + result.min = min; + result.max = max; + result.times = count; + + /* just make sure we are back to still image mode again */ + g_object_set (camera_bin, "mode", 0, NULL); + return TRUE; +} + +typedef gboolean (*test_case) (void); +static test_case test_cases[TEST_CASES] = { + test_01, + NULL, + test_03, + test_04, + test_05, + NULL, + test_07, + test_08 +}; + +static void +print_result (void) +{ + printf ("| %6.02f%% ", 100.0f * (float) result.max / (float) target[test_ix]); + printf ("|%5u ms ", (guint) GST_TIME_AS_MSECONDS (target[test_ix])); + printf ("|%5u ms ", (guint) GST_TIME_AS_MSECONDS (result.avg)); + printf ("|%5u ms ", (guint) GST_TIME_AS_MSECONDS (result.min)); + printf ("|%5u ms ", (guint) GST_TIME_AS_MSECONDS (result.max)); + printf ("| %3d ", result.times); + printf ("| %-19s |\n", test_names[test_ix]); + test_ix++; +} + +static gboolean +run_test (gpointer user_data) +{ + gboolean ret = TRUE; + + printf ("| %02d ", test_ix + 1); + if (test_cases[test_ix]) { + memset (&result, 0, sizeof (ResultType)); + ret = test_cases[test_ix] (); + + //while (g_main_context_pending (NULL)) g_main_context_iteration (NULL,FALSE); + if (ret) { + print_result (); + } + + } else { + printf ("| test not implemented "); + printf ("| %-19s |\n", test_names[test_ix]); + test_ix++; + } + + if (!camera_bin || test_ix == TEST_CASES) { + GST_INFO ("done"); + g_main_loop_quit (loop); + return FALSE; + } else { + GST_INFO ("%2d result: %d", test_ix, ret); + return ret; + } +} + +int +main (int argc, char *argv[]) +{ + GOptionEntry options[] = { + {"audio-src", '\0', 0, G_OPTION_ARG_STRING, &audiosrc_name, + "audio source used in video recording", NULL}, + {"video-src", '\0', 0, G_OPTION_ARG_STRING, &videosrc_name, + "video source used in still capture and video recording", NULL}, + {"audio-enc", '\0', 0, G_OPTION_ARG_STRING, &audioenc_name, + "audio encoder used in video recording", NULL}, + {"video-enc", '\0', 0, G_OPTION_ARG_STRING, &videoenc_name, + "video encoder used in video recording", NULL}, + {"image-enc", '\0', 0, G_OPTION_ARG_STRING, &imageenc_name, + "image encoder used in still capture", NULL}, + {"video-mux", '\0', 0, G_OPTION_ARG_STRING, &videomux_name, + "muxer used in video recording", NULL}, + {"image-width", '\0', 0, G_OPTION_ARG_INT, &image_width, + "width for image capture", NULL}, + {"image-height", '\0', 0, G_OPTION_ARG_INT, &image_height, + "height for image capture", NULL}, + {"view-framerate-num", '\0', 0, G_OPTION_ARG_INT, &view_framerate_num, + "framerate numerator for viewfinder", NULL}, + {"view-framerate-den", '\0', 0, G_OPTION_ARG_INT, &view_framerate_den, + "framerate denominator for viewfinder", NULL}, + {"src-colorspace", '\0', 0, G_OPTION_ARG_STRING, &src_csp, + "colorspace format for videosource (e.g. YUY2, UYVY)", NULL}, + {NULL} + }; + GOptionContext *ctx; + GError *err = NULL; + + if (!g_thread_supported ()) + g_thread_init (NULL); + + ctx = g_option_context_new (NULL); + g_option_context_add_main_entries (ctx, options, NULL); + g_option_context_add_group (ctx, gst_init_get_option_group ()); + if (!g_option_context_parse (ctx, &argc, &argv, &err)) { + g_print ("Error initializing: %s\n", err->message); + exit (1); + } + g_option_context_free (ctx); + + /* init */ + filename = g_string_new_len ("", 16); + loop = g_main_loop_new (NULL, FALSE); + + /* run */ + puts (""); + puts ("+---------------------------------------------------------------------------------------+"); + puts ("| test | rate | target | avg | min | max | trials | description |"); + puts ("+---------------------------------------------------------------------------------------+"); + g_idle_add ((GSourceFunc) run_test, NULL); + g_main_loop_run (loop); + puts ("+---------------------------------------------------------------------------------------+"); + puts (""); + + fflush (stdout); + + /* free */ + cleanup_pipeline (); + g_main_loop_unref (loop); + g_string_free (filename, TRUE); + g_free (audiosrc_name); + g_free (videosrc_name); + g_free (audioenc_name); + g_free (videoenc_name); + g_free (imageenc_name); + g_free (videomux_name); + g_free (src_csp); + + return 0; +} diff --git a/tests/examples/camerabin/gst-camera-perf.glade b/tests/examples/camerabin/gst-camera-perf.glade new file mode 100644 index 00000000..fe6098ec --- /dev/null +++ b/tests/examples/camerabin/gst-camera-perf.glade @@ -0,0 +1,120 @@ + + + + + + + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + GTK_WINDOW_TOPLEVEL + GTK_WIN_POS_NONE + False + 400 + 600 + True + False + True + False + False + GDK_WINDOW_TYPE_HINT_NORMAL + GDK_GRAVITY_NORTH_WEST + True + False + + + + + True + True + 200 + + + + 100 + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + True + False + + + + + + True + False + 0 + + + + True + True + start + True + GTK_RELIEF_NORMAL + True + + + + 0 + False + True + + + + + + True + True + GTK_POLICY_NEVER + GTK_POLICY_AUTOMATIC + GTK_SHADOW_NONE + GTK_CORNER_TOP_LEFT + + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + GTK_SHADOW_IN + + + + True + True + == Please wait few seconds after press start == + False + True + GTK_JUSTIFY_LEFT + True + True + 0.5 + 0 + 0 + 0 + PANGO_ELLIPSIZE_NONE + -1 + False + 0 + + + + + + + 0 + True + True + + + + + True + True + + + + + + + diff --git a/tests/examples/camerabin/gst-camera.c b/tests/examples/camerabin/gst-camera.c new file mode 100644 index 00000000..f894418c --- /dev/null +++ b/tests/examples/camerabin/gst-camera.c @@ -0,0 +1,1756 @@ +/* + * GStreamer + * Copyright (C) 2008 Nokia Corporation + * + * 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. + */ +/* + * This is a demo application to test the camerabin element. + * If you have question don't hesitate in contact me edgard.lima@indt.org.br + */ + +/* + * Includes + */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include +#include +#include // g_fopen() + +/* + * enums, typedefs and defines + */ + +#ifdef USE_MP4 +#define VID_FILE_EXT "mp4" +#else +#define VID_FILE_EXT "ogg" +#endif + +#define PREVIEW_TIME_MS (2 * 1000) +#define N_BURST_IMAGES 10 +#define DEFAULT_GLADE_FILE "gst-camera.glade" +#define SHARED_GLADE_FILE CAMERA_APPS_GLADEDIR"/"DEFAULT_GLADE_FILE + +/* Names of default elements */ +#define CAMERA_APP_VIDEOSRC "v4l2src" +#define CAMERA_APP_IMAGE_POSTPROC "dummy" + +#ifdef HAVE_GST_PHOTO_IFACE_H +#define EV_COMP_MAX 3.0 +#define EV_COMP_MIN -3.0 +#define EV_COMP_STEP 0.5 +#endif + +#define DEFAULT_VF_CAPS \ + "video/x-raw-yuv, width = (int) 320, height = (int) 240, framerate = (fraction) 1496/100;" \ + "video/x-raw-yuv, width = (int) 640, height = (int) 480, framerate = (fraction) 1494/100;" \ + "video/x-raw-yuv, width = (int) 800, height = (int) 480, framerate = (fraction) 2503/100;" \ + "video/x-raw-yuv, width = (int) 800, height = (int) 480, framerate = (fraction) 2988/100;" \ + "video/x-raw-yuv, width = (int) 800, height = (int) 480, framerate = (fraction) 1494/100;" \ + "video/x-raw-yuv, width = (int) 720, height = (int) 480, framerate = (fraction) 1494/100" + +#define PREVIEW_CAPS \ + "video/x-raw-rgb, width = (int) 640, height = (int) 480" + +/* states: + (image) <---> (video_stopped) <---> (video_recording) +*/ +typedef enum _tag_CaptureState +{ + CAP_STATE_IMAGE, + CAP_STATE_VIDEO_STOPED, + CAP_STATE_VIDEO_PAUSED, + CAP_STATE_VIDEO_RECORDING, +} CaptureState; + +/* + * Global Vars + */ + +static GladeXML *ui_glade_xml = NULL; +static GtkWidget *ui_main_window = NULL; +static GtkWidget *ui_drawing = NULL; +static GtkWidget *ui_drawing_frame = NULL; +static GtkWidget *ui_chk_continous = NULL; +static GtkButton *ui_bnt_shot = NULL; +static GtkButton *ui_bnt_pause = NULL; +static GtkWidget *ui_chk_mute = NULL; +static GtkWidget *ui_vbox_color_controls = NULL; +static GtkWidget *ui_chk_rawmsg = NULL; + +static GtkWidget *ui_rdbntImageCapture = NULL; +static GtkWidget *ui_rdbntVideoCapture = NULL; +static GtkWidget *ui_menuitem_photography = NULL; +static GtkWidget *ui_menuitem_capture = NULL; + +static GtkComboBox *ui_cbbox_resolution = NULL; +static guint ui_cbbox_resolution_count = 0; + +static CaptureState capture_state = CAP_STATE_IMAGE; + +static GstElement *gst_camera_bin = NULL; +static GstElement *gst_videosrc = NULL; + +static GString *filename = NULL; +static guint32 num_pics = 0; +static guint32 num_pics_cont = 0; +static guint32 num_vids = 0; + +static gint max_fr_n = 0; +static gint max_fr_d = 0; +static gchar *video_post; +static gchar *image_post; + +static GList *video_caps_list = NULL; + +#ifdef HAVE_GST_PHOTO_IFACE_H +static gchar *iso_speed_labels[] = { "auto", "100", "200", "400" }; + +static struct +{ + gchar *label; + gint width; + gint height; +} image_resolution_label_map[] = { + { + "View finder resolution", 0, 0}, { + "VGA", 640, 480}, { + "1,3Mpix (1280x960)", 1280, 960}, { + "3Mpix (2048x1536)", 2048, 1536}, { + "3,7Mpix 16:9 (2592x1456)", 2592, 1456}, { + "5Mpix (2592x1968)", 2592, 1968} +}; +#endif + +/* + * functions prototypes + */ +static gboolean me_gst_setup_pipeline (const gchar * imagepost, + const gchar * videopost); +static void me_gst_cleanup_element (void); + +static gboolean capture_mode_set_state (CaptureState state); +static void capture_mode_config_gui (void); +static gboolean capture_mode_stop (void); + +static void on_windowMain_delete_event (GtkWidget * widget, GdkEvent * event, + gpointer user_data); +static void on_buttonShot_clicked (GtkButton * button, gpointer user_data); +static void on_buttonPause_clicked (GtkButton * button, gpointer user_data); +static void on_comboboxResolution_changed (GtkComboBox * widget, + gpointer user_data); +static void on_radiobuttonImageCapture_toggled (GtkToggleButton * togglebutton, + gpointer user_data); +static void on_radiobuttonVideoCapture_toggled (GtkToggleButton * togglebutton, + gpointer user_data); +static void on_rbBntVidEffNone_toggled (GtkToggleButton * togglebutton, + gpointer user_data); +static void on_rbBntVidEffEdge_toggled (GtkToggleButton * togglebutton, + gpointer user_data); +static void on_rbBntVidEffAging_toggled (GtkToggleButton * togglebutton, + gpointer user_data); +static void on_rbBntVidEffDice_toggled (GtkToggleButton * togglebutton, + gpointer user_data); +static void on_rbBntVidEffWarp_toggled (GtkToggleButton * togglebutton, + gpointer user_data); +static void on_rbBntVidEffShagadelic_toggled (GtkToggleButton * togglebutton, + gpointer user_data); +static void on_rbBntVidEffVertigo_toggled (GtkToggleButton * togglebutton, + gpointer user_data); +static void on_rbBntVidEffRev_toggled (GtkToggleButton * togglebutton, + gpointer user_data); +static void on_rbBntVidEffQuark_toggled (GtkToggleButton * togglebutton, + gpointer user_data); +static void on_chkbntMute_toggled (GtkToggleButton * togglebutton, + gpointer user_data); +static void on_chkbtnRawMsg_toggled (GtkToggleButton * togglebutton, + gpointer data); +static void on_hscaleZoom_value_changed (GtkRange * range, gpointer user_data); + +static void ui_connect_signals (void); +static gboolean ui_create (void); +static void destroy_color_controls (void); +static void create_color_controls (void); +static void init_view_finder_resolution_combobox (void); + +#ifdef HAVE_GST_PHOTO_IFACE_H +static void menuitem_toggle_active (GtkWidget * widget, gpointer data); +static void sub_menu_initialize (GtkWidget * widget, gpointer data); +static void fill_photography_menu (GtkMenuItem * parent_item); +#endif + +/* + * functions implementation + */ + +static void +set_filename (GString * name) +{ + const gchar *datadir; + + if (capture_state == CAP_STATE_IMAGE) { + g_string_printf (name, G_DIR_SEPARATOR_S "test_%04u.jpg", num_pics); + datadir = g_get_user_special_dir (G_USER_DIRECTORY_PICTURES); + } else { + g_string_printf (name, G_DIR_SEPARATOR_S "test_%04u.%s", num_vids, + VID_FILE_EXT); + datadir = g_get_user_special_dir (G_USER_DIRECTORY_VIDEOS); + } + + if (datadir == NULL) { + // FIXME: maemo + //#define DEFAULT_IMAGEDIR "$HOME/MyDocs/.images/" + //#define DEFAULT_VIDEODIR "$HOME/MyDocs/.videos/" + gchar *curdir = g_get_current_dir (); + g_string_prepend (name, curdir); + g_free (curdir); + } else { + g_string_prepend (name, datadir); + } +} + +static GstBusSyncReply +set_xwindow (GstMessage ** message, gpointer data) +{ + GstBusSyncReply ret = GST_BUS_PASS; + const GstStructure *s = gst_message_get_structure (*message); + + if (!s || !gst_structure_has_name (s, "prepare-xwindow-id")) { + goto done; + } + + gst_x_overlay_set_xwindow_id (GST_X_OVERLAY (GST_MESSAGE_SRC (*message)), + GDK_WINDOW_XWINDOW (ui_drawing->window)); + + gst_message_unref (*message); + *message = NULL; + ret = GST_BUS_DROP; +done: + return ret; +} + +/* Write raw image buffer to file if found from message */ +static void +handle_element_message (GstMessage * msg) +{ + const GstStructure *st; + const GValue *image; + GstBuffer *buf = NULL; + guint8 *data = NULL; + gchar *caps_string; + guint size = 0; + gchar *filename = NULL; + FILE *f = NULL; + size_t written; + + st = gst_message_get_structure (msg); + if (g_str_equal (gst_structure_get_name (st), "autofocus-done")) { + gtk_button_set_label (ui_bnt_pause, "Focus"); + } else if (gst_structure_has_field_typed (st, "buffer", GST_TYPE_BUFFER)) { + image = gst_structure_get_value (st, "buffer"); + if (image) { + buf = gst_value_get_buffer (image); + data = GST_BUFFER_DATA (buf); + size = GST_BUFFER_SIZE (buf); + if (g_str_equal (gst_structure_get_name (st), "raw-image")) { + filename = g_strdup_printf ("test_%04u.raw", num_pics); + } else if (g_str_equal (gst_structure_get_name (st), "preview-image")) { + filename = g_strdup_printf ("test_%04u_vga.rgb", num_pics); + } else { + /* for future purposes */ + g_print ("unknown buffer received\n"); + return; + } + caps_string = gst_caps_to_string (GST_BUFFER_CAPS (buf)); + g_print ("writing buffer to %s, buffer caps: %s\n", + filename, caps_string); + g_free (caps_string); + f = g_fopen (filename, "w"); + if (f) { + written = fwrite (data, size, 1, f); + if (!written) { + g_print ("errro writing file\n"); + } + fclose (f); + } else { + g_print ("error opening file for raw image writing\n"); + } + g_free (filename); + } + } else if (g_str_equal (gst_structure_get_name (st), "photo-capture-start")) { + g_print ("=== CLICK ===\n"); + } +} + +static GstBusSyncReply +my_bus_sync_callback (GstBus * bus, GstMessage * message, gpointer data) +{ + GstBusSyncReply ret = GST_BUS_PASS; + + switch (GST_MESSAGE_TYPE (message)) { + case GST_MESSAGE_ELEMENT: + ret = set_xwindow (&message, data); + break; + default: + /* unhandled message */ + break; + } + return ret; +} + +static gboolean +my_bus_callback (GstBus * bus, GstMessage * message, gpointer data) +{ + switch (GST_MESSAGE_TYPE (message)) { + case GST_MESSAGE_WARNING:{ + GError *err; + gchar *debug; + + gst_message_parse_warning (message, &err, &debug); + g_print ("Warning: %s\n", err->message); + g_error_free (err); + g_free (debug); + break; + } + case GST_MESSAGE_ERROR:{ + GError *err; + gchar *debug; + + gst_message_parse_error (message, &err, &debug); + g_print ("Error: %s\n", err->message); + g_error_free (err); + g_free (debug); + + me_gst_cleanup_element (); + gtk_main_quit (); + break; + } + case GST_MESSAGE_EOS: + /* end-of-stream */ + gtk_main_quit (); + break; + case GST_MESSAGE_STATE_CHANGED:{ + GstState old, new, pending; + + gst_message_parse_state_changed (message, &old, &new, &pending); + + /* Create/destroy color controls according videosrc state */ + if (GST_MESSAGE_SRC (message) == GST_OBJECT (gst_videosrc)) { + if (old == GST_STATE_PAUSED && new == GST_STATE_READY) { + destroy_color_controls (); + } else if (old == GST_STATE_READY && new == GST_STATE_PAUSED) { + create_color_controls (); + } + } + + /* we only care about pipeline state change messages */ + if (GST_IS_PIPELINE (GST_MESSAGE_SRC (message))) { + /* dump graph for pipeline state changes */ + gchar *dump_name = g_strdup_printf ("camerabin.%s_%s", + gst_element_state_get_name (old), + gst_element_state_get_name (new)); + GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (GST_MESSAGE_SRC (message)), + GST_DEBUG_GRAPH_SHOW_MEDIA_TYPE | + GST_DEBUG_GRAPH_SHOW_NON_DEFAULT_PARAMS, dump_name); + g_free (dump_name); + } + } + break; + case GST_MESSAGE_ELEMENT: + { + handle_element_message (message); + break; + } + default: + /* unhandled message */ + break; + } + return TRUE; +} + +static void +me_set_next_cont_file_name (GString * filename) +{ + /* FIXME: better file naming (possible with signal) */ + if (G_UNLIKELY (num_pics_cont == 1)) { + gint i; + for (i = filename->len - 1; i > 0; --i) { + if (filename->str[i] == '.') + break; + } + g_string_insert (filename, i, "_0001"); + } else { + gchar tmp[6]; + gint i; + for (i = filename->len - 1; i > 0; --i) { + if (filename->str[i] == '_') + break; + } + snprintf (tmp, 6, "_%04d", num_pics_cont); + memcpy (filename->str + i, tmp, 5); + } +} + +static gboolean +stop_image_preview (gpointer data) +{ + g_return_val_if_fail (data != NULL, FALSE); + + g_signal_emit_by_name (data, "user-stop", 0); + + return FALSE; +} + +static gboolean +me_image_capture_done (GstElement * camera, const gchar * fname, + gpointer user_data) +{ + gboolean cont = + gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (ui_chk_continous)); + GString *filename = g_string_new (fname); + + if (num_pics_cont < N_BURST_IMAGES && cont) { + num_pics_cont++; + me_set_next_cont_file_name (filename); + g_object_set (G_OBJECT (camera), "filename", filename->str, NULL); + g_string_free (filename, TRUE); + } else { + gtk_widget_set_sensitive (GTK_WIDGET (ui_bnt_shot), TRUE); + printf ("%u image(s) saved\n", num_pics_cont + 1); + fflush (stdout); + num_pics_cont = 0; + + g_timeout_add (PREVIEW_TIME_MS, (GSourceFunc) stop_image_preview, camera); + + cont = FALSE; + } + return cont; +} + +static gboolean +me_gst_setup_pipeline_create_post_bin (const gchar * post, gboolean video) +{ + GstElement *vpp = NULL; + GstElement *bin, *c1, *c2, *filter; + GstPad *pad; + GstCaps *caps; + + /* this function uses a bin just because it needs ffmpegcolorspace. For + * performance reason one should provide an element without need for color + * convertion */ + + vpp = gst_element_factory_make (post, NULL); + if (NULL == vpp) { + fprintf (stderr, "cannot create \'%s\' element\n", post); + fflush (stderr); + goto done; + } + c1 = gst_element_factory_make ("ffmpegcolorspace", NULL); + c2 = gst_element_factory_make ("ffmpegcolorspace", NULL); + if (NULL == c1 || NULL == c2) { + fprintf (stderr, "cannot create \'ffmpegcolorspace\' element\n"); + fflush (stderr); + goto done; + } + filter = gst_element_factory_make ("capsfilter", NULL); + if (NULL == filter) { + fprintf (stderr, "cannot create \'capsfilter\' element\n"); + fflush (stderr); + goto done; + } + bin = gst_bin_new (video ? "vid_postproc_bin" : "img_postproc_bin"); + if (NULL == bin) { + goto done; + } + + caps = gst_caps_new_simple ("video/x-raw-yuv", + "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('I', '4', '2', '0'), NULL); + g_object_set (G_OBJECT (filter), "caps", caps, NULL); + gst_caps_unref (caps); + + gst_bin_add_many (GST_BIN (bin), c1, vpp, c2, filter, NULL); + if (!gst_element_link_many (c1, vpp, c2, filter, NULL)) { + fprintf (stderr, "cannot link video post proc elements\n"); + fflush (stderr); + goto done; + } + + pad = gst_element_get_static_pad (c1, "sink"); + gst_element_add_pad (bin, gst_ghost_pad_new ("sink", pad)); + gst_object_unref (GST_OBJECT (pad)); + + pad = gst_element_get_static_pad (filter, "src"); + gst_element_add_pad (bin, gst_ghost_pad_new ("src", pad)); + gst_object_unref (GST_OBJECT (pad)); + + g_object_set (gst_camera_bin, (video ? "videopp" : "imagepp"), bin, NULL); + return TRUE; +done: + return FALSE; +} + +static void +me_gst_setup_pipeline_create_codecs (void) +{ +#ifdef USE_MP4 + g_object_set (gst_camera_bin, "videoenc", + gst_element_factory_make ("omx_mpeg4enc", NULL), NULL); + + g_object_set (gst_camera_bin, "audioenc", + gst_element_factory_make ("omx_aacenc", NULL), NULL); + + g_object_set (gst_camera_bin, "videomux", + gst_element_factory_make ("hantromp4mux", NULL), NULL); +#else + /* using defaults theora, vorbis, ogg */ +#endif +} + +static gboolean +me_gst_setup_pipeline_create_img_post_bin (const gchar * imagepost) +{ + return me_gst_setup_pipeline_create_post_bin (imagepost, FALSE); +} + +static gboolean +me_gst_setup_pipeline_create_vid_post_bin (const gchar * videopost) +{ + return me_gst_setup_pipeline_create_post_bin (videopost, TRUE); +} + +static gboolean +me_gst_setup_pipeline (const gchar * imagepost, const gchar * videopost) +{ + GstBus *bus; + GstCaps *preview_caps; + + set_filename (filename); + + me_gst_cleanup_element (); + + gst_camera_bin = gst_element_factory_make ("camerabin", NULL); + if (NULL == gst_camera_bin) { + goto done; + } + + g_signal_connect (gst_camera_bin, "img-done", + (GCallback) me_image_capture_done, NULL); + + preview_caps = gst_caps_from_string (PREVIEW_CAPS); + + bus = gst_pipeline_get_bus (GST_PIPELINE (gst_camera_bin)); + gst_bus_add_watch (bus, my_bus_callback, NULL); + gst_bus_set_sync_handler (bus, my_bus_sync_callback, NULL); + gst_object_unref (bus); + + /* set properties */ + g_object_set (gst_camera_bin, "filename", filename->str, NULL); + g_object_set (gst_camera_bin, "preview-caps", preview_caps, NULL); + gst_caps_unref (preview_caps); + + gst_videosrc = gst_element_factory_make (CAMERA_APP_VIDEOSRC, NULL); + if (gst_videosrc) { + g_object_set (G_OBJECT (gst_camera_bin), "videosrc", gst_videosrc, NULL); + } + + if (imagepost) { + if (!me_gst_setup_pipeline_create_img_post_bin (imagepost)) + goto done; + } else { + /* Use default image postprocessing element */ + GstElement *ipp = + gst_element_factory_make (CAMERA_APP_IMAGE_POSTPROC, NULL); + if (ipp) { + g_object_set (G_OBJECT (gst_camera_bin), "imagepp", ipp, NULL); + } + } + + if (videopost) { + if (!me_gst_setup_pipeline_create_vid_post_bin (videopost)) + goto done; + } + + me_gst_setup_pipeline_create_codecs (); + + if (GST_STATE_CHANGE_FAILURE == + gst_element_set_state (gst_camera_bin, GST_STATE_READY)) { + goto done; + } + + if (!gst_videosrc) { + g_object_get (G_OBJECT (gst_camera_bin), "videosrc", &gst_videosrc, NULL); + } + + init_view_finder_resolution_combobox (); + + if (GST_STATE_CHANGE_FAILURE == + gst_element_set_state (gst_camera_bin, GST_STATE_PAUSED)) { + goto done; + } else { + gst_element_get_state (gst_camera_bin, NULL, NULL, GST_CLOCK_TIME_NONE); + } + + if (GST_STATE_CHANGE_FAILURE == + gst_element_set_state (gst_camera_bin, GST_STATE_PLAYING)) { + goto done; + } else { + gst_element_get_state (gst_camera_bin, NULL, NULL, GST_CLOCK_TIME_NONE); + } + +#ifdef HAVE_GST_PHOTO_IFACE_H + /* Initialize menus to default settings */ + GtkWidget *sub_menu = + gtk_menu_item_get_submenu (GTK_MENU_ITEM (ui_menuitem_capture)); + gtk_container_foreach (GTK_CONTAINER (sub_menu), sub_menu_initialize, NULL); + sub_menu = + gtk_menu_item_get_submenu (GTK_MENU_ITEM (ui_menuitem_photography)); + gtk_container_foreach (GTK_CONTAINER (sub_menu), sub_menu_initialize, NULL); +#endif + + capture_state = CAP_STATE_IMAGE; + return TRUE; +done: + fprintf (stderr, "error to create pipeline\n"); + fflush (stderr); + me_gst_cleanup_element (); + return FALSE; +} + +static void +me_gst_cleanup_element () +{ + if (gst_camera_bin) { + gst_element_set_state (gst_camera_bin, GST_STATE_NULL); + gst_element_get_state (gst_camera_bin, NULL, NULL, GST_CLOCK_TIME_NONE); + gst_object_unref (gst_camera_bin); + gst_camera_bin = NULL; + + g_list_foreach (video_caps_list, (GFunc) gst_caps_unref, NULL); + g_list_free (video_caps_list); + video_caps_list = NULL; + } +} + +static gboolean +capture_mode_stop () +{ + if (capture_state == CAP_STATE_VIDEO_PAUSED + || capture_state == CAP_STATE_VIDEO_RECORDING) { + return capture_mode_set_state (CAP_STATE_VIDEO_STOPED); + } else { + return TRUE; + } +} + +static void +capture_mode_config_gui () +{ + switch (capture_state) { + case CAP_STATE_IMAGE: + gtk_button_set_label (ui_bnt_shot, "Shot"); + gtk_button_set_label (ui_bnt_pause, "Focus"); + gtk_widget_set_sensitive (GTK_WIDGET (ui_bnt_pause), TRUE); + gtk_widget_show (ui_chk_continous); + gtk_widget_show (ui_chk_rawmsg); + gtk_widget_hide (ui_chk_mute); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ui_rdbntImageCapture), + TRUE); + break; + case CAP_STATE_VIDEO_STOPED: + gtk_button_set_label (ui_bnt_shot, "Rec"); + gtk_button_set_label (ui_bnt_pause, "Pause"); + gtk_widget_set_sensitive (GTK_WIDGET (ui_bnt_pause), FALSE); + gtk_widget_show (GTK_WIDGET (ui_bnt_pause)); + gtk_widget_show (ui_chk_mute); + gtk_widget_hide (ui_chk_continous); + gtk_widget_hide (ui_chk_rawmsg); + gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ui_rdbntVideoCapture), + TRUE); + break; + case CAP_STATE_VIDEO_PAUSED: + gtk_button_set_label (ui_bnt_pause, "Cont"); + break; + case CAP_STATE_VIDEO_RECORDING: + gtk_button_set_label (ui_bnt_shot, "Stop"); + gtk_button_set_label (ui_bnt_pause, "Pause"); + gtk_widget_set_sensitive (GTK_WIDGET (ui_bnt_pause), TRUE); + break; + default: + break; + } +} + +static gboolean +capture_mode_set_state (CaptureState state) +{ + if (capture_state == state) + return TRUE; + + switch (capture_state) { + case CAP_STATE_IMAGE: + if (state == CAP_STATE_VIDEO_PAUSED) { + goto done; + } + g_object_set (gst_camera_bin, "mode", 1, NULL); + capture_state = CAP_STATE_VIDEO_STOPED; + if (state == CAP_STATE_VIDEO_RECORDING) + capture_mode_set_state (state); + break; + case CAP_STATE_VIDEO_STOPED: + if (state == CAP_STATE_VIDEO_PAUSED) { + goto done; + } + capture_state = state; + if (state == CAP_STATE_IMAGE) + g_object_set (gst_camera_bin, "mode", 0, NULL); + else { /* state == CAP_STATE_VIDEO_RECORDING */ + g_object_set (gst_camera_bin, "mode", 1, NULL); + g_signal_emit_by_name (gst_camera_bin, "user-start", 0); + } + break; + case CAP_STATE_VIDEO_PAUSED: + if (state == CAP_STATE_VIDEO_RECORDING) { + g_signal_emit_by_name (gst_camera_bin, "user-start", 0); + capture_state = CAP_STATE_VIDEO_RECORDING; + } else { + g_signal_emit_by_name (gst_camera_bin, "user-stop", 0); + capture_state = CAP_STATE_VIDEO_STOPED; + if (state == CAP_STATE_IMAGE) + capture_mode_set_state (state); + } + break; + case CAP_STATE_VIDEO_RECORDING: + if (state == CAP_STATE_VIDEO_PAUSED) { + g_signal_emit_by_name (gst_camera_bin, "user-pause", 0); + capture_state = CAP_STATE_VIDEO_PAUSED; + } else { + g_signal_emit_by_name (gst_camera_bin, "user-stop", 0); + capture_state = CAP_STATE_VIDEO_STOPED; + if (state == CAP_STATE_IMAGE) + capture_mode_set_state (state); + } + break; + } + return TRUE; +done: + return FALSE; +} + +static void +on_windowMain_delete_event (GtkWidget * widget, GdkEvent * event, gpointer data) +{ + capture_mode_set_state (CAP_STATE_IMAGE); + capture_mode_config_gui (); + me_gst_cleanup_element (); + gtk_main_quit (); +} + +static void +set_metadata (void) +{ + /* for more information about image metadata tags, see: + * http://webcvs.freedesktop.org/gstreamer/gst-plugins-bad/tests/icles/metadata_editor.c + * and for the mapping: + * http://webcvs.freedesktop.org/gstreamer/gst-plugins-bad/ext/metadata/metadata_mapping.htm?view=co + */ + + GstTagSetter *setter = GST_TAG_SETTER (gst_camera_bin); + GTimeVal time = { 0, 0 }; + gchar *date_str, *desc_str; + + g_get_current_time (&time); + date_str = g_time_val_to_iso8601 (&time); /* this is UTC */ + desc_str = g_strdup_printf ("picture taken by %s", g_get_real_name ()); + + gst_tag_setter_add_tags (setter, GST_TAG_MERGE_REPLACE, + "date-time-original", date_str, + "date-time-modified", date_str, + "creator-tool", "camerabin-demo", + GST_TAG_DESCRIPTION, desc_str, + GST_TAG_TITLE, "My picture", GST_TAG_COPYRIGHT, "LGPL", NULL); + + g_free (date_str); + g_free (desc_str); +} + +static void +on_buttonShot_clicked (GtkButton * button, gpointer user_data) +{ + switch (capture_state) { + case CAP_STATE_IMAGE: + { + gtk_widget_set_sensitive (GTK_WIDGET (ui_bnt_shot), FALSE); + set_filename (filename); + num_pics++; + g_object_set (gst_camera_bin, "filename", filename->str, NULL); + + set_metadata (); + g_signal_emit_by_name (gst_camera_bin, "user-start", 0); + } + break; + case CAP_STATE_VIDEO_STOPED: + set_filename (filename); + num_vids++; + g_object_set (gst_camera_bin, "filename", filename->str, NULL); + capture_mode_set_state (CAP_STATE_VIDEO_RECORDING); + capture_mode_config_gui (); + break; + case CAP_STATE_VIDEO_PAUSED: + /* fall trough */ + case CAP_STATE_VIDEO_RECORDING: + capture_mode_set_state (CAP_STATE_VIDEO_STOPED); + capture_mode_config_gui (); + break; + default: + break; + } +} + +static void +on_buttonPause_clicked (GtkButton * button, gpointer user_data) +{ + switch (capture_state) { + case CAP_STATE_IMAGE: + if (g_str_equal (gtk_button_get_label (ui_bnt_pause), "Focus")) { + /* Start autofocus */ + gst_photography_set_autofocus (GST_PHOTOGRAPHY (gst_camera_bin), TRUE); + gtk_button_set_label (ui_bnt_pause, "Cancel Focus"); + } else { + /* Cancel autofocus */ + gst_photography_set_autofocus (GST_PHOTOGRAPHY (gst_camera_bin), FALSE); + gtk_button_set_label (ui_bnt_pause, "Focus"); + } + break; + case CAP_STATE_VIDEO_STOPED: + break; + case CAP_STATE_VIDEO_PAUSED: + capture_mode_set_state (CAP_STATE_VIDEO_RECORDING); + capture_mode_config_gui (); + break; + case CAP_STATE_VIDEO_RECORDING: + capture_mode_set_state (CAP_STATE_VIDEO_PAUSED); + capture_mode_config_gui (); + break; + default: + break; + } +} + +static gboolean +on_drawingareaView_configure_event (GtkWidget * widget, + GdkEventConfigure * event, gpointer data) +{ + Display *display = GDK_WINDOW_XDISPLAY (GDK_WINDOW (widget->window)); + + XMoveResizeWindow (display, GDK_WINDOW_XID (GDK_WINDOW (widget->window)), + widget->allocation.x, widget->allocation.y, + widget->allocation.width, widget->allocation.height); + XSync (display, False); + + return TRUE; +} + +static void +on_comboboxResolution_changed (GtkComboBox * widget, gpointer user_data) +{ + GstStructure *st; + gint w = 0, h = 0; + GstCaps *video_caps = + g_list_nth_data (video_caps_list, gtk_combo_box_get_active (widget)); + + if (video_caps) { + + gst_element_set_state (gst_camera_bin, GST_STATE_READY); + + st = gst_caps_get_structure (video_caps, 0); + + gst_structure_get_int (st, "width", &w); + gst_structure_get_int (st, "height", &h); + + if (w && h) { + g_object_set (ui_drawing_frame, "ratio", (gfloat) w / (gfloat) h, NULL); + } + + g_object_set (G_OBJECT (gst_camera_bin), "filter-caps", video_caps, NULL); + + gst_element_set_state (gst_camera_bin, GST_STATE_PLAYING); + } +} + +static void +on_radiobuttonImageCapture_toggled (GtkToggleButton * togglebutton, + gpointer user_data) +{ + if (gtk_toggle_button_get_active (togglebutton)) { + if (capture_state != CAP_STATE_IMAGE) { + capture_mode_set_state (CAP_STATE_IMAGE); + capture_mode_config_gui (); + } + } +} + +static void +on_radiobuttonVideoCapture_toggled (GtkToggleButton * togglebutton, + gpointer user_data) +{ + if (gtk_toggle_button_get_active (togglebutton)) { + if (capture_state == CAP_STATE_IMAGE) { + capture_mode_set_state (CAP_STATE_VIDEO_STOPED); + capture_mode_config_gui (); + } + } +} + +static void +on_rbBntVidEff_toggled (GtkToggleButton * togglebutton, gchar * effect) +{ + if (gtk_toggle_button_get_active (togglebutton)) { + /* lets also use those effects to image */ + video_post = effect; + image_post = effect; + capture_mode_stop (); + + me_gst_cleanup_element (); + if (!me_gst_setup_pipeline (image_post, video_post)) + gtk_main_quit (); + capture_mode_config_gui (); + } +} + +static void +on_rbBntVidEffNone_toggled (GtkToggleButton * togglebutton, gpointer data) +{ + on_rbBntVidEff_toggled (togglebutton, NULL); +} + +static void +on_rbBntVidEffEdge_toggled (GtkToggleButton * togglebutton, gpointer data) +{ + on_rbBntVidEff_toggled (togglebutton, "edgetv"); +} + +static void +on_rbBntVidEffAging_toggled (GtkToggleButton * togglebutton, gpointer user_data) +{ + on_rbBntVidEff_toggled (togglebutton, "agingtv"); +} + +static void +on_rbBntVidEffDice_toggled (GtkToggleButton * togglebutton, gpointer user_data) +{ + on_rbBntVidEff_toggled (togglebutton, "dicetv"); +} + +static void +on_rbBntVidEffWarp_toggled (GtkToggleButton * togglebutton, gpointer data) +{ + on_rbBntVidEff_toggled (togglebutton, "warptv"); +} + +static void +on_rbBntVidEffShagadelic_toggled (GtkToggleButton * togglebutton, gpointer data) +{ + on_rbBntVidEff_toggled (togglebutton, "shagadelictv"); +} + +static void +on_rbBntVidEffVertigo_toggled (GtkToggleButton * togglebutton, gpointer data) +{ + on_rbBntVidEff_toggled (togglebutton, "vertigotv"); +} + +static void +on_rbBntVidEffRev_toggled (GtkToggleButton * togglebutton, gpointer data) +{ + on_rbBntVidEff_toggled (togglebutton, "revtv"); +} + +static void +on_rbBntVidEffQuark_toggled (GtkToggleButton * togglebutton, gpointer data) +{ + on_rbBntVidEff_toggled (togglebutton, "quarktv"); +} + +static void +on_chkbntMute_toggled (GtkToggleButton * togglebutton, gpointer data) +{ + g_object_set (gst_camera_bin, "mute", + gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (togglebutton)), NULL); +} + +static void +on_chkbtnRawMsg_toggled (GtkToggleButton * togglebutton, gpointer data) +{ + const gchar *env_var = "CAMSRC_PUBLISH_RAW"; + if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (togglebutton))) { + g_setenv (env_var, "1", TRUE); + } else { + g_unsetenv (env_var); + } +} + +static void +on_hscaleZoom_value_changed (GtkRange * range, gpointer user_data) +{ + gint zoom = gtk_range_get_value (range); + g_object_set (gst_camera_bin, "zoom", zoom, NULL); +} + +static void +on_color_control_value_changed (GtkRange * range, gpointer user_data) +{ + GstColorBalance *balance = GST_COLOR_BALANCE (gst_camera_bin); + gint val = gtk_range_get_value (range); + GstColorBalanceChannel *channel = (GstColorBalanceChannel *) user_data; + gst_color_balance_set_value (balance, channel, val); +} + + +gboolean +on_key_released (GtkWidget * widget, GdkEventKey * event, gpointer user_data) +{ + g_return_val_if_fail (event != NULL, FALSE); + + switch (event->keyval) { + case GDK_F11: +#ifdef HAVE_GST_PHOTO_IFACE_H + gst_photography_set_autofocus (GST_PHOTOGRAPHY (gst_camera_bin), FALSE); +#endif + break; + default: + break; + } + + return FALSE; +} + +gboolean +on_key_pressed (GtkWidget * widget, GdkEventKey * event, gpointer user_data) +{ + g_return_val_if_fail (event != NULL, FALSE); + + switch (event->keyval) { + case GDK_F11: +#ifdef HAVE_GST_PHOTO_IFACE_H + gst_photography_set_autofocus (GST_PHOTOGRAPHY (gst_camera_bin), TRUE); +#endif + break; + case 0x0: + on_buttonShot_clicked (NULL, NULL); + break; + default: + break; + } + + return FALSE; +} + +static void +ui_connect_signals (void) +{ + glade_xml_signal_connect (ui_glade_xml, "on_windowMain_delete_event", + (GCallback) on_windowMain_delete_event); + + glade_xml_signal_connect (ui_glade_xml, "on_buttonShot_clicked", + (GCallback) on_buttonShot_clicked); + + glade_xml_signal_connect (ui_glade_xml, "on_buttonPause_clicked", + (GCallback) on_buttonPause_clicked); + + glade_xml_signal_connect (ui_glade_xml, "on_drawingareaView_configure_event", + (GCallback) on_drawingareaView_configure_event); + + glade_xml_signal_connect (ui_glade_xml, "on_comboboxResolution_changed", + (GCallback) on_comboboxResolution_changed); + + glade_xml_signal_connect (ui_glade_xml, "on_radiobuttonImageCapture_toggled", + (GCallback) on_radiobuttonImageCapture_toggled); + + glade_xml_signal_connect (ui_glade_xml, "on_radiobuttonVideoCapture_toggled", + (GCallback) on_radiobuttonVideoCapture_toggled); + + glade_xml_signal_connect (ui_glade_xml, "on_rbBntVidEffNone_toggled", + (GCallback) on_rbBntVidEffNone_toggled); + + glade_xml_signal_connect (ui_glade_xml, "on_rbBntVidEffEdge_toggled", + (GCallback) on_rbBntVidEffEdge_toggled); + + glade_xml_signal_connect (ui_glade_xml, "on_rbBntVidEffAging_toggled", + (GCallback) on_rbBntVidEffAging_toggled); + + glade_xml_signal_connect (ui_glade_xml, "on_rbBntVidEffDice_toggled", + (GCallback) on_rbBntVidEffDice_toggled); + + glade_xml_signal_connect (ui_glade_xml, "on_rbBntVidEffWarp_toggled", + (GCallback) on_rbBntVidEffWarp_toggled); + + glade_xml_signal_connect (ui_glade_xml, "on_rbBntVidEffShagadelic_toggled", + (GCallback) on_rbBntVidEffShagadelic_toggled); + + glade_xml_signal_connect (ui_glade_xml, "on_rbBntVidEffVertigo_toggled", + (GCallback) on_rbBntVidEffVertigo_toggled); + + glade_xml_signal_connect (ui_glade_xml, "on_rbBntVidEffRev_toggled", + (GCallback) on_rbBntVidEffRev_toggled); + + glade_xml_signal_connect (ui_glade_xml, "on_rbBntVidEffQuark_toggled", + (GCallback) on_rbBntVidEffQuark_toggled); + + glade_xml_signal_connect (ui_glade_xml, "on_chkbntMute_toggled", + (GCallback) on_chkbntMute_toggled); + + glade_xml_signal_connect (ui_glade_xml, "on_chkbtnRawMsg_toggled", + (GCallback) on_chkbtnRawMsg_toggled); + + glade_xml_signal_connect (ui_glade_xml, "on_hscaleZoom_value_changed", + (GCallback) on_hscaleZoom_value_changed); + + g_signal_connect (ui_main_window, "key-press-event", + (GCallback) on_key_pressed, NULL); + + g_signal_connect (ui_main_window, "key-release-event", + (GCallback) on_key_released, NULL); +} + +static gchar * +format_value_callback (GtkScale * scale, gdouble value, gpointer user_data) +{ + GstColorBalanceChannel *channel = (GstColorBalanceChannel *) user_data; + + return g_strdup_printf ("%s: %d", channel->label, (gint) value); +} + +static gint +create_menu_items_from_structure (GstStructure * structure) +{ + const GValue *framerate_list = NULL; + const gchar *structure_name; + GString *item_str = NULL; + guint j, num_items_created = 0, num_framerates = 1; + gint w = 0, h = 0, n = 0, d = 1; + guint32 fourcc = 0; + + g_return_val_if_fail (structure != NULL, 0); + + structure_name = gst_structure_get_name (structure); + + /* lets filter yuv only */ + if (0 == strcmp (structure_name, "video/x-raw-yuv")) { + item_str = g_string_new_len ("", 128); + + if (gst_structure_has_field_typed (structure, "format", GST_TYPE_FOURCC)) { + gst_structure_get_fourcc (structure, "format", &fourcc); + } + + if (gst_structure_has_field_typed (structure, "width", GST_TYPE_INT_RANGE)) { + const GValue *wrange = gst_structure_get_value (structure, "width"); + /* If range found, use the maximum */ + w = gst_value_get_int_range_max (wrange); + } else if (gst_structure_has_field_typed (structure, "width", G_TYPE_INT)) { + gst_structure_get_int (structure, "width", &w); + } + + if (gst_structure_has_field_typed (structure, "height", GST_TYPE_INT_RANGE)) { + const GValue *hrange = gst_structure_get_value (structure, "height"); + /* If range found, use the maximum */ + h = gst_value_get_int_range_max (hrange); + } else if (gst_structure_has_field_typed (structure, "height", G_TYPE_INT)) { + gst_structure_get_int (structure, "height", &h); + } + + if (gst_structure_has_field_typed (structure, "framerate", + GST_TYPE_FRACTION)) { + gst_structure_get_fraction (structure, "framerate", &n, &d); + } else if (gst_structure_has_field_typed (structure, "framerate", + GST_TYPE_LIST)) { + framerate_list = gst_structure_get_value (structure, "framerate"); + num_framerates = gst_value_list_get_size (framerate_list); + } else if (gst_structure_has_field_typed (structure, "framerate", + GST_TYPE_FRACTION_RANGE)) { + const GValue *fr = gst_structure_get_value (structure, "framerate"); + const GValue *frmax = gst_value_get_fraction_range_max (fr); + max_fr_n = gst_value_get_fraction_numerator (frmax); + max_fr_d = gst_value_get_fraction_denominator (frmax); + } + + if (max_fr_n || max_fr_d) { + goto range_found; + } + + for (j = 0; j < num_framerates; j++) { + GstCaps *video_caps; + + if (framerate_list) { + const GValue *item = gst_value_list_get_value (framerate_list, j); + n = gst_value_get_fraction_numerator (item); + d = gst_value_get_fraction_denominator (item); + } + g_string_assign (item_str, structure_name); + g_string_append_printf (item_str, " (%" GST_FOURCC_FORMAT ")", + GST_FOURCC_ARGS (fourcc)); + g_string_append_printf (item_str, ", %dx%d at %d/%d", w, h, n, d); + gtk_combo_box_append_text (ui_cbbox_resolution, item_str->str); + + video_caps = + gst_caps_new_simple (structure_name, "format", GST_TYPE_FOURCC, + fourcc, + "width", G_TYPE_INT, w, "height", G_TYPE_INT, h, + "framerate", GST_TYPE_FRACTION, n, d, NULL); + video_caps_list = g_list_append (video_caps_list, video_caps); + num_items_created++; + } + } + +range_found: + + if (item_str) { + g_string_free (item_str, TRUE); + } + + return num_items_created; +} + +static void +fill_resolution_combo (GstCaps * caps) +{ + guint size, num_items, i; + GstStructure *st; + + max_fr_n = max_fr_d = 0; + + /* Create new items */ + size = gst_caps_get_size (caps); + + for (i = 0; i < size; i++) { + st = gst_caps_get_structure (caps, i); + num_items = create_menu_items_from_structure (st); + ui_cbbox_resolution_count += num_items; + } +} + +static GstCaps * +create_default_caps () +{ + GstCaps *default_caps; + + default_caps = gst_caps_from_string (DEFAULT_VF_CAPS); + + return default_caps; +} + +static void +init_view_finder_resolution_combobox () +{ + GstCaps *input_caps = NULL, *default_caps = NULL, *intersect = NULL; + + g_object_get (gst_camera_bin, "inputcaps", &input_caps, NULL); + if (input_caps) { + fill_resolution_combo (input_caps); + } + + /* Fill in default items if supported */ + default_caps = create_default_caps (); + intersect = gst_caps_intersect (default_caps, input_caps); + if (intersect) { + fill_resolution_combo (intersect); + gst_caps_unref (intersect); + } + gst_caps_unref (default_caps); + + if (input_caps) { + gst_caps_unref (input_caps); + } + + /* Set some item active */ + gtk_combo_box_set_active (ui_cbbox_resolution, ui_cbbox_resolution_count - 1); +} + +static void +destroy_color_controls () +{ + GList *widgets, *item; + GtkWidget *widget = NULL; + + widgets = gtk_container_get_children (GTK_CONTAINER (ui_vbox_color_controls)); + for (item = widgets; item; item = g_list_next (item)) { + widget = GTK_WIDGET (item->data); + g_signal_handlers_disconnect_by_func (widget, (GFunc) format_value_callback, + g_object_get_data (G_OBJECT (widget), "channel")); + g_signal_handlers_disconnect_by_func (widget, + (GFunc) on_color_control_value_changed, + g_object_get_data (G_OBJECT (widget), "channel")); + gtk_container_remove (GTK_CONTAINER (ui_vbox_color_controls), widget); + } + g_list_free (widgets); +} + +static void +create_color_controls () +{ + GstColorBalance *balance = NULL; + const GList *controls, *item; + GstColorBalanceChannel *channel; + GtkWidget *hscale; + + if (GST_IS_COLOR_BALANCE (gst_camera_bin)) { + balance = GST_COLOR_BALANCE (gst_camera_bin); + } + + if (NULL == balance) { + goto done; + } + + controls = gst_color_balance_list_channels (balance); + for (item = controls; item; item = g_list_next (item)) { + channel = item->data; + + hscale = gtk_hscale_new ((GtkAdjustment *) + gtk_adjustment_new (gst_color_balance_get_value (balance, channel), + channel->min_value, channel->max_value, 1, 10, 10)); + + g_signal_connect (GTK_RANGE (hscale), "value-changed", + (GCallback) on_color_control_value_changed, (gpointer) channel); + g_signal_connect (GTK_SCALE (hscale), "format-value", + (GCallback) format_value_callback, (gpointer) channel); + g_object_set_data (G_OBJECT (hscale), "channel", (gpointer) channel); + + gtk_box_pack_start (GTK_BOX (ui_vbox_color_controls), GTK_WIDGET (hscale), + FALSE, TRUE, 0); + } + + gtk_widget_show_all (ui_vbox_color_controls); +done: + return; +} + +#ifdef HAVE_GST_PHOTO_IFACE_H +static void +menuitem_toggle_active (GtkWidget * widget, gpointer data) +{ + gboolean active; + g_object_get (G_OBJECT (widget), "active", &active, NULL); + if (active) { + gtk_check_menu_item_toggled (GTK_CHECK_MENU_ITEM (widget)); + } +} + +static void +sub_menu_initialize (GtkWidget * widget, gpointer data) +{ + GtkWidget *submenu; + submenu = gtk_menu_item_get_submenu (GTK_MENU_ITEM (widget)); + gtk_container_foreach (GTK_CONTAINER (submenu), menuitem_toggle_active, NULL); +} + +void +photo_menuitem_toggled_cb (GtkRadioMenuItem * menuitem, gpointer user_data) +{ + gboolean active = FALSE, ret = FALSE; + GEnumClass *eclass = (GEnumClass *) user_data; + GType etype = G_ENUM_CLASS_TYPE (eclass); + GEnumValue *val; + gint set_value = -1; + + /* Get value using menu item name */ + val = + g_enum_get_value_by_nick (eclass, + gtk_widget_get_name (GTK_WIDGET (menuitem))); + + g_object_get (G_OBJECT (menuitem), "active", &active, NULL); + if (active) { + if (etype == GST_TYPE_WHITE_BALANCE_MODE) { + GstWhiteBalanceMode mode; + ret = + gst_photography_set_white_balance_mode (GST_PHOTOGRAPHY + (gst_camera_bin), val->value); + gst_photography_get_white_balance_mode (GST_PHOTOGRAPHY (gst_camera_bin), + &mode); + set_value = (gint) mode; + } else if (etype == GST_TYPE_SCENE_MODE) { + GstSceneMode mode; + ret = + gst_photography_set_scene_mode (GST_PHOTOGRAPHY (gst_camera_bin), + val->value); + gst_photography_get_scene_mode (GST_PHOTOGRAPHY (gst_camera_bin), &mode); + set_value = (gint) mode; + } else if (etype == GST_TYPE_COLOUR_TONE_MODE) { + GstColourToneMode mode; + ret = + gst_photography_set_colour_tone_mode (GST_PHOTOGRAPHY + (gst_camera_bin), val->value); + gst_photography_get_colour_tone_mode (GST_PHOTOGRAPHY (gst_camera_bin), + &mode); + set_value = (gint) mode; + } else if (etype == GST_TYPE_FLASH_MODE) { + GstFlashMode mode; + ret = + gst_photography_set_flash_mode (GST_PHOTOGRAPHY (gst_camera_bin), + val->value); + gst_photography_get_flash_mode (GST_PHOTOGRAPHY (gst_camera_bin), &mode); + set_value = (gint) mode; + } + + if (!ret) { + g_print ("%s setting failed\n", val->value_name); + } else if (val->value != set_value) { + g_print ("%s setting failed, got %d\n", val->value_nick, set_value); + } + } +} + +void +photo_iso_speed_toggled_cb (GtkRadioMenuItem * menuitem, gpointer user_data) +{ + gboolean active; + const gchar *name; + guint val = 0, set_val = G_MAXUINT; + + g_object_get (G_OBJECT (menuitem), "active", &active, NULL); + if (active) { + name = gtk_widget_get_name (GTK_WIDGET (menuitem)); + /* iso auto setting = 0 */ + /* FIXME: check what values other than 0 can be set */ + if (!g_str_equal (name, "auto")) { + sscanf (name, "%d", &val); + } + if (!gst_photography_set_iso_speed (GST_PHOTOGRAPHY (gst_camera_bin), val)) { + g_print ("ISO speed (%d) setting failed\n", val); + } else { + gst_photography_get_iso_speed (GST_PHOTOGRAPHY (gst_camera_bin), + &set_val); + if (val != set_val) { + g_print ("ISO speed (%d) setting failed, got %d\n", val, set_val); + } + } + } +} + +void +photo_ev_comp_toggled_cb (GtkRadioMenuItem * menuitem, gpointer user_data) +{ + gboolean active; + const gchar *name; + gfloat val = 0.0, set_val = G_MAXFLOAT; + + g_object_get (G_OBJECT (menuitem), "active", &active, NULL); + if (active) { + name = gtk_widget_get_name (GTK_WIDGET (menuitem)); + sscanf (name, "%f", &val); + if (!gst_photography_set_ev_compensation (GST_PHOTOGRAPHY (gst_camera_bin), + val)) { + g_print ("EV compensation (%.1f) setting failed\n", val); + } else { + gst_photography_get_ev_compensation (GST_PHOTOGRAPHY (gst_camera_bin), + &set_val); + if (val != set_val) { + g_print ("EV compensation (%.1f) setting failed, got %.1f\n", val, + set_val); + } + } + } +} + +static void +photo_add_submenu_from_enum (GtkMenuItem * parent_item, GType enum_type) +{ + GTypeClass *tclass; + GEnumClass *eclass; + GtkWidget *new_item = NULL, *new_submenu = NULL; + guint i; + GEnumValue *val; + GSList *group = NULL; + + g_return_if_fail (parent_item && enum_type && G_TYPE_IS_CLASSED (enum_type)); + + tclass = g_type_class_ref (enum_type); + eclass = G_ENUM_CLASS (tclass); + new_submenu = gtk_menu_new (); + + for (i = 0; i < eclass->n_values; i++) { + val = g_enum_get_value (eclass, i); + new_item = gtk_radio_menu_item_new_with_label (group, val->value_nick); + /* Store enum nick as the menu item name */ + gtk_widget_set_name (new_item, val->value_nick); + group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (new_item)); + g_signal_connect (new_item, "toggled", + (GCallback) photo_menuitem_toggled_cb, eclass); + gtk_menu_shell_append (GTK_MENU_SHELL (new_submenu), new_item); + gtk_widget_show (new_item); + } + + gtk_menu_item_set_submenu (parent_item, new_submenu); + g_type_class_unref (tclass); +} + +static void +add_submenu_from_list (GtkMenuItem * parent_item, GList * labels, + GCallback toggled_cb) +{ + GtkWidget *new_item = NULL, *new_submenu = NULL; + GSList *group = NULL; + GList *l; + + new_submenu = gtk_menu_new (); + + for (l = labels; l != NULL; l = g_list_next (l)) { + const gchar *label = l->data; + new_item = gtk_radio_menu_item_new_with_label (group, label); + if (g_str_equal (label, "0")) { + /* Let's set zero as default */ + gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM (new_item), TRUE); + } + gtk_widget_set_name (new_item, label); + group = gtk_radio_menu_item_get_group (GTK_RADIO_MENU_ITEM (new_item)); + g_signal_connect (new_item, "toggled", toggled_cb, NULL); + gtk_menu_shell_append (GTK_MENU_SHELL (new_submenu), new_item); + gtk_widget_show (new_item); + } + + gtk_menu_item_set_submenu (parent_item, new_submenu); +} + +static GtkMenuItem * +add_menuitem (GtkMenu * parent_menu, const gchar * item_name) +{ + GtkWidget *new_item; + + new_item = gtk_menu_item_new_with_label (item_name); + gtk_menu_shell_append (GTK_MENU_SHELL (parent_menu), new_item); + gtk_widget_show (new_item); + + return GTK_MENU_ITEM (new_item); +} + +GList * +create_iso_speed_labels () +{ + GList *labels = NULL; + gint i; + for (i = 0; i < G_N_ELEMENTS (iso_speed_labels); i++) { + labels = g_list_append (labels, iso_speed_labels[i]); + } + return labels; +} + +GList * +create_ev_comp_labels () +{ + GList *labels = NULL; + gdouble comp; + char buf[G_ASCII_DTOSTR_BUF_SIZE]; + + for (comp = EV_COMP_MIN; comp <= EV_COMP_MAX; comp += EV_COMP_STEP) { + g_ascii_dtostr (buf, sizeof (buf), comp); + labels = g_list_append (labels, g_strdup (buf)); + } + return labels; +} + +static void +fill_photography_menu (GtkMenuItem * parent_item) +{ + GtkWidget *photo_menu = gtk_menu_new (); + GtkMenuItem *item = NULL; + GList *labels = NULL; + + /* Add menu items and create and associate submenus to each item */ + item = add_menuitem (GTK_MENU (photo_menu), "AWB"); + photo_add_submenu_from_enum (item, GST_TYPE_WHITE_BALANCE_MODE); + + item = add_menuitem (GTK_MENU (photo_menu), "Colour Tone"); + photo_add_submenu_from_enum (item, GST_TYPE_COLOUR_TONE_MODE); + + item = add_menuitem (GTK_MENU (photo_menu), "Scene"); + photo_add_submenu_from_enum (item, GST_TYPE_SCENE_MODE); + + item = add_menuitem (GTK_MENU (photo_menu), "Flash"); + photo_add_submenu_from_enum (item, GST_TYPE_FLASH_MODE); + + item = add_menuitem (GTK_MENU (photo_menu), "ISO"); + labels = create_iso_speed_labels (); + add_submenu_from_list (item, labels, (GCallback) photo_iso_speed_toggled_cb); + g_list_free (labels); + + item = add_menuitem (GTK_MENU (photo_menu), "EV comp"); + labels = create_ev_comp_labels (); + add_submenu_from_list (item, labels, (GCallback) photo_ev_comp_toggled_cb); + g_list_free (labels); + + gtk_menu_item_set_submenu (parent_item, photo_menu); +} + +void +capture_image_res_toggled_cb (GtkRadioMenuItem * menuitem, gpointer user_data) +{ + gboolean active; + const gchar *label; + gint i; + + g_object_get (G_OBJECT (menuitem), "active", &active, NULL); + if (active) { + label = gtk_widget_get_name (GTK_WIDGET (menuitem)); + /* Look for width and height corresponding to the label */ + for (i = 0; i < G_N_ELEMENTS (image_resolution_label_map); i++) { + if (g_str_equal (label, image_resolution_label_map[i].label)) { + /* set found values */ + g_signal_emit_by_name (gst_camera_bin, "user-image-res", + image_resolution_label_map[i].width, + image_resolution_label_map[i].height, 0); + break; + } + } + } +} + +GList * +create_image_resolution_labels () +{ + GList *labels = NULL; + int i; + for (i = 0; i < G_N_ELEMENTS (image_resolution_label_map); i++) { + labels = g_list_append (labels, image_resolution_label_map[i].label); + } + return labels; +} + +static void +fill_capture_menu (GtkMenuItem * parent_item) +{ + GtkWidget *capture_menu = gtk_menu_new (); + GtkMenuItem *item = NULL; + GList *labels = NULL; + + /* Add menu items and create and associate submenus to each item */ + item = add_menuitem (GTK_MENU (capture_menu), "Image resolution"); + + labels = create_image_resolution_labels (); + add_submenu_from_list (item, labels, + (GCallback) capture_image_res_toggled_cb); + g_list_free (labels); + + gtk_menu_item_set_submenu (parent_item, capture_menu); +} +#endif /* HAVE_GST_PHOTO_IFACE_H */ + +static gboolean +ui_create (void) +{ + gchar *gladefile = DEFAULT_GLADE_FILE; + + if (!g_file_test (gladefile, G_FILE_TEST_EXISTS)) { + gladefile = SHARED_GLADE_FILE; + } + + ui_glade_xml = glade_xml_new (gladefile, NULL, NULL); + if (!ui_glade_xml) { + fprintf (stderr, "glade_xml_new failed for %s\n", gladefile); + fflush (stderr); + goto done; + } + + ui_main_window = glade_xml_get_widget (ui_glade_xml, "windowMain"); + ui_drawing = glade_xml_get_widget (ui_glade_xml, "drawingareaView"); + ui_drawing_frame = glade_xml_get_widget (ui_glade_xml, "drawingareaFrame"); + ui_chk_continous = glade_xml_get_widget (ui_glade_xml, "chkbntContinous"); + ui_chk_rawmsg = glade_xml_get_widget (ui_glade_xml, "chkbtnRawMsg"); + ui_bnt_shot = GTK_BUTTON (glade_xml_get_widget (ui_glade_xml, "buttonShot")); + ui_bnt_pause = + GTK_BUTTON (glade_xml_get_widget (ui_glade_xml, "buttonPause")); + ui_cbbox_resolution = + GTK_COMBO_BOX (glade_xml_get_widget (ui_glade_xml, "comboboxResolution")); + ui_chk_mute = glade_xml_get_widget (ui_glade_xml, "chkbntMute"); + ui_vbox_color_controls = glade_xml_get_widget (ui_glade_xml, + "vboxColorControls"); + ui_rdbntImageCapture = glade_xml_get_widget (ui_glade_xml, + "radiobuttonImageCapture"); + ui_rdbntVideoCapture = glade_xml_get_widget (ui_glade_xml, + "radiobuttonVideoCapture"); + + ui_menuitem_photography = glade_xml_get_widget (ui_glade_xml, + "menuitemPhotography"); + ui_menuitem_capture = glade_xml_get_widget (ui_glade_xml, "menuitemCapture"); +#ifdef HAVE_GST_PHOTO_IFACE_H + if (ui_menuitem_photography) { + fill_photography_menu (GTK_MENU_ITEM (ui_menuitem_photography)); + } + + if (ui_menuitem_capture) { + fill_capture_menu (GTK_MENU_ITEM (ui_menuitem_capture)); + } +#endif + if (!(ui_main_window && ui_drawing && ui_chk_continous && ui_bnt_shot && + ui_bnt_pause && ui_cbbox_resolution && ui_chk_mute && + ui_vbox_color_controls && ui_rdbntImageCapture && + ui_rdbntVideoCapture && ui_chk_rawmsg && ui_menuitem_photography && + ui_menuitem_capture)) { + fprintf (stderr, "Some widgets couldn't be created\n"); + fflush (stderr); + goto done; + } + + gtk_widget_set_double_buffered (ui_drawing, FALSE); + ui_connect_signals (); + gtk_widget_show_all (ui_main_window); + capture_mode_config_gui (); + return TRUE; +done: + return FALSE; +} + +/* + * main + */ + +int +main (int argc, char *argv[]) +{ + int ret = 0; + + gst_init (&argc, &argv); + gtk_init (&argc, &argv); + + filename = g_string_new_len ("", 16); + + /* create UI */ + if (!ui_create ()) { + ret = -1; + goto done; + } + /* create pipeline and run */ + if (me_gst_setup_pipeline (NULL, NULL)) { + gtk_main (); + } + +done: + me_gst_cleanup_element (); + g_string_free (filename, TRUE); + return ret; +} diff --git a/tests/examples/camerabin/gst-camera.glade b/tests/examples/camerabin/gst-camera.glade new file mode 100644 index 00000000..5230c832 --- /dev/null +++ b/tests/examples/camerabin/gst-camera.glade @@ -0,0 +1,397 @@ + + + + + + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + gst-camera + + + + True + + + True + + + True + + + True + Photography + True + + + True + + + + + + + True + Capture + True + + + + + False + + + + + True + + + + + 1 + + + + + False + + + + + True + + + True + True + Image capture + True + 0 + True + True + + + + + + True + True + Video rec + True + 0 + True + True + radiobuttonImageCapture + + + + 1 + + + + + True + True + Shot + True + 0 + + + + 2 + + + + + True + True + Pause + True + 0 + + + + 3 + + + + + True + True + mute + True + 0 + True + + + + 4 + + + + + True + True + continous + True + 0 + True + + + 5 + + + + + True + True + Send raw image after still image capture as gstreamer message + raw msg + True + 0 + True + + + + 6 + + + + + False + 1 + + + + + True + 1 + 3 + + + True + + + True + video effects: + + + + + True + True + none + True + 0 + True + True + + + + 1 + + + + + True + True + edged + True + 0 + True + True + rbBntVidEffNone + + + + 2 + + + + + True + True + aging + True + 0 + True + True + rbBntVidEffNone + + + + 3 + + + + + True + True + dice + True + 0 + True + True + rbBntVidEffNone + + + + 4 + + + + + True + True + warp + True + 0 + True + True + rbBntVidEffNone + + + + 5 + + + + + True + True + shagadelic + True + 0 + True + True + rbBntVidEffNone + + + + 6 + + + + + True + True + vertigo + True + 0 + True + True + rbBntVidEffNone + + + + 7 + + + + + True + True + rev + True + 0 + True + True + rbBntVidEffNone + + + + 8 + + + + + True + True + quark + True + 0 + True + True + rbBntVidEffNone + + + + 9 + + + + + + + + + + 200 + 200 + True + True + GTK_POLICY_AUTOMATIC + GTK_POLICY_AUTOMATIC + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + True + + + + + + + 2 + 3 + + + + + + True + 0 + GTK_SHADOW_NONE + 1 + False + + + True + + + True + GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK + + + + + + + + 1 + 2 + + + + + 2 + + + + + True + True + 100 100 1100 10 100 100 + 0 + GTK_POS_LEFT + + + + False + 3 + + + + + + -- cgit v1.2.1 From a97139190657fa5e744e802bed54a319ec4f0bfa Mon Sep 17 00:00:00 2001 From: Stefan Kost Date: Fri, 12 Jun 2009 14:26:24 +0300 Subject: camerabin: code cruft removal and debug logs Remove unused code. Add lots of debug loging. Change comments for local functions to not use /** gtk-doc start style. --- gst/camerabin/camerabingeneral.c | 74 +++------------------------------------- gst/camerabin/camerabingeneral.h | 32 ++--------------- gst/camerabin/camerabinimage.c | 24 ++++++++----- gst/camerabin/camerabinvideo.c | 31 ++++++++++------- gst/camerabin/gstcamerabin.c | 65 +++++++++++++++++++++++++++-------- 5 files changed, 92 insertions(+), 134 deletions(-) diff --git a/gst/camerabin/camerabingeneral.c b/gst/camerabin/camerabingeneral.c index d9d9a202..ba6b82a9 100644 --- a/gst/camerabin/camerabingeneral.c +++ b/gst/camerabin/camerabingeneral.c @@ -32,74 +32,6 @@ GST_DEBUG_CATEGORY (gst_camerabin_debug); -static gboolean -camerabin_general_dbg_have_event (GstPad * pad, GstEvent * event, - gpointer u_data) -{ - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_NEWSEGMENT: - { - GstElement *elem = (GstElement *) u_data; - gchar *elem_name = gst_element_get_name (elem); - gchar *pad_name = gst_pad_get_name (pad); - - gboolean update; - gdouble rate; - GstFormat format; - gint64 start, stop, pos; - gst_event_parse_new_segment (event, &update, &rate, &format, &start, - &stop, &pos); - - GST_DEBUG ("element %s, pad %s, new_seg_start =%" GST_TIME_FORMAT - ", new_seg_stop =%" GST_TIME_FORMAT - ", new_seg_pos =%" GST_TIME_FORMAT "\n", elem_name, pad_name, - GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (pos)); - - g_free (pad_name); - g_free (elem_name); - } - break; - default: - break; - } - - return TRUE; -} - -static gboolean -camerabin_general_dbg_have_buffer (GstPad * pad, GstBuffer * buffer, - gpointer u_data) -{ - GstElement *elem = (GstElement *) u_data; - gchar *elem_name = gst_element_get_name (elem); - gchar *pad_name = gst_pad_get_name (pad); - - GST_DEBUG ("element %s, pad %s, buf_ts =%" GST_TIME_FORMAT "\n", elem_name, - pad_name, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer))); - - g_free (pad_name); - g_free (elem_name); - - return TRUE; - -} - -void -camerabin_general_dbg_set_probe (GstElement * elem, gchar * pad_name, - gboolean buf, gboolean evt) -{ - GstPad *pad = gst_element_get_static_pad (elem, pad_name); - - if (buf) - gst_pad_add_buffer_probe (pad, - G_CALLBACK (camerabin_general_dbg_have_buffer), elem); - if (evt) - gst_pad_add_event_probe (pad, - G_CALLBACK (camerabin_general_dbg_have_event), elem); - - gst_object_unref (pad); -} - /** * gst_camerabin_add_element: * @bin: add an element to this bin @@ -151,12 +83,12 @@ gst_camerabin_try_add_element (GstBin * bin, GstElement * new_elem) /* Get pads for linking */ bin_pad = gst_bin_find_unlinked_pad (bin, GST_PAD_SRC); - GST_DEBUG ("adding %" GST_PTR_FORMAT " to %s:%s", new_elem, - GST_DEBUG_PAD_NAME (bin_pad)); /* Add to bin */ gst_bin_add (GST_BIN (bin), new_elem); /* Link, if unconnected pad was found, otherwise just add it to bin */ if (bin_pad) { + GST_DEBUG_OBJECT (bin, "linking %s to %s:%s", GST_OBJECT_NAME (new_elem), + GST_DEBUG_PAD_NAME (bin_pad)); bin_elem = gst_pad_get_parent_element (bin_pad); gst_object_unref (bin_pad); if (!gst_element_link (bin_elem, new_elem)) { @@ -164,6 +96,8 @@ gst_camerabin_try_add_element (GstBin * bin, GstElement * new_elem) ret = FALSE; } gst_object_unref (bin_elem); + } else { + GST_INFO_OBJECT (bin, "no unlinked source pad in bin"); } return ret; diff --git a/gst/camerabin/camerabingeneral.h b/gst/camerabin/camerabingeneral.h index a84ab64b..13eea756 100644 --- a/gst/camerabin/camerabingeneral.h +++ b/gst/camerabin/camerabingeneral.h @@ -21,43 +21,17 @@ #ifndef __CAMERABIN_GENERAL_H_ #define __CAMERABIN_GENERAL_H_ -#ifdef HAVE_SYS_TIME_H -#include -#endif -#include - #include - -typedef struct timeval TIME_TYPE; -#define GET_TIME(t) do { gettimeofday(&(t), NULL); } while(0) -#define DIFF_TIME(t2,t1,d) do { d = ((t2).tv_sec - (t1).tv_sec) * 1000000 + \ - (t2).tv_usec - (t1).tv_usec; } while(0) - -#define _INIT_TIMER_BLOCK TIME_TYPE t1, t2; guint32 d; do {;}while (0) - -#define _OPEN_TIMER_BLOCK { GET_TIME(t1); do {;}while (0) -#define _CLOSE_TIMER_BLOCK GET_TIME(t2); DIFF_TIME(t2,t1,d); \ - GST_DEBUG("elapsed time = %u\n", d); \ - } do {;}while (0) - - -extern void -camerabin_general_dbg_set_probe (GstElement * elem, gchar * pad_name, - gboolean buf, gboolean evt); - gboolean gst_camerabin_try_add_element (GstBin * bin, GstElement * new_elem); - gboolean gst_camerabin_add_element (GstBin * bin, GstElement * new_elem); - -GstElement *gst_camerabin_create_and_add_element (GstBin * bin, - const gchar * elem_name); +GstElement *gst_camerabin_create_and_add_element (GstBin * bin, const gchar * elem_name); void gst_camerabin_remove_elements_from_bin (GstBin * bin); -gboolean -gst_camerabin_drop_eos_probe (GstPad * pad, GstEvent * event, gpointer u_data); +gboolean gst_camerabin_drop_eos_probe (GstPad * pad, GstEvent * event, gpointer u_data); +/* debug logging category */ GST_DEBUG_CATEGORY_EXTERN (gst_camerabin_debug); #define GST_CAT_DEFAULT gst_camerabin_debug diff --git a/gst/camerabin/camerabinimage.c b/gst/camerabin/camerabinimage.c index da979f0f..8eea8d91 100644 --- a/gst/camerabin/camerabinimage.c +++ b/gst/camerabin/camerabinimage.c @@ -162,6 +162,8 @@ gst_camerabin_image_init (GstCameraBinImage * img, static void gst_camerabin_image_dispose (GstCameraBinImage * img) { + GST_DEBUG_OBJECT (img, "disposing"); + g_string_free (img->filename, TRUE); img->filename = NULL; @@ -184,7 +186,10 @@ gst_camerabin_image_change_state (GstElement * element, { GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; GstCameraBinImage *img = GST_CAMERABIN_IMAGE (element); - GstObject *camerabin = NULL; + + GST_DEBUG_OBJECT (element, "changing state: %s -> %s", + gst_element_state_get_name (GST_STATE_TRANSITION_CURRENT (transition)), + gst_element_state_get_name (GST_STATE_TRANSITION_NEXT (transition))); switch (transition) { case GST_STATE_CHANGE_NULL_TO_READY: @@ -221,12 +226,10 @@ gst_camerabin_image_change_state (GstElement * element, switch (transition) { case GST_STATE_CHANGE_PAUSED_TO_PLAYING: - camerabin = gst_element_get_parent (img); /* Write debug graph to file */ - GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (camerabin), + GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (GST_ELEMENT_PARENT (img)), GST_DEBUG_GRAPH_SHOW_MEDIA_TYPE | GST_DEBUG_GRAPH_SHOW_NON_DEFAULT_PARAMS, "imagebin.playing"); - gst_object_unref (camerabin); break; case GST_STATE_CHANGE_READY_TO_NULL: gst_camerabin_image_destroy_elements (img); @@ -235,6 +238,11 @@ gst_camerabin_image_change_state (GstElement * element, break; } + GST_DEBUG_OBJECT (element, "changed state: %s -> %s = %s", + gst_element_state_get_name (GST_STATE_TRANSITION_CURRENT (transition)), + gst_element_state_get_name (GST_STATE_TRANSITION_NEXT (transition)), + gst_element_state_change_return_get_name (ret)); + return ret; } @@ -308,7 +316,7 @@ gst_camerabin_image_get_property (GObject * object, guint prop_id, * static helper functions implementation */ -/** +/* * metadata_write_probe: * @pad: sink pad of metadata muxer * @buffer: received buffer @@ -375,7 +383,7 @@ done: } -/** +/* * gst_camerabin_image_create_elements: * @img: a pointer to #GstCameraBinImage object * @@ -480,7 +488,7 @@ done: } -/** +/* * gst_camerabin_image_destroy_elements: * @img: a pointer to #GstCameraBinImage object * @@ -491,7 +499,7 @@ done: static void gst_camerabin_image_destroy_elements (GstCameraBinImage * img) { - GST_LOG ("destroying img elements"); + GST_LOG ("destroying image elements"); gst_ghost_pad_set_target (GST_GHOST_PAD (img->sinkpad), NULL); diff --git a/gst/camerabin/camerabinvideo.c b/gst/camerabin/camerabinvideo.c index fef9ac26..d3de662e 100644 --- a/gst/camerabin/camerabinvideo.c +++ b/gst/camerabin/camerabinvideo.c @@ -242,11 +242,12 @@ gst_camerabin_video_set_property (GObject * object, guint prop_id, switch (prop_id) { case PROP_FILENAME: g_string_assign (bin->filename, g_value_get_string (value)); + GST_INFO_OBJECT (bin, "received filename: '%s'", bin->filename->str); if (bin->sink) { g_object_set (G_OBJECT (bin->sink), "location", bin->filename->str, NULL); } else { - GST_INFO ("no sink, not setting name yet"); + GST_INFO_OBJECT (bin, "no sink, not setting name yet"); } break; default: @@ -290,7 +291,10 @@ gst_camerabin_video_change_state (GstElement * element, { GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; GstCameraBinVideo *vid = GST_CAMERABIN_VIDEO (element); - GstObject *camerabin = NULL; + + GST_DEBUG_OBJECT (element, "changing state: %s -> %s", + gst_element_state_get_name (GST_STATE_TRANSITION_CURRENT (transition)), + gst_element_state_get_name (GST_STATE_TRANSITION_NEXT (transition))); switch (transition) { case GST_STATE_CHANGE_NULL_TO_READY: @@ -314,7 +318,7 @@ gst_camerabin_video_change_state (GstElement * element, case GST_STATE_CHANGE_PAUSED_TO_READY: /* Set sink to NULL in order to write the file _now_ */ - GST_INFO ("write vid file: %s", vid->filename->str); + GST_INFO ("write video file: %s", vid->filename->str); gst_element_set_locked_state (vid->sink, TRUE); gst_element_set_state (vid->sink, GST_STATE_NULL); break; @@ -326,12 +330,10 @@ gst_camerabin_video_change_state (GstElement * element, switch (transition) { case GST_STATE_CHANGE_PAUSED_TO_PLAYING: - camerabin = gst_element_get_parent (vid); /* Write debug graph to file */ - GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (camerabin), + GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (GST_ELEMENT_PARENT (vid)), GST_DEBUG_GRAPH_SHOW_MEDIA_TYPE | GST_DEBUG_GRAPH_SHOW_NON_DEFAULT_PARAMS, "videobin.playing"); - gst_object_unref (camerabin); if (vid->pending_eos) { /* Video bin is still paused, so push eos directly to video queue */ @@ -359,6 +361,11 @@ gst_camerabin_video_change_state (GstElement * element, break; } + GST_DEBUG_OBJECT (element, "changed state: %s -> %s = %s", + gst_element_state_get_name (GST_STATE_TRANSITION_CURRENT (transition)), + gst_element_state_get_name (GST_STATE_TRANSITION_NEXT (transition)), + gst_element_state_change_return_get_name (ret)); + return ret; } @@ -366,7 +373,7 @@ gst_camerabin_video_change_state (GstElement * element, * static helper functions implementation */ -/** +/* * camerabin_video_pad_tee_src0_have_buffer: * @pad: tee src pad leading to video encoding * @event: received buffer @@ -414,7 +421,7 @@ camerabin_video_pad_tee_src0_have_buffer (GstPad * pad, GstBuffer * buffer, return TRUE; } -/** +/* * camerabin_video_pad_aud_src_have_buffer: * @pad: audio source src pad * @event: received buffer @@ -455,7 +462,7 @@ camerabin_video_pad_aud_src_have_buffer (GstPad * pad, GstBuffer * buffer, return TRUE; } -/** +/* * camerabin_video_sink_have_event: * @pad: video bin sink pad * @event: received event @@ -498,7 +505,7 @@ camerabin_video_sink_have_event (GstPad * pad, GstEvent * event, return ret; } -/** +/* * gst_camerabin_video_create_elements: * @vid: a pointer to #GstCameraBinVideo * @@ -675,7 +682,7 @@ error: } -/** +/* * gst_camerabin_video_destroy_elements: * @vid: a pointer to #GstCameraBinVideo * @@ -716,8 +723,6 @@ gst_camerabin_video_destroy_elements (GstCameraBinVideo * vid) gst_event_unref (vid->pending_eos); vid->pending_eos = NULL; } - - return; } /* diff --git a/gst/camerabin/gstcamerabin.c b/gst/camerabin/gstcamerabin.c index f1cd897a..ca2e8e18 100644 --- a/gst/camerabin/gstcamerabin.c +++ b/gst/camerabin/gstcamerabin.c @@ -207,7 +207,11 @@ static guint camerabin_signals[LAST_SIGNAL]; #define DEFAULT_CAPTURE_HEIGHT 600 #define DEFAULT_FPS_N 0 /* makes it use the default */ #define DEFAULT_FPS_D 1 + #define CAMERABIN_DEFAULT_VF_CAPS "video/x-raw-yuv,format=(fourcc)I420" +#define CAMERABIN_MAX_VF_WIDTH 848 +#define CAMERABIN_MAX_VF_HEIGHT 848 + /* Using "bilinear" as default zoom method */ #define CAMERABIN_DEFAULT_ZOOM_METHOD 1 @@ -215,19 +219,20 @@ static guint camerabin_signals[LAST_SIGNAL]; #define MAX_ZOOM 1000 #define ZOOM_1X MIN_ZOOM +/* FIXME: this is v4l2camsrc specific */ #define DEFAULT_V4L2CAMSRC_DRIVER_NAME "omap3cam" -/* internal element names */ +/* pipeline configuration */ +//#define USE_VIEWFINDER_COLOR_CONVERTER 1 +//#define USE_VIEWFINDER_SCALE 1 -#define USE_COLOR_CONVERTER 1 +/* internal element names */ /* FIXME: Make sure this can work with autovideosrc and use that. */ #define DEFAULT_SRC_VID_SRC "v4l2src" - #define DEFAULT_VIEW_SINK "autovideosink" -#define CAMERABIN_MAX_VF_WIDTH 848 -#define CAMERABIN_MAX_VF_HEIGHT 848 +/* message names */ #define PREVIEW_MESSAGE_NAME "preview-image" #define IMG_CAPTURED_MESSAGE_NAME "image-captured" @@ -579,6 +584,7 @@ camerabin_create_src_elements (GstCameraBin * camera) goto done; /* Set default "driver-name" for v4l2camsrc if not set */ + /* FIXME: v4l2camsrc specific */ if (g_object_class_find_property (G_OBJECT_GET_CLASS (camera->src_vid_src), "driver-name")) { g_object_get (G_OBJECT (camera->src_vid_src), "driver-name", @@ -650,6 +656,7 @@ camerabin_create_view_elements (GstCameraBin * camera) } camera->pad_view_src = GST_PAD (pads->data); +#ifdef USE_VIEWFINDER_CONVERTERS /* Add videoscale in case we need to downscale frame for view finder */ if (!(camera->view_scale = gst_camerabin_create_and_add_element (GST_BIN (camera), @@ -663,7 +670,8 @@ camerabin_create_view_elements (GstCameraBin * camera) "capsfilter"))) { goto error; } -#ifdef USE_COLOR_CONVERTER +#endif +#ifdef USE_VIEWFINDER_COLOR_CONVERTER if (!gst_camerabin_create_and_add_element (GST_BIN (camera), "ffmpegcolorspace")) { goto error; @@ -822,6 +830,7 @@ camerabin_destroy_elements (GstCameraBin * camera) } camera->view_sink = NULL; + camera->aspect_filter = NULL; camera->view_scale = NULL; camera->view_in_sel = NULL; @@ -943,18 +952,24 @@ static void gst_camerabin_change_mode (GstCameraBin * camera, gint mode) { if (camera->mode != mode || !camera->active_bin) { - GST_DEBUG_OBJECT (camera, "setting mode: %d", mode); + GST_DEBUG_OBJECT (camera, "setting mode: %d (old_mode=%d)", + mode, camera->mode); /* Interrupt ongoing capture */ gst_camerabin_do_stop (camera); camera->mode = mode; if (camera->active_bin) { + GST_DEBUG_OBJECT (camera, "stopping active bin"); gst_element_set_state (camera->active_bin, GST_STATE_NULL); } if (camera->mode == MODE_IMAGE) { GstStateChangeReturn state_ret; camera->active_bin = camera->imgbin; + /* we can't go to playing as filesink would error out if it does not have + * a filename yet, we set the filename async with the buffer flow */ state_ret = gst_element_set_state (camera->active_bin, GST_STATE_READY); + GST_DEBUG_OBJECT (camera, "setting imagebin to ready: %s", + gst_element_state_change_return_get_name (state_ret)); if (state_ret == GST_STATE_CHANGE_FAILURE) { GST_WARNING_OBJECT (camera, "state change failed"); @@ -979,7 +994,7 @@ static void gst_camerabin_change_filename (GstCameraBin * camera, const gchar * name) { if (0 != strcmp (camera->filename->str, name)) { - GST_DEBUG_OBJECT (camera, "changing filename from %s to %s", + GST_DEBUG_OBJECT (camera, "changing filename from '%s' to '%s'", camera->filename->str, name); g_string_assign (camera->filename, name); } @@ -1567,6 +1582,7 @@ gst_camerabin_start_image_capture (GstCameraBin * camera) gst_element_state_change_return_get_name (state_ret)); if (state_ret != GST_STATE_CHANGE_FAILURE) { + GST_INFO_OBJECT (camera, "imagebin is PAUSED"); g_mutex_lock (camera->capture_mutex); g_object_set (G_OBJECT (camera->src_out_sel), "resend-latest", TRUE, "active-pad", camera->pad_src_img, NULL); @@ -1766,6 +1782,8 @@ done: after one captured still image */ gst_camerabin_finish_image_capture (camera); + GST_DEBUG_OBJECT (camera, "image captured, switching to viewfinder"); + gst_camerabin_reset_to_view_finder (camera); GST_DEBUG_OBJECT (camera, "switched back to viewfinder"); @@ -1823,7 +1841,7 @@ gst_camerabin_have_src_buffer (GstPad * pad, GstBuffer * buffer, /* We can't send real EOS event, since it would switch the image queue into "draining mode". Therefore we send our own custom eos and catch & drop it later in queue's srcpad data probe */ - GST_DEBUG_OBJECT (camera, "sending eos to image queue"); + GST_DEBUG_OBJECT (camera, "sending img-eos to image queue"); gst_camerabin_send_img_queue_custom_event (camera, gst_structure_new ("img-eos", NULL)); @@ -1886,13 +1904,14 @@ gst_camerabin_have_queue_data (GstPad * pad, GstMiniObject * mini_obj, if (GST_EVENT_TYPE (event) == GST_EVENT_TAG) { GstTagList *tlist; + GST_DEBUG_OBJECT (camera, "queue sending taglist to image pipeline"); gst_event_parse_tag (event, &tlist); gst_tag_list_insert (camera->event_tags, tlist, GST_TAG_MERGE_REPLACE); ret = FALSE; } else if (evs && gst_structure_has_name (evs, "img-filename")) { const gchar *fname; - GST_LOG_OBJECT (camera, "queue setting image filename to imagebin"); + GST_DEBUG_OBJECT (camera, "queue setting image filename to imagebin"); fname = gst_structure_get_string (evs, "filename"); g_object_set (G_OBJECT (camera->imgbin), "filename", fname, NULL); @@ -1902,7 +1921,7 @@ gst_camerabin_have_queue_data (GstPad * pad, GstMiniObject * mini_obj, ret = FALSE; } else if (evs && gst_structure_has_name (evs, "img-eos")) { - GST_LOG_OBJECT (camera, "queue sending EOS to image pipeline"); + GST_DEBUG_OBJECT (camera, "queue sending EOS to image pipeline"); gst_pad_set_blocked_async (camera->pad_src_queue, TRUE, (GstPadBlockCallback) image_pad_blocked, camera); gst_element_send_event (camera->imgbin, gst_event_new_eos ()); @@ -2140,10 +2159,10 @@ gst_camerabin_find_better_framerate (GstCameraBin * camera, GstStructure * st, gint res, comparison; if (camera->night_mode) { - GST_LOG_OBJECT (camera, "finding min framerate"); + GST_LOG_OBJECT (camera, "finding min framerate in %" GST_PTR_FORMAT, st); comparison = GST_VALUE_LESS_THAN; } else { - GST_LOG_OBJECT (camera, "finding max framerate"); + GST_LOG_OBJECT (camera, "finding max framerate in %" GST_PTR_FORMAT, st); comparison = GST_VALUE_GREATER_THAN; } @@ -2198,6 +2217,7 @@ gst_camerabin_find_better_framerate (GstCameraBin * camera, GstStructure * st, static void gst_camerabin_update_aspect_filter (GstCameraBin * camera, GstCaps * new_caps) { +#ifdef USE_VIEWFINDER_SCALE GstCaps *sink_caps, *ar_caps; GstStructure *st; gint in_w = 0, in_h = 0, sink_w = 0, sink_h = 0, target_w = 0, target_h = 0; @@ -2266,6 +2286,7 @@ gst_camerabin_update_aspect_filter (GstCameraBin * camera, GstCaps * new_caps) ar_caps); g_object_set (G_OBJECT (camera->aspect_filter), "caps", ar_caps, NULL); gst_caps_unref (ar_caps); +#endif } /* @@ -2725,6 +2746,7 @@ gst_camerabin_init (GstCameraBin * camera, GstCameraBinClass * gclass) /* view finder elements */ camera->view_in_sel = NULL; camera->view_scale = NULL; + camera->aspect_filter = NULL; camera->view_sink = NULL; memset (&camera->photo_settings, 0, sizeof (GstPhotoSettings)); @@ -2971,6 +2993,10 @@ gst_camerabin_change_state (GstElement * element, GstStateChange transition) GstCameraBin *camera = GST_CAMERABIN (element); GstStateChangeReturn ret; + GST_DEBUG_OBJECT (element, "changing state: %s -> %s", + gst_element_state_get_name (GST_STATE_TRANSITION_CURRENT (transition)), + gst_element_state_get_name (GST_STATE_TRANSITION_NEXT (transition))); + switch (transition) { case GST_STATE_CHANGE_NULL_TO_READY: if (!camerabin_create_elements (camera)) { @@ -3000,9 +3026,13 @@ gst_camerabin_change_state (GstElement * element, GstStateChange transition) ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + GST_DEBUG_OBJECT (element, "after chaining up: %s -> %s = %s", + gst_element_state_get_name (GST_STATE_TRANSITION_CURRENT (transition)), + gst_element_state_get_name (GST_STATE_TRANSITION_NEXT (transition)), + gst_element_state_change_return_get_name (ret)); + switch (transition) { case GST_STATE_CHANGE_PAUSED_TO_READY: - GST_LOG_OBJECT (camera, "PAUSED to READY"); g_mutex_lock (camera->capture_mutex); if (camera->capturing) { GST_WARNING_OBJECT (camera, "was capturing when changing to READY"); @@ -3022,6 +3052,10 @@ gst_camerabin_change_state (GstElement * element, GstStateChange transition) } done: + GST_DEBUG_OBJECT (element, "changed state: %s -> %s = %s", + gst_element_state_get_name (GST_STATE_TRANSITION_CURRENT (transition)), + gst_element_state_get_name (GST_STATE_TRANSITION_NEXT (transition)), + gst_element_state_change_return_get_name (ret)); return ret; } @@ -3128,8 +3162,11 @@ gst_camerabin_user_start (GstCameraBin * camera) if (camera->active_bin) { if (camera->active_bin == camera->imgbin) { + GST_INFO_OBJECT (camera, "starting image capture"); gst_camerabin_start_image_capture (camera); } else if (camera->active_bin == camera->vidbin) { + GST_INFO_OBJECT (camera, + "setting video filename and starting video capture"); g_object_set (G_OBJECT (camera->active_bin), "filename", camera->filename->str, NULL); gst_camerabin_start_video_recording (camera); -- cgit v1.2.1 From b1367a95cae07d47360374cacbc5ac7b60675b42 Mon Sep 17 00:00:00 2001 From: Stefan Kost Date: Tue, 16 Jun 2009 17:12:27 +0300 Subject: camerabin: more cleanup in tests Add more debug logging. Remove unused mutex and cond. --- tests/check/elements/camerabin.c | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/tests/check/elements/camerabin.c b/tests/check/elements/camerabin.c index 795fb4f0..bb806c73 100644 --- a/tests/check/elements/camerabin.c +++ b/tests/check/elements/camerabin.c @@ -38,8 +38,6 @@ #define PHOTO_SETTING_DELAY_US 0 static GstElement *camera; -static GCond *cam_cond; -static GMutex *cam_mutex; static GMainLoop *main_loop; static guint cycle_count = 0; @@ -52,7 +50,7 @@ make_test_file_name (const gchar * base_name) g_snprintf (file_name, 999, "%s" G_DIR_SEPARATOR_S "%s", g_get_tmp_dir (), base_name); - GST_INFO ("capturing to: %s (cycle_count=%d)", file_name, cycle_count); + GST_INFO ("capturing to: %s (cycle: %d)", file_name, cycle_count); return file_name; } @@ -79,6 +77,7 @@ handle_image_captured_cb (gpointer data) GST_DEBUG ("handle_image_captured_cb, cycle: %d", cycle_count); if (cycle_count == 0) { + GST_DEBUG ("all cycles done"); g_main_loop_quit (loop); } else { /* Set video recording mode */ @@ -97,7 +96,7 @@ handle_image_captured_cb (gpointer data) g_signal_emit_by_name (camera, "user-start", NULL); cycle_count--; - GST_DEBUG ("next cycle"); + GST_DEBUG ("next cycle: %d", cycle_count); } GST_DEBUG ("handle_image_captured_cb done"); return FALSE; @@ -160,6 +159,10 @@ capture_bus_cb (GstBus * bus, GstMessage * message, gpointer data) GST_WARNING ("ERROR: %s [%s]", err->message, debug); g_error_free (err); g_free (debug); + /* Write debug graph to file */ + GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (camera), + GST_DEBUG_GRAPH_SHOW_ALL, "camerabin.error"); + fail_if (TRUE, "error while capturing"); g_main_loop_quit (loop); break; @@ -172,6 +175,9 @@ capture_bus_cb (GstBus * bus, GstMessage * message, gpointer data) GST_WARNING ("WARNING: %s [%s]", err->message, debug); g_error_free (err); g_free (debug); + /* Write debug graph to file */ + GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (camera), + GST_DEBUG_GRAPH_SHOW_ALL, "camerabin.warning"); break; } case GST_MESSAGE_EOS: @@ -200,9 +206,6 @@ setup (void) main_loop = g_main_loop_new (NULL, TRUE); - cam_cond = g_cond_new (); - cam_mutex = g_mutex_new (); - camera = gst_check_setup_element ("camerabin"); setup_camerabin_elements (camera); @@ -242,8 +245,6 @@ setup (void) static void teardown (void) { - g_mutex_free (cam_mutex); - g_cond_free (cam_cond); if (camera) gst_check_teardown_element (camera); -- cgit v1.2.1 From d5b302ffc4b83a93c726f3b69cd1593adb232944 Mon Sep 17 00:00:00 2001 From: Stefan Kost Date: Mon, 22 Jun 2009 18:35:21 +0300 Subject: metadata: map more tags and fix reading of xmp tags Register xmp schemas for photoshop and iptc. Map a few location tags there. Add more dc tags. Fix reading xmp tag by iteration over known schemas. Add some more debug logging. --- ext/metadata/metadatatags.c | 12 +++++++++ ext/metadata/metadatatags.h | 4 +++ ext/metadata/metadataxmp.c | 64 ++++++++++++++++++++++++++++++++++----------- 3 files changed, 65 insertions(+), 15 deletions(-) diff --git a/ext/metadata/metadatatags.c b/ext/metadata/metadatatags.c index 82e6c381..4beee172 100644 --- a/ext/metadata/metadatatags.c +++ b/ext/metadata/metadatatags.c @@ -446,5 +446,17 @@ metadata_tags_iptc_register (void) static void metadata_tags_xmp_register (void) { + gst_tag_register (GST_TAG_XMP_GEO_LOCATION_COUNTRY, GST_TAG_FLAG_META, + G_TYPE_STRING, GST_TAG_XMP_GEO_LOCATION_COUNTRY, + "human readable english country name of where the media has been recorded or produced", + NULL); + gst_tag_register (GST_TAG_XMP_GEO_LOCATION_CITY, GST_TAG_FLAG_META, + G_TYPE_STRING, GST_TAG_XMP_GEO_LOCATION_CITY, + "human readable english city name of where the media has been recorded or produced", + NULL); + gst_tag_register (GST_TAG_XMP_GEO_LOCATION_SUBLOCATION, GST_TAG_FLAG_META, + G_TYPE_STRING, GST_TAG_XMP_GEO_LOCATION_SUBLOCATION, + "human readable location detail of where the media has been recorded or produced", + NULL); } diff --git a/ext/metadata/metadatatags.h b/ext/metadata/metadatatags.h index 8500f15a..4d718738 100644 --- a/ext/metadata/metadatatags.h +++ b/ext/metadata/metadatatags.h @@ -126,6 +126,10 @@ typedef enum { #define GST_TAG_GPS_SPEED "" #define GST_TAG_GPS_TRACK "" +#define GST_TAG_XMP_GEO_LOCATION_COUNTRY "geo-location-country" +#define GST_TAG_XMP_GEO_LOCATION_CITY "geo-location-city" +#define GST_TAG_XMP_GEO_LOCATION_SUBLOCATION "geo-location-sublocation" + /* *INDENT-ON* */ /* diff --git a/ext/metadata/metadataxmp.c b/ext/metadata/metadataxmp.c index 4da279df..5d5bdefa 100644 --- a/ext/metadata/metadataxmp.c +++ b/ext/metadata/metadataxmp.c @@ -155,13 +155,26 @@ typedef struct _tag_SchemaMap #define XMP_SCHEMA_NODE 0x80000000UL /* *INDENT-OFF* */ -/* When changing this table, update 'metadata_mapping.htm' file too. */ +/* When changing these tables, update 'metadata_mapping.htm' file too. */ static const SchemaTagMap schema_map_dublin_tags_map[] = { + {"creator", GST_TAG_ARTIST }, {"description", GST_TAG_DESCRIPTION }, - {"title", GST_TAG_TITLE }, + {"format", GST_TAG_VIDEO_CODEC }, {"rights", GST_TAG_COPYRIGHT }, + {"subject", GST_TAG_KEYWORDS }, + {"title", GST_TAG_TITLE }, {"type", GST_TAG_CODEC }, - {"format", GST_TAG_VIDEO_CODEC }, + {NULL, NULL} +}; + +static const SchemaTagMap schema_map_photoshop_tags_map[] = { + {"country", GST_TAG_XMP_GEO_LOCATION_COUNTRY }, + {"city", GST_TAG_XMP_GEO_LOCATION_CITY }, + {NULL, NULL} +}; + +static const SchemaTagMap schema_map_iptc4xmpcore_tags_map[] = { + {"location", GST_TAG_XMP_GEO_LOCATION_SUBLOCATION }, {NULL, NULL} }; /* *INDENT-ON* */ @@ -173,9 +186,26 @@ static const SchemaMap schema_map_dublin = { schema_map_dublin_tags_map }; -/* When changing this table, update 'metadata_mapping.htm' file too. */ +/* http://www.adobe.com/devnet/xmp/pdfs/xmp_specification.pdf */ +static const SchemaMap schema_map_photoshop = { + "http://ns.adobe.com/photoshop/1.0/", + "photoshop:", + 10, + schema_map_photoshop_tags_map +}; + +/* http://www.iptc.org/std/Iptc4xmpCore/1.0/specification/Iptc4xmpCore_1.0-spec-XMPSchema_8.pdf */ +static const SchemaMap schema_map_iptc4xmpcore = { + "http://iptc.org/std/Iptc4xmpCore/1.0/xmlns/", + "Iptc4xmpCore:", + 13, + schema_map_iptc4xmpcore_tags_map +}; + static const SchemaMap *schemas_map[] = { &schema_map_dublin, + &schema_map_photoshop, + &schema_map_iptc4xmpcore, NULL }; @@ -474,7 +504,6 @@ metadatamux_xmp_get_tagsmap_from_gsttag (const SchemaMap * schema_map, if (NULL == schema_map) goto done; - for (i = 0; schema_map->tags_map[i].gst_tag; i++) { if (0 == strcmp (schema_map->tags_map[i].gst_tag, tag)) { tags_map = (SchemaTagMap *) & schema_map->tags_map[i]; @@ -567,10 +596,14 @@ void metadataparse_xmp_iter_node_schema (GstTagList * taglist, GstTagMergeMode mode, XmpPtr xmp, const char *schema, const char *path) { - SchemaMap *schema_map = NULL; + const SchemaMap *schema_map = NULL; + gint i; - if (0 == strcmp (schema, "http://purl.org/dc/elements/1.1/")) { - schema_map = (SchemaMap *) & schema_map_dublin; + for (i = 0; schemas_map[i]; i++) { + if (0 == strcmp (schema, schemas_map[i]->schema)) { + schema_map = schemas_map[i]; + break; + } } metadataparse_xmp_iter_array (taglist, mode, xmp, schema, path, schema_map); @@ -805,6 +838,8 @@ metadatamux_xmp_for_each_tag_in_list (const GstTagList * list, XmpPtr xmp = (XmpPtr) user_data; int i; + GST_DEBUG ("trying to map tag '%s' to xmp", tag); + for (i = 0; schemas_map[i]; i++) { /* FIXME: should try to get all of values (index) for the tag */ @@ -814,9 +849,7 @@ metadatamux_xmp_for_each_tag_in_list (const GstTagList * list, metadatamux_xmp_get_tagsmap_from_gsttag (smap, tag); if (stagmap) { - gchar *value = NULL; - GType type = gst_tag_get_type (tag); switch (type) { @@ -827,8 +860,10 @@ metadatamux_xmp_for_each_tag_in_list (const GstTagList * list, break; } - if (value) { + GST_DEBUG ("found mapping for tag '%s' in schema %s", tag, + schemas_map[i]->prefix); + if (value) { uint32_t options = 0; #ifdef XMP_1_99_5 @@ -857,13 +892,12 @@ metadatamux_xmp_for_each_tag_in_list (const GstTagList * list, } g_free (value); - } - + } else { + GST_DEBUG ("no xmp mapping for tag '%s' in schema %s found", tag, + schemas_map[i]->prefix); } - } - } #endif /* else (ifndef HAVE_XMP) */ -- cgit v1.2.1 From 8f1b3d3ec2ad2b2985e199ef8fee60a784ed7904 Mon Sep 17 00:00:00 2001 From: Stefan Kost Date: Mon, 22 Jun 2009 22:01:22 +0300 Subject: camerabin: debug log only change --- tests/check/elements/camerabin.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/check/elements/camerabin.c b/tests/check/elements/camerabin.c index bb806c73..cc08f50d 100644 --- a/tests/check/elements/camerabin.c +++ b/tests/check/elements/camerabin.c @@ -109,7 +109,7 @@ capture_done (GstElement * elem, const gchar * filename, gpointer user_data) g_idle_add ((GSourceFunc) handle_image_captured_cb, loop); - GST_DEBUG ("image saved"); + GST_INFO ("image saved"); return FALSE; } @@ -187,7 +187,7 @@ capture_bus_cb (GstBus * bus, GstMessage * message, gpointer data) default: st = gst_message_get_structure (message); if (st && gst_structure_has_name (st, "image-captured")) { - GST_INFO ("image-captured"); + GST_INFO ("image captured"); } break; } -- cgit v1.2.1 From 640caecd7648d872346caa2ed9720d0e15a27761 Mon Sep 17 00:00:00 2001 From: Dave Robillard Date: Sun, 29 Mar 2009 13:23:02 -0400 Subject: Add configure check for SLV2. --- configure.ac | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/configure.ac b/configure.ac index 13559944..29daf842 100644 --- a/configure.ac +++ b/configure.ac @@ -957,6 +957,14 @@ AG_GST_CHECK_FEATURE(LADSPA, [ladspa], ladspa, [ AC_SUBST(LRDF_CFLAGS) ]) +dnl *** LV2 *** +translit(dnm, m, l) AM_CONDITIONAL(USE_LV2, true) +AG_GST_CHECK_FEATURE(LV2, [lv2], lv2, [ + PKG_CHECK_MODULES(SLV2, slv2 >= 0.6.0, HAVE_SLV2="yes", HAVE_SLV2="no") + AC_SUBST(SLV2_CFLAGS) + AC_SUBST(SLV2_LIBS) +]) + dnl *** libmms *** translit(dnm, m, l) AM_CONDITIONAL(USE_LIBMMS, true) AG_GST_CHECK_FEATURE(LIBMMS, [mms protocol library], libmms, [ -- cgit v1.2.1 From 1d464a7eddeb2a3b2f2d024a4ce121d288ea54db Mon Sep 17 00:00:00 2001 From: Dave Robillard Date: Sun, 29 Mar 2009 13:31:21 -0400 Subject: Fix inconsistent style (trivial test commit). --- ext/ladspa/gstladspa.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/ladspa/gstladspa.h b/ext/ladspa/gstladspa.h index 7f824a8e..7ab94791 100644 --- a/ext/ladspa/gstladspa.h +++ b/ext/ladspa/gstladspa.h @@ -39,7 +39,7 @@ typedef struct _ladspa_control_info { gchar *param_name; gfloat lowerbound, upperbound; gfloat def; - gboolean lower,upper,samplerate; + gboolean lower, upper, samplerate; gboolean toggled, logarithmic, integer, writable; } ladspa_control_info; -- cgit v1.2.1 From ea184d72f532e4178221d7aa8881481f7f76798d Mon Sep 17 00:00:00 2001 From: Dave Robillard Date: Tue, 28 Apr 2009 23:24:45 -0400 Subject: Working LV2 plugin discovery. - Separate gstsignalprocessor into a separate library (not sure if this is in the right place, but it works for now anyway) - Create LV2 element based on LADSPA element, port most discovery functionality --- configure.ac | 4 +- ext/Makefile.am | 7 + ext/ladspa/Makefile.am | 6 +- ext/ladspa/gstladspa.h | 2 +- ext/ladspa/gstsignalprocessor.c | 1024 --------------------- ext/ladspa/gstsignalprocessor.h | 124 --- ext/lv2/Makefile.am | 9 + ext/lv2/gstlv2.c | 588 ++++++++++++ ext/lv2/gstlv2.h | 76 ++ gst-libs/gst/Makefile.am | 4 +- gst-libs/gst/signalprocessor/.gitignore | 7 + gst-libs/gst/signalprocessor/Makefile.am | 8 + gst-libs/gst/signalprocessor/gstsignalprocessor.c | 1024 +++++++++++++++++++++ gst-libs/gst/signalprocessor/gstsignalprocessor.h | 124 +++ 14 files changed, 1852 insertions(+), 1155 deletions(-) delete mode 100644 ext/ladspa/gstsignalprocessor.c delete mode 100644 ext/ladspa/gstsignalprocessor.h create mode 100644 ext/lv2/Makefile.am create mode 100644 ext/lv2/gstlv2.c create mode 100644 ext/lv2/gstlv2.h create mode 100644 gst-libs/gst/signalprocessor/.gitignore create mode 100644 gst-libs/gst/signalprocessor/Makefile.am create mode 100644 gst-libs/gst/signalprocessor/gstsignalprocessor.c create mode 100644 gst-libs/gst/signalprocessor/gstsignalprocessor.h diff --git a/configure.ac b/configure.ac index 29daf842..ac22aef5 100644 --- a/configure.ac +++ b/configure.ac @@ -960,7 +960,7 @@ AG_GST_CHECK_FEATURE(LADSPA, [ladspa], ladspa, [ dnl *** LV2 *** translit(dnm, m, l) AM_CONDITIONAL(USE_LV2, true) AG_GST_CHECK_FEATURE(LV2, [lv2], lv2, [ - PKG_CHECK_MODULES(SLV2, slv2 >= 0.6.0, HAVE_SLV2="yes", HAVE_SLV2="no") + PKG_CHECK_MODULES(SLV2, slv2 >= 0.6.0, HAVE_LV2="yes", HAVE_LV2="no") AC_SUBST(SLV2_CFLAGS) AC_SUBST(SLV2_LIBS) ]) @@ -1644,6 +1644,7 @@ gst-libs/Makefile gst-libs/gst/Makefile gst-libs/gst/dshow/Makefile gst-libs/gst/interfaces/Makefile +gst-libs/gst/signalprocessor/Makefile sys/Makefile sys/dshowdecwrapper/Makefile sys/acmenc/Makefile @@ -1691,6 +1692,7 @@ ext/ivorbis/Makefile ext/jack/Makefile ext/jp2k/Makefile ext/ladspa/Makefile +ext/lv2/Makefile ext/libmms/Makefile ext/Makefile ext/metadata/Makefile diff --git a/ext/Makefile.am b/ext/Makefile.am index f96337f9..8d395057 100644 --- a/ext/Makefile.am +++ b/ext/Makefile.am @@ -154,6 +154,12 @@ else LADSPA_DIR = endif +if USE_LV2 +LV2_DIR = lv2 +else +LV2_DIR = +endif + # if USE_LCS # LCS_DIR=lcs # else @@ -351,6 +357,7 @@ SUBDIRS=\ $(JACK_DIR) \ $(JP2K_DIR) \ $(LADSPA_DIR) \ + $(LV2_DIR) \ $(LCS_DIR) \ $(LIBFAME_DIR) \ $(LIBMMS_DIR) \ diff --git a/ext/ladspa/Makefile.am b/ext/ladspa/Makefile.am index 0ea92746..00582ed7 100644 --- a/ext/ladspa/Makefile.am +++ b/ext/ladspa/Makefile.am @@ -1,9 +1,9 @@ plugin_LTLIBRARIES = libgstladspa.la -libgstladspa_la_SOURCES = gstsignalprocessor.c gstladspa.c +libgstladspa_la_SOURCES = gstladspa.c libgstladspa_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CONTROLLER_CFLAGS) $(GST_CFLAGS) $(LRDF_CFLAGS) -libgstladspa_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) -lgstaudio-$(GST_MAJORMINOR) $(LIBM) $(LRDF_LIBS) +libgstladspa_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) -lgstaudio-$(GST_MAJORMINOR) $(LIBM) $(LRDF_LIBS) ../../gst-libs/gst/signalprocessor/libgstsignalprocessor.la libgstladspa_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) libgstladspa_la_LIBTOOLFLAGS = --tag=disable-static -noinst_HEADERS = gstsignalprocessor.h gstladspa.h +noinst_HEADERS = gstladspa.h diff --git a/ext/ladspa/gstladspa.h b/ext/ladspa/gstladspa.h index 7ab94791..f51d6233 100644 --- a/ext/ladspa/gstladspa.h +++ b/ext/ladspa/gstladspa.h @@ -28,7 +28,7 @@ #include -#include "gstsignalprocessor.h" +#include "../../gst-libs/gst/signalprocessor/gstsignalprocessor.h" G_BEGIN_DECLS diff --git a/ext/ladspa/gstsignalprocessor.c b/ext/ladspa/gstsignalprocessor.c deleted file mode 100644 index c46ae7a8..00000000 --- a/ext/ladspa/gstsignalprocessor.c +++ /dev/null @@ -1,1024 +0,0 @@ -/* GStreamer - * Copyright (C) 1999,2000 Erik Walthinsen - * 2000 Wim Taymans - * 2005 Wim Taymans - * - * gstsignalprocessor.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:gstsignalprocessor - * - * This baseclass allows to write elements that need data on all pads before - * their processing function can run. - * - * In push mode (gst_signal_processor_chain) it operates as follows: - * 1. store each received buffer on the pad and decrement pending_in - * 2. when pending_in==0, process as much as we can and push outputs - * - * In pull mode (gst_signal_processor_getrange) is operates as follows: - * 1. if there is an output ready, deliver - * 2. otherwise pull from each sink-pad, process requested frames and deliver - * the buffer - */ - -#include - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include -#include "gstsignalprocessor.h" - - -GST_DEBUG_CATEGORY_STATIC (gst_signal_processor_debug); -#define GST_CAT_DEFAULT gst_signal_processor_debug - -/* FIXME: this is mono only */ -static GstStaticCaps template_caps = -GST_STATIC_CAPS (GST_AUDIO_FLOAT_STANDARD_PAD_TEMPLATE_CAPS); - -#define GST_TYPE_SIGNAL_PROCESSOR_PAD_TEMPLATE \ - (gst_signal_processor_pad_template_get_type ()) -#define GST_SIGNAL_PROCESSOR_PAD_TEMPLATE(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_SIGNAL_PROCESSOR_PAD_TEMPLATE,\ - GstSignalProcessorPadTemplate)) -typedef struct _GstSignalProcessorPadTemplate GstSignalProcessorPadTemplate; -typedef GstPadTemplateClass GstSignalProcessorPadTemplateClass; - -struct _GstSignalProcessorPadTemplate -{ - GstPadTemplate parent; - - guint index; -}; - -static GType -gst_signal_processor_pad_template_get_type (void) -{ - static GType type = 0; - - if (!type) { - static const GTypeInfo info = { - sizeof (GstSignalProcessorPadTemplateClass), NULL, NULL, NULL, NULL, - NULL, sizeof (GstSignalProcessorPadTemplate), 0, NULL - }; - - type = g_type_register_static (GST_TYPE_PAD_TEMPLATE, - "GstSignalProcessorPadTemplate", &info, 0); - } - return type; -} - -/* - * gst_signal_processor_class_add_pad_template: - * @klass: element class - * @name: pad name - * @direction: pad direction (src/sink) - * @index: index for the pad per direction (starting from 0) - * - */ -void -gst_signal_processor_class_add_pad_template (GstSignalProcessorClass * klass, - const gchar * name, GstPadDirection direction, guint index) -{ - GstPadTemplate *new; - GstCaps *caps; - - g_return_if_fail (GST_IS_SIGNAL_PROCESSOR_CLASS (klass)); - g_return_if_fail (name != NULL); - g_return_if_fail (direction == GST_PAD_SRC || direction == GST_PAD_SINK); - - /* FIXME: would be nice to have the template as a parameter, right now this can - * only create mono pads */ - caps = gst_caps_copy (gst_static_caps_get (&template_caps)); - - new = g_object_new (gst_signal_processor_pad_template_get_type (), - "name", name, "name-template", name, - "direction", direction, "presence", GST_PAD_ALWAYS, "caps", caps, NULL); - - GST_SIGNAL_PROCESSOR_PAD_TEMPLATE (new)->index = index; - - gst_element_class_add_pad_template (GST_ELEMENT_CLASS (klass), new); -} - - -#define GST_TYPE_SIGNAL_PROCESSOR_PAD (gst_signal_processor_pad_get_type ()) -#define GST_SIGNAL_PROCESSOR_PAD(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_SIGNAL_PROCESSOR_PAD,\ - GstSignalProcessorPad)) -typedef struct _GstSignalProcessorPad GstSignalProcessorPad; -typedef GstPadClass GstSignalProcessorPadClass; - -struct _GstSignalProcessorPad -{ - GstPad parent; - - GstBuffer *pen; - - /* index for the pad per direction (starting from 0) */ - guint index; - - /* these are only used for sink pads */ - guint samples_avail; /* available mono sample frames */ - gfloat *data; /* data pointer to read from / write to */ -}; - -static GType -gst_signal_processor_pad_get_type (void) -{ - static GType type = 0; - - if (!type) { - static const GTypeInfo info = { - sizeof (GstSignalProcessorPadClass), NULL, NULL, NULL, NULL, - NULL, sizeof (GstSignalProcessorPad), 0, NULL - }; - - type = g_type_register_static (GST_TYPE_PAD, - "GstSignalProcessorPad", &info, 0); - } - return type; -} - - -GST_BOILERPLATE (GstSignalProcessor, gst_signal_processor, GstElement, - GST_TYPE_ELEMENT); - - -static void gst_signal_processor_finalize (GObject * object); -static gboolean gst_signal_processor_src_activate_pull (GstPad * pad, - gboolean active); -static gboolean gst_signal_processor_sink_activate_push (GstPad * pad, - gboolean active); -static GstStateChangeReturn gst_signal_processor_change_state (GstElement * - element, GstStateChange transition); - -static gboolean gst_signal_processor_event (GstPad * pad, GstEvent * event); -static GstFlowReturn gst_signal_processor_getrange (GstPad * pad, - guint64 offset, guint length, GstBuffer ** buffer); -static GstFlowReturn gst_signal_processor_chain (GstPad * pad, - GstBuffer * buffer); -static gboolean gst_signal_processor_setcaps (GstPad * pad, GstCaps * caps); - - -static void -gst_signal_processor_base_init (gpointer g_class) -{ - GST_DEBUG_CATEGORY_INIT (gst_signal_processor_debug, "gst-dsp", 0, - "signalprocessor element"); -} - -static void -gst_signal_processor_class_init (GstSignalProcessorClass * klass) -{ - GObjectClass *gobject_class; - GstElementClass *gstelement_class; - - gobject_class = G_OBJECT_CLASS (klass); - gstelement_class = GST_ELEMENT_CLASS (klass); - - gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_signal_processor_finalize); - - gstelement_class->change_state = - GST_DEBUG_FUNCPTR (gst_signal_processor_change_state); -} - -static void -gst_signal_processor_add_pad_from_template (GstSignalProcessor * self, - GstPadTemplate * templ) -{ - GstPad *new; - - new = g_object_new (GST_TYPE_SIGNAL_PROCESSOR_PAD, - "name", GST_OBJECT_NAME (templ), "direction", templ->direction, - "template", templ, NULL); - GST_SIGNAL_PROCESSOR_PAD (new)->index = - GST_SIGNAL_PROCESSOR_PAD_TEMPLATE (templ)->index; - - gst_pad_set_setcaps_function (new, - GST_DEBUG_FUNCPTR (gst_signal_processor_setcaps)); - - if (templ->direction == GST_PAD_SINK) { - GST_DEBUG ("added new sink pad"); - - gst_pad_set_event_function (new, - GST_DEBUG_FUNCPTR (gst_signal_processor_event)); - gst_pad_set_chain_function (new, - GST_DEBUG_FUNCPTR (gst_signal_processor_chain)); - gst_pad_set_activatepush_function (new, - GST_DEBUG_FUNCPTR (gst_signal_processor_sink_activate_push)); - } else { - GST_DEBUG ("added new src pad"); - - gst_pad_set_getrange_function (new, - GST_DEBUG_FUNCPTR (gst_signal_processor_getrange)); - gst_pad_set_activatepull_function (new, - GST_DEBUG_FUNCPTR (gst_signal_processor_src_activate_pull)); - } - - gst_element_add_pad (GST_ELEMENT (self), new); -} - -static void -gst_signal_processor_init (GstSignalProcessor * self, - GstSignalProcessorClass * klass) -{ - GList *templates; - - templates = - gst_element_class_get_pad_template_list (GST_ELEMENT_CLASS (klass)); - - while (templates) { - GstPadTemplate *templ = GST_PAD_TEMPLATE (templates->data); - - gst_signal_processor_add_pad_from_template (self, templ); - templates = templates->next; - } - - self->state = GST_SIGNAL_PROCESSOR_STATE_NULL; - - self->audio_in = g_new0 (gfloat *, klass->num_audio_in); - self->control_in = g_new0 (gfloat, klass->num_control_in); - self->audio_out = g_new0 (gfloat *, klass->num_audio_out); - self->control_out = g_new0 (gfloat, klass->num_control_out); - - /* init */ - self->pending_in = klass->num_audio_in; - self->pending_out = 0; - - self->sample_rate = 0; -} - -static void -gst_signal_processor_finalize (GObject * object) -{ - GstSignalProcessor *self = GST_SIGNAL_PROCESSOR (object); - - g_free (self->audio_in); - self->audio_in = NULL; - g_free (self->control_in); - self->control_in = NULL; - g_free (self->audio_out); - self->audio_out = NULL; - g_free (self->control_out); - self->control_out = NULL; - - G_OBJECT_CLASS (parent_class)->finalize (object); -} - -static gboolean -gst_signal_processor_setup (GstSignalProcessor * self, guint sample_rate) -{ - GstSignalProcessorClass *klass; - gboolean ret = TRUE; - - klass = GST_SIGNAL_PROCESSOR_GET_CLASS (self); - - GST_INFO_OBJECT (self, "setup()"); - - g_return_val_if_fail (self->state == GST_SIGNAL_PROCESSOR_STATE_NULL, FALSE); - - if (klass->setup) - ret = klass->setup (self, sample_rate); - - if (!ret) - goto setup_failed; - - self->state = GST_SIGNAL_PROCESSOR_STATE_INITIALIZED; - - return ret; - -setup_failed: - { - GST_INFO_OBJECT (self, "setup() failed at %u Hz", sample_rate); - return ret; - } -} - -static gboolean -gst_signal_processor_start (GstSignalProcessor * self) -{ - GstSignalProcessorClass *klass; - gboolean ret = TRUE; - - klass = GST_SIGNAL_PROCESSOR_GET_CLASS (self); - - g_return_val_if_fail (self->state == GST_SIGNAL_PROCESSOR_STATE_INITIALIZED, - FALSE); - - GST_INFO_OBJECT (self, "start()"); - - if (klass->start) - ret = klass->start (self); - - if (!ret) - goto start_failed; - - self->state = GST_SIGNAL_PROCESSOR_STATE_RUNNING; - - return ret; - -start_failed: - { - GST_INFO_OBJECT (self, "start() failed"); - return ret; - } -} - -static void -gst_signal_processor_stop (GstSignalProcessor * self) -{ - GstSignalProcessorClass *klass; - GstElement *elem; - GList *sinks; - - klass = GST_SIGNAL_PROCESSOR_GET_CLASS (self); - elem = GST_ELEMENT (self); - - GST_INFO_OBJECT (self, "stop()"); - - g_return_if_fail (self->state == GST_SIGNAL_PROCESSOR_STATE_RUNNING); - - if (klass->stop) - klass->stop (self); - - for (sinks = elem->sinkpads; sinks; sinks = sinks->next) - /* force set_caps when going to RUNNING, see note in _setcaps () */ - gst_pad_set_caps (GST_PAD (sinks->data), NULL); - - /* should also flush our buffers perhaps? */ - - self->state = GST_SIGNAL_PROCESSOR_STATE_INITIALIZED; -} - -static void -gst_signal_processor_cleanup (GstSignalProcessor * self) -{ - GstSignalProcessorClass *klass; - - klass = GST_SIGNAL_PROCESSOR_GET_CLASS (self); - - GST_INFO_OBJECT (self, "cleanup()"); - - g_return_if_fail (self->state == GST_SIGNAL_PROCESSOR_STATE_INITIALIZED); - - if (klass->cleanup) - klass->cleanup (self); - - self->state = GST_SIGNAL_PROCESSOR_STATE_NULL; -} - -static gboolean -gst_signal_processor_setcaps_pull (GstSignalProcessor * self, GstPad * pad, - GstCaps * caps) -{ - if (GST_PAD_IS_SRC (pad)) { - GList *l; - - for (l = GST_ELEMENT (self)->sinkpads; l; l = l->next) - if (!gst_pad_set_caps (GST_PAD (l->data), caps)) - goto src_setcaps_failed; - } else { - GstPad *peer; - gboolean res; - - peer = gst_pad_get_peer (pad); - if (!peer) - goto unlinked_sink; - - res = gst_pad_set_caps (peer, caps); - gst_object_unref (peer); - - if (!res) - goto peer_setcaps_failed; - } - - return TRUE; - -src_setcaps_failed: - { - /* not logging, presumably the sink pad already logged */ - return FALSE; - } -unlinked_sink: - { - GST_WARNING_OBJECT (self, "unlinked sink pad %" GST_PTR_FORMAT ", I wonder " - "how we passed activate_pull()", pad); - return FALSE; - } -peer_setcaps_failed: - { - GST_INFO_OBJECT (self, "peer of %" GST_PTR_FORMAT " did not accept caps", - pad); - return FALSE; - } -} - -static gboolean -gst_signal_processor_setcaps (GstPad * pad, GstCaps * caps) -{ - GstSignalProcessor *self; - - self = GST_SIGNAL_PROCESSOR (gst_pad_get_parent (pad)); - - if (self->mode == GST_ACTIVATE_PULL && !gst_caps_is_equal (caps, self->caps) - && !gst_signal_processor_setcaps_pull (self, pad, caps)) - goto setcaps_pull_failed; - - /* the whole processor has one caps; if the sample rate changes, let subclass - implementations know */ - if (!gst_caps_is_equal (caps, self->caps)) { - GstStructure *s; - gint sample_rate; - - GST_DEBUG_OBJECT (pad, "got caps %" GST_PTR_FORMAT, caps); - - s = gst_caps_get_structure (caps, 0); - if (!gst_structure_get_int (s, "rate", &sample_rate)) { - GST_WARNING ("got no sample-rate"); - goto impossible; - } - - GST_DEBUG_OBJECT (self, "Got rate=%d", sample_rate); - - if (GST_SIGNAL_PROCESSOR_IS_RUNNING (self)) - gst_signal_processor_stop (self); - if (GST_SIGNAL_PROCESSOR_IS_INITIALIZED (self)) - gst_signal_processor_cleanup (self); - - if (!gst_signal_processor_setup (self, sample_rate)) - goto start_or_setup_failed; - - self->sample_rate = sample_rate; - gst_caps_replace (&self->caps, caps); - } else { - GST_DEBUG_OBJECT (self, "skipping, have caps already"); - } - - /* we use this method to manage the processor's state, hence the caps clearing - in stop(). so it can be that we enter here just to manage the processor's - state, to take it to RUNNING from already being INITIALIZED with the right - sample rate (e.g., when having gone PLAYING->READY->PLAYING). make sure - when we leave that the processor is RUNNING. */ - if (!GST_SIGNAL_PROCESSOR_IS_INITIALIZED (self) - && !gst_signal_processor_setup (self, self->sample_rate)) - goto start_or_setup_failed; - if (!GST_SIGNAL_PROCESSOR_IS_RUNNING (self) - && !gst_signal_processor_start (self)) - goto start_or_setup_failed; - - gst_object_unref (self); - - return TRUE; - -start_or_setup_failed: - { - gst_object_unref (self); - return FALSE; - } -setcaps_pull_failed: - { - gst_object_unref (self); - return FALSE; - } -impossible: - { - g_critical ("something impossible happened"); - gst_object_unref (self); - return FALSE; - } -} - -static gboolean -gst_signal_processor_event (GstPad * pad, GstEvent * event) -{ - GstSignalProcessor *self; - GstSignalProcessorClass *bclass; - gboolean ret; - - self = GST_SIGNAL_PROCESSOR (gst_pad_get_parent (pad)); - bclass = GST_SIGNAL_PROCESSOR_GET_CLASS (self); - - /* FIXME, this probably isn't the correct interface: what about return values, - * what about overriding event_default - * Sync with GstBaseTransform::gst_base_transform_sink_event */ - if (bclass->event) - bclass->event (self, event); - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_FLUSH_START: - break; - case GST_EVENT_FLUSH_STOP: - /* clear errors now */ - self->flow_state = GST_FLOW_OK; - break; - default: - break; - } - ret = gst_pad_event_default (pad, event); - - gst_object_unref (self); - - return ret; -} - -static guint -gst_signal_processor_prepare (GstSignalProcessor * self, guint nframes) -{ - GstElement *elem = (GstElement *) self; - GstSignalProcessorClass *klass; - GList *sinks, *srcs; - guint samples_avail = nframes; - - klass = GST_SIGNAL_PROCESSOR_GET_CLASS (self); - - /* first, assign audio_in pointers, and determine the number of samples that - * we can process */ - for (sinks = elem->sinkpads; sinks; sinks = sinks->next) { - GstSignalProcessorPad *sinkpad; - - sinkpad = (GstSignalProcessorPad *) sinks->data; - g_assert (sinkpad->samples_avail > 0); - samples_avail = MIN (samples_avail, sinkpad->samples_avail); - self->audio_in[sinkpad->index] = sinkpad->data; - } - - /* FIXME: return if samples_avail==0 ? */ - - /* now assign output buffers. we can avoid allocation by reusing input - buffers, but only if process() can work in place, and if the input buffer - is the exact size of the number of samples we are processing. */ - sinks = elem->sinkpads; - srcs = elem->srcpads; - if (GST_SIGNAL_PROCESSOR_CLASS_CAN_PROCESS_IN_PLACE (klass)) { - while (sinks && srcs) { - GstSignalProcessorPad *sinkpad, *srcpad; - - sinkpad = (GstSignalProcessorPad *) sinks->data; - srcpad = (GstSignalProcessorPad *) srcs->data; - - if (GST_BUFFER_SIZE (sinkpad->pen) == samples_avail * sizeof (gfloat)) { - /* reusable, yay */ - g_assert (sinkpad->samples_avail == samples_avail); - srcpad->pen = sinkpad->pen; - sinkpad->pen = NULL; - self->audio_out[srcpad->index] = sinkpad->data; - self->pending_out++; - - srcs = srcs->next; - } - - sinks = sinks->next; - } - } - - g_return_val_if_fail (GST_SIGNAL_PROCESSOR_IS_RUNNING (self), 0); - - /* now allocate for any remaining outputs */ - while (srcs) { - GstSignalProcessorPad *srcpad; - GstFlowReturn ret; - - srcpad = (GstSignalProcessorPad *) srcs->data; - - ret = - gst_pad_alloc_buffer_and_set_caps (GST_PAD (srcpad), -1, - samples_avail * sizeof (gfloat), self->caps, &srcpad->pen); - - if (ret != GST_FLOW_OK) { - self->flow_state = ret; - return 0; - } else { - self->audio_out[srcpad->index] = (gfloat *) GST_BUFFER_DATA (srcpad->pen); - self->pending_out++; - } - - srcs = srcs->next; - } - - return samples_avail; -} - -static void -gst_signal_processor_update_inputs (GstSignalProcessor * self, guint nprocessed) -{ - GstElement *elem = (GstElement *) self; - GList *sinks; - - for (sinks = elem->sinkpads; sinks; sinks = sinks->next) { - GstSignalProcessorPad *sinkpad; - - sinkpad = (GstSignalProcessorPad *) sinks->data; - g_assert (sinkpad->samples_avail >= nprocessed); - - if (sinkpad->pen && sinkpad->samples_avail == nprocessed) { - /* used up this buffer, unpen */ - gst_buffer_unref (sinkpad->pen); - sinkpad->pen = NULL; - } - - if (!sinkpad->pen) { - /* this buffer was used up */ - self->pending_in++; - sinkpad->data = NULL; - sinkpad->samples_avail = 0; - } else { - /* advance ->data pointers and decrement ->samples_avail, unreffing buffer - if no samples are left */ - sinkpad->samples_avail -= nprocessed; - sinkpad->data += nprocessed; /* gfloat* arithmetic */ - } - } -} - -static void -gst_signal_processor_process (GstSignalProcessor * self, guint nframes) -{ - GstElement *elem; - GstSignalProcessorClass *klass; - - /* check if we have buffers enqueued */ - g_return_if_fail (self->pending_in == 0); - g_return_if_fail (self->pending_out == 0); - - elem = GST_ELEMENT (self); - - /* check how much input is available and prepare output buffers */ - nframes = gst_signal_processor_prepare (self, nframes); - if (G_UNLIKELY (nframes == 0)) - goto flow_error; - - klass = GST_SIGNAL_PROCESSOR_GET_CLASS (self); - - GST_LOG_OBJECT (self, "process(%u)", nframes); - - klass->process (self, nframes); - - gst_signal_processor_update_inputs (self, nframes); - - return; - -flow_error: - { - GST_WARNING ("gst_pad_alloc_buffer_and_set_caps() returned %d", - self->flow_state); - return; - } -} - -static void -gst_signal_processor_pen_buffer (GstSignalProcessor * self, GstPad * pad, - GstBuffer * buffer) -{ - GstSignalProcessorPad *spad = (GstSignalProcessorPad *) pad; - - if (spad->pen) - goto had_buffer; - - /* keep the reference */ - spad->pen = buffer; - spad->data = (gfloat *) GST_BUFFER_DATA (buffer); - spad->samples_avail = GST_BUFFER_SIZE (buffer) / sizeof (float); - - g_assert (self->pending_in != 0); - - self->pending_in--; - - return; - - /* ERRORS */ -had_buffer: - { - GST_WARNING ("Pad %s:%s already has penned buffer", - GST_DEBUG_PAD_NAME (pad)); - gst_buffer_unref (buffer); - return; - } -} - -static void -gst_signal_processor_flush (GstSignalProcessor * self) -{ - GList *pads; - GstSignalProcessorClass *klass; - - klass = GST_SIGNAL_PROCESSOR_GET_CLASS (self); - - GST_INFO_OBJECT (self, "flush()"); - - /* release enqueued buffers */ - for (pads = GST_ELEMENT (self)->pads; pads; pads = pads->next) { - GstSignalProcessorPad *spad = (GstSignalProcessorPad *) pads->data; - - if (spad->pen) { - gst_buffer_unref (spad->pen); - spad->pen = NULL; - spad->data = NULL; - spad->samples_avail = 0; - } - } - - /* no outputs prepared and inputs for each pad needed */ - self->pending_out = 0; - self->pending_in = klass->num_audio_in; -} - -static void -gst_signal_processor_do_pulls (GstSignalProcessor * self, guint nframes) -{ - GList *sinkpads; - - /* FIXME: not threadsafe atm */ - - sinkpads = GST_ELEMENT (self)->sinkpads; - - for (; sinkpads; sinkpads = sinkpads->next) { - GstSignalProcessorPad *spad = (GstSignalProcessorPad *) sinkpads->data; - GstFlowReturn ret = GST_FLOW_OK; - GstBuffer *buf; - - if (spad->pen) { - g_warning ("Unexpectedly full buffer pen for pad %s:%s", - GST_DEBUG_PAD_NAME (spad)); - continue; - } - - ret = - gst_pad_pull_range (GST_PAD (spad), -1, nframes * sizeof (gfloat), - &buf); - - if (ret != GST_FLOW_OK) { - gst_signal_processor_flush (self); - self->flow_state = ret; - return; - } else if (!buf) { - g_critical ("Pull failed to make a buffer!"); - self->flow_state = GST_FLOW_ERROR; - return; - } else { - gst_signal_processor_pen_buffer (self, GST_PAD (spad), buf); - } - } - - if (self->pending_in != 0) { - g_critical ("Something wierd happened..."); - self->flow_state = GST_FLOW_ERROR; - } else { - gst_signal_processor_process (self, nframes); - } -} - -static GstFlowReturn -gst_signal_processor_getrange (GstPad * pad, guint64 offset, - guint length, GstBuffer ** buffer) -{ - GstSignalProcessor *self; - GstSignalProcessorPad *spad = (GstSignalProcessorPad *) pad; - GstFlowReturn ret = GST_FLOW_ERROR; - - self = GST_SIGNAL_PROCESSOR (gst_pad_get_parent (pad)); - - if (spad->pen) { - *buffer = spad->pen; - spad->pen = NULL; - g_assert (self->pending_out != 0); - self->pending_out--; - ret = GST_FLOW_OK; - } else { - gst_signal_processor_do_pulls (self, length / sizeof (gfloat)); - if (!spad->pen) { - /* this is an error condition */ - *buffer = NULL; - ret = self->flow_state; - } else { - *buffer = spad->pen; - spad->pen = NULL; - self->pending_out--; - ret = GST_FLOW_OK; - } - } - - GST_DEBUG_OBJECT (self, "returns %s", gst_flow_get_name (ret)); - - gst_object_unref (self); - - return ret; -} - -static void -gst_signal_processor_do_pushes (GstSignalProcessor * self) -{ - GList *srcpads; - - /* not threadsafe atm */ - - srcpads = GST_ELEMENT (self)->srcpads; - - for (; srcpads; srcpads = srcpads->next) { - GstSignalProcessorPad *spad = (GstSignalProcessorPad *) srcpads->data; - GstFlowReturn ret = GST_FLOW_OK; - GstBuffer *buffer; - - if (!spad->pen) { - g_warning ("Unexpectedly empty buffer pen for pad %s:%s", - GST_DEBUG_PAD_NAME (spad)); - continue; - } - - /* take buffer from pen */ - buffer = spad->pen; - spad->pen = NULL; - - ret = gst_pad_push (GST_PAD (spad), buffer); - - if (ret != GST_FLOW_OK) { - gst_signal_processor_flush (self); - self->flow_state = ret; - return; - } else { - g_assert (self->pending_out > 0); - self->pending_out--; - } - } - - if (self->pending_out != 0) { - g_critical ("Something wierd happened..."); - self->flow_state = GST_FLOW_ERROR; - } -} - -static GstFlowReturn -gst_signal_processor_chain (GstPad * pad, GstBuffer * buffer) -{ - GstSignalProcessor *self; - - self = GST_SIGNAL_PROCESSOR (gst_pad_get_parent (pad)); - - gst_signal_processor_pen_buffer (self, pad, buffer); - - if (self->pending_in == 0) { - gst_signal_processor_process (self, G_MAXUINT); - - gst_signal_processor_do_pushes (self); - } - - gst_object_unref (self); - - return self->flow_state; -} - -static gboolean -gst_signal_processor_sink_activate_push (GstPad * pad, gboolean active) -{ - gboolean result = TRUE; - GstSignalProcessor *self; - GstSignalProcessorClass *bclass; - - self = GST_SIGNAL_PROCESSOR (gst_pad_get_parent (pad)); - bclass = GST_SIGNAL_PROCESSOR_GET_CLASS (self); - - if (active) { - if (self->mode == GST_ACTIVATE_NONE) { - self->mode = GST_ACTIVATE_PUSH; - result = TRUE; - } else if (self->mode == GST_ACTIVATE_PUSH) { - result = TRUE; - } else { - g_warning ("foo"); - result = FALSE; - } - } else { - if (self->mode == GST_ACTIVATE_NONE) { - result = TRUE; - } else if (self->mode == GST_ACTIVATE_PUSH) { - self->mode = GST_ACTIVATE_NONE; - result = TRUE; - } else { - g_warning ("foo"); - result = FALSE; - } - } - - GST_DEBUG_OBJECT (self, "result : %d", result); - - gst_object_unref (self); - - return result; -} - -static gboolean -gst_signal_processor_src_activate_pull (GstPad * pad, gboolean active) -{ - gboolean result = TRUE; - GstSignalProcessor *self; - GstSignalProcessorClass *bclass; - - self = GST_SIGNAL_PROCESSOR (gst_pad_get_parent (pad)); - bclass = GST_SIGNAL_PROCESSOR_GET_CLASS (self); - - if (active) { - if (self->mode == GST_ACTIVATE_NONE) { - GList *l; - - for (l = GST_ELEMENT (self)->sinkpads; l; l = l->next) - result &= gst_pad_activate_pull (pad, active); - if (result) - self->mode = GST_ACTIVATE_PULL; - } else if (self->mode == GST_ACTIVATE_PULL) { - result = TRUE; - } else { - g_warning ("foo"); - result = FALSE; - } - } else { - if (self->mode == GST_ACTIVATE_NONE) { - result = TRUE; - } else if (self->mode == GST_ACTIVATE_PULL) { - GList *l; - - for (l = GST_ELEMENT (self)->sinkpads; l; l = l->next) - result &= gst_pad_activate_pull (pad, active); - if (result) - self->mode = GST_ACTIVATE_NONE; - result = TRUE; - } else { - g_warning ("foo"); - result = FALSE; - } - } - - GST_DEBUG_OBJECT (self, "result : %d", result); - - gst_object_unref (self); - - return result; -} - -static GstStateChangeReturn -gst_signal_processor_change_state (GstElement * element, - GstStateChange transition) -{ - GstSignalProcessor *self; - GstStateChangeReturn result; - - self = GST_SIGNAL_PROCESSOR (element); - - switch (transition) { - case GST_STATE_CHANGE_NULL_TO_READY: - break; - case GST_STATE_CHANGE_READY_TO_PAUSED: - self->flow_state = GST_FLOW_OK; - break; - case GST_STATE_CHANGE_PAUSED_TO_PLAYING: - break; - default: - break; - } - - if ((result = - GST_ELEMENT_CLASS (parent_class)->change_state (element, - transition)) == GST_STATE_CHANGE_FAILURE) - goto failure; - - switch (transition) { - case GST_STATE_CHANGE_PLAYING_TO_PAUSED: - break; - case GST_STATE_CHANGE_PAUSED_TO_READY: - if (GST_SIGNAL_PROCESSOR_IS_RUNNING (self)) - gst_signal_processor_stop (self); - gst_signal_processor_flush (self); - break; - case GST_STATE_CHANGE_READY_TO_NULL: - if (GST_SIGNAL_PROCESSOR_IS_INITIALIZED (self)) - gst_signal_processor_cleanup (self); - break; - default: - break; - } - - return result; - - /* ERRORS */ -failure: - { - GST_DEBUG_OBJECT (element, "parent failed state change"); - return result; - } -} diff --git a/ext/ladspa/gstsignalprocessor.h b/ext/ladspa/gstsignalprocessor.h deleted file mode 100644 index d6f0d0b0..00000000 --- a/ext/ladspa/gstsignalprocessor.h +++ /dev/null @@ -1,124 +0,0 @@ -/* GStreamer - * Copyright (C) 1999,2000 Erik Walthinsen - * 2005 Wim Taymans - * - * gstsignalprocessor.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_SIGNAL_PROCESSOR_H__ -#define __GST_SIGNAL_PROCESSOR_H__ - -#include - -G_BEGIN_DECLS - - -typedef enum -{ - GST_SIGNAL_PROCESSOR_CLASS_FLAG_CAN_PROCESS_IN_PLACE = 1<<0 -} GstSignalProcessorClassFlags; - -#define GST_SIGNAL_PROCESSOR_CLASS_CAN_PROCESS_IN_PLACE(klass) \ - (GST_SIGNAL_PROCESSOR_CLASS (klass)->flags & \ - GST_SIGNAL_PROCESSOR_CLASS_FLAG_CAN_PROCESS_IN_PLACE) -#define GST_SIGNAL_PROCESSOR_CLASS_SET_CAN_PROCESS_IN_PLACE(klass) \ - GST_SIGNAL_PROCESSOR_CLASS (klass)->flags |= \ - GST_SIGNAL_PROCESSOR_CLASS_FLAG_CAN_PROCESS_IN_PLACE - -typedef enum -{ - GST_SIGNAL_PROCESSOR_STATE_NULL, - GST_SIGNAL_PROCESSOR_STATE_INITIALIZED, - GST_SIGNAL_PROCESSOR_STATE_RUNNING -} GstSignalProcessorState; - - -#define GST_TYPE_SIGNAL_PROCESSOR (gst_signal_processor_get_type()) -#define GST_SIGNAL_PROCESSOR(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_SIGNAL_PROCESSOR,GstSignalProcessor)) -#define GST_SIGNAL_PROCESSOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_SIGNAL_PROCESSOR,GstSignalProcessorClass)) -#define GST_SIGNAL_PROCESSOR_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS ((obj),GST_TYPE_SIGNAL_PROCESSOR,GstSignalProcessorClass)) -#define GST_IS_SIGNAL_PROCESSOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_SIGNAL_PROCESSOR)) -#define GST_IS_SIGNAL_PROCESSOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_SIGNAL_PROCESSOR)) - -#define GST_SIGNAL_PROCESSOR_IS_INITIALIZED(obj) \ - (GST_SIGNAL_PROCESSOR (obj)->state >= GST_SIGNAL_PROCESSOR_STATE_INITIALIZED) -#define GST_SIGNAL_PROCESSOR_IS_RUNNING(obj) \ - (GST_SIGNAL_PROCESSOR (obj)->state == GST_SIGNAL_PROCESSOR_STATE_RUNNING) - -typedef struct _GstSignalProcessor GstSignalProcessor; -typedef struct _GstSignalProcessorClass GstSignalProcessorClass; - - -struct _GstSignalProcessor { - GstElement element; - - GstCaps *caps; - - guint sample_rate; - - GstSignalProcessorState state; - - GstFlowReturn flow_state; - - GstActivateMode mode; - - /* pending inputs before processing can take place */ - guint pending_in; - /* panding outputs to be filled */ - guint pending_out; - - gfloat *control_in; - gfloat **audio_in; - gfloat *control_out; - gfloat **audio_out; -}; - -struct _GstSignalProcessorClass { - GstElementClass parent_class; - - /*< public >*/ - guint num_control_in; - guint num_audio_in; - guint num_control_out; - guint num_audio_out; - - guint flags; - - /* virtual methods for subclasses */ - - gboolean (*setup) (GstSignalProcessor *self, guint sample_rate); - gboolean (*start) (GstSignalProcessor *self); - void (*stop) (GstSignalProcessor *self); - void (*cleanup) (GstSignalProcessor *self); - void (*process) (GstSignalProcessor *self, guint num_frames); - gboolean (*event) (GstSignalProcessor *self, GstEvent *event); -}; - - -GType gst_signal_processor_get_type (void); -void gst_signal_processor_class_add_pad_template (GstSignalProcessorClass *klass, - const gchar *name, GstPadDirection direction, guint index); - - - -G_END_DECLS - - -#endif /* __GST_SIGNAL_PROCESSOR_H__ */ diff --git a/ext/lv2/Makefile.am b/ext/lv2/Makefile.am new file mode 100644 index 00000000..f10c7acf --- /dev/null +++ b/ext/lv2/Makefile.am @@ -0,0 +1,9 @@ +plugin_LTLIBRARIES = libgstlv2.la + +libgstlv2_la_SOURCES = gstlv2.c +libgstlv2_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CONTROLLER_CFLAGS) $(GST_CFLAGS) $(SLV2_CFLAGS) +libgstlv2_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) -lgstaudio-$(GST_MAJORMINOR) $(LIBM) $(SLV2_LIBS) ../../gst-libs/gst/signalprocessor/libgstsignalprocessor.la +libgstlv2_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) +libgstlv2_la_LIBTOOLFLAGS = --tag=disable-static + +noinst_HEADERS = gstlv2.h diff --git a/ext/lv2/gstlv2.c b/ext/lv2/gstlv2.c new file mode 100644 index 00000000..5d05f603 --- /dev/null +++ b/ext/lv2/gstlv2.c @@ -0,0 +1,588 @@ +/* GStreamer + * Copyright (C) 1999 Erik Walthinsen + * 2001 Steve Baker + * 2003 Andy Wingo + * + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include +#include + +#include "gstlv2.h" +#include + +#define GST_SLV2_PLUGIN_QDATA g_quark_from_static_string("slv2-plugin") + +static void gst_lv2_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec); + +static void gst_lv2_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec); + +static gboolean gst_lv2_setup (GstSignalProcessor * sigproc, guint sample_rate); +static gboolean gst_lv2_start (GstSignalProcessor * sigproc); +static void gst_lv2_stop (GstSignalProcessor * sigproc); +static void gst_lv2_cleanup (GstSignalProcessor * sigproc); +static void gst_lv2_process (GstSignalProcessor * sigproc, guint nframes); + +static SLV2World world; +SLV2Value audio_class; +SLV2Value control_class; +SLV2Value input_class; +SLV2Value output_class; +SLV2Value integer_prop; +SLV2Value toggled_prop; + +static GstSignalProcessorClass *parent_class; + +static GstPlugin *gst_lv2_plugin; + +GST_DEBUG_CATEGORY_STATIC (lv2_debug); +#define GST_CAT_DEFAULT lv2_debug + + +static void +gst_lv2_base_init (gpointer g_class) +{ + GstLV2Class *klass = (GstLV2Class *) g_class; + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + GstSignalProcessorClass *gsp_class = GST_SIGNAL_PROCESSOR_CLASS (g_class); + GstElementDetails *details; + SLV2Plugin lv2plugin; + SLV2Value val; + guint j, audio_in_count, audio_out_count, control_in_count, control_out_count; + gchar *klass_tags; + + GST_DEBUG ("base_init %p", g_class); + + lv2plugin = (SLV2Plugin) g_type_get_qdata (G_OBJECT_CLASS_TYPE (klass), + GST_SLV2_PLUGIN_QDATA); + + g_assert (lv2plugin); + + /* pad templates */ + gsp_class->num_audio_in = 0; + gsp_class->num_audio_out = 0; + /* properties */ + gsp_class->num_control_in = 0; + gsp_class->num_control_out = 0; + + for (j = 0; j < slv2_plugin_get_num_ports (lv2plugin); j++) { + SLV2Port port = slv2_plugin_get_port_by_index (lv2plugin, j); + if (slv2_port_is_a (lv2plugin, port, audio_class)) { + gchar *name = + g_strdup (slv2_value_as_string (slv2_port_get_symbol (lv2plugin, + port))); + + GST_DEBUG ("LV2 port name: \"%s\"", name); + + if (slv2_port_is_a (lv2plugin, port, input_class)) + gst_signal_processor_class_add_pad_template (gsp_class, name, + GST_PAD_SINK, gsp_class->num_audio_in++); + else if (slv2_port_is_a (lv2plugin, port, output_class)) + gst_signal_processor_class_add_pad_template (gsp_class, name, + GST_PAD_SRC, gsp_class->num_audio_out++); + /* TODO: else ignore plugin */ + + g_free (name); + } else if (slv2_port_is_a (lv2plugin, port, control_class)) { + if (slv2_port_is_a (lv2plugin, port, input_class)) + gsp_class->num_control_in++; + else if (slv2_port_is_a (lv2plugin, port, output_class)) + gsp_class->num_control_out++; + /* TODO: else ignore plugin */ + } + /* TODO: else ignore plugin */ + } + + /* construct the element details struct */ + details = g_new0 (GstElementDetails, 1); + val = slv2_plugin_get_name (lv2plugin); + if (val) { + details->longname = g_strdup (slv2_value_as_string (val)); + slv2_value_free (val); + } else { + details->longname = g_strdup ("no description available"); + } + details->description = details->longname; + val = slv2_plugin_get_author_name (lv2plugin); + if (val) { + details->author = g_strdup (slv2_value_as_string (val)); + slv2_value_free (val); + } else { + details->author = g_strdup ("no author available"); + } + + if (gsp_class->num_audio_in == 0) + klass_tags = "Source/Audio/LV2"; + else if (gsp_class->num_audio_out == 0) { + if (gsp_class->num_control_out == 0) + klass_tags = "Sink/Audio/LV2"; + else + klass_tags = "Sink/Analyzer/Audio/LV2"; + } else + klass_tags = "Filter/Effect/Audio/LV2"; + + details->klass = klass_tags; + GST_INFO ("tags : %s", details->klass); + gst_element_class_set_details (element_class, details); + g_free (details->longname); + g_free (details->author); + g_free (details); + + klass->audio_in_portnums = g_new0 (gint, gsp_class->num_audio_in); + klass->audio_out_portnums = g_new0 (gint, gsp_class->num_audio_out); + klass->control_in_portnums = g_new0 (gint, gsp_class->num_control_in); + klass->control_out_portnums = g_new0 (gint, gsp_class->num_control_out); + + audio_in_count = audio_out_count = control_in_count = control_out_count = 0; + + for (j = 0; j < slv2_plugin_get_num_ports (lv2plugin); j++) { + SLV2Port port = slv2_plugin_get_port_by_index (lv2plugin, j); + gboolean is_input = slv2_port_is_a (lv2plugin, port, input_class); + if (slv2_port_is_a (lv2plugin, port, audio_class)) { + if (is_input) + klass->audio_in_portnums[audio_in_count++] = j; + else + klass->audio_out_portnums[audio_out_count++] = j; + } else if (slv2_port_is_a (lv2plugin, port, control_class)) { + if (is_input) + klass->control_in_portnums[control_in_count++] = j; + else + klass->control_out_portnums[control_out_count++] = j; + } + } + + g_assert (audio_in_count == gsp_class->num_audio_in); + g_assert (audio_out_count == gsp_class->num_audio_out); + g_assert (control_in_count == gsp_class->num_control_in); + g_assert (control_out_count == gsp_class->num_control_out); + + /*if (!LV2_IS_INPLACE_BROKEN (desc->Properties)) + GST_SIGNAL_PROCESSOR_CLASS_SET_CAN_PROCESS_IN_PLACE (klass); */ + + klass->plugin = lv2plugin; +} + +static gchar * +gst_lv2_class_get_param_name (GstLV2Class * klass, gint portnum) +{ + SLV2Plugin lv2plugin = klass->plugin; + SLV2Port port = slv2_plugin_get_port_by_index (lv2plugin, portnum); + return g_strdup (slv2_value_as_string (slv2_port_get_symbol (lv2plugin, + port))); +} + +static GParamSpec * +gst_lv2_class_get_param_spec (GstLV2Class * klass, gint portnum) +{ + SLV2Plugin lv2plugin = klass->plugin; + SLV2Port port = slv2_plugin_get_port_by_index (lv2plugin, portnum); + SLV2Value lv2def, lv2min, lv2max; + GParamSpec *ret; + gchar *name; + gint perms; + gfloat lower = 0.0f, upper = 1.0f, def = 0.0f; + + name = gst_lv2_class_get_param_name (klass, portnum); + perms = G_PARAM_READABLE; + if (slv2_port_is_a (lv2plugin, port, input_class)) + perms |= G_PARAM_WRITABLE | G_PARAM_CONSTRUCT; + if (slv2_port_is_a (lv2plugin, port, control_class)) + perms |= GST_PARAM_CONTROLLABLE; + + if (slv2_port_has_property (lv2plugin, port, toggled_prop)) { + ret = g_param_spec_boolean (name, name, name, FALSE, perms); + g_free (name); + return ret; + } + + slv2_port_get_range (lv2plugin, port, &lv2def, &lv2min, &lv2max); + + if (lv2def) + def = slv2_value_as_float (lv2def); + if (lv2min) + lower = slv2_value_as_float (lv2min); + if (lv2max) + upper = slv2_value_as_float (lv2max); + + if (def < lower) { + fprintf (stderr, "ERROR: %s BAD LOWER %f > %f\n", + slv2_value_as_string (slv2_plugin_get_uri (lv2plugin)), lower, def); + lower = def; + } + + if (def > upper) { + fprintf (stderr, "ERROR: %s BAD UPPER %f < %f\n", + slv2_value_as_string (slv2_plugin_get_uri (lv2plugin)), upper, def); + upper = def; + } + + if (slv2_port_has_property (lv2plugin, port, integer_prop)) + ret = g_param_spec_int (name, name, name, lower, upper, def, perms); + else + ret = g_param_spec_float (name, name, name, lower, upper, def, perms); + + g_free (name); + + return ret; +} + +static void +gst_lv2_class_init (GstLV2Class * klass, SLV2Plugin lv2plugin) +{ + GObjectClass *gobject_class; + GstSignalProcessorClass *gsp_class; + gint i; + + GST_DEBUG ("class_init %p", klass); + + gobject_class = (GObjectClass *) klass; + gobject_class->set_property = gst_lv2_set_property; + gobject_class->get_property = gst_lv2_get_property; + + gsp_class = GST_SIGNAL_PROCESSOR_CLASS (klass); + gsp_class->setup = gst_lv2_setup; + gsp_class->start = gst_lv2_start; + gsp_class->stop = gst_lv2_stop; + gsp_class->cleanup = gst_lv2_cleanup; + gsp_class->process = gst_lv2_process; + + klass->plugin = lv2plugin; + + /* register properties */ + + for (i = 0; i < gsp_class->num_control_in; i++) { + GParamSpec *p; + + p = gst_lv2_class_get_param_spec (klass, klass->control_in_portnums[i]); + + /* properties have an offset of 1 */ + g_object_class_install_property (G_OBJECT_CLASS (klass), i + 1, p); + } + + for (i = 0; i < gsp_class->num_control_out; i++) { + GParamSpec *p; + + p = gst_lv2_class_get_param_spec (klass, klass->control_out_portnums[i]); + + /* properties have an offset of 1, and we already added num_control_in */ + g_object_class_install_property (G_OBJECT_CLASS (klass), + gsp_class->num_control_in + i + 1, p); + } +} + +static void +gst_lv2_init (GstLV2 * lv2, GstLV2Class * klass) +{ +#if 0 + lv2->plugin = klass->plugin; + lv2->instance = NULL; + lv2->activated = FALSE; + lv2->inplace_broken = LV2_IS_INPLACE_BROKEN (lv2->descriptor->Properties); +#endif +} + +static void +gst_lv2_set_property (GObject * object, guint prop_id, const GValue * value, + GParamSpec * pspec) +{ +#if 0 + GstSignalProcessor *gsp; + GstSignalProcessorClass *gsp_class; + + gsp = GST_SIGNAL_PROCESSOR (object); + gsp_class = GST_SIGNAL_PROCESSOR_GET_CLASS (object); + + /* remember, properties have an offset of 1 */ + prop_id--; + + /* only input ports */ + g_return_if_fail (prop_id < gsp_class->num_control_in); + + /* now see what type it is */ + switch (pspec->value_type) { + case G_TYPE_BOOLEAN: + gsp->control_in[prop_id] = g_value_get_boolean (value) ? 1.f : 0.f; + break; + case G_TYPE_INT: + gsp->control_in[prop_id] = g_value_get_int (value); + break; + case G_TYPE_FLOAT: + gsp->control_in[prop_id] = g_value_get_float (value); + break; + default: + g_assert_not_reached (); + } +#endif +} + +static void +gst_lv2_get_property (GObject * object, guint prop_id, GValue * value, + GParamSpec * pspec) +{ +#if 0 + GstSignalProcessor *gsp; + GstSignalProcessorClass *gsp_class; + gfloat *controls; + + gsp = GST_SIGNAL_PROCESSOR (object); + gsp_class = GST_SIGNAL_PROCESSOR_GET_CLASS (object); + + /* remember, properties have an offset of 1 */ + prop_id--; + + if (prop_id < gsp_class->num_control_in) { + controls = gsp->control_in; + } else if (prop_id < gsp_class->num_control_in + gsp_class->num_control_out) { + controls = gsp->control_out; + prop_id -= gsp_class->num_control_in; + } else { + g_return_if_reached (); + } + + /* now see what type it is */ + switch (pspec->value_type) { + case G_TYPE_BOOLEAN: + g_value_set_boolean (value, controls[prop_id] > 0.5); + break; + case G_TYPE_INT: + g_value_set_int (value, CLAMP (controls[prop_id], G_MININT, G_MAXINT)); + break; + case G_TYPE_FLOAT: + g_value_set_float (value, controls[prop_id]); + break; + default: + g_return_if_reached (); + } +#endif +} + +static gboolean +gst_lv2_setup (GstSignalProcessor * gsp, guint sample_rate) +{ +#if 0 + GstLV2 *ladspa; + GstLV2Class *oclass; + GstSignalProcessorClass *gsp_class; + LV2_Descriptor *desc; + int i; + + gsp_class = GST_SIGNAL_PROCESSOR_GET_CLASS (gsp); + ladspa = (GstLV2 *) gsp; + oclass = (GstLV2Class *) gsp_class; + desc = ladspa->descriptor; + + g_return_val_if_fail (ladspa->handle == NULL, FALSE); + g_return_val_if_fail (ladspa->activated == FALSE, FALSE); + + GST_DEBUG_OBJECT (ladspa, "instantiating the plugin at %d Hz", sample_rate); + + ladspa->handle = desc->instantiate (desc, sample_rate); + + g_return_val_if_fail (ladspa->handle != NULL, FALSE); + + /* connect the control ports */ + for (i = 0; i < gsp_class->num_control_in; i++) + desc->connect_port (ladspa->handle, + oclass->control_in_portnums[i], &(gsp->control_in[i])); + for (i = 0; i < gsp_class->num_control_out; i++) + desc->connect_port (ladspa->handle, + oclass->control_out_portnums[i], &(gsp->control_out[i])); +#endif + return TRUE; +} + +static gboolean +gst_lv2_start (GstSignalProcessor * gsp) +{ +#if 0 + GstLV2 *ladspa; + LV2_Descriptor *desc; + + ladspa = (GstLV2 *) gsp; + desc = ladspa->descriptor; + + g_return_val_if_fail (ladspa->activated == FALSE, FALSE); + g_return_val_if_fail (ladspa->handle != NULL, FALSE); + + GST_DEBUG_OBJECT (ladspa, "activating"); + + if (desc->activate) + desc->activate (ladspa->handle); + + ladspa->activated = TRUE; +#endif + + return TRUE; +} + +static void +gst_lv2_stop (GstSignalProcessor * gsp) +{ +#if 0 + GstLV2 *ladspa; + LV2_Descriptor *desc; + + ladspa = (GstLV2 *) gsp; + desc = ladspa->descriptor; + + g_return_if_fail (ladspa->activated == TRUE); + g_return_if_fail (ladspa->handle != NULL); + + GST_DEBUG_OBJECT (ladspa, "deactivating"); + + if (desc->activate) + desc->activate (ladspa->handle); + + ladspa->activated = FALSE; +#endif +} + +static void +gst_lv2_cleanup (GstSignalProcessor * gsp) +{ +#if 0 + GstLV2 *ladspa; + LV2_Descriptor *desc; + + ladspa = (GstLV2 *) gsp; + desc = ladspa->descriptor; + + g_return_if_fail (ladspa->activated == FALSE); + g_return_if_fail (ladspa->handle != NULL); + + GST_DEBUG_OBJECT (ladspa, "cleaning up"); + + if (desc->cleanup) + desc->cleanup (ladspa->handle); + + ladspa->handle = NULL; +#endif +} + +static void +gst_lv2_process (GstSignalProcessor * gsp, guint nframes) +{ +#if 0 + GstSignalProcessorClass *gsp_class; + GstLV2 *ladspa; + GstLV2Class *oclass; + LV2_Descriptor *desc; + guint i; + + gsp_class = GST_SIGNAL_PROCESSOR_GET_CLASS (gsp); + ladspa = (GstLV2 *) gsp; + oclass = (GstLV2Class *) gsp_class; + desc = ladspa->descriptor; + + for (i = 0; i < gsp_class->num_audio_in; i++) + desc->connect_port (ladspa->handle, oclass->audio_in_portnums[i], + gsp->audio_in[i]); + for (i = 0; i < gsp_class->num_audio_out; i++) + desc->connect_port (ladspa->handle, oclass->audio_out_portnums[i], + gsp->audio_out[i]); + + desc->run (ladspa->handle, nframes); +#endif +} + +/* search the plugin path + */ +static gboolean +lv2_plugin_discover (void) +{ + unsigned i; + SLV2Plugins plugins = slv2_world_get_all_plugins (world); + for (i = 0; i < slv2_plugins_size (plugins); ++i) { + SLV2Plugin lv2plugin = slv2_plugins_get_at (plugins, i); + GTypeInfo typeinfo = { + sizeof (GstLV2Class), + (GBaseInitFunc) gst_lv2_base_init, + NULL, + (GClassInitFunc) gst_lv2_class_init, + NULL, + lv2plugin, + sizeof (GstLV2), + 0, + (GInstanceInitFunc) gst_lv2_init, + }; + + GType type; + + /* construct the type name from plugin URI */ + gchar *type_name = g_strdup_printf ("%s", + slv2_value_as_uri (slv2_plugin_get_uri (lv2plugin))); + g_strcanon (type_name, G_CSET_A_2_Z G_CSET_a_2_z G_CSET_DIGITS "-+", '-'); + + /* if it's already registered, drop it */ + if (g_type_from_name (type_name)) + goto next; + + /* create the type */ + type = + g_type_register_static (GST_TYPE_SIGNAL_PROCESSOR, type_name, &typeinfo, + 0); + + /* FIXME: not needed anymore when we can add pad templates, etc in class_init + * as class_data contains the LADSPA_Descriptor too */ + g_type_set_qdata (type, GST_SLV2_PLUGIN_QDATA, (gpointer) lv2plugin); + + if (!gst_element_register (gst_lv2_plugin, type_name, GST_RANK_NONE, type)) + goto next; + + next: + g_free (type_name); + } + return TRUE; +} + +static gboolean +plugin_init (GstPlugin * plugin) +{ + GST_DEBUG_CATEGORY_INIT (lv2_debug, "lv2", + GST_DEBUG_FG_GREEN | GST_DEBUG_BG_BLACK | GST_DEBUG_BOLD, "LV2"); + + world = slv2_world_new (); + slv2_world_load_all (world); + + audio_class = slv2_value_new_uri (world, SLV2_PORT_CLASS_AUDIO); + control_class = slv2_value_new_uri (world, SLV2_PORT_CLASS_CONTROL); + input_class = slv2_value_new_uri (world, SLV2_PORT_CLASS_INPUT); + output_class = slv2_value_new_uri (world, SLV2_PORT_CLASS_OUTPUT); + integer_prop = + slv2_value_new_uri (world, "http://lv2plug.in/ns/lv2core#integer"); + toggled_prop = + slv2_value_new_uri (world, "http://lv2plug.in/ns/lv2core#toggled"); + + parent_class = g_type_class_ref (GST_TYPE_SIGNAL_PROCESSOR); + + gst_lv2_plugin = plugin; + + return lv2_plugin_discover (); +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "lv2", + "All LV2 plugins", + plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/ext/lv2/gstlv2.h b/ext/lv2/gstlv2.h new file mode 100644 index 00000000..f76235b4 --- /dev/null +++ b/ext/lv2/gstlv2.h @@ -0,0 +1,76 @@ +/* GStreamer + * Copyright (C) <1999> Erik Walthinsen + * + * gstladspa.h: Header for LV2 plugin + * + * 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_LV2_H__ +#define __GST_LV2_H__ + + +#include + +#include + +#include "../../gst-libs/gst/signalprocessor/gstsignalprocessor.h" + + +G_BEGIN_DECLS + + +typedef struct _lv2_control_info { + gchar *name; + gchar *param_name; + gfloat lowerbound, upperbound; + gfloat def; + gboolean lower, upper, samplerate; + gboolean toggled, logarithmic, integer, writable; +} lv2_control_info; + + +typedef struct _GstLV2 GstLV2; +typedef struct _GstLV2Class GstLV2Class; + + +struct _GstLV2 { + GstSignalProcessor parent; + + SLV2Plugin *plugin; + SLV2Instance *instance; + + gboolean activated; + gboolean inplace_broken; +}; + +struct _GstLV2Class { + GstSignalProcessorClass parent_class; + + SLV2Plugin plugin; + + gint *audio_in_portnums; + gint *audio_out_portnums; + gint *control_in_portnums; + gint *control_out_portnums; +}; + + +G_END_DECLS + + +#endif /* __GST_LV2_H__ */ diff --git a/gst-libs/gst/Makefile.am b/gst-libs/gst/Makefile.am index c50f8f4b..3471a759 100644 --- a/gst-libs/gst/Makefile.am +++ b/gst-libs/gst/Makefile.am @@ -1,5 +1,5 @@ -SUBDIRS = interfaces +SUBDIRS = interfaces signalprocessor noinst_HEADERS = gst-i18n-plugin.h gettext.h -DIST_SUBDIRS = dshow interfaces +DIST_SUBDIRS = dshow interfaces signalprocessor diff --git a/gst-libs/gst/signalprocessor/.gitignore b/gst-libs/gst/signalprocessor/.gitignore new file mode 100644 index 00000000..08f5ed37 --- /dev/null +++ b/gst-libs/gst/signalprocessor/.gitignore @@ -0,0 +1,7 @@ +Makefile +Makefile.in +*.o +*.lo +*.la +.deps +.libs diff --git a/gst-libs/gst/signalprocessor/Makefile.am b/gst-libs/gst/signalprocessor/Makefile.am new file mode 100644 index 00000000..a8455390 --- /dev/null +++ b/gst-libs/gst/signalprocessor/Makefile.am @@ -0,0 +1,8 @@ +lib_LTLIBRARIES = libgstsignalprocessor.la + +noinst_HEADERS = gstsignalprocessor.h + +libgstsignalprocessor_la_SOURCES = gstsignalprocessor.c +libgstsignalprocessor_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) +libgstsignalprocessor_la_LDFLAGS = $(GST_PLUGINS_BASE_LIBS) + diff --git a/gst-libs/gst/signalprocessor/gstsignalprocessor.c b/gst-libs/gst/signalprocessor/gstsignalprocessor.c new file mode 100644 index 00000000..c46ae7a8 --- /dev/null +++ b/gst-libs/gst/signalprocessor/gstsignalprocessor.c @@ -0,0 +1,1024 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2000 Wim Taymans + * 2005 Wim Taymans + * + * gstsignalprocessor.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:gstsignalprocessor + * + * This baseclass allows to write elements that need data on all pads before + * their processing function can run. + * + * In push mode (gst_signal_processor_chain) it operates as follows: + * 1. store each received buffer on the pad and decrement pending_in + * 2. when pending_in==0, process as much as we can and push outputs + * + * In pull mode (gst_signal_processor_getrange) is operates as follows: + * 1. if there is an output ready, deliver + * 2. otherwise pull from each sink-pad, process requested frames and deliver + * the buffer + */ + +#include + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include "gstsignalprocessor.h" + + +GST_DEBUG_CATEGORY_STATIC (gst_signal_processor_debug); +#define GST_CAT_DEFAULT gst_signal_processor_debug + +/* FIXME: this is mono only */ +static GstStaticCaps template_caps = +GST_STATIC_CAPS (GST_AUDIO_FLOAT_STANDARD_PAD_TEMPLATE_CAPS); + +#define GST_TYPE_SIGNAL_PROCESSOR_PAD_TEMPLATE \ + (gst_signal_processor_pad_template_get_type ()) +#define GST_SIGNAL_PROCESSOR_PAD_TEMPLATE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_SIGNAL_PROCESSOR_PAD_TEMPLATE,\ + GstSignalProcessorPadTemplate)) +typedef struct _GstSignalProcessorPadTemplate GstSignalProcessorPadTemplate; +typedef GstPadTemplateClass GstSignalProcessorPadTemplateClass; + +struct _GstSignalProcessorPadTemplate +{ + GstPadTemplate parent; + + guint index; +}; + +static GType +gst_signal_processor_pad_template_get_type (void) +{ + static GType type = 0; + + if (!type) { + static const GTypeInfo info = { + sizeof (GstSignalProcessorPadTemplateClass), NULL, NULL, NULL, NULL, + NULL, sizeof (GstSignalProcessorPadTemplate), 0, NULL + }; + + type = g_type_register_static (GST_TYPE_PAD_TEMPLATE, + "GstSignalProcessorPadTemplate", &info, 0); + } + return type; +} + +/* + * gst_signal_processor_class_add_pad_template: + * @klass: element class + * @name: pad name + * @direction: pad direction (src/sink) + * @index: index for the pad per direction (starting from 0) + * + */ +void +gst_signal_processor_class_add_pad_template (GstSignalProcessorClass * klass, + const gchar * name, GstPadDirection direction, guint index) +{ + GstPadTemplate *new; + GstCaps *caps; + + g_return_if_fail (GST_IS_SIGNAL_PROCESSOR_CLASS (klass)); + g_return_if_fail (name != NULL); + g_return_if_fail (direction == GST_PAD_SRC || direction == GST_PAD_SINK); + + /* FIXME: would be nice to have the template as a parameter, right now this can + * only create mono pads */ + caps = gst_caps_copy (gst_static_caps_get (&template_caps)); + + new = g_object_new (gst_signal_processor_pad_template_get_type (), + "name", name, "name-template", name, + "direction", direction, "presence", GST_PAD_ALWAYS, "caps", caps, NULL); + + GST_SIGNAL_PROCESSOR_PAD_TEMPLATE (new)->index = index; + + gst_element_class_add_pad_template (GST_ELEMENT_CLASS (klass), new); +} + + +#define GST_TYPE_SIGNAL_PROCESSOR_PAD (gst_signal_processor_pad_get_type ()) +#define GST_SIGNAL_PROCESSOR_PAD(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_SIGNAL_PROCESSOR_PAD,\ + GstSignalProcessorPad)) +typedef struct _GstSignalProcessorPad GstSignalProcessorPad; +typedef GstPadClass GstSignalProcessorPadClass; + +struct _GstSignalProcessorPad +{ + GstPad parent; + + GstBuffer *pen; + + /* index for the pad per direction (starting from 0) */ + guint index; + + /* these are only used for sink pads */ + guint samples_avail; /* available mono sample frames */ + gfloat *data; /* data pointer to read from / write to */ +}; + +static GType +gst_signal_processor_pad_get_type (void) +{ + static GType type = 0; + + if (!type) { + static const GTypeInfo info = { + sizeof (GstSignalProcessorPadClass), NULL, NULL, NULL, NULL, + NULL, sizeof (GstSignalProcessorPad), 0, NULL + }; + + type = g_type_register_static (GST_TYPE_PAD, + "GstSignalProcessorPad", &info, 0); + } + return type; +} + + +GST_BOILERPLATE (GstSignalProcessor, gst_signal_processor, GstElement, + GST_TYPE_ELEMENT); + + +static void gst_signal_processor_finalize (GObject * object); +static gboolean gst_signal_processor_src_activate_pull (GstPad * pad, + gboolean active); +static gboolean gst_signal_processor_sink_activate_push (GstPad * pad, + gboolean active); +static GstStateChangeReturn gst_signal_processor_change_state (GstElement * + element, GstStateChange transition); + +static gboolean gst_signal_processor_event (GstPad * pad, GstEvent * event); +static GstFlowReturn gst_signal_processor_getrange (GstPad * pad, + guint64 offset, guint length, GstBuffer ** buffer); +static GstFlowReturn gst_signal_processor_chain (GstPad * pad, + GstBuffer * buffer); +static gboolean gst_signal_processor_setcaps (GstPad * pad, GstCaps * caps); + + +static void +gst_signal_processor_base_init (gpointer g_class) +{ + GST_DEBUG_CATEGORY_INIT (gst_signal_processor_debug, "gst-dsp", 0, + "signalprocessor element"); +} + +static void +gst_signal_processor_class_init (GstSignalProcessorClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + + gobject_class = G_OBJECT_CLASS (klass); + gstelement_class = GST_ELEMENT_CLASS (klass); + + gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_signal_processor_finalize); + + gstelement_class->change_state = + GST_DEBUG_FUNCPTR (gst_signal_processor_change_state); +} + +static void +gst_signal_processor_add_pad_from_template (GstSignalProcessor * self, + GstPadTemplate * templ) +{ + GstPad *new; + + new = g_object_new (GST_TYPE_SIGNAL_PROCESSOR_PAD, + "name", GST_OBJECT_NAME (templ), "direction", templ->direction, + "template", templ, NULL); + GST_SIGNAL_PROCESSOR_PAD (new)->index = + GST_SIGNAL_PROCESSOR_PAD_TEMPLATE (templ)->index; + + gst_pad_set_setcaps_function (new, + GST_DEBUG_FUNCPTR (gst_signal_processor_setcaps)); + + if (templ->direction == GST_PAD_SINK) { + GST_DEBUG ("added new sink pad"); + + gst_pad_set_event_function (new, + GST_DEBUG_FUNCPTR (gst_signal_processor_event)); + gst_pad_set_chain_function (new, + GST_DEBUG_FUNCPTR (gst_signal_processor_chain)); + gst_pad_set_activatepush_function (new, + GST_DEBUG_FUNCPTR (gst_signal_processor_sink_activate_push)); + } else { + GST_DEBUG ("added new src pad"); + + gst_pad_set_getrange_function (new, + GST_DEBUG_FUNCPTR (gst_signal_processor_getrange)); + gst_pad_set_activatepull_function (new, + GST_DEBUG_FUNCPTR (gst_signal_processor_src_activate_pull)); + } + + gst_element_add_pad (GST_ELEMENT (self), new); +} + +static void +gst_signal_processor_init (GstSignalProcessor * self, + GstSignalProcessorClass * klass) +{ + GList *templates; + + templates = + gst_element_class_get_pad_template_list (GST_ELEMENT_CLASS (klass)); + + while (templates) { + GstPadTemplate *templ = GST_PAD_TEMPLATE (templates->data); + + gst_signal_processor_add_pad_from_template (self, templ); + templates = templates->next; + } + + self->state = GST_SIGNAL_PROCESSOR_STATE_NULL; + + self->audio_in = g_new0 (gfloat *, klass->num_audio_in); + self->control_in = g_new0 (gfloat, klass->num_control_in); + self->audio_out = g_new0 (gfloat *, klass->num_audio_out); + self->control_out = g_new0 (gfloat, klass->num_control_out); + + /* init */ + self->pending_in = klass->num_audio_in; + self->pending_out = 0; + + self->sample_rate = 0; +} + +static void +gst_signal_processor_finalize (GObject * object) +{ + GstSignalProcessor *self = GST_SIGNAL_PROCESSOR (object); + + g_free (self->audio_in); + self->audio_in = NULL; + g_free (self->control_in); + self->control_in = NULL; + g_free (self->audio_out); + self->audio_out = NULL; + g_free (self->control_out); + self->control_out = NULL; + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static gboolean +gst_signal_processor_setup (GstSignalProcessor * self, guint sample_rate) +{ + GstSignalProcessorClass *klass; + gboolean ret = TRUE; + + klass = GST_SIGNAL_PROCESSOR_GET_CLASS (self); + + GST_INFO_OBJECT (self, "setup()"); + + g_return_val_if_fail (self->state == GST_SIGNAL_PROCESSOR_STATE_NULL, FALSE); + + if (klass->setup) + ret = klass->setup (self, sample_rate); + + if (!ret) + goto setup_failed; + + self->state = GST_SIGNAL_PROCESSOR_STATE_INITIALIZED; + + return ret; + +setup_failed: + { + GST_INFO_OBJECT (self, "setup() failed at %u Hz", sample_rate); + return ret; + } +} + +static gboolean +gst_signal_processor_start (GstSignalProcessor * self) +{ + GstSignalProcessorClass *klass; + gboolean ret = TRUE; + + klass = GST_SIGNAL_PROCESSOR_GET_CLASS (self); + + g_return_val_if_fail (self->state == GST_SIGNAL_PROCESSOR_STATE_INITIALIZED, + FALSE); + + GST_INFO_OBJECT (self, "start()"); + + if (klass->start) + ret = klass->start (self); + + if (!ret) + goto start_failed; + + self->state = GST_SIGNAL_PROCESSOR_STATE_RUNNING; + + return ret; + +start_failed: + { + GST_INFO_OBJECT (self, "start() failed"); + return ret; + } +} + +static void +gst_signal_processor_stop (GstSignalProcessor * self) +{ + GstSignalProcessorClass *klass; + GstElement *elem; + GList *sinks; + + klass = GST_SIGNAL_PROCESSOR_GET_CLASS (self); + elem = GST_ELEMENT (self); + + GST_INFO_OBJECT (self, "stop()"); + + g_return_if_fail (self->state == GST_SIGNAL_PROCESSOR_STATE_RUNNING); + + if (klass->stop) + klass->stop (self); + + for (sinks = elem->sinkpads; sinks; sinks = sinks->next) + /* force set_caps when going to RUNNING, see note in _setcaps () */ + gst_pad_set_caps (GST_PAD (sinks->data), NULL); + + /* should also flush our buffers perhaps? */ + + self->state = GST_SIGNAL_PROCESSOR_STATE_INITIALIZED; +} + +static void +gst_signal_processor_cleanup (GstSignalProcessor * self) +{ + GstSignalProcessorClass *klass; + + klass = GST_SIGNAL_PROCESSOR_GET_CLASS (self); + + GST_INFO_OBJECT (self, "cleanup()"); + + g_return_if_fail (self->state == GST_SIGNAL_PROCESSOR_STATE_INITIALIZED); + + if (klass->cleanup) + klass->cleanup (self); + + self->state = GST_SIGNAL_PROCESSOR_STATE_NULL; +} + +static gboolean +gst_signal_processor_setcaps_pull (GstSignalProcessor * self, GstPad * pad, + GstCaps * caps) +{ + if (GST_PAD_IS_SRC (pad)) { + GList *l; + + for (l = GST_ELEMENT (self)->sinkpads; l; l = l->next) + if (!gst_pad_set_caps (GST_PAD (l->data), caps)) + goto src_setcaps_failed; + } else { + GstPad *peer; + gboolean res; + + peer = gst_pad_get_peer (pad); + if (!peer) + goto unlinked_sink; + + res = gst_pad_set_caps (peer, caps); + gst_object_unref (peer); + + if (!res) + goto peer_setcaps_failed; + } + + return TRUE; + +src_setcaps_failed: + { + /* not logging, presumably the sink pad already logged */ + return FALSE; + } +unlinked_sink: + { + GST_WARNING_OBJECT (self, "unlinked sink pad %" GST_PTR_FORMAT ", I wonder " + "how we passed activate_pull()", pad); + return FALSE; + } +peer_setcaps_failed: + { + GST_INFO_OBJECT (self, "peer of %" GST_PTR_FORMAT " did not accept caps", + pad); + return FALSE; + } +} + +static gboolean +gst_signal_processor_setcaps (GstPad * pad, GstCaps * caps) +{ + GstSignalProcessor *self; + + self = GST_SIGNAL_PROCESSOR (gst_pad_get_parent (pad)); + + if (self->mode == GST_ACTIVATE_PULL && !gst_caps_is_equal (caps, self->caps) + && !gst_signal_processor_setcaps_pull (self, pad, caps)) + goto setcaps_pull_failed; + + /* the whole processor has one caps; if the sample rate changes, let subclass + implementations know */ + if (!gst_caps_is_equal (caps, self->caps)) { + GstStructure *s; + gint sample_rate; + + GST_DEBUG_OBJECT (pad, "got caps %" GST_PTR_FORMAT, caps); + + s = gst_caps_get_structure (caps, 0); + if (!gst_structure_get_int (s, "rate", &sample_rate)) { + GST_WARNING ("got no sample-rate"); + goto impossible; + } + + GST_DEBUG_OBJECT (self, "Got rate=%d", sample_rate); + + if (GST_SIGNAL_PROCESSOR_IS_RUNNING (self)) + gst_signal_processor_stop (self); + if (GST_SIGNAL_PROCESSOR_IS_INITIALIZED (self)) + gst_signal_processor_cleanup (self); + + if (!gst_signal_processor_setup (self, sample_rate)) + goto start_or_setup_failed; + + self->sample_rate = sample_rate; + gst_caps_replace (&self->caps, caps); + } else { + GST_DEBUG_OBJECT (self, "skipping, have caps already"); + } + + /* we use this method to manage the processor's state, hence the caps clearing + in stop(). so it can be that we enter here just to manage the processor's + state, to take it to RUNNING from already being INITIALIZED with the right + sample rate (e.g., when having gone PLAYING->READY->PLAYING). make sure + when we leave that the processor is RUNNING. */ + if (!GST_SIGNAL_PROCESSOR_IS_INITIALIZED (self) + && !gst_signal_processor_setup (self, self->sample_rate)) + goto start_or_setup_failed; + if (!GST_SIGNAL_PROCESSOR_IS_RUNNING (self) + && !gst_signal_processor_start (self)) + goto start_or_setup_failed; + + gst_object_unref (self); + + return TRUE; + +start_or_setup_failed: + { + gst_object_unref (self); + return FALSE; + } +setcaps_pull_failed: + { + gst_object_unref (self); + return FALSE; + } +impossible: + { + g_critical ("something impossible happened"); + gst_object_unref (self); + return FALSE; + } +} + +static gboolean +gst_signal_processor_event (GstPad * pad, GstEvent * event) +{ + GstSignalProcessor *self; + GstSignalProcessorClass *bclass; + gboolean ret; + + self = GST_SIGNAL_PROCESSOR (gst_pad_get_parent (pad)); + bclass = GST_SIGNAL_PROCESSOR_GET_CLASS (self); + + /* FIXME, this probably isn't the correct interface: what about return values, + * what about overriding event_default + * Sync with GstBaseTransform::gst_base_transform_sink_event */ + if (bclass->event) + bclass->event (self, event); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_FLUSH_START: + break; + case GST_EVENT_FLUSH_STOP: + /* clear errors now */ + self->flow_state = GST_FLOW_OK; + break; + default: + break; + } + ret = gst_pad_event_default (pad, event); + + gst_object_unref (self); + + return ret; +} + +static guint +gst_signal_processor_prepare (GstSignalProcessor * self, guint nframes) +{ + GstElement *elem = (GstElement *) self; + GstSignalProcessorClass *klass; + GList *sinks, *srcs; + guint samples_avail = nframes; + + klass = GST_SIGNAL_PROCESSOR_GET_CLASS (self); + + /* first, assign audio_in pointers, and determine the number of samples that + * we can process */ + for (sinks = elem->sinkpads; sinks; sinks = sinks->next) { + GstSignalProcessorPad *sinkpad; + + sinkpad = (GstSignalProcessorPad *) sinks->data; + g_assert (sinkpad->samples_avail > 0); + samples_avail = MIN (samples_avail, sinkpad->samples_avail); + self->audio_in[sinkpad->index] = sinkpad->data; + } + + /* FIXME: return if samples_avail==0 ? */ + + /* now assign output buffers. we can avoid allocation by reusing input + buffers, but only if process() can work in place, and if the input buffer + is the exact size of the number of samples we are processing. */ + sinks = elem->sinkpads; + srcs = elem->srcpads; + if (GST_SIGNAL_PROCESSOR_CLASS_CAN_PROCESS_IN_PLACE (klass)) { + while (sinks && srcs) { + GstSignalProcessorPad *sinkpad, *srcpad; + + sinkpad = (GstSignalProcessorPad *) sinks->data; + srcpad = (GstSignalProcessorPad *) srcs->data; + + if (GST_BUFFER_SIZE (sinkpad->pen) == samples_avail * sizeof (gfloat)) { + /* reusable, yay */ + g_assert (sinkpad->samples_avail == samples_avail); + srcpad->pen = sinkpad->pen; + sinkpad->pen = NULL; + self->audio_out[srcpad->index] = sinkpad->data; + self->pending_out++; + + srcs = srcs->next; + } + + sinks = sinks->next; + } + } + + g_return_val_if_fail (GST_SIGNAL_PROCESSOR_IS_RUNNING (self), 0); + + /* now allocate for any remaining outputs */ + while (srcs) { + GstSignalProcessorPad *srcpad; + GstFlowReturn ret; + + srcpad = (GstSignalProcessorPad *) srcs->data; + + ret = + gst_pad_alloc_buffer_and_set_caps (GST_PAD (srcpad), -1, + samples_avail * sizeof (gfloat), self->caps, &srcpad->pen); + + if (ret != GST_FLOW_OK) { + self->flow_state = ret; + return 0; + } else { + self->audio_out[srcpad->index] = (gfloat *) GST_BUFFER_DATA (srcpad->pen); + self->pending_out++; + } + + srcs = srcs->next; + } + + return samples_avail; +} + +static void +gst_signal_processor_update_inputs (GstSignalProcessor * self, guint nprocessed) +{ + GstElement *elem = (GstElement *) self; + GList *sinks; + + for (sinks = elem->sinkpads; sinks; sinks = sinks->next) { + GstSignalProcessorPad *sinkpad; + + sinkpad = (GstSignalProcessorPad *) sinks->data; + g_assert (sinkpad->samples_avail >= nprocessed); + + if (sinkpad->pen && sinkpad->samples_avail == nprocessed) { + /* used up this buffer, unpen */ + gst_buffer_unref (sinkpad->pen); + sinkpad->pen = NULL; + } + + if (!sinkpad->pen) { + /* this buffer was used up */ + self->pending_in++; + sinkpad->data = NULL; + sinkpad->samples_avail = 0; + } else { + /* advance ->data pointers and decrement ->samples_avail, unreffing buffer + if no samples are left */ + sinkpad->samples_avail -= nprocessed; + sinkpad->data += nprocessed; /* gfloat* arithmetic */ + } + } +} + +static void +gst_signal_processor_process (GstSignalProcessor * self, guint nframes) +{ + GstElement *elem; + GstSignalProcessorClass *klass; + + /* check if we have buffers enqueued */ + g_return_if_fail (self->pending_in == 0); + g_return_if_fail (self->pending_out == 0); + + elem = GST_ELEMENT (self); + + /* check how much input is available and prepare output buffers */ + nframes = gst_signal_processor_prepare (self, nframes); + if (G_UNLIKELY (nframes == 0)) + goto flow_error; + + klass = GST_SIGNAL_PROCESSOR_GET_CLASS (self); + + GST_LOG_OBJECT (self, "process(%u)", nframes); + + klass->process (self, nframes); + + gst_signal_processor_update_inputs (self, nframes); + + return; + +flow_error: + { + GST_WARNING ("gst_pad_alloc_buffer_and_set_caps() returned %d", + self->flow_state); + return; + } +} + +static void +gst_signal_processor_pen_buffer (GstSignalProcessor * self, GstPad * pad, + GstBuffer * buffer) +{ + GstSignalProcessorPad *spad = (GstSignalProcessorPad *) pad; + + if (spad->pen) + goto had_buffer; + + /* keep the reference */ + spad->pen = buffer; + spad->data = (gfloat *) GST_BUFFER_DATA (buffer); + spad->samples_avail = GST_BUFFER_SIZE (buffer) / sizeof (float); + + g_assert (self->pending_in != 0); + + self->pending_in--; + + return; + + /* ERRORS */ +had_buffer: + { + GST_WARNING ("Pad %s:%s already has penned buffer", + GST_DEBUG_PAD_NAME (pad)); + gst_buffer_unref (buffer); + return; + } +} + +static void +gst_signal_processor_flush (GstSignalProcessor * self) +{ + GList *pads; + GstSignalProcessorClass *klass; + + klass = GST_SIGNAL_PROCESSOR_GET_CLASS (self); + + GST_INFO_OBJECT (self, "flush()"); + + /* release enqueued buffers */ + for (pads = GST_ELEMENT (self)->pads; pads; pads = pads->next) { + GstSignalProcessorPad *spad = (GstSignalProcessorPad *) pads->data; + + if (spad->pen) { + gst_buffer_unref (spad->pen); + spad->pen = NULL; + spad->data = NULL; + spad->samples_avail = 0; + } + } + + /* no outputs prepared and inputs for each pad needed */ + self->pending_out = 0; + self->pending_in = klass->num_audio_in; +} + +static void +gst_signal_processor_do_pulls (GstSignalProcessor * self, guint nframes) +{ + GList *sinkpads; + + /* FIXME: not threadsafe atm */ + + sinkpads = GST_ELEMENT (self)->sinkpads; + + for (; sinkpads; sinkpads = sinkpads->next) { + GstSignalProcessorPad *spad = (GstSignalProcessorPad *) sinkpads->data; + GstFlowReturn ret = GST_FLOW_OK; + GstBuffer *buf; + + if (spad->pen) { + g_warning ("Unexpectedly full buffer pen for pad %s:%s", + GST_DEBUG_PAD_NAME (spad)); + continue; + } + + ret = + gst_pad_pull_range (GST_PAD (spad), -1, nframes * sizeof (gfloat), + &buf); + + if (ret != GST_FLOW_OK) { + gst_signal_processor_flush (self); + self->flow_state = ret; + return; + } else if (!buf) { + g_critical ("Pull failed to make a buffer!"); + self->flow_state = GST_FLOW_ERROR; + return; + } else { + gst_signal_processor_pen_buffer (self, GST_PAD (spad), buf); + } + } + + if (self->pending_in != 0) { + g_critical ("Something wierd happened..."); + self->flow_state = GST_FLOW_ERROR; + } else { + gst_signal_processor_process (self, nframes); + } +} + +static GstFlowReturn +gst_signal_processor_getrange (GstPad * pad, guint64 offset, + guint length, GstBuffer ** buffer) +{ + GstSignalProcessor *self; + GstSignalProcessorPad *spad = (GstSignalProcessorPad *) pad; + GstFlowReturn ret = GST_FLOW_ERROR; + + self = GST_SIGNAL_PROCESSOR (gst_pad_get_parent (pad)); + + if (spad->pen) { + *buffer = spad->pen; + spad->pen = NULL; + g_assert (self->pending_out != 0); + self->pending_out--; + ret = GST_FLOW_OK; + } else { + gst_signal_processor_do_pulls (self, length / sizeof (gfloat)); + if (!spad->pen) { + /* this is an error condition */ + *buffer = NULL; + ret = self->flow_state; + } else { + *buffer = spad->pen; + spad->pen = NULL; + self->pending_out--; + ret = GST_FLOW_OK; + } + } + + GST_DEBUG_OBJECT (self, "returns %s", gst_flow_get_name (ret)); + + gst_object_unref (self); + + return ret; +} + +static void +gst_signal_processor_do_pushes (GstSignalProcessor * self) +{ + GList *srcpads; + + /* not threadsafe atm */ + + srcpads = GST_ELEMENT (self)->srcpads; + + for (; srcpads; srcpads = srcpads->next) { + GstSignalProcessorPad *spad = (GstSignalProcessorPad *) srcpads->data; + GstFlowReturn ret = GST_FLOW_OK; + GstBuffer *buffer; + + if (!spad->pen) { + g_warning ("Unexpectedly empty buffer pen for pad %s:%s", + GST_DEBUG_PAD_NAME (spad)); + continue; + } + + /* take buffer from pen */ + buffer = spad->pen; + spad->pen = NULL; + + ret = gst_pad_push (GST_PAD (spad), buffer); + + if (ret != GST_FLOW_OK) { + gst_signal_processor_flush (self); + self->flow_state = ret; + return; + } else { + g_assert (self->pending_out > 0); + self->pending_out--; + } + } + + if (self->pending_out != 0) { + g_critical ("Something wierd happened..."); + self->flow_state = GST_FLOW_ERROR; + } +} + +static GstFlowReturn +gst_signal_processor_chain (GstPad * pad, GstBuffer * buffer) +{ + GstSignalProcessor *self; + + self = GST_SIGNAL_PROCESSOR (gst_pad_get_parent (pad)); + + gst_signal_processor_pen_buffer (self, pad, buffer); + + if (self->pending_in == 0) { + gst_signal_processor_process (self, G_MAXUINT); + + gst_signal_processor_do_pushes (self); + } + + gst_object_unref (self); + + return self->flow_state; +} + +static gboolean +gst_signal_processor_sink_activate_push (GstPad * pad, gboolean active) +{ + gboolean result = TRUE; + GstSignalProcessor *self; + GstSignalProcessorClass *bclass; + + self = GST_SIGNAL_PROCESSOR (gst_pad_get_parent (pad)); + bclass = GST_SIGNAL_PROCESSOR_GET_CLASS (self); + + if (active) { + if (self->mode == GST_ACTIVATE_NONE) { + self->mode = GST_ACTIVATE_PUSH; + result = TRUE; + } else if (self->mode == GST_ACTIVATE_PUSH) { + result = TRUE; + } else { + g_warning ("foo"); + result = FALSE; + } + } else { + if (self->mode == GST_ACTIVATE_NONE) { + result = TRUE; + } else if (self->mode == GST_ACTIVATE_PUSH) { + self->mode = GST_ACTIVATE_NONE; + result = TRUE; + } else { + g_warning ("foo"); + result = FALSE; + } + } + + GST_DEBUG_OBJECT (self, "result : %d", result); + + gst_object_unref (self); + + return result; +} + +static gboolean +gst_signal_processor_src_activate_pull (GstPad * pad, gboolean active) +{ + gboolean result = TRUE; + GstSignalProcessor *self; + GstSignalProcessorClass *bclass; + + self = GST_SIGNAL_PROCESSOR (gst_pad_get_parent (pad)); + bclass = GST_SIGNAL_PROCESSOR_GET_CLASS (self); + + if (active) { + if (self->mode == GST_ACTIVATE_NONE) { + GList *l; + + for (l = GST_ELEMENT (self)->sinkpads; l; l = l->next) + result &= gst_pad_activate_pull (pad, active); + if (result) + self->mode = GST_ACTIVATE_PULL; + } else if (self->mode == GST_ACTIVATE_PULL) { + result = TRUE; + } else { + g_warning ("foo"); + result = FALSE; + } + } else { + if (self->mode == GST_ACTIVATE_NONE) { + result = TRUE; + } else if (self->mode == GST_ACTIVATE_PULL) { + GList *l; + + for (l = GST_ELEMENT (self)->sinkpads; l; l = l->next) + result &= gst_pad_activate_pull (pad, active); + if (result) + self->mode = GST_ACTIVATE_NONE; + result = TRUE; + } else { + g_warning ("foo"); + result = FALSE; + } + } + + GST_DEBUG_OBJECT (self, "result : %d", result); + + gst_object_unref (self); + + return result; +} + +static GstStateChangeReturn +gst_signal_processor_change_state (GstElement * element, + GstStateChange transition) +{ + GstSignalProcessor *self; + GstStateChangeReturn result; + + self = GST_SIGNAL_PROCESSOR (element); + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + break; + case GST_STATE_CHANGE_READY_TO_PAUSED: + self->flow_state = GST_FLOW_OK; + break; + case GST_STATE_CHANGE_PAUSED_TO_PLAYING: + break; + default: + break; + } + + if ((result = + GST_ELEMENT_CLASS (parent_class)->change_state (element, + transition)) == GST_STATE_CHANGE_FAILURE) + goto failure; + + switch (transition) { + case GST_STATE_CHANGE_PLAYING_TO_PAUSED: + break; + case GST_STATE_CHANGE_PAUSED_TO_READY: + if (GST_SIGNAL_PROCESSOR_IS_RUNNING (self)) + gst_signal_processor_stop (self); + gst_signal_processor_flush (self); + break; + case GST_STATE_CHANGE_READY_TO_NULL: + if (GST_SIGNAL_PROCESSOR_IS_INITIALIZED (self)) + gst_signal_processor_cleanup (self); + break; + default: + break; + } + + return result; + + /* ERRORS */ +failure: + { + GST_DEBUG_OBJECT (element, "parent failed state change"); + return result; + } +} diff --git a/gst-libs/gst/signalprocessor/gstsignalprocessor.h b/gst-libs/gst/signalprocessor/gstsignalprocessor.h new file mode 100644 index 00000000..d6f0d0b0 --- /dev/null +++ b/gst-libs/gst/signalprocessor/gstsignalprocessor.h @@ -0,0 +1,124 @@ +/* GStreamer + * Copyright (C) 1999,2000 Erik Walthinsen + * 2005 Wim Taymans + * + * gstsignalprocessor.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_SIGNAL_PROCESSOR_H__ +#define __GST_SIGNAL_PROCESSOR_H__ + +#include + +G_BEGIN_DECLS + + +typedef enum +{ + GST_SIGNAL_PROCESSOR_CLASS_FLAG_CAN_PROCESS_IN_PLACE = 1<<0 +} GstSignalProcessorClassFlags; + +#define GST_SIGNAL_PROCESSOR_CLASS_CAN_PROCESS_IN_PLACE(klass) \ + (GST_SIGNAL_PROCESSOR_CLASS (klass)->flags & \ + GST_SIGNAL_PROCESSOR_CLASS_FLAG_CAN_PROCESS_IN_PLACE) +#define GST_SIGNAL_PROCESSOR_CLASS_SET_CAN_PROCESS_IN_PLACE(klass) \ + GST_SIGNAL_PROCESSOR_CLASS (klass)->flags |= \ + GST_SIGNAL_PROCESSOR_CLASS_FLAG_CAN_PROCESS_IN_PLACE + +typedef enum +{ + GST_SIGNAL_PROCESSOR_STATE_NULL, + GST_SIGNAL_PROCESSOR_STATE_INITIALIZED, + GST_SIGNAL_PROCESSOR_STATE_RUNNING +} GstSignalProcessorState; + + +#define GST_TYPE_SIGNAL_PROCESSOR (gst_signal_processor_get_type()) +#define GST_SIGNAL_PROCESSOR(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_SIGNAL_PROCESSOR,GstSignalProcessor)) +#define GST_SIGNAL_PROCESSOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_SIGNAL_PROCESSOR,GstSignalProcessorClass)) +#define GST_SIGNAL_PROCESSOR_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj),GST_TYPE_SIGNAL_PROCESSOR,GstSignalProcessorClass)) +#define GST_IS_SIGNAL_PROCESSOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_SIGNAL_PROCESSOR)) +#define GST_IS_SIGNAL_PROCESSOR_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_SIGNAL_PROCESSOR)) + +#define GST_SIGNAL_PROCESSOR_IS_INITIALIZED(obj) \ + (GST_SIGNAL_PROCESSOR (obj)->state >= GST_SIGNAL_PROCESSOR_STATE_INITIALIZED) +#define GST_SIGNAL_PROCESSOR_IS_RUNNING(obj) \ + (GST_SIGNAL_PROCESSOR (obj)->state == GST_SIGNAL_PROCESSOR_STATE_RUNNING) + +typedef struct _GstSignalProcessor GstSignalProcessor; +typedef struct _GstSignalProcessorClass GstSignalProcessorClass; + + +struct _GstSignalProcessor { + GstElement element; + + GstCaps *caps; + + guint sample_rate; + + GstSignalProcessorState state; + + GstFlowReturn flow_state; + + GstActivateMode mode; + + /* pending inputs before processing can take place */ + guint pending_in; + /* panding outputs to be filled */ + guint pending_out; + + gfloat *control_in; + gfloat **audio_in; + gfloat *control_out; + gfloat **audio_out; +}; + +struct _GstSignalProcessorClass { + GstElementClass parent_class; + + /*< public >*/ + guint num_control_in; + guint num_audio_in; + guint num_control_out; + guint num_audio_out; + + guint flags; + + /* virtual methods for subclasses */ + + gboolean (*setup) (GstSignalProcessor *self, guint sample_rate); + gboolean (*start) (GstSignalProcessor *self); + void (*stop) (GstSignalProcessor *self); + void (*cleanup) (GstSignalProcessor *self); + void (*process) (GstSignalProcessor *self, guint num_frames); + gboolean (*event) (GstSignalProcessor *self, GstEvent *event); +}; + + +GType gst_signal_processor_get_type (void); +void gst_signal_processor_class_add_pad_template (GstSignalProcessorClass *klass, + const gchar *name, GstPadDirection direction, guint index); + + + +G_END_DECLS + + +#endif /* __GST_SIGNAL_PROCESSOR_H__ */ -- cgit v1.2.1 From 74f065ee755838ab8fd34b76840e0660a13b5ff8 Mon Sep 17 00:00:00 2001 From: Stefan Kost Date: Mon, 22 Jun 2009 23:49:03 +0300 Subject: camerabin: add local include dir to CFLAGS --- gst/camerabin/Makefile.am | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gst/camerabin/Makefile.am b/gst/camerabin/Makefile.am index d5085da9..e3fdfae0 100644 --- a/gst/camerabin/Makefile.am +++ b/gst/camerabin/Makefile.am @@ -23,7 +23,9 @@ libgstcamerabin_la_SOURCES = gstcamerabin.c \ nodist_libgstcamerabin_la_SOURCES = $(built_sources) libgstcamerabin_la_CFLAGS = \ - $(GST_CFLAGS) $(GST_BASE_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) -DGST_USE_UNSTABLE_API + -I$(top_builddir)/gst-libs \ + $(GST_CFLAGS) $(GST_BASE_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) \ + -DGST_USE_UNSTABLE_API libgstcamerabin_la_LIBADD = \ $(top_builddir)/gst-libs/gst/interfaces/libgstphotography-$(GST_MAJORMINOR).la \ $(GST_LIBS) $(GST_BASE_LIBS) $(GST_PLUGINS_BASE_LIBS) \ -- cgit v1.2.1 From a2a0322df9a7005a01aafb5efc32fcc1179d205c Mon Sep 17 00:00:00 2001 From: Stefan Kost Date: Mon, 22 Jun 2009 23:50:49 +0300 Subject: signalprocessor: use $(top_builddir) instead of relative paths --- ext/ladspa/Makefile.am | 10 ++++++++-- ext/ladspa/gstladspa.h | 2 +- ext/lv2/Makefile.am | 10 ++++++++-- ext/lv2/gstlv2.h | 2 +- 4 files changed, 18 insertions(+), 6 deletions(-) diff --git a/ext/ladspa/Makefile.am b/ext/ladspa/Makefile.am index 00582ed7..23c84f57 100644 --- a/ext/ladspa/Makefile.am +++ b/ext/ladspa/Makefile.am @@ -1,8 +1,14 @@ plugin_LTLIBRARIES = libgstladspa.la libgstladspa_la_SOURCES = gstladspa.c -libgstladspa_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CONTROLLER_CFLAGS) $(GST_CFLAGS) $(LRDF_CFLAGS) -libgstladspa_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) -lgstaudio-$(GST_MAJORMINOR) $(LIBM) $(LRDF_LIBS) ../../gst-libs/gst/signalprocessor/libgstsignalprocessor.la +libgstladspa_la_CFLAGS = \ + -I$(top_builddir)/gst-libs \ + $(GST_PLUGINS_BASE_CFLAGS) \ + $(GST_CONTROLLER_CFLAGS) $(GST_CFLAGS) $(LRDF_CFLAGS) +libgstladspa_la_LIBADD = \ + $(top_builddir)/gst-libs/gst/signalprocessor/libgstsignalprocessor.la \ + $(GST_PLUGINS_BASE_LIBS) -lgstaudio-$(GST_MAJORMINOR) \ + $(LIBM) $(LRDF_LIBS) libgstladspa_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) libgstladspa_la_LIBTOOLFLAGS = --tag=disable-static diff --git a/ext/ladspa/gstladspa.h b/ext/ladspa/gstladspa.h index f51d6233..14532318 100644 --- a/ext/ladspa/gstladspa.h +++ b/ext/ladspa/gstladspa.h @@ -28,7 +28,7 @@ #include -#include "../../gst-libs/gst/signalprocessor/gstsignalprocessor.h" +#include G_BEGIN_DECLS diff --git a/ext/lv2/Makefile.am b/ext/lv2/Makefile.am index f10c7acf..18fe6481 100644 --- a/ext/lv2/Makefile.am +++ b/ext/lv2/Makefile.am @@ -1,8 +1,14 @@ plugin_LTLIBRARIES = libgstlv2.la libgstlv2_la_SOURCES = gstlv2.c -libgstlv2_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CONTROLLER_CFLAGS) $(GST_CFLAGS) $(SLV2_CFLAGS) -libgstlv2_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) -lgstaudio-$(GST_MAJORMINOR) $(LIBM) $(SLV2_LIBS) ../../gst-libs/gst/signalprocessor/libgstsignalprocessor.la +libgstlv2_la_CFLAGS = \ + -I$(top_builddir)/gst-libs \ + $(GST_PLUGINS_BASE_CFLAGS) \ + $(GST_CONTROLLER_CFLAGS) $(GST_CFLAGS) $(SLV2_CFLAGS) +libgstlv2_la_LIBADD = \ + $(top_builddir)/gst-libs/gst/signalprocessor/libgstsignalprocessor.la \ + $(GST_PLUGINS_BASE_LIBS) -lgstaudio-$(GST_MAJORMINOR) \ + $(LIBM) $(SLV2_LIBS) libgstlv2_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) libgstlv2_la_LIBTOOLFLAGS = --tag=disable-static diff --git a/ext/lv2/gstlv2.h b/ext/lv2/gstlv2.h index f76235b4..389c03d1 100644 --- a/ext/lv2/gstlv2.h +++ b/ext/lv2/gstlv2.h @@ -28,7 +28,7 @@ #include -#include "../../gst-libs/gst/signalprocessor/gstsignalprocessor.h" +#include G_BEGIN_DECLS -- cgit v1.2.1