diff -Nru gst-plugin-ducati-1.6.7.2/debian/changelog gst-plugin-ducati-1.6.7.20/debian/changelog --- gst-plugin-ducati-1.6.7.2/debian/changelog 2012-10-02 13:44:54.000000000 +0000 +++ gst-plugin-ducati-1.6.7.20/debian/changelog 2012-12-06 15:48:23.000000000 +0000 @@ -1,3 +1,33 @@ +gst-plugin-ducati (1.6.7.20-1) precise; urgency=low + + * Imported Upstream version 1.6.7.20 based on commit 8e3e9454 + + -- Olivier Naudan Thu, 06 Dec 2012 15:48:12 +0000 + +gst-plugin-ducati (1.6.7.19-1) precise; urgency=low + + * Imported Upstream version 1.6.7.19 based on commit f5bbf1dd + + -- Olivier Naudan Wed, 28 Nov 2012 12:36:56 +0000 + +gst-plugin-ducati (1.6.7.16-1) precise; urgency=low + + * Imported Upstream version 1.6.7.16 based on commit c3072214 + + -- Olivier Naudan Fri, 26 Oct 2012 08:40:08 -0400 + +gst-plugin-ducati (1.6.7.6-1) precise; urgency=low + + * Imported Upstream version 1.6.7.6 based on commit f3d6195e + + -- Olivier Naudan Thu, 18 Oct 2012 07:29:00 -0400 + +gst-plugin-ducati (1.6.7.4-1) precise; urgency=low + + * Imported Upstream version 1.6.7.4 based on commit d8913a75 + + -- Olivier Naudan Tue, 09 Oct 2012 12:23:19 -0400 + gst-plugin-ducati (1.6.7.2-1) precise; urgency=low * Imported Upstream version 1.6.7.2 based on commit 47cd28af diff -Nru gst-plugin-ducati-1.6.7.2/src/Makefile.am gst-plugin-ducati-1.6.7.20/src/Makefile.am --- gst-plugin-ducati-1.6.7.2/src/Makefile.am 2012-10-02 13:38:43.000000000 +0000 +++ gst-plugin-ducati-1.6.7.20/src/Makefile.am 2012-12-06 15:48:06.000000000 +0000 @@ -2,13 +2,11 @@ # headers we need but don't want installed noinst_HEADERS = \ - gstducatirvdec.h \ - gstducativp7dec.h \ - gstducativp6dec.h \ gstducativc1dec.h \ gstducatimpeg2dec.h \ gstducatimpeg4dec.h \ gstducatih264dec.h \ + gstducatijpegdec.h \ gstducatividdec.h \ gstducatih264enc.h \ gstducatimpeg4enc.h \ @@ -18,13 +16,11 @@ # sources used to compile this plug-in libgstducati_la_SOURCES = \ - gstducatirvdec.c \ - gstducativp7dec.c \ - gstducativp6dec.c \ gstducativc1dec.c \ gstducatimpeg2dec.c \ gstducatimpeg4dec.c \ gstducatih264dec.c \ + gstducatijpegdec.c \ gstducatividdec.c \ gstducatih264enc.c \ gstducatimpeg4enc.c \ @@ -37,6 +33,7 @@ libgstducati_la_CFLAGS = \ $(GST_CFLAGS) \ $(LIBDCE_CFLAGS) \ + -Wno-unused-variable \ -DGST_USE_UNSTABLE_API libgstducati_la_LIBADD = \ diff -Nru gst-plugin-ducati-1.6.7.2/src/gstducati.c gst-plugin-ducati-1.6.7.20/src/gstducati.c --- gst-plugin-ducati-1.6.7.2/src/gstducati.c 2012-10-02 13:38:43.000000000 +0000 +++ gst-plugin-ducati-1.6.7.20/src/gstducati.c 2012-12-06 15:48:06.000000000 +0000 @@ -26,26 +26,40 @@ #include "gstducatimpeg4dec.h" #include "gstducatimpeg2dec.h" #include "gstducativc1dec.h" -#include "gstducativp6dec.h" -#include "gstducativp7dec.h" -#include "gstducatirvdec.h" +#include "gstducatijpegdec.h" #include "gstducatih264enc.h" #include "gstducatimpeg4enc.h" GST_DEBUG_CATEGORY (gst_ducati_debug); +void +gst_ducati_set_generic_error_strings (const char *strings[]) +{ +#ifndef GST_DISABLE_GST_DEBUG + strings[XDM_PARAMSCHANGE] = "sequence parameters change"; + strings[XDM_APPLIEDCONCEALMENT] = "applied concealment"; + strings[XDM_INSUFFICIENTDATA] = "insufficient data"; + strings[XDM_CORRUPTEDDATA] = "corrupted data"; + strings[XDM_CORRUPTEDHEADER] = "corrupted header"; + strings[XDM_UNSUPPORTEDINPUT] = "unsupported input"; + strings[XDM_UNSUPPORTEDPARAM] = "unsupported param"; + strings[XDM_FATALERROR] = "fatal"; +#endif +} + #ifndef GST_DISABLE_GST_DEBUG void -gst_ducati_log_extended_error_info (int error) +gst_ducati_log_extended_error_info (uint32_t error, const char *strings[]) { - GST_ERROR ("Error %s%s%s%s%s%s%s%x", - XDM_ISFATALERROR (error) ? "[fatal] " : "", - XDM_ISUNSUPPORTEDPARAM (error) ? "[unsupported param] " : "", - XDM_ISUNSUPPORTEDINPUT (error) ? "[unsupported input] " : "", - XDM_ISCORRUPTEDHEADER (error) ? "[corrupted header] " : "", - XDM_ISCORRUPTEDDATA (error) ? "[corrupted data] " : "", - XDM_ISINSUFFICIENTDATA (error) ? "[insufficient data] " : "", - XDM_ISAPPLIEDCONCEALMENT (error) ? "[applied concealment] " : "", error); + int bit = 0; + while (error) { + if (error & 1) { + GST_ERROR ("Bit %d (%08x): %s", bit, 1 << bit, + strings[bit] ? strings[bit] : "unknown"); + } + error >>= 1; + ++bit; + } } #endif @@ -54,9 +68,6 @@ { GST_DEBUG_CATEGORY_INIT (gst_ducati_debug, "ducati", 0, "ducati"); - /* TODO .. find some way to reasonably detect if the corresponding - * codecs are actually available.. - */ return gst_element_register (plugin, "ducatih264dec", GST_RANK_PRIMARY, GST_TYPE_DUCATIH264DEC) && gst_element_register (plugin, "ducatimpeg4dec", GST_RANK_PRIMARY, @@ -65,12 +76,8 @@ GST_TYPE_DUCATIMPEG2DEC) && gst_element_register (plugin, "ducativc1dec", GST_RANK_PRIMARY, GST_TYPE_DUCATIVC1DEC) && - gst_element_register (plugin, "ducativp6dec", GST_RANK_PRIMARY, - GST_TYPE_DUCATIVP6DEC) && - gst_element_register (plugin, "ducativp7dec", GST_RANK_PRIMARY, - GST_TYPE_DUCATIVP7DEC) && - gst_element_register (plugin, "ducatirvdec", GST_RANK_PRIMARY, - GST_TYPE_DUCATIRVDEC) && + gst_element_register (plugin, "ducatijpegdec", GST_RANK_PRIMARY, + GST_TYPE_DUCATIJPEGDEC) && gst_element_register (plugin, "ducatih264enc", GST_RANK_PRIMARY + 1, GST_TYPE_DUCATIH264ENC) && gst_element_register (plugin, "ducatimpeg4enc", GST_RANK_PRIMARY + 1, diff -Nru gst-plugin-ducati-1.6.7.2/src/gstducati.h gst-plugin-ducati-1.6.7.20/src/gstducati.h --- gst-plugin-ducati-1.6.7.2/src/gstducati.h 2012-10-02 13:38:43.000000000 +0000 +++ gst-plugin-ducati-1.6.7.20/src/gstducati.h 2012-12-06 15:48:06.000000000 +0000 @@ -41,7 +41,8 @@ G_END_DECLS #ifndef GST_DISABLE_GST_DEBUG -extern void gst_ducati_log_extended_error_info (int error); +extern void gst_ducati_set_generic_error_strings (const char * strings[]); +extern void gst_ducati_log_extended_error_info (uint32_t error, const char *strings[]); #else #define gst_ducati_log_extended_error_info(f) ((void)0) #endif diff -Nru gst-plugin-ducati-1.6.7.2/src/gstducatibuffer.c gst-plugin-ducati-1.6.7.20/src/gstducatibuffer.c --- gst-plugin-ducati-1.6.7.2/src/gstducatibuffer.c 2012-10-02 13:38:43.000000000 +0000 +++ gst-plugin-ducati-1.6.7.20/src/gstducatibuffer.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,138 +0,0 @@ -/* - * GStreamer - * - * Copyright (C) 2012 Texas Instruments - * Copyright (C) 2012 Collabora Ltd - * - * Authors: - * Alessandro Decina - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation - * version 2.1 of the License. - * - * 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "gstducatibuffer.h" -#include "gstducatibufferpool.h" - -G_DEFINE_TYPE (GstDucatiBuffer, gst_ducati_buffer, GST_TYPE_BUFFER); -G_DEFINE_TYPE (GstDucatiBufferAllocator, gst_ducati_buffer_allocator, - GST_TYPE_MINI_OBJECT); - -GstDucatiBuffer * -gst_ducati_buffer_new (GstDucatiBufferPool * pool) -{ - GstDucatiBuffer *self = (GstDucatiBuffer *) - gst_mini_object_new (GST_TYPE_DUCATI_BUFFER); - gst_ducati_buffer_set_pool (self, pool); - - return self; -} - -void -gst_ducati_buffer_set_pool (GstDucatiBuffer * self, GstDucatiBufferPool * pool) -{ - - GST_LOG_OBJECT (pool->element, "creating buffer %p in pool %p", self, pool); - - self->pool = (GstDucatiBufferPool *) - gst_mini_object_ref (GST_MINI_OBJECT (pool)); - self->remove_from_pool = FALSE; - - if (pool->caps) - gst_buffer_set_caps (GST_BUFFER (self), pool->caps); -} - -static void -gst_ducati_buffer_finalize (GstDucatiBuffer * self) -{ - GstDucatiBufferPool *pool = self->pool; - gboolean resuscitated = FALSE; - - GST_LOG_OBJECT (pool->element, "finalizing buffer %p", self); - - resuscitated = gst_ducati_buffer_pool_put (pool, self); - if (resuscitated) - return; - - if (self->orig) { - gst_buffer_unref (self->orig); - self->orig = NULL; - } - - GST_BUFFER_DATA (self) = NULL; - gst_mini_object_unref (GST_MINI_OBJECT (pool)); - - GST_MINI_OBJECT_CLASS (gst_ducati_buffer_parent_class)->finalize - (GST_MINI_OBJECT (self)); -} - -static void -gst_ducati_buffer_class_init (GstDucatiBufferClass * klass) -{ - GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (klass); - - mini_object_class->finalize = (GstMiniObjectFinalizeFunction) - GST_DEBUG_FUNCPTR (gst_ducati_buffer_finalize); -} - -static void -gst_ducati_buffer_init (GstDucatiBuffer * buffer) -{ -} - -/* Get the original buffer, or whatever is the best output buffer. - * Consumes the input reference, produces the output reference - */ -GstBuffer * -gst_ducati_buffer_get (GstDucatiBuffer * self) -{ - if (self->orig) { - // TODO copy to orig buffer.. if needed. - gst_buffer_unref (self->orig); - self->orig = NULL; - } - return GST_BUFFER (self); -} - -/* GstDucatiBufferAllocator */ - -GstDucatiBufferAllocator * -gst_ducati_buffer_allocator_new (void) -{ - GstDucatiBufferAllocator *self = (GstDucatiBufferAllocator *) - gst_mini_object_new (GST_TYPE_DUCATI_BUFFER_ALLOCATOR); - - return self; -} - -static void -gst_ducati_buffer_allocator_finalize (GstDucatiBufferAllocator * self) -{ - GST_MINI_OBJECT_CLASS (gst_ducati_buffer_allocator_parent_class)->finalize - (GST_MINI_OBJECT (self)); -} - -static void -gst_ducati_buffer_allocator_class_init (GstDucatiBufferAllocatorClass * klass) -{ - GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (klass); - - mini_object_class->finalize = (GstMiniObjectFinalizeFunction) - GST_DEBUG_FUNCPTR (gst_ducati_buffer_allocator_finalize); -} - -static void -gst_ducati_buffer_allocator_init (GstDucatiBufferAllocator * buffer) -{ -} diff -Nru gst-plugin-ducati-1.6.7.2/src/gstducatibuffer.h gst-plugin-ducati-1.6.7.20/src/gstducatibuffer.h --- gst-plugin-ducati-1.6.7.2/src/gstducatibuffer.h 2012-10-02 13:38:43.000000000 +0000 +++ gst-plugin-ducati-1.6.7.20/src/gstducatibuffer.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,92 +0,0 @@ -/* - * GStreamer - * - * Copyright (C) 2012 Texas Instruments - * Copyright (C) 2012 Collabora Ltd - * - * Authors: - * Alessandro Decina - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation - * version 2.1 of the License. - * - * 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef __GSTDUCATIBUFFER_H__ -#define __GSTDUCATIBUFFER_H__ - -#include "gstducati.h" -#include - -G_BEGIN_DECLS - -#define GST_TYPE_DUCATI_BUFFER (gst_ducati_buffer_get_type()) -#define GST_IS_DUCATI_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DUCATI_BUFFER)) -#define GST_DUCATI_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DUCATI_BUFFER, GstDucatiBuffer)) - -#define GST_TYPE_DUCATI_BUFFER_ALLOCATOR (gst_ducati_buffer_allocator_get_type()) -#define GST_IS_DUCATI_BUFFER_ALLOCATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DUCATI_BUFFER_ALLOCATOR)) -#define GST_DUCATI_BUFFER_ALLOCATOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DUCATI_BUFFER_ALLOCATOR, GstDucatiBufferAllocator)) -#define GST_DUCATI_BUFFER_ALLOCATOR_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_DUCATI_BUFFER_ALLOCATOR, GstDucatiBufferAllocatorClass)) -#define GST_DUCATI_BUFFER_ALLOCATOR_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_DUCATI_BUFFER_ALLOCATOR, GstDucatiBufferAllocatorClass)) - -typedef struct _GstDucatiBufferAllocator GstDucatiBufferAllocator; -typedef struct _GstDucatiBufferAllocatorClass GstDucatiBufferAllocatorClass; -typedef struct _GstDucatiBuffer GstDucatiBuffer; -typedef struct _GstDucatiBufferClass GstDucatiBufferClass; - -/* forward declaration */ -struct _GstDucatiBufferPool; - -struct _GstDucatiBufferAllocator -{ - GstMiniObject mini_object; -}; - -struct _GstDucatiBufferAllocatorClass -{ - GstMiniObjectClass klass; - - GstBuffer *(*alloc) (GstDucatiBufferAllocator * self, - struct _GstDucatiBufferPool * pool); - gboolean (*check_compatible) (GstDucatiBufferAllocator * allocator, - GstBuffer * buffer); - void (*setup_codec_output_buffers) (GstDucatiBufferAllocator * allocator, - GstVideoFormat format, int width, int height, int stride, GstBuffer * buf, - XDM2_BufDesc * bufs); -}; - -struct _GstDucatiBuffer { - GstBuffer parent; - - struct _GstDucatiBufferPool *pool; /* buffer-pool that this buffer belongs to */ - GstBuffer *orig; /* original buffer, if we need to copy output */ - GstDucatiBuffer *next; /* next in freelist, if not in use */ - gboolean remove_from_pool; -}; - -struct _GstDucatiBufferClass { - GstBufferClass klass; -}; - -GType gst_ducati_buffer_allocator_get_type (void); -GstDucatiBufferAllocator *gst_ducati_buffer_allocator_new (void); - -GType gst_ducati_buffer_get_type (void); -GstDucatiBuffer *gst_ducati_buffer_new (struct _GstDucatiBufferPool * pool); -void gst_ducati_buffer_set_pool (GstDucatiBuffer * self, struct _GstDucatiBufferPool * pool); -GstBuffer * gst_ducati_buffer_get (GstDucatiBuffer * self); - -G_END_DECLS - -#endif /* __GSTDUCATIBUFFER_H__ */ diff -Nru gst-plugin-ducati-1.6.7.2/src/gstducatibufferpool.c gst-plugin-ducati-1.6.7.20/src/gstducatibufferpool.c --- gst-plugin-ducati-1.6.7.2/src/gstducatibufferpool.c 2012-10-02 13:38:43.000000000 +0000 +++ gst-plugin-ducati-1.6.7.20/src/gstducatibufferpool.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,208 +0,0 @@ -/* - * GStreamer - * Copyright (c) 2010, Texas Instruments Incorporated - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation - * version 2.1 of the License. - * - * 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "gstducatibufferpool.h" -#include - -G_DEFINE_TYPE (GstDucatiBufferPool, gst_ducati_buffer_pool, - GST_TYPE_MINI_OBJECT); - -GstDucatiBufferPool * -gst_ducati_buffer_pool_new (GstElement * element, - GstDucatiBufferAllocator * allocator, GstCaps * caps, guint size) -{ - GstDucatiBufferPool *self = (GstDucatiBufferPool *) - gst_mini_object_new (GST_TYPE_DUCATI_BUFFER_POOL); - int i; - - self->element = gst_object_ref (element); - self->allocator = - GST_DUCATI_BUFFER_ALLOCATOR (gst_mini_object_ref (GST_MINI_OBJECT - (allocator))); - self->caps = NULL; - gst_ducati_buffer_pool_set_caps (self, caps); - self->size = size; - self->head = NULL; - self->tail = NULL; - self->lock = g_mutex_new (); - self->running = TRUE; - - - for (i = 0; i < 5; i++) { - GstDucatiBuffer *tmp = gst_ducati_buffer_pool_get (self, NULL, TRUE); - gst_buffer_unref (GST_BUFFER_CAST (tmp)); - } - - return self; -} - -void -gst_ducati_buffer_pool_set_caps (GstDucatiBufferPool * self, GstCaps * caps) -{ - gst_caps_replace (&self->caps, caps); - if (caps) { - GstStructure *s = gst_caps_get_structure (caps, 0); - - self->strided = - !strcmp (gst_structure_get_name (s), "video/x-raw-yuv-strided"); - - gst_structure_get_int (s, "width", &self->padded_width); - gst_structure_get_int (s, "height", &self->padded_height); - } else { - self->padded_width = 0; - self->padded_height = 0; - self->strided = FALSE; - } -} - -/** destroy existing bufferpool */ -void -gst_ducati_buffer_pool_destroy (GstDucatiBufferPool * self) -{ - g_return_if_fail (self); - - GST_DUCATI_BUFFER_POOL_LOCK (self); - self->running = FALSE; - - GST_DEBUG_OBJECT (self->element, "destroy pool"); - - /* free all buffers on the freelist */ - while (self->head) { - GstDucatiBuffer *buf = self->head; - self->head = buf->next; - buf->next = NULL; - GST_DEBUG_OBJECT (self, "unreffing %p from freelist", buf); - GST_DUCATI_BUFFER_POOL_UNLOCK (self); - gst_buffer_unref (GST_BUFFER (buf)); - GST_DUCATI_BUFFER_POOL_LOCK (self); - } - self->tail = NULL; - GST_DUCATI_BUFFER_POOL_UNLOCK (self); - gst_mini_object_unref (GST_MINI_OBJECT (self)); -} - -#if 0 -static void -dump_list (GstDucatiBufferPool * pool, GstDucatiBuffer * buf) -{ - GST_ERROR_OBJECT (pool->element, "LIST"); - while (buf) { - GST_ERROR_OBJECT (pool->element, "BUF: %p", buf); - buf = buf->next; - } -} -#endif - -/** get buffer from bufferpool, allocate new buffer if needed */ -GstDucatiBuffer * -gst_ducati_buffer_pool_get (GstDucatiBufferPool * self, GstBuffer * orig, - gboolean force_alloc) -{ - GstDucatiBuffer *buf = NULL; - - g_return_val_if_fail (self, NULL); - - GST_DUCATI_BUFFER_POOL_LOCK (self); - if (self->running) { - /* re-use a buffer off the freelist if any are available - */ - if (!force_alloc && self->head) { -// dump_list (self, self->head); - buf = self->head; - self->head = buf->next; - if (self->head == NULL) - self->tail = NULL; - } else { - GstDucatiBufferAllocatorClass *alloc_class; - - alloc_class = GST_DUCATI_BUFFER_ALLOCATOR_GET_CLASS (self->allocator); - buf = GST_DUCATI_BUFFER (alloc_class->alloc (self->allocator, self)); - } - buf->orig = orig; - if (self->caps) - gst_buffer_set_caps (GST_BUFFER (buf), self->caps); - } - GST_DUCATI_BUFFER_POOL_UNLOCK (self); - - if (buf && orig) { - GST_BUFFER_TIMESTAMP (buf) = GST_BUFFER_TIMESTAMP (orig); - GST_BUFFER_DURATION (buf) = GST_BUFFER_DURATION (orig); - } - - GST_LOG_OBJECT (self->element, "returning buf %p", buf); - - return buf; -} - -gboolean -gst_ducati_buffer_pool_put (GstDucatiBufferPool * self, GstDucatiBuffer * buf) -{ - gboolean reuse = FALSE; - - if (buf->remove_from_pool) - return FALSE; - - GST_DUCATI_BUFFER_POOL_LOCK (self); - if (self->running) { - reuse = TRUE; - - GST_LOG_OBJECT (self->element, "reviving buffer %p", buf); - gst_buffer_ref (GST_BUFFER (buf)); - - buf->next = NULL; - if (self->tail) - self->tail->next = buf; - self->tail = buf; - if (self->head == NULL) - self->head = self->tail; - buf->remove_from_pool = FALSE; - } else { - GST_INFO_OBJECT (self->element, "the pool is shutting down"); - buf->remove_from_pool = TRUE; - } - GST_DUCATI_BUFFER_POOL_UNLOCK (self); - - return reuse; -} - -static void -gst_ducati_buffer_pool_finalize (GstDucatiBufferPool * self) -{ - g_mutex_free (self->lock); - if (self->caps) - gst_caps_unref (self->caps); - gst_object_unref (self->element); - gst_mini_object_unref (GST_MINI_OBJECT (self->allocator)); - GST_MINI_OBJECT_CLASS (gst_ducati_buffer_pool_parent_class)->finalize - (GST_MINI_OBJECT (self)); -} - -static void -gst_ducati_buffer_pool_class_init (GstDucatiBufferPoolClass * klass) -{ - GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (klass); - - mini_object_class->finalize = (GstMiniObjectFinalizeFunction) - GST_DEBUG_FUNCPTR (gst_ducati_buffer_pool_finalize); -} - -static void -gst_ducati_buffer_pool_init (GstDucatiBufferPool * self) -{ -} diff -Nru gst-plugin-ducati-1.6.7.2/src/gstducatibufferpool.h gst-plugin-ducati-1.6.7.20/src/gstducatibufferpool.h --- gst-plugin-ducati-1.6.7.2/src/gstducatibufferpool.h 2012-10-02 13:38:43.000000000 +0000 +++ gst-plugin-ducati-1.6.7.20/src/gstducatibufferpool.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,72 +0,0 @@ -/* - * GStreamer - * Copyright (c) 2010, Texas Instruments Incorporated - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation - * version 2.1 of the License. - * - * 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef __GSTDUCATIBUFFERPOOL_H__ -#define __GSTDUCATIBUFFERPOOL_H__ - -#include "gstducatibuffer.h" - -G_BEGIN_DECLS - -#define GST_TYPE_DUCATI_BUFFER_POOL (gst_ducati_buffer_pool_get_type()) -#define GST_IS_DUCATI_BUFFER_POOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DUCATI_BUFFER_POOL)) -#define GST_DUCATI_BUFFER_POOL(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DUCATI_BUFFER_POOL, GstDucatiBufferPool)) - -#define GST_DUCATI_BUFFER_POOL_LOCK(self) g_mutex_lock ((self)->lock) -#define GST_DUCATI_BUFFER_POOL_UNLOCK(self) g_mutex_unlock ((self)->lock) - -typedef struct _GstDucatiBufferPool GstDucatiBufferPool; -typedef struct _GstDucatiBufferPoolClass GstDucatiBufferPoolClass; - -struct _GstDucatiBufferPool -{ - GstMiniObject parent; - - GstDucatiBufferAllocator *allocator; - - /* output (padded) size including any codec padding: */ - gint padded_width, padded_height; - - gboolean strided; /* 2d buffers? */ - GstCaps *caps; - GMutex *lock; - gboolean running; /* with lock */ - GstElement *element; /* the element that owns us.. */ - GstDucatiBuffer *head; /* list of available buffers */ - GstDucatiBuffer *tail; - guint size; -}; - -struct _GstDucatiBufferPoolClass -{ - GstMiniObjectClass klass; -}; - -GType gst_ducati_buffer_pool_get_type (void); -GstDucatiBufferPool * gst_ducati_buffer_pool_new (GstElement * element, - GstDucatiBufferAllocator * allocator, GstCaps * caps, guint size); -void gst_ducati_buffer_pool_destroy (GstDucatiBufferPool * pool); -void gst_ducati_buffer_pool_set_caps (GstDucatiBufferPool * self, GstCaps * caps); -GstDucatiBuffer * gst_ducati_buffer_pool_get (GstDucatiBufferPool * self, - GstBuffer * orig, gboolean force_alloc); -gboolean gst_ducati_buffer_pool_put (GstDucatiBufferPool * self, GstDucatiBuffer * buf); - -G_END_DECLS - -#endif /* __GSTDUCATIBUFFERPOOL_H__ */ diff -Nru gst-plugin-ducati-1.6.7.2/src/gstducatidrmbuffer.c gst-plugin-ducati-1.6.7.20/src/gstducatidrmbuffer.c --- gst-plugin-ducati-1.6.7.2/src/gstducatidrmbuffer.c 2012-10-02 13:38:43.000000000 +0000 +++ gst-plugin-ducati-1.6.7.20/src/gstducatidrmbuffer.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,204 +0,0 @@ -/* - * GStreamer - * - * Copyright (C) 2012 Texas Instruments - * Copyright (C) 2012 Collabora Ltd - * - * Authors: - * Alessandro Decina - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation - * version 2.1 of the License. - * - * 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#include "gstducatidrmbuffer.h" -#include "gstducatibufferpool.h" -#include -#include - -G_DEFINE_TYPE (GstDucatiDRMBuffer, gst_ducati_drm_buffer, - GST_TYPE_DUCATI_BUFFER); -G_DEFINE_TYPE (GstDucatiDRMBufferAllocator, gst_ducati_drm_buffer_allocator, - GST_TYPE_DUCATI_BUFFER_ALLOCATOR); - -static GstDucatiDRMBuffer * -gst_ducati_drm_buffer_new (GstDucatiBufferPool * pool, - struct omap_device *device) -{ - GstDucatiDRMBuffer *self = (GstDucatiDRMBuffer *) - gst_mini_object_new (GST_TYPE_DUCATI_DRM_BUFFER); - - self->device = device; - gst_ducati_buffer_set_pool (GST_DUCATI_BUFFER (self), pool); - gst_ducati_drm_buffer_setup_bos (self); - - return self; -} - -void -gst_ducati_drm_buffer_setup_bos (GstDucatiDRMBuffer * self) -{ - GstDucatiBufferPool *pool = GST_DUCATI_BUFFER (self)->pool; - - if (pool->strided) - g_assert (FALSE); - - self->bo[0] = omap_bo_new (self->device, pool->size, OMAP_BO_WC); - self->bo[1] = 0; - self->bo[2] = 0; - self->bo[3] = 0; - - self->handles[0] = omap_bo_handle (self->bo[0]); - self->handles[1] = self->handles[0]; - self->handles[2] = 0; - self->handles[3] = 0; - - self->pitches[0] = pool->padded_width; - self->pitches[1] = pool->padded_width; - self->pitches[2] = 0; - self->pitches[3] = 0; - - self->offsets[0] = 0; - self->offsets[1] = self->pitches[0] * pool->padded_height; - self->offsets[2] = 0; - self->offsets[3] = 0; - - GST_BUFFER_DATA (self) = omap_bo_map (self->bo[0]); - GST_BUFFER_SIZE (self) = pool->size; -} - -static void -gst_ducati_drm_buffer_finalize (GstDucatiDRMBuffer * self) -{ - GstDucatiBuffer *ducati_buf = (GstDucatiBuffer *) self; - GstDucatiBufferPool *pool = ducati_buf->pool; - gboolean resuscitated = FALSE; - int i; - - GST_LOG_OBJECT (pool->element, "finalizing buffer %p", self); - - resuscitated = gst_ducati_buffer_pool_put (pool, ducati_buf); - if (resuscitated) - return; - - GST_LOG_OBJECT (pool->element, - "buffer %p (data %p, len %u) not recovered, freeing", - self, GST_BUFFER_DATA (self), GST_BUFFER_SIZE (self)); - - for (i = 0; i < G_N_ELEMENTS (self->bo); i++) { - if (self->bo[i]) { - omap_bo_del (self->bo[i]); - self->bo[i] = 0; - } - } - - /* only chain up if the buffer isn't being reused */ - GST_MINI_OBJECT_CLASS (gst_ducati_drm_buffer_parent_class)->finalize - (GST_MINI_OBJECT (self)); -} - -static void -gst_ducati_drm_buffer_class_init (GstDucatiDRMBufferClass * klass) -{ - GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (klass); - - mini_object_class->finalize = (GstMiniObjectFinalizeFunction) - GST_DEBUG_FUNCPTR (gst_ducati_drm_buffer_finalize); -} - -static void -gst_ducati_drm_buffer_init (GstDucatiDRMBuffer * buffer) -{ -} - -GstDucatiDRMBufferAllocator * -gst_ducati_drm_buffer_allocator_new (struct omap_device *device) -{ - GstDucatiDRMBufferAllocator *self = (GstDucatiDRMBufferAllocator *) - gst_mini_object_new (GST_TYPE_DUCATI_DRM_BUFFER_ALLOCATOR); - self->device = device; - - return self; -} - -static void -gst_ducati_drm_buffer_allocator_finalize (GstDucatiDRMBufferAllocator * self) -{ - GST_MINI_OBJECT_CLASS (gst_ducati_drm_buffer_allocator_parent_class)->finalize - (GST_MINI_OBJECT (self)); -} - -static GstBuffer * -allocator_alloc (GstDucatiBufferAllocator * allocator, - GstDucatiBufferPool * pool) -{ - GstDucatiDRMBufferAllocator *self = - GST_DUCATI_DRM_BUFFER_ALLOCATOR (allocator); - GstDucatiDRMBuffer *buf = gst_ducati_drm_buffer_new (pool, self->device); - return GST_BUFFER_CAST (buf); -} - -static gboolean -allocator_check_compatible (GstDucatiBufferAllocator * allocator, - GstBuffer * buffer) -{ - static GType kms_type = -1; - if (kms_type == -1) - kms_type = g_type_from_name ("GstDucatiKMSBuffer"); - - return GST_IS_DUCATI_DRM_BUFFER (buffer) || - (kms_type != -1 && G_TYPE_CHECK_INSTANCE_TYPE (buffer, kms_type)); -} - -static void -allocator_setup_codec_output_buffers (GstDucatiBufferAllocator * allocator, - GstVideoFormat format, int width, int height, int stride, - GstBuffer * buffer, XDM2_BufDesc * bufs) -{ - GstDucatiDRMBuffer *drmbuf = (GstDucatiDRMBuffer *) buffer; - int uv_offset, size; - - uv_offset = gst_video_format_get_component_offset (format, 1, stride, height); - size = gst_video_format_get_size (format, stride, height); - - bufs->numBufs = 2; - bufs->descs[0].memType = XDM_MEMTYPE_BO; - bufs->descs[0].buf = (XDAS_Int8 *) omap_bo_handle (drmbuf->bo[0]); - bufs->descs[0].bufSize.bytes = uv_offset; - bufs->descs[1].memType = XDM_MEMTYPE_BO_OFFSET; - bufs->descs[1].buf = (XDAS_Int8 *) uv_offset; - bufs->descs[1].bufSize.bytes = size - uv_offset; -} - -static void -gst_ducati_drm_buffer_allocator_class_init (GstDucatiDRMBufferAllocatorClass * - klass) -{ - GstMiniObjectClass *mini_object_class = GST_MINI_OBJECT_CLASS (klass); - GstDucatiBufferAllocatorClass *buffer_allocator_class = - GST_DUCATI_BUFFER_ALLOCATOR_CLASS (klass); - - mini_object_class->finalize = (GstMiniObjectFinalizeFunction) - GST_DEBUG_FUNCPTR (gst_ducati_drm_buffer_allocator_finalize); - - buffer_allocator_class->alloc = allocator_alloc; - buffer_allocator_class->check_compatible = allocator_check_compatible; - buffer_allocator_class->setup_codec_output_buffers = - allocator_setup_codec_output_buffers; -} - -static void -gst_ducati_drm_buffer_allocator_init (GstDucatiDRMBufferAllocator * allocator) -{ -} diff -Nru gst-plugin-ducati-1.6.7.2/src/gstducatidrmbuffer.h gst-plugin-ducati-1.6.7.20/src/gstducatidrmbuffer.h --- gst-plugin-ducati-1.6.7.2/src/gstducatidrmbuffer.h 2012-10-02 13:38:43.000000000 +0000 +++ gst-plugin-ducati-1.6.7.20/src/gstducatidrmbuffer.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,82 +0,0 @@ -/* - * GStreamer - * - * Copyright (C) 2012 Texas Instruments - * Copyright (C) 2012 Collabora Ltd - * - * Authors: - * Alessandro Decina - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation - * version 2.1 of the License. - * - * 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef __GSTDUCATIBUFFERDRM_H__ -#define __GSTDUCATIBUFFERDRM_H__ - -#include - -#include "gstducatibuffer.h" - -G_BEGIN_DECLS - -#define GST_TYPE_DUCATI_DRM_BUFFER (gst_ducati_drm_buffer_get_type()) -#define GST_IS_DUCATI_DRM_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DUCATI_DRM_BUFFER)) -#define GST_DUCATI_DRM_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DUCATI_DRM_BUFFER, GstDucatiDRMBuffer)) - -#define GST_TYPE_DUCATI_DRM_BUFFER_ALLOCATOR (gst_ducati_drm_buffer_allocator_get_type()) -#define GST_IS_DUCATI_DRM_BUFFER_ALLOCATOR(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_DUCATI_DRM_BUFFER_ALLOCATOR)) -#define GST_DUCATI_DRM_BUFFER_ALLOCATOR(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_DUCATI_DRM_BUFFER_ALLOCATOR, GstDucatiDRMBufferAllocator)) - -typedef struct _GstDucatiDRMBufferAllocator GstDucatiDRMBufferAllocator; -typedef struct _GstDucatiDRMBufferAllocatorClass GstDucatiDRMBufferAllocatorClass; -typedef struct _GstDucatiDRMBuffer GstDucatiDRMBuffer; -typedef struct _GstDucatiDRMBufferClass GstDucatiDRMBufferClass; -typedef struct _GstDucatiDRMBufferAllocator GstDucatiDRMBufferAllocator; -typedef struct _GstDucatiDRMBufferAllocatorClass GstDucatiDRMBufferAllocatorClass; - -struct _GstDucatiDRMBuffer -{ - GstDucatiBuffer parent; - struct omap_bo *bo[4]; - uint32_t handles[4]; - uint32_t pitches[4]; - uint32_t offsets[4]; - struct omap_device *device; -}; - -struct _GstDucatiDRMBufferClass -{ - GstDucatiBufferClass parent_class; -}; - -struct _GstDucatiDRMBufferAllocator -{ - GstDucatiBufferAllocator parent; - struct omap_device *device; -}; - -struct _GstDucatiDRMBufferAllocatorClass -{ - GstDucatiBufferAllocatorClass parent_class; -}; - -GType gst_ducati_drm_buffer_get_type (void); -void gst_ducati_drm_buffer_setup_bos (GstDucatiDRMBuffer *self); - -GType gst_ducati_drm_buffer_allocator_get_type (void); -GstDucatiDRMBufferAllocator * gst_ducati_drm_buffer_allocator_new (struct omap_device *device); -G_END_DECLS - -#endif /* __GSTDUCATIBUFFERDRM_H__ */ diff -Nru gst-plugin-ducati-1.6.7.2/src/gstducatih264dec.c gst-plugin-ducati-1.6.7.20/src/gstducatih264dec.c --- gst-plugin-ducati-1.6.7.2/src/gstducatih264dec.c 2012-10-02 13:38:43.000000000 +0000 +++ gst-plugin-ducati-1.6.7.20/src/gstducatih264dec.c 2012-12-06 15:48:06.000000000 +0000 @@ -42,6 +42,10 @@ #define PADX 32 #define PADY 24 +/* This structure is not public, this should be replaced by + sizeof(sErrConcealLayerStr) when it is made so. */ +#define SIZE_OF_CONCEALMENT_DATA 65536 + GST_BOILERPLATE (GstDucatiH264Dec, gst_ducati_h264dec, GstDucatiVidDec, GST_TYPE_DUCATIVIDDEC); @@ -119,11 +123,30 @@ IH264VDEC_Params *params = (IH264VDEC_Params *) self->params; self->params->displayDelay = IVIDDEC3_DECODE_ORDER; - params->maxNumRefFrames = IH264VDEC_NUM_REFFRAMES_AUTO; + params->dpbSizeInFrames = IH264VDEC_DPB_NUMFRAMES_AUTO; params->pConstantMemory = 0; params->presetLevelIdc = IH264VDEC_LEVEL41; params->errConcealmentMode = IH264VDEC_APPLY_CONCEALMENT; params->temporalDirModePred = TRUE; + + if (self->codec_debug_info) { + /* We must allocate a byte per MB, plus the size of some struture which + is not public. Place this in the first metadata buffer slot, and ask + for MBINFO metadata for it. */ + GstDucatiH264Dec *h264dec = GST_DUCATIH264DEC (self); + unsigned mbw = (self->width + 15) / 16; + unsigned mbh = (self->height + 15) / 16; + unsigned nmb = mbw * mbh; + + h264dec->bo_mberror = + omap_bo_new (self->device, nmb + SIZE_OF_CONCEALMENT_DATA, + OMAP_BO_WC); + self->outBufs->descs[2].memType = XDM_MEMTYPE_BO; + self->outBufs->descs[2].buf = + (XDAS_Int8 *) omap_bo_handle (h264dec->bo_mberror); + self->outBufs->descs[2].bufSize.bytes = nmb + SIZE_OF_CONCEALMENT_DATA; + self->params->metadataType[0] = IVIDEO_METADATAPLANE_MBINFO; + } } return ret; @@ -133,6 +156,44 @@ gst_ducati_h264dec_handle_error (GstDucatiVidDec * self, gint ret, gint extended_error, gint status_extended_error) { + GstDucatiH264Dec *h264dec = GST_DUCATIH264DEC (self); + const unsigned char *mberror, *mbcon; + unsigned mbw, mbh, nmb; + uint16_t mbwr, mbhr; + size_t n, nerr = 0; + char *line; + unsigned x, y; + + if (h264dec->bo_mberror) { + mberror = omap_bo_map (h264dec->bo_mberror); + mbw = (self->width + 15) / 16; + mbh = (self->height + 15) / 16; + nmb = mbw * mbh; + mbcon = mberror + nmb; + mbwr = ((const uint16_t *) mbcon)[21]; /* not a public struct */ + mbhr = ((const uint16_t *) mbcon)[22]; /* not a public struct */ + if (nmb != mbwr * mbhr) { + GST_WARNING_OBJECT (self, "Failed to find MB size - " + "corruption might have happened"); + } else { + for (n = 0; n < nmb; ++n) { + if (mberror[n]) + ++nerr; + } + GST_INFO_OBJECT (self, "Frame has %zu MB errors over %zu (%u x %u) MBs", + nerr, nmb, mbwr, mbhr); + line = g_malloc (mbw + 1); + for (y = 0; y < mbh; y++) { + line[mbw] = 0; + for (x = 0; x < mbw; x++) { + line[x] = mberror[x + y * mbw] ? '!' : '.'; + } + GST_INFO_OBJECT (self, "MB: %4u: %s", y, line); + } + g_free (line); + } + } + if (extended_error & 0x00000001) { /* No valid slice. This seems to be bad enough that it's better to flush and * skip to the next keyframe. @@ -179,7 +240,7 @@ latency = 0; /* Take into account the backlog frames for reordering */ - latency *= (self->backlog_maxframes + 1); + latency *= (vdec->backlog_maxframes + 1); if (min == GST_CLOCK_TIME_NONE) min = latency; @@ -246,20 +307,20 @@ structure = gst_caps_get_structure (caps, 0); if (!structure) - return 16; + return -1; level = gst_structure_get_string (structure, "level"); if (!level) - return 16; + return -1; max_dpb = gst_ducati_h264dec_find_max_dpb_from_level (self, level); if (max_dpb < 0) - return 16; + return -1; max_dpb_size = lrint (ceil (1024 * max_dpb / (wmb * hmb * 256 * chroma_factor))); - if (max_dpb_size > 16) - max_dpb_size = 16; + if (max_dpb_size > MAX_BACKLOG_FRAMES) + max_dpb_size = MAX_BACKLOG_FRAMES; return max_dpb_size; } @@ -267,7 +328,6 @@ static gboolean gst_ducati_h264dec_set_sink_caps (GstDucatiVidDec * self, GstCaps * caps) { - GstDucatiH264Dec *h264dec = GST_DUCATIH264DEC (self); GstStructure *structure; GST_DEBUG_OBJECT (self, "set_sink_caps: %" GST_PTR_FORMAT, caps); @@ -302,103 +362,63 @@ } #endif - h264dec->backlog_maxframes = -1; + self->backlog_maxframes = -1; structure = gst_caps_get_structure (caps, 0); if (structure) { - gint num_ref_frames = -1; + gint num_ref_frames = -1, num_reorder_frames = -1; + const char *profile; + + /* baseline profile does not use B frames (and I'll say constrained-baseline + is unlikely either from the name, it's not present in my H264 spec... */ + profile = gst_structure_get_string (structure, "profile"); + if (profile && (!strcmp (profile, "baseline") + || !strcmp (profile, "constrained-baseline"))) { + GST_DEBUG_OBJECT (self, "No need for reordering for %s profile", profile); + self->backlog_maxframes = 0; + goto no_b_frames; + } + + if (gst_structure_get_int (structure, "num-ref-frames", &num_ref_frames) && num_ref_frames >= 0) { - ((IH264VDEC_Params *) self->params)->maxNumRefFrames = num_ref_frames; - - if (num_ref_frames > MAX_BACKLOG_FRAMES) { - h264dec->backlog_maxframes = MAX_BACKLOG_FRAMES; + ((IH264VDEC_Params *) self->params)->dpbSizeInFrames = num_ref_frames; + } + if (gst_structure_get_int (structure, "num-reorder-frames", + &num_reorder_frames) + && num_reorder_frames >= 0) { + if (num_reorder_frames > MAX_BACKLOG_FRAMES) { + self->backlog_maxframes = MAX_BACKLOG_FRAMES; GST_WARNING_OBJECT (self, "Stream needs %d frames for reordering, we can only accomodate %d", - num_ref_frames, MAX_BACKLOG_FRAMES); + num_reorder_frames, MAX_BACKLOG_FRAMES); } else { - h264dec->backlog_maxframes = num_ref_frames; + self->backlog_maxframes = num_reorder_frames; GST_INFO_OBJECT (self, "Num frames for reordering: %d", - h264dec->backlog_maxframes); + self->backlog_maxframes); } } } /* If not present, use the spec forumula for a bound */ - if (h264dec->backlog_maxframes < 0) { - h264dec->backlog_maxframes = - gst_ducati_h264dec_get_max_dpb_size (self, caps); - GST_WARNING_OBJECT (self, - "num-ref-frames not found on caps, defaulting to %d", - h264dec->backlog_maxframes); - } - - return TRUE; -} - -/* The following few functions reorder buffers by timestamp, on the - assumption that buffers are properly timestamped by presentation - time, but pushed in any (but presumably decode) order. - They also assume all incoming buffers have a valid timestamp. - */ - -static GstFlowReturn -gst_ducati_h264dec_push_earliest (GstDucatiH264Dec * self) -{ - GstClockTime earliest_ts = GST_CLOCK_TIME_NONE; - guint earliest_index = 0, i; - GstBuffer *buf; - - if (self->backlog_nframes == 0) - return GST_FLOW_OK; - - /* work out which frame has the earliest ts */ - for (i = 0; i < self->backlog_nframes; i++) { - GstClockTime ts = GST_BUFFER_TIMESTAMP (self->backlog_frames[i]); - if (earliest_ts == GST_CLOCK_TIME_NONE || ts < earliest_ts) { - earliest_ts = ts; - earliest_index = i; + if (self->backlog_maxframes < 0) { + self->backlog_maxframes = gst_ducati_h264dec_get_max_dpb_size (self, caps); + if (self->backlog_maxframes >= 0) { + GST_WARNING_OBJECT (self, + "num-reorder-frames not found on caps, calculation from stream parameters gives %d", + self->backlog_maxframes); + } else { + self->backlog_maxframes = MAX_H264_BACKLOG_FRAMES; } } + if (self->backlog_maxframes > self->backlog_max_maxframes) + self->backlog_maxframes = self->backlog_max_maxframes; + GST_WARNING_OBJECT (self, + "Using %d frames for reordering", self->backlog_maxframes); - /* send it, giving away the ref */ - buf = self->backlog_frames[earliest_index]; - self->backlog_frames[earliest_index] = - self->backlog_frames[--self->backlog_nframes]; - GST_DEBUG_OBJECT (self, "Actually pushing backlog buffer %" GST_PTR_FORMAT, - buf); - return gst_pad_push (GST_DUCATIVIDDEC (self)->srcpad, buf); -} - -static GstFlowReturn -gst_ducati_h264dec_push_output (GstDucatiVidDec * self, GstBuffer * buf) -{ - GstDucatiH264Dec *h264dec = GST_DUCATIH264DEC (self); - GstFlowReturn ret = GST_FLOW_OK; - - /* add the frame to the list, the array will own the ref */ - GST_DEBUG_OBJECT (self, "Adding buffer %" GST_PTR_FORMAT " to backlog", buf); - h264dec->backlog_frames[h264dec->backlog_nframes++] = buf; - - /* push till we have no more than the max needed, or error */ - while (h264dec->backlog_nframes > h264dec->backlog_maxframes) { - ret = gst_ducati_h264dec_push_earliest (h264dec); - if (ret != GST_FLOW_OK) - break; - } - - return ret; -} - -static void -gst_ducati_h264dec_on_flush (GstDucatiVidDec * self, gboolean eos) -{ - GstDucatiH264Dec *h264dec = GST_DUCATIH264DEC (self); +no_b_frames: - /* push everything on the backlog, ignoring errors */ - while (h264dec->backlog_nframes > 0) { - gst_ducati_h264dec_push_earliest (h264dec); - } + return TRUE; } /* GObject vmethod implementations */ @@ -419,9 +439,19 @@ } static void +gst_ducati_h264dec_finalize (GObject * obj) +{ + GstDucatiH264Dec *self = GST_DUCATIH264DEC (obj); + if (self->bo_mberror) + omap_bo_del (self->bo_mberror); + G_OBJECT_CLASS (parent_class)->finalize (obj); +} + +static void gst_ducati_h264dec_class_init (GstDucatiH264DecClass * klass) { GstDucatiVidDecClass *bclass = GST_DUCATIVIDDEC_CLASS (klass); + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); bclass->codec_name = "ivahd_h264dec"; bclass->update_buffer_size = GST_DEBUG_FUNCPTR (gst_ducati_h264dec_update_buffer_size); @@ -431,15 +461,40 @@ bclass->can_drop_frame = GST_DEBUG_FUNCPTR (gst_ducati_h264dec_can_drop_frame); bclass->query = GST_DEBUG_FUNCPTR (gst_ducati_h264dec_query); - bclass->push_output = GST_DEBUG_FUNCPTR (gst_ducati_h264dec_push_output); - bclass->on_flush = GST_DEBUG_FUNCPTR (gst_ducati_h264dec_on_flush); bclass->set_sink_caps = GST_DEBUG_FUNCPTR (gst_ducati_h264dec_set_sink_caps); + gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_ducati_h264dec_finalize); } static void gst_ducati_h264dec_init (GstDucatiH264Dec * self, GstDucatiH264DecClass * gclass) { - self->backlog_maxframes = 0; - self->backlog_nframes = 0; +#ifndef GST_DISABLE_GST_DEBUG + GstDucatiVidDec *dec = GST_DUCATIVIDDEC (self); + + dec->error_strings[0] = "no error-free slice"; + dec->error_strings[1] = "error parsing SPS"; + dec->error_strings[2] = "error parsing PPS"; + dec->error_strings[3] = "error parsing slice header"; + dec->error_strings[4] = "error parsing MB data"; + dec->error_strings[5] = "unknown SPS"; + dec->error_strings[6] = "unknown PPS"; + dec->error_strings[7] = "invalid parameter"; + dec->error_strings[16] = "unsupported feature"; + dec->error_strings[17] = "SEI buffer overflow"; + dec->error_strings[18] = "stream end"; + dec->error_strings[19] = "no free buffers"; + dec->error_strings[20] = "resolution change"; + dec->error_strings[21] = "unsupported resolution"; + dec->error_strings[22] = "invalid maxNumRefFrames"; + dec->error_strings[23] = "invalid mbox message"; + dec->error_strings[24] = "bad datasync input"; + dec->error_strings[25] = "missing slice"; + dec->error_strings[26] = "bad datasync param"; + dec->error_strings[27] = "bad hw state"; + dec->error_strings[28] = "temporal direct mode"; + dec->error_strings[29] = "display width too small"; + dec->error_strings[30] = "no SPS/PPS header"; + dec->error_strings[31] = "gap in frame num"; +#endif } diff -Nru gst-plugin-ducati-1.6.7.2/src/gstducatih264dec.h gst-plugin-ducati-1.6.7.20/src/gstducatih264dec.h --- gst-plugin-ducati-1.6.7.2/src/gstducatih264dec.h 2012-10-02 13:38:43.000000000 +0000 +++ gst-plugin-ducati-1.6.7.20/src/gstducatih264dec.h 2012-12-06 15:48:06.000000000 +0000 @@ -37,16 +37,13 @@ typedef struct _GstDucatiH264DecClass GstDucatiH264DecClass; /* The H.264 spec has a hard limit of 16 */ -#define MAX_BACKLOG_FRAMES 16 +#define MAX_H264_BACKLOG_FRAMES 16 struct _GstDucatiH264Dec { GstDucatiVidDec parent; - /* Frames waiting to be reordered */ - GstBuffer *backlog_frames[MAX_BACKLOG_FRAMES + 1]; - gint backlog_maxframes; - gint backlog_nframes; + struct omap_bo *bo_mberror; }; struct _GstDucatiH264DecClass diff -Nru gst-plugin-ducati-1.6.7.2/src/gstducatih264enc.c gst-plugin-ducati-1.6.7.20/src/gstducatih264enc.c --- gst-plugin-ducati-1.6.7.2/src/gstducatih264enc.c 2012-10-02 13:38:43.000000000 +0000 +++ gst-plugin-ducati-1.6.7.20/src/gstducatih264enc.c 2012-12-06 15:48:06.000000000 +0000 @@ -33,11 +33,21 @@ #define GST_CAT_DEFAULT gst_ducati_debug -#define DEFAULT_PROFILE GST_DUCATI_H264ENC_PROFILE_HIGH -#define DEFAULT_LEVEL GST_DUCATI_H264ENC_LEVEL_40 +#define DEFAULT_PROFILE IH264_HIGH_PROFILE +#define DEFAULT_LEVEL IH264_LEVEL_40 +#define DEFAULT_QPI 28 +#define DEFAULT_QP_MAX_I 36 +#define DEFAULT_QP_MIN_I 10 +/* 2 x targetBitRate for VBR Rate Control */ +#define DEFAULT_HRD_BUFFER_SIZE 40960000 +#define DEFAULT_INTER_INTERVAL 4 #define GST_TYPE_DUCATI_H264ENC_PROFILE (gst_ducati_h264enc_profile_get_type ()) #define GST_TYPE_DUCATI_H264ENC_LEVEL (gst_ducati_h264enc_level_get_type ()) +#define GST_TYPE_DUCATI_H264ENC_RCPP (gst_ducati_h264enc_get_rate_control_params_preset_type ()) +#define GST_TYPE_DUCATI_H264ENC_RATE_CONTROL_ALGO (gst_ducati_h264enc_get_rate_control_algo_type ()) +#define GST_TYPE_DUCATI_H264ENC_ENTROPY_CODING_MODE (gst_ducati_h264enc_get_entropy_coding_mode_type ()) +#define GST_TYPE_DUCATI_H264ENC_SLICE_MODE (gst_ducati_h264enc_get_slice_mode_type ()) enum @@ -50,6 +60,15 @@ PROP_0, PROP_PROFILE, PROP_LEVEL, + PROP_RATE_CONTROL_PARAMS_PRESET, + PROP_RATE_CONTROL_ALGO, + PROP_QPI, + PROP_QP_MAX_I, + PROP_QP_MIN_I, + PROP_HRD_BUFFER_SIZE, + PROP_ENTROPY_CODING_MODE, + PROP_INTER_INTERVAL, + PROP_SLICE_MODE, }; static void gst_ducati_h264enc_set_property (GObject * object, guint prop_id, @@ -61,6 +80,8 @@ self, gint params_sz, gint dynparams_sz, gint status_sz, gint inargs_sz, gint outargs_sz); static gboolean gst_ducati_h264enc_configure (GstDucatiVidEnc * self); +static gboolean gst_ducati_h264enc_is_sync_point (GstDucatiVidEnc * enc, + int type); static GstStaticPadTemplate gst_ducati_h264enc_sink_template = @@ -75,62 +96,72 @@ GST_PAD_SRC, GST_PAD_ALWAYS, GST_STATIC_CAPS - ("video/x-h264, align=(string)au, stream-format=(string)byte-stream") + ("video/x-h264, alignment=(string)au, stream-format=(string)byte-stream") ); GST_BOILERPLATE (GstDucatiH264Enc, gst_ducati_h264enc, GstDucatiVidEnc, GST_TYPE_DUCATIVIDENC); -/* the values for the following enums are taken from the codec */ - -enum +static GType +gst_ducati_h264enc_profile_get_type (void) { - GST_DUCATI_H264ENC_PROFILE_BASELINE = 66, /**< BaseLine Profile */ - GST_DUCATI_H264ENC_PROFILE_MAIN = 77, /**< Main Profile */ - GST_DUCATI_H264ENC_PROFILE_EXTENDED = 88, /**< Extended Profile */ - GST_DUCATI_H264ENC_PROFILE_HIGH = 100, /**< High Profile */ - GST_DUCATI_H264ENC_PROFILE_HIGH_10 = 110, /**< High 10 Profile */ - GST_DUCATI_H264ENC_PROFILE_HIGH_422 = 122 /**< High 4:2:2 Profile */ -}; + static GType type = 0; -enum + if (!type) { + static const GEnumValue vals[] = { + {IH264_BASELINE_PROFILE, "Base Profile", "baseline"}, + {IH264_MAIN_PROFILE, "Main Profile", "main"}, + {IH264_EXTENDED_PROFILE, "Extended Profile", "extended"}, + {IH264_HIGH_PROFILE, "High Profile", "high"}, + {IH264_HIGH10_PROFILE, "High 10 Profile", "high-10"}, + {IH264_HIGH422_PROFILE, "High 4:2:2 Profile", "high-422"}, + {0, NULL, NULL}, + }; + + type = g_enum_register_static ("GstDucatiH264EncProfile", vals); + } + + return type; +} + +static GType +gst_ducati_h264enc_get_rate_control_params_preset_type (void) { - GST_DUCATI_H264ENC_LEVEL_10 = 10, /**< Level 1.0 */ - GST_DUCATI_H264ENC_LEVEL_1b = 9, /**< Level 1.b */ - GST_DUCATI_H264ENC_LEVEL_11 = 11, /**< Level 1.1 */ - GST_DUCATI_H264ENC_LEVEL_12 = 12, /**< Level 1.2 */ - GST_DUCATI_H264ENC_LEVEL_13 = 13, /**< Level 1.3 */ - GST_DUCATI_H264ENC_LEVEL_20 = 20, /**< Level 2.0 */ - GST_DUCATI_H264ENC_LEVEL_21 = 21, /**< Level 2.1 */ - GST_DUCATI_H264ENC_LEVEL_22 = 22, /**< Level 2.2 */ - GST_DUCATI_H264ENC_LEVEL_30 = 30, /**< Level 3.0 */ - GST_DUCATI_H264ENC_LEVEL_31 = 31, /**< Level 3.1 */ - GST_DUCATI_H264ENC_LEVEL_32 = 32, /**< Level 3.2 */ - GST_DUCATI_H264ENC_LEVEL_40 = 40, /**< Level 4.0 */ - GST_DUCATI_H264ENC_LEVEL_41 = 41, /**< Level 4.1 */ - GST_DUCATI_H264ENC_LEVEL_42 = 42, /**< Level 4.2 */ - GST_DUCATI_H264ENC_LEVEL_50 = 50, /**< Level 5.0 */ - GST_DUCATI_H264ENC_LEVEL_51 = 51 /**< Level 5.1 */ -}; + static GType type = 0; + + if (!type) { + static const GEnumValue vals[] = { + {IH264_RATECONTROLPARAMS_DEFAULT, "Rate Control params preset default", + "rate-control-params-preset-default"}, + {IH264_RATECONTROLPARAMS_USERDEFINED, "User defined rate control", + "rate-control-params-preset-user-defined"}, + {IH264_RATECONTROLPARAMS_EXISTING, "Existing rate control params", + "rate-control-params-preset-existing"}, + {0, NULL, NULL}, + }; + + type = g_enum_register_static ("GstDucatiH264EncRateControlParams", vals); + } + + return type; +} static GType -gst_ducati_h264enc_profile_get_type (void) +gst_ducati_h264enc_get_rate_control_algo_type (void) { static GType type = 0; if (!type) { static const GEnumValue vals[] = { - {GST_DUCATI_H264ENC_PROFILE_BASELINE, "Base Profile", "baseline"}, - {GST_DUCATI_H264ENC_PROFILE_MAIN, "Main Profile", "main"}, - {GST_DUCATI_H264ENC_PROFILE_EXTENDED, "Extended Profile", "extended"}, - {GST_DUCATI_H264ENC_PROFILE_HIGH, "High Profile", "high"}, - {GST_DUCATI_H264ENC_PROFILE_HIGH_10, "High 10 Profile", "high-10"}, - {GST_DUCATI_H264ENC_PROFILE_HIGH_422, "High 4:2:2 Profile", "high-422"}, + {IH264_RATECONTROL_PRC, "Perceptual rate control", + "perceptual-rate-control"}, + {IH264_RATECONTROL_PRC_LOW_DELAY, "Low delay rate control", + "low-delay-rate-control"}, {0, NULL, NULL}, }; - type = g_enum_register_static ("GstDucatiH264EncProfile", vals); + type = g_enum_register_static ("GstDucatiH264EncRateControlAlgo", vals); } return type; @@ -143,22 +174,22 @@ if (!type) { static const GEnumValue vals[] = { - {GST_DUCATI_H264ENC_LEVEL_10, "Level 1", "level-1"}, - {GST_DUCATI_H264ENC_LEVEL_1b, "Level 1b", "level-1b"}, - {GST_DUCATI_H264ENC_LEVEL_11, "Level 11", "level-11"}, - {GST_DUCATI_H264ENC_LEVEL_12, "Level 12", "level-12"}, - {GST_DUCATI_H264ENC_LEVEL_13, "Level 13", "level-13"}, - {GST_DUCATI_H264ENC_LEVEL_20, "Level 2", "level-2"}, - {GST_DUCATI_H264ENC_LEVEL_21, "Level 21", "level-21"}, - {GST_DUCATI_H264ENC_LEVEL_22, "Level 22", "level-22"}, - {GST_DUCATI_H264ENC_LEVEL_30, "Level 3", "level-3"}, - {GST_DUCATI_H264ENC_LEVEL_31, "Level 31", "level-31"}, - {GST_DUCATI_H264ENC_LEVEL_32, "Level 32", "level-32"}, - {GST_DUCATI_H264ENC_LEVEL_40, "Level 4", "level-4"}, - {GST_DUCATI_H264ENC_LEVEL_41, "Level 41", "level-41"}, - {GST_DUCATI_H264ENC_LEVEL_42, "Level 42", "level-42"}, - {GST_DUCATI_H264ENC_LEVEL_50, "Level 5", "level-5"}, - {GST_DUCATI_H264ENC_LEVEL_51, "Level 51", "level-51"}, + {IH264_LEVEL_10, "Level 1", "level-1"}, + {IH264_LEVEL_1b, "Level 1b", "level-1b"}, + {IH264_LEVEL_11, "Level 11", "level-11"}, + {IH264_LEVEL_12, "Level 12", "level-12"}, + {IH264_LEVEL_13, "Level 13", "level-13"}, + {IH264_LEVEL_20, "Level 2", "level-2"}, + {IH264_LEVEL_21, "Level 21", "level-21"}, + {IH264_LEVEL_22, "Level 22", "level-22"}, + {IH264_LEVEL_30, "Level 3", "level-3"}, + {IH264_LEVEL_31, "Level 31", "level-31"}, + {IH264_LEVEL_32, "Level 32", "level-32"}, + {IH264_LEVEL_40, "Level 4", "level-4"}, + {IH264_LEVEL_41, "Level 41", "level-41"}, + {IH264_LEVEL_42, "Level 42", "level-42"}, + {IH264_LEVEL_50, "Level 5", "level-5"}, + {IH264_LEVEL_51, "Level 51", "level-51"}, {0, NULL, NULL}, }; @@ -168,6 +199,48 @@ return type; } +static GType +gst_ducati_h264enc_get_entropy_coding_mode_type (void) +{ + static GType type = 0; + + if (!type) { + static const GEnumValue vals[] = { + {IH264_ENTROPYCODING_CAVLC, "CAVLC coding type", "cavlc"}, + {IH264_ENTROPYCODING_CABAC, "Cabac coding mode", "cabac"}, + {0, NULL, NULL}, + }; + + type = g_enum_register_static ("GstDucatiEntropyCodingMode", vals); + } + + return type; +} + +static GType +gst_ducati_h264enc_get_slice_mode_type (void) +{ + static GType type = 0; + + if (!type) { + static const GEnumValue vals[] = { + {IH264_SLICEMODE_NONE, "No slice mode", "none"}, + {IH264_SLICEMODE_MBUNIT, + "Slices are controlled based upon number of Macroblocks", "mbunit"}, + {IH264_SLICEMODE_BYTES, + "Slices are controlled based upon number of bytes", "bytes"}, + {IH264_SLICEMODE_OFFSET, + "Slices are controlled based upon user defined offset unit of Row", + "offset"}, + {0, NULL, NULL}, + }; + + type = g_enum_register_static ("GstDucatiSliceMode", vals); + } + + return type; +} + static void gst_ducati_h264enc_base_init (gpointer g_class) { @@ -201,6 +274,7 @@ videnc_class->allocate_params = gst_ducati_h264enc_allocate_params; videnc_class->configure = gst_ducati_h264enc_configure; + videnc_class->is_sync_point = gst_ducati_h264enc_is_sync_point; g_object_class_install_property (gobject_class, PROP_PROFILE, g_param_spec_enum ("profile", "H.264 Profile", "H.264 Profile", @@ -209,6 +283,68 @@ g_object_class_install_property (gobject_class, PROP_LEVEL, g_param_spec_enum ("level", "H.264 Level", "H.264 Level", GST_TYPE_DUCATI_H264ENC_LEVEL, DEFAULT_LEVEL, G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, PROP_INTER_INTERVAL, + g_param_spec_uint ("inter-interval", "Inter-frame interval", + "Max inter frame interval (B frames are allowed between them if > 1)", + 1, 31, DEFAULT_INTER_INTERVAL, G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, + PROP_RATE_CONTROL_PARAMS_PRESET, + g_param_spec_enum ("rate-control-params-preset", + "H.264 rate control params preset", + "This preset controls the USER_DEFINED versus " + "DEFAULT mode. If you are not aware about the " + "fields, it should be set as 'rate-control-params-preset-default'", + GST_TYPE_DUCATI_H264ENC_RCPP, IH264_RATECONTROLPARAMS_DEFAULT, + G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, PROP_RATE_CONTROL_ALGO, + g_param_spec_enum ("rate-control-algo", "H.264 rate control algorithm", + "This defines the rate control algorithm to be used. Only useful if " + " 'rate-control-params-preset' is set as " + "'rate-control-params-preset-user-defined'", + GST_TYPE_DUCATI_H264ENC_RATE_CONTROL_ALGO, IH264_RATECONTROL_DEFAULT, + G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, PROP_QPI, + g_param_spec_int ("qpi", "Initial quantization parameter", + "Initial quantization parameter for I/IDR frames.", -1, 51, + DEFAULT_QPI, G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, PROP_QP_MIN_I, + g_param_spec_int ("qp-min-i", "Minimum quantization parameter", + "Minimum quantization parameter for I/IDR frames.", 0, 51, + DEFAULT_QP_MIN_I, G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, PROP_QP_MAX_I, + g_param_spec_int ("qp-max-i", "Maximum quantization parameter", + "Maximum quantization parameter for I/IDR frames.", 0, 51, + DEFAULT_QP_MAX_I, G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, PROP_HRD_BUFFER_SIZE, + g_param_spec_uint ("hrd-buffer-size", + "Hypothetical reference decoder buffer size", + "Hypothetical reference decoder buffer size. This " + "size controls the frame skip logic of the encoder. " + "For low delay applications this size should be " + "small. This size is in bits. Maximum Value is level " + "dependant and min value is 4096", + 4096, G_MAXUINT, DEFAULT_HRD_BUFFER_SIZE, G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, PROP_ENTROPY_CODING_MODE, + g_param_spec_enum ("entropy-coding-mode", "H.264 entropy coding mode", + "Controls the entropy coding type.", + GST_TYPE_DUCATI_H264ENC_ENTROPY_CODING_MODE, + IH264_ENTROPYCODING_DEFAULT, G_PARAM_READWRITE)); + + g_object_class_install_property (gobject_class, PROP_SLICE_MODE, + g_param_spec_enum ("slice-mode", "H.264 slice mode", + "This defines the control mechanism to split a picture in slices." + " It can be either MB based or bytes based", + GST_TYPE_DUCATI_H264ENC_SLICE_MODE, + IH264_SLICEMODE_DEFAULT, G_PARAM_READWRITE)); + } static void @@ -218,6 +354,13 @@ self->profile = DEFAULT_PROFILE; self->level = DEFAULT_LEVEL; + self->rate_control_params_preset = IH264_RATECONTROLPARAMS_DEFAULT; + self->rate_control_algo = IH264_RATECONTROL_DEFAULT; + self->qpi = DEFAULT_QPI; + self->qp_min_i = DEFAULT_QP_MIN_I; + self->qp_max_i = DEFAULT_QP_MAX_I; + self->hrd_buffer_size = DEFAULT_HRD_BUFFER_SIZE; + self->inter_interval = DEFAULT_INTER_INTERVAL; } static void @@ -225,8 +368,10 @@ const GValue * value, GParamSpec * pspec) { GstDucatiH264Enc *self = GST_DUCATIH264ENC (object); + GstDucatiVidEnc *venc = GST_DUCATIVIDENC (object); + IH264ENC_DynamicParams *dynParams = + (IH264ENC_DynamicParams *) venc->dynParams; - g_return_if_fail (GST_IS_DUCATIH264ENC (object)); self = GST_DUCATIH264ENC (object); switch (prop_id) { @@ -236,6 +381,53 @@ case PROP_LEVEL: self->level = g_value_get_enum (value); break; + case PROP_RATE_CONTROL_PARAMS_PRESET: + self->rate_control_params_preset = g_value_get_enum (value); + if (dynParams) + dynParams->rateControlParams.rateControlParamsPreset = + self->rate_control_params_preset; + break; + case PROP_RATE_CONTROL_ALGO: + self->rate_control_algo = g_value_get_enum (value); + + if (self->rate_control_params_preset != + IH264_RATECONTROLPARAMS_USERDEFINED) + GST_INFO_OBJECT (self, + "Setting rcAlgo but rateControlParamsPreset not " + "'rate-control-params-preset-user-defined' config won't be taken " + "into account"); + + if (dynParams) + dynParams->rateControlParams.rcAlgo = self->rate_control_algo; + break; + case PROP_QPI: + self->qpi = g_value_get_int (value); + if (dynParams) + dynParams->rateControlParams.qpI = self->qpi; + + break; + case PROP_QP_MIN_I: + self->qp_min_i = g_value_get_int (value); + if (dynParams) + dynParams->rateControlParams.qpMinI = self->qp_min_i; + break; + case PROP_QP_MAX_I: + self->qp_max_i = g_value_get_int (value); + if (dynParams) + dynParams->rateControlParams.qpMaxI = self->qp_max_i; + break; + case PROP_HRD_BUFFER_SIZE: + self->hrd_buffer_size = g_value_get_uint (value); + break; + case PROP_ENTROPY_CODING_MODE: + self->entropy_coding_mode = g_value_get_enum (value); + break; + case PROP_SLICE_MODE: + self->slice_mode = g_value_get_enum (value); + break; + case PROP_INTER_INTERVAL: + self->inter_interval = g_value_get_uint (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } @@ -257,41 +449,161 @@ case PROP_LEVEL: g_value_set_enum (value, self->level); break; + case PROP_RATE_CONTROL_PARAMS_PRESET: + g_value_set_enum (value, self->rate_control_params_preset); + break; + case PROP_RATE_CONTROL_ALGO: + g_value_set_enum (value, self->rate_control_algo); + break; + case PROP_QPI: + g_value_set_int (value, self->qpi); + break; + case PROP_QP_MIN_I: + g_value_set_int (value, self->qp_min_i); + break; + case PROP_QP_MAX_I: + g_value_set_int (value, self->qp_max_i); + break; + case PROP_HRD_BUFFER_SIZE: + g_value_set_uint (value, self->hrd_buffer_size); + break; + case PROP_ENTROPY_CODING_MODE: + g_value_set_enum (value, self->entropy_coding_mode); + break; + case PROP_SLICE_MODE: + g_value_set_enum (value, self->slice_mode); + break; + case PROP_INTER_INTERVAL: + g_value_set_uint (value, self->inter_interval); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); } } +static const char * +get_profile_name (guint profile) +{ + switch (profile) { + case IH264_BASELINE_PROFILE: + return "baseline"; + case IH264_MAIN_PROFILE: + return "main"; + case IH264_EXTENDED_PROFILE: + return "extended"; + case IH264_HIGH_PROFILE: + return "high"; + case IH264_HIGH10_PROFILE: + return "high-10"; + case IH264_HIGH422_PROFILE: + return "high-422"; + default: + return NULL; + } +} + +static const char * +get_level_name (guint level) +{ + switch (level) { + case IH264_LEVEL_10: + return "1"; + case IH264_LEVEL_1b: + return "1b"; + case IH264_LEVEL_11: + return "1.1"; + case IH264_LEVEL_12: + return "1.2"; + case IH264_LEVEL_13: + return "1.3"; + case IH264_LEVEL_20: + return "2"; + case IH264_LEVEL_21: + return "2.1"; + case IH264_LEVEL_22: + return "2.2"; + case IH264_LEVEL_30: + return "3"; + case IH264_LEVEL_31: + return "3.1"; + case IH264_LEVEL_32: + return "3.2"; + case IH264_LEVEL_40: + return "4"; + case IH264_LEVEL_41: + return "4.1"; + case IH264_LEVEL_42: + return "4.2"; + case IH264_LEVEL_50: + return "5"; + case IH264_LEVEL_51: + return "5.1"; + default: + return NULL; + } +} + static gboolean gst_ducati_h264enc_configure (GstDucatiVidEnc * videnc) { GstDucatiH264Enc *self = GST_DUCATIH264ENC (videnc); IH264ENC_Params *params; + IH264ENC_DynamicParams *dynParams; gboolean ret; + const char *s; + const GstVideoState *state; + GstCaps *caps; + int inter_interval; + + ret = GST_DUCATIVIDENC_CLASS (parent_class)->configure (videnc); + if (!ret) + return FALSE; videnc->params->profile = self->profile; videnc->params->level = self->level; + inter_interval = self->inter_interval; + if (self->profile == IH264_BASELINE_PROFILE) + inter_interval = 1; + else if (videnc->rate_preset == IVIDEO_LOW_DELAY) + inter_interval = 1; + params = (IH264ENC_Params *) videnc->params; /* this is the only non-base field strictly required */ params->maxIntraFrameInterval = 0x7fffffff; params->IDRFrameInterval = 1; params->numTemporalLayer = 1; + params->entropyCodingMode = self->entropy_coding_mode; + videnc->params->maxInterFrameInterval = inter_interval; - ret = GST_DUCATIVIDENC_CLASS (parent_class)->configure (videnc); - if (ret) { - const GstVideoState *state = - gst_base_video_encoder_get_state (GST_BASE_VIDEO_ENCODER (videnc)); - GstCaps *caps = gst_caps_new_simple ("video/x-h264", - "width", G_TYPE_INT, videnc->rect.w, - "height", G_TYPE_INT, videnc->rect.h, - "framerate", GST_TYPE_FRACTION, state->fps_n, state->fps_d, - "pixel-aspect-ratio", GST_TYPE_FRACTION, state->par_n, state->par_d, - "stream-format", G_TYPE_STRING, "byte-stream", - "align", G_TYPE_STRING, "au", - NULL); - ret = gst_pad_set_caps (GST_BASE_VIDEO_CODEC_SRC_PAD (self), caps); - } + /* Dynamic params */ + dynParams = (IH264ENC_DynamicParams *) videnc->dynParams; + dynParams->rateControlParams.rateControlParamsPreset = + self->rate_control_params_preset; + dynParams->rateControlParams.rcAlgo = self->rate_control_algo; + dynParams->rateControlParams.qpI = self->qpi; + dynParams->rateControlParams.qpMaxI = self->qp_max_i; + dynParams->rateControlParams.qpMinI = self->qp_min_i; + dynParams->rateControlParams.HRDBufferSize = self->hrd_buffer_size; + dynParams->sliceCodingParams.sliceMode = self->slice_mode; + videnc->dynParams->interFrameInterval = inter_interval; + + state = gst_base_video_encoder_get_state (GST_BASE_VIDEO_ENCODER (videnc)); + caps = gst_caps_new_simple ("video/x-h264", + "width", G_TYPE_INT, videnc->rect.w, + "height", G_TYPE_INT, videnc->rect.h, + "framerate", GST_TYPE_FRACTION, state->fps_n, state->fps_d, + "pixel-aspect-ratio", GST_TYPE_FRACTION, state->par_n, state->par_d, + "stream-format", G_TYPE_STRING, "byte-stream", + "align", G_TYPE_STRING, "au", + "num-reorder-frames", G_TYPE_INT, inter_interval - 1, NULL); + s = get_profile_name (self->profile); + if (s) + gst_caps_set_simple (caps, "profile", G_TYPE_STRING, s, NULL); + s = get_level_name (self->level); + if (s) + gst_caps_set_simple (caps, "level", G_TYPE_STRING, s, NULL); + ret = gst_pad_set_caps (GST_BASE_VIDEO_CODEC_SRC_PAD (self), caps); return ret; } @@ -301,8 +613,32 @@ videnc, gint params_sz, gint dynparams_sz, gint status_sz, gint inargs_sz, gint outargs_sz) { - return GST_DUCATIVIDENC_CLASS (parent_class)->allocate_params (videnc, - sizeof (IH264ENC_Params), sizeof (IVIDENC2_DynamicParams), + gboolean ret = GST_DUCATIVIDENC_CLASS (parent_class)->allocate_params (videnc, + sizeof (IH264ENC_Params), sizeof (IH264ENC_DynamicParams), sizeof (IVIDENC2_Status), sizeof (IVIDENC2_InArgs), sizeof (IVIDENC2_OutArgs)); + + GstDucatiH264Enc *self = GST_DUCATIH264ENC (videnc); + + if (ret == TRUE) { + IH264ENC_DynamicParams *dynParams = + (IH264ENC_DynamicParams *) videnc->dynParams; + + dynParams->rateControlParams.rateControlParamsPreset = + self->rate_control_params_preset; + dynParams->rateControlParams.rcAlgo = self->rate_control_algo; + dynParams->rateControlParams.qpI = self->qpi; + dynParams->rateControlParams.qpMaxI = self->qp_max_i; + dynParams->rateControlParams.qpMinI = self->qp_min_i; + dynParams->rateControlParams.HRDBufferSize = self->hrd_buffer_size; + dynParams->sliceCodingParams.sliceMode = self->slice_mode; + } + + return ret; +} + +static gboolean +gst_ducati_h264enc_is_sync_point (GstDucatiVidEnc * enc, int type) +{ + return type == IVIDEO_IDR_FRAME; } diff -Nru gst-plugin-ducati-1.6.7.2/src/gstducatih264enc.h gst-plugin-ducati-1.6.7.20/src/gstducatih264enc.h --- gst-plugin-ducati-1.6.7.2/src/gstducatih264enc.h 2012-10-02 13:38:43.000000000 +0000 +++ gst-plugin-ducati-1.6.7.20/src/gstducatih264enc.h 2012-12-06 15:48:06.000000000 +0000 @@ -45,6 +45,17 @@ guint profile; guint level; + + gint qp_min_i; + gint qpi; + gint qp_max_i; + guint hrd_buffer_size; + + IH264ENC_RateControlParamsPreset rate_control_params_preset; + IH264ENC_RateControlAlgo rate_control_algo; + IH264ENC_EntropyCodingMode entropy_coding_mode; + IH264ENC_SliceMode slice_mode; + guint inter_interval; }; struct _GstDucatiH264EncClass diff -Nru gst-plugin-ducati-1.6.7.2/src/gstducatijpegdec.c gst-plugin-ducati-1.6.7.20/src/gstducatijpegdec.c --- gst-plugin-ducati-1.6.7.2/src/gstducatijpegdec.c 1970-01-01 00:00:00.000000000 +0000 +++ gst-plugin-ducati-1.6.7.20/src/gstducatijpegdec.c 2012-12-06 15:48:06.000000000 +0000 @@ -0,0 +1,151 @@ +/* + * GStreamer + * Copyright (c) 2010, Texas Instruments Incorporated + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation + * version 2.1 of the License. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * SECTION:element-ducatijpegdec + * + * FIXME:Describe ducatijpegdec here. + * + * + * Example launch line + * |[ + * gst-launch -v -m fakesrc ! ducatijpegdec ! fakesink silent=TRUE + * ]| + * + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "gstducatijpegdec.h" + +GST_BOILERPLATE (GstDucatiJpegDec, gst_ducati_jpegdec, GstDucatiVidDec, + GST_TYPE_DUCATIVIDDEC); + +static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("image/jpeg, " + "parsed = (boolean)true, " + "width = (int)[ 32, 2048 ], " + "height = (int)[ 32, 2048 ], " "framerate = (fraction)[ 0, max ];") + ); + +/* GstDucatiVidDec vmethod implementations */ + +static void +gst_ducati_jpegdec_update_buffer_size (GstDucatiVidDec * self) +{ + gint w = self->width; + gint h = self->height; + + /* calculate output buffer parameters: */ + self->padded_width = w; + self->padded_height = h; + self->min_buffers = 1; +} + +static gboolean +gst_ducati_jpegdec_allocate_params (GstDucatiVidDec * self, gint params_sz, + gint dynparams_sz, gint status_sz, gint inargs_sz, gint outargs_sz) +{ + IJPEGVDEC_DynamicParams *dynParams; + + gboolean ret = parent_class->allocate_params (self, + sizeof (IJPEGVDEC_Params), sizeof (IJPEGVDEC_DynamicParams), + sizeof (IJPEGVDEC_Status), sizeof (IJPEGVDEC_InArgs), + sizeof (IJPEGVDEC_OutArgs)); + + if (!ret) + return ret; + + /* We're doing ENTIREFRAME decoding so in theory 0 should be a valid value + * for this. The codec seems to check that it's non-zero though... + */ + self->params->numOutputDataUnits = 1; + + dynParams = (IJPEGVDEC_DynamicParams *) self->dynParams; + dynParams->decodeThumbnail = 0; + dynParams->thumbnailMode = 3; + dynParams->downsamplingFactor = 1; + dynParams->streamingCompliant = 0; + + return ret; +} + +/* GObject vmethod implementations */ + +static void +gst_ducati_jpegdec_base_init (gpointer gclass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (gclass); + + gst_element_class_set_details_simple (element_class, + "DucatiJpegDec", + "Codec/Decoder/Video", + "Decodes video in MJPEG format with ducati", + "Alessandro Decina "); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&sink_factory)); +} + +static void +gst_ducati_jpegdec_class_init (GstDucatiJpegDecClass * klass) +{ + GstDucatiVidDecClass *bclass = GST_DUCATIVIDDEC_CLASS (klass); + bclass->codec_name = "ivahd_jpegvdec"; + bclass->update_buffer_size = + GST_DEBUG_FUNCPTR (gst_ducati_jpegdec_update_buffer_size); + bclass->allocate_params = + GST_DEBUG_FUNCPTR (gst_ducati_jpegdec_allocate_params); +} + +static void +gst_ducati_jpegdec_init (GstDucatiJpegDec * self, + GstDucatiJpegDecClass * gclass) +{ + GstDucatiVidDec *vdec = GST_DUCATIVIDDEC (self); + vdec->pageMemType = XDM_MEMTYPE_RAW; +#ifndef GST_DISABLE_GST_DEBUG + vdec->error_strings[0] = "unsupported VIDDEC3 parameters"; + vdec->error_strings[1] = "unsupported VIDDEC3 dynamic parameters"; + vdec->error_strings[2] = "unsupported JPEGDEC dynamic parameters"; + vdec->error_strings[3] = "no slice"; + vdec->error_strings[4] = "MB data error"; + vdec->error_strings[5] = "standby"; + vdec->error_strings[6] = "invalid mbox message"; + vdec->error_strings[7] = "HDVICP reset"; + vdec->error_strings[16] = "HDVICP wait not clean exit"; + vdec->error_strings[17] = "Frame header error"; + vdec->error_strings[18] = "Scan header error"; + vdec->error_strings[19] = "Huffman table header error"; + vdec->error_strings[20] = "Quantization table header error"; + vdec->error_strings[21] = "Bad chroma format"; + vdec->error_strings[22] = "Unsupported marker"; + vdec->error_strings[23] = "Thumbnail error"; + vdec->error_strings[24] = "IRES handle error"; + vdec->error_strings[25] = "Dynamic params handle error"; + vdec->error_strings[26] = "Data sync error"; + vdec->error_strings[27] = "Downsample input format error"; + vdec->error_strings[28] = "Unsupported feature"; + vdec->error_strings[29] = "Unsupported resolution"; +#endif +} diff -Nru gst-plugin-ducati-1.6.7.2/src/gstducatijpegdec.h gst-plugin-ducati-1.6.7.20/src/gstducatijpegdec.h --- gst-plugin-ducati-1.6.7.2/src/gstducatijpegdec.h 1970-01-01 00:00:00.000000000 +0000 +++ gst-plugin-ducati-1.6.7.20/src/gstducatijpegdec.h 2012-12-06 15:48:06.000000000 +0000 @@ -0,0 +1,55 @@ +/* + * GStreamer + * Copyright (c) 2010, Texas Instruments Incorporated + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation + * version 2.1 of the License. + * + * 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 + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __GST_DUCATIJPEGDEC_H__ +#define __GST_DUCATIJPEGDEC_H__ + +#include "gstducatividdec.h" + +#include + + +G_BEGIN_DECLS + +#define GST_TYPE_DUCATIJPEGDEC (gst_ducati_jpegdec_get_type()) +#define GST_DUCATIJPEGDEC(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_DUCATIJPEGDEC, GstDucatiJpegDec)) +#define GST_DUCATIJPEGDEC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_DUCATIJPEGDEC, GstDucatiJpegDecClass)) +#define GST_IS_DUCATIJPEGDEC(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_DUCATIJPEGDEC)) +#define GST_IS_DUCATIJPEGDEC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_DUCATIJPEGDEC)) + +typedef struct _GstDucatiJpegDec GstDucatiJpegDec; +typedef struct _GstDucatiJpegDecClass GstDucatiJpegDecClass; + +struct _GstDucatiJpegDec +{ + GstDucatiVidDec parent; + + gboolean prepend_codec_data; +}; + +struct _GstDucatiJpegDecClass +{ + GstDucatiVidDecClass parent_class; +}; + +GType gst_ducati_jpegdec_get_type (void); + +G_END_DECLS + +#endif /* __GST_DUCATIJPEGDEC_H__ */ diff -Nru gst-plugin-ducati-1.6.7.2/src/gstducatimpeg2dec.c gst-plugin-ducati-1.6.7.20/src/gstducatimpeg2dec.c --- gst-plugin-ducati-1.6.7.2/src/gstducatimpeg2dec.c 2012-10-02 13:38:43.000000000 +0000 +++ gst-plugin-ducati-1.6.7.20/src/gstducatimpeg2dec.c 2012-12-06 15:48:06.000000000 +0000 @@ -42,13 +42,11 @@ static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, - GST_STATIC_CAPS ("video/mpeg, " - "mpegversion = (int)[ 1, 2 ], " // XXX check on MPEG-1.. + GST_STATIC_CAPS ("video/mpeg, " "mpegversion = (int)[ 1, 2 ], " // XXX check on MPEG-1.. "systemstream = (boolean)false, " "parsed = (boolean)true, " "width = (int)[ 64, 2048 ], " - "height = (int)[ 64, 2048 ], " - "framerate = (fraction)[ 0, max ];") + "height = (int)[ 64, 2048 ], " "framerate = (fraction)[ 0, max ];") ); /* GstDucatiVidDec vmethod implementations */ @@ -75,7 +73,7 @@ sizeof (IVIDDEC3_OutArgs)); if (ret) - self->params->displayDelay = IVIDDEC3_DISPLAY_DELAY_1; + self->params->displayDelay = IVIDDEC3_DECODE_ORDER; return ret; } @@ -109,6 +107,36 @@ return NULL; } +static gboolean +gst_ducati_mpeg2dec_set_sink_caps (GstDucatiVidDec * self, GstCaps * caps) +{ + GstStructure *structure; + const gchar *profile; + + GST_DEBUG_OBJECT (self, "set_sink_caps: %" GST_PTR_FORMAT, caps); + + if (!GST_CALL_PARENT_WITH_DEFAULT (GST_DUCATIVIDDEC_CLASS, set_sink_caps, + (self, caps), TRUE)) + return FALSE; + + /* Simple profile does not have B frames */ + structure = gst_caps_get_structure (caps, 0); + profile = gst_structure_get_string (structure, "profile"); + if (!profile || strcmp (profile, "simple")) { + /* TODO: can a better bound be found from stream headers ? */ + self->backlog_maxframes = self->backlog_max_maxframes; + } + + return TRUE; +} + +static GstFlowReturn +gst_ducati_mpeg2dec_push_output (GstDucatiVidDec * self, GstBuffer * buf) +{ + GST_BUFFER_OFFSET_END (buf) = GST_BUFFER_TIMESTAMP (buf); + return parent_class->push_output (self, buf); +} + /* GObject vmethod implementations */ static void @@ -119,8 +147,7 @@ gst_element_class_set_details_simple (element_class, "DucatiMpeg2Dec", "Codec/Decoder/Video", - "Decodes video in MPEG-2 format with ducati", - "Rob Clark "); + "Decodes video in MPEG-2 format with ducati", "Rob Clark "); gst_element_class_add_pad_template (element_class, gst_static_pad_template_get (&sink_factory)); @@ -135,8 +162,9 @@ GST_DEBUG_FUNCPTR (gst_ducati_mpeg2dec_update_buffer_size); bclass->allocate_params = GST_DEBUG_FUNCPTR (gst_ducati_mpeg2dec_allocate_params); - bclass->push_input = - GST_DEBUG_FUNCPTR (gst_ducati_mpeg2dec_push_input); + bclass->push_input = GST_DEBUG_FUNCPTR (gst_ducati_mpeg2dec_push_input); + bclass->set_sink_caps = GST_DEBUG_FUNCPTR (gst_ducati_mpeg2dec_set_sink_caps); + bclass->push_output = GST_DEBUG_FUNCPTR (gst_ducati_mpeg2dec_push_output); } static void diff -Nru gst-plugin-ducati-1.6.7.2/src/gstducatimpeg4dec.c gst-plugin-ducati-1.6.7.20/src/gstducatimpeg4dec.c --- gst-plugin-ducati-1.6.7.2/src/gstducatimpeg4dec.c 2012-10-02 13:38:43.000000000 +0000 +++ gst-plugin-ducati-1.6.7.20/src/gstducatimpeg4dec.c 2012-12-06 15:48:06.000000000 +0000 @@ -54,19 +54,11 @@ static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, - GST_STATIC_CAPS ( - "video/mpeg, " - "mpegversion = (int)4, " - "systemstream = (boolean)false, " - MPEG4DEC_SINKCAPS_COMMON ";" - "video/x-divx, " - "divxversion = (int)[4, 5], " /* TODO check this */ - MPEG4DEC_SINKCAPS_COMMON ";" + GST_STATIC_CAPS ("video/mpeg, " "mpegversion = (int)4, " "systemstream = (boolean)false, " MPEG4DEC_SINKCAPS_COMMON ";" "video/x-divx, " "divxversion = (int)[4, 5], " /* TODO check this */ + MPEG4DEC_SINKCAPS_COMMON ";" "video/x-xvid, " - MPEG4DEC_SINKCAPS_COMMON ";" - "video/x-3ivx, " - MPEG4DEC_SINKCAPS_COMMON ";" - ) + MPEG4DEC_SINKCAPS_COMMON ";" + "video/x-3ivx, " MPEG4DEC_SINKCAPS_COMMON ";") ); /* GstDucatiVidDec vmethod implementations */ @@ -99,25 +91,26 @@ self->dynParams->lateAcquireArg = -1; params->outloopDeBlocking = FALSE; params->sorensonSparkStream = FALSE; - params->ErrorConcealmentON = FALSE; + params->errorConcealmentEnable = FALSE; } return ret; } -#define VOS_START_CODE 0xb0 /* + visual object sequence */ +#define VOS_START_CODE 0xb0 /* + visual object sequence */ #define VOS_END_CODE 0xb1 -#define UD_START_CODE 0xb2 /* user data */ -#define GVOP_START_CODE 0xb3 /* + group of VOP */ +#define UD_START_CODE 0xb2 /* user data */ +#define GVOP_START_CODE 0xb3 /* + group of VOP */ #define VS_ERROR_CODE 0xb4 -#define VO_START_CODE 0xb5 /* visual object */ -#define VOP_START_CODE 0xb6 /* + */ +#define VO_START_CODE 0xb5 /* visual object */ +#define VOP_START_CODE 0xb6 /* + */ + +static const guint8 sc[] = { 0x00, 0x00, 0x01 }; /* start code */ -static const guint8 sc[] = {0x00, 0x00, 0x01}; /* start code */ #define SC_SZ G_N_ELEMENTS (sc) /* start code size */ static GstBitReader * -get_bit_reader (GstDucatiMpeg4Dec *self, const guint8 * data, guint size) +get_bit_reader (GstDucatiMpeg4Dec * self, const guint8 * data, guint size) { if (self->br) { gst_bit_reader_init (self->br, data, size); @@ -128,48 +121,48 @@ } static void -decode_vol_header (GstDucatiMpeg4Dec *self, const guint8 * data, guint size) +decode_vol_header (GstDucatiMpeg4Dec * self, const guint8 * data, guint size) { GstBitReader *br = get_bit_reader (self, data, size); guint32 is_oli = 0, vc_param = 0, vbv_param = 0; guint32 ar_info = 0, vop_tir = 0; - gst_bit_reader_skip (br, 1); /* random_accessible_vol */ - gst_bit_reader_skip (br, 8); /* video_object_type_indication */ + gst_bit_reader_skip (br, 1); /* random_accessible_vol */ + gst_bit_reader_skip (br, 8); /* video_object_type_indication */ - gst_bit_reader_get_bits_uint32 (br, /* is_object_layer_identifier */ + gst_bit_reader_get_bits_uint32 (br, /* is_object_layer_identifier */ &is_oli, 1); if (is_oli) { - gst_bit_reader_skip (br, 4); /* video_object_layer_verid */ - gst_bit_reader_skip (br, 3); /* video_object_layer_priority */ + gst_bit_reader_skip (br, 4); /* video_object_layer_verid */ + gst_bit_reader_skip (br, 3); /* video_object_layer_priority */ } - gst_bit_reader_get_bits_uint32 (br, /* aspect_ratio_info */ + gst_bit_reader_get_bits_uint32 (br, /* aspect_ratio_info */ &ar_info, 4); if (ar_info == 0xf) { - gst_bit_reader_skip (br, 8); /* par_width */ - gst_bit_reader_skip (br, 8); /* par_height */ + gst_bit_reader_skip (br, 8); /* par_width */ + gst_bit_reader_skip (br, 8); /* par_height */ } - gst_bit_reader_get_bits_uint32 (br, /* vol_control_parameters */ + gst_bit_reader_get_bits_uint32 (br, /* vol_control_parameters */ &vc_param, 1); if (vc_param) { - gst_bit_reader_skip (br, 2); /* chroma_format */ - gst_bit_reader_skip (br, 1); /* low_delay */ - gst_bit_reader_get_bits_uint32 ( /* vbv_parameters */ + gst_bit_reader_skip (br, 2); /* chroma_format */ + gst_bit_reader_skip (br, 1); /* low_delay */ + gst_bit_reader_get_bits_uint32 ( /* vbv_parameters */ br, &vbv_param, 1); if (vbv_param) { - gst_bit_reader_skip (br, 79); /* don't care */ + gst_bit_reader_skip (br, 79); /* don't care */ } } - gst_bit_reader_skip (br, 2); /* video_object_layer_shape */ - gst_bit_reader_skip (br, 1); /* marker_bit */ - gst_bit_reader_get_bits_uint32 (br, /* vop_time_increment_resolution */ + gst_bit_reader_skip (br, 2); /* video_object_layer_shape */ + gst_bit_reader_skip (br, 1); /* marker_bit */ + gst_bit_reader_get_bits_uint32 (br, /* vop_time_increment_resolution */ &vop_tir, 16); - gst_bit_reader_skip (br, 1); /* marker_bit */ + gst_bit_reader_skip (br, 1); /* marker_bit */ - self->time_increment_bits = (guint32)log2((double)(vop_tir - 1)) + 1; + self->time_increment_bits = (guint32) log2 ((double) (vop_tir - 1)) + 1; GST_DEBUG_OBJECT (self, "vop_tir=%d, time_increment_bits=%d", vop_tir, self->time_increment_bits); @@ -181,17 +174,17 @@ } static void -decode_user_data (GstDucatiMpeg4Dec *self, const guint8 * data, guint size) +decode_user_data (GstDucatiMpeg4Dec * self, const guint8 * data, guint size) { GstDucatiVidDec *vdec = GST_DUCATIVIDDEC (self); - const char *buf = (const char *)data; + const char *buf = (const char *) data; int n, ver, build; char c; /* divx detection: */ - n = sscanf(buf, "DivX%dBuild%d%c", &ver, &build, &c); + n = sscanf (buf, "DivX%dBuild%d%c", &ver, &build, &c); if (n < 2) - n = sscanf(buf, "DivX%db%d%c", &ver, &build, &c); + n = sscanf (buf, "DivX%db%d%c", &ver, &build, &c); if (n >= 2) { GST_INFO_OBJECT (self, "DivX: version %d, build %d", ver, build); if ((n == 3) && (c == 'p')) { @@ -202,7 +195,7 @@ } /* xvid detection: */ - n = sscanf(buf, "XviD%d", &build); + n = sscanf (buf, "XviD%d", &build); if (n == 1) { GST_INFO_OBJECT (self, "XviD: build %d", build); /* I believe we only get this in avi container, which means @@ -213,23 +206,22 @@ } static gboolean -is_vop_coded (GstDucatiMpeg4Dec *self, const guint8 * data, guint size) +is_vop_coded (GstDucatiMpeg4Dec * self, const guint8 * data, guint size) { - GstBitReader *br = - get_bit_reader (self, data, size); + GstBitReader *br = get_bit_reader (self, data, size); guint32 b = 0; - gst_bit_reader_skip (br, 2); /* vop_coding_type */ + gst_bit_reader_skip (br, 2); /* vop_coding_type */ - do { /* modulo_time_base */ + do { /* modulo_time_base */ gst_bit_reader_get_bits_uint32 (br, &b, 1); } while (b != 0); - gst_bit_reader_skip (br, 1); /* marker_bit */ - gst_bit_reader_skip (br, /* vop_time_increment */ + gst_bit_reader_skip (br, 1); /* marker_bit */ + gst_bit_reader_skip (br, /* vop_time_increment */ self->time_increment_bits); - gst_bit_reader_skip (br, 1); /* marker_bit */ - gst_bit_reader_get_bits_uint32 (br, /* vop_coded */ + gst_bit_reader_skip (br, 1); /* marker_bit */ + gst_bit_reader_get_bits_uint32 (br, /* vop_coded */ &b, 1); return b; @@ -241,7 +233,7 @@ GstDucatiMpeg4Dec *self = GST_DUCATIMPEG4DEC (vdec); GstBuffer *remaining = NULL; gint insize = GST_BUFFER_SIZE (buf); - const guint8 *in = GST_BUFFER_DATA (buf); + const guint8 *in = GST_BUFFER_DATA (buf); gint size = 0; guint8 last_start_code = 0xff; @@ -259,10 +251,7 @@ if (size > 0) { /* check if we've found a potential start of frame: */ - if ((start_code == VOS_START_CODE) || - (start_code == GVOP_START_CODE) || - (start_code == VOP_START_CODE) || - (start_code <= 0x1f)) { /* 00->0f is video_object_start_code */ + if ((start_code == VOS_START_CODE) || (start_code == GVOP_START_CODE) || (start_code == VOP_START_CODE) || (start_code <= 0x1f)) { /* 00->0f is video_object_start_code */ /* if last was a VOP, or if this is first VOP, then what follows * must be the next frame: */ @@ -278,8 +267,7 @@ last_start_code = start_code; - nal_size = SC_SZ + - find_start_code (sc, SC_SZ, in + SC_SZ, insize - SC_SZ); + nal_size = SC_SZ + find_start_code (sc, SC_SZ, in + SC_SZ, insize - SC_SZ); if ((start_code == VOP_START_CODE) && (nal_size < 20)) { /* suspiciously small nal.. check for !vop_coded and filter @@ -290,10 +278,10 @@ * are all 7 bytes but need to come up with some sane * threshold */ - skip = ! is_vop_coded (self, in + SC_SZ + 1, insize - SC_SZ - 1); + skip = !is_vop_coded (self, in + SC_SZ + 1, insize - SC_SZ - 1); if (skip) GST_DEBUG_OBJECT (self, "skipping non-coded VOP"); - } else if (start_code == UD_START_CODE){ + } else if (start_code == UD_START_CODE) { decode_user_data (self, in + SC_SZ + 1, nal_size - SC_SZ - 1); } @@ -344,8 +332,7 @@ gst_element_class_set_details_simple (element_class, "DucatiMpeg4Dec", "Codec/Decoder/Video", - "Decodes video in MPEG-4 format with ducati", - "Rob Clark "); + "Decodes video in MPEG-4 format with ducati", "Rob Clark "); gst_element_class_add_pad_template (element_class, gst_static_pad_template_get (&sink_factory)); @@ -357,20 +344,46 @@ GObjectClass *gobject_class = G_OBJECT_CLASS (klass); GstDucatiVidDecClass *bclass = GST_DUCATIVIDDEC_CLASS (klass); - gobject_class->finalize = - GST_DEBUG_FUNCPTR (gst_ducati_mpeg4dec_finalize); + gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_ducati_mpeg4dec_finalize); bclass->codec_name = "ivahd_mpeg4dec"; bclass->update_buffer_size = GST_DEBUG_FUNCPTR (gst_ducati_mpeg4dec_update_buffer_size); bclass->allocate_params = GST_DEBUG_FUNCPTR (gst_ducati_mpeg4dec_allocate_params); - bclass->push_input = - GST_DEBUG_FUNCPTR (gst_ducati_mpeg4dec_push_input); + bclass->push_input = GST_DEBUG_FUNCPTR (gst_ducati_mpeg4dec_push_input); } static void gst_ducati_mpeg4dec_init (GstDucatiMpeg4Dec * self, GstDucatiMpeg4DecClass * gclass) { +#ifndef GST_DISABLE_GST_DEBUG + GstDucatiVidDec *dec = GST_DUCATIVIDDEC (self); + + dec->error_strings[0] = "no video object sequence found"; + dec->error_strings[1] = "incorrect video object type"; + dec->error_strings[2] = "error in video object layer"; + dec->error_strings[3] = "error parsing group of video"; + dec->error_strings[4] = "error parsing video object plane"; + dec->error_strings[5] = "error in short header parsing"; + dec->error_strings[6] = "error in GOB parsing"; + dec->error_strings[7] = "error in video packet parsing"; + dec->error_strings[16] = "error in MB data parsing"; + dec->error_strings[17] = "invalid parameter"; + dec->error_strings[18] = "unsupported feature"; + dec->error_strings[19] = "stream end"; + dec->error_strings[20] = "valid header not found"; + dec->error_strings[21] = "unsupported resolution"; + dec->error_strings[22] = "stream buffer underflow"; + dec->error_strings[23] = "invalid mbox message"; + dec->error_strings[24] = "no frame to flush"; + dec->error_strings[25] = "given vop is not codec"; + dec->error_strings[26] = "start code not present"; + dec->error_strings[27] = "unsupported time increment resolution"; + dec->error_strings[28] = "resolution change"; + dec->error_strings[29] = "unsupported H263 annex"; + dec->error_strings[30] = "bad HDVICP2 state"; + dec->error_strings[31] = "frame dropped"; +#endif } diff -Nru gst-plugin-ducati-1.6.7.2/src/gstducatimpeg4enc.c gst-plugin-ducati-1.6.7.20/src/gstducatimpeg4enc.c --- gst-plugin-ducati-1.6.7.2/src/gstducatimpeg4enc.c 2012-10-02 13:38:43.000000000 +0000 +++ gst-plugin-ducati-1.6.7.20/src/gstducatimpeg4enc.c 2012-12-06 15:48:06.000000000 +0000 @@ -33,8 +33,8 @@ #define GST_CAT_DEFAULT gst_ducati_debug -#define DEFAULT_PROFILE GST_DUCATI_MPEG4ENC_PROFILE_SIMPLE -#define DEFAULT_LEVEL GST_DUCATI_MPEG4ENC_LEVEL_5 +#define DEFAULT_PROFILE MPEG4_SIMPLE_PROFILE_IDC +#define DEFAULT_LEVEL IMPEG4ENC_SP_LEVEL_5 #define GST_TYPE_DUCATI_MPEG4ENC_PROFILE (gst_ducati_mpeg4enc_profile_get_type ()) #define GST_TYPE_DUCATI_MPEG4ENC_LEVEL (gst_ducati_mpeg4enc_level_get_type ()) @@ -81,25 +81,6 @@ GST_TYPE_DUCATIVIDENC); -/* the values for the following enums are taken from the codec */ - -enum -{ - GST_DUCATI_MPEG4ENC_PROFILE_SIMPLE = 3, /**< BaseLine Profile */ -}; - -enum -{ - GST_DUCATI_MPEG4ENC_LEVEL_0 = 0, /**< MPEG4 Simple Profile Level 0 */ - GST_DUCATI_MPEG4ENC_LEVEL_0B = 9, /**< MPEG4 Simple Profile Level 0b*/ - GST_DUCATI_MPEG4ENC_LEVEL_1 = 1, /**< MPEG4 Simple Profile Level 1 */ - GST_DUCATI_MPEG4ENC_LEVEL_2 = 2, /**< MPEG4 Simple Profile Level 2 */ - GST_DUCATI_MPEG4ENC_LEVEL_3 = 3, /**< MPEG4 Simple Profile Level 3 */ - GST_DUCATI_MPEG4ENC_LEVEL_4A = 4, /**< MPEG4 Simple Profile Level 4a*/ - GST_DUCATI_MPEG4ENC_LEVEL_5 = 5, /**< MPEG4 Simple Profile Level 5 */ - GST_DUCATI_MPEG4ENC_LEVEL_6 = 6 /**< MPEG4 Simple Profile Level 6 */ -}; - static GType gst_ducati_mpeg4enc_profile_get_type (void) { @@ -107,7 +88,7 @@ if (!type) { static const GEnumValue vals[] = { - {GST_DUCATI_MPEG4ENC_PROFILE_SIMPLE, "Simple", "simple"}, + {IMPEG4ENC_SP_LEVEL_3, "Simple", "simple"}, {0, NULL, NULL}, }; @@ -124,14 +105,14 @@ if (!type) { static const GEnumValue vals[] = { - {GST_DUCATI_MPEG4ENC_LEVEL_0, "Level 0", "level-0"}, - {GST_DUCATI_MPEG4ENC_LEVEL_0B, "Level 0B", "level-0b"}, - {GST_DUCATI_MPEG4ENC_LEVEL_1, "Level 1", "level-1"}, - {GST_DUCATI_MPEG4ENC_LEVEL_2, "Level 2", "level-2"}, - {GST_DUCATI_MPEG4ENC_LEVEL_3, "Level 3", "level-3"}, - {GST_DUCATI_MPEG4ENC_LEVEL_4A, "Level 4", "level-4"}, - {GST_DUCATI_MPEG4ENC_LEVEL_5, "Level 5", "level-5"}, - {GST_DUCATI_MPEG4ENC_LEVEL_6, "Level 6", "level-6"}, + {IMPEG4ENC_SP_LEVEL_0, "Level 0", "level-0"}, + {IMPEG4ENC_SP_LEVEL_0B, "Level 0B", "level-0b"}, + {IMPEG4ENC_SP_LEVEL_1, "Level 1", "level-1"}, + {IMPEG4ENC_SP_LEVEL_2, "Level 2", "level-2"}, + {IMPEG4ENC_SP_LEVEL_3, "Level 3", "level-3"}, + {IMPEG4ENC_SP_LEVEL_4A, "Level 4", "level-4"}, + {IMPEG4ENC_SP_LEVEL_5, "Level 5", "level-5"}, + {IMPEG4ENC_SP_LEVEL_6, "Level 6", "level-6"}, {0, NULL, NULL}, }; @@ -237,10 +218,25 @@ } } +static const char * +get_profile_name (guint profile) +{ + switch (profile) { + case IMPEG4ENC_SP_LEVEL_3: + return "simple"; + default: + return NULL; + } +} + static gboolean gst_ducati_mpeg4enc_configure (GstDucatiVidEnc * videnc) { GstDucatiMPEG4Enc *self = GST_DUCATIMPEG4ENC (videnc); + const GstVideoState *state; + GstCaps *caps; + const char *s; + gboolean ret = TRUE; if (!GST_DUCATIVIDENC_CLASS (parent_class)->configure (videnc)) return FALSE; @@ -251,7 +247,21 @@ videnc->dynParams->mvAccuracy = IVIDENC2_MOTIONVECTOR_HALFPEL; videnc->dynParams->interFrameInterval = 0; - return TRUE; + state = gst_base_video_encoder_get_state (GST_BASE_VIDEO_ENCODER (videnc)); + caps = gst_caps_new_simple ("video/mpeg", + "mpegversion", G_TYPE_INT, 4, + "systemstream", G_TYPE_BOOLEAN, FALSE, + "width", G_TYPE_INT, videnc->rect.w, + "height", G_TYPE_INT, videnc->rect.h, + "framerate", GST_TYPE_FRACTION, state->fps_n, state->fps_d, + "pixel-aspect-ratio", GST_TYPE_FRACTION, state->par_n, state->par_d, + NULL); + s = get_profile_name (self->profile); + if (s) + gst_caps_set_simple (caps, "profile", G_TYPE_STRING, s, NULL); + ret = gst_pad_set_caps (GST_BASE_VIDEO_CODEC_SRC_PAD (self), caps); + + return ret; } static gboolean diff -Nru gst-plugin-ducati-1.6.7.2/src/gstducatimpeg4enc.h gst-plugin-ducati-1.6.7.20/src/gstducatimpeg4enc.h --- gst-plugin-ducati-1.6.7.2/src/gstducatimpeg4enc.h 2012-10-02 13:38:43.000000000 +0000 +++ gst-plugin-ducati-1.6.7.20/src/gstducatimpeg4enc.h 2012-12-06 15:48:06.000000000 +0000 @@ -20,6 +20,7 @@ #ifndef __GST_DUCATIMPEG4ENC_H__ #define __GST_DUCATIMPEG4ENC_H__ +#include #include "gstducatividenc.h" #define GST_TYPE_DUCATIMPEG4ENC \ diff -Nru gst-plugin-ducati-1.6.7.2/src/gstducatirvdec.c gst-plugin-ducati-1.6.7.20/src/gstducatirvdec.c --- gst-plugin-ducati-1.6.7.2/src/gstducatirvdec.c 2012-10-02 13:38:43.000000000 +0000 +++ gst-plugin-ducati-1.6.7.20/src/gstducatirvdec.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,256 +0,0 @@ -/* - * GStreamer - * Copyright (c) 2010, Texas Instruments Incorporated - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation - * version 2.1 of the License. - * - * 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/** - * SECTION:element-ducatirvdec - * - * FIXME:Describe ducatirvdec here. - * - * - * Example launch line - * |[ - * gst-launch -v -m fakesrc ! ducatirvdec ! fakesink silent=TRUE - * ]| - * - */ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include "gstducatirvdec.h" - - -#define PADX 32 -#define PADY 32 - - -GST_BOILERPLATE (GstDucatiRVDec, gst_ducati_rvdec, GstDucatiVidDec, - GST_TYPE_DUCATIVIDDEC); - -static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS ("video/x-pn-realvideo, " - "systemstream = (boolean)false, " - "rmversion = (int){ 3, 4 }, " - "width = (int)[ 16, 2048 ], " - "height = (int)[ 16, 2048 ], " - "framerate = (fraction)[ 0, max ];") - ); - -/* GstDucatiVidDec vmethod implementations */ - -static gboolean -gst_ducati_rvdec_parse_caps (GstDucatiVidDec * vdec, GstStructure * s) -{ - GstDucatiRVDec *self = GST_DUCATIRVDEC (vdec); - - if (parent_class->parse_caps (vdec, s)) { - gboolean ret = gst_structure_get_int (s, "rmversion", &self->rmversion); - if (ret) { - IrealVDEC_Params *params = (IrealVDEC_Params *) vdec->params; - GST_DEBUG_OBJECT (self, "rmversion: %d", self->rmversion); - - if (self->rmversion == 3) { - params->stream_type = 1; - params->codec_version = 8; - } else if (self->rmversion == 4) { - params->stream_type = 1; - params->codec_version = 9; - } else { - ret = FALSE; - } - } - - return ret; - } - - return FALSE; -} - -static void -gst_ducati_rvdec_update_buffer_size (GstDucatiVidDec * self) -{ - /* calculate output buffer parameters: */ - self->padded_width = ALIGN2 (self->width + (2 * PADX), 7); - self->padded_height = self->height + 2 * PADY; - self->min_buffers = 8; -} - -static gboolean -gst_ducati_rvdec_allocate_params (GstDucatiVidDec * vdec, gint params_sz, - gint dynparams_sz, gint status_sz, gint inargs_sz, gint outargs_sz) -{ - gboolean ret = parent_class->allocate_params (vdec, - sizeof (IrealVDEC_Params), sizeof (IrealVDEC_DynamicParams), - sizeof (IrealVDEC_Status), sizeof (IrealVDEC_InArgs), - sizeof (IrealVDEC_OutArgs)); - - if (ret) { - /*IrealVDEC_Params *params = (IrealVDEC_Params *) vdec->params;*/ - vdec->params->displayDelay = IVIDDEC3_DISPLAY_DELAY_1; - vdec->dynParams->newFrameFlag = FALSE; - vdec->dynParams->lateAcquireArg = -1; - vdec->params->numInputDataUnits = 1; - vdec->params->numOutputDataUnits = 1; - } - - return ret; -} - -static GstBuffer * -gst_ducati_rvdec_push_input (GstDucatiVidDec * vdec, GstBuffer * buf) -{ - GstDucatiRVDec *self = GST_DUCATIRVDEC (vdec); - guint8 *data; - guint8 val[4]; - gint i, sz, slice_count; - - /* *** on first buffer, build up the stream header for the codec *** */ - if (G_UNLIKELY (vdec->first_in_buffer) && vdec->codec_data) { - - sz = GST_BUFFER_SIZE (vdec->codec_data); - data = GST_BUFFER_DATA (vdec->codec_data); - - /* header size, 4 bytes, big-endian */ - GST_WRITE_UINT32_BE (val, sz + 26); - push_input (vdec, val, 4); - - /* stream type */ - if (self->rmversion == 3) { - push_input (vdec, (guint8 *)"VIDORV30", 8); - } else if (self->rmversion == 4) { - push_input (vdec, (guint8 *)"VIDORV40", 8); - } - - /* horiz x vert resolution */ - GST_WRITE_UINT16_BE (val, vdec->width); - push_input (vdec, val, 2); - GST_WRITE_UINT16_BE (val, vdec->height); - push_input (vdec, val, 2); - - /* unknown? */ - GST_WRITE_UINT32_BE (val, 0x000c0000); - push_input (vdec, val, 4); - - /* unknown? may be framerate.. */ - GST_WRITE_UINT32_BE (val, 0x0000000f); - push_input (vdec, val, 4); - - /* unknown? */ - GST_WRITE_UINT16_BE (val, 0x0000); - push_input (vdec, val, 2); - - /* and rest of stream header is the codec_data */ - push_input (vdec, data, sz); - } - - data = GST_BUFFER_DATA (buf); - sz = GST_BUFFER_SIZE (buf); - slice_count = (*data++) + 1; - - /* payload size, excluding fixed header and slice header */ - sz -= 1 + (8 * slice_count); - - /* *** insert frame header *** */ - /* payload size */ - GST_WRITE_UINT32_BE (val, sz); - push_input (vdec, val, 4); - - /* unknown? may be timestamp, hopefully decoder doesn't care */ - GST_WRITE_UINT32_BE (val, 0x00000001); - push_input (vdec, val, 4); - - /* unknown? may be sequence number, hopefully decoder doesn't care */ - GST_WRITE_UINT16_BE (val, 0x0000); - push_input (vdec, val, 2); - - /* unknown? may indicate I frame, hopefully decoder doesn't care */ - if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT)) { - GST_WRITE_UINT16_BE (val, 0x0000); - } else { - GST_WRITE_UINT16_BE (val, 0x0002); - } - push_input (vdec, val, 2); - - /* unknown? seems to be always zeros */ - GST_WRITE_UINT32_BE (val, 0x00000000); - push_input (vdec, val, 4); - - /* convert the slice_header to big endian, and note that the codec - * expects to get slice_count rather than slice_count-1 - */ - GST_WRITE_UINT32_BE (val, slice_count); - push_input (vdec, val, 4); - - for (i = 0; i < slice_count; i++) { - GST_WRITE_UINT32_BE (val, 0x00000001); - push_input (vdec, val, 4); - - data += 4; - GST_WRITE_UINT32_BE (val, GST_READ_UINT32_LE (data)); - data += 4; - push_input (vdec, val, 4); - } - - /* copy the payload (rest of buffer) */ - push_input (vdec, data, sz); - gst_buffer_unref (buf); - - return NULL; -} - -/* GObject vmethod implementations */ - -static void -gst_ducati_rvdec_base_init (gpointer gclass) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (gclass); - - gst_element_class_set_details_simple (element_class, - "DucatiRVDec", - "Codec/Decoder/Video", - "Decodes video in RealVideo (RV8/9/10) format with ducati", - "Rob Clark "); - - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&sink_factory)); -} - -static void -gst_ducati_rvdec_class_init (GstDucatiRVDecClass * klass) -{ - GstDucatiVidDecClass *bclass = GST_DUCATIVIDDEC_CLASS (klass); - bclass->codec_name = "ivahd_realvdec"; - bclass->parse_caps = - GST_DEBUG_FUNCPTR (gst_ducati_rvdec_parse_caps); - bclass->update_buffer_size = - GST_DEBUG_FUNCPTR (gst_ducati_rvdec_update_buffer_size); - bclass->allocate_params = - GST_DEBUG_FUNCPTR (gst_ducati_rvdec_allocate_params); - bclass->push_input = - GST_DEBUG_FUNCPTR (gst_ducati_rvdec_push_input); -} - -static void -gst_ducati_rvdec_init (GstDucatiRVDec * self, - GstDucatiRVDecClass * gclass) -{ -} diff -Nru gst-plugin-ducati-1.6.7.2/src/gstducatirvdec.h gst-plugin-ducati-1.6.7.20/src/gstducatirvdec.h --- gst-plugin-ducati-1.6.7.2/src/gstducatirvdec.h 2012-10-02 13:38:43.000000000 +0000 +++ gst-plugin-ducati-1.6.7.20/src/gstducatirvdec.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,55 +0,0 @@ -/* - * GStreamer - * Copyright (c) 2010, Texas Instruments Incorporated - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation - * version 2.1 of the License. - * - * 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef __GST_DUCATIRVDEC_H__ -#define __GST_DUCATIRVDEC_H__ - -#include "gstducatividdec.h" - -#include - - -G_BEGIN_DECLS - -#define GST_TYPE_DUCATIRVDEC (gst_ducati_rvdec_get_type()) -#define GST_DUCATIRVDEC(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_DUCATIRVDEC, GstDucatiRVDec)) -#define GST_DUCATIRVDEC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_DUCATIRVDEC, GstDucatiRVDecClass)) -#define GST_IS_DUCATIRVDEC(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_DUCATIRVDEC)) -#define GST_IS_DUCATIRVDEC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_DUCATIRVDEC)) - -typedef struct _GstDucatiRVDec GstDucatiRVDec; -typedef struct _GstDucatiRVDecClass GstDucatiRVDecClass; - -struct _GstDucatiRVDec -{ - GstDucatiVidDec parent; - - gint rmversion; -}; - -struct _GstDucatiRVDecClass -{ - GstDucatiVidDecClass parent_class; -}; - -GType gst_ducati_rvdec_get_type (void); - -G_END_DECLS - -#endif /* __GST_DUCATIRVDEC_H__ */ diff -Nru gst-plugin-ducati-1.6.7.2/src/gstducativc1dec.c gst-plugin-ducati-1.6.7.20/src/gstducativc1dec.c --- gst-plugin-ducati-1.6.7.2/src/gstducativc1dec.c 2012-10-02 13:38:43.000000000 +0000 +++ gst-plugin-ducati-1.6.7.20/src/gstducativc1dec.c 2012-12-06 15:48:06.000000000 +0000 @@ -52,8 +52,7 @@ "wmvversion = (int) 3, " "format = (fourcc){ WVC1, WMV3 }, " "width = (int)[ 16, 2048 ], " - "height = (int)[ 16, 2048 ], " - "framerate = (fraction)[ 0, max ];") + "height = (int)[ 16, 2048 ], " "framerate = (fraction)[ 0, max ];") ); /* GstDucatiVidDec vmethod implementations */ @@ -79,11 +78,10 @@ break; } } + GST_INFO_OBJECT (vdec, "level %d", self->level); return ret; } - GST_INFO_OBJECT (vdec, "level %d", self->level); - return FALSE; } @@ -118,7 +116,7 @@ params->frameLayerDataPresentFlag = FALSE; /* enable concealment */ - params->ErrorConcealmentON = 1; + params->errorConcealmentON = 1; /* codec wants lateAcquireArg = -1 */ self->dynParams->lateAcquireArg = -1; @@ -139,6 +137,19 @@ self->first_ts = GST_BUFFER_TIMESTAMP (buf); if (G_UNLIKELY (vdec->first_in_buffer) && vdec->codec_data) { + if (GST_BUFFER_SIZE (vdec->codec_data) > 0) { + unsigned char *header = GST_BUFFER_DATA (vdec->codec_data); + + /* There is at least one VC1 stream that claims it is simple profile, + but goes on to have frames that use some feature that is unavailable + in simple profile(intensity compensation). Since ducati supports + both, we frob the header to claim all simple profile videos are + main profile. This is a lie, but it should not cause any trouble + (I'm sure all liars must say that). */ + if (!(header[0] & 192)) + header[0] |= 64; + } + if (self->level == 4) { /* for VC-1 Advanced Profile, strip off first byte, and * send rest of codec_data unmodified; @@ -151,52 +162,54 @@ */ val = 0xc5ffffff; /* we don't know the number of frames */ - push_input (vdec, (guint8 *) & val, 4); + push_input (vdec, (const guint8 *) &val, 4); /* STRUCT_C (preceded by length).. see Table 263, 264 */ val = 0x00000004; - push_input (vdec, (guint8 *) & val, 4); + push_input (vdec, (const guint8 *) &val, 4); val = GST_READ_UINT32_LE (GST_BUFFER_DATA (vdec->codec_data)); /* FIXME: i have NO idea why asfdemux gives me something I need to patch... */ val |= 0x01 << 24; - push_input (vdec, (guint8 *) & val, 4); + push_input (vdec, (const guint8 *) &val, 4); /* STRUCT_A.. see Table 260 and Annex J.2 */ val = vdec->height; - push_input (vdec, (guint8 *) & val, 4); + push_input (vdec, (const guint8 *) &val, 4); val = vdec->width; - push_input (vdec, (guint8 *) & val, 4); - GST_INFO_OBJECT (vdec, "seq hdr resolution: %dx%d", vdec->width, vdec->height); + push_input (vdec, (const guint8 *) &val, 4); + GST_INFO_OBJECT (vdec, "seq hdr resolution: %dx%d", vdec->width, + vdec->height); val = 0x0000000c; - push_input (vdec, (guint8 *) & val, 4); + push_input (vdec, (const guint8 *) &val, 4); /* STRUCT_B.. see Table 261, 262 */ val = 0x00000000; /* not sure how to populate, but codec ignores anyways */ - push_input (vdec, (guint8 *) & val, 4); - push_input (vdec, (guint8 *) & val, 4); - push_input (vdec, (guint8 *) & val, 4); + push_input (vdec, (const guint8 *) &val, 4); + push_input (vdec, (const guint8 *) &val, 4); + push_input (vdec, (const guint8 *) &val, 4); } } /* VC-1 Advanced profile needs start-code prepended: */ if (self->level == 4) { - static guint8 sc[] = { 0x00, 0x00, 0x01, 0x0d }; /* start code */ + static const guint8 sc[] = { 0x00, 0x00, 0x01, 0x0d }; /* start code */ push_input (vdec, sc, sizeof (sc)); } - + if (params->frameLayerDataPresentFlag) { val = GST_BUFFER_SIZE (buf); if (!GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT)) val |= 0x80 << 24; else val |= 0x00 << 24; - push_input (vdec, (guint8 *) & val, 4); + push_input (vdec, (const guint8 *) &val, 4); val = GST_TIME_AS_MSECONDS (GST_BUFFER_TIMESTAMP (buf) - self->first_ts); - push_input (vdec, (guint8 *) & val, 4); + push_input (vdec, (const guint8 *) &val, 4); } + push_input (vdec, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf)); gst_buffer_unref (buf); @@ -235,8 +248,7 @@ /* GstElement vmethod implementations */ static GstStateChangeReturn -gst_ducati_vc1dec_change_state (GstElement * element, - GstStateChange transition) +gst_ducati_vc1dec_change_state (GstElement * element, GstStateChange transition) { GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; GstDucatiVC1Dec *self = GST_DUCATIVC1DEC (element); @@ -292,24 +304,43 @@ GST_DEBUG_FUNCPTR (gst_ducati_vc1dec_change_state); bclass->codec_name = "ivahd_vc1vdec"; - bclass->parse_caps = - GST_DEBUG_FUNCPTR (gst_ducati_vc1dec_parse_caps); + bclass->parse_caps = GST_DEBUG_FUNCPTR (gst_ducati_vc1dec_parse_caps); bclass->update_buffer_size = GST_DEBUG_FUNCPTR (gst_ducati_vc1dec_update_buffer_size); bclass->allocate_params = GST_DEBUG_FUNCPTR (gst_ducati_vc1dec_allocate_params); - bclass->push_input = - GST_DEBUG_FUNCPTR (gst_ducati_vc1dec_push_input); + bclass->push_input = GST_DEBUG_FUNCPTR (gst_ducati_vc1dec_push_input); bclass->handle_error = GST_DEBUG_FUNCPTR (gst_ducati_vc1dec_handle_error); bclass->can_drop_frame = GST_DEBUG_FUNCPTR (gst_ducati_vc1dec_can_drop_frame); } static void -gst_ducati_vc1dec_init (GstDucatiVC1Dec * self, - GstDucatiVC1DecClass * gclass) +gst_ducati_vc1dec_init (GstDucatiVC1Dec * self, GstDucatiVC1DecClass * gclass) { GstDucatiVidDec *vdec = GST_DUCATIVIDDEC (self); +#ifndef GST_DISABLE_GST_DEBUG + vdec->error_strings[0] = "unsupported VIDDEC3 params"; + vdec->error_strings[1] = "unsupported dynamic VIDDEC3 params"; + vdec->error_strings[2] = "unsupported VC1 VIDDEC3 params"; + vdec->error_strings[3] = "bad datasync settings"; + vdec->error_strings[4] = "no slice"; + vdec->error_strings[5] = "corrupted slice header"; + vdec->error_strings[6] = "corrupted MB data"; + vdec->error_strings[7] = "unsupported VC1 feature"; + vdec->error_strings[16] = "stream end"; + vdec->error_strings[17] = "unsupported resolution"; + vdec->error_strings[18] = "IVA standby"; + vdec->error_strings[19] = "invalid mbox message"; + vdec->error_strings[20] = "corrupted sequence header"; + vdec->error_strings[21] = "corrupted entry point header"; + vdec->error_strings[22] = "corrupted picture header"; + vdec->error_strings[23] = "ref picture buffer error"; + vdec->error_strings[24] = "no sequence header"; + vdec->error_strings[30] = "invalid buffer descriptor"; + vdec->error_strings[31] = "pic size change"; +#endif + self->level = -1; self->first_ts = GST_CLOCK_TIME_NONE; vdec->pageMemType = XDM_MEMTYPE_RAW; diff -Nru gst-plugin-ducati-1.6.7.2/src/gstducatividdec.c gst-plugin-ducati-1.6.7.20/src/gstducatividdec.c --- gst-plugin-ducati-1.6.7.2/src/gstducatividdec.c 2012-10-02 13:38:43.000000000 +0000 +++ gst-plugin-ducati-1.6.7.20/src/gstducatividdec.c 2012-12-06 15:48:06.000000000 +0000 @@ -31,13 +31,15 @@ static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, - GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV_STRIDED ("NV12", "[ 0, max ]")) + GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("NV12")) ); enum { PROP_0, PROP_VERSION, + PROP_MAX_REORDER_FRAMES, + PROP_CODEC_DEBUG_INFO }; /* helper functions */ @@ -147,7 +149,7 @@ static gboolean codec_create (GstDucatiVidDec * self) { - gint err; + gint err, n; const gchar *codec_name; codec_delete (self); @@ -191,6 +193,16 @@ self->inBufs->numBufs = 1; self->inBufs->descs[0].buf = (XDAS_Int8 *) omap_bo_handle (self->input_bo); + /* Actual buffers will be set later, as they will be different for every + frame. We allow derived classes to add their own buffers, however, so + we initialize the number of outBufs here, counting the number of extra + buffers required, including "holes" in planes, which may not be filled + if not assigned. */ + self->outBufs->numBufs = 2; /* luma and chroma planes, always */ + for (n = 0; n < 3; n++) + if (self->params->metadataType[n] != IVIDEO_METADATAPLANE_NONE) + self->outBufs->numBufs = 2 + n + 1; + return TRUE; } @@ -259,7 +271,8 @@ return codec_prepare_outbuf (self, buf, FALSE); } - self->outBufs->numBufs = 2; + /* There are at least two buffers. Derived classes may add codec specific + buffers (eg, debug info) after these two if they want to. */ self->outBufs->descs[0].memType = XDM_MEMTYPE_BO; self->outBufs->descs[0].buf = (XDAS_Int8 *) omap_bo_handle (priv->bo); self->outBufs->descs[0].bufSize.bytes = priv->uv_offset; @@ -294,9 +307,41 @@ } } +static GstFlowReturn +gst_ducati_viddec_push_earliest (GstDucatiVidDec * self) +{ + guint64 earliest_order = G_MAXUINT64; + guint earliest_index = 0, i; + GstBuffer *buf; + + if (self->backlog_nframes == 0) + return GST_FLOW_OK; + + /* work out which frame has the earliest poc */ + for (i = 0; i < self->backlog_nframes; i++) { + guint64 order = GST_BUFFER_OFFSET_END (self->backlog_frames[i]); + if (earliest_order == G_MAXUINT64 || order < earliest_order) { + earliest_order = order; + earliest_index = i; + } + } + + /* send it, giving away the ref */ + buf = self->backlog_frames[earliest_index]; + self->backlog_frames[earliest_index] = + self->backlog_frames[--self->backlog_nframes]; + GST_DEBUG_OBJECT (self, "Actually pushing backlog buffer %" GST_PTR_FORMAT, + buf); + return gst_pad_push (self->srcpad, buf); +} + static void gst_ducati_viddec_on_flush (GstDucatiVidDec * self, gboolean eos) { + /* push everything on the backlog, ignoring errors */ + while (self->backlog_nframes > 0) { + gst_ducati_viddec_push_earliest (self); + } } static gint @@ -316,22 +361,27 @@ memset (&self->outArgs->outputID, 0, sizeof (self->outArgs->outputID)); memset (&self->outArgs->freeBufID, 0, sizeof (self->outArgs->freeBufID)); + GST_DEBUG ("Calling VIDDEC3_process"); t = gst_util_get_timestamp (); err = VIDDEC3_process (self->codec, self->inBufs, self->outBufs, self->inArgs, self->outArgs); - GST_DEBUG_OBJECT (self, "%10dns", (gint) (gst_util_get_timestamp () - t)); + t = gst_util_get_timestamp () - t; + GST_DEBUG_OBJECT (self, "VIDDEC3_process took %10dns (%d ms)", (gint) t, + (gint) (t / 1000000)); if (err) { GST_WARNING_OBJECT (self, "err=%d, extendedError=%08x", err, self->outArgs->extendedError); - gst_ducati_log_extended_error_info (self->outArgs->extendedError); + gst_ducati_log_extended_error_info (self->outArgs->extendedError, + self->error_strings); err = VIDDEC3_control (self->codec, XDM_GETSTATUS, self->dynParams, self->status); if (err) { GST_WARNING_OBJECT (self, "XDM_GETSTATUS: err=%d, extendedError=%08x", err, self->status->extendedError); - gst_ducati_log_extended_error_info (self->status->extendedError); + gst_ducati_log_extended_error_info (self->status->extendedError, + self->error_strings); } if (flush) @@ -503,6 +553,7 @@ gst_ducati_viddec_codec_flush (GstDucatiVidDec * self, gboolean eos) { gint err = FALSE; + int prev_num_in_bufs, prev_num_out_bufs; GST_DEBUG_OBJECT (self, "flush: eos=%d", eos); @@ -539,10 +590,14 @@ goto out; } + prev_num_in_bufs = self->inBufs->numBufs; + prev_num_out_bufs = self->outBufs->numBufs; + self->inBufs->descs[0].bufSize.bytes = 0; self->inBufs->numBufs = 0; self->inArgs->numBytes = 0; self->inArgs->inputID = 0; + self->outBufs->numBufs = 0; do { err = codec_process (self, eos, TRUE, NULL); @@ -559,8 +614,9 @@ self->dynParams->newFrameFlag = XDAS_TRUE; - /* Reset the push buffer */ - self->inBufs->numBufs = 1; + /* Reset the push buffer and YUV buffers, plus any codec specific buffers */ + self->inBufs->numBufs = prev_num_in_bufs; + self->outBufs->numBufs = prev_num_out_bufs; /* on a flush, it is normal (and not an error) for the last _process() call * to return an error.. @@ -699,7 +755,26 @@ static GstFlowReturn gst_ducati_viddec_push_output (GstDucatiVidDec * self, GstBuffer * buf) { - return gst_pad_push (self->srcpad, buf); + GstFlowReturn ret = GST_FLOW_OK; + + /* if no reordering info was set, just send the buffer */ + if (GST_BUFFER_OFFSET_END (buf) == GST_BUFFER_OFFSET_NONE) { + GST_DEBUG_OBJECT (self, "No reordering info on that buffer, sending now"); + return gst_pad_push (self->srcpad, buf); + } + + /* add the frame to the list, the array will own the ref */ + GST_DEBUG_OBJECT (self, "Adding buffer %" GST_PTR_FORMAT " to backlog", buf); + self->backlog_frames[self->backlog_nframes++] = buf; + + /* push till we have no more than the max needed, or error */ + while (self->backlog_nframes > self->backlog_maxframes) { + ret = gst_ducati_viddec_push_earliest (self); + if (ret != GST_FLOW_OK) + break; + } + + return ret; } static gint @@ -756,9 +831,6 @@ } if (!outcaps) { - /* note: default to non-strided for better compatibility with - * other gst elements that don't understand stride: - */ outcaps = gst_caps_new_simple ("video/x-raw-yuv", "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('N', 'V', '1', '2'), NULL); } @@ -775,15 +847,8 @@ if (self->interlaced) gst_structure_set (out_s, "interlaced", G_TYPE_BOOLEAN, TRUE, NULL); - if (!strcmp (gst_structure_get_name (out_s), "video/x-raw-yuv-strided")) { - if (!gst_structure_get_int (out_s, "rowstride", &self->stride)) { - self->stride = 4096; - gst_structure_set (out_s, "rowstride", G_TYPE_INT, self->stride, NULL); - } - } else { - self->stride = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_NV12, - 0, self->padded_width); - } + self->stride = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_NV12, + 0, self->padded_width); self->outsize = gst_video_format_get_size (GST_VIDEO_FORMAT_NV12, self->stride, self->padded_height); @@ -807,6 +872,9 @@ GST_INFO_OBJECT (self, "set caps done %d, %" GST_PTR_FORMAT, ret, outcaps); + /* default to no reordering */ + self->backlog_maxframes = 0; + out: if (outcaps) gst_caps_unref (outcaps); @@ -834,41 +902,13 @@ gst_ducati_viddec_src_getcaps (GstPad * pad) { GstCaps *caps = NULL; - GstCaps *outcaps = NULL; - int i; caps = GST_PAD_CAPS (pad); if (caps == NULL) { - outcaps = gst_caps_copy (gst_pad_get_pad_template_caps (pad)); - return outcaps; - } - - outcaps = gst_caps_new_empty (); - - /* allow -rowstrided and regular yuv */ - for (i = 0; i < gst_caps_get_size (caps); i++) { - GstStructure *structure; - GstStructure *modified_structure; - GValue value = { 0 }; - - structure = gst_caps_get_structure (caps, i); - gst_caps_append_structure (outcaps, gst_structure_copy (structure)); - modified_structure = gst_structure_copy (structure); - - if (gst_structure_has_name (structure, "video/x-raw-yuv")) { - gst_structure_set_name (modified_structure, "video/x-raw-yuv-strided"); - g_value_init (&value, GST_TYPE_INT_RANGE); - gst_value_set_int_range (&value, 0, G_MAXINT); - gst_structure_set_value (modified_structure, "rowstride", &value); - gst_caps_append_structure (outcaps, modified_structure); - g_value_unset (&value); - } else { - gst_structure_set_name (modified_structure, "video/x-raw-yuv"); - gst_structure_remove_field (modified_structure, "rowstride"); - gst_caps_append_structure (outcaps, modified_structure); - } + return gst_caps_copy (gst_pad_get_pad_template_caps (pad)); + } else { + return gst_caps_copy (caps); } - return outcaps; } static gboolean @@ -1061,6 +1101,7 @@ gst_buffer_unref (buf); return GST_FLOW_ERROR; } + GST_BUFFER_OFFSET_END (outbuf) = GST_BUFFER_OFFSET_END (buf); have_out_buf: buf = GST_DUCATIVIDDEC_GET_CLASS (self)->push_input (self, buf); @@ -1094,7 +1135,8 @@ if (err) { GST_ELEMENT_ERROR (self, STREAM, DECODE, (NULL), ("process returned error: %d %08x", err, self->outArgs->extendedError)); - gst_ducati_log_extended_error_info (self->outArgs->extendedError); + gst_ducati_log_extended_error_info (self->outArgs->extendedError, + self->error_strings); return GST_FLOW_ERROR; } @@ -1340,6 +1382,32 @@ break; } + case PROP_MAX_REORDER_FRAMES: + g_value_set_int (value, self->backlog_max_maxframes); + break; + case PROP_CODEC_DEBUG_INFO: + g_value_set_boolean (value, self->codec_debug_info); + break; + default:{ + G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec); + break; + } + } +} + +static void +gst_ducati_viddec_set_property (GObject * obj, + guint prop_id, const GValue * value, GParamSpec * pspec) +{ + GstDucatiVidDec *self = GST_DUCATIVIDDEC (obj); + + switch (prop_id) { + case PROP_MAX_REORDER_FRAMES: + self->backlog_max_maxframes = g_value_get_int (value); + break; + case PROP_CODEC_DEBUG_INFO: + self->codec_debug_info = g_value_get_boolean (value); + break; default:{ G_OBJECT_WARN_INVALID_PROPERTY_ID (obj, prop_id, pspec); break; @@ -1382,6 +1450,8 @@ gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_ducati_viddec_get_property); + gobject_class->set_property = + GST_DEBUG_FUNCPTR (gst_ducati_viddec_set_property); gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_ducati_viddec_finalize); gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_ducati_viddec_change_state); @@ -1401,6 +1471,24 @@ g_param_spec_string ("version", "Version", "The codec version string", "", G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_MAX_REORDER_FRAMES, + g_param_spec_int ("max-reorder-frames", + "Maximum number of frames needed for reordering", + "The maximum number of frames needed for reordering output frames. " + "Only meaningful for codecs with B frames. 0 means no reordering. " + "This value will be used if the correct value cannot be inferred " + "from the stream. Too low a value may cause misordering, too high " + "will cause extra latency.", + 0, MAX_BACKLOG_FRAMES, MAX_BACKLOG_FRAMES, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_CODEC_DEBUG_INFO, + g_param_spec_boolean ("codec-debug-info", + "Gather debug info from the codec", + "Gather and log relevant debug information from the codec. " + "What is gathered is typically codec specific", FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); } static void @@ -1408,6 +1496,8 @@ { GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); + gst_ducati_set_generic_error_strings (self->error_strings); + self->sinkpad = gst_pad_new_from_template (gst_element_class_get_pad_template (gstelement_class, "sink"), "sink"); @@ -1463,6 +1553,12 @@ self->device = NULL; self->input_bo = NULL; + self->backlog_maxframes = 0; + self->backlog_nframes = 0; + self->backlog_max_maxframes = MAX_BACKLOG_FRAMES; + + self->codec_debug_info = FALSE; + self->passed_in_bufs = g_hash_table_new_full (g_direct_hash, g_direct_equal, NULL, (GDestroyNotify) gst_buffer_unref); } diff -Nru gst-plugin-ducati-1.6.7.2/src/gstducatividdec.h gst-plugin-ducati-1.6.7.20/src/gstducatividdec.h --- gst-plugin-ducati-1.6.7.2/src/gstducatividdec.h 2012-10-02 13:38:43.000000000 +0000 +++ gst-plugin-ducati-1.6.7.20/src/gstducatividdec.h 2012-12-06 15:48:06.000000000 +0000 @@ -44,6 +44,8 @@ typedef struct _GstDucatiVidDec GstDucatiVidDec; typedef struct _GstDucatiVidDecClass GstDucatiVidDecClass; +#define MAX_BACKLOG_FRAMES 16 + struct _GstDucatiVidDec { GstElement parent; @@ -135,6 +137,16 @@ XDAS_Int16 pageMemType; struct omap_device *device; + + /* Frames waiting to be reordered */ + GstBuffer *backlog_frames[MAX_BACKLOG_FRAMES + 1]; + gint backlog_maxframes; + gint backlog_nframes; + gint backlog_max_maxframes; + + gboolean codec_debug_info; + + const char *error_strings[32]; }; struct _GstDucatiVidDecClass diff -Nru gst-plugin-ducati-1.6.7.2/src/gstducatividenc.c gst-plugin-ducati-1.6.7.20/src/gstducatividenc.c --- gst-plugin-ducati-1.6.7.2/src/gstducatividenc.c 2012-10-02 13:38:43.000000000 +0000 +++ gst-plugin-ducati-1.6.7.20/src/gstducatividenc.c 2012-12-06 15:48:06.000000000 +0000 @@ -33,10 +33,11 @@ #include #define GST_CAT_DEFAULT gst_ducati_debug +GST_DEBUG_CATEGORY_STATIC (GST_CAT_PERFORMANCE); #define DEFAULT_BITRATE 2048 #define DEFAULT_RATE_PRESET GST_DUCATI_VIDENC_RATE_PRESET_STORAGE -#define DEFAULT_INTRA_INTERVAL 15 +#define DEFAULT_INTRA_INTERVAL 16 #define GST_TYPE_DUCATI_VIDENC_RATE_PRESET (gst_ducati_videnc_rate_preset_get_type ()) @@ -74,6 +75,8 @@ static gboolean gst_ducati_videnc_allocate_params_default (GstDucatiVidEnc * self, gint params_sz, gint dynparams_sz, gint status_sz, gint inargs_sz, gint outargs_sz); +static gboolean gst_ducati_videnc_is_sync_point_default (GstDucatiVidEnc * enc, + int type); static gboolean gst_ducati_videnc_configure_default (GstDucatiVidEnc * self); static gboolean gst_ducati_videnc_event (GstBaseVideoEncoder * enc, GstEvent * event); @@ -87,17 +90,17 @@ enum { - GST_DUCATI_VIDENC_RATE_PRESET_LOW_DELAY = 1, /**< CBR rate control for video conferencing. */ - GST_DUCATI_VIDENC_RATE_PRESET_STORAGE = 2, /**< VBR rate control for local storage (DVD) + GST_DUCATI_VIDENC_RATE_PRESET_LOW_DELAY = IVIDEO_LOW_DELAY, /**< CBR rate control for video conferencing. */ + GST_DUCATI_VIDENC_RATE_PRESET_STORAGE = IVIDEO_STORAGE, /**< VBR rate control for local storage (DVD) * recording. */ - GST_DUCATI_VIDENC_RATE_PRESET_TWOPASS = 3, /**< Two pass rate control for non real time + GST_DUCATI_VIDENC_RATE_PRESET_TWOPASS = IVIDEO_TWOPASS, /**< Two pass rate control for non real time * applications. */ - GST_DUCATI_VIDENC_RATE_PRESET_NONE = 4, /**< No configurable video rate control + GST_DUCATI_VIDENC_RATE_PRESET_NONE = IVIDEO_NONE, /**< No configurable video rate control * mechanism. */ - GST_DUCATI_VIDENC_RATE_PRESET_USER_DEFINED = 5,/**< User defined configuration using extended + GST_DUCATI_VIDENC_RATE_PRESET_USER_DEFINED = IVIDEO_USER_DEFINED,/**< User defined configuration using extended * parameters. */ }; @@ -112,6 +115,9 @@ {GST_DUCATI_VIDENC_RATE_PRESET_LOW_DELAY, "Low Delay", "low-delay"}, {GST_DUCATI_VIDENC_RATE_PRESET_STORAGE, "Storage", "storage"}, {GST_DUCATI_VIDENC_RATE_PRESET_TWOPASS, "Two-Pass", "two-pass"}, + {GST_DUCATI_VIDENC_RATE_PRESET_NONE, "None", "none"}, + {GST_DUCATI_VIDENC_RATE_PRESET_USER_DEFINED, "User defined", + "user-defined"}, {0, NULL, NULL}, }; @@ -149,6 +155,7 @@ klass->allocate_params = gst_ducati_videnc_allocate_params_default; klass->configure = gst_ducati_videnc_configure_default; + klass->is_sync_point = gst_ducati_videnc_is_sync_point_default; g_object_class_install_property (gobject_class, PROP_BITRATE, g_param_spec_int ("bitrate", "Bitrate", "Bitrate in kbit/sec", -1, @@ -161,8 +168,12 @@ G_PARAM_READWRITE)); g_object_class_install_property (gobject_class, PROP_INTRA_INTERVAL, - g_param_spec_int ("intra-interval", "Intra-frame interval", "Interval between intra frames (keyframes)", 0, - INT_MAX, DEFAULT_INTRA_INTERVAL, G_PARAM_READWRITE)); + g_param_spec_int ("intra-interval", "Intra-frame interval", + "Interval between intra frames (keyframes)", 0, INT_MAX, + DEFAULT_INTRA_INTERVAL, G_PARAM_READWRITE)); + + GST_DEBUG_CATEGORY_GET (GST_CAT_PERFORMANCE, "GST_PERFORMANCE"); + } static void @@ -170,6 +181,8 @@ { GST_DEBUG ("gst_ducati_videnc_init"); + gst_ducati_set_generic_error_strings (self->error_strings); + self->device = NULL; self->engine = NULL; self->codec = NULL; @@ -202,7 +215,7 @@ gst_ducati_videnc_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { - GstDucatiVidEnc *self = GST_DUCATIVIDENC (object); + GstDucatiVidEnc *self; g_return_if_fail (GST_IS_DUCATIVIDENC (object)); self = GST_DUCATIVIDENC (object); @@ -226,7 +239,7 @@ gst_ducati_videnc_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { - GstDucatiVidEnc *self = GST_DUCATIVIDENC (object); + GstDucatiVidEnc *self; g_return_if_fail (GST_IS_DUCATIVIDENC (object)); self = GST_DUCATIVIDENC (object); @@ -276,7 +289,8 @@ if (err) { GST_ERROR_OBJECT (self, "XDM_SETPARAMS err=%d, extendedError=%08x", err, self->status->extendedError); - gst_ducati_log_extended_error_info (self->status->extendedError); + gst_ducati_log_extended_error_info (self->status->extendedError, + self->error_strings); return FALSE; } @@ -566,6 +580,8 @@ XDAS_Int32 err; const GstVideoState *state; int i; + GstClockTime ts; + GstClockTime t; state = gst_base_video_encoder_get_state (base_video_encoder); @@ -579,6 +595,7 @@ } inbuf = gst_buffer_ref (frame->sink_buffer); + ts = GST_BUFFER_TIMESTAMP (inbuf); have_inbuf: priv_in = get_buffer_priv (self, inbuf, state->width, state->height); if (priv_in == NULL) { @@ -587,6 +604,7 @@ inbuf = GST_BUFFER (gst_drm_buffer_pool_get (self->input_pool, FALSE)); memcpy (GST_BUFFER_DATA (inbuf), GST_BUFFER_DATA (frame->sink_buffer), GST_BUFFER_SIZE (frame->sink_buffer)); + GST_BUFFER_TIMESTAMP (inbuf) = ts; goto have_inbuf; } @@ -621,15 +639,20 @@ self->outBufs->descs[0].bufSize.bytes = GST_BUFFER_SIZE (outbuf); self->outBufs->descs[0].memType = XDM_MEMTYPE_BO; - self->inArgs->inputID = GPOINTER_TO_INT (inbuf); + GST_DEBUG ("Calling VIDENC2_process"); + t = gst_util_get_timestamp (); err = VIDENC2_process (self->codec, self->inBufs, self->outBufs, self->inArgs, self->outArgs); + t = gst_util_get_timestamp () - t; + GST_DEBUG_OBJECT (self, "VIDENC2_process took %10dns (%d ms)", (gint) t, + (gint) (t / 1000000)); if (err) { GST_WARNING_OBJECT (self, "process failed: err=%d, extendedError=%08x", err, self->outArgs->extendedError); - gst_ducati_log_extended_error_info (self->outArgs->extendedError); + gst_ducati_log_extended_error_info (self->outArgs->extendedError, + self->error_strings); err = VIDENC2_control (self->codec, XDM_GETSTATUS, (IVIDENC2_DynamicParams *) self->dynParams, @@ -641,16 +664,39 @@ return GST_FLOW_ERROR; } - if (!strcmp (GST_DUCATIVIDENC_GET_CLASS (self)->codec_name, "ivahd_h264enc")) { - if (self->outArgs->encodedFrameType == IVIDEO_IDR_FRAME) - frame->is_sync_point = TRUE; - } else { - if (self->outArgs->encodedFrameType == IVIDEO_I_FRAME) - frame->is_sync_point = TRUE; - } - frame->src_buffer = gst_buffer_new_and_alloc (self->outArgs->bytesGenerated); - memcpy (GST_BUFFER_DATA (frame->src_buffer), - GST_BUFFER_DATA (outbuf), self->outArgs->bytesGenerated); + if (self->outArgs->bytesGenerated > 0) { + frame->is_sync_point = + GST_DUCATIVIDENC_GET_CLASS (self)->is_sync_point (self, + self->outArgs->encodedFrameType); + frame->src_buffer = + gst_buffer_new_and_alloc (self->outArgs->bytesGenerated); + memcpy (GST_BUFFER_DATA (frame->src_buffer), GST_BUFFER_DATA (outbuf), + self->outArgs->bytesGenerated); + GST_CAT_DEBUG_OBJECT (GST_CAT_PERFORMANCE, self, + "Encoded frame in %u bytes", self->outArgs->bytesGenerated); + + /* As we can get frames in a different order we sent them (if the codec + supports B frames and we set it up for generating those), we need to + work out what input frame corresponds to the frame we just got, to + keep presentation times correct. + It seems that the codec will free buffers in the right order for this, + but I can not find anything saying this in the docs, so: + - it might be subject to change + - it might not be true in all setups + - it might not be true for all codecs + However, that's the only way I can see to do it. So there's a nice + assert below that will blow up if the codec does not free exactly one + input frame when it outputs a frame. That doesn't catch all cases, + such as when it frees them in the wrong order, but that seems less + likely to happen. + The timestamp and duration are given to the base class, which will + in turn set them onto the encoded buffer. */ + g_assert (self->outArgs->freeBufID[0] && !self->outArgs->freeBufID[1]); + inbuf = GST_BUFFER (self->outArgs->freeBufID[0]); + frame->presentation_timestamp = GST_BUFFER_TIMESTAMP (inbuf); + frame->presentation_duration = GST_BUFFER_DURATION (inbuf); + GST_BUFFER_OFFSET_END (frame->src_buffer) = GST_BUFFER_TIMESTAMP (inbuf); + } gst_buffer_unref (outbuf); @@ -665,6 +711,12 @@ } static gboolean +gst_ducati_videnc_is_sync_point_default (GstDucatiVidEnc * enc, int type) +{ + return type == IVIDEO_I_FRAME; +} + +static gboolean gst_ducati_videnc_event (GstBaseVideoEncoder * enc, GstEvent * event) { gboolean handled = FALSE; diff -Nru gst-plugin-ducati-1.6.7.2/src/gstducatividenc.h gst-plugin-ducati-1.6.7.20/src/gstducatividenc.h --- gst-plugin-ducati-1.6.7.2/src/gstducatividenc.h 2012-10-02 13:38:43.000000000 +0000 +++ gst-plugin-ducati-1.6.7.20/src/gstducatividenc.h 2012-12-06 15:48:06.000000000 +0000 @@ -79,6 +79,8 @@ gint bitrate; guint rate_preset; guint intra_interval; + + const char *error_strings[32]; }; struct _GstDucatiVidEncClass @@ -89,6 +91,7 @@ gboolean (*allocate_params) (GstDucatiVidEnc * self, gint params_sz, gint dynparams_sz, gint status_sz, gint inargs_sz, gint outargs_sz); gboolean (*configure) (GstDucatiVidEnc * self); + gboolean (*is_sync_point) (GstDucatiVidEnc * self, int type); }; GType gst_ducati_videnc_get_type (void); diff -Nru gst-plugin-ducati-1.6.7.2/src/gstducativp6dec.c gst-plugin-ducati-1.6.7.20/src/gstducativp6dec.c --- gst-plugin-ducati-1.6.7.2/src/gstducativp6dec.c 2012-10-02 13:38:43.000000000 +0000 +++ gst-plugin-ducati-1.6.7.20/src/gstducativp6dec.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,148 +0,0 @@ -/* - * GStreamer - * Copyright (c) 2010, Texas Instruments Incorporated - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation - * version 2.1 of the License. - * - * 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/** - * SECTION:element-ducativp6dec - * - * FIXME:Describe ducativp6dec here. - * - * - * Example launch line - * |[ - * gst-launch -v -m fakesrc ! ducativp6dec ! fakesink silent=TRUE - * ]| - * - */ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include "gstducativp6dec.h" - - -#define PADX 48 -#define PADY 48 - - -GST_BOILERPLATE (GstDucatiVP6Dec, gst_ducati_vp6dec, GstDucatiVidDec, - GST_TYPE_DUCATIVIDDEC); - -static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS ("video/x-vp6, " - "width = (int)[ 16, 2048 ], " - "height = (int)[ 16, 2048 ], " - "framerate = (fraction)[ 0, max ];") - ); - -/* GstDucatiVidDec vmethod implementations */ - -static void -gst_ducati_vp6dec_update_buffer_size (GstDucatiVidDec * self) -{ - gint w = self->width; - gint h = self->height; - - /* calculate output buffer parameters: */ - self->padded_width = ALIGN2 (w + (2 * PADX), 7); - self->padded_height = h + 2 * PADY; - self->min_buffers = 8; -} - -static gboolean -gst_ducati_vp6dec_allocate_params (GstDucatiVidDec * self, gint params_sz, - gint dynparams_sz, gint status_sz, gint inargs_sz, gint outargs_sz) -{ - gboolean ret = parent_class->allocate_params (self, - sizeof (Ivp6VDEC_Params), sizeof (Ivp6VDEC_DynamicParams), - sizeof (Ivp6VDEC_Status), sizeof (Ivp6VDEC_InArgs), - sizeof (Ivp6VDEC_OutArgs)); - - if (ret) { - Ivp6VDEC_Params *params = (Ivp6VDEC_Params *) self->params; - self->params->displayDelay = IVIDDEC3_DECODE_ORDER; - self->dynParams->newFrameFlag = FALSE; - self->dynParams->lateAcquireArg = -1; - self->params->numInputDataUnits = 1; - self->params->numOutputDataUnits = 1; - params->ivfFormat = FALSE; - params->payloadHeaderPresent = TRUE; - } - - return ret; -} - -/* this should be unneeded in future codec versions: */ -static GstBuffer * -gst_ducati_vp6dec_push_input (GstDucatiVidDec * vdec, GstBuffer * buf) -{ - guint32 sz; - - if (G_UNLIKELY (vdec->first_in_buffer) && vdec->codec_data) { - // XXX none of the vp6 clips I've seen have codec_data.. - } - - /* current codec version requires size prepended on input buffer: */ - sz = GST_BUFFER_SIZE (buf); - push_input (vdec, (guint8 *)&sz, 4); - - push_input (vdec, GST_BUFFER_DATA (buf), sz); - gst_buffer_unref (buf); - - return NULL; -} - - -/* GObject vmethod implementations */ - -static void -gst_ducati_vp6dec_base_init (gpointer gclass) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (gclass); - - gst_element_class_set_details_simple (element_class, - "DucatiVP6Dec", - "Codec/Decoder/Video", - "Decodes video in On2 VP6 format with ducati", - "Rob Clark "); - - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&sink_factory)); -} - -static void -gst_ducati_vp6dec_class_init (GstDucatiVP6DecClass * klass) -{ - GstDucatiVidDecClass *bclass = GST_DUCATIVIDDEC_CLASS (klass); - bclass->codec_name = "ivahd_vp6dec"; - bclass->update_buffer_size = - GST_DEBUG_FUNCPTR (gst_ducati_vp6dec_update_buffer_size); - bclass->allocate_params = - GST_DEBUG_FUNCPTR (gst_ducati_vp6dec_allocate_params); - bclass->push_input = - GST_DEBUG_FUNCPTR (gst_ducati_vp6dec_push_input); -} - -static void -gst_ducati_vp6dec_init (GstDucatiVP6Dec * self, - GstDucatiVP6DecClass * gclass) -{ -} diff -Nru gst-plugin-ducati-1.6.7.2/src/gstducativp6dec.h gst-plugin-ducati-1.6.7.20/src/gstducativp6dec.h --- gst-plugin-ducati-1.6.7.2/src/gstducativp6dec.h 2012-10-02 13:38:43.000000000 +0000 +++ gst-plugin-ducati-1.6.7.20/src/gstducativp6dec.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,53 +0,0 @@ -/* - * GStreamer - * Copyright (c) 2010, Texas Instruments Incorporated - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation - * version 2.1 of the License. - * - * 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef __GST_DUCATIVP6DEC_H__ -#define __GST_DUCATIVP6DEC_H__ - -#include "gstducatividdec.h" - -#include - - -G_BEGIN_DECLS - -#define GST_TYPE_DUCATIVP6DEC (gst_ducati_vp6dec_get_type()) -#define GST_DUCATIVP6DEC(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_DUCATIVP6DEC, GstDucatiVP6Dec)) -#define GST_DUCATIVP6DEC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_DUCATIVP6DEC, GstDucatiVP6DecClass)) -#define GST_IS_DUCATIVP6DEC(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_DUCATIVP6DEC)) -#define GST_IS_DUCATIVP6DEC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_DUCATIVP6DEC)) - -typedef struct _GstDucatiVP6Dec GstDucatiVP6Dec; -typedef struct _GstDucatiVP6DecClass GstDucatiVP6DecClass; - -struct _GstDucatiVP6Dec -{ - GstDucatiVidDec parent; -}; - -struct _GstDucatiVP6DecClass -{ - GstDucatiVidDecClass parent_class; -}; - -GType gst_ducati_vp6dec_get_type (void); - -G_END_DECLS - -#endif /* __GST_DUCATIVP6DEC_H__ */ diff -Nru gst-plugin-ducati-1.6.7.2/src/gstducativp7dec.c gst-plugin-ducati-1.6.7.20/src/gstducativp7dec.c --- gst-plugin-ducati-1.6.7.2/src/gstducativp7dec.c 2012-10-02 13:38:43.000000000 +0000 +++ gst-plugin-ducati-1.6.7.20/src/gstducativp7dec.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,148 +0,0 @@ -/* - * GStreamer - * Copyright (c) 2010, Texas Instruments Incorporated - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation - * version 2.1 of the License. - * - * 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/** - * SECTION:element-ducativp7dec - * - * FIXME:Describe ducativp7dec here. - * - * - * Example launch line - * |[ - * gst-launch -v -m fakesrc ! ducativp7dec ! fakesink silent=TRUE - * ]| - * - */ - -#ifdef HAVE_CONFIG_H -# include -#endif - -#include "gstducativp7dec.h" - - -#define PADX 48 -#define PADY 48 - - -GST_BOILERPLATE (GstDucatiVP7Dec, gst_ducati_vp7dec, GstDucatiVidDec, - GST_TYPE_DUCATIVIDDEC); - -static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS ("video/x-vp7, " - "width = (int)[ 16, 2048 ], " - "height = (int)[ 16, 2048 ], " - "framerate = (fraction)[ 0, max ];") - ); - -/* GstDucatiVidDec vmethod implementations */ - -static void -gst_ducati_vp7dec_update_buffer_size (GstDucatiVidDec * self) -{ - gint w = self->width; - gint h = self->height; - - /* calculate output buffer parameters: */ - self->padded_width = ALIGN2 (w + (2 * PADX), 7); - self->padded_height = h + 2 * PADY; - self->min_buffers = 8; -} - -static gboolean -gst_ducati_vp7dec_allocate_params (GstDucatiVidDec * self, gint params_sz, - gint dynparams_sz, gint status_sz, gint inargs_sz, gint outargs_sz) -{ - gboolean ret = parent_class->allocate_params (self, - sizeof (Ivp7VDEC_Params), sizeof (Ivp7VDEC_DynamicParams), - sizeof (Ivp7VDEC_Status), sizeof (Ivp7VDEC_InArgs), - sizeof (Ivp7VDEC_OutArgs)); - - if (ret) { - Ivp7VDEC_Params *params = (Ivp7VDEC_Params *) self->params; - self->params->displayDelay = IVIDDEC3_DECODE_ORDER; - self->dynParams->newFrameFlag = FALSE; - self->dynParams->lateAcquireArg = -1; - self->params->numInputDataUnits = 1; - self->params->numOutputDataUnits = 1; - params->ivfFormat = FALSE; - params->payloadHeaderPresent = TRUE; - } - - return ret; -} - -/* this should be unneeded in future codec versions: */ -static GstBuffer * -gst_ducati_vp7dec_push_input (GstDucatiVidDec * vdec, GstBuffer * buf) -{ - guint32 sz; - - if (G_UNLIKELY (vdec->first_in_buffer) && vdec->codec_data) { - // XXX none of the vp7 clips I've seen have codec_data.. - } - - /* current codec version requires size prepended on input buffer: */ - sz = GST_BUFFER_SIZE (buf); - push_input (vdec, (guint8 *)&sz, 4); - - push_input (vdec, GST_BUFFER_DATA (buf), sz); - gst_buffer_unref (buf); - - return NULL; -} - - -/* GObject vmethod implementations */ - -static void -gst_ducati_vp7dec_base_init (gpointer gclass) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (gclass); - - gst_element_class_set_details_simple (element_class, - "DucatiVP7Dec", - "Codec/Decoder/Video", - "Decodes video in On2 VP7 format with ducati", - "Rob Clark "); - - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&sink_factory)); -} - -static void -gst_ducati_vp7dec_class_init (GstDucatiVP7DecClass * klass) -{ - GstDucatiVidDecClass *bclass = GST_DUCATIVIDDEC_CLASS (klass); - bclass->codec_name = "ivahd_vp7dec"; - bclass->update_buffer_size = - GST_DEBUG_FUNCPTR (gst_ducati_vp7dec_update_buffer_size); - bclass->allocate_params = - GST_DEBUG_FUNCPTR (gst_ducati_vp7dec_allocate_params); - bclass->push_input = - GST_DEBUG_FUNCPTR (gst_ducati_vp7dec_push_input); -} - -static void -gst_ducati_vp7dec_init (GstDucatiVP7Dec * self, - GstDucatiVP7DecClass * gclass) -{ -} diff -Nru gst-plugin-ducati-1.6.7.2/src/gstducativp7dec.h gst-plugin-ducati-1.6.7.20/src/gstducativp7dec.h --- gst-plugin-ducati-1.6.7.2/src/gstducativp7dec.h 2012-10-02 13:38:43.000000000 +0000 +++ gst-plugin-ducati-1.6.7.20/src/gstducativp7dec.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,53 +0,0 @@ -/* - * GStreamer - * Copyright (c) 2010, Texas Instruments Incorporated - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation - * version 2.1 of the License. - * - * 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 - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -#ifndef __GST_DUCATIVP7DEC_H__ -#define __GST_DUCATIVP7DEC_H__ - -#include "gstducatividdec.h" - -#include - - -G_BEGIN_DECLS - -#define GST_TYPE_DUCATIVP7DEC (gst_ducati_vp7dec_get_type()) -#define GST_DUCATIVP7DEC(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_DUCATIVP7DEC, GstDucatiVP7Dec)) -#define GST_DUCATIVP7DEC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_DUCATIVP7DEC, GstDucatiVP7DecClass)) -#define GST_IS_DUCATIVP7DEC(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_DUCATIVP7DEC)) -#define GST_IS_DUCATIVP7DEC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_DUCATIVP7DEC)) - -typedef struct _GstDucatiVP7Dec GstDucatiVP7Dec; -typedef struct _GstDucatiVP7DecClass GstDucatiVP7DecClass; - -struct _GstDucatiVP7Dec -{ - GstDucatiVidDec parent; -}; - -struct _GstDucatiVP7DecClass -{ - GstDucatiVidDecClass parent_class; -}; - -GType gst_ducati_vp7dec_get_type (void); - -G_END_DECLS - -#endif /* __GST_DUCATIVP7DEC_H__ */ diff -Nru gst-plugin-ducati-1.6.7.2/tools/parse-gst-traces.py gst-plugin-ducati-1.6.7.20/tools/parse-gst-traces.py --- gst-plugin-ducati-1.6.7.2/tools/parse-gst-traces.py 1970-01-01 00:00:00.000000000 +0000 +++ gst-plugin-ducati-1.6.7.20/tools/parse-gst-traces.py 2012-12-06 15:48:06.000000000 +0000 @@ -0,0 +1,109 @@ +#! /usr/bin/python +# GStreamer scheduling parser +# Analyze GST traces and shows the time spent for each buffer at each element level. +# +# Usage: GST_DEBUG=*:2,GST_SCHEDULING:5,GST_PERFORMANCE:5 gst-launch --gst-debug-no-color -e [PIPELINE] >foo 2>&1 +# ./parse-gst-traces.py foo +# Example of pipeline: videotestsrc num-buffers=200 ! "video/x-raw-yuv, format=(fourcc)NV12, width=1280, height=720, framerate=30/1" ! ducatih264enc profile=66 ! ducatih264dec! dri2videosink sync=false + +import sys +import time +import fileinput +import re +import operator +from datetime import datetime + +def string_to_time (d): + return datetime.strptime(d[0:14], "%H:%M:%S.%f") + +def main(): + tr = dict() + cam = dict() + dec = dict() + ecs = 0 + + ### Parse stdin or any file on the command line + for line in fileinput.input(): + + # Filter out GST traces from other output + m = re.match(r"([\w:.]+)[\s]+([\w]+)[\s]+([\w]+)[\s]+([\w]+)[\s]+(.*)",line) + if m == None: + print line + continue + (tsr,pid,adr,sev,msg) = m.groups() + + # Parse GST_SCHEDULING traces + m = re.match(r"GST_SCHEDULING[\s]+gstpad.c:[\w]+:([\w_]+):<([A-Za-z0-9_]+)([0-9]+):([\w_]+)> calling chainfunction &[\w]+ with buffer ([\w]+), data ([\w]+), malloc ([\w()]+), ts ([\w:.]+), dur ([\w:.]+)", msg) + if m != None: + (func, elem, number, pad, gstBuffer, data, malloc, tsb, dur) = m.groups() + if func != "gst_pad_push": + continue + if elem == "cam" and pad == "src" and gstBuffer in cam: + tr[tsb] = [(cam[gstBuffer], "FillBufferDone")] + elif elem == "ducatih264dec" and pad == "src": + dec[gstBuffer] = tsb + elif elem == "udpsrc" or elem == "recv_rtp_sink_" or elem == "rtpsession" or elem =="rtpssrcdemux": + continue + if tsb not in tr: + tr[tsb] = [] + tr[tsb].append((tsr, "%s:<%s%s:%s>" % (func, elem, number, pad) )) + continue + + # Parse omx_camera traces + m = re.match(r"GST_PERFORMANCE gstomx_core.c:[\w]+:FillBufferDone: FillBufferDone: GstBuffer=([\w]+)", msg) + if m != None: + gstBuffer = m.group(1) + cam[gstBuffer] = tsr + continue + + # Parse encoder traces + m = re.match(r"GST_PERFORMANCE gstducatividenc.c:[\w]+:gst_ducati_videnc_handle_frame: Encoded frame in ([\w]+) bytes", msg) + if m != None: + ecs += int(m.group(1)) + continue + + # Parse dri2videosink traces + m = re.match(r"GST_PERFORMANCE gstdri2util.c:[\w]+:gst_dri2window_buffer_show: (Before DRI2SwapBuffersVid|After DRI2WaitSBC), buf=([\w]+)", msg) + if m != None: + (ba, dri2_buf) = m.groups() + if dri2_buf in dec: + tr[dec[dri2_buf]].append((tsr, ba)) + continue + + ### End of stdin parsing + + # Display the results, frame per frame + avg = cnt = 0 + for tsb, tfs in tr.iteritems(): + cnt +=1 + first = prev = string_to_time(tfs[0][0]) + print "\n*** Frame no: %d, timestamp: %s" % (cnt, tsb) + for el in tfs: + cur = string_to_time(el[0]) + if cur != prev: + later = "(%6d us later)" % (cur - prev).microseconds + else: + later = "( first event)" + print "At %s %s Func: %s" % (el[0][5:14], later, el[1]) + prev = cur + total = cur - first + avg += total.microseconds + print "*** Total: %6d us" % (total.microseconds) + + # Display the totals + if (cnt != 0): + if (ecs != 0): + ecs = "%s KB" % (ecs / 1024) + else: + ecs = "N/A (lack of encoder traces)" + print "\n=-= Encoded stream size: %s" % (ecs) + print "\n=-= Average: %6d us on %d frames" % (avg / cnt, cnt) + else: + print "\n=-= No frame, the pipeline have failed" + + return 0 +if __name__ == '__main__': + main() + + + diff -Nru gst-plugin-ducati-1.6.7.2/tools/playback.py gst-plugin-ducati-1.6.7.20/tools/playback.py --- gst-plugin-ducati-1.6.7.2/tools/playback.py 1970-01-01 00:00:00.000000000 +0000 +++ gst-plugin-ducati-1.6.7.20/tools/playback.py 2012-12-06 15:48:06.000000000 +0000 @@ -0,0 +1,66 @@ +#! /usr/bin/python +import gobject +gobject.threads_init() +import gst +import sys +from argparse import ArgumentParser +import time + +class Playlist(object): + def run(self): + parser = ArgumentParser() + parser.add_argument('--skip-after', type=int, default=0) + parser.add_argument('-d', dest='vs',action='store_const', const='dri2videosink', default='dri2videosink') + parser.add_argument('-k', dest='vs', action='store_const', const='kmssink', default='') + parser.add_argument('-p', dest='vs',action='store_const', const='pvrvideosink', default='') + parser.add_argument('uris', nargs='+') + args = parser.parse_args() + + self.uris = args.uris + self.skip_after = args.skip_after + self.playbin = playbin = gst.element_factory_make("playbin2") + self.sink = gst.element_factory_make(args.vs) + self.playbin.set_property('video-sink', self.sink) + bus = playbin.get_bus() + bus.add_signal_watch() + bus.connect('message::eos', self.eos) + bus.connect('message::error', self.error) + + self.current_index = -1 + self.next() + + self.loop = gobject.MainLoop() + self.loop.run() + playbin.set_state(gst.STATE_NULL) + + def eos(self, bus, message): + print 'EOS' + self.next() + + def error(self, bus, message): + gerror, debug = message.parse_error() + print 'ERROR', gerror.message, debug + self.next() + + def next(self): + if self.current_index >= 0: + print '*** STOPPING ', self.uris[self.current_index] + playbin = self.playbin + playbin.set_state(gst.STATE_NULL) + self.current_index += 1 + if self.current_index == len(self.uris): + self.loop.quit() + return + time.sleep(2) + + playbin.props.uri = self.uris[self.current_index] + print '*** STARTING ', self.uris[self.current_index] + playbin.set_state(gst.STATE_PLAYING) + if self.skip_after: + gobject.timeout_add_seconds(self.skip_after, self.next) + + + +if __name__ == '__main__': + Playlist().run() +