From a8d891dc5eb7d7404f2580c2450b2a7cf577ddc6 Mon Sep 17 00:00:00 2001 From: Mart Raudsepp Date: Mon, 29 Nov 2010 20:06:07 +0000 Subject: [PATCH 001/448] dvbsuboverlay: initial version, work in progress --- configure.ac | 2 + gst/dvbsuboverlay/Makefile.am | 10 + gst/dvbsuboverlay/TODO | 6 + gst/dvbsuboverlay/dvb-sub.c | 1640 +++++++++++++++++++++++++ gst/dvbsuboverlay/dvb-sub.h | 136 ++ gst/dvbsuboverlay/ffmpeg-colorspace.h | 116 ++ gst/dvbsuboverlay/gstdvbsuboverlay.c | 1275 +++++++++++++++++++ gst/dvbsuboverlay/gstdvbsuboverlay.h | 90 ++ 8 files changed, 3275 insertions(+) create mode 100644 gst/dvbsuboverlay/Makefile.am create mode 100644 gst/dvbsuboverlay/TODO create mode 100644 gst/dvbsuboverlay/dvb-sub.c create mode 100644 gst/dvbsuboverlay/dvb-sub.h create mode 100644 gst/dvbsuboverlay/ffmpeg-colorspace.h create mode 100644 gst/dvbsuboverlay/gstdvbsuboverlay.c create mode 100644 gst/dvbsuboverlay/gstdvbsuboverlay.h diff --git a/configure.ac b/configure.ac index e728fcdcc5..566de0d7e4 100644 --- a/configure.ac +++ b/configure.ac @@ -300,6 +300,7 @@ AG_GST_CHECK_PLUGIN(dataurisrc) AG_GST_CHECK_PLUGIN(dccp) AG_GST_CHECK_PLUGIN(debugutils) AG_GST_CHECK_PLUGIN(dtmf) +AG_GST_CHECK_PLUGIN(dvbsuboverlay) AG_GST_CHECK_PLUGIN(dvdspu) AG_GST_CHECK_PLUGIN(festival) AG_GST_CHECK_PLUGIN(freeze) @@ -1725,6 +1726,7 @@ gst/dataurisrc/Makefile gst/dccp/Makefile gst/debugutils/Makefile gst/dtmf/Makefile +gst/dvbsuboverlay/Makefile gst/dvdspu/Makefile gst/festival/Makefile gst/freeze/Makefile diff --git a/gst/dvbsuboverlay/Makefile.am b/gst/dvbsuboverlay/Makefile.am new file mode 100644 index 0000000000..9cc2f38d4e --- /dev/null +++ b/gst/dvbsuboverlay/Makefile.am @@ -0,0 +1,10 @@ +plugin_LTLIBRARIES = libgstdvbsuboverlay.la + +libgstdvbsuboverlay_la_SOURCES = dvb-sub.c gstdvbsuboverlay.c + +libgstdvbsuboverlay_la_CFLAGS = $(GST_PLUGINS_BAD_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) +libgstdvbsuboverlay_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) $(GST_LIBS) -lgstvideo-@GST_MAJORMINOR@ +libgstdvbsuboverlay_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) +libgstdvbsuboverlay_la_LIBTOOLFLAGS = --tag=disable-static + +noinst_HEADERS = gstdvbsuboverlay.h dvb-sub.h ffmpeg-colorspace.h diff --git a/gst/dvbsuboverlay/TODO b/gst/dvbsuboverlay/TODO new file mode 100644 index 0000000000..7042734c6c --- /dev/null +++ b/gst/dvbsuboverlay/TODO @@ -0,0 +1,6 @@ +Check about GST_PAD_PARENT vs gst_pad_get_parent - do we need a reference - is there any danger of losing the parent in the middle or not: + one uses GST_PAD_PARENT in situations where you can be sure the parent exists and will exist for the entire time you need it + and gst_pad_get_parent when you need a ref because the pad might get unparented while you're using it + +Ask about individual segment handling on separate sink pads. Is it possible that the separate NEWSEGMENT events on the text and video pad have different start and/or stop values, as to require some code complexity present? + diff --git a/gst/dvbsuboverlay/dvb-sub.c b/gst/dvbsuboverlay/dvb-sub.c new file mode 100644 index 0000000000..b0b26cc465 --- /dev/null +++ b/gst/dvbsuboverlay/dvb-sub.c @@ -0,0 +1,1640 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */ +/* + * libdvbsub - DVB subtitle decoding + * Copyright (C) Mart Raudsepp 2009 + * + * Heavily uses code algorithms ported from ffmpeg's libavcodec/dvbsubdec.c, + * especially the segment parsers. The original license applies to this + * ported code and the whole code in this file as well. + * + * Original copyright information follows: + */ +/* + * DVB subtitle decoding for ffmpeg + * Copyright (c) 2005 Ian Caulfield + * + * This file is part of FFmpeg. + * + * FFmpeg 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; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#include "dvb-sub.h" +#include /* memset */ +#include /* GST_READ_UINT16_BE */ +#include /* GstBitReader */ +#include "ffmpeg-colorspace.h" /* YUV_TO_RGB1_CCIR */ /* FIXME: Just give YUV data to gstreamer then? */ + +/* FIXME: Convert to GST_LOG and clean up */ +void (*g_log_callback) (GLogLevelFlags log_level, const gchar * format, + va_list args, gpointer user_data) = NULL; +gpointer g_log_callback_user_data = NULL; + +#define DEBUG +#ifdef DEBUG +#define dvb_log(log_type, log_level, format...) real_dvb_log(log_type, log_level, ## format) +typedef enum +{ + /* dvb_log types // DVB_LOG environment variable string */ + DVB_LOG_GENERAL, /* GENERAL */ + DVB_LOG_PAGE, /* PAGE */ + DVB_LOG_REGION, /* REGION */ + DVB_LOG_CLUT, /* CLUT */ + DVB_LOG_OBJECT, /* OBJECT */ + DVB_LOG_PIXEL, /* PIXEL */ + DVB_LOG_RUNLEN, /* RUNLEN */ + DVB_LOG_DISPLAY, /* DISPLAY */ + DVB_LOG_STREAM, /* STREAM - issues in the encoded stream (TV service provider encoder problem) */ + DVB_LOG_PACKET, /* PACKET - messages during raw demuxer data packet handling */ + DVB_LOG_LAST /* sentinel use only */ +} DvbLogTypes; + +static void +real_dvb_log (const gint log_type, GLogLevelFlags log_level, + const gchar * format, ...) +{ + if (g_log_callback) { + va_list va; + va_start (va, format); + switch (log_type) { + default: + g_log_callback (log_level, format, va, g_log_callback_user_data); + break; + case DVB_LOG_PIXEL: + case DVB_LOG_RUNLEN: + break; + } + va_end (va); + } +} +#else +#define dvb_log(log_type, log_level, format...) +#endif + +/* FIXME: Are we waiting for an acquisition point before trying to do things? */ +/* FIXME: In the end convert some of the guint8/16 (especially stack variables) back to gint for access efficiency */ + +/** + * SECTION:dvb-sub + * @short_description: a DVB subtitle parsing class + * @stability: Unstable + * + * The #DvbSub represents an object used for parsing a DVB subpicture, + * and signalling the API user for new bitmaps to show on screen. + */ + +#define MAX_NEG_CROP 1024 +static guint8 ff_cropTbl[256 + 2 * MAX_NEG_CROP] = { 0, }; + +#define cm (ff_cropTbl + MAX_NEG_CROP) + +/* FIXME: This is really ARGB... We might need this configurable for performant + * FIXME: use in GStreamer as well if that likes RGBA more (Qt prefers ARGB) */ +#define RGBA(r,g,b,a) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b)) + +typedef struct DVBSubCLUT +{ + int id; /* default_clut uses -1 for this, so guint8 isn't fine without adaptations first */ + + guint32 clut4[4]; + guint32 clut16[16]; + guint32 clut256[256]; + + struct DVBSubCLUT *next; +} DVBSubCLUT; + +static DVBSubCLUT default_clut; + +typedef struct DVBSubObjectDisplay +{ + /* FIXME: Use more correct sizes */ + int object_id; + int region_id; + + int x_pos; + int y_pos; + + int fgcolor; + int bgcolor; + + /* FIXME: Should we use GSList? The relating interaction and pointer assigment is quite complex and perhaps unsuited for a plain GSList anyway */ + struct DVBSubObjectDisplay *region_list_next; + struct DVBSubObjectDisplay *object_list_next; +} DVBSubObjectDisplay; + +typedef struct DVBSubObject +{ + /* FIXME: Use more correct sizes */ + int id; /* FIXME: Use guint8 after checking it's fine in all code using it */ + + int type; + + /* FIXME: Should we use GSList? */ + DVBSubObjectDisplay *display_list; + struct DVBSubObject *next; +} DVBSubObject; + +typedef struct DVBSubRegionDisplay +{ /* FIXME: Figure out if this structure is only used temporarily in page_segment parser, or also more */ + int region_id; + + int x_pos; + int y_pos; + + struct DVBSubRegionDisplay *next; +} DVBSubRegionDisplay; + +typedef struct DVBSubRegion +{ + guint8 id; + guint16 width; + guint16 height; + guint8 depth; /* If we want to make this a guint8, then need to ensure it isn't wrap around with reserved values in region handling code */ + + guint8 clut; + guint8 bgcolor; + + /* FIXME: Validate these fields existence and exact types */ + guint8 *pbuf; + int buf_size; + + DVBSubObjectDisplay *display_list; + + struct DVBSubRegion *next; +} DVBSubRegion; + +typedef struct _DvbSubPrivate DvbSubPrivate; +struct _DvbSubPrivate +{ + int fd; + DvbSubCallbacks callbacks; + gpointer user_data; + + guint8 page_time_out; + DVBSubRegion *region_list; + DVBSubCLUT *clut_list; + DVBSubObject *object_list; + /* FIXME... */ + int display_list_size; + DVBSubRegionDisplay *display_list; + GString *pes_buffer; +}; + +#define DVB_SUB_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), DVB_TYPE_SUB, DvbSubPrivate)) + +G_DEFINE_TYPE (DvbSub, dvb_sub, G_TYPE_OBJECT); + +typedef enum +{ + TOP_FIELD = 0, + BOTTOM_FIELD = 1 +} DvbSubPixelDataSubBlockFieldType; + +/* FIXME: It might make sense to pass DvbSubPrivate for all the get_* functions, instead of public DvbSub */ +static DVBSubObject * +get_object (DvbSub * dvb_sub, guint16 object_id) +{ + const DvbSubPrivate *priv = (DvbSubPrivate *) dvb_sub->private_data; + DVBSubObject *ptr = priv->object_list; + + while (ptr && ptr->id != object_id) { + ptr = ptr->next; + } + + return ptr; +} + +static DVBSubCLUT * +get_clut (DvbSub * dvb_sub, gint clut_id) +{ + const DvbSubPrivate *priv = (DvbSubPrivate *) dvb_sub->private_data; + DVBSubCLUT *ptr = priv->clut_list; + + while (ptr && ptr->id != clut_id) { + ptr = ptr->next; + } + + return ptr; +} + +// FIXME: Just pass private_data pointer directly here and in other get_* helper functions? +static DVBSubRegion * +get_region (DvbSub * dvb_sub, guint8 region_id) +{ + const DvbSubPrivate *priv = (DvbSubPrivate *) dvb_sub->private_data; + DVBSubRegion *ptr = priv->region_list; + + while (ptr && ptr->id != region_id) { + ptr = ptr->next; + } + + return ptr; +} + +static void +delete_region_display_list (DvbSub * dvb_sub, DVBSubRegion * region) +{ + const DvbSubPrivate *priv = (DvbSubPrivate *) dvb_sub->private_data; + DVBSubObject *object, *obj2; + DVBSubObject **obj2_ptr; + DVBSubObjectDisplay *display, *obj_disp, **obj_disp_ptr; + + while (region->display_list) { + display = region->display_list; + + object = get_object (dvb_sub, display->object_id); + + if (object) { + obj_disp_ptr = &object->display_list; + obj_disp = *obj_disp_ptr; + + while (obj_disp && obj_disp != display) { + obj_disp_ptr = &obj_disp->object_list_next; + obj_disp = *obj_disp_ptr; + } + + if (obj_disp) { + *obj_disp_ptr = obj_disp->object_list_next; + + if (!object->display_list) { + obj2_ptr = (DVBSubObject **) & priv->object_list; /* FIXME: Evil casting */ + obj2 = *obj2_ptr; + + while (obj2 != object) { + g_assert (obj2); + obj2_ptr = &obj2->next; + obj2 = *obj2_ptr; + } + + *obj2_ptr = obj2->next; + + g_slice_free (DVBSubObject, obj2); + } + } + } + + region->display_list = display->region_list_next; + + g_slice_free (DVBSubObjectDisplay, display); + } +} + +static void +delete_state (DvbSub * dvb_sub) +{ + DvbSubPrivate *priv = (DvbSubPrivate *) dvb_sub->private_data; + DVBSubRegion *region; + + while (priv->region_list) { + region = priv->region_list; + + priv->region_list = region->next; + + delete_region_display_list (dvb_sub, region); + if (region->pbuf) + g_free (region->pbuf); + + g_slice_free (DVBSubRegion, region); + } + + g_slice_free_chain (DVBSubCLUT, priv->clut_list, next); + priv->clut_list = NULL; + + /* Should already be null */ + if (priv->object_list) + g_warning ("Memory deallocation error!"); +} + +static void +dvb_sub_init (DvbSub * self) +{ + DvbSubPrivate *priv; + + self->private_data = priv = DVB_SUB_GET_PRIVATE (self); + + /* TODO: Add initialization code here */ + /* FIXME: Do we have a reason to initiate the members to zero, or are we guaranteed that anyway? */ + priv->region_list = NULL; + priv->object_list = NULL; + priv->page_time_out = 0; /* FIXME: Maybe 255 instead? */ + priv->pes_buffer = g_string_new (NULL); +} + +static void +dvb_sub_finalize (GObject * object) +{ + DvbSub *self = DVB_SUB (object); + DvbSubPrivate *priv = (DvbSubPrivate *) self->private_data; + /* TODO: Add deinitalization code here */ + /* FIXME: Clear up region_list contents */ + delete_state (self); /* close_pid should have called this, but lets be sure */ + g_string_free (priv->pes_buffer, TRUE); + + G_OBJECT_CLASS (dvb_sub_parent_class)->finalize (object); +} + +/* init static data necessary for ffmpeg-colorspace conversion */ +static void +dsputil_static_init (void) +{ + int i; + + for (i = 0; i < 256; i++) + ff_cropTbl[i + MAX_NEG_CROP] = i; + for (i = 0; i < MAX_NEG_CROP; i++) { + ff_cropTbl[i] = 0; + ff_cropTbl[i + MAX_NEG_CROP + 256] = 255; + } +} + +static void +dvb_sub_class_init (DvbSubClass * klass) +{ + int i, r, g, b, a = 0; + GObjectClass *object_class = (GObjectClass *) klass; + + object_class->finalize = dvb_sub_finalize; + + g_type_class_add_private (klass, sizeof (DvbSubPrivate)); + + dsputil_static_init (); /* Initializes ff_cropTbl table, used in YUV_TO_RGB conversion */ + + /* Initialize the static default_clut structure, from which other clut + * structures are initialized from (to start off with default CLUTs + * as defined in the specification). */ + default_clut.id = -1; + + default_clut.clut4[0] = RGBA (0, 0, 0, 0); + default_clut.clut4[1] = RGBA (255, 255, 255, 255); + default_clut.clut4[2] = RGBA (0, 0, 0, 255); + default_clut.clut4[3] = RGBA (127, 127, 127, 255); + + default_clut.clut16[0] = RGBA (0, 0, 0, 0); + for (i = 1; i < 16; i++) { + if (i < 8) { + r = (i & 1) ? 255 : 0; + g = (i & 2) ? 255 : 0; + b = (i & 4) ? 255 : 0; + } else { + r = (i & 1) ? 127 : 0; + g = (i & 2) ? 127 : 0; + b = (i & 4) ? 127 : 0; + } + default_clut.clut16[i] = RGBA (r, g, b, 255); + } + + default_clut.clut256[0] = RGBA (0, 0, 0, 0); + for (i = 1; i < 256; i++) { + if (i < 8) { + r = (i & 1) ? 255 : 0; + g = (i & 2) ? 255 : 0; + b = (i & 4) ? 255 : 0; + a = 63; + } else { + switch (i & 0x88) { + case 0x00: + r = ((i & 1) ? 85 : 0) + ((i & 0x10) ? 170 : 0); + g = ((i & 2) ? 85 : 0) + ((i & 0x20) ? 170 : 0); + b = ((i & 4) ? 85 : 0) + ((i & 0x40) ? 170 : 0); + a = 255; + break; + case 0x08: + r = ((i & 1) ? 85 : 0) + ((i & 0x10) ? 170 : 0); + g = ((i & 2) ? 85 : 0) + ((i & 0x20) ? 170 : 0); + b = ((i & 4) ? 85 : 0) + ((i & 0x40) ? 170 : 0); + a = 127; + break; + case 0x80: + r = 127 + ((i & 1) ? 43 : 0) + ((i & 0x10) ? 85 : 0); + g = 127 + ((i & 2) ? 43 : 0) + ((i & 0x20) ? 85 : 0); + b = 127 + ((i & 4) ? 43 : 0) + ((i & 0x40) ? 85 : 0); + a = 255; + break; + case 0x88: + r = ((i & 1) ? 43 : 0) + ((i & 0x10) ? 85 : 0); + g = ((i & 2) ? 43 : 0) + ((i & 0x20) ? 85 : 0); + b = ((i & 4) ? 43 : 0) + ((i & 0x40) ? 85 : 0); + a = 255; + break; + } + } + default_clut.clut256[i] = RGBA (r, g, b, a); + } +} + +static void +_dvb_sub_parse_page_segment (DvbSub * dvb_sub, guint16 page_id, guint8 * buf, + gint buf_size) +{ /* FIXME: Use guint for buf_size here and in many other places? */ + DvbSubPrivate *priv = (DvbSubPrivate *) dvb_sub->private_data; + DVBSubRegionDisplay *display; + DVBSubRegionDisplay *tmp_display_list, **tmp_ptr; + + const guint8 *buf_end = buf + buf_size; + guint8 region_id; + guint8 page_state; + +#ifdef DEBUG + static int counter = 0; + static const gchar *page_state_str[] = { + "Normal case", + "ACQUISITION POINT", + "Mode Change", + "RESERVED" + }; +#endif + + if (buf_size < 1) + return; + + priv->page_time_out = *buf++; + page_state = ((*buf++) >> 2) & 3; + +#ifdef DEBUG + ++counter; + dvb_log (DVB_LOG_PAGE, G_LOG_LEVEL_DEBUG, + "%d: page_id = %u, length = %d, page_time_out = %u seconds, page_state = %s", + counter, page_id, buf_size, priv->page_time_out, + page_state_str[page_state]); +#endif + + if (page_state == 2) { /* Mode change */ + delete_state (dvb_sub); + } + + tmp_display_list = priv->display_list; + priv->display_list = NULL; + priv->display_list_size = 0; + + while (buf + 5 < buf_end) { + region_id = *buf++; + buf += 1; + + display = tmp_display_list; + tmp_ptr = &tmp_display_list; + + while (display && display->region_id != region_id) { + tmp_ptr = &display->next; + display = display->next; + } + + if (!display) + display = g_slice_new0 (DVBSubRegionDisplay); + + display->region_id = region_id; + + display->x_pos = GST_READ_UINT16_BE (buf); + buf += 2; + display->y_pos = GST_READ_UINT16_BE (buf); + buf += 2; + + *tmp_ptr = display->next; + + display->next = priv->display_list; + priv->display_list = display; + priv->display_list_size++; + + dvb_log (DVB_LOG_PAGE, G_LOG_LEVEL_DEBUG, + "%d: REGION information: ID = %u, address = %ux%u", + counter, region_id, display->x_pos, display->y_pos); + } + + while (tmp_display_list) { + display = tmp_display_list; + + tmp_display_list = display->next; + + g_slice_free (DVBSubRegionDisplay, display); + } +} + +static void +_dvb_sub_parse_region_segment (DvbSub * dvb_sub, guint16 page_id, guint8 * buf, + gint buf_size) +{ + DvbSubPrivate *priv = (DvbSubPrivate *) dvb_sub->private_data; + + const guint8 *buf_end = buf + buf_size; + guint8 region_id; + guint16 object_id; + DVBSubRegion *region; + DVBSubObject *object; + DVBSubObjectDisplay *object_display; + gboolean fill; + + if (buf_size < 10) + return; + + region_id = *buf++; + + region = get_region (dvb_sub, region_id); + + if (!region) { /* Create a new region */ + region = g_slice_new0 (DVBSubRegion); + region->id = region_id; + region->next = priv->region_list; + priv->region_list = region; + } + + fill = ((*buf++) >> 3) & 1; + + region->width = GST_READ_UINT16_BE (buf); + buf += 2; + region->height = GST_READ_UINT16_BE (buf); + buf += 2; + + if (region->width * region->height != region->buf_size) { /* FIXME: Read closer from spec what happens when dimensions change */ + if (region->pbuf) + g_free (region->pbuf); + + region->buf_size = region->width * region->height; + + region->pbuf = g_malloc (region->buf_size); /* TODO: We can probably use GSlice here if careful about freeing while buf_size still records the correct size */ + + fill = 1; /* FIXME: Validate from spec that fill is forced on (in the following codes context) when dimensions change */ + } + + region->depth = 1 << (((*buf++) >> 2) & 7); + if (region->depth < 2 || region->depth > 8) { + g_warning ("region depth %d is invalid\n", region->depth); + region->depth = 4; /* FIXME: Check from spec this is the default? */ + } + + region->clut = *buf++; + + if (region->depth == 8) + region->bgcolor = *buf++; + else { + buf += 1; + + if (region->depth == 4) + region->bgcolor = (((*buf++) >> 4) & 15); + else + region->bgcolor = (((*buf++) >> 2) & 3); + } + + dvb_log (DVB_LOG_REGION, G_LOG_LEVEL_DEBUG, + "id = %u, (%ux%u)@%u-bit", + region_id, region->width, region->height, region->depth); + + if (fill) { + memset (region->pbuf, region->bgcolor, region->buf_size); + dvb_log (DVB_LOG_REGION, G_LOG_LEVEL_DEBUG, + "Filling region (%u) with bgcolor = %u", region->id, region->bgcolor); + } + + delete_region_display_list (dvb_sub, region); /* Delete the region display list for current region - FIXME: why? */ + + while (buf + 6 <= buf_end) { + object_id = GST_READ_UINT16_BE (buf); + buf += 2; + + object = get_object (dvb_sub, object_id); + + if (!object) { + object = g_slice_new0 (DVBSubObject); + + object->id = object_id; + + object->next = priv->object_list; + priv->object_list = object; + } + + object->type = (*buf) >> 6; + + object_display = g_slice_new0 (DVBSubObjectDisplay); + + object_display->object_id = object_id; + object_display->region_id = region_id; + + object_display->x_pos = GST_READ_UINT16_BE (buf) & 0xfff; + buf += 2; + object_display->y_pos = GST_READ_UINT16_BE (buf) & 0xfff; + buf += 2; + + if ((object->type == 1 || object->type == 2) && buf + 2 <= buf_end) { + object_display->fgcolor = *buf++; + object_display->bgcolor = *buf++; + } + + object_display->region_list_next = region->display_list; + region->display_list = object_display; + + object_display->object_list_next = object->display_list; + object->display_list = object_display; + + dvb_log (DVB_LOG_REGION, G_LOG_LEVEL_DEBUG, + "REGION DATA: object_id = %u, region_id = %u, pos = %ux%u, obj_type = %u", + object->id, region->id, object_display->x_pos, object_display->y_pos, + object->type); + if (object->type == 1 || object->type == 2) + dvb_log (DVB_LOG_REGION, G_LOG_LEVEL_DEBUG, + "REGION DATA: fgcolor = %u, bgcolor = %u\n", object_display->fgcolor, + object_display->bgcolor); + } +} + +static void +_dvb_sub_parse_clut_segment (DvbSub * dvb_sub, guint16 page_id, guint8 * buf, + gint buf_size) +{ + DvbSubPrivate *priv = (DvbSubPrivate *) dvb_sub->private_data; + + const guint8 *buf_end = buf + buf_size; + guint8 clut_id; + DVBSubCLUT *clut; + int entry_id, depth, full_range; + int y, cr, cb, alpha; + int r, g, b, r_add, g_add, b_add; + +#ifdef DEBUG_PACKET_CONTENTS + g_print ("DVB clut packet:\n"); + gst_util_dump_mem (buf, buf_size); +#endif + + clut_id = *buf++; + buf += 1; + + clut = get_clut (dvb_sub, clut_id); + + if (!clut) { + clut = g_slice_new (DVBSubCLUT); /* FIXME-MEMORY-LEAK: This seems to leak per valgrind */ + + memcpy (clut, &default_clut, sizeof (DVBSubCLUT)); + + clut->id = clut_id; + + clut->next = priv->clut_list; + priv->clut_list = clut; + } + + while (buf + 4 < buf_end) { + entry_id = *buf++; + + depth = (*buf) & 0xe0; + + if (depth == 0) { + g_warning ("Invalid clut depth 0x%x!", *buf); + return; + } + + full_range = (*buf++) & 1; + + if (full_range) { + y = *buf++; + cr = *buf++; + cb = *buf++; + alpha = *buf++; + } else { + y = buf[0] & 0xfc; + cr = (((buf[0] & 3) << 2) | ((buf[1] >> 6) & 3)) << 4; + cb = (buf[1] << 2) & 0xf0; + alpha = (buf[1] << 6) & 0xc0; + + buf += 2; + } + + if (y == 0) + alpha = 0xff; + + YUV_TO_RGB1_CCIR (cb, cr); + YUV_TO_RGB2_CCIR (r, g, b, y); + + dvb_log (DVB_LOG_CLUT, G_LOG_LEVEL_DEBUG, + "CLUT DEFINITION: clut %d := (%d,%d,%d,%d)", entry_id, r, g, b, alpha); + + if (depth & 0x80) + clut->clut4[entry_id] = RGBA (r, g, b, 255 - alpha); + if (depth & 0x40) + clut->clut16[entry_id] = RGBA (r, g, b, 255 - alpha); + if (depth & 0x20) + clut->clut256[entry_id] = RGBA (r, g, b, 255 - alpha); + } +} + +// FFMPEG-FIXME: The same code in ffmpeg is much more complex, it could use the same +// FFMPEG-FIXME: refactoring as done here +static int +_dvb_sub_read_2bit_string (guint8 * destbuf, gint dbuf_len, + const guint8 ** srcbuf, gint buf_size, guint8 non_mod, guint8 * map_table) +{ + GstBitReader gb = GST_BIT_READER_INIT (*srcbuf, buf_size); + /* FIXME: Handle FALSE returns from gst_bit_reader_get_* calls? */ + + gboolean stop_parsing = FALSE; + guint32 bits = 0; + guint32 pixels_read = 0; + + static gboolean warning_shown = FALSE; + if (!warning_shown) { + g_warning + ("Parsing 2bit color DVB sub-picture. This is not tested at all. If you see this message, " + "please provide the developers with sample media with these subtitles, if possible."); + warning_shown = TRUE; + } + dvb_log (DVB_LOG_PIXEL, G_LOG_LEVEL_DEBUG, + "(n=2): Inside %s with dbuf_len = %d", __PRETTY_FUNCTION__, dbuf_len); + + while (!stop_parsing && (gst_bit_reader_get_remaining (&gb) > 0)) { + guint run_length = 0, clut_index = 0; + gst_bit_reader_get_bits_uint32 (&gb, &bits, 2); + + if (bits) { /* 2-bit_pixel-code */ + run_length = 1; + clut_index = bits; + } else { /* 2-bit_zero */ + gst_bit_reader_get_bits_uint32 (&gb, &bits, 1); + if (bits == 1) { /* switch_1 == '1' */ + gst_bit_reader_get_bits_uint32 (&gb, &run_length, 3); + run_length += 3; + gst_bit_reader_get_bits_uint32 (&gb, &clut_index, 2); + } else { /* switch_1 == '0' */ + gst_bit_reader_get_bits_uint32 (&gb, &bits, 1); + if (bits == 1) { /* switch_2 == '1' */ + run_length = 1; /* 1x pseudo-colour '00' */ + } else { /* switch_2 == '0' */ + gst_bit_reader_get_bits_uint32 (&gb, &bits, 2); + switch (bits) { /* switch_3 */ + case 0x0: /* end of 2-bit/pixel_code_string */ + stop_parsing = TRUE; + break; + case 0x1: /* two pixels shall be set to pseudo colour (entry) '00' */ + run_length = 2; + break; + case 0x2: /* the following 6 bits contain run length coded pixel data */ + gst_bit_reader_get_bits_uint32 (&gb, &run_length, 4); + run_length += 12; + gst_bit_reader_get_bits_uint32 (&gb, &clut_index, 2); + break; + case 0x3: /* the following 10 bits contain run length coded pixel data */ + gst_bit_reader_get_bits_uint32 (&gb, &run_length, 8); + run_length += 29; + gst_bit_reader_get_bits_uint32 (&gb, &clut_index, 2); + break; + } + } + } + } + + /* If run_length is zero, continue. Only case happening is when + * stop_parsing is TRUE too, so next cycle shouldn't run */ + if (run_length == 0) + continue; + + /* Trim the run_length to not go beyond the line end and consume + * it from remaining length of dest line */ + run_length = MIN (run_length, dbuf_len); + dbuf_len -= run_length; + + /* Make clut_index refer to the index into the desired bit depths + * CLUT definition table */ + if (map_table) + clut_index = map_table[clut_index]; /* now clut_index signifies the index into map_table dest */ + + /* Now we can simply memset run_length count of destination bytes + * to clut_index, but only if not non_modifying */ + dvb_log (DVB_LOG_RUNLEN, G_LOG_LEVEL_DEBUG, + "Setting %u pixels to color 0x%x in destination buffer; dbuf_len left is %d pixels", + run_length, clut_index, dbuf_len); + if (!(non_mod == 1 && bits == 1)) + memset (destbuf, clut_index, run_length); + + destbuf += run_length; + pixels_read += run_length; + } + + // FIXME: Test skip_to_byte instead of adding 7 bits, once everything else is working good + //gst_bit_reader_skip_to_byte (&gb); + *srcbuf += (gst_bit_reader_get_pos (&gb) + 7) >> 3; + + dvb_log (DVB_LOG_PIXEL, G_LOG_LEVEL_DEBUG, + "Returning from 2bit_string parser with %u pixels read", pixels_read); + // FIXME: Shouldn't need this variable if tracking things in the loop better + return pixels_read; +} + +// FFMPEG-FIXME: The same code in ffmpeg is much more complex, it could use the same +// FFMPEG-FIXME: refactoring as done here, explained in commit 895296c3 +static int +_dvb_sub_read_4bit_string (guint8 * destbuf, gint dbuf_len, + const guint8 ** srcbuf, gint buf_size, guint8 non_mod, guint8 * map_table) +{ + GstBitReader gb = GST_BIT_READER_INIT (*srcbuf, buf_size); + /* FIXME: Handle FALSE returns from gst_bit_reader_get_* calls? */ + gboolean stop_parsing = FALSE; + guint32 bits = 0; + guint32 pixels_read = 0; + + dvb_log (DVB_LOG_RUNLEN, G_LOG_LEVEL_DEBUG, + "Entering 4bit_string parser at srcbuf position %p with buf_size = %d; destination buffer size is %d @ %p", + *srcbuf, buf_size, dbuf_len, destbuf); + + while (!stop_parsing && (gst_bit_reader_get_remaining (&gb) > 0)) { + guint run_length = 0, clut_index = 0; + gst_bit_reader_get_bits_uint32 (&gb, &bits, 4); + + if (bits) { + run_length = 1; + clut_index = bits; + } else { + gst_bit_reader_get_bits_uint32 (&gb, &bits, 1); + if (bits == 0) { /* switch_1 == '0' */ + gst_bit_reader_get_bits_uint32 (&gb, &run_length, 3); + if (!run_length) { + stop_parsing = TRUE; + } else { + run_length += 2; + } + } else { /* switch_1 == '1' */ + gst_bit_reader_get_bits_uint32 (&gb, &bits, 1); + if (bits == 0) { /* switch_2 == '0' */ + gst_bit_reader_get_bits_uint32 (&gb, &run_length, 2); + run_length += 4; + gst_bit_reader_get_bits_uint32 (&gb, &clut_index, 4); + } else { /* switch_2 == '1' */ + gst_bit_reader_get_bits_uint32 (&gb, &bits, 2); + switch (bits) { + case 0x0: /* switch_3 == '00' */ + run_length = 1; /* 1 pixel of pseudo-color 0 */ + break; + case 0x1: /* switch_3 == '01' */ + run_length = 2; /* 2 pixels of pseudo-color 0 */ + break; + case 0x2: /* switch_3 == '10' */ + gst_bit_reader_get_bits_uint32 (&gb, &run_length, 4); + run_length += 9; + gst_bit_reader_get_bits_uint32 (&gb, &clut_index, 4); + break; + case 0x3: /* switch_3 == '11' */ + gst_bit_reader_get_bits_uint32 (&gb, &run_length, 8); + run_length += 25; + gst_bit_reader_get_bits_uint32 (&gb, &clut_index, 4); + break; + } + } + } + } + + /* If run_length is zero, continue. Only case happening is when + * stop_parsing is TRUE too, so next cycle shouldn't run */ + if (run_length == 0) + continue; + + /* Trim the run_length to not go beyond the line end and consume + * it from remaining length of dest line */ + run_length = MIN (run_length, dbuf_len); + dbuf_len -= run_length; + + /* Make clut_index refer to the index into the desired bit depths + * CLUT definition table */ + if (map_table) + clut_index = map_table[clut_index]; /* now clut_index signifies the index into map_table dest */ + + /* Now we can simply memset run_length count of destination bytes + * to clut_index, but only if not non_modifying */ + dvb_log (DVB_LOG_RUNLEN, G_LOG_LEVEL_DEBUG, + "Setting %u pixels to color 0x%x in destination buffer; dbuf_len left is %d pixels", + run_length, clut_index, dbuf_len); + if (!(non_mod == 1 && bits == 1)) + memset (destbuf, clut_index, run_length); + + destbuf += run_length; + pixels_read += run_length; + } + + // FIXME: Test skip_to_byte instead of adding 7 bits, once everything else is working good + //gst_bit_reader_skip_to_byte (&gb); + *srcbuf += (gst_bit_reader_get_pos (&gb) + 7) >> 3; + + dvb_log (DVB_LOG_PIXEL, G_LOG_LEVEL_DEBUG, + "Returning from 4bit_string parser with %u pixels read", pixels_read); + // FIXME: Shouldn't need this variable if tracking things in the loop better + return pixels_read; +} + +static int +_dvb_sub_read_8bit_string (guint8 * destbuf, gint dbuf_len, + const guint8 ** srcbuf, gint buf_size, guint8 non_mod, guint8 * map_table) +{ + GstBitReader gb = GST_BIT_READER_INIT (*srcbuf, buf_size); + /* FIXME: Handle FALSE returns from gst_bit_reader_get_* calls? */ + + gboolean stop_parsing = FALSE; + guint32 bits = 0; + guint32 pixels_read = 0; + + static gboolean warning_shown = FALSE; + if (!warning_shown) { + g_warning + ("Parsing 8bit color DVB sub-picture. This is not tested at all. If you see this message, " + "please provide the developers with sample media with these subtitles, if possible."); + warning_shown = TRUE; + } + dvb_log (DVB_LOG_PIXEL, G_LOG_LEVEL_DEBUG, + "(n=8): Inside %s with dbuf_len = %d", __PRETTY_FUNCTION__, dbuf_len); + + /* FFMPEG-FIXME: ffmpeg uses a manual byte walking algorithm, which might be more performant, + * FFMPEG-FIXME: but it does almost absolutely no buffer length checking, so could walk over + * FFMPEG-FIXME: memory boundaries. While we don't check gst_bit_reader_get_bits_uint32 + * FFMPEG-FIXME: return values either and therefore might get some pixels corrupted, we at + * FFMPEG-FIXME: lest have no chance of reading memory we don't own and visual corruption + * FFMPEG-FIXME: is guaranteed anyway when not all bytes are present */ + /* Rephrased - it's better to work with bytes with default value '0' instead of reading from memory we don't own. */ + while (!stop_parsing && (gst_bit_reader_get_remaining (&gb) > 0)) { + guint run_length = 0, clut_index = 0; + gst_bit_reader_get_bits_uint32 (&gb, &bits, 8); + + if (bits) { /* 8-bit_pixel-code */ + run_length = 1; + clut_index = bits; + } else { /* 8-bit_zero */ + gst_bit_reader_get_bits_uint32 (&gb, &bits, 1); + if (bits == 0) { /* switch_1 == '0' */ + /* run_length_1-127 for pseudo-colour _entry) '0x00' */ + gst_bit_reader_get_bits_uint32 (&gb, &run_length, 7); + if (run_length == 0) { /* end_of_string_signal */ + stop_parsing = TRUE; + } + } else { /* switch_1 == '1' */ + /* run_length_3-127 */ + gst_bit_reader_get_bits_uint32 (&gb, &run_length, 7); + gst_bit_reader_get_bits_uint32 (&gb, &clut_index, 8); +#ifdef DEBUG + /* Emit a debugging message about stream not following specification */ + if (run_length < 3) { + dvb_log (DVB_LOG_STREAM, G_LOG_LEVEL_WARNING, + "8-bit/pixel_code_string::run_length_3-127 value was %u, but the spec requires it must be >=3", + run_length); + } +#endif + } + } + + /* If run_length is zero, continue. Only case happening is when + * stop_parsing is TRUE too, so next cycle shouldn't run */ + if (run_length == 0) + continue; + + /* Trim the run_length to not go beyond the line end and consume + * it from remaining length of dest line */ + run_length = MIN (run_length, dbuf_len); + dbuf_len -= run_length; + + /* Make clut_index refer to the index into the desired bit depths + * CLUT definition table */ + if (map_table) + clut_index = map_table[clut_index]; /* now clut_index signifies the index into map_table dest */ + + /* Now we can simply memset run_length count of destination bytes + * to clut_index, but only if not non_modifying */ + dvb_log (DVB_LOG_RUNLEN, G_LOG_LEVEL_DEBUG, + "Setting %u pixels to color 0x%x in destination buffer; dbuf_len left is %d pixels", + run_length, clut_index, dbuf_len); + if (!(non_mod == 1 && bits == 1)) + memset (destbuf, clut_index, run_length); + + destbuf += run_length; + pixels_read += run_length; + } + + dvb_log (DVB_LOG_PIXEL, G_LOG_LEVEL_DEBUG, + "Returning from 8bit_string parser with %u pixels read", pixels_read); + // FIXME: Shouldn't need this variable if tracking things in the loop better + return pixels_read; +} + +static void +_dvb_sub_parse_pixel_data_block (DvbSub * dvb_sub, + DVBSubObjectDisplay * display, const guint8 * buf, gint buf_size, + DvbSubPixelDataSubBlockFieldType top_bottom, guint8 non_mod) +{ + DVBSubRegion *region = get_region (dvb_sub, display->region_id); + const guint8 *buf_end = buf + buf_size; + guint8 *pbuf; + int x_pos, y_pos; + int i; + gboolean dest_buf_filled = FALSE; + + guint8 map2to4[] = { 0x0, 0x7, 0x8, 0xf }; + guint8 map2to8[] = { 0x00, 0x77, 0x88, 0xff }; + guint8 map4to8[] = { 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff + }; + guint8 *map_table; + + dvb_log (DVB_LOG_PIXEL, G_LOG_LEVEL_DEBUG, + "(parse_block): DVB pixel block size %d, %s field:", + buf_size, top_bottom ? "bottom" : "top"); + +#ifdef DEBUG_PACKET_CONTENTS + gst_util_dump_mem (buf, buf_size); +#endif + + if (region == NULL) { + g_print ("Region is NULL, returning\n"); + return; + } + + pbuf = region->pbuf; + + x_pos = display->x_pos; + y_pos = display->y_pos; + + if ((y_pos & 1) != top_bottom) + y_pos++; + + while (buf < buf_end) { + dvb_log (DVB_LOG_PIXEL, G_LOG_LEVEL_DEBUG, + "Iteration start, %u bytes missing from end; buf = %p, buf_end = %p; " + "Region is number %u, with a dimension of %dx%d; We are at position %dx%d", + buf_end - buf, buf, buf_end, + region->id, region->width, region->height, x_pos, y_pos); + // FFMPEG-FIXME: ffmpeg doesn't check for equality and so can overflow destination buffer later on with bad input data + // FFMPEG-FIXME: However that makes it warn on end_of_object_line and map tables as well, so we add the dest_buf_filled tracking + // FIXME: Removed x_pos checking here, because we don't want to turn dest_buf_filled to TRUE permanently in that case + // FIXME: We assume that region->width - x_pos as dbuf_len to read_nbit_string will take care of that case nicely; + // FIXME: That is, that read_nbit_string never scribbles anything if dbuf_len passed to it is zero due to this. + if (y_pos >= region->height) { + dest_buf_filled = TRUE; + } + + switch (*buf++) { + case 0x10: + if (dest_buf_filled) { + g_warning ("Invalid object location for data_type 0x%x!\n", *(buf - 1)); /* FIXME: Be more verbose */ + g_print ("Remaining data after invalid object location:\n"); + gst_util_dump_mem (buf, buf_end - buf); + return; + } + + if (region->depth == 8) + map_table = map2to8; + else if (region->depth == 4) + map_table = map2to4; + else + map_table = NULL; + + // FFMPEG-FIXME: ffmpeg code passes buf_size instead of buf_end - buf, and could + // FFMPEG-FIXME: therefore potentially walk over the memory area we own + x_pos += + _dvb_sub_read_2bit_string (pbuf + (y_pos * region->width) + x_pos, + region->width - x_pos, &buf, buf_end - buf, non_mod, map_table); + break; + case 0x11: + if (dest_buf_filled) { + g_warning ("Invalid object location for data_type 0x%x!\n", *(buf - 1)); /* FIXME: Be more verbose */ + g_print ("Remaining data after invalid object location:\n"); + gst_util_dump_mem (buf, buf_end - buf); + return; // FIXME: Perhaps tell read_nbit_string that dbuf_len is zero and let it walk the bytes regardless? (Same FIXME for 2bit and 8bit) + } + + if (region->depth < 4) { + g_warning ("4-bit pixel string in %d-bit region!\n", region->depth); + return; + } + + if (region->depth == 8) + map_table = map4to8; + else + map_table = NULL; + + dvb_log (DVB_LOG_PIXEL, G_LOG_LEVEL_DEBUG, + "READ_nBIT_STRING (4): String data into position %dx%d; buf before is %p\n", + x_pos, y_pos, buf); + // FFMPEG-FIXME: ffmpeg code passes buf_size instead of buf_end - buf, and could + // FFMPEG-FIXME: therefore potentially walk over the memory area we own + x_pos += + _dvb_sub_read_4bit_string (pbuf + (y_pos * region->width) + x_pos, + region->width - x_pos, &buf, buf_end - buf, non_mod, map_table); + dvb_log (DVB_LOG_PIXEL, G_LOG_LEVEL_DEBUG, + "READ_nBIT_STRING (4) finished: buf pointer now %p", buf); + break; + case 0x12: + if (dest_buf_filled) { + g_warning ("Invalid object location for data_type 0x%x!\n", *(buf - 1)); /* FIXME: Be more verbose */ + g_print ("Remaining data after invalid object location:\n"); + gst_util_dump_mem (buf, buf_end - buf); + return; + } + + if (region->depth < 8) { + g_warning ("8-bit pixel string in %d-bit region!\n", region->depth); + return; + } + // FFMPEG-FIXME: ffmpeg code passes buf_size instead of buf_end - buf, and could + // FFMPEG-FIXME: therefore potentially walk over the memory area we own + x_pos += + _dvb_sub_read_8bit_string (pbuf + (y_pos * region->width) + x_pos, + region->width - x_pos, &buf, buf_end - buf, non_mod, NULL); + break; + + case 0x20: + dvb_log (DVB_LOG_PIXEL, G_LOG_LEVEL_DEBUG, + "(parse_block): handling map2to4 table data"); + /* FIXME: I don't see any guards about buffer size here - buf++ happens with the switch, but + * FIXME: buffer is walked without length checks? Same deal in other map table cases */ + map2to4[0] = (*buf) >> 4; + map2to4[1] = (*buf++) & 0xf; + map2to4[2] = (*buf) >> 4; + map2to4[3] = (*buf++) & 0xf; + break; + case 0x21: + dvb_log (DVB_LOG_PIXEL, G_LOG_LEVEL_DEBUG, + "(parse_block): handling map2to8 table data"); + for (i = 0; i < 4; i++) + map2to8[i] = *buf++; + break; + case 0x22: + dvb_log (DVB_LOG_PIXEL, G_LOG_LEVEL_DEBUG, + "(parse_block): handling map4to8 table data"); + for (i = 0; i < 16; i++) + map4to8[i] = *buf++; + break; + + case 0xf0: + dvb_log (DVB_LOG_PIXEL, G_LOG_LEVEL_DEBUG, + "(parse_block): end of object line code encountered"); + x_pos = display->x_pos; + y_pos += 2; + break; + default: + /* FIXME: Do we consume word align stuffing byte that could follow top/bottom data? */ + g_warning ("Unknown/unsupported pixel block 0x%x", *(buf - 1)); + } + } +} + +static void +_dvb_sub_parse_object_segment (DvbSub * dvb_sub, guint16 page_id, guint8 * buf, + gint buf_size) +{ + const guint8 *buf_end = buf + buf_size; + guint object_id; + DVBSubObject *object; + + guint8 coding_method, non_modifying_color; + + object_id = GST_READ_UINT16_BE (buf); + buf += 2; + + object = get_object (dvb_sub, object_id); + + dvb_log (DVB_LOG_OBJECT, G_LOG_LEVEL_DEBUG, + "parse_object_segment: A new object segment has occurred for object_id = %u", + object_id); + + if (!object) { + g_warning + ("Nothing known about object with ID %u yet inside parse_object_segment, bailing out", + object_id); + return; + } + + coding_method = ((*buf) >> 2) & 3; + non_modifying_color = ((*buf++) >> 1) & 1; + + if (coding_method == 0) { + const guint8 *block; + DVBSubObjectDisplay *display; + guint16 top_field_len, bottom_field_len; + + top_field_len = GST_READ_UINT16_BE (buf); + buf += 2; + bottom_field_len = GST_READ_UINT16_BE (buf); + buf += 2; + + if (buf + top_field_len + bottom_field_len > buf_end) { + g_warning ("%s: Field data size too large\n", __PRETTY_FUNCTION__); + return; + } + + /* FIXME: Potential optimization opportunity here - parse the object pixmap only once, and copy it to all the + * FIXME: regions that need it. One object being in multiple regions is a rare occurrence in real life, however */ + for (display = object->display_list; display; + display = display->object_list_next) { + block = buf; + + dvb_log (DVB_LOG_OBJECT, G_LOG_LEVEL_DEBUG, + "Parsing top and bottom part of object id %d; top_field_len = %u, bottom_field_len = %u", + display->object_id, top_field_len, bottom_field_len); + _dvb_sub_parse_pixel_data_block (dvb_sub, display, block, top_field_len, + TOP_FIELD, non_modifying_color); + + if (bottom_field_len > 0) + block = buf + top_field_len; + else + bottom_field_len = top_field_len; + + _dvb_sub_parse_pixel_data_block (dvb_sub, display, block, + bottom_field_len, BOTTOM_FIELD, non_modifying_color); + } + + } else if (coding_method == 1) { + g_warning ("'a string of characters' coding method not supported (yet?)!"); + } else { + g_warning ("%s: Unknown object coding 0x%x\n", __PRETTY_FUNCTION__, + coding_method); + } +} + +static gint +_dvb_sub_parse_end_of_display_set (DvbSub * dvb_sub, guint16 page_id, + guint8 * buf, gint buf_size, guint64 pts) +{ + DvbSubPrivate *priv = (DvbSubPrivate *) dvb_sub->private_data; + + DVBSubtitles *sub = g_slice_new0 (DVBSubtitles); + + DVBSubRegion *region; + DVBSubRegionDisplay *display; + DVBSubtitleRect *rect; + DVBSubCLUT *clut; + guint32 *clut_table; + int i; + + static unsigned counter = 0; /* DEBUG use only */ + + dvb_log (DVB_LOG_DISPLAY, G_LOG_LEVEL_DEBUG, + "END OF DISPLAY SET: page_id = %u, length = %d\n", page_id, buf_size); + + sub->rects = NULL; +#if 0 /* FIXME: PTS stuff not figured out yet */ + sub->start_display_time = 0; + sub->end_display_time = priv->page_time_out * 1000; + sub->format = 0; /* 0 = graphics */ +#endif + + sub->num_rects = priv->display_list_size; + + if (sub->num_rects > 0) { + // FIXME-MEMORY-LEAK: This structure is not freed up yet + sub->rects = g_malloc0 (sizeof (*sub->rects) * sub->num_rects); /* GSlice? */ + for (i = 0; i < sub->num_rects; i++) + sub->rects[i] = g_malloc0 (sizeof (*sub->rects[i])); /* GSlice? */ + } + + i = 0; + + for (display = priv->display_list; display; display = display->next) { + region = get_region (dvb_sub, display->region_id); + rect = sub->rects[i]; + + if (!region) + continue; + + rect->x = display->x_pos; + rect->y = display->y_pos; + rect->w = region->width; + rect->h = region->height; +#if 0 /* FIXME: Don't think we need to save the number of colors in the palette when we are saving as RGBA? */ + rect->nb_colors = 16; +#endif +#if 0 /* FIXME: Needed to be specified once we support strings of characters based subtitles */ + rect->type = SUBTITLE_BITMAP; +#endif + rect->pict.rowstride = region->width; + rect->pict.palette_bits_count = region->depth; + + clut = get_clut (dvb_sub, region->clut); + + if (!clut) + clut = &default_clut; + + switch (region->depth) { + case 2: + clut_table = clut->clut4; + break; + case 8: + clut_table = clut->clut256; + break; + case 4: + default: + clut_table = clut->clut16; + break; + } + + /* FIXME: Tweak this to be saved in a format most suitable for Qt and GStreamer instead. + * Currently kept in AVPicture for quick save_display_set testing */ + rect->pict.palette = g_malloc ((1 << region->depth) * sizeof (guint32)); /* FIXME: Can we use GSlice here? */ + memcpy (rect->pict.palette, clut_table, + (1 << region->depth) * sizeof (guint32)); +#if 0 + g_print ("rect->pict.data.palette content:\n"); + gst_util_dump_mem (rect->pict.palette, + (1 << region->depth) * sizeof (guint32)); +#endif + + rect->pict.data = g_malloc (region->buf_size); /* FIXME: Can we use GSlice here? */ + memcpy (rect->pict.data, region->pbuf, region->buf_size); + + ++counter; + dvb_log (DVB_LOG_DISPLAY, G_LOG_LEVEL_DEBUG, + "An object rect created: number %u, iteration %u, pos: %d:%d, size: %dx%d", + counter, i, rect->x, rect->y, rect->w, rect->h); +#if 0 + g_print ("rect->pict.data content:\n"); + gst_util_dump_mem (rect->pict.data, region->buf_size); +#endif + + ++i; + } + + sub->num_rects = i; + + if (priv->callbacks.new_data) + priv->callbacks.new_data (dvb_sub, pts, sub, priv->page_time_out, + priv->user_data); + + /* Now free up all the temporary memory we allocated */ + for (i = 0; i < sub->num_rects; ++i) { + rect = sub->rects[i]; + + g_free (rect->pict.palette); + g_free (rect->pict.data); + g_free (rect); + } + g_free (sub->rects); + g_slice_free (DVBSubtitles, sub); + + return 1; /* FIXME: The caller of this function is probably supposed to do something with the return value */ +} + +/** + * dvb_sub_new: + * + * Creates a new #DvbSub. + * + * Return value: a newly created #DvbSub + */ +DvbSub * +dvb_sub_new (void) +{ + DvbSub *dvbsub = g_object_new (DVB_TYPE_SUB, NULL); + + return dvbsub; +} + +/** + * dvb_sub_feed: + * @dvb_sub: a #DvbSub + * @data: The data to feed to the parser + * @len: Length of the data + * + * Feeds the DvbSub parser with new PES packet data to parse. + * The data given must be a full PES packet, which must + * include a PTS field in the headers. + * Only one packet is handled in one call, so the available data + * should be fed continously until all is consumed. + * + * Return value: a negative value on errors, -4 if simply not enough data for the PES packet; + * Amount of data consumed (length of handled PES packet on success) + */ +gint +dvb_sub_feed (DvbSub * dvb_sub, guint8 * data, gint len) +{ + guint64 pts = 0; + unsigned int pos = 0; + guint16 PES_packet_len; + guint8 PES_packet_header_len; + gboolean is_subtitle_packet = TRUE; + gboolean pts_field_present = FALSE; + g_warning ("Feeding %d bytes of data to dvbsub!!!!!!!!!!!!\n", len); + if (len == 0) + return 0; + + if (len <= 8) { + dvb_log (DVB_LOG_PACKET, G_LOG_LEVEL_WARNING, + "Length %d too small for further processing", len); + return -1; + } + + if (data[0] != 0x00 || data[1] != 0x00 || data[2] != 0x01) { + dvb_log (DVB_LOG_PACKET, G_LOG_LEVEL_WARNING, + "Data fed to dvb_sub_feed is not a PES packet - does not start with a code_prefix of 0x000001"); + return 1; // FIXME: Probably handle it? - we need to skip PES_packet_len from this elementary stream then and move on + } + + if (data[3] != 0xBD) { + dvb_log (DVB_LOG_PACKET, G_LOG_LEVEL_INFO, + "Data fed to dvb_sub_feed is not a PES packet of type private_stream_1, but rather '0x%X', so not a subtitle stream", + data[3]); + is_subtitle_packet = FALSE; + } + + PES_packet_len = (data[4] << 8) | data[5]; + dvb_log (DVB_LOG_PACKET, G_LOG_LEVEL_DEBUG, + "PES packet length is %u", PES_packet_len); + pos = 6; + + /* FIXME: If the packet is cut, we could be feeding data more than we actually have here, which breaks everything. Probably need to buffer up and handle it, + * FIXME: Or push back in front to the file descriptor buffer (but we are using read, not libc buffered fread, so that idea might not be possible )*/ + if ((len - 5) < PES_packet_len) { + dvb_log (DVB_LOG_PACKET, G_LOG_LEVEL_WARNING, + "!!!!!!!!!!! claimed PES packet length was %d, but we only had %d bytes available, falling back and waiting more !!!!!!!!!", + PES_packet_len, len - 5); + return -4; + } + /* FIXME: Validate sizes inbetween here */ + + /* If this is a non-subtitle packet, still skip the data, pretending we consumed it (FIXME: Signal up) */ + if (!is_subtitle_packet) { + return pos + PES_packet_len; + } + + pos++; + + if (data[pos++] & 0x80) { /* PTS fields present (possibly also DTS). Technically this must be present per the spec */ + pts_field_present = TRUE; + } + + /* pos should be 8 now anyway */ + pos = 8; + + PES_packet_header_len = data[pos++]; + + if (pts_field_present) { + /* '001x', PTS[32..30], marker, PTS[29..15], marker, PTS[14..0], marker */ + pts = ((guint64) (data[pos] & 0x0E)) << 29; /* PTS[32..30], ignore marker at rightmost bit */ + pts |= ((guint64) (data[pos + 1])) << 22; /* PTS[29..22], full byte */ + pts |= ((guint64) (data[pos + 2] & 0xFE)) << 14; /* PTS[21..15], ignore marker at rightmost bit */ + pts |= ((guint64) (data[pos + 3])) << 7; /* PTS[14.. 7], full byte */ + pts |= ((guint64) (data[pos + 4] & 0xFE)) >> 1; /* PTS[ 6.. 0], ignore marker at rightmost bit */ + } + + pos += PES_packet_header_len; /* FIXME: Currently including all header values with all but PTS ignored */ + + dvb_sub_feed_with_pts (dvb_sub, pts, data + pos, PES_packet_len - PES_packet_header_len - 3); /* 2 bytes between PES_packet_len and PES_packet_header_len fields, minus header_len itself */ + pos += PES_packet_len - PES_packet_header_len - 3; + dvb_log (DVB_LOG_PACKET, G_LOG_LEVEL_DEBUG, + "Finished PES packet - consumed %u bytes of %d", pos, len); + + return pos; +} + +#define DVB_SUB_SEGMENT_PAGE_COMPOSITION 0x10 +#define DVB_SUB_SEGMENT_REGION_COMPOSITION 0x11 +#define DVB_SUB_SEGMENT_CLUT_DEFINITION 0x12 +#define DVB_SUB_SEGMENT_OBJECT_DATA 0x13 +#define DVB_SUB_SEGMENT_END_OF_DISPLAY_SET 0x80 +#define DVB_SUB_SEGMENT_STUFFING 0xFF + +#define DVB_SUB_SYNC_BYTE 0x0f +/** + * dvb_sub_feed_with_pts: + * @dvb_sub: a #DvbSub + * @pts: The PTS of the data + * @data: The data to feed to the parser + * @len: Length of the data + * + * Feeds the DvbSub parser with new binary data to parse, + * with an associated PTS value. E.g, data left after PES + * packet header has been already parsed, which contains + * the PTS information). + * + * Return value: -1 if data was unhandled (e.g, not a subtitle packet), + * -2 if data parsing was unsuccesful (e.g, length was invalid), + * 0 or positive if data was handled. If positive, then amount of data consumed on success. FIXME: List the positive return values. + */ +gint +dvb_sub_feed_with_pts (DvbSub * dvb_sub, guint64 pts, guint8 * data, gint len) +{ + unsigned int pos = 0; + guint8 segment_type; + guint16 segment_len; + guint16 page_id; + + dvb_log (DVB_LOG_PACKET, G_LOG_LEVEL_DEBUG, + "Inside dvb_sub_feed_with_pts with pts=%" G_GUINT64_FORMAT + " and length %d", pts, len); + + g_return_val_if_fail (data != NULL, -1); + + if (len <= 3) { /* len(0x20 0x00 end_of_PES_data_field_marker) */ + g_warning ("Data length too short"); + return -1; + } + + if (data[pos++] != 0x20) { + g_warning + ("Tried to handle a PES packet private data that isn't a subtitle packet (does not start with 0x20)"); + return -1; + } + + if (data[pos++] != 0x00) { + g_warning + ("'Subtitle stream in this PES packet' was not 0x00, so this is in theory not a DVB subtitle stream (but some other subtitle standard?); bailing out"); + return -1; + } + + while (data[pos++] == DVB_SUB_SYNC_BYTE) { + if ((len - pos) < (2 * 2 + 1)) { + g_warning + ("Data after SYNC BYTE too short, less than needed to even get to segment_length"); + return -2; + } + segment_type = data[pos++]; + dvb_log (DVB_LOG_PACKET, G_LOG_LEVEL_DEBUG, + "=== Segment type is 0x%x", segment_type); + page_id = (data[pos] << 8) | data[pos + 1]; + dvb_log (DVB_LOG_PACKET, G_LOG_LEVEL_DEBUG, "page_id is 0x%x", page_id); + pos += 2; + segment_len = (data[pos] << 8) | data[pos + 1]; + dvb_log (DVB_LOG_PACKET, G_LOG_LEVEL_DEBUG, + "segment_length is %d (0x%x 0x%x)", segment_len, data[pos], + data[pos + 1]); + pos += 2; + if ((len - pos) < segment_len) { + g_warning + ("segment_length was told to be %u, but we only have %d bytes left", + segment_len, len - pos); + return -2; + } + // TODO: Parse the segment per type + switch (segment_type) { + case DVB_SUB_SEGMENT_PAGE_COMPOSITION: + dvb_log (DVB_LOG_PACKET, G_LOG_LEVEL_DEBUG, + "Page composition segment at buffer pos %u\n", pos); + _dvb_sub_parse_page_segment (dvb_sub, page_id, data + pos, segment_len); /* FIXME: Not sure about args */ + break; + case DVB_SUB_SEGMENT_REGION_COMPOSITION: + dvb_log (DVB_LOG_PACKET, G_LOG_LEVEL_DEBUG, + "Region composition segment at buffer pos %u\n", pos); + _dvb_sub_parse_region_segment (dvb_sub, page_id, data + pos, segment_len); /* FIXME: Not sure about args */ + break; + case DVB_SUB_SEGMENT_CLUT_DEFINITION: + dvb_log (DVB_LOG_PACKET, G_LOG_LEVEL_DEBUG, + "CLUT definition segment at buffer pos %u\n", pos); + _dvb_sub_parse_clut_segment (dvb_sub, page_id, data + pos, segment_len); /* FIXME: Not sure about args */ + break; + case DVB_SUB_SEGMENT_OBJECT_DATA: + dvb_log (DVB_LOG_PACKET, G_LOG_LEVEL_DEBUG, + "Object data segment at buffer pos %u\n", pos); + _dvb_sub_parse_object_segment (dvb_sub, page_id, data + pos, segment_len); /* FIXME: Not sure about args */ + break; + case DVB_SUB_SEGMENT_END_OF_DISPLAY_SET: + dvb_log (DVB_LOG_PACKET, G_LOG_LEVEL_DEBUG, + "End of display set at buffer pos %u\n", pos); + _dvb_sub_parse_end_of_display_set (dvb_sub, page_id, data + pos, segment_len, pts); /* FIXME: Not sure about args */ + break; + default: + g_warning ("Unhandled segment type 0x%x", segment_type); + break; + } + + pos += segment_len; + + if (pos == len) { + g_warning ("Data ended without a PES data end marker"); + return 1; + } + } + + g_warning ("Processed %d bytes out of %d\n", pos, len); + return pos; +} + +/** + * dvb_sub_set_callbacks: + * @dvb_sub: a #DvbSub + * @callbacks: the callbacks to install + * @user_data: a user_data argument for the callback + * + * Set callback which will be executed when new subpictures are available. + */ +void +dvb_sub_set_callbacks (DvbSub * dvb_sub, DvbSubCallbacks * callbacks, + gpointer user_data) +{ + DvbSubPrivate *priv; + + g_return_if_fail (dvb_sub != NULL); + g_return_if_fail (DVB_IS_SUB (dvb_sub)); + g_return_if_fail (callbacks != NULL); + + priv = (DvbSubPrivate *) dvb_sub->private_data; + + priv->callbacks = *callbacks; + priv->user_data = user_data; +} + +void +dvb_sub_set_global_log_cb (void (*log_cb) (GLogLevelFlags log_level, + const gchar * format, va_list args, gpointer user_data), + gpointer user_data) +{ + if (log_cb) { + g_log_callback = log_cb; + g_log_callback_user_data = user_data; + } +} diff --git a/gst/dvbsuboverlay/dvb-sub.h b/gst/dvbsuboverlay/dvb-sub.h new file mode 100644 index 0000000000..fee88164d2 --- /dev/null +++ b/gst/dvbsuboverlay/dvb-sub.h @@ -0,0 +1,136 @@ +/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */ +/* + * libdvbsub - DVB subtitle decoding + * Copyright (C) Mart Raudsepp 2009 + * + * 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; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * 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 _DVB_SUB_H_ +#define _DVB_SUB_H_ + +#include + +G_BEGIN_DECLS + +#define DVB_TYPE_SUB (dvb_sub_get_type ()) +#define DVB_SUB(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), DVB_TYPE_SUB, DvbSub)) +#define DVB_SUB_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), DVB_TYPE_SUB, DvbSubClass)) +#define DVB_IS_SUB(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), DVB_TYPE_SUB)) +#define DVB_IS_SUB_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), DVB_TYPE_SUB)) +#define DVB_SUB_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DVB_TYPE_SUB, DvbSubClass)) + +typedef struct _DvbSubClass DvbSubClass; +typedef struct _DvbSub DvbSub; + +struct _DvbSubClass +{ + GObjectClass parent_class; +}; + +/** + * DvbSub: + * + * The #DvbSub struct contains only private fields and should not be + * directly accessed. + */ +struct _DvbSub +{ + GObject parent_instance; + + /*< private >*/ + gpointer private_data; +}; + +/** + * DVBSubtitlePicture: + * @data: the data in the form of palette indices, each byte represents one pixel + * as an index into the @palette. + * @palette: the palette used for this subtitle rectangle, up to 256 items depending + * on the depth of the subpicture; each palette item is in ARGB form, 8-bits per channel. + * @palette_bits_count: the amount of bits used in indeces into @palette in @data. + * @rowstride: the number of bytes between the start of a row and the start of the next row. + * + * A structure representing the contents of a subtitle rectangle. + * + * FIXME: Expose the depth of the palette, and perhaps also the height in this struct. + */ +typedef struct DVBSubtitlePicture { + guint8 *data; + guint32 *palette; + guint8 palette_bits_count; + int rowstride; +} DVBSubtitlePicture; + +/** + * DVBSubtitleRect: + * @x: x coordinate of top left corner + * @y: y coordinate of top left corner + * @w: the width of this subpicture rectangle + * @h: the height of this subpicture rectangle + * @pict: the content of this subpicture rectangle + * + * A structure representing one subtitle objects position, dimension and content. + */ +typedef struct DVBSubtitleRect { + int x; + int y; + int w; + int h; + + DVBSubtitlePicture pict; +} DVBSubtitleRect; + +/** + * DVBSubtitles: + * @num_rects: the number of #DVBSubtitleRect in @rects + * @rects: dynamic array of #DVBSubtitleRect + * + * A structure representing a set of subtitle objects. + */ +typedef struct DVBSubtitles { + unsigned int num_rects; + DVBSubtitleRect **rects; +} DVBSubtitles; + +/** + * DvbSubCallbacks: + * @new_data: called when new subpicture data is available for display. @dvb_sub + * is the #DvbSub instance this callback originates from; @subs is the set of + * subtitle objects that should be display for no more than @page_time_out + * seconds at @pts; @user_data is the same user_data as was passed through + * dvb_sub_set_callbacks(); + * + * A set of callbacks that can be installed on the #DvbSub with + * dvb_sub_set_callbacks(). + */ +typedef struct { + void (*new_data) (DvbSub *dvb_sub, guint64 pts, DVBSubtitles * subs, guint8 page_time_out, gpointer user_data); + /*< private >*/ + gpointer _dvb_sub_reserved[3]; +} DvbSubCallbacks; + +GType dvb_sub_get_type (void) G_GNUC_CONST; +DvbSub *dvb_sub_new (void); +gint dvb_sub_feed (DvbSub *dvb_sub, guint8 *data, gint len); +gint dvb_sub_feed_with_pts (DvbSub *dvb_sub, guint64 pts, guint8 *data, gint len); +void dvb_sub_set_callbacks (DvbSub *dvb_sub, DvbSubCallbacks *callbacks, gpointer user_data); + +void dvb_sub_set_global_log_cb (void (*log_cb) (GLogLevelFlags log_level, const gchar *format, va_list args, gpointer user_data), + gpointer user_data); + +G_END_DECLS + +#endif /* _DVB_SUB_H_ */ diff --git a/gst/dvbsuboverlay/ffmpeg-colorspace.h b/gst/dvbsuboverlay/ffmpeg-colorspace.h new file mode 100644 index 0000000000..18bfe5521c --- /dev/null +++ b/gst/dvbsuboverlay/ffmpeg-colorspace.h @@ -0,0 +1,116 @@ +/* + * This file is copied from ffmpeg's libavcodec/colorspace.h + * for the YUV_TO_RGB{1,2}_CCIR macros. + * Original copyright header and contents follows: + */ +/* + * Colorspace conversion defines + * Copyright (c) 2001, 2002, 2003 Fabrice Bellard + * + * This file is part of FFmpeg. + * + * FFmpeg 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; either + * version 2.1 of the License, or (at your option) any later version. + * + * FFmpeg 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 FFmpeg; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + */ + +/** + * @file libavcodec/colorspace.h + * Various defines for YUV<->RGB conversion + */ + +#ifndef AVCODEC_COLORSPACE_H +#define AVCODEC_COLORSPACE_H + +#define SCALEBITS 10 +#define ONE_HALF (1 << (SCALEBITS - 1)) +#define FIX(x) ((int) ((x) * (1<> SCALEBITS];\ + g = cm[(y + g_add) >> SCALEBITS];\ + b = cm[(y + b_add) >> SCALEBITS];\ +} + +#define YUV_TO_RGB1(cb1, cr1)\ +{\ + cb = (cb1) - 128;\ + cr = (cr1) - 128;\ + r_add = FIX(1.40200) * cr + ONE_HALF;\ + g_add = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF;\ + b_add = FIX(1.77200) * cb + ONE_HALF;\ +} + +#define YUV_TO_RGB2(r, g, b, y1)\ +{\ + y = (y1) << SCALEBITS;\ + r = cm[(y + r_add) >> SCALEBITS];\ + g = cm[(y + g_add) >> SCALEBITS];\ + b = cm[(y + b_add) >> SCALEBITS];\ +} + +#define Y_CCIR_TO_JPEG(y)\ + cm[((y) * FIX(255.0/219.0) + (ONE_HALF - 16 * FIX(255.0/219.0))) >> SCALEBITS] + +#define Y_JPEG_TO_CCIR(y)\ + (((y) * FIX(219.0/255.0) + (ONE_HALF + (16 << SCALEBITS))) >> SCALEBITS) + +#define C_CCIR_TO_JPEG(y)\ + cm[(((y) - 128) * FIX(127.0/112.0) + (ONE_HALF + (128 << SCALEBITS))) >> SCALEBITS] + +/* NOTE: the clamp is really necessary! */ +static inline int C_JPEG_TO_CCIR(int y) { + y = (((y - 128) * FIX(112.0/127.0) + (ONE_HALF + (128 << SCALEBITS))) >> SCALEBITS); + if (y < 16) + y = 16; + return y; +} + + +#define RGB_TO_Y(r, g, b) \ +((FIX(0.29900) * (r) + FIX(0.58700) * (g) + \ + FIX(0.11400) * (b) + ONE_HALF) >> SCALEBITS) + +#define RGB_TO_U(r1, g1, b1, shift)\ +(((- FIX(0.16874) * r1 - FIX(0.33126) * g1 + \ + FIX(0.50000) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128) + +#define RGB_TO_V(r1, g1, b1, shift)\ +(((FIX(0.50000) * r1 - FIX(0.41869) * g1 - \ + FIX(0.08131) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128) + +#define RGB_TO_Y_CCIR(r, g, b) \ +((FIX(0.29900*219.0/255.0) * (r) + FIX(0.58700*219.0/255.0) * (g) + \ + FIX(0.11400*219.0/255.0) * (b) + (ONE_HALF + (16 << SCALEBITS))) >> SCALEBITS) + +#define RGB_TO_U_CCIR(r1, g1, b1, shift)\ +(((- FIX(0.16874*224.0/255.0) * r1 - FIX(0.33126*224.0/255.0) * g1 + \ + FIX(0.50000*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128) + +#define RGB_TO_V_CCIR(r1, g1, b1, shift)\ +(((FIX(0.50000*224.0/255.0) * r1 - FIX(0.41869*224.0/255.0) * g1 - \ + FIX(0.08131*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128) + +#endif /* AVCODEC_COLORSPACE_H */ diff --git a/gst/dvbsuboverlay/gstdvbsuboverlay.c b/gst/dvbsuboverlay/gstdvbsuboverlay.c new file mode 100644 index 0000000000..a2157e9542 --- /dev/null +++ b/gst/dvbsuboverlay/gstdvbsuboverlay.c @@ -0,0 +1,1275 @@ +/* GStreamer DVB subtitles overlay + * Copyright (c) 2010 Mart Raudsepp + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/** + * SECTION:element-dvbsuboverlay + * + * Renders DVB subtitles on top of a video stream. + * + * + * Example launch line + * |[ FIXME + * gst-launch -v filesrc location=/path/to/ts ! mpegtsdemux name=d ! queue ! mp3parse ! mad ! audioconvert ! autoaudiosink \ + * d. ! queue ! mpeg2dec ! ffmpegcolorspace ! r. \ + * d. ! queue ! "private/x-dvbsub" ! dvbsuboverlay name=r ! ffmpegcolorspace ! autovideosink + * ]| This pipeline demuxes a MPEG-TS file with MPEG2 video, MP3 audio and embedded DVB subtitles and renders the subtitles on top of the video. + * + */ + + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "gstdvbsuboverlay.h" + +#include + +GST_DEBUG_CATEGORY_STATIC (gst_dvbsub_overlay_debug); +GST_DEBUG_CATEGORY_STATIC (gst_dvbsub_overlay_lib_debug); +#define GST_CAT_DEFAULT gst_dvbsub_overlay_debug + +/* Filter signals and props */ +enum +{ + LAST_SIGNAL +}; + +enum +{ + PROP_0, + PROP_ENABLE +}; + +static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ( +#ifdef DVBSUB_OVERLAY_RGB_SUPPORT + GST_VIDEO_CAPS_RGB ";" GST_VIDEO_CAPS_BGR ";" + GST_VIDEO_CAPS_xRGB ";" GST_VIDEO_CAPS_xBGR ";" + GST_VIDEO_CAPS_RGBx ";" GST_VIDEO_CAPS_BGRx ";" +#endif + GST_VIDEO_CAPS_YUV ("I420")) + ); + +static GstStaticPadTemplate video_sink_factory = + GST_STATIC_PAD_TEMPLATE ("video_sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ( +#ifdef DVBSUB_OVERLAY_RGB_SUPPORT + GST_VIDEO_CAPS_RGB ";" GST_VIDEO_CAPS_BGR ";" + GST_VIDEO_CAPS_xRGB ";" GST_VIDEO_CAPS_xBGR ";" + GST_VIDEO_CAPS_RGBx ";" GST_VIDEO_CAPS_BGRx ";" +#endif + GST_VIDEO_CAPS_YUV ("I420")) + ); + +static GstStaticPadTemplate text_sink_factory = +GST_STATIC_PAD_TEMPLATE ("text_sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("private/x-dvbsub") + ); + +static void gst_dvbsub_overlay_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_dvbsub_overlay_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +static void gst_dvbsub_overlay_finalize (GObject * object); + +#define GST_DVBSUB_OVERLAY_GET_COND(ov) (((GstDVBSubOverlay *)ov)->subtitle_cond) +#define GST_DVBSUB_OVERLAY_WAIT(ov) (g_cond_wait (GST_DVBSUB_OVERLAY_GET_COND (ov), GST_OBJECT_GET_LOCK (ov))) +#define GST_DVBSUB_OVERLAY_BROADCAST(ov) (g_cond_broadcast (GST_DVBSUB_OVERLAY_GET_COND (ov))) + +static GstStateChangeReturn gst_dvbsub_overlay_change_state (GstElement * + element, GstStateChange transition); + +GST_BOILERPLATE (GstDVBSubOverlay, gst_dvbsub_overlay, GstElement, + GST_TYPE_ELEMENT); + +static GstCaps *gst_dvbsub_overlay_getcaps (GstPad * pad); + +static gboolean gst_dvbsub_overlay_setcaps_video (GstPad * pad, GstCaps * caps); +static gboolean gst_dvbsub_overlay_setcaps_text (GstPad * pad, GstCaps * caps); + +static GstFlowReturn gst_dvbsub_overlay_chain_video (GstPad * pad, + GstBuffer * buf); +static GstFlowReturn gst_dvbsub_overlay_chain_text (GstPad * pad, + GstBuffer * buf); + +static gboolean gst_dvbsub_overlay_event_video (GstPad * pad, GstEvent * event); +static gboolean gst_dvbsub_overlay_event_text (GstPad * pad, GstEvent * event); +static gboolean gst_dvbsub_overlay_event_src (GstPad * pad, GstEvent * event); + +static void new_dvb_subtitles_cb (DvbSub * dvb_sub, guint64 pts, + DVBSubtitles * subs, guint8 page_time_out, gpointer user_data); + +static GstFlowReturn gst_dvbsub_overlay_bufferalloc_video (GstPad * pad, + guint64 offset, guint size, GstCaps * caps, GstBuffer ** buffer); + +static gboolean gst_dvbsub_overlay_query_src (GstPad * pad, GstQuery * query); + +static void +gst_dvbsub_overlay_base_init (gpointer gclass) +{ + GstElementClass *element_class = (GstElementClass *) gclass; + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&src_factory)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&video_sink_factory)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&text_sink_factory)); + + gst_element_class_set_details_simple (element_class, "DVB Subtitles Overlay", "Mixer/Video/Overlay/Subtitle", "Renders DVB subtitles", "Mart Raudsepp "); // FIXME: Credit assrender and textoverlay? +} + +/* initialize the plugin's class */ +static void +gst_dvbsub_overlay_class_init (GstDVBSubOverlayClass * klass) +{ + GObjectClass *gobject_class = (GObjectClass *) klass; + GstElementClass *gstelement_class = (GstElementClass *) klass; + + gobject_class->set_property = gst_dvbsub_overlay_set_property; + gobject_class->get_property = gst_dvbsub_overlay_get_property; + gobject_class->finalize = gst_dvbsub_overlay_finalize; + + g_object_class_install_property (gobject_class, PROP_ENABLE, g_param_spec_boolean ("enable", "Enable", /* FIXME: "enable" vs "silent"? */ + "Enable rendering of subtitles", TRUE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + gstelement_class->change_state = + GST_DEBUG_FUNCPTR (gst_dvbsub_overlay_change_state); +} + +static void +_dvbsub_log_cb (GLogLevelFlags level, const gchar * fmt, va_list args, + gpointer render) +{ + gchar *message = g_strdup_vprintf (fmt, args); + + if (level & G_LOG_LEVEL_ERROR) + GST_CAT_ERROR_OBJECT (gst_dvbsub_overlay_lib_debug, render, "%s", message); + else if (level & G_LOG_LEVEL_WARNING) + GST_CAT_WARNING_OBJECT (gst_dvbsub_overlay_lib_debug, render, "%s", + message); + else if (level & G_LOG_LEVEL_INFO) + GST_CAT_INFO_OBJECT (gst_dvbsub_overlay_lib_debug, render, "%s", message); + else if (level & G_LOG_LEVEL_DEBUG) + GST_CAT_DEBUG_OBJECT (gst_dvbsub_overlay_lib_debug, render, "%s", message); + else + GST_CAT_LOG_OBJECT (gst_dvbsub_overlay_lib_debug, render, + "log level %d: %s", level, message); + + g_free (message); +} + +static void +gst_dvbsub_overlay_init (GstDVBSubOverlay * render, + GstDVBSubOverlayClass * gclass) +{ + GST_DEBUG_OBJECT (render, "init"); + + render->srcpad = gst_pad_new_from_static_template (&src_factory, "src"); + render->video_sinkpad = + gst_pad_new_from_static_template (&video_sink_factory, "video_sink"); + render->text_sinkpad = + gst_pad_new_from_static_template (&text_sink_factory, "text_sink"); + + gst_pad_set_setcaps_function (render->video_sinkpad, + GST_DEBUG_FUNCPTR (gst_dvbsub_overlay_setcaps_video)); + gst_pad_set_setcaps_function (render->text_sinkpad, + GST_DEBUG_FUNCPTR (gst_dvbsub_overlay_setcaps_text)); + + gst_pad_set_getcaps_function (render->srcpad, + GST_DEBUG_FUNCPTR (gst_dvbsub_overlay_getcaps)); + gst_pad_set_getcaps_function (render->video_sinkpad, + GST_DEBUG_FUNCPTR (gst_dvbsub_overlay_getcaps)); + + gst_pad_set_chain_function (render->video_sinkpad, + GST_DEBUG_FUNCPTR (gst_dvbsub_overlay_chain_video)); + gst_pad_set_chain_function (render->text_sinkpad, + GST_DEBUG_FUNCPTR (gst_dvbsub_overlay_chain_text)); + + gst_pad_set_event_function (render->video_sinkpad, + GST_DEBUG_FUNCPTR (gst_dvbsub_overlay_event_video)); + gst_pad_set_event_function (render->text_sinkpad, + GST_DEBUG_FUNCPTR (gst_dvbsub_overlay_event_text)); + gst_pad_set_event_function (render->srcpad, + GST_DEBUG_FUNCPTR (gst_dvbsub_overlay_event_src)); + + gst_pad_set_bufferalloc_function (render->video_sinkpad, + GST_DEBUG_FUNCPTR (gst_dvbsub_overlay_bufferalloc_video)); + + gst_pad_set_query_function (render->srcpad, + GST_DEBUG_FUNCPTR (gst_dvbsub_overlay_query_src)); + + gst_element_add_pad (GST_ELEMENT (render), render->srcpad); + gst_element_add_pad (GST_ELEMENT (render), render->video_sinkpad); + gst_element_add_pad (GST_ELEMENT (render), render->text_sinkpad); + + render->width = 0; + render->height = 0; + + render->subtitle_mutex = g_mutex_new (); + render->subtitle_cond = g_cond_new (); + + render->renderer_init_ok = FALSE; + render->enable = TRUE; + + gst_segment_init (&render->video_segment, GST_FORMAT_TIME); + gst_segment_init (&render->subtitle_segment, GST_FORMAT_TIME); + + render->dvbsub_mutex = g_mutex_new (); + + dvb_sub_set_global_log_cb (_dvbsub_log_cb, render); + + + render->dvb_sub = dvb_sub_new (); + if (!render->dvb_sub) { + GST_WARNING_OBJECT (render, "cannot create dvbsub instance"); + g_assert_not_reached (); + } + + { + DvbSubCallbacks dvbsub_callbacks = { &new_dvb_subtitles_cb, }; + dvb_sub_set_callbacks (render->dvb_sub, &dvbsub_callbacks, render); + } + + GST_DEBUG_OBJECT (render, "init complete"); +} + +static void +gst_dvbsub_overlay_finalize (GObject * object) +{ + GstDVBSubOverlay *overlay = GST_DVBSUB_OVERLAY (object); + + if (overlay->subtitle_mutex) + g_mutex_free (overlay->subtitle_mutex); + + if (overlay->subtitle_cond) + g_cond_free (overlay->subtitle_cond); + + if (overlay->dvb_sub) { + g_object_unref (overlay->dvb_sub); + } + + if (overlay->dvbsub_mutex) + g_mutex_free (overlay->dvbsub_mutex); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +gst_dvbsub_overlay_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstDVBSubOverlay *overlay = GST_DVBSUB_OVERLAY (object); + + switch (prop_id) { + case PROP_ENABLE: + overlay->enable = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_dvbsub_overlay_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstDVBSubOverlay *overlay = GST_DVBSUB_OVERLAY (object); + + switch (prop_id) { + case PROP_ENABLE: + g_value_set_boolean (value, overlay->enable); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static GstStateChangeReturn +gst_dvbsub_overlay_change_state (GstElement * element, + GstStateChange transition) +{ + GstDVBSubOverlay *render = GST_DVBSUB_OVERLAY (element); + GstStateChangeReturn ret; + + switch (transition) { + case GST_STATE_CHANGE_READY_TO_PAUSED: + render->subtitle_flushing = FALSE; + gst_segment_init (&render->video_segment, GST_FORMAT_TIME); + gst_segment_init (&render->subtitle_segment, GST_FORMAT_TIME); + break; + case GST_STATE_CHANGE_NULL_TO_READY: + case GST_STATE_CHANGE_PAUSED_TO_PLAYING: + default: + break; + + case GST_STATE_CHANGE_PAUSED_TO_READY: + g_mutex_lock (render->subtitle_mutex); + render->subtitle_flushing = TRUE; + if (render->subtitle_pending) + gst_buffer_unref (render->subtitle_pending); + render->subtitle_pending = NULL; + g_cond_signal (render->subtitle_cond); + g_mutex_unlock (render->subtitle_mutex); + break; + } + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + + switch (transition) { + case GST_STATE_CHANGE_PAUSED_TO_READY: + render->renderer_init_ok = FALSE; + break; + case GST_STATE_CHANGE_PLAYING_TO_PAUSED: + case GST_STATE_CHANGE_READY_TO_NULL: + default: + break; + } + + + return ret; +} + +static gboolean +gst_dvbsub_overlay_query_src (GstPad * pad, GstQuery * query) +{ + GstDVBSubOverlay *render = GST_DVBSUB_OVERLAY (gst_pad_get_parent (pad)); + gboolean ret; + + ret = gst_pad_peer_query (render->video_sinkpad, query); + + gst_object_unref (render); + return ret; +} + +static gboolean +gst_dvbsub_overlay_event_src (GstPad * pad, GstEvent * event) +{ + GstDVBSubOverlay *render = GST_DVBSUB_OVERLAY (gst_pad_get_parent (pad)); + gboolean ret = FALSE; + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_SEEK:{ + GstSeekFlags flags; + + GST_DEBUG_OBJECT (render, "seek received, driving from here"); + + gst_event_parse_seek (event, NULL, NULL, &flags, NULL, NULL, NULL, NULL); + + /* Flush downstream, only for flushing seek */ + if (flags & GST_SEEK_FLAG_FLUSH) + gst_pad_push_event (render->srcpad, gst_event_new_flush_start ()); + + /* Mark subtitle as flushing, unblocks chains */ + g_mutex_lock (render->subtitle_mutex); + if (render->subtitle_pending) + gst_buffer_unref (render->subtitle_pending); + render->subtitle_pending = NULL; + render->subtitle_flushing = TRUE; + g_cond_signal (render->subtitle_cond); + g_mutex_unlock (render->subtitle_mutex); + + /* Seek on each sink pad */ + gst_event_ref (event); + ret = gst_pad_push_event (render->video_sinkpad, event); + if (ret) { + ret = gst_pad_push_event (render->text_sinkpad, event); + } else { + gst_event_unref (event); + } + break; + } + default: + gst_event_ref (event); + ret = gst_pad_push_event (render->video_sinkpad, event); + gst_pad_push_event (render->text_sinkpad, event); + break; + } + + gst_object_unref (render); + + return ret; +} + +static GstCaps * +gst_dvbsub_overlay_getcaps (GstPad * pad) +{ + GstDVBSubOverlay *render = GST_DVBSUB_OVERLAY (gst_pad_get_parent (pad)); + GstPad *otherpad; + GstCaps *caps; + + if (pad == render->srcpad) + otherpad = render->video_sinkpad; + else + otherpad = render->srcpad; + + /* we can do what the peer can */ + caps = gst_pad_peer_get_caps (otherpad); + if (caps) { + GstCaps *temp; + const GstCaps *templ; + + /* filtered against our padtemplate */ + templ = gst_pad_get_pad_template_caps (otherpad); + temp = gst_caps_intersect (caps, templ); + gst_caps_unref (caps); + /* this is what we can do */ + caps = temp; + } else { + /* no peer, our padtemplate is enough then */ + caps = gst_caps_copy (gst_pad_get_pad_template_caps (pad)); + } + + gst_object_unref (render); + + return caps; +} + +#ifdef DVBSUB_OVERLAY_RGB_SUPPORT + +#define CREATE_RGB_BLIT_FUNCTION(name,bpp,R,G,B) \ +static void \ +blit_##name (GstDVBSubOverlay * overlay, DVBSubtitles * subs, GstBuffer * buffer) \ +{ \ + guint counter; \ + DVBSubtitleRect *sub_region; \ + gint alpha, r, g, b, k; \ + guint32 color; \ + const guint8 *src; \ + guint8 *dst; \ + gint x, y, w, h; \ + gint width = overlay->width; \ + gint height = overlay->height; \ + gint dst_stride = GST_ROUND_UP_4 (width * bpp); \ + gint dst_skip; \ + gint src_stride, src_skip; \ + \ + for (counter = 0; counter < subs->num_rects; counter++) { \ + sub_region = subs->rects[counter]; \ + if (sub_region->y > height || sub_region->x > width) \ + continue; \ + \ + /* blend subtitles onto the video frame */ \ + src = sub_region->pict.data; \ + dst = buffer->data + sub_region->y * dst_stride + sub_region->x * bpp; \ + \ + w = MIN (sub_region->w, width - sub_region->x); \ + h = MIN (sub_region->h, height - sub_region->y); \ + src_stride = sub_region->pict.rowstride; \ + src_skip = sub_region->pict.rowstride - w; \ + dst_skip = dst_stride - w * bpp; \ + \ + for (y = 0; y < h; y++) { \ + for (x = 0; x < w; x++) { \ + color = sub_region->pict.palette[src[0]]; \ + alpha = 255 - (color & 0xff); /* FIXME: We get ARGB, not RGBA as assumed here */ \ + r = (color >> 24) & 0xff; \ + g = (color >> 16) & 0xff; \ + b = (color >> 8) & 0xff; \ + k = color * alpha / 255; /* FIXME */ \ + dst[R] = (k * r + (255 - k) * dst[R]) / 255; \ + dst[G] = (k * g + (255 - k) * dst[G]) / 255; \ + dst[B] = (k * b + (255 - k) * dst[B]) / 255; \ + src++; \ + dst += bpp; \ + } \ + src += src_skip; \ + dst += dst_skip; \ + } \ + } \ + GST_LOG_OBJECT (overlay, "amount of rendered DVBSubtitleRect: %u", counter); \ +} + +CREATE_RGB_BLIT_FUNCTION (rgb, 3, 0, 1, 2); +CREATE_RGB_BLIT_FUNCTION (bgr, 3, 2, 1, 0); +CREATE_RGB_BLIT_FUNCTION (xrgb, 4, 1, 2, 3); +CREATE_RGB_BLIT_FUNCTION (xbgr, 4, 3, 2, 1); +CREATE_RGB_BLIT_FUNCTION (rgbx, 4, 0, 1, 2); +CREATE_RGB_BLIT_FUNCTION (bgrx, 4, 2, 1, 0); + +#undef CREATE_RGB_BLIT_FUNCTION + +#endif + +static inline gint +rgb_to_y (gint r, gint g, gint b) +{ + gint ret; + + ret = (gint) (((19595 * r) >> 16) + ((38470 * g) >> 16) + ((7471 * b) >> 16)); + ret = CLAMP (ret, 0, 255); + return ret; +} + +static inline gint +rgb_to_u (gint r, gint g, gint b) +{ + gint ret; + + ret = + (gint) (-((11059 * r) >> 16) - ((21709 * g) >> 16) + ((32768 * b) >> 16) + + 128); + ret = CLAMP (ret, 0, 255); + return ret; +} + +static inline gint +rgb_to_v (gint r, gint g, gint b) +{ + gint ret; + + ret = + (gint) (((32768 * r) >> 16) - ((27439 * g) >> 16) - ((5329 * b) >> 16) + + 128); + ret = CLAMP (ret, 0, 255); + return ret; +} + +/* FIXME: DVB-SUB actually provides us AYUV from CLUT, but libdvbsub used to convert it to ARGB */ +static void +blit_i420 (GstDVBSubOverlay * overlay, DVBSubtitles * subs, GstBuffer * buffer) +{ + guint counter; + DVBSubtitleRect *sub_region; + gint alpha, r, g, b, k, k2; + gint Y, U, V; + guint32 color, color2; + const guint8 *src; + guint8 *dst_y, *dst_u, *dst_v; + gint x, y, w, h; + gint w2, h2; + gint width = overlay->width; + gint height = overlay->height; + gint src_stride; + gint y_offset, y_height, y_width, y_stride; + gint u_offset, u_height, u_width, u_stride; + gint v_offset, v_height, v_width, v_stride; + + y_offset = + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_I420, 0, width, + height); + u_offset = + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_I420, 1, width, + height); + v_offset = + gst_video_format_get_component_offset (GST_VIDEO_FORMAT_I420, 2, width, + height); + + y_height = + gst_video_format_get_component_height (GST_VIDEO_FORMAT_I420, 0, height); + u_height = + gst_video_format_get_component_height (GST_VIDEO_FORMAT_I420, 1, height); + v_height = + gst_video_format_get_component_height (GST_VIDEO_FORMAT_I420, 2, height); + + y_width = + gst_video_format_get_component_width (GST_VIDEO_FORMAT_I420, 0, width); + u_width = + gst_video_format_get_component_width (GST_VIDEO_FORMAT_I420, 1, width); + v_width = + gst_video_format_get_component_width (GST_VIDEO_FORMAT_I420, 2, width); + + y_stride = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_I420, 0, width); + u_stride = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_I420, 1, width); + v_stride = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_I420, 2, width); + + for (counter = 0; counter < subs->num_rects; counter++) { + sub_region = subs->rects[counter]; + if (sub_region->y > height || sub_region->x > width) + continue; + + /* blend subtitles onto the video frame */ + w = MIN (sub_region->w, width - sub_region->x); + h = MIN (sub_region->h, height - sub_region->y); + + w2 = (w + 1) / 2; + h2 = (h + 1) / 2; + + src_stride = sub_region->pict.rowstride; + + src = sub_region->pict.data; + dst_y = buffer->data + y_offset + sub_region->y * y_stride + sub_region->x; + dst_u = + buffer->data + u_offset + ((sub_region->y + 1) / 2) * u_stride + + (sub_region->x + 1) / 2; + dst_v = + buffer->data + v_offset + ((sub_region->y + 1) / 2) * v_stride + + (sub_region->x + 1) / 2; + + for (y = 0; y < h - 1; y += 2) { + for (x = 0; x < w - 1; x += 2) { + /* FIXME: Completely wrong blending code */ + color = sub_region->pict.palette[src[0]]; + color2 = sub_region->pict.palette[src[1]]; + alpha = 255 - (color & 0xff); + r = (color >> 24) & 0xff; + g = (color >> 16) & 0xff; + b = (color >> 8) & 0xff; + + Y = rgb_to_y (r, g, b); + U = rgb_to_u (r, g, b); + V = rgb_to_v (r, g, b); + + k = src[0] * alpha / 255; + k2 = k; + dst_y[0] = (k * Y + (255 - k) * dst_y[0]) / 255; + + k = src[1] * alpha / 255; + k2 += k; + dst_y[1] = (k * Y + (255 - k) * dst_y[1]) / 255; + + src += src_stride; + dst_y += y_stride; + + k = src[0] * alpha / 255; + k2 += k; + dst_y[0] = (k * Y + (255 - k) * dst_y[0]) / 255; + + k = src[1] * alpha / 255; + k2 += k; + dst_y[1] = (k * Y + (255 - k) * dst_y[1]) / 255; + + k2 /= 4; + dst_u[0] = (k2 * U + (255 - k2) * dst_u[0]) / 255; + dst_v[0] = (k2 * V + (255 - k2) * dst_v[0]) / 255; + dst_u++; + dst_v++; + + src += -src_stride + 2; + dst_y += -y_stride + 2; + } + + if (x < w) { + /* FIXME: Completely wrong blending code */ + color = sub_region->pict.palette[src[0]]; + color2 = sub_region->pict.palette[src[1]]; + alpha = 255 - (color & 0xff); + r = (color >> 24) & 0xff; + g = (color >> 16) & 0xff; + b = (color >> 8) & 0xff; + + Y = rgb_to_y (r, g, b); + U = rgb_to_u (r, g, b); + V = rgb_to_v (r, g, b); + + k = src[0] * alpha / 255; + k2 = k; + dst_y[0] = (k * Y + (255 - k) * dst_y[0]) / 255; + + src += src_stride; + dst_y += y_stride; + + k = src[0] * alpha / 255; + k2 += k; + dst_y[0] = (k * Y + (255 - k) * dst_y[0]) / 255; + + k2 /= 2; + dst_u[0] = (k2 * U + (255 - k2) * dst_u[0]) / 255; + dst_v[0] = (k2 * V + (255 - k2) * dst_v[0]) / 255; + dst_u++; + dst_v++; + + src += -src_stride + 1; + dst_y += -y_stride + 1; + } + + src += src_stride + (src_stride - w); + dst_y += y_stride + (y_stride - w); + dst_u += u_stride - w2; + dst_v += v_stride - w2; + } + + if (y < h) { + for (x = 0; x < w - 1; x += 2) { + /* FIXME: Completely wrong blending code */ + color = sub_region->pict.palette[src[0]]; + color2 = sub_region->pict.palette[src[1]]; + alpha = 255 - (color & 0xff); + r = (color >> 24) & 0xff; + g = (color >> 16) & 0xff; + b = (color >> 8) & 0xff; + + Y = rgb_to_y (r, g, b); + U = rgb_to_u (r, g, b); + V = rgb_to_v (r, g, b); + + k = src[0] * alpha / 255; + k2 = k; + dst_y[0] = (k * Y + (255 - k) * dst_y[0]) / 255; + + k = src[1] * alpha / 255; + k2 += k; + dst_y[1] = (k * Y + (255 - k) * dst_y[1]) / 255; + + k2 /= 2; + dst_u[0] = (k2 * U + (255 - k2) * dst_u[0]) / 255; + dst_v[0] = (k2 * V + (255 - k2) * dst_v[0]) / 255; + dst_u++; + dst_v++; + + src += 2; + dst_y += 2; + } + + if (x < w) { + /* FIXME: Completely wrong blending code */ + color = sub_region->pict.palette[src[0]]; + color2 = sub_region->pict.palette[src[1]]; + alpha = 255 - (color & 0xff); + r = (color >> 24) & 0xff; + g = (color >> 16) & 0xff; + b = (color >> 8) & 0xff; + + Y = rgb_to_y (r, g, b); + U = rgb_to_u (r, g, b); + V = rgb_to_v (r, g, b); + + k = src[0] * alpha / 255; + k2 = k; + dst_y[0] = (k * Y + (255 - k) * dst_y[0]) / 255; + + dst_u[0] = (k2 * U + (255 - k2) * dst_u[0]) / 255; + dst_v[0] = (k2 * V + (255 - k2) * dst_v[0]) / 255; + } + } + } + + GST_LOG_OBJECT (overlay, "amount of rendered DVBSubtitleRect: %u", counter); +} + +static gboolean +gst_dvbsub_overlay_setcaps_video (GstPad * pad, GstCaps * caps) +{ + GstDVBSubOverlay *render = GST_DVBSUB_OVERLAY (gst_pad_get_parent (pad)); + gboolean ret = FALSE; + gint par_n = 1, par_d = 1; + gdouble dar; + + render->width = 0; + render->height = 0; + + if (!gst_video_format_parse_caps (caps, &render->format, &render->width, + &render->height) || + !gst_video_parse_caps_framerate (caps, &render->fps_n, &render->fps_d)) { + GST_ERROR_OBJECT (render, "Can't parse caps: %" GST_PTR_FORMAT, caps); + ret = FALSE; + goto out; + } + + gst_video_parse_caps_pixel_aspect_ratio (caps, &par_n, &par_d); + + ret = gst_pad_set_caps (render->srcpad, caps); + if (!ret) + goto out; + + switch (render->format) { +#ifdef DVBSUB_OVERLAY_RGB_SUPPORT + case GST_VIDEO_FORMAT_RGB: + render->blit = blit_rgb; + break; + case GST_VIDEO_FORMAT_BGR: + render->blit = blit_bgr; + break; + case GST_VIDEO_FORMAT_xRGB: + render->blit = blit_xrgb; + break; + case GST_VIDEO_FORMAT_xBGR: + render->blit = blit_xbgr; + break; + case GST_VIDEO_FORMAT_RGBx: + render->blit = blit_rgbx; + break; + case GST_VIDEO_FORMAT_BGRx: + render->blit = blit_bgrx; + break; +#endif + case GST_VIDEO_FORMAT_I420: + render->blit = blit_i420; + break; + default: + ret = FALSE; + goto out; + } + + /* FIXME: We need to handle aspect ratio ourselves */ +#if 0 + g_mutex_lock (render->ass_mutex); + ass_set_frame_size (render->ass_renderer, render->width, render->height); +#endif + dar = (((gdouble) par_n) * ((gdouble) render->width)) + / (((gdouble) par_d) * ((gdouble) render->height)); +#if 0 + ass_set_aspect_ratio (render->ass_renderer, + dar, ((gdouble) render->width) / ((gdouble) render->height)); + + g_mutex_unlock (render->ass_mutex); +#endif + + render->renderer_init_ok = TRUE; + + GST_DEBUG_OBJECT (render, "ass renderer setup complete"); + +out: + gst_object_unref (render); + + return ret; +} + +static gboolean +gst_dvbsub_overlay_setcaps_text (GstPad * pad, GstCaps * caps) +{ + GstDVBSubOverlay *render = GST_DVBSUB_OVERLAY (gst_pad_get_parent (pad)); + GstStructure *structure; + const GValue *value; +#if 0 // FIXME + GstBuffer *priv; + gchar *codec_private; + guint codec_private_size; +#endif + gboolean ret = FALSE; + + structure = gst_caps_get_structure (caps, 0); + + GST_DEBUG_OBJECT (render, "text pad linked with caps: %" GST_PTR_FORMAT, + caps); + + value = gst_structure_get_value (structure, "codec_data"); + + /* FIXME: */ +#if 0 + g_mutex_lock (render->ass_mutex); + if (value != NULL) { + priv = gst_value_get_buffer (value); + g_return_val_if_fail (priv != NULL, FALSE); + + codec_private = (gchar *) GST_BUFFER_DATA (priv); + codec_private_size = GST_BUFFER_SIZE (priv); + + if (!render->ass_track) + render->ass_track = ass_new_track (render->ass_library); + + ass_process_codec_private (render->ass_track, + codec_private, codec_private_size); + + GST_DEBUG_OBJECT (render, "ass track created"); + + render->track_init_ok = TRUE; + + ret = TRUE; + } else if (!render->ass_track) { + render->ass_track = ass_new_track (render->ass_library); + + render->track_init_ok = TRUE; + + ret = TRUE; + } + g_mutex_unlock (render->ass_mutex); +#endif + + gst_object_unref (render); + + // FIXME + ret = TRUE; + + return ret; +} + +#define CLOCK_BASE 9LL +#define GSTTIME_TO_MPEGTIME(time) (gst_util_uint64_scale ((time), \ + CLOCK_BASE, GST_MSECOND/10)) + +static void +gst_dvbsub_overlay_process_text (GstDVBSubOverlay * overlay, GstBuffer * buffer) +{ + /* FIXME: Locking in this function */ + guint8 *data = (guint8 *) GST_BUFFER_DATA (buffer); + guint size = GST_BUFFER_SIZE (buffer); + guint64 pts = GSTTIME_TO_MPEGTIME (GST_BUFFER_TIMESTAMP (buffer)); + + GST_DEBUG_OBJECT (overlay, + "Processing subtitles with running time %" GST_TIME_FORMAT + " which is PTS=%" G_GUINT64_FORMAT, + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)), pts); + GST_DEBUG_OBJECT (overlay, "Feeding %u bytes to libdvbsub", size); + g_mutex_lock (overlay->dvbsub_mutex); /* FIXME: Use standard lock? */ + dvb_sub_feed_with_pts (overlay->dvb_sub, pts, data, size); + g_mutex_unlock (overlay->dvbsub_mutex); + gst_buffer_unref (buffer); +} + +static void +new_dvb_subtitles_cb (DvbSub * dvb_sub, guint64 pts, DVBSubtitles * subs, + guint8 page_time_out, gpointer user_data) +{ + GstDVBSubOverlay *overlay = GST_DVBSUB_OVERLAY (user_data); + GST_INFO_OBJECT (overlay, + "New DVB subtitles arrived with a page_time_out of %d and %d regions for PTS=%" + G_GUINT64_FORMAT "\n", page_time_out, subs->num_rects, pts); + //GST_OBJECT_LOCK (overlay); + overlay->subtitle_buffer = subs->num_rects; + //GST_OBJECT_UNLOCK (overlay); +} + +static GstFlowReturn +gst_dvbsub_overlay_bufferalloc_video (GstPad * pad, guint64 offset, guint size, + GstCaps * caps, GstBuffer ** buffer) +{ + GstDVBSubOverlay *render = GST_DVBSUB_OVERLAY (gst_pad_get_parent (pad)); + GstFlowReturn ret = GST_FLOW_WRONG_STATE; + GstPad *allocpad; + + GST_OBJECT_LOCK (render); + allocpad = render->srcpad ? gst_object_ref (render->srcpad) : NULL; + GST_OBJECT_UNLOCK (render); + + if (allocpad) { + ret = gst_pad_alloc_buffer (allocpad, offset, size, caps, buffer); + gst_object_unref (allocpad); + } + + gst_object_unref (render); + + return ret; +} + +static GstFlowReturn +gst_dvbsub_overlay_chain_text (GstPad * pad, GstBuffer * buffer) +{ + GstDVBSubOverlay *overlay = GST_DVBSUB_OVERLAY (GST_PAD_PARENT (pad)); + gint64 clip_start = 0, clip_stop = 0; + gboolean in_seg = FALSE; + + GST_INFO_OBJECT (overlay, "private/x-dvbsub buffer with size %u", + GST_BUFFER_SIZE (buffer)); + + GST_OBJECT_LOCK (overlay); + + if (overlay->subtitle_flushing) { + GST_OBJECT_UNLOCK (overlay); + GST_LOG_OBJECT (overlay, "text flushing"); + return GST_FLOW_WRONG_STATE; + } + + if (overlay->subtitle_eos) { + GST_OBJECT_UNLOCK (overlay); + GST_LOG_OBJECT (overlay, "text EOS"); + return GST_FLOW_UNEXPECTED; + } + + GST_LOG_OBJECT (overlay, + "Video segment: %" GST_SEGMENT_FORMAT " --- Subtitle segment: %" + GST_SEGMENT_FORMAT " --- BUFFER: ts=%" GST_TIME_FORMAT " -- PTS: %" + G_GUINT64_FORMAT, &overlay->video_segment, &overlay->subtitle_segment, + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)), + GSTTIME_TO_MPEGTIME (GST_BUFFER_TIMESTAMP (buffer))); + + /* DVB subtitle packets are required to carry the PTS */ + if (G_UNLIKELY (!GST_BUFFER_TIMESTAMP_IS_VALID (buffer))) { + GST_OBJECT_UNLOCK (overlay); + GST_WARNING_OBJECT (overlay, + "Text buffer without valid timestamp, dropping"); + gst_buffer_unref (buffer); + return GST_FLOW_OK; + } + + /* FIXME: Is the faking of a zero duration buffer correct here? Probably a better way to check segment inclusion then than to clip as a side effect */ + in_seg = gst_segment_clip (&overlay->subtitle_segment, GST_FORMAT_TIME, + GST_BUFFER_TIMESTAMP (buffer), GST_BUFFER_TIMESTAMP (buffer), &clip_start, + &clip_stop); + + /* As the passed start and stop is equal, we shouldn't need to care about out of segment at all, + * the subtitle data for the PTS is completely out of interest to us. A given display set must + * carry the same PTS value. */ + /* FIXME: Consider with larger than 64kB display sets, which would be cut into multiple packets, + * FIXME: does our waiting + render code work when there are more than one packets before + * FIXME: rendering callback will get called? */ + + if (!in_seg) { + GST_DEBUG_OBJECT (overlay, + "Subtitle timestamp (%" GST_TIME_FORMAT + ") outside of the subtitle segment (%" GST_SEGMENT_FORMAT "), dropping", + GST_BUFFER_TIMESTAMP (buffer), &overlay->subtitle_segment); + gst_buffer_unref (buffer); + return GST_FLOW_OK; + } +#if 0 /* In case of DVB-SUB, we get notified of the shown subtitle going away by the next + * page composition, so we can't just wait for the buffer to go away (unless we keep + * non-rendered raw DVBSubtitleRects or DVBSubtitlePicture in there, which is + * suboptimal */ + /* Wait for the previous buffer to go away */ + while (overlay->subtitle_buffer > 0) { + GST_DEBUG ("Pad %s:%s has a buffer queued, waiting", + GST_DEBUG_PAD_NAME (pad)); + GST_DVBSUB_OVERLAY_WAIT (overlay); + GST_DEBUG ("Pad %s:%s resuming", GST_DEBUG_PAD_NAME (pad)); + if (overlay->subtitle_flushing) { + GST_OBJECT_UNLOCK (overlay); + /* FIXME: No need to unref buffer? */ + return GST_FLOW_WRONG_STATE; + } + } +#endif + + /* FIXME: How is this useful? */ + gst_segment_set_last_stop (&overlay->subtitle_segment, GST_FORMAT_TIME, + clip_start); + + overlay->subtitle_buffer = 0; /*buffer FIXME: Need to do buffering elsewhere */ + + /* That's a new text buffer we need to render */ + /*overlay->need_render = TRUE; *//* FIXME: Actually feed it to libdvbsub and set need_render on a callback */ + + gst_dvbsub_overlay_process_text (overlay, buffer); + + /* in case the video chain is waiting for a text buffer, wake it up */ + GST_DVBSUB_OVERLAY_BROADCAST (overlay); + + GST_OBJECT_UNLOCK (overlay); + + return GST_FLOW_OK; +} + +static GstFlowReturn +gst_dvbsub_overlay_chain_video (GstPad * pad, GstBuffer * buffer) +{ + GstDVBSubOverlay *overlay = GST_DVBSUB_OVERLAY (GST_PAD_PARENT (pad)); + GstFlowReturn ret = GST_FLOW_OK; + gint64 start, stop; + + if (!GST_BUFFER_TIMESTAMP_IS_VALID (buffer)) + goto missing_timestamp; + + start = GST_BUFFER_TIMESTAMP (buffer); + + GST_LOG_OBJECT (overlay, + "Video last_stop: %" GST_TIME_FORMAT " --- Subtitle last_stop: %" + GST_TIME_FORMAT " --- BUFFER: ts=%" GST_TIME_FORMAT " -- PTS: %" + G_GUINT64_FORMAT, &overlay->video_segment.last_stop, + &overlay->subtitle_segment.last_stop, GST_TIME_ARGS (start), + GSTTIME_TO_MPEGTIME (start)); + + /* ignore buffers that are outside of the current segment */ + if (!GST_BUFFER_DURATION_IS_VALID (buffer)) { + stop = GST_CLOCK_TIME_NONE; + } else { + stop = start + GST_BUFFER_DURATION (buffer); + } + + /* FIXME: Probably update last_stop somewhere */ + + /* FIXME: Segment clipping code */ + + if (overlay->subtitle_buffer > 0) { + GST_DEBUG_OBJECT (overlay, "Should be rendering %u regions", + overlay->subtitle_buffer); + } + + ret = gst_pad_push (overlay->srcpad, buffer); + + return ret; + +missing_timestamp: + { + GST_WARNING_OBJECT (overlay, "video buffer without timestamp, discarding"); + gst_buffer_unref (buffer); + return GST_FLOW_OK; + } +} + +static gboolean +gst_dvbsub_overlay_event_video (GstPad * pad, GstEvent * event) +{ + gboolean ret = FALSE; + GstDVBSubOverlay *render = GST_DVBSUB_OVERLAY (gst_pad_get_parent (pad)); + + GST_DEBUG_OBJECT (pad, "received video event %s", + GST_EVENT_TYPE_NAME (event)); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_NEWSEGMENT: + { + GstFormat format; + gdouble rate; + gint64 start, stop, time; + gboolean update; + + GST_DEBUG_OBJECT (render, "received new segment"); + + gst_event_parse_new_segment (event, &update, &rate, &format, &start, + &stop, &time); + + if (format == GST_FORMAT_TIME) { + GST_DEBUG_OBJECT (render, "VIDEO SEGMENT now: %" GST_SEGMENT_FORMAT, + &render->video_segment); + + gst_segment_set_newsegment (&render->video_segment, update, rate, + format, start, stop, time); + + GST_DEBUG_OBJECT (render, "VIDEO SEGMENT after: %" GST_SEGMENT_FORMAT, + &render->video_segment); + ret = gst_pad_push_event (render->srcpad, event); + } else { + GST_ELEMENT_WARNING (render, STREAM, MUX, (NULL), + ("received non-TIME newsegment event on video input")); + ret = FALSE; + gst_event_unref (event); + } + break; + } + case GST_EVENT_FLUSH_STOP: + gst_segment_init (&render->video_segment, GST_FORMAT_TIME); + default: + ret = gst_pad_push_event (render->srcpad, event); + break; + } + + gst_object_unref (render); + + return ret; +} + +static gboolean +gst_dvbsub_overlay_event_text (GstPad * pad, GstEvent * event) +{ + //gint i; // FIXME + gboolean ret = FALSE; + GstDVBSubOverlay *render = GST_DVBSUB_OVERLAY (gst_pad_get_parent (pad)); + + GST_DEBUG_OBJECT (pad, "received text event %s", GST_EVENT_TYPE_NAME (event)); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_NEWSEGMENT: + { + GstFormat format; + gdouble rate; + gint64 start, stop, time; + gboolean update; + + GST_DEBUG_OBJECT (render, "received new segment"); + + /* FIXME: overlay */ render->subtitle_eos = FALSE; + + gst_event_parse_new_segment (event, &update, &rate, &format, &start, + &stop, &time); + + if (format == GST_FORMAT_TIME) { + GST_DEBUG_OBJECT (render, "SUBTITLE SEGMENT now: %" GST_SEGMENT_FORMAT, + &render->subtitle_segment); + + gst_segment_set_newsegment (&render->subtitle_segment, update, rate, + format, start, stop, time); + + GST_DEBUG_OBJECT (render, + "SUBTITLE SEGMENT after: %" GST_SEGMENT_FORMAT, + &render->subtitle_segment); + ret = TRUE; + gst_event_unref (event); + } else { + GST_ELEMENT_WARNING (render, STREAM, MUX, (NULL), + ("received non-TIME newsegment event on subtitle input")); + ret = FALSE; + gst_event_unref (event); + } + /* FIXME: Not fully compared with textoverlay */ + GST_OBJECT_LOCK (render); + GST_DVBSUB_OVERLAY_BROADCAST (render); + GST_OBJECT_UNLOCK (render); + break; + } + case GST_EVENT_FLUSH_STOP: + gst_segment_init (&render->subtitle_segment, GST_FORMAT_TIME); + render->subtitle_flushing = FALSE; + /*FIXME: overlay */ render->subtitle_eos = FALSE; + gst_event_unref (event); + ret = TRUE; + break; + case GST_EVENT_FLUSH_START: + GST_DEBUG_OBJECT (render, "begin flushing"); +#if 0 // FIXME + g_mutex_lock (render->ass_mutex); + if (render->ass_track) { + /* delete any events on the ass_track */ + for (i = 0; i < render->ass_track->n_events; i++) { + GST_DEBUG_OBJECT (render, "deleted event with eid %i", i); + ass_free_event (render->ass_track, i); + } + render->ass_track->n_events = 0; + GST_DEBUG_OBJECT (render, "done flushing"); + } + g_mutex_unlock (render->ass_mutex); +#endif + g_mutex_lock (render->subtitle_mutex); + if (render->subtitle_pending) + gst_buffer_unref (render->subtitle_pending); + render->subtitle_pending = NULL; + render->subtitle_flushing = TRUE; + GST_DVBSUB_OVERLAY_BROADCAST (render); + g_mutex_unlock (render->subtitle_mutex); + gst_event_unref (event); + ret = TRUE; + break; + case GST_EVENT_EOS: + GST_OBJECT_LOCK (render); + /*FIXME: overlay */ render->subtitle_eos = TRUE; + GST_INFO_OBJECT (render, "text EOS"); + /* wake up the video chain, it might be waiting for a text buffer or + * a text segment update */ + GST_DVBSUB_OVERLAY_BROADCAST (render); + GST_OBJECT_UNLOCK (render); + gst_event_unref (event); + ret = TRUE; + break; + default: + ret = gst_pad_push_event (render->srcpad, event); + break; + } + + gst_object_unref (render); + + return ret; +} + +static gboolean +plugin_init (GstPlugin * plugin) +{ + GST_DEBUG_CATEGORY_INIT (gst_dvbsub_overlay_debug, "dvbsuboverlay", + 0, "DVB subtitle overlay"); + GST_DEBUG_CATEGORY_INIT (gst_dvbsub_overlay_lib_debug, "dvbsub_library", + 0, "libdvbsub library"); + + return gst_element_register (plugin, "dvbsuboverlay", + GST_RANK_PRIMARY, GST_TYPE_DVBSUB_OVERLAY); +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "dvbsuboverlay", + "DVB subtitle renderer", + plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/gst/dvbsuboverlay/gstdvbsuboverlay.h b/gst/dvbsuboverlay/gstdvbsuboverlay.h new file mode 100644 index 0000000000..bf4c97825e --- /dev/null +++ b/gst/dvbsuboverlay/gstdvbsuboverlay.h @@ -0,0 +1,90 @@ +/* GStreamer DVB subtitles overlay + * Copyright (c) 2010 Mart Raudsepp + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public License + * along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_DVBSUB_OVERLAY_H__ +#define __GST_DVBSUB_OVERLAY_H__ + +#include +#include + +#include "dvb-sub.h" + +G_BEGIN_DECLS + +#define GST_TYPE_DVBSUB_OVERLAY (gst_dvbsub_overlay_get_type()) +#define GST_DVBSUB_OVERLAY(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_DVBSUB_OVERLAY,GstDVBSubOverlay)) +#define GST_DVBSUB_OVERLAY_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_DVBSUB_OVERLAY,GstDVBSubOverlayClass)) +#define GST_IS_DVBSUB_OVERLAY(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_DVBSUB_OVERLAY)) +#define GST_IS_DVBSUB_OVERLAY_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_DVBSUB_OVERLAY)) + +typedef struct _GstDVBSubOverlay GstDVBSubOverlay; +typedef struct _GstDVBSubOverlayClass GstDVBSubOverlayClass; +typedef void (*GstAssRenderBlitFunction) (GstDVBSubOverlay *overlay, DVBSubtitles *subs, GstBuffer *buffer); + +struct _GstDVBSubOverlay +{ + GstElement element; + + GstPad *video_sinkpad, *text_sinkpad, *srcpad; + + /* properties */ + gboolean enable; + + /* */ + GstSegment video_segment; + GstSegment subtitle_segment; + + GstVideoFormat format; + gint width, height; + gint fps_n, fps_d; + GstAssRenderBlitFunction blit; + + guint subtitle_buffer; /* FIXME: This should hold the pre-rendered + * subtitle regions for fast blending on top + * of each frame. Currently just a number of + * active regions that ought to get blended, + * to get all the timing code working, + * leaving the actual conversion from + * libdvbsub to a suitable cache format and + * blending to later */ + GMutex *subtitle_mutex; + GCond *subtitle_cond; /* to signal removal of a queued text + * buffer, arrival of a text buffer, + * a text segment update, or a change + * in status (e.g. shutdown, flushing) + * FIXME: Update comment for dvbsub case */ + GstBuffer *subtitle_pending; + gboolean subtitle_flushing; + gboolean subtitle_eos; + + GMutex *dvbsub_mutex; /* FIXME: Do we need a mutex lock in case of libdvbsub? Probably, but... */ + DvbSub *dvb_sub; + + gboolean renderer_init_ok; +}; + +struct _GstDVBSubOverlayClass +{ + GstElementClass parent_class; +}; + +GType gst_dvbsub_overlay_get_type (void); + +G_END_DECLS + +#endif From 1db547f0b62155f64377882a87b0a7a053225802 Mon Sep 17 00:00:00 2001 From: Mart Raudsepp Date: Mon, 29 Nov 2010 20:10:17 +0000 Subject: [PATCH 002/448] gstmpegtsdemux: add temporary **HACK** for dvb subs testing so dvbsuboverlay gets whole packets leio, what's the mpegts demux hack about? my libdvbsub code can't handle cut packets so the hack instructs the demuxer to gather full packets before pushing down, but it applies that to more PES packet types than just dvbsub, but I'm not sure if that's a bad thing either way, needs a cleaner solution, either in demuxer, or I need to handle cut packets ok, but really it should be fixed in the overlay, right? or a parser be inserted the problem is that I don't know from the first packet beforehand if it is a cut one or no not err, first buffer just when I receive the next one I see if it has a valid timestamp on it or not so I can't very well queue it up in the chain either, I might be blocking the very last subtitle for no reason or something but you could just drop/ignore packets until you find one, right? find what? a complete packet? the problem isn't that they aren't complete the problem is that they are cut across multiple GstBuffers by the demuxer without the hack sure, I understand that but you can't easily determine if a GstBuffer contains he start fragment of a packet or not? I guess I could parse the packet and see if its length is enough, just like the libdvbsub code eventually does too I can, it has a timestamp if it's the first chunk I just never know if I need to wait for more, without some parsing ah ok while the demuxer could just give me an uncut one in the first place like it always does for program streams that gather_pes is always set in gstmpegdemux, but not in gstmpegtsdemux --- gst/mpegdemux/gstmpegtsdemux.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/gst/mpegdemux/gstmpegtsdemux.c b/gst/mpegdemux/gstmpegtsdemux.c index 865dce2883..0dd8d7d337 100644 --- a/gst/mpegdemux/gstmpegtsdemux.c +++ b/gst/mpegdemux/gstmpegtsdemux.c @@ -1469,7 +1469,15 @@ gst_mpegts_stream_parse_pmt (GstMpegTSStream * stream, ES_stream->flags |= MPEGTS_STREAM_FLAG_IS_VIDEO; /* set adaptor */ + GST_LOG ("Initializing PES filter for PID %u", ES_stream->PID); gst_pes_filter_init (&ES_stream->filter, NULL, NULL); + if (ES_stream->stream_type == ST_PRIVATE_DATA) { + GST_FIXME ("Stream type is ST_PRIVATE_DATA, setting " + "filter->gather_pes as a HACK"); + /* FIXME: There's another place where pes filters could get + * initialized. Might need similar temporary hack there as well */ + ES_stream->filter.gather_pes = TRUE; + } gst_pes_filter_set_callbacks (&ES_stream->filter, (GstPESFilterData) gst_mpegts_demux_data_cb, (GstPESFilterResync) gst_mpegts_demux_resync_cb, ES_stream); @@ -2298,6 +2306,7 @@ gst_mpegts_demux_parse_stream (GstMpegTSDemux * demux, GstMpegTSStream * stream, } /* Initialise our PES filter */ + GST_LOG ("Initializing PES filter for PID %u", stream->PID); gst_pes_filter_init (&stream->filter, NULL, NULL); gst_pes_filter_set_callbacks (&stream->filter, (GstPESFilterData) gst_mpegts_demux_data_cb, From 08c355823bbec567729a4e66b1afe1fc847a6c8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Mon, 29 Nov 2010 20:55:30 +0000 Subject: [PATCH 003/448] dvbsuboverlay: more TODO --- gst/dvbsuboverlay/TODO | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/gst/dvbsuboverlay/TODO b/gst/dvbsuboverlay/TODO index 7042734c6c..cf1c45cca4 100644 --- a/gst/dvbsuboverlay/TODO +++ b/gst/dvbsuboverlay/TODO @@ -4,3 +4,7 @@ Check about GST_PAD_PARENT vs gst_pad_get_parent - do we need a reference - is t Ask about individual segment handling on separate sink pads. Is it possible that the separate NEWSEGMENT events on the text and video pad have different start and/or stop values, as to require some code complexity present? +- parse incoming buffers into complete packets (first buffer of a packet should + have a timestamp set), and get rid of the gstmpegtsdemux hack + +- implement blitting/overlay for at least I420 From 7cab41013e4315a3a86fc9c9c25dedace3e69741 Mon Sep 17 00:00:00 2001 From: Mart Raudsepp Date: Tue, 30 Nov 2010 03:47:46 +0200 Subject: [PATCH 004/448] dvbsuboverlay: Remove dvb_sub_feed() API GStreamer will only use dvb_sub_feed_with_pts, as it has its own PES filter to do the header parsing. --- gst/dvbsuboverlay/dvb-sub.c | 97 ------------------------------------- gst/dvbsuboverlay/dvb-sub.h | 1 - 2 files changed, 98 deletions(-) diff --git a/gst/dvbsuboverlay/dvb-sub.c b/gst/dvbsuboverlay/dvb-sub.c index b0b26cc465..fb9aa56687 100644 --- a/gst/dvbsuboverlay/dvb-sub.c +++ b/gst/dvbsuboverlay/dvb-sub.c @@ -1385,103 +1385,6 @@ dvb_sub_new (void) return dvbsub; } -/** - * dvb_sub_feed: - * @dvb_sub: a #DvbSub - * @data: The data to feed to the parser - * @len: Length of the data - * - * Feeds the DvbSub parser with new PES packet data to parse. - * The data given must be a full PES packet, which must - * include a PTS field in the headers. - * Only one packet is handled in one call, so the available data - * should be fed continously until all is consumed. - * - * Return value: a negative value on errors, -4 if simply not enough data for the PES packet; - * Amount of data consumed (length of handled PES packet on success) - */ -gint -dvb_sub_feed (DvbSub * dvb_sub, guint8 * data, gint len) -{ - guint64 pts = 0; - unsigned int pos = 0; - guint16 PES_packet_len; - guint8 PES_packet_header_len; - gboolean is_subtitle_packet = TRUE; - gboolean pts_field_present = FALSE; - g_warning ("Feeding %d bytes of data to dvbsub!!!!!!!!!!!!\n", len); - if (len == 0) - return 0; - - if (len <= 8) { - dvb_log (DVB_LOG_PACKET, G_LOG_LEVEL_WARNING, - "Length %d too small for further processing", len); - return -1; - } - - if (data[0] != 0x00 || data[1] != 0x00 || data[2] != 0x01) { - dvb_log (DVB_LOG_PACKET, G_LOG_LEVEL_WARNING, - "Data fed to dvb_sub_feed is not a PES packet - does not start with a code_prefix of 0x000001"); - return 1; // FIXME: Probably handle it? - we need to skip PES_packet_len from this elementary stream then and move on - } - - if (data[3] != 0xBD) { - dvb_log (DVB_LOG_PACKET, G_LOG_LEVEL_INFO, - "Data fed to dvb_sub_feed is not a PES packet of type private_stream_1, but rather '0x%X', so not a subtitle stream", - data[3]); - is_subtitle_packet = FALSE; - } - - PES_packet_len = (data[4] << 8) | data[5]; - dvb_log (DVB_LOG_PACKET, G_LOG_LEVEL_DEBUG, - "PES packet length is %u", PES_packet_len); - pos = 6; - - /* FIXME: If the packet is cut, we could be feeding data more than we actually have here, which breaks everything. Probably need to buffer up and handle it, - * FIXME: Or push back in front to the file descriptor buffer (but we are using read, not libc buffered fread, so that idea might not be possible )*/ - if ((len - 5) < PES_packet_len) { - dvb_log (DVB_LOG_PACKET, G_LOG_LEVEL_WARNING, - "!!!!!!!!!!! claimed PES packet length was %d, but we only had %d bytes available, falling back and waiting more !!!!!!!!!", - PES_packet_len, len - 5); - return -4; - } - /* FIXME: Validate sizes inbetween here */ - - /* If this is a non-subtitle packet, still skip the data, pretending we consumed it (FIXME: Signal up) */ - if (!is_subtitle_packet) { - return pos + PES_packet_len; - } - - pos++; - - if (data[pos++] & 0x80) { /* PTS fields present (possibly also DTS). Technically this must be present per the spec */ - pts_field_present = TRUE; - } - - /* pos should be 8 now anyway */ - pos = 8; - - PES_packet_header_len = data[pos++]; - - if (pts_field_present) { - /* '001x', PTS[32..30], marker, PTS[29..15], marker, PTS[14..0], marker */ - pts = ((guint64) (data[pos] & 0x0E)) << 29; /* PTS[32..30], ignore marker at rightmost bit */ - pts |= ((guint64) (data[pos + 1])) << 22; /* PTS[29..22], full byte */ - pts |= ((guint64) (data[pos + 2] & 0xFE)) << 14; /* PTS[21..15], ignore marker at rightmost bit */ - pts |= ((guint64) (data[pos + 3])) << 7; /* PTS[14.. 7], full byte */ - pts |= ((guint64) (data[pos + 4] & 0xFE)) >> 1; /* PTS[ 6.. 0], ignore marker at rightmost bit */ - } - - pos += PES_packet_header_len; /* FIXME: Currently including all header values with all but PTS ignored */ - - dvb_sub_feed_with_pts (dvb_sub, pts, data + pos, PES_packet_len - PES_packet_header_len - 3); /* 2 bytes between PES_packet_len and PES_packet_header_len fields, minus header_len itself */ - pos += PES_packet_len - PES_packet_header_len - 3; - dvb_log (DVB_LOG_PACKET, G_LOG_LEVEL_DEBUG, - "Finished PES packet - consumed %u bytes of %d", pos, len); - - return pos; -} - #define DVB_SUB_SEGMENT_PAGE_COMPOSITION 0x10 #define DVB_SUB_SEGMENT_REGION_COMPOSITION 0x11 #define DVB_SUB_SEGMENT_CLUT_DEFINITION 0x12 diff --git a/gst/dvbsuboverlay/dvb-sub.h b/gst/dvbsuboverlay/dvb-sub.h index fee88164d2..c52febacfd 100644 --- a/gst/dvbsuboverlay/dvb-sub.h +++ b/gst/dvbsuboverlay/dvb-sub.h @@ -124,7 +124,6 @@ typedef struct { GType dvb_sub_get_type (void) G_GNUC_CONST; DvbSub *dvb_sub_new (void); -gint dvb_sub_feed (DvbSub *dvb_sub, guint8 *data, gint len); gint dvb_sub_feed_with_pts (DvbSub *dvb_sub, guint64 pts, guint8 *data, gint len); void dvb_sub_set_callbacks (DvbSub *dvb_sub, DvbSubCallbacks *callbacks, gpointer user_data); From 316cd44c8d11d0355deb0a5cd65cf290c3d472b0 Mon Sep 17 00:00:00 2001 From: Mart Raudsepp Date: Tue, 30 Nov 2010 03:56:32 +0200 Subject: [PATCH 005/448] dvbsuboverlay: Add FIXME note about non-constant PTS for a display set handling. --- gst/dvbsuboverlay/dvb-sub.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gst/dvbsuboverlay/dvb-sub.c b/gst/dvbsuboverlay/dvb-sub.c index fb9aa56687..dc13ce94d2 100644 --- a/gst/dvbsuboverlay/dvb-sub.c +++ b/gst/dvbsuboverlay/dvb-sub.c @@ -1463,7 +1463,9 @@ dvb_sub_feed_with_pts (DvbSub * dvb_sub, guint64 pts, guint8 * data, gint len) segment_len, len - pos); return -2; } - // TODO: Parse the segment per type + // TODO: Parse the segment per type (this is probably a leftover TODO that is now done?) + /* FIXME: Handle differing PTS values - all segments of a given display set must be with the same PTS, + * FIXME: but we let it slip and just take it for granted in end_of_display_set */ switch (segment_type) { case DVB_SUB_SEGMENT_PAGE_COMPOSITION: dvb_log (DVB_LOG_PACKET, G_LOG_LEVEL_DEBUG, From 4a68decb52175f02ae699719e75bd43ad46f5862 Mon Sep 17 00:00:00 2001 From: Mart Raudsepp Date: Tue, 30 Nov 2010 04:45:54 +0200 Subject: [PATCH 006/448] dvbsuboverlay: Work with GstClockTime instead of PTS for subtitle timing Abuse libdvbsub PTS tracking to just store our running time in it, to get it back in the callbacks. As GStreamer does its own PTS handling behind our back (especially for video), we should just sync with video per running time, not try to do it with PTS, which doesn't seem well accessible for video chain. We can later relabel dvb-sub.c pts naming convention if wanted, it's just passing along guint64 values, which GstClockTime fortunately is too. The current idea is to collect the regions returned by the callback into a FIFO buffer and pop and pre-render the top one into a separate quick-to-blend cached format, which is then appropriately blended in the video chain until the next one on top of the stack reaches the video chains running time (or the fallback timer hits). --- gst/dvbsuboverlay/gstdvbsuboverlay.c | 46 +++++++++++++++------------- 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/gst/dvbsuboverlay/gstdvbsuboverlay.c b/gst/dvbsuboverlay/gstdvbsuboverlay.c index a2157e9542..e57fae24af 100644 --- a/gst/dvbsuboverlay/gstdvbsuboverlay.c +++ b/gst/dvbsuboverlay/gstdvbsuboverlay.c @@ -901,22 +901,18 @@ gst_dvbsub_overlay_setcaps_text (GstPad * pad, GstCaps * caps) return ret; } -#define CLOCK_BASE 9LL -#define GSTTIME_TO_MPEGTIME(time) (gst_util_uint64_scale ((time), \ - CLOCK_BASE, GST_MSECOND/10)) - static void -gst_dvbsub_overlay_process_text (GstDVBSubOverlay * overlay, GstBuffer * buffer) +gst_dvbsub_overlay_process_text (GstDVBSubOverlay * overlay, GstBuffer * buffer, + guint64 pts) { - /* FIXME: Locking in this function */ + /* FIXME: Locking in this function? */ guint8 *data = (guint8 *) GST_BUFFER_DATA (buffer); guint size = GST_BUFFER_SIZE (buffer); - guint64 pts = GSTTIME_TO_MPEGTIME (GST_BUFFER_TIMESTAMP (buffer)); GST_DEBUG_OBJECT (overlay, - "Processing subtitles with running time %" GST_TIME_FORMAT - " which is PTS=%" G_GUINT64_FORMAT, - GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)), pts); + "Processing subtitles with fake PTS=%" G_GUINT64_FORMAT + " which is a running time of %" GST_TIME_FORMAT, + pts, GST_TIME_ARGS (pts)); GST_DEBUG_OBJECT (overlay, "Feeding %u bytes to libdvbsub", size); g_mutex_lock (overlay->dvbsub_mutex); /* FIXME: Use standard lock? */ dvb_sub_feed_with_pts (overlay->dvb_sub, pts, data, size); @@ -931,7 +927,8 @@ new_dvb_subtitles_cb (DvbSub * dvb_sub, guint64 pts, DVBSubtitles * subs, GstDVBSubOverlay *overlay = GST_DVBSUB_OVERLAY (user_data); GST_INFO_OBJECT (overlay, "New DVB subtitles arrived with a page_time_out of %d and %d regions for PTS=%" - G_GUINT64_FORMAT "\n", page_time_out, subs->num_rects, pts); + G_GUINT64_FORMAT ", which should be at running time %" GST_TIME_FORMAT, + page_time_out, subs->num_rects, pts, GST_TIME_ARGS (pts)); //GST_OBJECT_LOCK (overlay); overlay->subtitle_buffer = subs->num_rects; //GST_OBJECT_UNLOCK (overlay); @@ -965,6 +962,7 @@ gst_dvbsub_overlay_chain_text (GstPad * pad, GstBuffer * buffer) GstDVBSubOverlay *overlay = GST_DVBSUB_OVERLAY (GST_PAD_PARENT (pad)); gint64 clip_start = 0, clip_stop = 0; gboolean in_seg = FALSE; + GstClockTime sub_running_time; GST_INFO_OBJECT (overlay, "private/x-dvbsub buffer with size %u", GST_BUFFER_SIZE (buffer)); @@ -985,10 +983,9 @@ gst_dvbsub_overlay_chain_text (GstPad * pad, GstBuffer * buffer) GST_LOG_OBJECT (overlay, "Video segment: %" GST_SEGMENT_FORMAT " --- Subtitle segment: %" - GST_SEGMENT_FORMAT " --- BUFFER: ts=%" GST_TIME_FORMAT " -- PTS: %" - G_GUINT64_FORMAT, &overlay->video_segment, &overlay->subtitle_segment, - GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)), - GSTTIME_TO_MPEGTIME (GST_BUFFER_TIMESTAMP (buffer))); + GST_SEGMENT_FORMAT " --- BUFFER: ts=%" GST_TIME_FORMAT, + &overlay->video_segment, &overlay->subtitle_segment, + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer))); /* DVB subtitle packets are required to carry the PTS */ if (G_UNLIKELY (!GST_BUFFER_TIMESTAMP_IS_VALID (buffer))) { @@ -1041,12 +1038,20 @@ gst_dvbsub_overlay_chain_text (GstPad * pad, GstBuffer * buffer) gst_segment_set_last_stop (&overlay->subtitle_segment, GST_FORMAT_TIME, clip_start); + sub_running_time = + gst_segment_to_running_time (&overlay->subtitle_segment, GST_FORMAT_TIME, + GST_BUFFER_TIMESTAMP (buffer)); + + GST_DEBUG_OBJECT (overlay, "SUBTITLE real running time: %" GST_TIME_FORMAT, + GST_TIME_ARGS (sub_running_time)); + overlay->subtitle_buffer = 0; /*buffer FIXME: Need to do buffering elsewhere */ /* That's a new text buffer we need to render */ /*overlay->need_render = TRUE; *//* FIXME: Actually feed it to libdvbsub and set need_render on a callback */ - gst_dvbsub_overlay_process_text (overlay, buffer); + /* FIXME: We are abusing libdvbsub pts value for tracking our gstreamer running time instead of real PTS. Should be mostly fine though... */ + gst_dvbsub_overlay_process_text (overlay, buffer, sub_running_time); /* in case the video chain is waiting for a text buffer, wake it up */ GST_DVBSUB_OVERLAY_BROADCAST (overlay); @@ -1069,11 +1074,10 @@ gst_dvbsub_overlay_chain_video (GstPad * pad, GstBuffer * buffer) start = GST_BUFFER_TIMESTAMP (buffer); GST_LOG_OBJECT (overlay, - "Video last_stop: %" GST_TIME_FORMAT " --- Subtitle last_stop: %" - GST_TIME_FORMAT " --- BUFFER: ts=%" GST_TIME_FORMAT " -- PTS: %" - G_GUINT64_FORMAT, &overlay->video_segment.last_stop, - &overlay->subtitle_segment.last_stop, GST_TIME_ARGS (start), - GSTTIME_TO_MPEGTIME (start)); + "Video segment: %" GST_SEGMENT_FORMAT " --- Subtitle last_stop: %" + GST_TIME_FORMAT " --- BUFFER: ts=%" GST_TIME_FORMAT, + &overlay->video_segment, &overlay->subtitle_segment.last_stop, + GST_TIME_ARGS (start)); /* ignore buffers that are outside of the current segment */ if (!GST_BUFFER_DURATION_IS_VALID (buffer)) { From aca72378787a83da6601eed7b791d0ee2f5b14f0 Mon Sep 17 00:00:00 2001 From: Mart Raudsepp Date: Wed, 1 Dec 2010 04:28:02 +0200 Subject: [PATCH 007/448] dvbsuboverlay: Make the libdvbsub callback handler responsible for memory cleanup We want to allow queueing of raw region image data in the gst plugin side, and keep the data around until we pop the item from the queue. So make the callback handler responsible for memory cleanup, if one is installed. --- gst/dvbsuboverlay/dvb-sub.c | 18 +++++++++++++++--- gst/dvbsuboverlay/dvb-sub.h | 4 +++- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/gst/dvbsuboverlay/dvb-sub.c b/gst/dvbsuboverlay/dvb-sub.c index dc13ce94d2..767e7bf809 100644 --- a/gst/dvbsuboverlay/dvb-sub.c +++ b/gst/dvbsuboverlay/dvb-sub.c @@ -1352,9 +1352,23 @@ _dvb_sub_parse_end_of_display_set (DvbSub * dvb_sub, guint16 page_id, sub->num_rects = i; - if (priv->callbacks.new_data) + if (priv->callbacks.new_data) { priv->callbacks.new_data (dvb_sub, pts, sub, priv->page_time_out, priv->user_data); + } else { + /* No-one responsible to clean up memory, so do it ourselves */ + /* FIXME: Just don't bother with all this palette image creation in the first place then... */ + dvb_subtitles_free (sub); + } + + return 1; /* FIXME: The caller of this function is probably supposed to do something with the return value */ +} + +void +dvb_subtitles_free (DVBSubtitles * sub) +{ + int i; + DVBSubtitleRect *rect; /* Now free up all the temporary memory we allocated */ for (i = 0; i < sub->num_rects; ++i) { @@ -1366,8 +1380,6 @@ _dvb_sub_parse_end_of_display_set (DvbSub * dvb_sub, guint16 page_id, } g_free (sub->rects); g_slice_free (DVBSubtitles, sub); - - return 1; /* FIXME: The caller of this function is probably supposed to do something with the return value */ } /** diff --git a/gst/dvbsuboverlay/dvb-sub.h b/gst/dvbsuboverlay/dvb-sub.h index c52febacfd..05c9e42fcf 100644 --- a/gst/dvbsuboverlay/dvb-sub.h +++ b/gst/dvbsuboverlay/dvb-sub.h @@ -111,7 +111,8 @@ typedef struct DVBSubtitles { * is the #DvbSub instance this callback originates from; @subs is the set of * subtitle objects that should be display for no more than @page_time_out * seconds at @pts; @user_data is the same user_data as was passed through - * dvb_sub_set_callbacks(); + * dvb_sub_set_callbacks(); The callback handler is responsible for eventually + * cleaning up the subpicture data @subs with a call to dvb_subtitles_free() * * A set of callbacks that can be installed on the #DvbSub with * dvb_sub_set_callbacks(). @@ -126,6 +127,7 @@ GType dvb_sub_get_type (void) G_GNUC_CONST; DvbSub *dvb_sub_new (void); gint dvb_sub_feed_with_pts (DvbSub *dvb_sub, guint64 pts, guint8 *data, gint len); void dvb_sub_set_callbacks (DvbSub *dvb_sub, DvbSubCallbacks *callbacks, gpointer user_data); +void dvb_subtitles_free (DVBSubtitles *sub); void dvb_sub_set_global_log_cb (void (*log_cb) (GLogLevelFlags log_level, const gchar *format, va_list args, gpointer user_data), gpointer user_data); From 7e2e52cab8db0225c0de39c66c796f311026198d Mon Sep 17 00:00:00 2001 From: Mart Raudsepp Date: Wed, 1 Dec 2010 05:26:02 +0200 Subject: [PATCH 008/448] dvbsuboverlay: Pass page_time_out and pts with the DVBSubtitles structure Eases holding onto the information in gst plugins side queue of DVBSubtitles, so we won't need to create yet another temporary struct to keep the pts and page_time_out too. And this really logically belongs at the toplevel information set anyway and in that struct... --- gst/dvbsuboverlay/dvb-sub.c | 5 +++-- gst/dvbsuboverlay/dvb-sub.h | 4 +++- gst/dvbsuboverlay/gstdvbsuboverlay.c | 10 +++++----- 3 files changed, 11 insertions(+), 8 deletions(-) diff --git a/gst/dvbsuboverlay/dvb-sub.c b/gst/dvbsuboverlay/dvb-sub.c index 767e7bf809..2df0297867 100644 --- a/gst/dvbsuboverlay/dvb-sub.c +++ b/gst/dvbsuboverlay/dvb-sub.c @@ -1350,11 +1350,12 @@ _dvb_sub_parse_end_of_display_set (DvbSub * dvb_sub, guint16 page_id, ++i; } + sub->pts = pts; + sub->page_time_out = priv->page_time_out; sub->num_rects = i; if (priv->callbacks.new_data) { - priv->callbacks.new_data (dvb_sub, pts, sub, priv->page_time_out, - priv->user_data); + priv->callbacks.new_data (dvb_sub, sub, priv->user_data); } else { /* No-one responsible to clean up memory, so do it ourselves */ /* FIXME: Just don't bother with all this palette image creation in the first place then... */ diff --git a/gst/dvbsuboverlay/dvb-sub.h b/gst/dvbsuboverlay/dvb-sub.h index 05c9e42fcf..ffee9106e8 100644 --- a/gst/dvbsuboverlay/dvb-sub.h +++ b/gst/dvbsuboverlay/dvb-sub.h @@ -101,6 +101,8 @@ typedef struct DVBSubtitleRect { * A structure representing a set of subtitle objects. */ typedef struct DVBSubtitles { + guint64 pts; + guint8 page_time_out; unsigned int num_rects; DVBSubtitleRect **rects; } DVBSubtitles; @@ -118,7 +120,7 @@ typedef struct DVBSubtitles { * dvb_sub_set_callbacks(). */ typedef struct { - void (*new_data) (DvbSub *dvb_sub, guint64 pts, DVBSubtitles * subs, guint8 page_time_out, gpointer user_data); + void (*new_data) (DvbSub *dvb_sub, DVBSubtitles * subs, gpointer user_data); /*< private >*/ gpointer _dvb_sub_reserved[3]; } DvbSubCallbacks; diff --git a/gst/dvbsuboverlay/gstdvbsuboverlay.c b/gst/dvbsuboverlay/gstdvbsuboverlay.c index e57fae24af..c62957a2af 100644 --- a/gst/dvbsuboverlay/gstdvbsuboverlay.c +++ b/gst/dvbsuboverlay/gstdvbsuboverlay.c @@ -120,8 +120,8 @@ static gboolean gst_dvbsub_overlay_event_video (GstPad * pad, GstEvent * event); static gboolean gst_dvbsub_overlay_event_text (GstPad * pad, GstEvent * event); static gboolean gst_dvbsub_overlay_event_src (GstPad * pad, GstEvent * event); -static void new_dvb_subtitles_cb (DvbSub * dvb_sub, guint64 pts, - DVBSubtitles * subs, guint8 page_time_out, gpointer user_data); +static void new_dvb_subtitles_cb (DvbSub * dvb_sub, DVBSubtitles * subs, + gpointer user_data); static GstFlowReturn gst_dvbsub_overlay_bufferalloc_video (GstPad * pad, guint64 offset, guint size, GstCaps * caps, GstBuffer ** buffer); @@ -921,14 +921,14 @@ gst_dvbsub_overlay_process_text (GstDVBSubOverlay * overlay, GstBuffer * buffer, } static void -new_dvb_subtitles_cb (DvbSub * dvb_sub, guint64 pts, DVBSubtitles * subs, - guint8 page_time_out, gpointer user_data) +new_dvb_subtitles_cb (DvbSub * dvb_sub, DVBSubtitles * subs, gpointer user_data) { GstDVBSubOverlay *overlay = GST_DVBSUB_OVERLAY (user_data); GST_INFO_OBJECT (overlay, "New DVB subtitles arrived with a page_time_out of %d and %d regions for PTS=%" G_GUINT64_FORMAT ", which should be at running time %" GST_TIME_FORMAT, - page_time_out, subs->num_rects, pts, GST_TIME_ARGS (pts)); + subs->page_time_out, subs->num_rects, subs->pts, + GST_TIME_ARGS (subs->pts)); //GST_OBJECT_LOCK (overlay); overlay->subtitle_buffer = subs->num_rects; //GST_OBJECT_UNLOCK (overlay); From 41c82583f50512cc1a41b05afc5045ceb1f5f4bb Mon Sep 17 00:00:00 2001 From: Mart Raudsepp Date: Wed, 1 Dec 2010 05:49:22 +0200 Subject: [PATCH 009/448] dvbsuboverlay: Make the new dvb_subtitles_free() accept NULL Don't crash if dvb_subtitles_free(NULL) gets passed, like most other *_free functions are happy with. --- gst/dvbsuboverlay/dvb-sub.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/gst/dvbsuboverlay/dvb-sub.c b/gst/dvbsuboverlay/dvb-sub.c index 2df0297867..4c28ddde95 100644 --- a/gst/dvbsuboverlay/dvb-sub.c +++ b/gst/dvbsuboverlay/dvb-sub.c @@ -1371,6 +1371,9 @@ dvb_subtitles_free (DVBSubtitles * sub) int i; DVBSubtitleRect *rect; + if (sub == NULL) + return; + /* Now free up all the temporary memory we allocated */ for (i = 0; i < sub->num_rects; ++i) { rect = sub->rects[i]; From 3d09a3b18ab52e72c4c73b2b2e8dc7033d6c8b36 Mon Sep 17 00:00:00 2001 From: Mart Raudsepp Date: Wed, 1 Dec 2010 06:01:15 +0200 Subject: [PATCH 010/448] dvbsuboverlay: Implement subtitle queueing and syncing with video Push incoming subtitle pages in a FIFO queue (pending_subtitles) and dequeue the head when it's time to show it (when video running time reaches the subtitle page running time). Keep the subtitle page, that is supposed to be blended on top of video currently, in a separate object variable (current_subtitle). As a next step we can then pre-render current_subtitle to a better to blend format. --- gst/dvbsuboverlay/gstdvbsuboverlay.c | 37 +++++++++++++++++++++++----- gst/dvbsuboverlay/gstdvbsuboverlay.h | 12 +++------ 2 files changed, 35 insertions(+), 14 deletions(-) diff --git a/gst/dvbsuboverlay/gstdvbsuboverlay.c b/gst/dvbsuboverlay/gstdvbsuboverlay.c index c62957a2af..9d86c78366 100644 --- a/gst/dvbsuboverlay/gstdvbsuboverlay.c +++ b/gst/dvbsuboverlay/gstdvbsuboverlay.c @@ -234,6 +234,9 @@ gst_dvbsub_overlay_init (GstDVBSubOverlay * render, render->subtitle_mutex = g_mutex_new (); render->subtitle_cond = g_cond_new (); + render->current_subtitle = NULL; + render->pending_subtitles = g_queue_new (); + render->renderer_init_ok = FALSE; render->enable = TRUE; @@ -270,6 +273,11 @@ gst_dvbsub_overlay_finalize (GObject * object) if (overlay->subtitle_cond) g_cond_free (overlay->subtitle_cond); + if (overlay->pending_subtitles) { + /* FIXME: Free up contents */ + g_queue_free (overlay->pending_subtitles); + } + if (overlay->dvb_sub) { g_object_unref (overlay->dvb_sub); } @@ -930,7 +938,7 @@ new_dvb_subtitles_cb (DvbSub * dvb_sub, DVBSubtitles * subs, gpointer user_data) subs->page_time_out, subs->num_rects, subs->pts, GST_TIME_ARGS (subs->pts)); //GST_OBJECT_LOCK (overlay); - overlay->subtitle_buffer = subs->num_rects; + g_queue_push_tail (overlay->pending_subtitles, subs); //GST_OBJECT_UNLOCK (overlay); } @@ -1045,8 +1053,6 @@ gst_dvbsub_overlay_chain_text (GstPad * pad, GstBuffer * buffer) GST_DEBUG_OBJECT (overlay, "SUBTITLE real running time: %" GST_TIME_FORMAT, GST_TIME_ARGS (sub_running_time)); - overlay->subtitle_buffer = 0; /*buffer FIXME: Need to do buffering elsewhere */ - /* That's a new text buffer we need to render */ /*overlay->need_render = TRUE; *//* FIXME: Actually feed it to libdvbsub and set need_render on a callback */ @@ -1067,6 +1073,7 @@ gst_dvbsub_overlay_chain_video (GstPad * pad, GstBuffer * buffer) GstDVBSubOverlay *overlay = GST_DVBSUB_OVERLAY (GST_PAD_PARENT (pad)); GstFlowReturn ret = GST_FLOW_OK; gint64 start, stop; + GstClockTime vid_running_time; if (!GST_BUFFER_TIMESTAMP_IS_VALID (buffer)) goto missing_timestamp; @@ -1086,13 +1093,29 @@ gst_dvbsub_overlay_chain_video (GstPad * pad, GstBuffer * buffer) stop = start + GST_BUFFER_DURATION (buffer); } + vid_running_time = + gst_segment_to_running_time (&overlay->video_segment, GST_FORMAT_TIME, + GST_BUFFER_TIMESTAMP (buffer)); + + GST_DEBUG_OBJECT (overlay, "Video running time: %" GST_TIME_FORMAT, + GST_TIME_ARGS (vid_running_time)); + /* FIXME: Probably update last_stop somewhere */ /* FIXME: Segment clipping code */ - if (overlay->subtitle_buffer > 0) { - GST_DEBUG_OBJECT (overlay, "Should be rendering %u regions", - overlay->subtitle_buffer); + if (!g_queue_is_empty (overlay->pending_subtitles)) { + DVBSubtitles *pending_sub = g_queue_peek_head (overlay->pending_subtitles); + if (vid_running_time >= pending_sub->pts) { + GST_DEBUG_OBJECT (overlay, + "Time to show the next subtitle page (%" GST_TIME_FORMAT " >= %" + GST_TIME_FORMAT ") - it has %u regions", + GST_TIME_ARGS (vid_running_time), GST_TIME_ARGS (pending_sub->pts), + pending_sub->num_rects); + dvb_subtitles_free (overlay->current_subtitle); + overlay->current_subtitle = g_queue_pop_head (overlay->pending_subtitles); + /* FIXME: Pre-convert current_subtitle to a quick-blend format, num_rects=0 means that there are no regions, e.g, a subtitle "clear" happened */ + } } ret = gst_pad_push (overlay->srcpad, buffer); @@ -1216,6 +1239,8 @@ gst_dvbsub_overlay_event_text (GstPad * pad, GstEvent * event) break; case GST_EVENT_FLUSH_START: GST_DEBUG_OBJECT (render, "begin flushing"); + + /* FIXME: Reset subtitles queue and any other state */ #if 0 // FIXME g_mutex_lock (render->ass_mutex); if (render->ass_track) { diff --git a/gst/dvbsuboverlay/gstdvbsuboverlay.h b/gst/dvbsuboverlay/gstdvbsuboverlay.h index bf4c97825e..62290c777e 100644 --- a/gst/dvbsuboverlay/gstdvbsuboverlay.h +++ b/gst/dvbsuboverlay/gstdvbsuboverlay.h @@ -54,14 +54,10 @@ struct _GstDVBSubOverlay gint fps_n, fps_d; GstAssRenderBlitFunction blit; - guint subtitle_buffer; /* FIXME: This should hold the pre-rendered - * subtitle regions for fast blending on top - * of each frame. Currently just a number of - * active regions that ought to get blended, - * to get all the timing code working, - * leaving the actual conversion from - * libdvbsub to a suitable cache format and - * blending to later */ + DVBSubtitles *current_subtitle; /* The currently active set of subtitle regions, if any */ + GQueue *pending_subtitles; /* A queue of raw subtitle region sets with + * metadata that are waiting their running time */ + GMutex *subtitle_mutex; GCond *subtitle_cond; /* to signal removal of a queued text * buffer, arrival of a text buffer, From 84b52f6eb4f7141b084531f15a8d9ad48443e52e Mon Sep 17 00:00:00 2001 From: Mart Raudsepp Date: Wed, 1 Dec 2010 07:06:35 +0200 Subject: [PATCH 011/448] dvbsuboverlay: Implement fallback page_time_out honoring The spec has a page_time_out in the page composition segment to ensure subtitles don't get stuck on screen for too much longer than intended, when future page composition segments get lost on bad reception, or other problems. Honor it in the gst plugin side. --- gst/dvbsuboverlay/gstdvbsuboverlay.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/gst/dvbsuboverlay/gstdvbsuboverlay.c b/gst/dvbsuboverlay/gstdvbsuboverlay.c index 9d86c78366..60c45184a4 100644 --- a/gst/dvbsuboverlay/gstdvbsuboverlay.c +++ b/gst/dvbsuboverlay/gstdvbsuboverlay.c @@ -1118,6 +1118,18 @@ gst_dvbsub_overlay_chain_video (GstPad * pad, GstBuffer * buffer) } } + /* Check that we haven't hit the fallback timeout for current subtitle page */ + if (overlay->current_subtitle + && vid_running_time > + (overlay->current_subtitle->pts + + (overlay->current_subtitle->page_time_out * GST_SECOND))) { + GST_INFO_OBJECT (overlay, + "Subtitle page not redefined before fallback page_time_out of %u seconds (missed data?) - deleting current page", + overlay->current_subtitle->page_time_out); + dvb_subtitles_free (overlay->current_subtitle); + overlay->current_subtitle = NULL; + } + ret = gst_pad_push (overlay->srcpad, buffer); return ret; From 21abf9c4a8a15b5db6a79e7fd34ef54349f4165b Mon Sep 17 00:00:00 2001 From: Mart Raudsepp Date: Wed, 1 Dec 2010 07:20:07 +0200 Subject: [PATCH 012/448] dvbsuboverlay: Do blending calls when appropriate This gives us actually shown subtitles, however with bugs in the current blitting code, resulting in very transparent subtitles. --- gst/dvbsuboverlay/gstdvbsuboverlay.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/gst/dvbsuboverlay/gstdvbsuboverlay.c b/gst/dvbsuboverlay/gstdvbsuboverlay.c index 60c45184a4..7269cdb925 100644 --- a/gst/dvbsuboverlay/gstdvbsuboverlay.c +++ b/gst/dvbsuboverlay/gstdvbsuboverlay.c @@ -1130,6 +1130,12 @@ gst_dvbsub_overlay_chain_video (GstPad * pad, GstBuffer * buffer) overlay->current_subtitle = NULL; } + /* Now render it */ + if (overlay->current_subtitle && overlay->current_subtitle->num_rects > 0) { + buffer = gst_buffer_make_writable (buffer); + blit_i420 (overlay, overlay->current_subtitle, buffer); + } + ret = gst_pad_push (overlay->srcpad, buffer); return ret; From efa1e9a1fec13391a41c6010dc2ef4b03c262cf9 Mon Sep 17 00:00:00 2001 From: Mart Raudsepp Date: Wed, 1 Dec 2010 07:26:03 +0200 Subject: [PATCH 013/448] dvbsuboverlay: Fix blending bug regarding color channel addressing. libdvbsub gives us ARGB ordered pixels right now, not RGBA. --- gst/dvbsuboverlay/gstdvbsuboverlay.c | 32 ++++++++++++++-------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/gst/dvbsuboverlay/gstdvbsuboverlay.c b/gst/dvbsuboverlay/gstdvbsuboverlay.c index 7269cdb925..71b31194a3 100644 --- a/gst/dvbsuboverlay/gstdvbsuboverlay.c +++ b/gst/dvbsuboverlay/gstdvbsuboverlay.c @@ -636,10 +636,10 @@ blit_i420 (GstDVBSubOverlay * overlay, DVBSubtitles * subs, GstBuffer * buffer) /* FIXME: Completely wrong blending code */ color = sub_region->pict.palette[src[0]]; color2 = sub_region->pict.palette[src[1]]; - alpha = 255 - (color & 0xff); - r = (color >> 24) & 0xff; - g = (color >> 16) & 0xff; - b = (color >> 8) & 0xff; + alpha = 255 - ((color >> 24) & 0xff); + r = (color >> 16) & 0xff; + g = (color >> 8) & 0xff; + b = color & 0xff; Y = rgb_to_y (r, g, b); U = rgb_to_u (r, g, b); @@ -678,10 +678,10 @@ blit_i420 (GstDVBSubOverlay * overlay, DVBSubtitles * subs, GstBuffer * buffer) /* FIXME: Completely wrong blending code */ color = sub_region->pict.palette[src[0]]; color2 = sub_region->pict.palette[src[1]]; - alpha = 255 - (color & 0xff); - r = (color >> 24) & 0xff; - g = (color >> 16) & 0xff; - b = (color >> 8) & 0xff; + alpha = 255 - ((color >> 24) & 0xff); + r = (color >> 16) & 0xff; + g = (color >> 8) & 0xff; + b = color & 0xff; Y = rgb_to_y (r, g, b); U = rgb_to_u (r, g, b); @@ -719,10 +719,10 @@ blit_i420 (GstDVBSubOverlay * overlay, DVBSubtitles * subs, GstBuffer * buffer) /* FIXME: Completely wrong blending code */ color = sub_region->pict.palette[src[0]]; color2 = sub_region->pict.palette[src[1]]; - alpha = 255 - (color & 0xff); - r = (color >> 24) & 0xff; - g = (color >> 16) & 0xff; - b = (color >> 8) & 0xff; + alpha = 255 - ((color >> 24) & 0xff); + r = (color >> 16) & 0xff; + g = (color >> 8) & 0xff; + b = color & 0xff; Y = rgb_to_y (r, g, b); U = rgb_to_u (r, g, b); @@ -750,10 +750,10 @@ blit_i420 (GstDVBSubOverlay * overlay, DVBSubtitles * subs, GstBuffer * buffer) /* FIXME: Completely wrong blending code */ color = sub_region->pict.palette[src[0]]; color2 = sub_region->pict.palette[src[1]]; - alpha = 255 - (color & 0xff); - r = (color >> 24) & 0xff; - g = (color >> 16) & 0xff; - b = (color >> 8) & 0xff; + alpha = 255 - ((color >> 24) & 0xff); + r = (color >> 16) & 0xff; + g = (color >> 8) & 0xff; + b = color & 0xff; Y = rgb_to_y (r, g, b); U = rgb_to_u (r, g, b); From a203ad1aab9efbf1e70fbe402c0d411114b11e68 Mon Sep 17 00:00:00 2001 From: Mart Raudsepp Date: Wed, 1 Dec 2010 09:59:14 +0200 Subject: [PATCH 014/448] dvbsuboverlay: Fix more of the blending, so it looks quite good now * libdvbsub gives us alpha channel already, not transparency level, so don't do another "alpha = 255 - alpha", this is done by libdvbsub. * Fix alpha channel handling in interpolation - assrender had an additional 1bpp alpha bitmap as a possible mask, we don't. So don't use the palette index array as alpha values; bug from quick code porting long ago to changing pixel colors (assrender has a single pixel color for whole regions or something, unlike dvbsub, which has indexed colors). * Don't forget to reassign our YUV and other local pixel color variables after shifting to work on the bottom part of a 2x2 subsample block, or it's obviously very blocky. Remaining issues in blending: * Should probably be interpolating or doing something else useful with the resulting U and V channels, so that most of the source pixel UV values would actually be actually cared about, except for just one out of possibly four. * Don't convert AYUV to ARGB in libdvbsub, and then back from ARGB to AYUV in dvbsuboverlay for no reason * Re-factor the whole thing to something more like textoverlay blending * Related to that, perhaps cache the current spu in a good format for quick blending on each frame, after which the more often called blending parts might become more straightforward --- gst/dvbsuboverlay/gstdvbsuboverlay.c | 86 +++++++++++++++++++--------- 1 file changed, 60 insertions(+), 26 deletions(-) diff --git a/gst/dvbsuboverlay/gstdvbsuboverlay.c b/gst/dvbsuboverlay/gstdvbsuboverlay.c index 71b31194a3..5dbdf61848 100644 --- a/gst/dvbsuboverlay/gstdvbsuboverlay.c +++ b/gst/dvbsuboverlay/gstdvbsuboverlay.c @@ -566,8 +566,8 @@ blit_i420 (GstDVBSubOverlay * overlay, DVBSubtitles * subs, GstBuffer * buffer) { guint counter; DVBSubtitleRect *sub_region; - gint alpha, r, g, b, k, k2; - gint Y, U, V; + gint alpha, alpha2, r, g, b, r2, g2, b2, k, k2; + gint Y, U, V, Y2, U2, V2; guint32 color, color2; const guint8 *src; guint8 *dst_y, *dst_u, *dst_v; @@ -631,12 +631,12 @@ blit_i420 (GstDVBSubOverlay * overlay, DVBSubtitles * subs, GstBuffer * buffer) buffer->data + v_offset + ((sub_region->y + 1) / 2) * v_stride + (sub_region->x + 1) / 2; + /* FIXME: This whole blending business will need a refactor */ + /* FIXME: Also interpolation for Cr and Cb channels missing */ for (y = 0; y < h - 1; y += 2) { for (x = 0; x < w - 1; x += 2) { - /* FIXME: Completely wrong blending code */ color = sub_region->pict.palette[src[0]]; - color2 = sub_region->pict.palette[src[1]]; - alpha = 255 - ((color >> 24) & 0xff); + alpha = (color >> 24) & 0xff; r = (color >> 16) & 0xff; g = (color >> 8) & 0xff; b = color & 0xff; @@ -645,24 +645,54 @@ blit_i420 (GstDVBSubOverlay * overlay, DVBSubtitles * subs, GstBuffer * buffer) U = rgb_to_u (r, g, b); V = rgb_to_v (r, g, b); - k = src[0] * alpha / 255; + color2 = sub_region->pict.palette[src[1]]; + alpha2 = (color2 >> 24) & 0xff; + r2 = (color2 >> 16) & 0xff; + g2 = (color2 >> 8) & 0xff; + b2 = color2 & 0xff; + + Y2 = rgb_to_y (r2, g2, b2); + U2 = rgb_to_u (r2, g2, b2); + V2 = rgb_to_v (r2, g2, b2); + + k = alpha; k2 = k; dst_y[0] = (k * Y + (255 - k) * dst_y[0]) / 255; - k = src[1] * alpha / 255; + k = alpha2; k2 += k; - dst_y[1] = (k * Y + (255 - k) * dst_y[1]) / 255; + dst_y[1] = (k * Y2 + (255 - k) * dst_y[1]) / 255; src += src_stride; dst_y += y_stride; - k = src[0] * alpha / 255; + color = sub_region->pict.palette[src[0]]; + alpha = (color >> 24) & 0xff; + r = (color >> 16) & 0xff; + g = (color >> 8) & 0xff; + b = color & 0xff; + + Y = rgb_to_y (r, g, b); + U = rgb_to_u (r, g, b); + V = rgb_to_v (r, g, b); + + color2 = sub_region->pict.palette[src[1]]; + alpha2 = (color2 >> 24) & 0xff; + r2 = (color2 >> 16) & 0xff; + g2 = (color2 >> 8) & 0xff; + b2 = color2 & 0xff; + + Y2 = rgb_to_y (r2, g2, b2); + U2 = rgb_to_u (r2, g2, b2); + V2 = rgb_to_v (r2, g2, b2); + + k = alpha; k2 += k; dst_y[0] = (k * Y + (255 - k) * dst_y[0]) / 255; - k = src[1] * alpha / 255; + k = alpha2; k2 += k; - dst_y[1] = (k * Y + (255 - k) * dst_y[1]) / 255; + dst_y[1] = (k * Y2 + (255 - k) * dst_y[1]) / 255; k2 /= 4; dst_u[0] = (k2 * U + (255 - k2) * dst_u[0]) / 255; @@ -675,10 +705,8 @@ blit_i420 (GstDVBSubOverlay * overlay, DVBSubtitles * subs, GstBuffer * buffer) } if (x < w) { - /* FIXME: Completely wrong blending code */ color = sub_region->pict.palette[src[0]]; - color2 = sub_region->pict.palette[src[1]]; - alpha = 255 - ((color >> 24) & 0xff); + alpha = (color >> 24) & 0xff; r = (color >> 16) & 0xff; g = (color >> 8) & 0xff; b = color & 0xff; @@ -687,14 +715,14 @@ blit_i420 (GstDVBSubOverlay * overlay, DVBSubtitles * subs, GstBuffer * buffer) U = rgb_to_u (r, g, b); V = rgb_to_v (r, g, b); - k = src[0] * alpha / 255; + k = alpha; k2 = k; dst_y[0] = (k * Y + (255 - k) * dst_y[0]) / 255; src += src_stride; dst_y += y_stride; - k = src[0] * alpha / 255; + k = alpha; k2 += k; dst_y[0] = (k * Y + (255 - k) * dst_y[0]) / 255; @@ -716,10 +744,8 @@ blit_i420 (GstDVBSubOverlay * overlay, DVBSubtitles * subs, GstBuffer * buffer) if (y < h) { for (x = 0; x < w - 1; x += 2) { - /* FIXME: Completely wrong blending code */ color = sub_region->pict.palette[src[0]]; - color2 = sub_region->pict.palette[src[1]]; - alpha = 255 - ((color >> 24) & 0xff); + alpha = (color >> 24) & 0xff; r = (color >> 16) & 0xff; g = (color >> 8) & 0xff; b = color & 0xff; @@ -728,13 +754,23 @@ blit_i420 (GstDVBSubOverlay * overlay, DVBSubtitles * subs, GstBuffer * buffer) U = rgb_to_u (r, g, b); V = rgb_to_v (r, g, b); - k = src[0] * alpha / 255; + color2 = sub_region->pict.palette[src[1]]; + alpha2 = (color2 >> 24) & 0xff; + r2 = (color2 >> 16) & 0xff; + g2 = (color2 >> 8) & 0xff; + b2 = color2 & 0xff; + + Y2 = rgb_to_y (r2, g2, b2); + U2 = rgb_to_u (r2, g2, b2); + V2 = rgb_to_v (r2, g2, b2); + + k = alpha; k2 = k; dst_y[0] = (k * Y + (255 - k) * dst_y[0]) / 255; - k = src[1] * alpha / 255; + k = alpha2; k2 += k; - dst_y[1] = (k * Y + (255 - k) * dst_y[1]) / 255; + dst_y[1] = (k * Y2 + (255 - k) * dst_y[1]) / 255; k2 /= 2; dst_u[0] = (k2 * U + (255 - k2) * dst_u[0]) / 255; @@ -747,10 +783,8 @@ blit_i420 (GstDVBSubOverlay * overlay, DVBSubtitles * subs, GstBuffer * buffer) } if (x < w) { - /* FIXME: Completely wrong blending code */ color = sub_region->pict.palette[src[0]]; - color2 = sub_region->pict.palette[src[1]]; - alpha = 255 - ((color >> 24) & 0xff); + alpha = (color >> 24) & 0xff; r = (color >> 16) & 0xff; g = (color >> 8) & 0xff; b = color & 0xff; @@ -759,7 +793,7 @@ blit_i420 (GstDVBSubOverlay * overlay, DVBSubtitles * subs, GstBuffer * buffer) U = rgb_to_u (r, g, b); V = rgb_to_v (r, g, b); - k = src[0] * alpha / 255; + k = alpha; k2 = k; dst_y[0] = (k * Y + (255 - k) * dst_y[0]) / 255; From 2a976ae133863a24e319a195df4a4fdc64148909 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Fri, 3 Dec 2010 15:46:40 +0100 Subject: [PATCH 015/448] dvbsuboverlay: Remove lots of commented out and unused code and clean up locking --- gst/dvbsuboverlay/gstdvbsuboverlay.c | 333 ++------------------------- gst/dvbsuboverlay/gstdvbsuboverlay.h | 15 +- 2 files changed, 22 insertions(+), 326 deletions(-) diff --git a/gst/dvbsuboverlay/gstdvbsuboverlay.c b/gst/dvbsuboverlay/gstdvbsuboverlay.c index 5dbdf61848..7740ba7787 100644 --- a/gst/dvbsuboverlay/gstdvbsuboverlay.c +++ b/gst/dvbsuboverlay/gstdvbsuboverlay.c @@ -60,26 +60,14 @@ enum static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, - GST_STATIC_CAPS ( -#ifdef DVBSUB_OVERLAY_RGB_SUPPORT - GST_VIDEO_CAPS_RGB ";" GST_VIDEO_CAPS_BGR ";" - GST_VIDEO_CAPS_xRGB ";" GST_VIDEO_CAPS_xBGR ";" - GST_VIDEO_CAPS_RGBx ";" GST_VIDEO_CAPS_BGRx ";" -#endif - GST_VIDEO_CAPS_YUV ("I420")) + GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("I420")) ); static GstStaticPadTemplate video_sink_factory = - GST_STATIC_PAD_TEMPLATE ("video_sink", +GST_STATIC_PAD_TEMPLATE ("video_sink", GST_PAD_SINK, GST_PAD_ALWAYS, - GST_STATIC_CAPS ( -#ifdef DVBSUB_OVERLAY_RGB_SUPPORT - GST_VIDEO_CAPS_RGB ";" GST_VIDEO_CAPS_BGR ";" - GST_VIDEO_CAPS_xRGB ";" GST_VIDEO_CAPS_xBGR ";" - GST_VIDEO_CAPS_RGBx ";" GST_VIDEO_CAPS_BGRx ";" -#endif - GST_VIDEO_CAPS_YUV ("I420")) + GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("I420")) ); static GstStaticPadTemplate text_sink_factory = @@ -96,10 +84,6 @@ static void gst_dvbsub_overlay_get_property (GObject * object, guint prop_id, static void gst_dvbsub_overlay_finalize (GObject * object); -#define GST_DVBSUB_OVERLAY_GET_COND(ov) (((GstDVBSubOverlay *)ov)->subtitle_cond) -#define GST_DVBSUB_OVERLAY_WAIT(ov) (g_cond_wait (GST_DVBSUB_OVERLAY_GET_COND (ov), GST_OBJECT_GET_LOCK (ov))) -#define GST_DVBSUB_OVERLAY_BROADCAST(ov) (g_cond_broadcast (GST_DVBSUB_OVERLAY_GET_COND (ov))) - static GstStateChangeReturn gst_dvbsub_overlay_change_state (GstElement * element, GstStateChange transition); @@ -109,7 +93,6 @@ GST_BOILERPLATE (GstDVBSubOverlay, gst_dvbsub_overlay, GstElement, static GstCaps *gst_dvbsub_overlay_getcaps (GstPad * pad); static gboolean gst_dvbsub_overlay_setcaps_video (GstPad * pad, GstCaps * caps); -static gboolean gst_dvbsub_overlay_setcaps_text (GstPad * pad, GstCaps * caps); static GstFlowReturn gst_dvbsub_overlay_chain_video (GstPad * pad, GstBuffer * buf); @@ -140,7 +123,10 @@ gst_dvbsub_overlay_base_init (gpointer gclass) gst_element_class_add_pad_template (element_class, gst_static_pad_template_get (&text_sink_factory)); - gst_element_class_set_details_simple (element_class, "DVB Subtitles Overlay", "Mixer/Video/Overlay/Subtitle", "Renders DVB subtitles", "Mart Raudsepp "); // FIXME: Credit assrender and textoverlay? + gst_element_class_set_details_simple (element_class, + "DVB Subtitles Overlay", + "Mixer/Video/Overlay/Subtitle", + "Renders DVB subtitles", "Mart Raudsepp "); } /* initialize the plugin's class */ @@ -198,8 +184,6 @@ gst_dvbsub_overlay_init (GstDVBSubOverlay * render, gst_pad_set_setcaps_function (render->video_sinkpad, GST_DEBUG_FUNCPTR (gst_dvbsub_overlay_setcaps_video)); - gst_pad_set_setcaps_function (render->text_sinkpad, - GST_DEBUG_FUNCPTR (gst_dvbsub_overlay_setcaps_text)); gst_pad_set_getcaps_function (render->srcpad, GST_DEBUG_FUNCPTR (gst_dvbsub_overlay_getcaps)); @@ -231,13 +215,9 @@ gst_dvbsub_overlay_init (GstDVBSubOverlay * render, render->width = 0; render->height = 0; - render->subtitle_mutex = g_mutex_new (); - render->subtitle_cond = g_cond_new (); - render->current_subtitle = NULL; render->pending_subtitles = g_queue_new (); - render->renderer_init_ok = FALSE; render->enable = TRUE; gst_segment_init (&render->video_segment, GST_FORMAT_TIME); @@ -247,7 +227,6 @@ gst_dvbsub_overlay_init (GstDVBSubOverlay * render, dvb_sub_set_global_log_cb (_dvbsub_log_cb, render); - render->dvb_sub = dvb_sub_new (); if (!render->dvb_sub) { GST_WARNING_OBJECT (render, "cannot create dvbsub instance"); @@ -266,17 +245,12 @@ static void gst_dvbsub_overlay_finalize (GObject * object) { GstDVBSubOverlay *overlay = GST_DVBSUB_OVERLAY (object); + DVBSubtitles *subs; - if (overlay->subtitle_mutex) - g_mutex_free (overlay->subtitle_mutex); - - if (overlay->subtitle_cond) - g_cond_free (overlay->subtitle_cond); - - if (overlay->pending_subtitles) { - /* FIXME: Free up contents */ - g_queue_free (overlay->pending_subtitles); + while ((subs = g_queue_pop_head (overlay->pending_subtitles))) { + dvb_subtitles_free (subs); } + g_queue_free (overlay->pending_subtitles); if (overlay->dvb_sub) { g_object_unref (overlay->dvb_sub); @@ -329,7 +303,6 @@ gst_dvbsub_overlay_change_state (GstElement * element, switch (transition) { case GST_STATE_CHANGE_READY_TO_PAUSED: - render->subtitle_flushing = FALSE; gst_segment_init (&render->video_segment, GST_FORMAT_TIME); gst_segment_init (&render->subtitle_segment, GST_FORMAT_TIME); break; @@ -337,24 +310,12 @@ gst_dvbsub_overlay_change_state (GstElement * element, case GST_STATE_CHANGE_PAUSED_TO_PLAYING: default: break; - - case GST_STATE_CHANGE_PAUSED_TO_READY: - g_mutex_lock (render->subtitle_mutex); - render->subtitle_flushing = TRUE; - if (render->subtitle_pending) - gst_buffer_unref (render->subtitle_pending); - render->subtitle_pending = NULL; - g_cond_signal (render->subtitle_cond); - g_mutex_unlock (render->subtitle_mutex); - break; } ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); switch (transition) { case GST_STATE_CHANGE_PAUSED_TO_READY: - render->renderer_init_ok = FALSE; - break; case GST_STATE_CHANGE_PLAYING_TO_PAUSED: case GST_STATE_CHANGE_READY_TO_NULL: default: @@ -395,14 +356,7 @@ gst_dvbsub_overlay_event_src (GstPad * pad, GstEvent * event) if (flags & GST_SEEK_FLAG_FLUSH) gst_pad_push_event (render->srcpad, gst_event_new_flush_start ()); - /* Mark subtitle as flushing, unblocks chains */ - g_mutex_lock (render->subtitle_mutex); - if (render->subtitle_pending) - gst_buffer_unref (render->subtitle_pending); - render->subtitle_pending = NULL; - render->subtitle_flushing = TRUE; - g_cond_signal (render->subtitle_cond); - g_mutex_unlock (render->subtitle_mutex); + /* FIXME: flush subtitles */ /* Seek on each sink pad */ gst_event_ref (event); @@ -460,72 +414,6 @@ gst_dvbsub_overlay_getcaps (GstPad * pad) return caps; } -#ifdef DVBSUB_OVERLAY_RGB_SUPPORT - -#define CREATE_RGB_BLIT_FUNCTION(name,bpp,R,G,B) \ -static void \ -blit_##name (GstDVBSubOverlay * overlay, DVBSubtitles * subs, GstBuffer * buffer) \ -{ \ - guint counter; \ - DVBSubtitleRect *sub_region; \ - gint alpha, r, g, b, k; \ - guint32 color; \ - const guint8 *src; \ - guint8 *dst; \ - gint x, y, w, h; \ - gint width = overlay->width; \ - gint height = overlay->height; \ - gint dst_stride = GST_ROUND_UP_4 (width * bpp); \ - gint dst_skip; \ - gint src_stride, src_skip; \ - \ - for (counter = 0; counter < subs->num_rects; counter++) { \ - sub_region = subs->rects[counter]; \ - if (sub_region->y > height || sub_region->x > width) \ - continue; \ - \ - /* blend subtitles onto the video frame */ \ - src = sub_region->pict.data; \ - dst = buffer->data + sub_region->y * dst_stride + sub_region->x * bpp; \ - \ - w = MIN (sub_region->w, width - sub_region->x); \ - h = MIN (sub_region->h, height - sub_region->y); \ - src_stride = sub_region->pict.rowstride; \ - src_skip = sub_region->pict.rowstride - w; \ - dst_skip = dst_stride - w * bpp; \ - \ - for (y = 0; y < h; y++) { \ - for (x = 0; x < w; x++) { \ - color = sub_region->pict.palette[src[0]]; \ - alpha = 255 - (color & 0xff); /* FIXME: We get ARGB, not RGBA as assumed here */ \ - r = (color >> 24) & 0xff; \ - g = (color >> 16) & 0xff; \ - b = (color >> 8) & 0xff; \ - k = color * alpha / 255; /* FIXME */ \ - dst[R] = (k * r + (255 - k) * dst[R]) / 255; \ - dst[G] = (k * g + (255 - k) * dst[G]) / 255; \ - dst[B] = (k * b + (255 - k) * dst[B]) / 255; \ - src++; \ - dst += bpp; \ - } \ - src += src_skip; \ - dst += dst_skip; \ - } \ - } \ - GST_LOG_OBJECT (overlay, "amount of rendered DVBSubtitleRect: %u", counter); \ -} - -CREATE_RGB_BLIT_FUNCTION (rgb, 3, 0, 1, 2); -CREATE_RGB_BLIT_FUNCTION (bgr, 3, 2, 1, 0); -CREATE_RGB_BLIT_FUNCTION (xrgb, 4, 1, 2, 3); -CREATE_RGB_BLIT_FUNCTION (xbgr, 4, 3, 2, 1); -CREATE_RGB_BLIT_FUNCTION (rgbx, 4, 0, 1, 2); -CREATE_RGB_BLIT_FUNCTION (bgrx, 4, 2, 1, 0); - -#undef CREATE_RGB_BLIT_FUNCTION - -#endif - static inline gint rgb_to_y (gint r, gint g, gint b) { @@ -811,8 +699,6 @@ gst_dvbsub_overlay_setcaps_video (GstPad * pad, GstCaps * caps) { GstDVBSubOverlay *render = GST_DVBSUB_OVERLAY (gst_pad_get_parent (pad)); gboolean ret = FALSE; - gint par_n = 1, par_d = 1; - gdouble dar; render->width = 0; render->height = 0; @@ -825,57 +711,13 @@ gst_dvbsub_overlay_setcaps_video (GstPad * pad, GstCaps * caps) goto out; } - gst_video_parse_caps_pixel_aspect_ratio (caps, &par_n, &par_d); + gst_video_parse_caps_pixel_aspect_ratio (caps, &render->par_n, + &render->par_d); ret = gst_pad_set_caps (render->srcpad, caps); if (!ret) goto out; - switch (render->format) { -#ifdef DVBSUB_OVERLAY_RGB_SUPPORT - case GST_VIDEO_FORMAT_RGB: - render->blit = blit_rgb; - break; - case GST_VIDEO_FORMAT_BGR: - render->blit = blit_bgr; - break; - case GST_VIDEO_FORMAT_xRGB: - render->blit = blit_xrgb; - break; - case GST_VIDEO_FORMAT_xBGR: - render->blit = blit_xbgr; - break; - case GST_VIDEO_FORMAT_RGBx: - render->blit = blit_rgbx; - break; - case GST_VIDEO_FORMAT_BGRx: - render->blit = blit_bgrx; - break; -#endif - case GST_VIDEO_FORMAT_I420: - render->blit = blit_i420; - break; - default: - ret = FALSE; - goto out; - } - - /* FIXME: We need to handle aspect ratio ourselves */ -#if 0 - g_mutex_lock (render->ass_mutex); - ass_set_frame_size (render->ass_renderer, render->width, render->height); -#endif - dar = (((gdouble) par_n) * ((gdouble) render->width)) - / (((gdouble) par_d) * ((gdouble) render->height)); -#if 0 - ass_set_aspect_ratio (render->ass_renderer, - dar, ((gdouble) render->width) / ((gdouble) render->height)); - - g_mutex_unlock (render->ass_mutex); -#endif - - render->renderer_init_ok = TRUE; - GST_DEBUG_OBJECT (render, "ass renderer setup complete"); out: @@ -884,70 +726,10 @@ out: return ret; } -static gboolean -gst_dvbsub_overlay_setcaps_text (GstPad * pad, GstCaps * caps) -{ - GstDVBSubOverlay *render = GST_DVBSUB_OVERLAY (gst_pad_get_parent (pad)); - GstStructure *structure; - const GValue *value; -#if 0 // FIXME - GstBuffer *priv; - gchar *codec_private; - guint codec_private_size; -#endif - gboolean ret = FALSE; - - structure = gst_caps_get_structure (caps, 0); - - GST_DEBUG_OBJECT (render, "text pad linked with caps: %" GST_PTR_FORMAT, - caps); - - value = gst_structure_get_value (structure, "codec_data"); - - /* FIXME: */ -#if 0 - g_mutex_lock (render->ass_mutex); - if (value != NULL) { - priv = gst_value_get_buffer (value); - g_return_val_if_fail (priv != NULL, FALSE); - - codec_private = (gchar *) GST_BUFFER_DATA (priv); - codec_private_size = GST_BUFFER_SIZE (priv); - - if (!render->ass_track) - render->ass_track = ass_new_track (render->ass_library); - - ass_process_codec_private (render->ass_track, - codec_private, codec_private_size); - - GST_DEBUG_OBJECT (render, "ass track created"); - - render->track_init_ok = TRUE; - - ret = TRUE; - } else if (!render->ass_track) { - render->ass_track = ass_new_track (render->ass_library); - - render->track_init_ok = TRUE; - - ret = TRUE; - } - g_mutex_unlock (render->ass_mutex); -#endif - - gst_object_unref (render); - - // FIXME - ret = TRUE; - - return ret; -} - static void gst_dvbsub_overlay_process_text (GstDVBSubOverlay * overlay, GstBuffer * buffer, guint64 pts) { - /* FIXME: Locking in this function? */ guint8 *data = (guint8 *) GST_BUFFER_DATA (buffer); guint size = GST_BUFFER_SIZE (buffer); @@ -956,9 +738,7 @@ gst_dvbsub_overlay_process_text (GstDVBSubOverlay * overlay, GstBuffer * buffer, " which is a running time of %" GST_TIME_FORMAT, pts, GST_TIME_ARGS (pts)); GST_DEBUG_OBJECT (overlay, "Feeding %u bytes to libdvbsub", size); - g_mutex_lock (overlay->dvbsub_mutex); /* FIXME: Use standard lock? */ dvb_sub_feed_with_pts (overlay->dvb_sub, pts, data, size); - g_mutex_unlock (overlay->dvbsub_mutex); gst_buffer_unref (buffer); } @@ -966,14 +746,16 @@ static void new_dvb_subtitles_cb (DvbSub * dvb_sub, DVBSubtitles * subs, gpointer user_data) { GstDVBSubOverlay *overlay = GST_DVBSUB_OVERLAY (user_data); + GST_INFO_OBJECT (overlay, "New DVB subtitles arrived with a page_time_out of %d and %d regions for PTS=%" G_GUINT64_FORMAT ", which should be at running time %" GST_TIME_FORMAT, subs->page_time_out, subs->num_rects, subs->pts, GST_TIME_ARGS (subs->pts)); - //GST_OBJECT_LOCK (overlay); + + g_mutex_lock (overlay->dvbsub_mutex); g_queue_push_tail (overlay->pending_subtitles, subs); - //GST_OBJECT_UNLOCK (overlay); + g_mutex_unlock (overlay->dvbsub_mutex); } static GstFlowReturn @@ -1009,20 +791,6 @@ gst_dvbsub_overlay_chain_text (GstPad * pad, GstBuffer * buffer) GST_INFO_OBJECT (overlay, "private/x-dvbsub buffer with size %u", GST_BUFFER_SIZE (buffer)); - GST_OBJECT_LOCK (overlay); - - if (overlay->subtitle_flushing) { - GST_OBJECT_UNLOCK (overlay); - GST_LOG_OBJECT (overlay, "text flushing"); - return GST_FLOW_WRONG_STATE; - } - - if (overlay->subtitle_eos) { - GST_OBJECT_UNLOCK (overlay); - GST_LOG_OBJECT (overlay, "text EOS"); - return GST_FLOW_UNEXPECTED; - } - GST_LOG_OBJECT (overlay, "Video segment: %" GST_SEGMENT_FORMAT " --- Subtitle segment: %" GST_SEGMENT_FORMAT " --- BUFFER: ts=%" GST_TIME_FORMAT, @@ -1031,7 +799,6 @@ gst_dvbsub_overlay_chain_text (GstPad * pad, GstBuffer * buffer) /* DVB subtitle packets are required to carry the PTS */ if (G_UNLIKELY (!GST_BUFFER_TIMESTAMP_IS_VALID (buffer))) { - GST_OBJECT_UNLOCK (overlay); GST_WARNING_OBJECT (overlay, "Text buffer without valid timestamp, dropping"); gst_buffer_unref (buffer); @@ -1058,23 +825,6 @@ gst_dvbsub_overlay_chain_text (GstPad * pad, GstBuffer * buffer) gst_buffer_unref (buffer); return GST_FLOW_OK; } -#if 0 /* In case of DVB-SUB, we get notified of the shown subtitle going away by the next - * page composition, so we can't just wait for the buffer to go away (unless we keep - * non-rendered raw DVBSubtitleRects or DVBSubtitlePicture in there, which is - * suboptimal */ - /* Wait for the previous buffer to go away */ - while (overlay->subtitle_buffer > 0) { - GST_DEBUG ("Pad %s:%s has a buffer queued, waiting", - GST_DEBUG_PAD_NAME (pad)); - GST_DVBSUB_OVERLAY_WAIT (overlay); - GST_DEBUG ("Pad %s:%s resuming", GST_DEBUG_PAD_NAME (pad)); - if (overlay->subtitle_flushing) { - GST_OBJECT_UNLOCK (overlay); - /* FIXME: No need to unref buffer? */ - return GST_FLOW_WRONG_STATE; - } - } -#endif /* FIXME: How is this useful? */ gst_segment_set_last_stop (&overlay->subtitle_segment, GST_FORMAT_TIME, @@ -1087,17 +837,9 @@ gst_dvbsub_overlay_chain_text (GstPad * pad, GstBuffer * buffer) GST_DEBUG_OBJECT (overlay, "SUBTITLE real running time: %" GST_TIME_FORMAT, GST_TIME_ARGS (sub_running_time)); - /* That's a new text buffer we need to render */ - /*overlay->need_render = TRUE; *//* FIXME: Actually feed it to libdvbsub and set need_render on a callback */ - /* FIXME: We are abusing libdvbsub pts value for tracking our gstreamer running time instead of real PTS. Should be mostly fine though... */ gst_dvbsub_overlay_process_text (overlay, buffer, sub_running_time); - /* in case the video chain is waiting for a text buffer, wake it up */ - GST_DVBSUB_OVERLAY_BROADCAST (overlay); - - GST_OBJECT_UNLOCK (overlay); - return GST_FLOW_OK; } @@ -1138,6 +880,7 @@ gst_dvbsub_overlay_chain_video (GstPad * pad, GstBuffer * buffer) /* FIXME: Segment clipping code */ + g_mutex_lock (overlay->dvbsub_mutex); if (!g_queue_is_empty (overlay->pending_subtitles)) { DVBSubtitles *pending_sub = g_queue_peek_head (overlay->pending_subtitles); if (vid_running_time >= pending_sub->pts) { @@ -1169,6 +912,7 @@ gst_dvbsub_overlay_chain_video (GstPad * pad, GstBuffer * buffer) buffer = gst_buffer_make_writable (buffer); blit_i420 (overlay, overlay->current_subtitle, buffer); } + g_mutex_unlock (overlay->dvbsub_mutex); ret = gst_pad_push (overlay->srcpad, buffer); @@ -1237,7 +981,6 @@ gst_dvbsub_overlay_event_video (GstPad * pad, GstEvent * event) static gboolean gst_dvbsub_overlay_event_text (GstPad * pad, GstEvent * event) { - //gint i; // FIXME gboolean ret = FALSE; GstDVBSubOverlay *render = GST_DVBSUB_OVERLAY (gst_pad_get_parent (pad)); @@ -1253,8 +996,6 @@ gst_dvbsub_overlay_event_text (GstPad * pad, GstEvent * event) GST_DEBUG_OBJECT (render, "received new segment"); - /* FIXME: overlay */ render->subtitle_eos = FALSE; - gst_event_parse_new_segment (event, &update, &rate, &format, &start, &stop, &time); @@ -1272,20 +1013,14 @@ gst_dvbsub_overlay_event_text (GstPad * pad, GstEvent * event) gst_event_unref (event); } else { GST_ELEMENT_WARNING (render, STREAM, MUX, (NULL), - ("received non-TIME newsegment event on subtitle input")); + ("received non-TIME newsegment event on subtitle sinkpad")); ret = FALSE; gst_event_unref (event); } - /* FIXME: Not fully compared with textoverlay */ - GST_OBJECT_LOCK (render); - GST_DVBSUB_OVERLAY_BROADCAST (render); - GST_OBJECT_UNLOCK (render); break; } case GST_EVENT_FLUSH_STOP: gst_segment_init (&render->subtitle_segment, GST_FORMAT_TIME); - render->subtitle_flushing = FALSE; - /*FIXME: overlay */ render->subtitle_eos = FALSE; gst_event_unref (event); ret = TRUE; break; @@ -1293,37 +1028,11 @@ gst_dvbsub_overlay_event_text (GstPad * pad, GstEvent * event) GST_DEBUG_OBJECT (render, "begin flushing"); /* FIXME: Reset subtitles queue and any other state */ -#if 0 // FIXME - g_mutex_lock (render->ass_mutex); - if (render->ass_track) { - /* delete any events on the ass_track */ - for (i = 0; i < render->ass_track->n_events; i++) { - GST_DEBUG_OBJECT (render, "deleted event with eid %i", i); - ass_free_event (render->ass_track, i); - } - render->ass_track->n_events = 0; - GST_DEBUG_OBJECT (render, "done flushing"); - } - g_mutex_unlock (render->ass_mutex); -#endif - g_mutex_lock (render->subtitle_mutex); - if (render->subtitle_pending) - gst_buffer_unref (render->subtitle_pending); - render->subtitle_pending = NULL; - render->subtitle_flushing = TRUE; - GST_DVBSUB_OVERLAY_BROADCAST (render); - g_mutex_unlock (render->subtitle_mutex); gst_event_unref (event); ret = TRUE; break; case GST_EVENT_EOS: - GST_OBJECT_LOCK (render); - /*FIXME: overlay */ render->subtitle_eos = TRUE; GST_INFO_OBJECT (render, "text EOS"); - /* wake up the video chain, it might be waiting for a text buffer or - * a text segment update */ - GST_DVBSUB_OVERLAY_BROADCAST (render); - GST_OBJECT_UNLOCK (render); gst_event_unref (event); ret = TRUE; break; diff --git a/gst/dvbsuboverlay/gstdvbsuboverlay.h b/gst/dvbsuboverlay/gstdvbsuboverlay.h index 62290c777e..c8d392f64d 100644 --- a/gst/dvbsuboverlay/gstdvbsuboverlay.h +++ b/gst/dvbsuboverlay/gstdvbsuboverlay.h @@ -34,7 +34,6 @@ G_BEGIN_DECLS typedef struct _GstDVBSubOverlay GstDVBSubOverlay; typedef struct _GstDVBSubOverlayClass GstDVBSubOverlayClass; -typedef void (*GstAssRenderBlitFunction) (GstDVBSubOverlay *overlay, DVBSubtitles *subs, GstBuffer *buffer); struct _GstDVBSubOverlay { @@ -52,26 +51,14 @@ struct _GstDVBSubOverlay GstVideoFormat format; gint width, height; gint fps_n, fps_d; - GstAssRenderBlitFunction blit; + gint par_n, par_d; DVBSubtitles *current_subtitle; /* The currently active set of subtitle regions, if any */ GQueue *pending_subtitles; /* A queue of raw subtitle region sets with * metadata that are waiting their running time */ - GMutex *subtitle_mutex; - GCond *subtitle_cond; /* to signal removal of a queued text - * buffer, arrival of a text buffer, - * a text segment update, or a change - * in status (e.g. shutdown, flushing) - * FIXME: Update comment for dvbsub case */ - GstBuffer *subtitle_pending; - gboolean subtitle_flushing; - gboolean subtitle_eos; - GMutex *dvbsub_mutex; /* FIXME: Do we need a mutex lock in case of libdvbsub? Probably, but... */ DvbSub *dvb_sub; - - gboolean renderer_init_ok; }; struct _GstDVBSubOverlayClass From 472cace08b92d364a86b274e1ea732e9aac30e4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Fri, 3 Dec 2010 15:52:21 +0100 Subject: [PATCH 016/448] dvbsuboverlay: Set the global library log function exactly once And don't use one of the possibly many renderer instances, this is only calling for crashes. --- gst/dvbsuboverlay/gstdvbsuboverlay.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/gst/dvbsuboverlay/gstdvbsuboverlay.c b/gst/dvbsuboverlay/gstdvbsuboverlay.c index 7740ba7787..df83372618 100644 --- a/gst/dvbsuboverlay/gstdvbsuboverlay.c +++ b/gst/dvbsuboverlay/gstdvbsuboverlay.c @@ -155,16 +155,15 @@ _dvbsub_log_cb (GLogLevelFlags level, const gchar * fmt, va_list args, gchar *message = g_strdup_vprintf (fmt, args); if (level & G_LOG_LEVEL_ERROR) - GST_CAT_ERROR_OBJECT (gst_dvbsub_overlay_lib_debug, render, "%s", message); + GST_CAT_ERROR (gst_dvbsub_overlay_lib_debug, "%s", message); else if (level & G_LOG_LEVEL_WARNING) - GST_CAT_WARNING_OBJECT (gst_dvbsub_overlay_lib_debug, render, "%s", - message); + GST_CAT_WARNING (gst_dvbsub_overlay_lib_debug, "%s", message); else if (level & G_LOG_LEVEL_INFO) - GST_CAT_INFO_OBJECT (gst_dvbsub_overlay_lib_debug, render, "%s", message); + GST_CAT_INFO (gst_dvbsub_overlay_lib_debug, "%s", message); else if (level & G_LOG_LEVEL_DEBUG) - GST_CAT_DEBUG_OBJECT (gst_dvbsub_overlay_lib_debug, render, "%s", message); + GST_CAT_DEBUG (gst_dvbsub_overlay_lib_debug, "%s", message); else - GST_CAT_LOG_OBJECT (gst_dvbsub_overlay_lib_debug, render, + GST_CAT_LOG (gst_dvbsub_overlay_lib_debug, "log level %d: %s", level, message); g_free (message); @@ -225,8 +224,6 @@ gst_dvbsub_overlay_init (GstDVBSubOverlay * render, render->dvbsub_mutex = g_mutex_new (); - dvb_sub_set_global_log_cb (_dvbsub_log_cb, render); - render->dvb_sub = dvb_sub_new (); if (!render->dvb_sub) { GST_WARNING_OBJECT (render, "cannot create dvbsub instance"); @@ -1054,6 +1051,8 @@ plugin_init (GstPlugin * plugin) GST_DEBUG_CATEGORY_INIT (gst_dvbsub_overlay_lib_debug, "dvbsub_library", 0, "libdvbsub library"); + dvb_sub_set_global_log_cb (_dvbsub_log_cb, NULL); + return gst_element_register (plugin, "dvbsuboverlay", GST_RANK_PRIMARY, GST_TYPE_DVBSUB_OVERLAY); } From 92109fdfbcefb92528b6b357f042c73205d579c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Fri, 3 Dec 2010 16:05:56 +0100 Subject: [PATCH 017/448] dvbsuboverlay: Flush subtitles and all internal state when needed --- gst/dvbsuboverlay/gstdvbsuboverlay.c | 56 ++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 16 deletions(-) diff --git a/gst/dvbsuboverlay/gstdvbsuboverlay.c b/gst/dvbsuboverlay/gstdvbsuboverlay.c index df83372618..75fdf9d0ee 100644 --- a/gst/dvbsuboverlay/gstdvbsuboverlay.c +++ b/gst/dvbsuboverlay/gstdvbsuboverlay.c @@ -169,6 +169,32 @@ _dvbsub_log_cb (GLogLevelFlags level, const gchar * fmt, va_list args, g_free (message); } +static void +gst_dvbsub_overlay_flush_subtitles (GstDVBSubOverlay * render) +{ + DVBSubtitles *subs; + + g_mutex_lock (render->dvbsub_mutex); + while ((subs = g_queue_pop_head (render->pending_subtitles))) { + dvb_subtitles_free (subs); + } + + if (render->dvb_sub) + g_object_unref (render->dvb_sub); + render->dvb_sub = dvb_sub_new (); + if (!render->dvb_sub) { + GST_WARNING_OBJECT (render, "cannot create dvbsub instance"); + g_assert_not_reached (); + } + + { + DvbSubCallbacks dvbsub_callbacks = { &new_dvb_subtitles_cb, }; + dvb_sub_set_callbacks (render->dvb_sub, &dvbsub_callbacks, render); + } + + g_mutex_unlock (render->dvbsub_mutex); +} + static void gst_dvbsub_overlay_init (GstDVBSubOverlay * render, GstDVBSubOverlayClass * gclass) @@ -219,22 +245,12 @@ gst_dvbsub_overlay_init (GstDVBSubOverlay * render, render->enable = TRUE; + render->dvbsub_mutex = g_mutex_new (); + gst_dvbsub_overlay_flush_subtitles (render); + gst_segment_init (&render->video_segment, GST_FORMAT_TIME); gst_segment_init (&render->subtitle_segment, GST_FORMAT_TIME); - render->dvbsub_mutex = g_mutex_new (); - - render->dvb_sub = dvb_sub_new (); - if (!render->dvb_sub) { - GST_WARNING_OBJECT (render, "cannot create dvbsub instance"); - g_assert_not_reached (); - } - - { - DvbSubCallbacks dvbsub_callbacks = { &new_dvb_subtitles_cb, }; - dvb_sub_set_callbacks (render->dvb_sub, &dvbsub_callbacks, render); - } - GST_DEBUG_OBJECT (render, "init complete"); } @@ -313,6 +329,11 @@ gst_dvbsub_overlay_change_state (GstElement * element, switch (transition) { case GST_STATE_CHANGE_PAUSED_TO_READY: + gst_dvbsub_overlay_flush_subtitles (render); + gst_segment_init (&render->video_segment, GST_FORMAT_TIME); + gst_segment_init (&render->subtitle_segment, GST_FORMAT_TIME); + render->format = GST_VIDEO_FORMAT_UNKNOWN; + break; case GST_STATE_CHANGE_PLAYING_TO_PAUSED: case GST_STATE_CHANGE_READY_TO_NULL: default: @@ -353,7 +374,7 @@ gst_dvbsub_overlay_event_src (GstPad * pad, GstEvent * event) if (flags & GST_SEEK_FLAG_FLUSH) gst_pad_push_event (render->srcpad, gst_event_new_flush_start ()); - /* FIXME: flush subtitles */ + gst_dvbsub_overlay_flush_subtitles (render); /* Seek on each sink pad */ gst_event_ref (event); @@ -848,6 +869,9 @@ gst_dvbsub_overlay_chain_video (GstPad * pad, GstBuffer * buffer) gint64 start, stop; GstClockTime vid_running_time; + if (overlay->format == GST_VIDEO_FORMAT_UNKNOWN) + return GST_FLOW_NOT_NEGOTIATED; + if (!GST_BUFFER_TIMESTAMP_IS_VALID (buffer)) goto missing_timestamp; @@ -1017,14 +1041,14 @@ gst_dvbsub_overlay_event_text (GstPad * pad, GstEvent * event) break; } case GST_EVENT_FLUSH_STOP: + GST_DEBUG_OBJECT (render, "stop flushing"); + gst_dvbsub_overlay_flush_subtitles (render); gst_segment_init (&render->subtitle_segment, GST_FORMAT_TIME); gst_event_unref (event); ret = TRUE; break; case GST_EVENT_FLUSH_START: GST_DEBUG_OBJECT (render, "begin flushing"); - - /* FIXME: Reset subtitles queue and any other state */ gst_event_unref (event); ret = TRUE; break; From 672cb276be21f8a54826f10d8ba062b3f753de5b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Fri, 3 Dec 2010 16:08:13 +0100 Subject: [PATCH 018/448] dvbsuboverlay: Clean up locking some more --- gst/dvbsuboverlay/gstdvbsuboverlay.c | 4 ++-- gst/dvbsuboverlay/gstdvbsuboverlay.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gst/dvbsuboverlay/gstdvbsuboverlay.c b/gst/dvbsuboverlay/gstdvbsuboverlay.c index 75fdf9d0ee..07d74cf7be 100644 --- a/gst/dvbsuboverlay/gstdvbsuboverlay.c +++ b/gst/dvbsuboverlay/gstdvbsuboverlay.c @@ -756,7 +756,9 @@ gst_dvbsub_overlay_process_text (GstDVBSubOverlay * overlay, GstBuffer * buffer, " which is a running time of %" GST_TIME_FORMAT, pts, GST_TIME_ARGS (pts)); GST_DEBUG_OBJECT (overlay, "Feeding %u bytes to libdvbsub", size); + g_mutex_lock (overlay->dvbsub_mutex); dvb_sub_feed_with_pts (overlay->dvb_sub, pts, data, size); + g_mutex_unlock (overlay->dvbsub_mutex); gst_buffer_unref (buffer); } @@ -771,9 +773,7 @@ new_dvb_subtitles_cb (DvbSub * dvb_sub, DVBSubtitles * subs, gpointer user_data) subs->page_time_out, subs->num_rects, subs->pts, GST_TIME_ARGS (subs->pts)); - g_mutex_lock (overlay->dvbsub_mutex); g_queue_push_tail (overlay->pending_subtitles, subs); - g_mutex_unlock (overlay->dvbsub_mutex); } static GstFlowReturn diff --git a/gst/dvbsuboverlay/gstdvbsuboverlay.h b/gst/dvbsuboverlay/gstdvbsuboverlay.h index c8d392f64d..1b2b0b0669 100644 --- a/gst/dvbsuboverlay/gstdvbsuboverlay.h +++ b/gst/dvbsuboverlay/gstdvbsuboverlay.h @@ -57,7 +57,7 @@ struct _GstDVBSubOverlay GQueue *pending_subtitles; /* A queue of raw subtitle region sets with * metadata that are waiting their running time */ - GMutex *dvbsub_mutex; /* FIXME: Do we need a mutex lock in case of libdvbsub? Probably, but... */ + GMutex *dvbsub_mutex; /* protects the queue and the DvbSub instance */ DvbSub *dvb_sub; }; From 01cf79ae59634f81ac3a089dfd66beba20d72ddf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Fri, 3 Dec 2010 16:21:15 +0100 Subject: [PATCH 019/448] dvbsuboverlay: Implement clipping of video buffers Also don't clip subpicture buffers, they have no duration and clipping them doesn't make much sense here. --- gst/dvbsuboverlay/gstdvbsuboverlay.c | 40 +++++++++++++--------------- 1 file changed, 18 insertions(+), 22 deletions(-) diff --git a/gst/dvbsuboverlay/gstdvbsuboverlay.c b/gst/dvbsuboverlay/gstdvbsuboverlay.c index 07d74cf7be..c0df91c220 100644 --- a/gst/dvbsuboverlay/gstdvbsuboverlay.c +++ b/gst/dvbsuboverlay/gstdvbsuboverlay.c @@ -802,8 +802,6 @@ static GstFlowReturn gst_dvbsub_overlay_chain_text (GstPad * pad, GstBuffer * buffer) { GstDVBSubOverlay *overlay = GST_DVBSUB_OVERLAY (GST_PAD_PARENT (pad)); - gint64 clip_start = 0, clip_stop = 0; - gboolean in_seg = FALSE; GstClockTime sub_running_time; GST_INFO_OBJECT (overlay, "private/x-dvbsub buffer with size %u", @@ -823,11 +821,6 @@ gst_dvbsub_overlay_chain_text (GstPad * pad, GstBuffer * buffer) return GST_FLOW_OK; } - /* FIXME: Is the faking of a zero duration buffer correct here? Probably a better way to check segment inclusion then than to clip as a side effect */ - in_seg = gst_segment_clip (&overlay->subtitle_segment, GST_FORMAT_TIME, - GST_BUFFER_TIMESTAMP (buffer), GST_BUFFER_TIMESTAMP (buffer), &clip_start, - &clip_stop); - /* As the passed start and stop is equal, we shouldn't need to care about out of segment at all, * the subtitle data for the PTS is completely out of interest to us. A given display set must * carry the same PTS value. */ @@ -835,18 +828,8 @@ gst_dvbsub_overlay_chain_text (GstPad * pad, GstBuffer * buffer) * FIXME: does our waiting + render code work when there are more than one packets before * FIXME: rendering callback will get called? */ - if (!in_seg) { - GST_DEBUG_OBJECT (overlay, - "Subtitle timestamp (%" GST_TIME_FORMAT - ") outside of the subtitle segment (%" GST_SEGMENT_FORMAT "), dropping", - GST_BUFFER_TIMESTAMP (buffer), &overlay->subtitle_segment); - gst_buffer_unref (buffer); - return GST_FLOW_OK; - } - - /* FIXME: How is this useful? */ gst_segment_set_last_stop (&overlay->subtitle_segment, GST_FORMAT_TIME, - clip_start); + GST_BUFFER_TIMESTAMP (buffer)); sub_running_time = gst_segment_to_running_time (&overlay->subtitle_segment, GST_FORMAT_TIME, @@ -867,6 +850,8 @@ gst_dvbsub_overlay_chain_video (GstPad * pad, GstBuffer * buffer) GstDVBSubOverlay *overlay = GST_DVBSUB_OVERLAY (GST_PAD_PARENT (pad)); GstFlowReturn ret = GST_FLOW_OK; gint64 start, stop; + gint64 cstart, cstop; + gboolean in_seg; GstClockTime vid_running_time; if (overlay->format == GST_VIDEO_FORMAT_UNKNOWN) @@ -890,16 +875,27 @@ gst_dvbsub_overlay_chain_video (GstPad * pad, GstBuffer * buffer) stop = start + GST_BUFFER_DURATION (buffer); } + in_seg = gst_segment_clip (&overlay->video_segment, GST_FORMAT_TIME, + start, stop, &cstart, &cstop); + if (!in_seg) { + GST_DEBUG_OBJECT (overlay, "Buffer outside configured segment -- dropping"); + gst_buffer_unref (buffer); + return GST_FLOW_OK; + } + + buffer = gst_buffer_make_metadata_writable (buffer); + GST_BUFFER_TIMESTAMP (buffer) = cstart; + if (GST_BUFFER_DURATION_IS_VALID (buffer)) + GST_BUFFER_DURATION (buffer) = cstop - cstart; + vid_running_time = gst_segment_to_running_time (&overlay->video_segment, GST_FORMAT_TIME, GST_BUFFER_TIMESTAMP (buffer)); - GST_DEBUG_OBJECT (overlay, "Video running time: %" GST_TIME_FORMAT, GST_TIME_ARGS (vid_running_time)); - /* FIXME: Probably update last_stop somewhere */ - - /* FIXME: Segment clipping code */ + gst_segment_set_last_stop (&overlay->video_segment, GST_FORMAT_TIME, + GST_BUFFER_TIMESTAMP (buffer)); g_mutex_lock (overlay->dvbsub_mutex); if (!g_queue_is_empty (overlay->pending_subtitles)) { From 2282a08890033e26b47b430e9f662ba98a2f90da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Fri, 3 Dec 2010 17:35:36 +0100 Subject: [PATCH 020/448] dvbsuboverlay: Improve selection of current to be displayed subpictures Drop all subpictures that are too old anyway and clear the currently displayed subpictures if num_rects==0 happens. --- gst/dvbsuboverlay/gstdvbsuboverlay.c | 48 +++++++++++++++++++++------- 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/gst/dvbsuboverlay/gstdvbsuboverlay.c b/gst/dvbsuboverlay/gstdvbsuboverlay.c index c0df91c220..e104b0f2d3 100644 --- a/gst/dvbsuboverlay/gstdvbsuboverlay.c +++ b/gst/dvbsuboverlay/gstdvbsuboverlay.c @@ -899,16 +899,39 @@ gst_dvbsub_overlay_chain_video (GstPad * pad, GstBuffer * buffer) g_mutex_lock (overlay->dvbsub_mutex); if (!g_queue_is_empty (overlay->pending_subtitles)) { - DVBSubtitles *pending_sub = g_queue_peek_head (overlay->pending_subtitles); - if (vid_running_time >= pending_sub->pts) { - GST_DEBUG_OBJECT (overlay, - "Time to show the next subtitle page (%" GST_TIME_FORMAT " >= %" - GST_TIME_FORMAT ") - it has %u regions", - GST_TIME_ARGS (vid_running_time), GST_TIME_ARGS (pending_sub->pts), - pending_sub->num_rects); - dvb_subtitles_free (overlay->current_subtitle); - overlay->current_subtitle = g_queue_pop_head (overlay->pending_subtitles); - /* FIXME: Pre-convert current_subtitle to a quick-blend format, num_rects=0 means that there are no regions, e.g, a subtitle "clear" happened */ + DVBSubtitles *pending_sub = NULL; + + while (!g_queue_is_empty (overlay->pending_subtitles)) { + pending_sub = g_queue_peek_head (overlay->pending_subtitles); + + if (pending_sub->pts + + pending_sub->page_time_out * GST_SECOND * + overlay->subtitle_segment.abs_rate < vid_running_time) { + /* Drop all subpictures that are too late anyway */ + dvb_subtitles_free (pending_sub); + g_queue_pop_head (overlay->pending_subtitles); + pending_sub = NULL; + } else if (pending_sub->num_rects == 0) { + /* Clear screen */ + if (overlay->current_subtitle) + dvb_subtitles_free (overlay->current_subtitle); + overlay->current_subtitle = NULL; + dvb_subtitles_free (pending_sub); + g_queue_pop_head (overlay->pending_subtitles); + } else if (vid_running_time >= pending_sub->pts) { + GST_DEBUG_OBJECT (overlay, + "Time to show the next subtitle page (%" GST_TIME_FORMAT " >= %" + GST_TIME_FORMAT ") - it has %u regions", + GST_TIME_ARGS (vid_running_time), GST_TIME_ARGS (pending_sub->pts), + pending_sub->num_rects); + dvb_subtitles_free (overlay->current_subtitle); + overlay->current_subtitle = + g_queue_pop_head (overlay->pending_subtitles); + /* FIXME: Pre-convert current_subtitle to a quick-blend format, num_rects=0 means that there are no regions, e.g, a subtitle "clear" happened */ + } else { + /* Keep old */ + break; + } } } @@ -916,7 +939,8 @@ gst_dvbsub_overlay_chain_video (GstPad * pad, GstBuffer * buffer) if (overlay->current_subtitle && vid_running_time > (overlay->current_subtitle->pts + - (overlay->current_subtitle->page_time_out * GST_SECOND))) { + overlay->current_subtitle->page_time_out * GST_SECOND * + overlay->subtitle_segment.abs_rate)) { GST_INFO_OBJECT (overlay, "Subtitle page not redefined before fallback page_time_out of %u seconds (missed data?) - deleting current page", overlay->current_subtitle->page_time_out); @@ -925,7 +949,7 @@ gst_dvbsub_overlay_chain_video (GstPad * pad, GstBuffer * buffer) } /* Now render it */ - if (overlay->current_subtitle && overlay->current_subtitle->num_rects > 0) { + if (overlay->current_subtitle) { buffer = gst_buffer_make_writable (buffer); blit_i420 (overlay, overlay->current_subtitle, buffer); } From e25a1dc0cc4876c9ecf4ddfafc17b5fc682cb999 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Mon, 6 Dec 2010 16:44:11 +0100 Subject: [PATCH 021/448] dvbsuboverlay: Refactor blending function and take average of all chroma values --- gst/dvbsuboverlay/gstdvbsuboverlay.c | 222 ++++++++++++++------------- 1 file changed, 112 insertions(+), 110 deletions(-) diff --git a/gst/dvbsuboverlay/gstdvbsuboverlay.c b/gst/dvbsuboverlay/gstdvbsuboverlay.c index e104b0f2d3..212a7cd674 100644 --- a/gst/dvbsuboverlay/gstdvbsuboverlay.c +++ b/gst/dvbsuboverlay/gstdvbsuboverlay.c @@ -472,11 +472,14 @@ blit_i420 (GstDVBSubOverlay * overlay, DVBSubtitles * subs, GstBuffer * buffer) { guint counter; DVBSubtitleRect *sub_region; - gint alpha, alpha2, r, g, b, r2, g2, b2, k, k2; - gint Y, U, V, Y2, U2, V2; - guint32 color, color2; - const guint8 *src; - guint8 *dst_y, *dst_u, *dst_v; + gint r, g, b; + gint a1, a2, a3, a4; + gint y1, y2, y3, y4; + gint u1, u2, u3, u4; + gint v1, v2, v3, v4; + guint32 color; + const guint8 *src, *src2; + guint8 *dst_y, *dst_y2, *dst_u, *dst_v; gint x, y, w, h; gint w2, h2; gint width = overlay->width; @@ -529,7 +532,11 @@ blit_i420 (GstDVBSubOverlay * overlay, DVBSubtitles * subs, GstBuffer * buffer) src_stride = sub_region->pict.rowstride; src = sub_region->pict.data; + src2 = sub_region->pict.data + src_stride; dst_y = buffer->data + y_offset + sub_region->y * y_stride + sub_region->x; + dst_y2 = + buffer->data + y_offset + (sub_region->y + 1) * y_stride + + sub_region->x; dst_u = buffer->data + u_offset + ((sub_region->y + 1) / 2) * u_stride + (sub_region->x + 1) / 2; @@ -537,174 +544,169 @@ blit_i420 (GstDVBSubOverlay * overlay, DVBSubtitles * subs, GstBuffer * buffer) buffer->data + v_offset + ((sub_region->y + 1) / 2) * v_stride + (sub_region->x + 1) / 2; - /* FIXME: This whole blending business will need a refactor */ - /* FIXME: Also interpolation for Cr and Cb channels missing */ for (y = 0; y < h - 1; y += 2) { for (x = 0; x < w - 1; x += 2) { color = sub_region->pict.palette[src[0]]; - alpha = (color >> 24) & 0xff; + a1 = (color >> 24) & 0xff; r = (color >> 16) & 0xff; g = (color >> 8) & 0xff; b = color & 0xff; - Y = rgb_to_y (r, g, b); - U = rgb_to_u (r, g, b); - V = rgb_to_v (r, g, b); + y1 = rgb_to_y (r, g, b); + u1 = rgb_to_u (r, g, b); + v1 = rgb_to_v (r, g, b); - color2 = sub_region->pict.palette[src[1]]; - alpha2 = (color2 >> 24) & 0xff; - r2 = (color2 >> 16) & 0xff; - g2 = (color2 >> 8) & 0xff; - b2 = color2 & 0xff; - - Y2 = rgb_to_y (r2, g2, b2); - U2 = rgb_to_u (r2, g2, b2); - V2 = rgb_to_v (r2, g2, b2); - - k = alpha; - k2 = k; - dst_y[0] = (k * Y + (255 - k) * dst_y[0]) / 255; - - k = alpha2; - k2 += k; - dst_y[1] = (k * Y2 + (255 - k) * dst_y[1]) / 255; - - src += src_stride; - dst_y += y_stride; - - color = sub_region->pict.palette[src[0]]; - alpha = (color >> 24) & 0xff; + color = sub_region->pict.palette[src[1]]; + a2 = (color >> 24) & 0xff; r = (color >> 16) & 0xff; g = (color >> 8) & 0xff; b = color & 0xff; - Y = rgb_to_y (r, g, b); - U = rgb_to_u (r, g, b); - V = rgb_to_v (r, g, b); + y2 = rgb_to_y (r, g, b); + u2 = rgb_to_u (r, g, b); + v2 = rgb_to_v (r, g, b); - color2 = sub_region->pict.palette[src[1]]; - alpha2 = (color2 >> 24) & 0xff; - r2 = (color2 >> 16) & 0xff; - g2 = (color2 >> 8) & 0xff; - b2 = color2 & 0xff; + color = sub_region->pict.palette[src2[0]]; + a3 = (color >> 24) & 0xff; + r = (color >> 16) & 0xff; + g = (color >> 8) & 0xff; + b = color & 0xff; - Y2 = rgb_to_y (r2, g2, b2); - U2 = rgb_to_u (r2, g2, b2); - V2 = rgb_to_v (r2, g2, b2); + y3 = rgb_to_y (r, g, b); + u3 = rgb_to_u (r, g, b); + v3 = rgb_to_v (r, g, b); - k = alpha; - k2 += k; - dst_y[0] = (k * Y + (255 - k) * dst_y[0]) / 255; + color = sub_region->pict.palette[src2[1]]; + a4 = (color >> 24) & 0xff; + r = (color >> 16) & 0xff; + g = (color >> 8) & 0xff; + b = color & 0xff; - k = alpha2; - k2 += k; - dst_y[1] = (k * Y2 + (255 - k) * dst_y[1]) / 255; + y4 = rgb_to_y (r, g, b); + u4 = rgb_to_u (r, g, b); + v4 = rgb_to_v (r, g, b); - k2 /= 4; - dst_u[0] = (k2 * U + (255 - k2) * dst_u[0]) / 255; - dst_v[0] = (k2 * V + (255 - k2) * dst_v[0]) / 255; - dst_u++; - dst_v++; + dst_y[0] = (a1 * y1 + (255 - a1) * dst_y[0]) / 255; + dst_y[1] = (a2 * y2 + (255 - a2) * dst_y[1]) / 255; + dst_y2[0] = (a3 * y3 + (255 - a3) * dst_y2[0]) / 255; + dst_y2[1] = (a4 * y4 + (255 - a4) * dst_y2[1]) / 255; - src += -src_stride + 2; - dst_y += -y_stride + 2; + a1 = (a1 + a2 + a3 + a4) / 4; + dst_u[0] = + (a1 * ((u1 + u2 + u3 + u4) / 4) + (255 - a1) * dst_u[0]) / 255; + dst_v[0] = + (a1 * ((v1 + v2 + v3 + v4) / 4) + (255 - a1) * dst_v[0]) / 255; + + src += 2; + src2 += 2; + dst_y += 2; + dst_y2 += 2; + dst_u += 1; + dst_v += 1; } + /* Odd width */ if (x < w) { color = sub_region->pict.palette[src[0]]; - alpha = (color >> 24) & 0xff; + a1 = (color >> 24) & 0xff; r = (color >> 16) & 0xff; g = (color >> 8) & 0xff; b = color & 0xff; - Y = rgb_to_y (r, g, b); - U = rgb_to_u (r, g, b); - V = rgb_to_v (r, g, b); + y1 = rgb_to_y (r, g, b); + u1 = rgb_to_u (r, g, b); + v1 = rgb_to_v (r, g, b); - k = alpha; - k2 = k; - dst_y[0] = (k * Y + (255 - k) * dst_y[0]) / 255; + color = sub_region->pict.palette[src2[0]]; + a3 = (color >> 24) & 0xff; + r = (color >> 16) & 0xff; + g = (color >> 8) & 0xff; + b = color & 0xff; - src += src_stride; - dst_y += y_stride; + y3 = rgb_to_y (r, g, b); + u3 = rgb_to_u (r, g, b); + v3 = rgb_to_v (r, g, b); - k = alpha; - k2 += k; - dst_y[0] = (k * Y + (255 - k) * dst_y[0]) / 255; + dst_y[0] = (a1 * y1 + (255 - a1) * dst_y[0]) / 255; + dst_y2[0] = (a3 * y3 + (255 - a3) * dst_y2[0]) / 255; - k2 /= 2; - dst_u[0] = (k2 * U + (255 - k2) * dst_u[0]) / 255; - dst_v[0] = (k2 * V + (255 - k2) * dst_v[0]) / 255; - dst_u++; - dst_v++; + a1 = (a1 + a3) / 2; + dst_u[0] = (a1 * ((u1 + u3) / 2) + (255 - a1) * dst_u[0]) / 255; + dst_v[0] = (a1 * ((v1 + v3) / 2) + (255 - a1) * dst_v[0]) / 255; - src += -src_stride + 1; - dst_y += -y_stride + 1; + src += 1; + src2 += 1; + dst_y += 1; + dst_y2 += 1; + dst_u += 1; + dst_v += 1; } src += src_stride + (src_stride - w); + src2 += src_stride + (src_stride - w); dst_y += y_stride + (y_stride - w); + dst_y2 += y_stride + (y_stride - w); dst_u += u_stride - w2; dst_v += v_stride - w2; } + /* Odd height */ if (y < h) { for (x = 0; x < w - 1; x += 2) { color = sub_region->pict.palette[src[0]]; - alpha = (color >> 24) & 0xff; + a1 = (color >> 24) & 0xff; r = (color >> 16) & 0xff; g = (color >> 8) & 0xff; b = color & 0xff; - Y = rgb_to_y (r, g, b); - U = rgb_to_u (r, g, b); - V = rgb_to_v (r, g, b); + y1 = rgb_to_y (r, g, b); + u1 = rgb_to_u (r, g, b); + v1 = rgb_to_v (r, g, b); - color2 = sub_region->pict.palette[src[1]]; - alpha2 = (color2 >> 24) & 0xff; - r2 = (color2 >> 16) & 0xff; - g2 = (color2 >> 8) & 0xff; - b2 = color2 & 0xff; + color = sub_region->pict.palette[src[1]]; + a2 = (color >> 24) & 0xff; + r = (color >> 16) & 0xff; + g = (color >> 8) & 0xff; + b = color & 0xff; - Y2 = rgb_to_y (r2, g2, b2); - U2 = rgb_to_u (r2, g2, b2); - V2 = rgb_to_v (r2, g2, b2); + y2 = rgb_to_y (r, g, b); + u2 = rgb_to_u (r, g, b); + v2 = rgb_to_v (r, g, b); - k = alpha; - k2 = k; - dst_y[0] = (k * Y + (255 - k) * dst_y[0]) / 255; + dst_y[0] = (a1 * y1 + (255 - a1) * dst_y[0]) / 255; + dst_y[1] = (a2 * y2 + (255 - a2) * dst_y[1]) / 255; - k = alpha2; - k2 += k; - dst_y[1] = (k * Y2 + (255 - k) * dst_y[1]) / 255; - - k2 /= 2; - dst_u[0] = (k2 * U + (255 - k2) * dst_u[0]) / 255; - dst_v[0] = (k2 * V + (255 - k2) * dst_v[0]) / 255; - dst_u++; - dst_v++; + a1 = (a1 + a2) / 2; + dst_u[0] = (a1 * ((u1 + u2) / 2) + (255 - a1) * dst_u[0]) / 255; + dst_v[0] = (a1 * ((v1 + v2) / 2) + (255 - a1) * dst_v[0]) / 255; src += 2; dst_y += 2; + dst_u += 1; + dst_v += 1; } + /* Odd height and width */ if (x < w) { color = sub_region->pict.palette[src[0]]; - alpha = (color >> 24) & 0xff; + a1 = (color >> 24) & 0xff; r = (color >> 16) & 0xff; g = (color >> 8) & 0xff; b = color & 0xff; - Y = rgb_to_y (r, g, b); - U = rgb_to_u (r, g, b); - V = rgb_to_v (r, g, b); + y1 = rgb_to_y (r, g, b); + u1 = rgb_to_u (r, g, b); + v1 = rgb_to_v (r, g, b); - k = alpha; - k2 = k; - dst_y[0] = (k * Y + (255 - k) * dst_y[0]) / 255; + dst_y[0] = (a1 * y1 + (255 - a1) * dst_y[0]) / 255; - dst_u[0] = (k2 * U + (255 - k2) * dst_u[0]) / 255; - dst_v[0] = (k2 * V + (255 - k2) * dst_v[0]) / 255; + dst_u[0] = (a1 * u1 + (255 - a1) * dst_u[0]) / 255; + dst_v[0] = (a1 * v1 + (255 - a1) * dst_v[0]) / 255; + + src += 1; + dst_y += 1; + dst_u += 1; + dst_v += 1; } } } From 68b8fca0470c069974155b91a45fd693cc4f3cc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Mon, 6 Dec 2010 17:05:28 +0100 Subject: [PATCH 022/448] dvbsuboverlay: Really choose the latest possible subpictures And not the first subpictures that are still valid according to the page timeout. --- gst/dvbsuboverlay/gstdvbsuboverlay.c | 73 ++++++++++++++++++---------- 1 file changed, 48 insertions(+), 25 deletions(-) diff --git a/gst/dvbsuboverlay/gstdvbsuboverlay.c b/gst/dvbsuboverlay/gstdvbsuboverlay.c index 212a7cd674..86bc64429f 100644 --- a/gst/dvbsuboverlay/gstdvbsuboverlay.c +++ b/gst/dvbsuboverlay/gstdvbsuboverlay.c @@ -518,6 +518,8 @@ blit_i420 (GstDVBSubOverlay * overlay, DVBSubtitles * subs, GstBuffer * buffer) v_stride = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_I420, 2, width); for (counter = 0; counter < subs->num_rects; counter++) { + gint dw, dh; + sub_region = subs->rects[counter]; if (sub_region->y > height || sub_region->x > width) continue; @@ -526,6 +528,13 @@ blit_i420 (GstDVBSubOverlay * overlay, DVBSubtitles * subs, GstBuffer * buffer) w = MIN (sub_region->w, width - sub_region->x); h = MIN (sub_region->h, height - sub_region->y); + /* TODO + dw = MIN (sub_region->dw, width - sub_region->x); + dh = MIN (sub_region->dh, height - sub_region->y); + */ + dw = w; + dh = h + 10; + w2 = (w + 1) / 2; h2 = (h + 1) / 2; @@ -854,7 +863,7 @@ gst_dvbsub_overlay_chain_video (GstPad * pad, GstBuffer * buffer) gint64 start, stop; gint64 cstart, cstop; gboolean in_seg; - GstClockTime vid_running_time; + GstClockTime vid_running_time, vid_running_time_end; if (overlay->format == GST_VIDEO_FORMAT_UNKNOWN) return GST_FLOW_NOT_NEGOTIATED; @@ -892,7 +901,14 @@ gst_dvbsub_overlay_chain_video (GstPad * pad, GstBuffer * buffer) vid_running_time = gst_segment_to_running_time (&overlay->video_segment, GST_FORMAT_TIME, - GST_BUFFER_TIMESTAMP (buffer)); + cstart); + if (GST_BUFFER_DURATION_IS_VALID (buffer)) + vid_running_time_end = + gst_segment_to_running_time (&overlay->video_segment, GST_FORMAT_TIME, + cstop); + else + vid_running_time_end = vid_running_time; + GST_DEBUG_OBJECT (overlay, "Video running time: %" GST_TIME_FORMAT, GST_TIME_ARGS (vid_running_time)); @@ -901,40 +917,47 @@ gst_dvbsub_overlay_chain_video (GstPad * pad, GstBuffer * buffer) g_mutex_lock (overlay->dvbsub_mutex); if (!g_queue_is_empty (overlay->pending_subtitles)) { - DVBSubtitles *pending_sub = NULL; + DVBSubtitles *tmp, *candidate = NULL; while (!g_queue_is_empty (overlay->pending_subtitles)) { - pending_sub = g_queue_peek_head (overlay->pending_subtitles); + tmp = g_queue_peek_head (overlay->pending_subtitles); - if (pending_sub->pts + - pending_sub->page_time_out * GST_SECOND * - overlay->subtitle_segment.abs_rate < vid_running_time) { - /* Drop all subpictures that are too late anyway */ - dvb_subtitles_free (pending_sub); - g_queue_pop_head (overlay->pending_subtitles); - pending_sub = NULL; - } else if (pending_sub->num_rects == 0) { + if (tmp->pts > vid_running_time_end) { + /* For a future video frame */ + break; + } else if (tmp->num_rects == 0) { /* Clear screen */ if (overlay->current_subtitle) dvb_subtitles_free (overlay->current_subtitle); overlay->current_subtitle = NULL; - dvb_subtitles_free (pending_sub); + if (candidate) + dvb_subtitles_free (candidate); + candidate = NULL; + g_queue_pop_head (overlay->pending_subtitles); + } else if (tmp->pts + tmp->page_time_out * GST_SECOND * + overlay->subtitle_segment.abs_rate >= vid_running_time) { + if (candidate) + dvb_subtitles_free (candidate); + candidate = tmp; g_queue_pop_head (overlay->pending_subtitles); - } else if (vid_running_time >= pending_sub->pts) { - GST_DEBUG_OBJECT (overlay, - "Time to show the next subtitle page (%" GST_TIME_FORMAT " >= %" - GST_TIME_FORMAT ") - it has %u regions", - GST_TIME_ARGS (vid_running_time), GST_TIME_ARGS (pending_sub->pts), - pending_sub->num_rects); - dvb_subtitles_free (overlay->current_subtitle); - overlay->current_subtitle = - g_queue_pop_head (overlay->pending_subtitles); - /* FIXME: Pre-convert current_subtitle to a quick-blend format, num_rects=0 means that there are no regions, e.g, a subtitle "clear" happened */ } else { - /* Keep old */ - break; + /* Too late */ + dvb_subtitles_free (tmp); + tmp = NULL; + g_queue_pop_head (overlay->pending_subtitles); } } + + if (candidate) { + GST_DEBUG_OBJECT (overlay, + "Time to show the next subtitle page (%" GST_TIME_FORMAT " >= %" + GST_TIME_FORMAT ") - it has %u regions", + GST_TIME_ARGS (vid_running_time), GST_TIME_ARGS (candidate->pts), + candidate->num_rects); + dvb_subtitles_free (overlay->current_subtitle); + overlay->current_subtitle = candidate; + /* FIXME: Pre-convert current_subtitle to a quick-blend format, num_rects=0 means that there are no regions, e.g, a subtitle "clear" happened */ + } } /* Check that we haven't hit the fallback timeout for current subtitle page */ From 8974371914fd35926d31e6b27643eb8e3d2d664d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Mon, 6 Dec 2010 17:08:55 +0100 Subject: [PATCH 023/448] dvbsuboverlay: Revert some parts of last commit that shouldn't be committed --- gst/dvbsuboverlay/gstdvbsuboverlay.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/gst/dvbsuboverlay/gstdvbsuboverlay.c b/gst/dvbsuboverlay/gstdvbsuboverlay.c index 86bc64429f..f8d6e8107a 100644 --- a/gst/dvbsuboverlay/gstdvbsuboverlay.c +++ b/gst/dvbsuboverlay/gstdvbsuboverlay.c @@ -518,8 +518,6 @@ blit_i420 (GstDVBSubOverlay * overlay, DVBSubtitles * subs, GstBuffer * buffer) v_stride = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_I420, 2, width); for (counter = 0; counter < subs->num_rects; counter++) { - gint dw, dh; - sub_region = subs->rects[counter]; if (sub_region->y > height || sub_region->x > width) continue; @@ -528,13 +526,6 @@ blit_i420 (GstDVBSubOverlay * overlay, DVBSubtitles * subs, GstBuffer * buffer) w = MIN (sub_region->w, width - sub_region->x); h = MIN (sub_region->h, height - sub_region->y); - /* TODO - dw = MIN (sub_region->dw, width - sub_region->x); - dh = MIN (sub_region->dh, height - sub_region->y); - */ - dw = w; - dh = h + 10; - w2 = (w + 1) / 2; h2 = (h + 1) / 2; From 7abe0a56af44446eb153185f10736cfb11fcd0ff Mon Sep 17 00:00:00 2001 From: Arun Raghavan Date: Mon, 6 Dec 2010 22:48:09 +0530 Subject: [PATCH 024/448] audioparse: Allow implicit channel map for 1-/2-channel audio This makes sure we don't set an empty channel map array for 1-/2-channel audio, causing an assert later on. --- gst/rawparse/gstaudioparse.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/gst/rawparse/gstaudioparse.c b/gst/rawparse/gstaudioparse.c index 1341c57e36..d4f82bad42 100644 --- a/gst/rawparse/gstaudioparse.c +++ b/gst/rawparse/gstaudioparse.c @@ -373,6 +373,11 @@ gst_audio_parse_set_channel_positions (GstAudioParse * ap, GstStructure * s) GValue pos_array = { 0, }; gint i; + if (!ap->channel_positions && ap->channels <= 2) { + /* Implicit mapping for 1- and 2-channel audio is okay */ + return; + } + g_value_init (&pos_array, GST_TYPE_ARRAY); if (ap->channel_positions @@ -382,7 +387,8 @@ gst_audio_parse_set_channel_positions (GstAudioParse * ap, GstStructure * s) for (i = 0; i < ap->channels; i++) gst_value_array_append_value (&pos_array, g_value_array_get_nth (ap->channel_positions, i)); - } else if (ap->channels != 1 && ap->channels != 2) { + } else { + /* >2 channels and no explicit mapping */ GValue pos_none = { 0, }; GST_WARNING_OBJECT (ap, "Using NONE channel positions"); From 0a26e138dda3f09b02790f5fd68c9ea98966bade Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Mon, 6 Dec 2010 18:18:11 +0100 Subject: [PATCH 025/448] jpegparse: avoid infinite loop when resyncing --- gst/jpegformat/gstjpegparse.c | 1 + 1 file changed, 1 insertion(+) diff --git a/gst/jpegformat/gstjpegparse.c b/gst/jpegformat/gstjpegparse.c index d22dd46ab0..a08579e573 100644 --- a/gst/jpegformat/gstjpegparse.c +++ b/gst/jpegformat/gstjpegparse.c @@ -406,6 +406,7 @@ gst_jpeg_parse_get_image_length (GstJpegParse * parse) if (noffset < 0) { /* ignore and continue resyncing until we hit the end * of our data or find a sync point that looks okay */ + offset++; continue; } GST_DEBUG ("found sync at 0x%x", offset + 2); From 49d7f207cbfd49e64321a36ad03f7ae857ed560e Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Mon, 6 Dec 2010 18:19:20 +0100 Subject: [PATCH 026/448] jpegparse: discard incomplete image ... as determined when finding SOI next image before an EOI. --- gst/jpegformat/gstjpegparse.c | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/gst/jpegformat/gstjpegparse.c b/gst/jpegformat/gstjpegparse.c index a08579e573..4ec736c5a0 100644 --- a/gst/jpegformat/gstjpegparse.c +++ b/gst/jpegformat/gstjpegparse.c @@ -289,9 +289,10 @@ gst_jpeg_parse_parse_tag_has_entropy_segment (guint8 tag) return FALSE; } -/* returns image length in bytes if parsed - * successfully, otherwise 0 if not enough data */ -static guint +/* returns image length in bytes if parsed successfully, + * otherwise 0 if more data needed, + * if < 0 the absolute value needs to be flushed */ +static gint gst_jpeg_parse_get_image_length (GstJpegParse * parse) { guint size; @@ -353,6 +354,13 @@ gst_jpeg_parse_get_image_length (GstJpegParse * parse) parse->priv->last_resync = FALSE; parse->priv->last_offset = 0; return (offset + 4); + } else if (value == 0xd8) { + /* Skip this frame if we found another SOI marker */ + GST_DEBUG ("0x%08x: SOI marker before EOI, skipping", offset + 2); + /* clear parse state */ + parse->priv->last_resync = FALSE; + parse->priv->last_offset = 0; + return -(offset + 2); } if (value >= 0xd0 && value <= 0xd7) @@ -846,7 +854,7 @@ static GstFlowReturn gst_jpeg_parse_chain (GstPad * pad, GstBuffer * buf) { GstJpegParse *parse; - guint len; + gint len; GstClockTime timestamp, duration; GstFlowReturn ret = GST_FLOW_OK; @@ -865,8 +873,12 @@ gst_jpeg_parse_chain (GstPad * pad, GstBuffer * buf) /* check if we already have a EOI */ len = gst_jpeg_parse_get_image_length (parse); - if (len == 0) + if (len == 0) { return GST_FLOW_OK; + } else if (len < 0) { + gst_adapter_flush (parse->priv->adapter, -len); + continue; + } GST_LOG_OBJECT (parse, "parsed image of size %d", len); From 74fb627a087af3d6da3dd6b3c5f8944f630f3f72 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Mon, 6 Dec 2010 19:00:28 +0100 Subject: [PATCH 027/448] jpegparse: try to convert comment tag to UTF-8 --- gst/jpegformat/gstjpegparse.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/gst/jpegformat/gstjpegparse.c b/gst/jpegformat/gstjpegparse.c index 4ec736c5a0..8dbc511c31 100644 --- a/gst/jpegformat/gstjpegparse.c +++ b/gst/jpegformat/gstjpegparse.c @@ -562,16 +562,25 @@ gst_jpeg_parse_read_header (GstJpegParse * parse, GstBuffer * buffer) case COM:{ /* read comment and post as tag */ const guint8 *comment = NULL; + const gchar *comm; + const gchar *env_vars[] = { "GST_JPEG_TAG_ENCODING", + "GST_TAG_ENCODING", NULL + }; if (!gst_byte_reader_get_uint16_be (&reader, &size)) goto error; if (!gst_byte_reader_get_data (&reader, size - 2, &comment)) goto error; - if (!parse->priv->tags) - parse->priv->tags = gst_tag_list_new (); - gst_tag_list_add (parse->priv->tags, GST_TAG_MERGE_REPLACE, - GST_TAG_COMMENT, comment, NULL); + comm = (const gchar *) comment; + comm = gst_tag_freeform_string_to_utf8 (comm, size - 2, env_vars); + + if (comm) { + if (!parse->priv->tags) + parse->priv->tags = gst_tag_list_new (); + gst_tag_list_add (parse->priv->tags, GST_TAG_MERGE_REPLACE, + GST_TAG_COMMENT, comm, NULL); + } break; } From 6f966febce5f245c0d97ba4b6cb7a3a675a6b006 Mon Sep 17 00:00:00 2001 From: Arun Raghavan Date: Wed, 17 Nov 2010 19:16:12 +0530 Subject: [PATCH 028/448] h264parse: Set srcpad caps before forwarding newsegment This holds all newsegement and most other events till there is enough data to set srcpad caps, so that the downstream link is properly negotiated before data starts flowing. https://bugzilla.gnome.org/show_bug.cgi?id=635205 --- gst/h264parse/gsth264parse.c | 66 +++++++++++++++++++++++++++++++++--- gst/h264parse/gsth264parse.h | 3 ++ 2 files changed, 65 insertions(+), 4 deletions(-) diff --git a/gst/h264parse/gsth264parse.c b/gst/h264parse/gsth264parse.c index 2a5d9a6bb1..6922fb7f7e 100644 --- a/gst/h264parse/gsth264parse.c +++ b/gst/h264parse/gsth264parse.c @@ -1016,6 +1016,14 @@ gst_h264_parse_reset (GstH264Parse * h264parse) h264parse->picture_start = FALSE; h264parse->idr_offset = -1; + if (h264parse->pending_segment) + gst_event_unref (h264parse->pending_segment); + h264parse->pending_segment = NULL; + + g_list_foreach (h264parse->pending_events, (GFunc) gst_event_unref, NULL); + g_list_free (h264parse->pending_events); + h264parse->pending_events = NULL; + gst_caps_replace (&h264parse->src_caps, NULL); } @@ -1040,6 +1048,13 @@ gst_h264_parse_finalize (GObject * object) g_slice_free (GstH264Pps, h264parse->pps_buffers[i]); } + if (h264parse->pending_segment) + gst_event_replace (&h264parse->pending_segment, NULL); + + g_list_foreach (h264parse->pending_events, (GFunc) gst_event_unref, NULL); + g_list_free (h264parse->pending_events); + h264parse->pending_events = NULL; + G_OBJECT_CLASS (parent_class)->finalize (object); } @@ -1369,8 +1384,10 @@ gst_h264_parse_update_src_caps (GstH264Parse * h264parse, GstCaps * caps) /* save as new caps, caps will be set when pushing data */ /* avoid replacing caps by a mere identical copy, thereby triggering * negotiating (which e.g. some container might not appreciate) */ - if (modified) + if (modified) { gst_caps_replace (&h264parse->src_caps, src_caps); + gst_pad_set_caps (h264parse->srcpad, h264parse->src_caps); + } gst_caps_unref (src_caps); return TRUE; @@ -1599,6 +1616,23 @@ gst_h264_parse_push_buffer (GstH264Parse * h264parse, GstBuffer * buf) { GstFlowReturn ret = GST_FLOW_OK; + /* We can send pending events if this is the first call, since we now have + * caps for the srcpad */ + if (G_UNLIKELY (h264parse->pending_segment != NULL)) { + gst_pad_push_event (h264parse->srcpad, h264parse->pending_segment); + h264parse->pending_segment = NULL; + + if (G_UNLIKELY (h264parse->pending_events != NULL)) { + GList *l; + + for (l = h264parse->pending_events; l != NULL; l = l->next) + gst_pad_push_event (h264parse->srcpad, GST_EVENT (l->data)); + + g_list_free (h264parse->pending_events); + h264parse->pending_events = NULL; + } + } + /* start of picture is good time to slip in codec_data NALUs * (when outputting NALS and transforming to bytestream) */ if (G_UNLIKELY (h264parse->codec_nals && h264parse->picture_start)) { @@ -2583,6 +2617,11 @@ gst_h264_parse_sink_event (GstPad * pad, GstEvent * event) break; case GST_EVENT_EOS: GST_DEBUG_OBJECT (h264parse, "received EOS"); + if (h264parse->pending_segment) { + /* Send pending newsegment before EOS */ + gst_pad_push_event (h264parse->srcpad, h264parse->pending_segment); + h264parse->pending_segment = NULL; + } if (h264parse->segment.rate < 0.0) { gst_h264_parse_chain_reverse (h264parse, TRUE, NULL); gst_h264_parse_flush_decode (h264parse); @@ -2595,6 +2634,7 @@ gst_h264_parse_sink_event (GstPad * pad, GstEvent * event) GstFormat format; gint64 start, stop, pos; gboolean update; + GstEvent **ev; gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate, &format, &start, &stop, &pos); @@ -2604,17 +2644,35 @@ gst_h264_parse_sink_event (GstPad * pad, GstEvent * event) rate, applied_rate, format, start, stop, pos); GST_DEBUG_OBJECT (h264parse, - "Pushing newseg rate %g, applied rate %g, format %d, start %" + "Keeping newseg rate %g, applied rate %g, format %d, start %" G_GINT64_FORMAT ", stop %" G_GINT64_FORMAT ", pos %" G_GINT64_FORMAT, rate, applied_rate, format, start, stop, pos); + ev = &h264parse->pending_segment; + gst_event_replace (ev, event); + gst_event_unref (event); + res = TRUE; + break; + } + case GST_EVENT_FLUSH_START: + { res = gst_pad_push_event (h264parse->srcpad, event); break; } default: - res = gst_pad_push_event (h264parse->srcpad, event); - break; + { + if (G_UNLIKELY (h264parse->src_caps == NULL || + h264parse->pending_segment)) { + /* We don't yet have enough data to set caps on the srcpad, so collect + * non-critical events till we do */ + h264parse->pending_events = g_list_append (h264parse->pending_events, + event); + res = TRUE; + } else + res = gst_pad_push_event (h264parse->srcpad, event); + break; + } } gst_object_unref (h264parse); diff --git a/gst/h264parse/gsth264parse.h b/gst/h264parse/gsth264parse.h index 051353f062..e245ea0015 100644 --- a/gst/h264parse/gsth264parse.h +++ b/gst/h264parse/gsth264parse.h @@ -137,6 +137,9 @@ struct _GstH264Parse GstBuffer *pps_nals[MAX_PPS_COUNT]; GstCaps *src_caps; + + GstEvent *pending_segment; + GList *pending_events; }; struct _GstH264ParseClass From 26d69e63d49d9865d8265e6ab767786f984302a3 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Tue, 7 Dec 2010 14:55:15 +0100 Subject: [PATCH 029/448] h264parse: re-use reset() in finalize() --- gst/h264parse/gsth264parse.c | 20 ++------------------ 1 file changed, 2 insertions(+), 18 deletions(-) diff --git a/gst/h264parse/gsth264parse.c b/gst/h264parse/gsth264parse.c index 6922fb7f7e..b44bcc0d43 100644 --- a/gst/h264parse/gsth264parse.c +++ b/gst/h264parse/gsth264parse.c @@ -1031,30 +1031,14 @@ static void gst_h264_parse_finalize (GObject * object) { GstH264Parse *h264parse; - gint i; h264parse = GST_H264PARSE (object); + gst_h264_parse_reset (h264parse); + g_object_unref (h264parse->adapter); g_object_unref (h264parse->picture_adapter); - for (i = 0; i < MAX_SPS_COUNT; i++) { - if (h264parse->sps_buffers[i] != NULL) - g_slice_free (GstH264Sps, h264parse->sps_buffers[i]); - } - - for (i = 0; i < MAX_PPS_COUNT; i++) { - if (h264parse->pps_buffers[i] != NULL) - g_slice_free (GstH264Pps, h264parse->pps_buffers[i]); - } - - if (h264parse->pending_segment) - gst_event_replace (&h264parse->pending_segment, NULL); - - g_list_foreach (h264parse->pending_events, (GFunc) gst_event_unref, NULL); - g_list_free (h264parse->pending_events); - h264parse->pending_events = NULL; - G_OBJECT_CLASS (parent_class)->finalize (object); } From de85aef3336c0761735642cc3b80ba6085d6c4a2 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Tue, 7 Dec 2010 14:55:28 +0100 Subject: [PATCH 030/448] h264parse: align code with comment --- gst/h264parse/gsth264parse.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/gst/h264parse/gsth264parse.c b/gst/h264parse/gsth264parse.c index b44bcc0d43..9c35d3b2b6 100644 --- a/gst/h264parse/gsth264parse.c +++ b/gst/h264parse/gsth264parse.c @@ -1368,10 +1368,8 @@ gst_h264_parse_update_src_caps (GstH264Parse * h264parse, GstCaps * caps) /* save as new caps, caps will be set when pushing data */ /* avoid replacing caps by a mere identical copy, thereby triggering * negotiating (which e.g. some container might not appreciate) */ - if (modified) { + if (modified) gst_caps_replace (&h264parse->src_caps, src_caps); - gst_pad_set_caps (h264parse->srcpad, h264parse->src_caps); - } gst_caps_unref (src_caps); return TRUE; From 04eb5814800ef461bd9d7496e4b010527c06dbfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Tue, 7 Dec 2010 17:17:44 +0100 Subject: [PATCH 031/448] dvbsuboverlay: Implement nearest neighbour scaling for the subpictures This becomes necessary when SDTV subtitles are used for HDTV videos. --- gst/dvbsuboverlay/gstdvbsuboverlay.c | 81 ++++++++++++++++++---------- 1 file changed, 54 insertions(+), 27 deletions(-) diff --git a/gst/dvbsuboverlay/gstdvbsuboverlay.c b/gst/dvbsuboverlay/gstdvbsuboverlay.c index f8d6e8107a..df9bedf95c 100644 --- a/gst/dvbsuboverlay/gstdvbsuboverlay.c +++ b/gst/dvbsuboverlay/gstdvbsuboverlay.c @@ -478,7 +478,7 @@ blit_i420 (GstDVBSubOverlay * overlay, DVBSubtitles * subs, GstBuffer * buffer) gint u1, u2, u3, u4; gint v1, v2, v3, v4; guint32 color; - const guint8 *src, *src2; + const guint8 *src; guint8 *dst_y, *dst_y2, *dst_u, *dst_v; gint x, y, w, h; gint w2, h2; @@ -518,6 +518,10 @@ blit_i420 (GstDVBSubOverlay * overlay, DVBSubtitles * subs, GstBuffer * buffer) v_stride = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_I420, 2, width); for (counter = 0; counter < subs->num_rects; counter++) { + gint dw, dh; + gint32 sx, sy; /* 16.16 fixed point */ + gint32 xstep, ystep; /* 16.16 fixed point */ + sub_region = subs->rects[counter]; if (sub_region->y > height || sub_region->x > width) continue; @@ -526,13 +530,22 @@ blit_i420 (GstDVBSubOverlay * overlay, DVBSubtitles * subs, GstBuffer * buffer) w = MIN (sub_region->w, width - sub_region->x); h = MIN (sub_region->h, height - sub_region->y); - w2 = (w + 1) / 2; - h2 = (h + 1) / 2; + /* TODO + dw = MIN (sub_region->dw, width - sub_region->x); + dh = MIN (sub_region->dh, height - sub_region->y); + */ + dw = w; + dh = h; + + xstep = (w << 16) / dw; + ystep = (h << 16) / dh; + + w2 = (dw + 1) / 2; + h2 = (dh + 1) / 2; src_stride = sub_region->pict.rowstride; src = sub_region->pict.data; - src2 = sub_region->pict.data + src_stride; dst_y = buffer->data + y_offset + sub_region->y * y_stride + sub_region->x; dst_y2 = buffer->data + y_offset + (sub_region->y + 1) * y_stride + @@ -544,9 +557,12 @@ blit_i420 (GstDVBSubOverlay * overlay, DVBSubtitles * subs, GstBuffer * buffer) buffer->data + v_offset + ((sub_region->y + 1) / 2) * v_stride + (sub_region->x + 1) / 2; - for (y = 0; y < h - 1; y += 2) { - for (x = 0; x < w - 1; x += 2) { - color = sub_region->pict.palette[src[0]]; + sy = 0; + for (y = 0; y < dh - 1; y += 2) { + sx = 0; + for (x = 0; x < dw - 1; x += 2) { + color = + sub_region->pict.palette[src[(sy >> 16) * src_stride + (sx >> 16)]]; a1 = (color >> 24) & 0xff; r = (color >> 16) & 0xff; g = (color >> 8) & 0xff; @@ -556,7 +572,9 @@ blit_i420 (GstDVBSubOverlay * overlay, DVBSubtitles * subs, GstBuffer * buffer) u1 = rgb_to_u (r, g, b); v1 = rgb_to_v (r, g, b); - color = sub_region->pict.palette[src[1]]; + color = + sub_region->pict.palette[src[(sy >> 16) * src_stride + ((sx + + xstep) >> 16)]]; a2 = (color >> 24) & 0xff; r = (color >> 16) & 0xff; g = (color >> 8) & 0xff; @@ -566,7 +584,9 @@ blit_i420 (GstDVBSubOverlay * overlay, DVBSubtitles * subs, GstBuffer * buffer) u2 = rgb_to_u (r, g, b); v2 = rgb_to_v (r, g, b); - color = sub_region->pict.palette[src2[0]]; + color = + sub_region->pict.palette[src[((sy + ystep) >> 16) * src_stride + + (sx >> 16)]]; a3 = (color >> 24) & 0xff; r = (color >> 16) & 0xff; g = (color >> 8) & 0xff; @@ -576,7 +596,9 @@ blit_i420 (GstDVBSubOverlay * overlay, DVBSubtitles * subs, GstBuffer * buffer) u3 = rgb_to_u (r, g, b); v3 = rgb_to_v (r, g, b); - color = sub_region->pict.palette[src2[1]]; + color = + sub_region->pict.palette[src[((sy + ystep) >> 16) * src_stride + + ((sx + xstep) >> 16)]]; a4 = (color >> 24) & 0xff; r = (color >> 16) & 0xff; g = (color >> 8) & 0xff; @@ -597,17 +619,17 @@ blit_i420 (GstDVBSubOverlay * overlay, DVBSubtitles * subs, GstBuffer * buffer) dst_v[0] = (a1 * ((v1 + v2 + v3 + v4) / 4) + (255 - a1) * dst_v[0]) / 255; - src += 2; - src2 += 2; dst_y += 2; dst_y2 += 2; dst_u += 1; dst_v += 1; + sx += 2 * xstep; } /* Odd width */ - if (x < w) { - color = sub_region->pict.palette[src[0]]; + if (x < dw) { + color = + sub_region->pict.palette[src[(sy >> 16) * src_stride + (sx >> 16)]]; a1 = (color >> 24) & 0xff; r = (color >> 16) & 0xff; g = (color >> 8) & 0xff; @@ -617,7 +639,9 @@ blit_i420 (GstDVBSubOverlay * overlay, DVBSubtitles * subs, GstBuffer * buffer) u1 = rgb_to_u (r, g, b); v1 = rgb_to_v (r, g, b); - color = sub_region->pict.palette[src2[0]]; + color = + sub_region->pict.palette[src[((sy + ystep) >> 16) * src_stride + + (sx >> 16)]]; a3 = (color >> 24) & 0xff; r = (color >> 16) & 0xff; g = (color >> 8) & 0xff; @@ -634,16 +658,15 @@ blit_i420 (GstDVBSubOverlay * overlay, DVBSubtitles * subs, GstBuffer * buffer) dst_u[0] = (a1 * ((u1 + u3) / 2) + (255 - a1) * dst_u[0]) / 255; dst_v[0] = (a1 * ((v1 + v3) / 2) + (255 - a1) * dst_v[0]) / 255; - src += 1; - src2 += 1; dst_y += 1; dst_y2 += 1; dst_u += 1; dst_v += 1; + sx += xstep; } - src += src_stride + (src_stride - w); - src2 += src_stride + (src_stride - w); + sy += 2 * ystep; + dst_y += y_stride + (y_stride - w); dst_y2 += y_stride + (y_stride - w); dst_u += u_stride - w2; @@ -651,9 +674,10 @@ blit_i420 (GstDVBSubOverlay * overlay, DVBSubtitles * subs, GstBuffer * buffer) } /* Odd height */ - if (y < h) { - for (x = 0; x < w - 1; x += 2) { - color = sub_region->pict.palette[src[0]]; + if (y < dh) { + for (x = 0; x < dw - 1; x += 2) { + color = + sub_region->pict.palette[src[(sy >> 16) * src_stride + (sx >> 16)]]; a1 = (color >> 24) & 0xff; r = (color >> 16) & 0xff; g = (color >> 8) & 0xff; @@ -663,7 +687,9 @@ blit_i420 (GstDVBSubOverlay * overlay, DVBSubtitles * subs, GstBuffer * buffer) u1 = rgb_to_u (r, g, b); v1 = rgb_to_v (r, g, b); - color = sub_region->pict.palette[src[1]]; + color = + sub_region->pict.palette[src[(sy >> 16) * src_stride + ((sx + + xstep) >> 16)]]; a2 = (color >> 24) & 0xff; r = (color >> 16) & 0xff; g = (color >> 8) & 0xff; @@ -680,15 +706,16 @@ blit_i420 (GstDVBSubOverlay * overlay, DVBSubtitles * subs, GstBuffer * buffer) dst_u[0] = (a1 * ((u1 + u2) / 2) + (255 - a1) * dst_u[0]) / 255; dst_v[0] = (a1 * ((v1 + v2) / 2) + (255 - a1) * dst_v[0]) / 255; - src += 2; dst_y += 2; dst_u += 1; dst_v += 1; + sx += 2 * xstep; } /* Odd height and width */ - if (x < w) { - color = sub_region->pict.palette[src[0]]; + if (x < dw) { + color = + sub_region->pict.palette[src[(sy >> 16) * src_stride + (sx >> 16)]]; a1 = (color >> 24) & 0xff; r = (color >> 16) & 0xff; g = (color >> 8) & 0xff; @@ -703,10 +730,10 @@ blit_i420 (GstDVBSubOverlay * overlay, DVBSubtitles * subs, GstBuffer * buffer) dst_u[0] = (a1 * u1 + (255 - a1) * dst_u[0]) / 255; dst_v[0] = (a1 * v1 + (255 - a1) * dst_v[0]) / 255; - src += 1; dst_y += 1; dst_u += 1; dst_v += 1; + sx += xstep; } } } From 522f470883ee51033340838de0fbec81a55d356a Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Tue, 7 Dec 2010 15:20:29 +0100 Subject: [PATCH 032/448] mpeg4videoparse: minor fix to error handling We weren't handling unparseable codec_data in some cases. https://bugzilla.gnome.org/show_bug.cgi?id=635202 --- gst/mpeg4videoparse/mpeg4videoparse.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/gst/mpeg4videoparse/mpeg4videoparse.c b/gst/mpeg4videoparse/mpeg4videoparse.c index 09f35212ef..7dfa556862 100644 --- a/gst/mpeg4videoparse/mpeg4videoparse.c +++ b/gst/mpeg4videoparse/mpeg4videoparse.c @@ -731,6 +731,7 @@ gst_mpeg4vparse_sink_setcaps (GstPad * pad, GstCaps * caps) } else { const guint8 *data = GST_BUFFER_DATA (buf); + res = FALSE; if (data[0] == 0 && data[1] == 0 && data[2] == 1) { if (data[3] == VOS_STARTCODE) { /* Usually the codec data will be a visual object sequence, containing @@ -745,6 +746,8 @@ gst_mpeg4vparse_sink_setcaps (GstPad * pad, GstCaps * caps) res = gst_mpeg4vparse_handle_vo (parse, data, GST_BUFFER_SIZE (buf), FALSE); } + if (!res) + goto failed_parse; } else { GST_WARNING_OBJECT (parse, "codec_data does not begin with start code, invalid"); From 8f30fca6362dabf9fc709e9974fa48edc79b8294 Mon Sep 17 00:00:00 2001 From: Arun Raghavan Date: Thu, 18 Nov 2010 23:29:51 +0530 Subject: [PATCH 033/448] mpeg4videoparse: Use sinkpad caps as base for srcpad caps This way, we don't lose additional fields that come from upstream (like profile/level for now). https://bugzilla.gnome.org/show_bug.cgi?id=635202 --- gst/mpeg4videoparse/mpeg4videoparse.c | 17 ++++++++++++++--- gst/mpeg4videoparse/mpeg4videoparse.h | 2 ++ 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/gst/mpeg4videoparse/mpeg4videoparse.c b/gst/mpeg4videoparse/mpeg4videoparse.c index 7dfa556862..969ca7e393 100644 --- a/gst/mpeg4videoparse/mpeg4videoparse.c +++ b/gst/mpeg4videoparse/mpeg4videoparse.c @@ -65,9 +65,15 @@ gst_mpeg4vparse_set_new_caps (GstMpeg4VParse * parse, gint aspect_ratio_width, gint aspect_ratio_height, gint width, gint height) { gboolean res; - GstCaps *out_caps = gst_caps_new_simple ("video/mpeg", - "mpegversion", G_TYPE_INT, 4, - "systemstream", G_TYPE_BOOLEAN, FALSE, + GstCaps *out_caps; + + if (parse->sink_caps) { + out_caps = gst_caps_copy (parse->sink_caps); + } else { + out_caps = gst_caps_new_simple ("video/mpeg", + "mpegversion", G_TYPE_INT, 4, NULL); + } + gst_caps_set_simple (out_caps, "systemstream", G_TYPE_BOOLEAN, FALSE, "parsed", G_TYPE_BOOLEAN, TRUE, NULL); if (parse->profile != 0) { @@ -710,6 +716,7 @@ gst_mpeg4vparse_sink_setcaps (GstPad * pad, GstCaps * caps) const GValue *value; GST_DEBUG_OBJECT (parse, "setcaps called with %" GST_PTR_FORMAT, caps); + parse->sink_caps = gst_caps_ref (caps); s = gst_caps_get_structure (caps, 0); @@ -860,6 +867,10 @@ gst_mpeg4vparse_src_query (GstPad * pad, GstQuery * query) static void gst_mpeg4vparse_cleanup (GstMpeg4VParse * parse) { + if (parse->sink_caps) { + gst_caps_unref (parse->sink_caps); + parse->sink_caps = NULL; + } if (parse->adapter) { gst_adapter_clear (parse->adapter); } diff --git a/gst/mpeg4videoparse/mpeg4videoparse.h b/gst/mpeg4videoparse/mpeg4videoparse.h index f5ce3f3c81..3c114caef8 100644 --- a/gst/mpeg4videoparse/mpeg4videoparse.h +++ b/gst/mpeg4videoparse/mpeg4videoparse.h @@ -54,6 +54,8 @@ struct _GstMpeg4VParse { GstPad * sinkpad; GstPad * srcpad; + GstCaps *sink_caps; + guint interval; GstClockTime last_report; From 5b442d0712bf1b7665fa5ea552fb6e1dd670301c Mon Sep 17 00:00:00 2001 From: Arun Raghavan Date: Thu, 18 Nov 2010 13:39:23 +0530 Subject: [PATCH 034/448] mpeg4videoparse: Set srcpad caps before forwarding newsegment This holds all newsegement and most other events till there is enough data to set srcpad caps, so that the downstream link is properly negotiated before data starts flowing. https://bugzilla.gnome.org/show_bug.cgi?id=635204 --- gst/mpeg4videoparse/mpeg4videoparse.c | 55 ++++++++++++++++++++++++++- gst/mpeg4videoparse/mpeg4videoparse.h | 4 ++ 2 files changed, 58 insertions(+), 1 deletion(-) diff --git a/gst/mpeg4videoparse/mpeg4videoparse.c b/gst/mpeg4videoparse/mpeg4videoparse.c index 969ca7e393..9e58a9e35c 100644 --- a/gst/mpeg4videoparse/mpeg4videoparse.c +++ b/gst/mpeg4videoparse/mpeg4videoparse.c @@ -118,6 +118,22 @@ gst_mpeg4vparse_set_new_caps (GstMpeg4VParse * parse, res = gst_pad_set_caps (parse->srcpad, out_caps); gst_caps_unref (out_caps); + parse->have_src_caps = TRUE; + if (parse->pending_segment != NULL) { + /* We can send pending events since we now have caps for the srcpad */ + gst_pad_push_event (parse->srcpad, parse->pending_segment); + parse->pending_segment = NULL; + + if (G_UNLIKELY (parse->pending_events != NULL)) { + GList *l; + + for (l = parse->pending_events; l != NULL; l = l->next) + gst_pad_push_event (parse->srcpad, GST_EVENT (l->data)); + + g_list_free (parse->pending_events); + parse->pending_events = NULL; + } + } return res; } @@ -794,6 +810,11 @@ gst_mpeg4vparse_sink_event (GstPad * pad, GstEvent * event) parse->offset = 0; break; case GST_EVENT_EOS: + if (parse->pending_segment != NULL) { + /* Send pending newsegment before EOS */ + gst_pad_push_event (parse->srcpad, parse->pending_segment); + parse->pending_segment = NULL; + } if (parse->state == PARSE_VOP_FOUND) { /* If we've found the start of the VOP assume what's left in the * adapter is the complete VOP. This might cause us to send an @@ -802,11 +823,25 @@ gst_mpeg4vparse_sink_event (GstPad * pad, GstEvent * event) gst_mpeg4vparse_push (parse, gst_adapter_available (parse->adapter)); } /* fallthrough */ + case GST_EVENT_FLUSH_START: + res = gst_pad_event_default (pad, event); + break; + case GST_EVENT_NEWSEGMENT: + gst_event_replace (&parse->pending_segment, event); + gst_event_unref (event); + res = TRUE; + break; default: + if (G_UNLIKELY (!parse->have_src_caps || parse->pending_segment)) { + /* We don't yet have enough data to set caps on the srcpad, so collect + * non-critical events till we do */ + parse->pending_events = g_list_append (parse->pending_events, event); + res = TRUE; + } else + res = gst_pad_event_default (pad, event); break; } - res = gst_pad_event_default (pad, event); gst_object_unref (parse); return res; @@ -879,6 +914,16 @@ gst_mpeg4vparse_cleanup (GstMpeg4VParse * parse) parse->config = NULL; } + if (parse->pending_segment) + gst_event_unref (parse->pending_segment); + parse->pending_segment = NULL; + + g_list_foreach (parse->pending_events, (GFunc) gst_event_unref, NULL); + g_list_free (parse->pending_events); + parse->pending_events = NULL; + + parse->have_src_caps = FALSE; + parse->state = PARSE_NEED_START; parse->have_config = FALSE; parse->offset = 0; @@ -918,6 +963,14 @@ gst_mpeg4vparse_dispose (GObject * object) parse->config = NULL; } + if (parse->pending_segment) + gst_event_unref (parse->pending_segment); + parse->pending_segment = NULL; + + g_list_foreach (parse->pending_events, (GFunc) gst_event_unref, NULL); + g_list_free (parse->pending_events); + parse->pending_events = NULL; + GST_CALL_PARENT (G_OBJECT_CLASS, dispose, (object)); } diff --git a/gst/mpeg4videoparse/mpeg4videoparse.h b/gst/mpeg4videoparse/mpeg4videoparse.h index 3c114caef8..29f7fa1834 100644 --- a/gst/mpeg4videoparse/mpeg4videoparse.h +++ b/gst/mpeg4videoparse/mpeg4videoparse.h @@ -73,6 +73,10 @@ struct _GstMpeg4VParse { GstClockTime frame_duration; gboolean drop; + + gboolean have_src_caps; + GstEvent *pending_segment; + GList *pending_events; }; struct _GstMpeg4VParseClass { From 26877f66c939da35b899f87b15d058e45a61b047 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Tue, 7 Dec 2010 15:44:00 +0100 Subject: [PATCH 035/448] mpeg4videoparse: re-use cleanup() in finalize() ... and also favor finalize() rather than dispose(). --- gst/mpeg4videoparse/mpeg4videoparse.c | 20 +++++--------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/gst/mpeg4videoparse/mpeg4videoparse.c b/gst/mpeg4videoparse/mpeg4videoparse.c index 9e58a9e35c..4d3f14d831 100644 --- a/gst/mpeg4videoparse/mpeg4videoparse.c +++ b/gst/mpeg4videoparse/mpeg4videoparse.c @@ -950,28 +950,18 @@ gst_mpeg4vparse_change_state (GstElement * element, GstStateChange transition) } static void -gst_mpeg4vparse_dispose (GObject * object) +gst_mpeg4vparse_finalize (GObject * object) { GstMpeg4VParse *parse = GST_MPEG4VIDEOPARSE (object); + gst_mpeg4vparse_cleanup (parse); + if (parse->adapter) { g_object_unref (parse->adapter); parse->adapter = NULL; } - if (parse->config != NULL) { - gst_buffer_unref (parse->config); - parse->config = NULL; - } - if (parse->pending_segment) - gst_event_unref (parse->pending_segment); - parse->pending_segment = NULL; - - g_list_foreach (parse->pending_events, (GFunc) gst_event_unref, NULL); - g_list_free (parse->pending_events); - parse->pending_events = NULL; - - GST_CALL_PARENT (G_OBJECT_CLASS, dispose, (object)); + GST_CALL_PARENT (G_OBJECT_CLASS, finalize, (object)); } static void @@ -1036,7 +1026,7 @@ gst_mpeg4vparse_class_init (GstMpeg4VParseClass * klass) parent_class = g_type_class_peek_parent (klass); - gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_mpeg4vparse_dispose); + gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_mpeg4vparse_finalize); gobject_class->set_property = gst_mpeg4vparse_set_property; gobject_class->get_property = gst_mpeg4vparse_get_property; From dd3fe6ad3cbe3f970756a766b01d3c9ad7dccc01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Wed, 8 Dec 2010 15:18:32 +0000 Subject: [PATCH 036/448] configure: require released versions of core/base instead of old git --- configure.ac | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac index 566de0d7e4..674f029591 100644 --- a/configure.ac +++ b/configure.ac @@ -50,8 +50,8 @@ AC_LIBTOOL_WIN32_DLL AM_PROG_LIBTOOL dnl *** required versions of GStreamer stuff *** -GST_REQ=0.10.30.1 -GSTPB_REQ=0.10.30.1 +GST_REQ=0.10.31 +GSTPB_REQ=0.10.31 dnl *** autotools stuff **** From a8c488aefa88a8cd1131cfebafc3e7b2d0c7a8fc Mon Sep 17 00:00:00 2001 From: Stefan Kost Date: Wed, 24 Nov 2010 12:22:01 +0200 Subject: [PATCH 037/448] output-selector-test: don't hardcode videosinks and use more colorspace conv. Use autovideosink instead of hardcoded sinks. Use an additional colorspace converter between videotestsrc and timeoverlay. --- tests/icles/output-selector-test.c | 46 +++++++++++++++++++++--------- 1 file changed, 32 insertions(+), 14 deletions(-) diff --git a/tests/icles/output-selector-test.c b/tests/icles/output-selector-test.c index 1d54b34a2b..24ad2835dc 100644 --- a/tests/icles/output-selector-test.c +++ b/tests/icles/output-selector-test.c @@ -66,10 +66,16 @@ switch_cb (gpointer user_data) } +static void +on_bin_element_added (GstBin * bin, GstElement * element, gpointer user_data) +{ + g_object_set (G_OBJECT (element), "sync", FALSE, "async", FALSE, NULL); +} + gint main (gint argc, gchar * argv[]) { - GstElement *pipeline, *src, *toverlay, *osel, *sink1, *sink2, *convert; + GstElement *pipeline, *src, *toverlay, *osel, *sink1, *sink2, *c1, *c2, *c0; GstPad *sinkpad; GstBus *bus; @@ -80,54 +86,66 @@ main (gint argc, gchar * argv[]) /* create elements */ pipeline = gst_element_factory_make ("pipeline", "pipeline"); src = gst_element_factory_make ("videotestsrc", "src"); + c0 = gst_element_factory_make ("ffmpegcolorspace", NULL); toverlay = gst_element_factory_make ("timeoverlay", "timeoverlay"); osel = gst_element_factory_make ("output-selector", "osel"); - convert = gst_element_factory_make ("ffmpegcolorspace", "convert"); - sink1 = gst_element_factory_make ("xvimagesink", "sink1"); - sink2 = gst_element_factory_make ("ximagesink", "sink2"); + c1 = gst_element_factory_make ("ffmpegcolorspace", NULL); + c2 = gst_element_factory_make ("ffmpegcolorspace", NULL); + sink1 = gst_element_factory_make ("autovideosink", "sink1"); + sink2 = gst_element_factory_make ("autovideosink", "sink2"); - if (!pipeline || !src || !toverlay || !osel || !convert || !sink1 || !sink2) { + if (!pipeline || !src || !c0 || !toverlay || !osel || !c1 || !c2 || !sink1 || + !sink2) { g_print ("missing element\n"); return -1; } /* add them to bin */ - gst_bin_add_many (GST_BIN (pipeline), src, toverlay, osel, convert, sink1, + gst_bin_add_many (GST_BIN (pipeline), src, c0, toverlay, osel, c1, sink1, c2, sink2, NULL); /* set properties */ g_object_set (G_OBJECT (src), "is-live", TRUE, NULL); g_object_set (G_OBJECT (src), "do-timestamp", TRUE, NULL); g_object_set (G_OBJECT (src), "num-buffers", NUM_VIDEO_BUFFERS, NULL); - g_object_set (G_OBJECT (sink1), "sync", FALSE, "async", FALSE, NULL); - g_object_set (G_OBJECT (sink2), "sync", FALSE, "async", FALSE, NULL); g_object_set (G_OBJECT (osel), "resend-latest", TRUE, NULL); + /* handle deferred properties */ + g_signal_connect (G_OBJECT (sink1), "element-added", + G_CALLBACK (on_bin_element_added), NULL); + g_signal_connect (G_OBJECT (sink2), "element-added", + G_CALLBACK (on_bin_element_added), NULL); + /* link src ! timeoverlay ! osel */ - if (!gst_element_link_many (src, toverlay, osel, NULL)) { + if (!gst_element_link_many (src, c0, toverlay, osel, NULL)) { g_print ("linking failed\n"); return -1; } /* link output 1 */ - sinkpad = gst_element_get_static_pad (sink1, "sink"); + sinkpad = gst_element_get_static_pad (c1, "sink"); osel_src1 = gst_element_get_request_pad (osel, "src%d"); if (gst_pad_link (osel_src1, sinkpad) != GST_PAD_LINK_OK) { + g_print ("linking output 1 converter failed\n"); + return -1; + } + gst_object_unref (sinkpad); + + if (!gst_element_link (c1, sink1)) { g_print ("linking output 1 failed\n"); return -1; } - gst_object_unref (sinkpad); /* link output 2 */ - sinkpad = gst_element_get_static_pad (convert, "sink"); + sinkpad = gst_element_get_static_pad (c2, "sink"); osel_src2 = gst_element_get_request_pad (osel, "src%d"); if (gst_pad_link (osel_src2, sinkpad) != GST_PAD_LINK_OK) { - g_print ("linking output 2 failed\n"); + g_print ("linking output 2 converter failed\n"); return -1; } gst_object_unref (sinkpad); - if (!gst_element_link (convert, sink2)) { + if (!gst_element_link (c2, sink2)) { g_print ("linking output 2 failed\n"); return -1; } From 5c097c447b397647e6857936bb7cd0eed4ce46f0 Mon Sep 17 00:00:00 2001 From: Alessandro Decina Date: Wed, 8 Dec 2010 19:36:48 +0100 Subject: [PATCH 038/448] dvbsuboverlay: fix compiler warnings on OSX. --- gst/dvbsuboverlay/gstdvbsuboverlay.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/gst/dvbsuboverlay/gstdvbsuboverlay.c b/gst/dvbsuboverlay/gstdvbsuboverlay.c index df9bedf95c..3f261e58b4 100644 --- a/gst/dvbsuboverlay/gstdvbsuboverlay.c +++ b/gst/dvbsuboverlay/gstdvbsuboverlay.c @@ -519,7 +519,7 @@ blit_i420 (GstDVBSubOverlay * overlay, DVBSubtitles * subs, GstBuffer * buffer) for (counter = 0; counter < subs->num_rects; counter++) { gint dw, dh; - gint32 sx, sy; /* 16.16 fixed point */ + gint32 sx = 0, sy; /* 16.16 fixed point */ gint32 xstep, ystep; /* 16.16 fixed point */ sub_region = subs->rects[counter]; @@ -894,7 +894,8 @@ gst_dvbsub_overlay_chain_video (GstPad * pad, GstBuffer * buffer) GST_LOG_OBJECT (overlay, "Video segment: %" GST_SEGMENT_FORMAT " --- Subtitle last_stop: %" GST_TIME_FORMAT " --- BUFFER: ts=%" GST_TIME_FORMAT, - &overlay->video_segment, &overlay->subtitle_segment.last_stop, + &overlay->video_segment, + GST_TIME_ARGS (overlay->subtitle_segment.last_stop), GST_TIME_ARGS (start)); /* ignore buffers that are outside of the current segment */ From 67415fc4128ba17cf1837135881c2e5fffa924c2 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Wed, 24 Nov 2010 17:28:57 -0300 Subject: [PATCH 039/448] camerabin2: viewfinderbin: Adds viewfinderbin element Adds viewfinder bin element, one of the modules of camerabin2 that is responsible for displaying the video from the camera. For now it is only a bin with ffmpegcolorspace ! videoscale ! autovideosink --- configure.ac | 2 + gst/camerabin2/Makefile.am | 15 +++ gst/camerabin2/gstviewfinderbin.c | 180 ++++++++++++++++++++++++++++++ gst/camerabin2/gstviewfinderbin.h | 54 +++++++++ 4 files changed, 251 insertions(+) create mode 100644 gst/camerabin2/Makefile.am create mode 100644 gst/camerabin2/gstviewfinderbin.c create mode 100644 gst/camerabin2/gstviewfinderbin.h diff --git a/configure.ac b/configure.ac index 674f029591..51b6d0e2bc 100644 --- a/configure.ac +++ b/configure.ac @@ -293,6 +293,7 @@ AG_GST_CHECK_PLUGIN(audioparsers) AG_GST_CHECK_PLUGIN(autoconvert) AG_GST_CHECK_PLUGIN(bayer) AG_GST_CHECK_PLUGIN(camerabin) +AG_GST_CHECK_PLUGIN(camerabin2) AG_GST_CHECK_PLUGIN(cdxaparse) AG_GST_CHECK_PLUGIN(coloreffects) AG_GST_CHECK_PLUGIN(colorspace) @@ -1719,6 +1720,7 @@ gst/audioparsers/Makefile gst/autoconvert/Makefile gst/bayer/Makefile gst/camerabin/Makefile +gst/camerabin2/Makefile gst/cdxaparse/Makefile gst/colorspace/Makefile gst/coloreffects/Makefile diff --git a/gst/camerabin2/Makefile.am b/gst/camerabin2/Makefile.am new file mode 100644 index 0000000000..287c73c41c --- /dev/null +++ b/gst/camerabin2/Makefile.am @@ -0,0 +1,15 @@ +plugin_LTLIBRARIES = libgstcamerabin2.la + +libgstcamerabin2_la_SOURCES = gstviewfinderbin.c + +libgstcamerabin2_la_CFLAGS = \ + $(GST_PLUGINS_BAD_CFLAGS) \ + $(GST_CFLAGS) $(GST_BASE_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) + +libgstcamerabin2_la_LIBADD = \ + $(GST_LIBS) $(GST_BASE_LIBS) $(GST_PLUGINS_BASE_LIBS) + +libgstcamerabin2_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) +libgstcamerabin2_la_LIBTOOLFLAGS = --tag=disable-static + +noinst_HEADERS = gstviewfinderbin.h diff --git a/gst/camerabin2/gstviewfinderbin.c b/gst/camerabin2/gstviewfinderbin.c new file mode 100644 index 0000000000..df9611307f --- /dev/null +++ b/gst/camerabin2/gstviewfinderbin.c @@ -0,0 +1,180 @@ +/* GStreamer + * Copyright (C) 2010 Thiago Santos + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +/** + * SECTION:element-gstviewfinderbin + * + * The gstviewfinderbin element does FIXME stuff. + * + * + * Example launch line + * |[ + * gst-launch -v videotestsrc ! viewfinderbin + * ]| + * FIXME Describe what the pipeline does. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstviewfinderbin.h" + +/* prototypes */ + + +enum +{ + PROP_0 +}; + +/* pad templates */ + +static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("video/x-raw-yuv; video/x-raw-rgb") + ); + +/* class initialization */ + +GST_BOILERPLATE (GstViewfinderBin, gst_viewfinder_bin, GstBin, GST_TYPE_BIN); + +/* Element class functions */ +static GstStateChangeReturn +gst_viewfinder_bin_change_state (GstElement * element, GstStateChange trans); + +static void +gst_viewfinder_bin_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&sink_template)); + + gst_element_class_set_details_simple (element_class, "Viewfinder Bin", + "Sink/Video", "Viewfinder Bin used in camerabin2", + "Thiago Santos "); +} + +static void +gst_viewfinder_bin_class_init (GstViewfinderBinClass * klass) +{ + GstElementClass *element_class; + + element_class = GST_ELEMENT_CLASS (klass); + + element_class->change_state = + GST_DEBUG_FUNCPTR (gst_viewfinder_bin_change_state); +} + +static void +gst_viewfinder_bin_init (GstViewfinderBin * viewfinderbin, + GstViewfinderBinClass * viewfinderbin_class) +{ + viewfinderbin->ghostpad = gst_ghost_pad_new_no_target_from_template ("sink", + gst_static_pad_template_get (&sink_template)); + gst_element_add_pad (GST_ELEMENT_CAST (viewfinderbin), + viewfinderbin->ghostpad); +} + +static gboolean +gst_viewfinder_bin_create_elements (GstViewfinderBin * vfbin) +{ + GstElement *csp; + GstElement *videoscale; + GstElement *sink; + GstPad *pad = NULL; + + if (vfbin->elements_created) + return TRUE; + + /* create elements */ + csp = gst_element_factory_make ("ffmpegcolorspace", "vfbin-csp"); + if (!csp) + goto error; + + videoscale = gst_element_factory_make ("videoscale", "vfbin-videoscale"); + if (!videoscale) + goto error; + + sink = gst_element_factory_make ("autovideosink", "vfbin-sink"); + if (!sink) + goto error; + + /* add and link */ + gst_bin_add_many (GST_BIN_CAST (vfbin), csp, videoscale, sink, NULL); + if (!gst_element_link_many (csp, videoscale, sink, NULL)) + goto error; + + /* add ghostpad */ + pad = gst_element_get_static_pad (csp, "sink"); + if (!gst_ghost_pad_set_target (GST_GHOST_PAD (vfbin->ghostpad), pad)) + goto error; + + vfbin->elements_created = TRUE; + return TRUE; + +error: + if (pad) + gst_object_unref (pad); + return FALSE; +} + +static GstStateChangeReturn +gst_viewfinder_bin_change_state (GstElement * element, GstStateChange trans) +{ + GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; + GstViewfinderBin *vfbin = GST_VIEWFINDER_BIN_CAST (element); + + switch (trans) { + case GST_STATE_CHANGE_NULL_TO_READY: + if (!gst_viewfinder_bin_create_elements (vfbin)) { + return GST_STATE_CHANGE_FAILURE; + } + break; + default: + break; + } + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, trans); + + switch (trans) { + case GST_STATE_CHANGE_READY_TO_NULL: + break; + default: + break; + } + + return ret; +} + +static gboolean +plugin_init (GstPlugin * plugin) +{ + gst_element_register (plugin, "viewfinderbin", GST_RANK_NONE, + gst_viewfinder_bin_get_type ()); + + return TRUE; +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "viewfinderbin", "viewfinder bin of camerabin2", + plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/gst/camerabin2/gstviewfinderbin.h b/gst/camerabin2/gstviewfinderbin.h new file mode 100644 index 0000000000..9b4567b098 --- /dev/null +++ b/gst/camerabin2/gstviewfinderbin.h @@ -0,0 +1,54 @@ +/* GStreamer + * Copyright (C) 2010 Thiago Santos + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef _GST_VIEWFINDER_BIN_H_ +#define _GST_VIEWFINDER_BIN_H_ + +#include + +G_BEGIN_DECLS + +#define GST_TYPE_VIEWFINDER_BIN (gst_viewfinder_bin_get_type()) +#define GST_VIEWFINDER_BIN(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VIEWFINDER_BIN,GstViewfinderBin)) +#define GST_VIEWFINDER_BIN_CAST(obj) ((GstViewfinderBin *) obj) +#define GST_VIEWFINDER_BIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VIEWFINDER_BIN,GstViewfinderBinClass)) +#define GST_IS_VIEWFINDER_BIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VIEWFINDER_BIN)) +#define GST_IS_VIEWFINDER_BIN_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VIEWFINDER_BIN)) + +typedef struct _GstViewfinderBin GstViewfinderBin; +typedef struct _GstViewfinderBinClass GstViewfinderBinClass; + +struct _GstViewfinderBin +{ + GstBin bin; + + GstPad *ghostpad; + + gboolean elements_created; +}; + +struct _GstViewfinderBinClass +{ + GstBinClass bin_class; +}; + +GType gst_viewfinder_bin_get_type (void); + +G_END_DECLS + +#endif From 3a8ec18f9680e0bdbee02d041852dd83273f7f9b Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Wed, 24 Nov 2010 20:15:38 -0300 Subject: [PATCH 040/448] camerabin2: Move plugin init to a separate file Moves plugin init to gstplugin.c to allow multiple elements to register themselves. --- gst/camerabin2/Makefile.am | 3 ++- gst/camerabin2/gstplugin.c | 40 +++++++++++++++++++++++++++++++ gst/camerabin2/gstviewfinderbin.c | 13 +++------- gst/camerabin2/gstviewfinderbin.h | 1 + 4 files changed, 46 insertions(+), 11 deletions(-) create mode 100644 gst/camerabin2/gstplugin.c diff --git a/gst/camerabin2/Makefile.am b/gst/camerabin2/Makefile.am index 287c73c41c..f00f49a903 100644 --- a/gst/camerabin2/Makefile.am +++ b/gst/camerabin2/Makefile.am @@ -1,6 +1,7 @@ plugin_LTLIBRARIES = libgstcamerabin2.la -libgstcamerabin2_la_SOURCES = gstviewfinderbin.c +libgstcamerabin2_la_SOURCES = gstviewfinderbin.c \ + gstplugin.c libgstcamerabin2_la_CFLAGS = \ $(GST_PLUGINS_BAD_CFLAGS) \ diff --git a/gst/camerabin2/gstplugin.c b/gst/camerabin2/gstplugin.c new file mode 100644 index 0000000000..798ed91122 --- /dev/null +++ b/gst/camerabin2/gstplugin.c @@ -0,0 +1,40 @@ +/* GStreamer + * Copyright (C) <2010> Thiago Santos + * + * gstplugin.c: camerabin2 plugin registering + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstviewfinderbin.h" + +static gboolean +plugin_init (GstPlugin * plugin) +{ + if (!gst_viewfinder_bin_plugin_init (plugin)) + return FALSE; + + return TRUE; +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "camerabin2", "camerabin2", + plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/gst/camerabin2/gstviewfinderbin.c b/gst/camerabin2/gstviewfinderbin.c index df9611307f..5d92526ad4 100644 --- a/gst/camerabin2/gstviewfinderbin.c +++ b/gst/camerabin2/gstviewfinderbin.c @@ -165,16 +165,9 @@ gst_viewfinder_bin_change_state (GstElement * element, GstStateChange trans) return ret; } -static gboolean -plugin_init (GstPlugin * plugin) +gboolean +gst_viewfinder_bin_plugin_init (GstPlugin * plugin) { - gst_element_register (plugin, "viewfinderbin", GST_RANK_NONE, + return gst_element_register (plugin, "viewfinderbin", GST_RANK_NONE, gst_viewfinder_bin_get_type ()); - - return TRUE; } - -GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, - GST_VERSION_MINOR, - "viewfinderbin", "viewfinder bin of camerabin2", - plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/gst/camerabin2/gstviewfinderbin.h b/gst/camerabin2/gstviewfinderbin.h index 9b4567b098..da5e0efcb8 100644 --- a/gst/camerabin2/gstviewfinderbin.h +++ b/gst/camerabin2/gstviewfinderbin.h @@ -48,6 +48,7 @@ struct _GstViewfinderBinClass }; GType gst_viewfinder_bin_get_type (void); +gboolean gst_viewfinder_bin_plugin_init (GstPlugin * plugin); G_END_DECLS From 12245366d811f94724865ef8e3b7ab1d54cceb2d Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Wed, 24 Nov 2010 20:31:33 -0300 Subject: [PATCH 041/448] camerabin2: Adds new imagecapturebin Adds an bin that is responsible for image captures. It is a simple ffmpegcolorspace ! jpegenc ! jifmux ! multifilesink for now. --- gst/camerabin2/Makefile.am | 4 +- gst/camerabin2/gstimagecapturebin.c | 182 ++++++++++++++++++++++++++++ gst/camerabin2/gstimagecapturebin.h | 55 +++++++++ gst/camerabin2/gstplugin.c | 3 + 4 files changed, 243 insertions(+), 1 deletion(-) create mode 100644 gst/camerabin2/gstimagecapturebin.c create mode 100644 gst/camerabin2/gstimagecapturebin.h diff --git a/gst/camerabin2/Makefile.am b/gst/camerabin2/Makefile.am index f00f49a903..49d29aa005 100644 --- a/gst/camerabin2/Makefile.am +++ b/gst/camerabin2/Makefile.am @@ -1,6 +1,7 @@ plugin_LTLIBRARIES = libgstcamerabin2.la libgstcamerabin2_la_SOURCES = gstviewfinderbin.c \ + gstimagecapturebin.c \ gstplugin.c libgstcamerabin2_la_CFLAGS = \ @@ -13,4 +14,5 @@ libgstcamerabin2_la_LIBADD = \ libgstcamerabin2_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) libgstcamerabin2_la_LIBTOOLFLAGS = --tag=disable-static -noinst_HEADERS = gstviewfinderbin.h +noinst_HEADERS = gstviewfinderbin.h \ + gstimagecapturebin.h diff --git a/gst/camerabin2/gstimagecapturebin.c b/gst/camerabin2/gstimagecapturebin.c new file mode 100644 index 0000000000..6334a8b3e2 --- /dev/null +++ b/gst/camerabin2/gstimagecapturebin.c @@ -0,0 +1,182 @@ +/* GStreamer + * Copyright (C) 2010 Thiago Santos + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +/** + * SECTION:element-gstimagecapturebin + * + * The gstimagecapturebin element does FIXME stuff. + * + * + * Example launch line + * |[ + * gst-launch -v videotestsrc num-buffers=3 ! imagecapturebin + * ]| + * FIXME Describe what the pipeline does. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstimagecapturebin.h" + +/* prototypes */ + + +enum +{ + PROP_0 +}; + +/* pad templates */ + +static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("video/x-raw-yuv; video/x-raw-rgb") + ); + +/* class initialization */ + +GST_BOILERPLATE (GstImageCaptureBin, gst_image_capture_bin, GstBin, + GST_TYPE_BIN); + +/* Element class functions */ +static GstStateChangeReturn +gst_image_capture_bin_change_state (GstElement * element, GstStateChange trans); + +static void +gst_image_capture_bin_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&sink_template)); + + gst_element_class_set_details_simple (element_class, "Image Capture Bin", + "Sink/Video", "Image Capture Bin used in camerabin2", + "Thiago Santos "); +} + +static void +gst_image_capture_bin_class_init (GstImageCaptureBinClass * klass) +{ + GstElementClass *element_class; + + element_class = GST_ELEMENT_CLASS (klass); + + element_class->change_state = + GST_DEBUG_FUNCPTR (gst_image_capture_bin_change_state); +} + +static void +gst_image_capture_bin_init (GstImageCaptureBin * image_capturebin, + GstImageCaptureBinClass * image_capturebin_class) +{ + image_capturebin->ghostpad = + gst_ghost_pad_new_no_target_from_template ("sink", + gst_static_pad_template_get (&sink_template)); + gst_element_add_pad (GST_ELEMENT_CAST (image_capturebin), + image_capturebin->ghostpad); +} + +static gboolean +gst_image_capture_bin_create_elements (GstImageCaptureBin * icbin) +{ + GstElement *csp; + GstElement *enc; + GstElement *mux; + GstElement *sink; + GstPad *pad = NULL; + + if (icbin->elements_created) + return TRUE; + + /* create elements */ + csp = gst_element_factory_make ("ffmpegcolorspace", "icbin-csp"); + if (!csp) + goto error; + + enc = gst_element_factory_make ("jpegenc", "icbin-enc"); + if (!enc) + goto error; + + mux = gst_element_factory_make ("jifmux", "icbin-mux"); + if (!mux) + goto error; + + sink = gst_element_factory_make ("multifilesink", "icbin-sink"); + if (!sink) + goto error; + + g_object_set (sink, "location", "cap_%03d.jpg", NULL); + + /* add and link */ + gst_bin_add_many (GST_BIN_CAST (icbin), csp, enc, mux, sink, NULL); + if (!gst_element_link_many (csp, enc, mux, sink, NULL)) + goto error; + + /* add ghostpad */ + pad = gst_element_get_static_pad (csp, "sink"); + if (!gst_ghost_pad_set_target (GST_GHOST_PAD (icbin->ghostpad), pad)) + goto error; + + icbin->elements_created = TRUE; + return TRUE; + +error: + if (pad) + gst_object_unref (pad); + return FALSE; +} + +static GstStateChangeReturn +gst_image_capture_bin_change_state (GstElement * element, GstStateChange trans) +{ + GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; + GstImageCaptureBin *icbin = GST_IMAGE_CAPTURE_BIN_CAST (element); + + switch (trans) { + case GST_STATE_CHANGE_NULL_TO_READY: + if (!gst_image_capture_bin_create_elements (icbin)) { + return GST_STATE_CHANGE_FAILURE; + } + break; + default: + break; + } + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, trans); + + switch (trans) { + case GST_STATE_CHANGE_READY_TO_NULL: + break; + default: + break; + } + + return ret; +} + +gboolean +gst_image_capture_bin_plugin_init (GstPlugin * plugin) +{ + return gst_element_register (plugin, "imagecapturebin", GST_RANK_NONE, + gst_image_capture_bin_get_type ()); +} diff --git a/gst/camerabin2/gstimagecapturebin.h b/gst/camerabin2/gstimagecapturebin.h new file mode 100644 index 0000000000..b1f5f168d2 --- /dev/null +++ b/gst/camerabin2/gstimagecapturebin.h @@ -0,0 +1,55 @@ +/* GStreamer + * Copyright (C) 2010 Thiago Santos + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef _GST_IMAGE_CAPTURE_BIN_H_ +#define _GST_IMAGE_CAPTURE_BIN_H_ + +#include + +G_BEGIN_DECLS + +#define GST_TYPE_IMAGE_CAPTURE_BIN (gst_image_capture_bin_get_type()) +#define GST_IMAGE_CAPTURE_BIN(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_IMAGE_CAPTURE_BIN,GstImageCaptureBin)) +#define GST_IMAGE_CAPTURE_BIN_CAST(obj) ((GstImageCaptureBin *) obj) +#define GST_IMAGE_CAPTURE_BIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_IMAGE_CAPTURE_BIN,GstImageCaptureBinClass)) +#define GST_IS_IMAGE_CAPTURE_BIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_IMAGE_CAPTURE_BIN)) +#define GST_IS_IMAGE_CAPTURE_BIN_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_IMAGE_CAPTURE_BIN)) + +typedef struct _GstImageCaptureBin GstImageCaptureBin; +typedef struct _GstImageCaptureBinClass GstImageCaptureBinClass; + +struct _GstImageCaptureBin +{ + GstBin bin; + + GstPad *ghostpad; + + gboolean elements_created; +}; + +struct _GstImageCaptureBinClass +{ + GstBinClass bin_class; +}; + +GType gst_image_capture_bin_get_type (void); +gboolean gst_image_capture_bin_plugin_init (GstPlugin * plugin); + +G_END_DECLS + +#endif diff --git a/gst/camerabin2/gstplugin.c b/gst/camerabin2/gstplugin.c index 798ed91122..1f1dd0ea7a 100644 --- a/gst/camerabin2/gstplugin.c +++ b/gst/camerabin2/gstplugin.c @@ -24,12 +24,15 @@ #endif #include "gstviewfinderbin.h" +#include "gstimagecapturebin.h" static gboolean plugin_init (GstPlugin * plugin) { if (!gst_viewfinder_bin_plugin_init (plugin)) return FALSE; + if (!gst_image_capture_bin_plugin_init (plugin)) + return FALSE; return TRUE; } From 94da473ba7c216025f3c6c52897a6377ce72ba05 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Thu, 25 Nov 2010 13:00:50 -0300 Subject: [PATCH 042/448] camerabin2: Adding v4l2camerasrc from robclark's branch Adds 3-pad v4l2 camera source from Rob Clark's camerabin branch on http://gitorious.org/robclark-gstreamer/gst-plugins-bad --- gst/camerabin2/Makefile.am | 17 +- gst/camerabin2/camerabingeneral.c | 276 +++++++ gst/camerabin2/camerabingeneral.h | 42 ++ gst/camerabin2/gstbasecamerasrc.c | 509 +++++++++++++ gst/camerabin2/gstbasecamerasrc.h | 146 ++++ gst/camerabin2/gstcamerabin-enum.c | 78 ++ gst/camerabin2/gstcamerabin-enum.h | 140 ++++ gst/camerabin2/gstplugin.c | 3 + gst/camerabin2/gstv4l2camerasrc.c | 1077 ++++++++++++++++++++++++++++ gst/camerabin2/gstv4l2camerasrc.h | 112 +++ 10 files changed, 2397 insertions(+), 3 deletions(-) create mode 100644 gst/camerabin2/camerabingeneral.c create mode 100644 gst/camerabin2/camerabingeneral.h create mode 100644 gst/camerabin2/gstbasecamerasrc.c create mode 100644 gst/camerabin2/gstbasecamerasrc.h create mode 100644 gst/camerabin2/gstcamerabin-enum.c create mode 100644 gst/camerabin2/gstcamerabin-enum.h create mode 100644 gst/camerabin2/gstv4l2camerasrc.c create mode 100644 gst/camerabin2/gstv4l2camerasrc.h diff --git a/gst/camerabin2/Makefile.am b/gst/camerabin2/Makefile.am index 49d29aa005..25b1e61ed6 100644 --- a/gst/camerabin2/Makefile.am +++ b/gst/camerabin2/Makefile.am @@ -2,17 +2,28 @@ plugin_LTLIBRARIES = libgstcamerabin2.la libgstcamerabin2_la_SOURCES = gstviewfinderbin.c \ gstimagecapturebin.c \ + camerabingeneral.c \ + gstbasecamerasrc.c \ + gstcamerabin-enum.c \ + gstv4l2camerasrc.c \ gstplugin.c libgstcamerabin2_la_CFLAGS = \ $(GST_PLUGINS_BAD_CFLAGS) \ - $(GST_CFLAGS) $(GST_BASE_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) + $(GST_CFLAGS) $(GST_BASE_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) \ + -DGST_USE_UNSTABLE_API libgstcamerabin2_la_LIBADD = \ - $(GST_LIBS) $(GST_BASE_LIBS) $(GST_PLUGINS_BASE_LIBS) + $(top_builddir)/gst-libs/gst/interfaces/libgstphotography-$(GST_MAJORMINOR).la \ + $(GST_LIBS) $(GST_BASE_LIBS) $(GST_PLUGINS_BASE_LIBS) \ + -lgstinterfaces-$(GST_MAJORMINOR) -lgsttag-$(GST_MAJORMINOR) libgstcamerabin2_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) libgstcamerabin2_la_LIBTOOLFLAGS = --tag=disable-static noinst_HEADERS = gstviewfinderbin.h \ - gstimagecapturebin.h + gstimagecapturebin.h \ + camerabingeneral.h \ + gstbasecamerasrc.h \ + gstv4l2camerasrc.h \ + gstcamerabin-enum.h diff --git a/gst/camerabin2/camerabingeneral.c b/gst/camerabin2/camerabingeneral.c new file mode 100644 index 0000000000..2a50d9e126 --- /dev/null +++ b/gst/camerabin2/camerabingeneral.c @@ -0,0 +1,276 @@ +/* + * GStreamer + * Copyright (C) 2008 Nokia Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/** + * SECTION:camerabingeneral + * @short_description: helper functions for #GstCameraBin and it's modules + * + * Common helper functions for #GstCameraBin, #GstCameraBinImage and + * #GstCameraBinVideo. + * + */ +#include + +#include "camerabingeneral.h" +#include + +GST_DEBUG_CATEGORY (gst_camerabin_debug); + +/** + * gst_camerabin_add_element: + * @bin: add an element to this bin + * @new_elem: new element to be added + * + * Adds given element to given @bin. Looks for an unconnected src pad + * from the @bin and links the element to it. Raises an error if adding + * or linking failed. Unrefs the element in the case of an error. + * + * Returns: %TRUE if adding and linking succeeded, %FALSE otherwise. + */ +gboolean +gst_camerabin_add_element (GstBin * bin, GstElement * new_elem) +{ + return gst_camerabin_add_element_full (bin, NULL, new_elem, NULL); +} + +/** + * gst_camerabin_add_element_full: + * @bin: add an element to this bin + * @srcpad: src pad name, or NULL for any + * @new_elem: new element to be added + * @dstpad: dst pad name, or NULL for any + * + * Adds given element to given @bin. Looks for an unconnected src pad + * (with name @srcpad, if specified) from the @bin and links the element + * to it. Raises an error if adding or linking failed. Unrefs the element + * in the case of an error. + * + * Returns: %TRUE if adding and linking succeeded, %FALSE otherwise. + */ +gboolean +gst_camerabin_add_element_full (GstBin * bin, const gchar * srcpad, + GstElement * new_elem, const gchar * dstpad) +{ + gboolean ret; + + g_return_val_if_fail (bin, FALSE); + g_return_val_if_fail (new_elem, FALSE); + + ret = gst_camerabin_try_add_element (bin, srcpad, new_elem, dstpad); + + if (!ret) { + gchar *elem_name = gst_element_get_name (new_elem); + GST_ELEMENT_ERROR (bin, CORE, NEGOTIATION, (NULL), + ("linking %s failed", elem_name)); + g_free (elem_name); + gst_object_unref (new_elem); + } + + return ret; +} + +/** + * gst_camerabin_try_add_element: + * @bin: tries adding an element to this bin + * @srcpad: src pad name, or NULL for any + * @new_elem: new element to be added + * @dstpad: dst pad name, or NULL for any + * + * Adds given element to given @bin. Looks for an unconnected src pad + * (with name @srcpad, if specified) from the @bin and links the element to + * it. + * + * Returns: %TRUE if adding and linking succeeded, %FALSE otherwise. + */ +gboolean +gst_camerabin_try_add_element (GstBin * bin, const gchar * srcpad, + GstElement * new_elem, const gchar * dstpad) +{ + GstPad *bin_pad; + GstElement *bin_elem; + gboolean ret = TRUE; + + g_return_val_if_fail (bin, FALSE); + g_return_val_if_fail (new_elem, FALSE); + + /* Get pads for linking */ + bin_pad = gst_bin_find_unlinked_pad (bin, GST_PAD_SRC); + /* Add to bin */ + gst_bin_add (GST_BIN (bin), new_elem); + /* Link, if unconnected pad was found, otherwise just add it to bin */ + if (bin_pad) { + GST_DEBUG_OBJECT (bin, "linking %s to %s:%s", GST_OBJECT_NAME (new_elem), + GST_DEBUG_PAD_NAME (bin_pad)); + bin_elem = gst_pad_get_parent_element (bin_pad); + gst_object_unref (bin_pad); + if (!gst_element_link_pads (bin_elem, srcpad, new_elem, dstpad)) { + gst_object_ref (new_elem); + gst_bin_remove (bin, new_elem); + ret = FALSE; + } + gst_object_unref (bin_elem); + } else { + GST_INFO_OBJECT (bin, "no unlinked source pad in bin"); + } + + return ret; +} + +/** + * gst_camerabin_create_and_add_element: + * @bin: tries adding an element to this bin + * @elem_name: name of the element to be created + * + * Creates an element according to given name and + * adds it to given @bin. Looks for an unconnected src pad + * from the @bin and links the element to it. + * + * Returns: pointer to the new element if successful, NULL otherwise. + */ +GstElement * +gst_camerabin_create_and_add_element (GstBin * bin, const gchar * elem_name) +{ + GstElement *new_elem; + + g_return_val_if_fail (bin, FALSE); + g_return_val_if_fail (elem_name, FALSE); + + new_elem = gst_element_factory_make (elem_name, NULL); + if (!new_elem) { + GST_ELEMENT_ERROR (bin, CORE, MISSING_PLUGIN, (NULL), + ("could not create \"%s\" element.", elem_name)); + } else if (!gst_camerabin_add_element (bin, new_elem)) { + new_elem = NULL; + } + + return new_elem; +} + +/* try to change the state of an element. This function returns the element when + * the state change could be performed. When this function returns NULL an error + * occured and the element is unreffed if @unref is TRUE. */ +static GstElement * +try_element (GstElement * bin, GstElement * element, gboolean unref) +{ + GstStateChangeReturn ret; + + if (element) { + ret = gst_element_set_state (element, GST_STATE_READY); + if (ret == GST_STATE_CHANGE_FAILURE) { + GST_DEBUG_OBJECT (bin, "failed state change.."); + gst_element_set_state (element, GST_STATE_NULL); + if (unref) + gst_object_unref (element); + element = NULL; + } + } + return element; +} + +GstElement * +gst_camerabin_setup_default_element (GstBin * bin, GstElement * user_elem, + const gchar * auto_elem_name, const gchar * default_elem_name) +{ + GstElement *elem; + + if (user_elem) { + GST_DEBUG_OBJECT (bin, "trying configured element"); + elem = try_element (GST_ELEMENT_CAST (bin), user_elem, FALSE); + } else { + /* only try fallback if no specific sink was chosen */ + GST_DEBUG_OBJECT (bin, "trying %s", auto_elem_name); + elem = gst_element_factory_make (auto_elem_name, NULL); + elem = try_element (GST_ELEMENT_CAST (bin), elem, TRUE); + if (elem == NULL) { + /* if default sink from config.h is different then try it too */ + if (strcmp (default_elem_name, auto_elem_name)) { + GST_DEBUG_OBJECT (bin, "trying %s", default_elem_name); + elem = gst_element_factory_make (default_elem_name, NULL); + elem = try_element (GST_ELEMENT_CAST (bin), elem, TRUE); + } + } + } + return elem; +} + +/** + * gst_camerabin_remove_elements_from_bin: + * @bin: removes all elements from this bin + * + * Removes all elements from this @bin. + */ +void +gst_camerabin_remove_elements_from_bin (GstBin * bin) +{ + GstIterator *iter = NULL; + gpointer data = NULL; + GstElement *elem = NULL; + gboolean done = FALSE; + + iter = gst_bin_iterate_elements (bin); + while (!done) { + switch (gst_iterator_next (iter, &data)) { + case GST_ITERATOR_OK: + elem = GST_ELEMENT (data); + gst_bin_remove (bin, elem); + gst_element_set_state (GST_ELEMENT (elem), GST_STATE_NULL); + /* Iterator increased the element refcount, so unref */ + gst_object_unref (elem); + break; + case GST_ITERATOR_RESYNC: + gst_iterator_resync (iter); + break; + case GST_ITERATOR_ERROR: + GST_WARNING_OBJECT (bin, "error in iterating elements"); + done = TRUE; + break; + case GST_ITERATOR_DONE: + done = TRUE; + break; + } + } + gst_iterator_free (iter); +} + +/** + * gst_camerabin_drop_eos_probe: + * @pad: pad receiving the event + * @event: received event + * @u_data: not used + * + * Event probe that drop all eos events. + * + * Returns: FALSE to drop the event, TRUE otherwise + */ +gboolean +gst_camerabin_drop_eos_probe (GstPad * pad, GstEvent * event, gpointer u_data) +{ + gboolean ret = TRUE; + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_EOS: + GST_DEBUG ("dropping eos in %s:%s", GST_DEBUG_PAD_NAME (pad)); + ret = FALSE; + break; + default: + break; + } + return ret; +} diff --git a/gst/camerabin2/camerabingeneral.h b/gst/camerabin2/camerabingeneral.h new file mode 100644 index 0000000000..93520c5a60 --- /dev/null +++ b/gst/camerabin2/camerabingeneral.h @@ -0,0 +1,42 @@ +/* + * GStreamer + * Copyright (C) 2008 Nokia Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __CAMERABIN_GENERAL_H_ +#define __CAMERABIN_GENERAL_H_ + +#include + +gboolean gst_camerabin_try_add_element (GstBin * bin, const gchar * srcpad, GstElement * new_elem, const gchar * dstpad); +gboolean gst_camerabin_add_element (GstBin * bin, GstElement * new_elem); +gboolean gst_camerabin_add_element_full (GstBin * bin, const gchar * srcpad, GstElement * new_elem, const gchar * dstpad); + +GstElement *gst_camerabin_create_and_add_element (GstBin * bin, const gchar * elem_name); + +GstElement * gst_camerabin_setup_default_element (GstBin * bin, GstElement *user_elem, const gchar *auto_elem_name, const gchar *default_elem_name); + +void gst_camerabin_remove_elements_from_bin (GstBin * bin); + +gboolean gst_camerabin_drop_eos_probe (GstPad * pad, GstEvent * event, gpointer u_data); + +/* debug logging category */ +GST_DEBUG_CATEGORY_EXTERN (gst_camerabin_debug); +#define GST_CAT_DEFAULT gst_camerabin_debug + +#endif /* #ifndef __CAMERABIN_GENERAL_H_ */ diff --git a/gst/camerabin2/gstbasecamerasrc.c b/gst/camerabin2/gstbasecamerasrc.c new file mode 100644 index 0000000000..aba756e82b --- /dev/null +++ b/gst/camerabin2/gstbasecamerasrc.c @@ -0,0 +1,509 @@ +/* + * GStreamer + * Copyright (C) 2010 Texas Instruments, Inc + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + + +/** + * SECTION:element-basecamerasrc + * + * Base class for the camera src bin used by camerabin. Indented to be + * subclassed when plugging in more sophisticated cameras. + */ + + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "gstbasecamerasrc.h" + +GST_DEBUG_CATEGORY (base_camera_src_debug); +#define GST_CAT_DEFAULT base_camera_src_debug + +GST_BOILERPLATE (GstBaseCameraSrc, gst_base_camera_src, GstBin, GST_TYPE_BIN); + +static GstStaticPadTemplate vfsrc_template = GST_STATIC_PAD_TEMPLATE ("vfsrc", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +static GstStaticPadTemplate imgsrc_template = GST_STATIC_PAD_TEMPLATE ("imgsrc", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +static GstStaticPadTemplate vidsrc_template = GST_STATIC_PAD_TEMPLATE ("vidsrc", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +/* note: we could provide a vmethod for derived class to overload to provide + * it's own implementation of interface.. but in all cases I can think of at + * moment, either the camerasrc itself, or some element within the bin, will + * be implementing the interface.. + */ + +/** + * gst_base_camera_src_get_photography: + * @self: the camerasrc bin + * + * Get object implementing photography interface, if there is one. Otherwise + * returns NULL. + */ +GstPhotography * +gst_base_camera_src_get_photography (GstBaseCameraSrc * self) +{ + GstElement *elem; + + if (GST_IS_PHOTOGRAPHY (self)) { + elem = GST_ELEMENT (self); + } else { + elem = gst_bin_get_by_interface (GST_BIN (self), GST_TYPE_PHOTOGRAPHY); + } + + if (elem) { + return GST_PHOTOGRAPHY (self); + } + + return NULL; +} + + +/** + * gst_base_camera_src_get_colorbalance: + * @self: the camerasrc bin + * + * Get object implementing colorbalance interface, if there is one. Otherwise + * returns NULL. + */ +GstColorBalance * +gst_base_camera_src_get_color_balance (GstBaseCameraSrc * self) +{ + GstElement *elem; + + if (GST_IS_COLOR_BALANCE (self)) { + elem = GST_ELEMENT (self); + } else { + elem = gst_bin_get_by_interface (GST_BIN (self), GST_TYPE_COLOR_BALANCE); + } + + if (elem) { + return GST_COLOR_BALANCE (self); + } + + return NULL; +} + +/** + * gst_base_camera_src_set_mode: + * @self: the camerasrc bin + * @mode: the mode + * + * XXX + */ +gboolean +gst_base_camera_src_set_mode (GstBaseCameraSrc * self, GstCameraBinMode mode) +{ + GstBaseCameraSrcClass *bclass = GST_BASE_CAMERA_SRC_GET_CLASS (self); + + g_return_val_if_fail (bclass->set_mode, FALSE); + + return bclass->set_mode (self, mode); +} + +/** + * gst_base_camera_src_setup_zoom: + * @self: camerasrc object + * + * Apply zoom configured to camerabin to capture. + */ +void +gst_base_camera_src_setup_zoom (GstBaseCameraSrc * self) +{ + GstBaseCameraSrcClass *bclass = GST_BASE_CAMERA_SRC_GET_CLASS (self); + gint zoom; + + zoom = g_atomic_int_get (&self->zoom); + + g_return_if_fail (zoom); + g_return_if_fail (bclass->set_zoom); + + bclass->set_zoom (self, zoom); +} + + +/** + * gst_base_camera_src_get_allowed_input_caps: + * @self: the camerasrc bin + * + * Retrieve caps from videosrc describing formats it supports + * + * Returns: caps object from videosrc + */ +GstCaps * +gst_base_camera_src_get_allowed_input_caps (GstBaseCameraSrc * self) +{ + GstBaseCameraSrcClass *bclass = GST_BASE_CAMERA_SRC_GET_CLASS (self); + + g_return_val_if_fail (bclass->get_allowed_input_caps, NULL); + + return bclass->get_allowed_input_caps (self); +} + +/** + * gst_base_camera_src_finish_image_capture: + * @self: camerasrc object + * + * Perform finishing operations after image capture is done and + * returning back to view finder mode. + */ +void +gst_base_camera_src_finish_image_capture (GstBaseCameraSrc * self) +{ + GstBaseCameraSrcClass *bclass = GST_BASE_CAMERA_SRC_GET_CLASS (self); + + if (bclass->finish_image_capture) { + bclass->finish_image_capture (self); + } +} + +/** + * gst_base_camera_src_find_better_framerate: + * @self: camerasrc object + * @st: structure that contains framerate candidates + * @orig_framerate: best framerate so far + * + * Looks for framerate better than @orig_framerate from @st structure. + * In night mode lowest framerate is considered best, otherwise highest is + * best. + * + * Returns: @orig_framerate or better if found + */ +const GValue * +gst_base_camera_src_find_better_framerate (GstBaseCameraSrc * self, + GstStructure * st, const GValue * orig_framerate) +{ + const GValue *framerate = NULL; + guint i, i_best, list_size; + gint res, comparison; + + if (self->night_mode) { + GST_LOG_OBJECT (self, "finding min framerate in %" GST_PTR_FORMAT, st); + comparison = GST_VALUE_LESS_THAN; + } else { + GST_LOG_OBJECT (self, "finding max framerate in %" GST_PTR_FORMAT, st); + comparison = GST_VALUE_GREATER_THAN; + } + + if (gst_structure_has_field (st, "framerate")) { + framerate = gst_structure_get_value (st, "framerate"); + /* Handle framerate lists */ + if (GST_VALUE_HOLDS_LIST (framerate)) { + list_size = gst_value_list_get_size (framerate); + GST_LOG_OBJECT (self, "finding framerate from list"); + for (i = 0, i_best = 0; i < list_size; i++) { + res = gst_value_compare (gst_value_list_get_value (framerate, i), + gst_value_list_get_value (framerate, i_best)); + if (comparison == res) { + i_best = i; + } + } + GST_LOG_OBJECT (self, "found best framerate from index %d", i_best); + framerate = gst_value_list_get_value (framerate, i_best); + } + /* Handle framerate ranges */ + if (GST_VALUE_HOLDS_FRACTION_RANGE (framerate)) { + if (self->night_mode) { + GST_LOG_OBJECT (self, "getting min framerate from range"); + framerate = gst_value_get_fraction_range_min (framerate); + } else { + GST_LOG_OBJECT (self, "getting max framerate from range"); + framerate = gst_value_get_fraction_range_max (framerate); + } + } + } + + /* Check if we found better framerate */ + if (orig_framerate && framerate) { + res = gst_value_compare (orig_framerate, framerate); + if (comparison == res) { + GST_LOG_OBJECT (self, "original framerate was the best"); + framerate = orig_framerate; + } + } + + return framerate; +} + +/** + * + */ +static void +gst_base_camera_src_dispose (GObject * object) +{ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +gst_base_camera_src_finalize (GstBaseCameraSrc * self) +{ + G_OBJECT_CLASS (parent_class)->finalize ((GObject *) (self)); +} + +static void +gst_base_camera_src_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec) +{ + GstBaseCameraSrc *self = GST_BASE_CAMERA_SRC (object); + + switch (prop_id) { + case ARG_ZOOM:{ + g_atomic_int_set (&self->zoom, g_value_get_int (value)); + /* does not set it if in NULL, the src is not created yet */ + if (GST_STATE (self) != GST_STATE_NULL) + gst_base_camera_src_setup_zoom (self); + break; + } + case ARG_IMAGE_CAPTURE_WIDTH:{ + gint width = g_value_get_int (value); + + if (width != self->image_capture_width) { + self->image_capture_width = width; +//XXX self->image_capture_caps_update = TRUE; + } + break; + } + case ARG_IMAGE_CAPTURE_HEIGHT:{ + gint height = g_value_get_int (value); + + if (height != self->image_capture_height) { + self->image_capture_height = height; +//XXX self->image_capture_caps_update = TRUE; + } + break; + } + case ARG_VIDEO_CAPTURE_WIDTH:{ + gint width = g_value_get_int (value); + + if (width != self->width) { + self->width = width; +//XXX self->video_capture_caps_update = TRUE; + } + break; + } + case ARG_VIDEO_CAPTURE_HEIGHT:{ + gint height = g_value_get_int (value); + + if (height != self->height) { + self->height = height; +//XXX self->video_capture_caps_update = TRUE; + } + break; + } + case ARG_VIDEO_CAPTURE_FRAMERATE:{ + gint fps_n, fps_d; + + fps_n = gst_value_get_fraction_numerator (value); + fps_d = gst_value_get_fraction_denominator (value); + + if (fps_n != self->fps_n || fps_d != self->fps_d) { + self->fps_n = fps_n; + self->fps_d = fps_d; +//XXX self->video_capture_caps_update = TRUE; + } + break; + } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec); + break; + } +} + +static void +gst_base_camera_src_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec) +{ + GstBaseCameraSrc *self = GST_BASE_CAMERA_SRC (object); + + switch (prop_id) { + case ARG_ZOOM: + g_value_set_int (value, g_atomic_int_get (&self->zoom)); + break; + case ARG_IMAGE_CAPTURE_WIDTH: + g_value_set_int (value, self->image_capture_width); + break; + case ARG_IMAGE_CAPTURE_HEIGHT: + g_value_set_int (value, self->image_capture_height); + break; + case ARG_VIDEO_CAPTURE_WIDTH: + g_value_set_int (value, self->width); + break; + case ARG_VIDEO_CAPTURE_HEIGHT: + g_value_set_int (value, self->height); + break; + case ARG_VIDEO_CAPTURE_FRAMERATE: + gst_value_set_fraction (value, self->fps_n, self->fps_d); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec); + break; + } +} + +static gboolean +construct_pipeline (GstBaseCameraSrc * self) +{ + GstBaseCameraSrcClass *bclass = GST_BASE_CAMERA_SRC_GET_CLASS (self); + GstPad *vfsrc = NULL; + GstPad *imgsrc = NULL; + GstPad *vidsrc = NULL; + + g_return_val_if_fail (bclass->construct_pipeline, FALSE); + + if (!bclass->construct_pipeline (self, &vfsrc, &imgsrc, &vidsrc)) { + GST_ERROR_OBJECT (self, "pipeline construction failed"); + return FALSE; + } + + if (!vfsrc || !imgsrc || !vidsrc) { + GST_ERROR_OBJECT (self, "derived class must return src pads"); + return FALSE; + } + + GST_DEBUG_OBJECT (self, "vfsrc: %" GST_PTR_FORMAT, vfsrc); + GST_DEBUG_OBJECT (self, "imgsrc: %" GST_PTR_FORMAT, imgsrc); + GST_DEBUG_OBJECT (self, "vidsrc: %" GST_PTR_FORMAT, vidsrc); + + /* hook-up the ghostpads */ + gst_ghost_pad_set_target (GST_GHOST_PAD (self->vfsrc), vfsrc); + gst_ghost_pad_set_target (GST_GHOST_PAD (self->imgsrc), imgsrc); + gst_ghost_pad_set_target (GST_GHOST_PAD (self->vidsrc), vidsrc); + + gst_pad_set_active (self->vfsrc, TRUE); + gst_pad_set_active (self->imgsrc, TRUE); /* XXX ??? */ + gst_pad_set_active (self->vidsrc, TRUE); /* XXX ??? */ + + return TRUE; +} + +static gboolean +setup_pipeline (GstBaseCameraSrc * self) +{ + GstBaseCameraSrcClass *bclass = GST_BASE_CAMERA_SRC_GET_CLASS (self); + if (bclass->setup_pipeline) + return bclass->setup_pipeline (self); + return TRUE; +} + +static GstStateChangeReturn +gst_base_camera_src_change_state (GstElement * element, + GstStateChange transition) +{ + GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; + GstBaseCameraSrc *self = GST_BASE_CAMERA_SRC (element); + + GST_DEBUG_OBJECT (self, "%d -> %d", + GST_STATE_TRANSITION_CURRENT (transition), + GST_STATE_TRANSITION_NEXT (transition)); + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + if (!construct_pipeline (self)) + return GST_STATE_CHANGE_FAILURE; + break; + case GST_STATE_CHANGE_READY_TO_PAUSED: + if (!setup_pipeline (self)) + return GST_STATE_CHANGE_FAILURE; + break; + default: + break; + } + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + + return ret; +} + +static void +gst_base_camera_src_base_init (gpointer g_class) +{ + GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class); + + GST_DEBUG_CATEGORY_INIT (base_camera_src_debug, "base_camera_src", 0, + "Base camera src"); + + gst_element_class_set_details_simple (gstelement_class, + "Base class for camerabin src bin", "Source/Video", + "Abstracts capture device for camerabin", "Rob Clark "); + + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&vfsrc_template)); + + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&imgsrc_template)); + + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&vidsrc_template)); +} + +static void +gst_base_camera_src_class_init (GstBaseCameraSrcClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + + gobject_class = G_OBJECT_CLASS (klass); + gstelement_class = GST_ELEMENT_CLASS (klass); + + gobject_class->dispose = gst_base_camera_src_dispose; + gobject_class->finalize = (GObjectFinalizeFunc) gst_base_camera_src_finalize; + gobject_class->set_property = gst_base_camera_src_set_property; + gobject_class->get_property = gst_base_camera_src_get_property; + + // g_object_class_install_property .... + + gstelement_class->change_state = gst_base_camera_src_change_state; + +} + +static void +gst_base_camera_src_init (GstBaseCameraSrc * self, + GstBaseCameraSrcClass * klass) +{ + self->vfsrc = gst_ghost_pad_new_no_target ("vfsrc", GST_PAD_SRC); + gst_element_add_pad (GST_ELEMENT (self), self->vfsrc); + + self->imgsrc = gst_ghost_pad_new_no_target ("imgsrc", GST_PAD_SRC); + gst_element_add_pad (GST_ELEMENT (self), self->imgsrc); + + self->vidsrc = gst_ghost_pad_new_no_target ("vidsrc", GST_PAD_SRC); + gst_element_add_pad (GST_ELEMENT (self), self->vidsrc); + + self->width = DEFAULT_WIDTH; + self->height = DEFAULT_HEIGHT; + self->zoom = DEFAULT_ZOOM; + self->image_capture_width = 0; + self->image_capture_height = 0; + + self->night_mode = FALSE; + + self->fps_n = DEFAULT_FPS_N; + self->fps_d = DEFAULT_FPS_D; +} diff --git a/gst/camerabin2/gstbasecamerasrc.h b/gst/camerabin2/gstbasecamerasrc.h new file mode 100644 index 0000000000..75ef0222ac --- /dev/null +++ b/gst/camerabin2/gstbasecamerasrc.h @@ -0,0 +1,146 @@ +/* + * GStreamer + * Copyright (C) 2010 Texas Instruments, Inc + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_BASE_CAMERA_SRC_H__ +#define __GST_BASE_CAMERA_SRC_H__ + +#include +#include +#include +#include +#include "gstcamerabin-enum.h" + +G_BEGIN_DECLS +#define GST_TYPE_BASE_CAMERA_SRC \ + (gst_base_camera_src_get_type()) +#define GST_BASE_CAMERA_SRC(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_BASE_CAMERA_SRC,GstBaseCameraSrc)) +#define GST_BASE_CAMERA_SRC_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_BASE_CAMERA_SRC, GstBaseCameraSrcClass)) +#define GST_BASE_CAMERA_SRC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_BASE_CAMERA_SRC,GstBaseCameraSrcClass)) +#define GST_IS_BASE_CAMERA_SRC(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_BASE_CAMERA_SRC)) +#define GST_IS_BASE_CAMERA_SRC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_BASE_CAMERA_SRC)) + GType gst_base_camera_src_get_type (void); + +typedef struct _GstBaseCameraSrc GstBaseCameraSrc; +typedef struct _GstBaseCameraSrcClass GstBaseCameraSrcClass; + + +/** + * GstBaseCameraSrc: + */ +struct _GstBaseCameraSrc +{ + GstBin parent; + + GstPad *vfsrc; + GstPad *imgsrc; + GstPad *vidsrc; + + /* XXX preview pads? */ + + /* Resolution of the buffers configured to camerabin */ + gint width; + gint height; + + /* The digital zoom (from 100% to 1000%) */ + gint zoom; + + /* Image capture resolution */ + gint image_capture_width; + gint image_capture_height; + + /* Frames per second configured to camerabin */ + gint fps_n; + gint fps_d; + + /* Night mode handling */ + gboolean night_mode; + gint pre_night_fps_n; + gint pre_night_fps_d; + + gpointer _gst_reserved[GST_PADDING_LARGE]; +}; + + +/** + * GstBaseCameraSrcClass: + * @construct_pipeline: construct pipeline must be implemented by derived + * class, and return by reference vfsrc, imgsrc, and vidsrc pads of the + * contained pipeline, which will be ghosted to the src pads of the + * camerasrc bin (and optionally the preview src pads?) + * @setup_pipeline: + * @set_zoom: set the zoom + * @set_mode: set the mode + */ +struct _GstBaseCameraSrcClass +{ + GstBinClass parent; + + /* construct pipeline must be implemented by derived class, and return by + * reference vfsrc, imgsrc, and vidsrc pads of the contained pipeline, which + * will be ghosted to the src pads of the camerasrc bin (and optionally the + * preview src pads?) */ + gboolean (*construct_pipeline) (GstBaseCameraSrc *self, + GstPad **vfsrc, GstPad **imgsrc, + GstPad **vidsrc); + + /* optional */ + gboolean (*setup_pipeline) (GstBaseCameraSrc *self); + + /* set the zoom */ + void (*set_zoom) (GstBaseCameraSrc *self, gint zoom); + + /* set the mode */ + gboolean (*set_mode) (GstBaseCameraSrc *self, + GstCameraBinMode mode); + + /* */ + GstCaps * (*get_allowed_input_caps) (GstBaseCameraSrc * self); + + /* optional */ + void (*finish_image_capture) (GstBaseCameraSrc * self); + + + gpointer _gst_reserved[GST_PADDING_LARGE]; +}; + + +#define MIN_ZOOM 100 +#define MAX_ZOOM 1000 +#define ZOOM_1X MIN_ZOOM + +GstPhotography * gst_base_camera_src_get_photography (GstBaseCameraSrc *self); +GstColorBalance * gst_base_camera_src_get_color_balance (GstBaseCameraSrc *self); + +gboolean gst_base_camera_src_set_mode (GstBaseCameraSrc *self, GstCameraBinMode mode); +void gst_base_camera_src_setup_zoom (GstBaseCameraSrc * self); +GstCaps * gst_base_camera_src_get_allowed_input_caps (GstBaseCameraSrc * self); +void gst_base_camera_src_finish_image_capture (GstBaseCameraSrc * self); +const GValue * gst_base_camera_src_find_better_framerate ( + GstBaseCameraSrc * self, GstStructure * st, const GValue * orig_framerate); + +// XXX add methods to get/set img capture and vid capture caps.. + +#endif /* __GST_BASE_CAMERA_SRC_H__ */ diff --git a/gst/camerabin2/gstcamerabin-enum.c b/gst/camerabin2/gstcamerabin-enum.c new file mode 100644 index 0000000000..8d1d0c92d3 --- /dev/null +++ b/gst/camerabin2/gstcamerabin-enum.c @@ -0,0 +1,78 @@ +/* + * GStreamer + * Copyright (C) 2009 Nokia Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include "gstcamerabin-enum.h" + +#define C_FLAGS(v) ((guint) v) + +static void +register_gst_camerabin_flags (GType * id) +{ + static const GFlagsValue values[] = { + {C_FLAGS (GST_CAMERABIN_FLAG_SOURCE_RESIZE), + "Enable source crop and scale", "source-resize"}, + {C_FLAGS (GST_CAMERABIN_FLAG_SOURCE_COLOR_CONVERSION), + "Enable colorspace conversion for video source", + "source-colorspace-conversion"}, + {C_FLAGS (GST_CAMERABIN_FLAG_VIEWFINDER_COLOR_CONVERSION), + "Enable colorspace conversion for viewfinder", + "viewfinder-colorspace-conversion"}, + {C_FLAGS (GST_CAMERABIN_FLAG_VIEWFINDER_SCALE), + "Enable scale for viewfinder", "viewfinder-scale"}, + {C_FLAGS (GST_CAMERABIN_FLAG_AUDIO_CONVERSION), + "Enable audio conversion for video capture", "audio-conversion"}, + {C_FLAGS (GST_CAMERABIN_FLAG_DISABLE_AUDIO), + "Disable audio elements for video capture", "disable-audio"}, + {C_FLAGS (GST_CAMERABIN_FLAG_IMAGE_COLOR_CONVERSION), + "Enable colorspace conversion for still image", + "image-colorspace-conversion"}, + {0, NULL, NULL} + }; + *id = g_flags_register_static ("GstCameraBinFlags", values); +} + +GType +gst_camerabin_flags_get_type (void) +{ + static GType id; + static GOnce once = G_ONCE_INIT; + + g_once (&once, (GThreadFunc) register_gst_camerabin_flags, &id); + return id; +} + + +GType +gst_camerabin_mode_get_type (void) +{ + static GType gtype = 0; + + if (gtype == 0) { + static const GEnumValue values[] = { + {MODE_PREVIEW, "Preview mode (should be default?)", "mode-preview"}, + {MODE_IMAGE, "Still image capture (default)", "mode-image"}, + {MODE_VIDEO, "Video recording", "mode-video"}, + {0, NULL, NULL} + }; + + gtype = g_enum_register_static ("GstCameraBinMode", values); + } + return gtype; +} diff --git a/gst/camerabin2/gstcamerabin-enum.h b/gst/camerabin2/gstcamerabin-enum.h new file mode 100644 index 0000000000..cd1707dd2e --- /dev/null +++ b/gst/camerabin2/gstcamerabin-enum.h @@ -0,0 +1,140 @@ +/* + * GStreamer + * Copyright (C) 2009 Nokia Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_CAMERABIN_ENUM_H__ +#define __GST_CAMERABIN_ENUM_H__ + +#include + +G_BEGIN_DECLS + +/* XXX find better place for property related enum/defaults */ +enum +{ + ARG_0, + ARG_FILENAME, + ARG_MODE, + ARG_FLAGS, + ARG_MUTE, + ARG_ZOOM, + ARG_IMAGE_POST, + ARG_IMAGE_ENC, + ARG_VIDEO_POST, + ARG_VIDEO_ENC, + ARG_AUDIO_ENC, + ARG_VIDEO_MUX, + ARG_VF_SINK, + ARG_VIDEO_SRC, + ARG_AUDIO_SRC, + ARG_INPUT_CAPS, + ARG_FILTER_CAPS, + ARG_PREVIEW_CAPS, + ARG_WB_MODE, + ARG_COLOUR_TONE, + ARG_SCENE_MODE, + ARG_FLASH_MODE, + ARG_FOCUS_STATUS, + ARG_CAPABILITIES, + ARG_SHAKE_RISK, + ARG_EV_COMP, + ARG_ISO_SPEED, + ARG_APERTURE, + ARG_EXPOSURE, + ARG_VIDEO_SOURCE_FILTER, + ARG_IMAGE_CAPTURE_SUPPORTED_CAPS, + ARG_VIEWFINDER_FILTER, + ARG_FLICKER_MODE, + ARG_FOCUS_MODE, + ARG_BLOCK_VIEWFINDER, + ARG_IMAGE_CAPTURE_WIDTH, + ARG_IMAGE_CAPTURE_HEIGHT, + ARG_VIDEO_CAPTURE_WIDTH, + ARG_VIDEO_CAPTURE_HEIGHT, + ARG_VIDEO_CAPTURE_FRAMERATE +}; + +#define DEFAULT_WIDTH 640 +#define DEFAULT_HEIGHT 480 +#define DEFAULT_CAPTURE_WIDTH 800 +#define DEFAULT_CAPTURE_HEIGHT 600 +#define DEFAULT_FPS_N 0 /* makes it use the default */ +#define DEFAULT_FPS_D 1 +#define DEFAULT_ZOOM MIN_ZOOM + + +/** + * GstCameraBinFlags: + * @GST_CAMERABIN_FLAG_SOURCE_RESIZE: enable video crop and scale + * after capture + * @GST_CAMERABIN_FLAG_SOURCE_COLOR_CONVERSION: enable conversion + * of native video format by enabling ffmpegcolorspace + * @GST_CAMERABIN_FLAG_VIEWFINDER_COLOR_CONVERSION: enable color + * conversion for viewfinder element + * @GST_CAMERABIN_FLAG_VIEWFINDER_SCALE: enable scaling in + * viewfinder element retaining aspect ratio + * @GST_CAMERABIN_FLAG_AUDIO_CONVERSION: enable audioconvert and + * audioresample elements + * @GST_CAMERABIN_FLAG_DISABLE_AUDIO: disable audio elements + * @GST_CAMERABIN_FLAG_IMAGE_COLOR_CONVERSION: enable color + * conversion for image output element + * + * Extra flags to configure the behaviour of the sinks. + */ +typedef enum { + GST_CAMERABIN_FLAG_SOURCE_RESIZE = (1 << 0), + GST_CAMERABIN_FLAG_SOURCE_COLOR_CONVERSION = (1 << 1), + GST_CAMERABIN_FLAG_VIEWFINDER_COLOR_CONVERSION = (1 << 2), + GST_CAMERABIN_FLAG_VIEWFINDER_SCALE = (1 << 3), + GST_CAMERABIN_FLAG_AUDIO_CONVERSION = (1 << 4), + GST_CAMERABIN_FLAG_DISABLE_AUDIO = (1 << 5), + GST_CAMERABIN_FLAG_IMAGE_COLOR_CONVERSION = (1 << 6) +} GstCameraBinFlags; + +#define GST_TYPE_CAMERABIN_FLAGS (gst_camerabin_flags_get_type()) +GType gst_camerabin_flags_get_type (void); + + +/** + * GstCameraBinMode: + * @MODE_PREVIEW: preview only (no capture) mode + * @MODE_IMAGE: image capture + * @MODE_VIDEO: video capture + * + * Capture mode to use. + */ +typedef enum +{ + /* note: changed to align with 'capture-mode' property (even though + * I have no idea where this property comes from..) But it somehow + * seems more logical for preview to be mode==0 even if it is an ABI + * break.. + */ + MODE_PREVIEW = 0, + MODE_IMAGE = 1, + MODE_VIDEO = 2, +} GstCameraBinMode; + + +#define GST_TYPE_CAMERABIN_MODE (gst_camerabin_mode_get_type ()) +GType gst_camerabin_mode_get_type (void); + +G_END_DECLS + +#endif /* #ifndef __GST_CAMERABIN_ENUM_H__ */ diff --git a/gst/camerabin2/gstplugin.c b/gst/camerabin2/gstplugin.c index 1f1dd0ea7a..c88ad8d038 100644 --- a/gst/camerabin2/gstplugin.c +++ b/gst/camerabin2/gstplugin.c @@ -25,6 +25,7 @@ #include "gstviewfinderbin.h" #include "gstimagecapturebin.h" +#include "gstv4l2camerasrc.h" static gboolean plugin_init (GstPlugin * plugin) @@ -33,6 +34,8 @@ plugin_init (GstPlugin * plugin) return FALSE; if (!gst_image_capture_bin_plugin_init (plugin)) return FALSE; + if (!gst_v4l2_camera_src_plugin_init (plugin)) + return FALSE; return TRUE; } diff --git a/gst/camerabin2/gstv4l2camerasrc.c b/gst/camerabin2/gstv4l2camerasrc.c new file mode 100644 index 0000000000..1cc4ca81d3 --- /dev/null +++ b/gst/camerabin2/gstv4l2camerasrc.c @@ -0,0 +1,1077 @@ +/* + * GStreamer + * Copyright (C) 2010 Texas Instruments, Inc + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +/** + * SECTION:element-v4l2camerasrc + * + * A camera src element for camerabin.. currently uses v4l2 directly. + * It could be worthwhile to make this subclassable, so that other + * camera elements with a single src pad could re-use this.. + */ + +#ifdef HAVE_CONFIG_H +# include +#endif + +#include "gstv4l2camerasrc.h" +#include "camerabingeneral.h" +#include "gstcamerabin-enum.h" + + +#define CAMERABIN_DEFAULT_VF_CAPS "video/x-raw-yuv,format=(fourcc)I420" +//#define CAMERABIN_MAX_VF_WIDTH 848 +//#define CAMERABIN_MAX_VF_HEIGHT 848 + +/* Using "bilinear" as default zoom method */ +#define CAMERABIN_DEFAULT_ZOOM_METHOD 1 + +/* FIXME: this is v4l2camsrc specific */ +#define DEFAULT_V4L2CAMSRC_DRIVER_NAME "omap3cam" + +//GST_DEBUG_CATEGORY (v4l2_camera_src_debug); +//#define GST_CAT_DEFAULT v4l2_camera_src_debug + +GST_BOILERPLATE (GstV4l2CameraSrc, gst_v4l2_camera_src, GstBaseCameraSrc, + GST_TYPE_BASE_CAMERA_SRC); + +static void configure_format (GstV4l2CameraSrc * self, GstCaps * caps); +static void set_capsfilter_caps (GstV4l2CameraSrc * self, GstCaps * new_caps); + +static void +gst_v4l2_camera_src_dispose (GObject * object) +{ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +gst_v4l2_camera_src_finalize (GstV4l2CameraSrc * self) +{ + G_OBJECT_CLASS (parent_class)->finalize ((GObject *) (self)); +} + +static void +gst_v4l2_camera_src_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec) +{ + GstV4l2CameraSrc *self = GST_V4L2_CAMERA_SRC (object); + + switch (prop_id) { + case ARG_FILTER_CAPS: + GST_OBJECT_LOCK (self); + gst_caps_replace (&self->view_finder_caps, + (GstCaps *) gst_value_get_caps (value)); + GST_OBJECT_UNLOCK (self); + configure_format (self, self->view_finder_caps); + break; + case ARG_VIDEO_SOURCE_FILTER: + if (GST_STATE (self) != GST_STATE_NULL) { + GST_ELEMENT_ERROR (self, CORE, FAILED, + ("camerasrc must be in NULL state when setting the video filter element"), + (NULL)); + } else { + if (self->app_video_filter) + gst_object_unref (self->app_video_filter); + self->app_video_filter = g_value_dup_object (value); + } + break; + case ARG_VIDEO_SRC: + if (GST_STATE (self) != GST_STATE_NULL) { + GST_ELEMENT_ERROR (self, CORE, FAILED, + ("camerasrc must be in NULL state when setting the video source element"), + (NULL)); + } else { + if (self->app_vid_src) + gst_object_unref (self->app_vid_src); + self->app_vid_src = g_value_get_object (value); + gst_object_ref (self->app_vid_src); + } + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec); + break; + } +} + +static void +gst_v4l2_camera_src_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec) +{ + GstV4l2CameraSrc *self = GST_V4L2_CAMERA_SRC (object); + + switch (prop_id) { + case ARG_FILTER_CAPS: + gst_value_set_caps (value, self->view_finder_caps); + break; + case ARG_VIDEO_SOURCE_FILTER: + g_value_set_object (value, self->app_video_filter); + break; + case ARG_VIDEO_SRC: + if (self->src_vid_src) + g_value_set_object (value, self->src_vid_src); + else + g_value_set_object (value, self->app_vid_src); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec); + break; + } +} + +/** + * gst_v4l2_camera_src_imgsrc_probe: + * + * Buffer probe called before sending each buffer to image queue. + */ +static gboolean +gst_v4l2_camera_src_imgsrc_probe (GstPad * pad, GstBuffer * buffer, + gpointer data) +{ + GstV4l2CameraSrc *self = GST_V4L2_CAMERA_SRC (data); + GST_DEBUG_OBJECT (self, "pass buffer: %d", self->mode == MODE_IMAGE); + return self->mode == MODE_IMAGE; +} + +/** + * gst_v4l2_camera_src_vidsrc_probe: + * + * Buffer probe called before sending each buffer to image queue. + */ +static gboolean +gst_v4l2_camera_src_vidsrc_probe (GstPad * pad, GstBuffer * buffer, + gpointer data) +{ + GstV4l2CameraSrc *self = GST_V4L2_CAMERA_SRC (data); + GST_DEBUG_OBJECT (self, "pass buffer: %d", self->mode == MODE_VIDEO); + return self->mode == MODE_VIDEO; +} + +/** + * gst_v4l2_camera_src_construct_pipeline: + * @bcamsrc: camerasrc object + * @vfsrc: viewfinder src element (returned by reference) + * @imgsrc: image src element (returned by reference) + * @vidsrc: video src element (returned by reference) + * + * This function creates and links the elements of the camerasrc bin + * videosrc ! cspconv ! capsfilter ! crop ! scale ! capsfilter ! tee ! .. + * + * Returns: TRUE, if elements were successfully created, FALSE otherwise + */ +static gboolean +gst_v4l2_camera_src_construct_pipeline (GstBaseCameraSrc * bcamsrc, + GstPad ** vfsrc, GstPad ** imgsrc, GstPad ** vidsrc) +{ + GstV4l2CameraSrc *self = GST_V4L2_CAMERA_SRC (bcamsrc); + GstBin *cbin = GST_BIN (bcamsrc); + GstElement *tee; + gboolean ret = FALSE; + + GST_DEBUG_OBJECT (self, "constructing pipeline"); + + /* Add application set or default video src element */ + if (!(self->src_vid_src = gst_camerabin_setup_default_element (cbin, + self->app_vid_src, "autovideosrc", DEFAULT_VIDEOSRC))) { + self->src_vid_src = NULL; + goto done; + } else { + if (!gst_camerabin_add_element (cbin, self->src_vid_src)) { + goto done; + } + } + +#if 0 + /* XXX srcbin needs to know of some flags, perhaps?? */ + if (camera->flags & GST_CAMERABIN_FLAG_SOURCE_COLOR_CONVERSION) { +#else + if (1) { +#endif + if (!gst_camerabin_create_and_add_element (cbin, "ffmpegcolorspace")) + goto done; + } + + if (!(self->src_filter = + gst_camerabin_create_and_add_element (cbin, "capsfilter"))) + goto done; + +#if 0 + /* XXX srcbin needs to know of some flags, perhaps?? */ + if (camera->flags & GST_CAMERABIN_FLAG_SOURCE_RESIZE) { +#else + if (1) { +#endif + if (!(self->src_zoom_crop = + gst_camerabin_create_and_add_element (cbin, "videocrop"))) + goto done; + if (!(self->src_zoom_scale = + gst_camerabin_create_and_add_element (cbin, "videoscale"))) + goto done; + if (!(self->src_zoom_filter = + gst_camerabin_create_and_add_element (cbin, "capsfilter"))) + goto done; + } + + if (self->app_video_filter) { + if (!gst_camerabin_add_element (cbin, self->app_video_filter)) { + goto done; + } + } + + if (!(tee = gst_camerabin_create_and_add_element (cbin, "tee"))) + goto done; + + self->tee_vf_srcpad = gst_element_get_request_pad (tee, "src%d"); + self->tee_image_srcpad = gst_element_get_request_pad (tee, "src%d"); + self->tee_video_srcpad = gst_element_get_request_pad (tee, "src%d"); + + gst_pad_add_buffer_probe (self->tee_image_srcpad, + G_CALLBACK (gst_v4l2_camera_src_imgsrc_probe), self); + gst_pad_add_buffer_probe (self->tee_video_srcpad, + G_CALLBACK (gst_v4l2_camera_src_vidsrc_probe), self); + + *vfsrc = self->tee_vf_srcpad; + *imgsrc = self->tee_image_srcpad; + *vidsrc = self->tee_video_srcpad; + +#if 0 + /* XXX another idea... put common parts in GstBaseCameraSrc.. perhaps + * derived class could use some flags, or something like this, to + * indicate which pads in needs vscale and queue on.. (but I think it + * doesn't hurt ot have on all..) + */ + /* XXX perhaps we should keep queues and vscale's in camerabin itself, + * because GstOmxCameraSrc would also probably need the queues.. and + * maybe some OMX camera implementations would want the vscale's (and + * at least the vscale's should become pass-through if OMX camera can + * negotiate the requested sizes.. + */ + queue = gst_element_factory_make ("queue", "viewfinder-queue"); + if (!gst_camerabin_add_element (cbin, queue)) { + goto error; + } + /* Set queue leaky, we don't want to block video encoder feed, but + * prefer leaking view finder buffers instead. */ + g_object_set (G_OBJECT (queue), "leaky", 2, "max-size-buffers", 1, NULL); +#endif + + /* Set default "driver-name" for v4l2camsrc if not set */ + /* FIXME: v4l2camsrc specific */ + { + gchar *driver_name = NULL; + if (g_object_class_find_property (G_OBJECT_GET_CLASS (self->src_vid_src), + "driver-name")) { + g_object_get (G_OBJECT (self->src_vid_src), "driver-name", + &driver_name, NULL); + if (!driver_name) { + g_object_set (G_OBJECT (self->src_vid_src), "driver-name", + DEFAULT_V4L2CAMSRC_DRIVER_NAME, NULL); + } + } + } + + ret = TRUE; +done: + return ret; +} + +/** + * get_srcpad_current_format: + * @element: element to get the format from + * + * Helper function to get the negotiated fourcc + * format from @element src pad. + * + * Returns: negotiated format (fourcc), 0 if not found + */ +static guint32 +get_srcpad_current_format (GstElement * element) +{ + GstPad *srcpad = NULL; + GstCaps *srccaps = NULL; + GstStructure *structure; + guint32 format = 0; + + g_return_val_if_fail (element != NULL, 0); + + if ((srcpad = gst_element_get_static_pad (element, "src")) == NULL) { + goto no_pad; + } + + if ((srccaps = gst_pad_get_negotiated_caps (srcpad)) == NULL) { + goto no_caps; + } + + GST_LOG ("negotiated caps %" GST_PTR_FORMAT, srccaps); + + structure = gst_caps_get_structure (srccaps, 0); + if (gst_structure_has_field (structure, "format")) { + gst_structure_get_fourcc (structure, "format", &format); + } + + gst_caps_unref (srccaps); +no_caps: + gst_object_unref (srcpad); +no_pad: + GST_DEBUG ("current format for %" GST_PTR_FORMAT ": %" GST_FOURCC_FORMAT, + element, GST_FOURCC_ARGS (format)); + return format; +} + +/** + * set_allowed_framerate: + * @self: camerasrc object + * @filter_caps: update allowed framerate to these caps + * + * Find allowed frame rate from video source that matches with + * resolution in @filter_caps. Set found frame rate to @filter_caps. + */ +static void +set_allowed_framerate (GstV4l2CameraSrc * self, GstCaps * filter_caps) +{ + GstBaseCameraSrc *bcamsrc = GST_BASE_CAMERA_SRC (self); + GstStructure *structure; + GstCaps *allowed_caps = NULL, *intersect = NULL, *tmp_caps = NULL; + const GValue *framerate = NULL; + guint caps_size, i; + guint32 format = 0; + + GST_INFO_OBJECT (self, "filter caps:%" GST_PTR_FORMAT, filter_caps); + + structure = gst_structure_copy (gst_caps_get_structure (filter_caps, 0)); + + /* Set fourcc format according to current videosrc format */ + format = get_srcpad_current_format (self->src_vid_src); + if (format) { + GST_DEBUG_OBJECT (self, + "using format %" GST_FOURCC_FORMAT " for matching", + GST_FOURCC_ARGS (format)); + gst_structure_set (structure, "format", GST_TYPE_FOURCC, format, NULL); + } else { + GST_DEBUG_OBJECT (self, "not matching against fourcc format"); + gst_structure_remove_field (structure, "format"); + } + + tmp_caps = gst_caps_new_full (structure, NULL); + + /* Get supported caps from video src that matches with new filter caps */ + allowed_caps = gst_base_camera_src_get_allowed_input_caps (bcamsrc); + intersect = gst_caps_intersect (allowed_caps, tmp_caps); + GST_INFO_OBJECT (self, "intersect caps:%" GST_PTR_FORMAT, intersect); + + /* Find the best framerate from the caps */ + caps_size = gst_caps_get_size (intersect); + for (i = 0; i < caps_size; i++) { + structure = gst_caps_get_structure (intersect, i); + framerate = gst_base_camera_src_find_better_framerate (bcamsrc, + structure, framerate); + } + + /* Set found frame rate to original caps */ + if (GST_VALUE_HOLDS_FRACTION (framerate)) { + gst_caps_set_simple (filter_caps, + "framerate", GST_TYPE_FRACTION, + gst_value_get_fraction_numerator (framerate), + gst_value_get_fraction_denominator (framerate), NULL); + } + + /* Unref helper caps */ + if (allowed_caps) { + gst_caps_unref (allowed_caps); + } + if (intersect) { + gst_caps_unref (intersect); + } + if (tmp_caps) { + gst_caps_unref (tmp_caps); + } +} + +/** + * gst_v4l2_camera_src_setup_pipeline: + * @bcamsrc: camerasrc object + * + * This function updates camerabin capsfilters according + * to fps, resolution and zoom that have been configured + * to camerabin. + */ +static gboolean +gst_v4l2_camera_src_setup_pipeline (GstBaseCameraSrc * bcamsrc) +{ + GstV4l2CameraSrc *self = GST_V4L2_CAMERA_SRC (bcamsrc); + GstStructure *st; + GstCaps *new_caps; + gboolean detect_framerate = FALSE; + + /* clear video update status */ +//XXX self->video_capture_caps_update = FALSE; + + if (!self->view_finder_caps) { + st = gst_structure_from_string (CAMERABIN_DEFAULT_VF_CAPS, NULL); + } else { + st = gst_structure_copy (gst_caps_get_structure (self->view_finder_caps, + 0)); + } + + if (bcamsrc->width > 0 && bcamsrc->height > 0) { + gst_structure_set (st, + "width", G_TYPE_INT, bcamsrc->width, + "height", G_TYPE_INT, bcamsrc->height, NULL); + } + + if (bcamsrc->fps_n > 0 && bcamsrc->fps_d > 0) { + if (bcamsrc->night_mode) { + GST_INFO_OBJECT (self, "night mode, lowest allowed fps will be forced"); + bcamsrc->pre_night_fps_n = bcamsrc->fps_n; + bcamsrc->pre_night_fps_d = bcamsrc->fps_d; + detect_framerate = TRUE; + } else { + gst_structure_set (st, + "framerate", GST_TYPE_FRACTION, bcamsrc->fps_n, bcamsrc->fps_d, NULL); + new_caps = gst_caps_new_full (st, NULL); + } + } else { + GST_DEBUG_OBJECT (self, "no framerate specified"); + detect_framerate = TRUE; + } + + if (detect_framerate) { + GST_DEBUG_OBJECT (self, "detecting allowed framerate"); + /* Remove old framerate if any */ + if (gst_structure_has_field (st, "framerate")) { + gst_structure_remove_field (st, "framerate"); + } + new_caps = gst_caps_new_full (st, NULL); + + /* Set allowed framerate for the resolution */ + set_allowed_framerate (self, new_caps); + } + + /* Set default zoom method */ + if (self->src_zoom_scale) { + g_object_set (self->src_zoom_scale, "method", + CAMERABIN_DEFAULT_ZOOM_METHOD, NULL); + } + + /* we create new caps in any way and they take ownership of the structure st */ + gst_caps_replace (&self->view_finder_caps, new_caps); + gst_caps_unref (new_caps); + + /* Set caps for view finder mode */ + /* This also sets zoom */ + set_capsfilter_caps (self, self->view_finder_caps); + + return TRUE; +} + +static gboolean +copy_missing_fields (GQuark field_id, const GValue * value, gpointer user_data) +{ + GstStructure *st = (GstStructure *) user_data; + const GValue *val = gst_structure_id_get_value (st, field_id); + + if (G_UNLIKELY (val == NULL)) { + gst_structure_id_set_value (st, field_id, value); + } + + return TRUE; +} + +/** + * adapt_image_capture: + * @self: camerasrc object + * @in_caps: caps object that describes incoming image format + * + * Adjust capsfilters and crop according image capture caps if necessary. + * The captured image format from video source might be different from + * what application requested, so we can try to fix that in camerabin. + * + */ +static void +adapt_image_capture (GstV4l2CameraSrc * self, GstCaps * in_caps) +{ + GstBaseCameraSrc *bcamsrc = GST_BASE_CAMERA_SRC (self); + GstStructure *in_st, *new_st, *req_st; + gint in_width = 0, in_height = 0, req_width = 0, req_height = 0, crop = 0; + gdouble ratio_w, ratio_h; + GstCaps *filter_caps = NULL; + + GST_LOG_OBJECT (self, "in caps: %" GST_PTR_FORMAT, in_caps); + GST_LOG_OBJECT (self, "requested caps: %" GST_PTR_FORMAT, + self->image_capture_caps); + + in_st = gst_caps_get_structure (in_caps, 0); + gst_structure_get_int (in_st, "width", &in_width); + gst_structure_get_int (in_st, "height", &in_height); + + req_st = gst_caps_get_structure (self->image_capture_caps, 0); + gst_structure_get_int (req_st, "width", &req_width); + gst_structure_get_int (req_st, "height", &req_height); + + GST_INFO_OBJECT (self, "we requested %dx%d, and got %dx%d", req_width, + req_height, in_width, in_height); + + new_st = gst_structure_copy (req_st); + /* If new fields have been added, we need to copy them */ + gst_structure_foreach (in_st, copy_missing_fields, new_st); + +#if 0 + /* XXX srcbin needs to know of some flags, perhaps?? */ + if (!(camera->flags & GST_CAMERABIN_FLAG_SOURCE_RESIZE)) { +#else + if (1) { +#endif + GST_DEBUG_OBJECT (self, + "source-resize flag disabled, unable to adapt resolution"); + gst_structure_set (new_st, "width", G_TYPE_INT, in_width, "height", + G_TYPE_INT, in_height, NULL); + } + + GST_LOG_OBJECT (self, "new image capture caps: %" GST_PTR_FORMAT, new_st); + + /* Crop if requested aspect ratio differs from incoming frame aspect ratio */ + if (self->src_zoom_crop) { + + ratio_w = (gdouble) in_width / req_width; + ratio_h = (gdouble) in_height / req_height; + + if (ratio_w < ratio_h) { + crop = in_height - (req_height * ratio_w); + self->base_crop_top = crop / 2; + self->base_crop_bottom = crop / 2; + } else { + crop = in_width - (req_width * ratio_h); + self->base_crop_left = crop / 2; + self->base_crop_right += crop / 2; + } + + GST_INFO_OBJECT (self, + "setting base crop: left:%d, right:%d, top:%d, bottom:%d", + self->base_crop_left, self->base_crop_right, self->base_crop_top, + self->base_crop_bottom); + g_object_set (G_OBJECT (self->src_zoom_crop), + "top", self->base_crop_top, + "bottom", self->base_crop_bottom, + "left", self->base_crop_left, "right", self->base_crop_right, NULL); + } + + /* Update capsfilters */ + gst_caps_replace (&self->image_capture_caps, + gst_caps_new_full (new_st, NULL)); + set_capsfilter_caps (self, self->image_capture_caps); + + /* Adjust the capsfilter before crop and videoscale elements if necessary */ + if (in_width == bcamsrc->width && in_height == bcamsrc->height) { + GST_DEBUG_OBJECT (self, "no adaptation with resolution needed"); + } else { + GST_DEBUG_OBJECT (self, + "changing %" GST_PTR_FORMAT " from %dx%d to %dx%d", self->src_filter, + bcamsrc->width, bcamsrc->height, in_width, in_height); + /* Apply the width and height to filter caps */ + g_object_get (G_OBJECT (self->src_filter), "caps", &filter_caps, NULL); + filter_caps = gst_caps_make_writable (filter_caps); + gst_caps_set_simple (filter_caps, "width", G_TYPE_INT, in_width, "height", + G_TYPE_INT, in_height, NULL); + g_object_set (G_OBJECT (self->src_filter), "caps", filter_caps, NULL); + gst_caps_unref (filter_caps); + } +} + +/** + * img_capture_prepared: + * @data: camerasrc object + * @caps: caps describing the prepared image format + * + * Callback which is called after image capture has been prepared. + */ +static void +img_capture_prepared (gpointer data, GstCaps * caps) +{ + GstV4l2CameraSrc *self = GST_V4L2_CAMERA_SRC (data); + + GST_INFO_OBJECT (self, "image capture prepared"); + + /* It is possible we are about to get something else that we requested */ + if (!gst_caps_is_equal (self->image_capture_caps, caps)) { + adapt_image_capture (self, caps); + } else { + set_capsfilter_caps (self, self->image_capture_caps); + } + +//XXX g_object_set (G_OBJECT (camera->src_out_sel), "resend-latest", FALSE, +//XXX "active-pad", camera->pad_src_img, NULL); +} + +static void +set_image_capture_caps (GstV4l2CameraSrc * self, gint width, gint height) +{ + GstStructure *structure; + GstCaps *new_caps = NULL; + + if (width && height && self->view_finder_caps) { + /* Use view finder mode caps as a basis */ + structure = gst_caps_get_structure (self->view_finder_caps, 0); + + /* Set new resolution for image capture */ + new_caps = gst_caps_new_simple (gst_structure_get_name (structure), + "width", G_TYPE_INT, width, "height", G_TYPE_INT, height, NULL); + + /* Set allowed framerate for the resolution. */ + set_allowed_framerate (self, new_caps); + } + + GST_INFO_OBJECT (self, + "init filter caps for image capture %" GST_PTR_FORMAT, new_caps); + gst_caps_replace (&self->image_capture_caps, new_caps); + self->image_capture_caps_update = FALSE; +} + +/** + * + */ +static gboolean +start_image_capture (GstV4l2CameraSrc * self) +{ + GstBaseCameraSrc *bcamsrc = GST_BASE_CAMERA_SRC (self); + GstPhotography *photography = gst_base_camera_src_get_photography (bcamsrc); + gboolean wait_for_prepare = FALSE, ret = FALSE; + + if (photography) { + wait_for_prepare = TRUE; + + if (!self->image_capture_caps || self->image_capture_caps_update) { + if (bcamsrc->image_capture_width && bcamsrc->image_capture_height) { + /* Resolution is set, but it isn't in use yet */ + set_image_capture_caps (self, bcamsrc->image_capture_width, + bcamsrc->image_capture_height); + } else { + /* Capture resolution not set. Use viewfinder resolution */ + self->image_capture_caps = gst_caps_copy (self->view_finder_caps); + self->image_capture_caps_update = FALSE; + } + } + + /* Start preparations for image capture */ + GST_DEBUG_OBJECT (self, "prepare image capture caps %" GST_PTR_FORMAT, + self->image_capture_caps); + + ret = gst_photography_prepare_for_capture (photography, + (GstPhotoCapturePrepared) img_capture_prepared, + self->image_capture_caps, self); + + } else { +//XXX g_object_set (G_OBJECT (camera->src_out_sel), "resend-latest", TRUE, +//XXX "active-pad", camera->pad_src_img, NULL); + ret = TRUE; + } + + return ret; +} + +static gboolean +gst_v4l2_camera_src_set_mode (GstBaseCameraSrc * bcamsrc, GstCameraBinMode mode) +{ + GstV4l2CameraSrc *self = GST_V4L2_CAMERA_SRC (bcamsrc); + GstPhotography *photography = gst_base_camera_src_get_photography (bcamsrc); + + if (photography) { + if (g_object_class_find_property (G_OBJECT_GET_CLASS (photography), + "capture-mode")) { + g_object_set (G_OBJECT (photography), "capture-mode", mode, NULL); + } + } + + self->mode = mode; + + switch (mode) { + case MODE_PREVIEW: + return TRUE; // XXX + case MODE_IMAGE: + return start_image_capture (GST_V4L2_CAMERA_SRC (bcamsrc)); + case MODE_VIDEO: + return TRUE; // XXX + } + + g_assert_not_reached (); + + return FALSE; +} + +static gboolean +set_videosrc_zoom (GstV4l2CameraSrc * self, gint zoom) +{ + gboolean ret = FALSE; + + if (g_object_class_find_property (G_OBJECT_GET_CLASS (self->src_vid_src), + "zoom")) { + g_object_set (G_OBJECT (self->src_vid_src), "zoom", + (gfloat) zoom / 100, NULL); + ret = TRUE; + } + return ret; +} + +static gboolean +set_element_zoom (GstV4l2CameraSrc * self, gint zoom) +{ + gboolean ret = FALSE; + GstBaseCameraSrc *bcamsrc = GST_BASE_CAMERA_SRC (self); + gint w2_crop = 0, h2_crop = 0; + GstPad *pad_zoom_sink = NULL; + gint left = self->base_crop_left; + gint right = self->base_crop_right; + gint top = self->base_crop_top; + gint bottom = self->base_crop_bottom; + + if (self->src_zoom_crop) { + /* Update capsfilters to apply the zoom */ + GST_INFO_OBJECT (self, "zoom: %d, orig size: %dx%d", zoom, + bcamsrc->width, bcamsrc->height); + + if (zoom != ZOOM_1X) { + w2_crop = (bcamsrc->width - (bcamsrc->width * ZOOM_1X / zoom)) / 2; + h2_crop = (bcamsrc->height - (bcamsrc->height * ZOOM_1X / zoom)) / 2; + + left += w2_crop; + right += w2_crop; + top += h2_crop; + bottom += h2_crop; + + /* force number of pixels cropped from left to be even, to avoid slow code + * path on videoscale */ + left &= 0xFFFE; + } + + pad_zoom_sink = gst_element_get_static_pad (self->src_zoom_crop, "sink"); + + GST_INFO_OBJECT (self, + "sw cropping: left:%d, right:%d, top:%d, bottom:%d", left, right, top, + bottom); + + GST_PAD_STREAM_LOCK (pad_zoom_sink); + g_object_set (self->src_zoom_crop, "left", left, "right", right, "top", + top, "bottom", bottom, NULL); + GST_PAD_STREAM_UNLOCK (pad_zoom_sink); + gst_object_unref (pad_zoom_sink); + ret = TRUE; + } + return ret; +} + +static void +gst_v4l2_camera_src_set_zoom (GstBaseCameraSrc * bcamsrc, gint zoom) +{ + GstV4l2CameraSrc *self = GST_V4L2_CAMERA_SRC (bcamsrc); + + GST_INFO_OBJECT (self, "setting zoom %d", zoom); + + if (set_videosrc_zoom (self, zoom)) { + set_element_zoom (self, ZOOM_1X); + GST_INFO_OBJECT (self, "zoom set using videosrc"); + } else if (set_element_zoom (self, zoom)) { + GST_INFO_OBJECT (self, "zoom set using gst elements"); + } else { + GST_INFO_OBJECT (self, "setting zoom failed"); + } +} + +static GstCaps * +gst_v4l2_camera_src_get_allowed_input_caps (GstBaseCameraSrc * bcamsrc) +{ + GstV4l2CameraSrc *self = GST_V4L2_CAMERA_SRC (bcamsrc); + GstCaps *caps = NULL; + GstPad *pad = NULL, *peer_pad = NULL; + GstState state; + GstElement *videosrc; + + videosrc = self->src_vid_src ? self->src_vid_src : self->app_vid_src; + + if (!videosrc) { + GST_WARNING_OBJECT (self, "no videosrc, can't get allowed caps"); + goto failed; + } + + if (self->allowed_caps) { + GST_DEBUG_OBJECT (self, "returning cached caps"); + goto done; + } + + pad = gst_element_get_static_pad (videosrc, "src"); + + if (!pad) { + GST_WARNING_OBJECT (self, "no srcpad in videosrc"); + goto failed; + } + + state = GST_STATE (videosrc); + + /* Make this function work also in NULL state */ + if (state == GST_STATE_NULL) { + GST_DEBUG_OBJECT (self, "setting videosrc to ready temporarily"); + peer_pad = gst_pad_get_peer (pad); + if (peer_pad) { + gst_pad_unlink (pad, peer_pad); + } + /* Set videosrc to READY to open video device */ + gst_element_set_locked_state (videosrc, TRUE); + gst_element_set_state (videosrc, GST_STATE_READY); + } + + self->allowed_caps = gst_pad_get_caps (pad); + + /* Restore state and re-link if necessary */ + if (state == GST_STATE_NULL) { + GST_DEBUG_OBJECT (self, "restoring videosrc state %d", state); + /* Reset videosrc to NULL state, some drivers seem to need this */ + gst_element_set_state (videosrc, GST_STATE_NULL); + if (peer_pad) { + gst_pad_link (pad, peer_pad); + gst_object_unref (peer_pad); + } + gst_element_set_locked_state (videosrc, FALSE); + } + + gst_object_unref (pad); + +done: + if (self->allowed_caps) { + caps = gst_caps_copy (self->allowed_caps); + } + GST_DEBUG_OBJECT (self, "allowed caps:%" GST_PTR_FORMAT, caps); +failed: + return caps; +} + +/** + * configure_format: + * @self: camerasrc object + * @caps: caps describing new format + * + * Configure internal video format for camerabin. + */ +static void +configure_format (GstV4l2CameraSrc * self, GstCaps * caps) +{ + GstBaseCameraSrc *bcamsrc = GST_BASE_CAMERA_SRC (self); + GstStructure *st; + gint width, height; + + st = gst_caps_get_structure (caps, 0); + + gst_structure_get_int (st, "width", &width); + gst_structure_get_int (st, "height", &height); + + g_object_set (self, "width", width, "height", height, NULL); + + if (gst_structure_has_field_typed (st, "framerate", GST_TYPE_FRACTION)) { + gst_structure_get_fraction (st, "framerate", &bcamsrc->fps_n, + &bcamsrc->fps_d); + } +} + + +/** + * update_aspect_filter: + * @self: camerasrc object + * @new_caps: new caps of next buffers arriving to view finder sink element + * + * Updates aspect ratio capsfilter to maintain aspect ratio, if we need to + * scale frames for showing them in view finder. + */ +static void +update_aspect_filter (GstV4l2CameraSrc * self, GstCaps * new_caps) +{ + // XXX why not instead add a preserve-aspect-ratio property to videoscale? +#if 0 + if (camera->flags & GST_CAMERABIN_FLAG_VIEWFINDER_SCALE) { + GstCaps *sink_caps, *ar_caps; + GstStructure *st; + gint in_w = 0, in_h = 0, sink_w = 0, sink_h = 0, target_w = 0, target_h = 0; + gdouble ratio_w, ratio_h; + GstPad *sink_pad; + const GValue *range; + + sink_pad = gst_element_get_static_pad (camera->view_sink, "sink"); + + if (sink_pad) { + sink_caps = gst_pad_get_caps (sink_pad); + gst_object_unref (sink_pad); + if (sink_caps) { + if (!gst_caps_is_any (sink_caps)) { + GST_DEBUG_OBJECT (camera, "sink element caps %" GST_PTR_FORMAT, + sink_caps); + /* Get maximum resolution that view finder sink accepts */ + st = gst_caps_get_structure (sink_caps, 0); + if (gst_structure_has_field_typed (st, "width", GST_TYPE_INT_RANGE)) { + range = gst_structure_get_value (st, "width"); + sink_w = gst_value_get_int_range_max (range); + } + if (gst_structure_has_field_typed (st, "height", GST_TYPE_INT_RANGE)) { + range = gst_structure_get_value (st, "height"); + sink_h = gst_value_get_int_range_max (range); + } + GST_DEBUG_OBJECT (camera, "sink element accepts max %dx%d", sink_w, + sink_h); + + /* Get incoming frames' resolution */ + if (sink_h && sink_w) { + st = gst_caps_get_structure (new_caps, 0); + gst_structure_get_int (st, "width", &in_w); + gst_structure_get_int (st, "height", &in_h); + GST_DEBUG_OBJECT (camera, "new caps with %dx%d", in_w, in_h); + } + } + gst_caps_unref (sink_caps); + } + } + + /* If we get bigger frames than view finder sink accepts, then we scale. + If we scale we need to adjust aspect ratio capsfilter caps in order + to maintain aspect ratio while scaling. */ + if (in_w && in_h && (in_w > sink_w || in_h > sink_h)) { + ratio_w = (gdouble) sink_w / in_w; + ratio_h = (gdouble) sink_h / in_h; + + if (ratio_w < ratio_h) { + target_w = sink_w; + target_h = (gint) (ratio_w * in_h); + } else { + target_w = (gint) (ratio_h * in_w); + target_h = sink_h; + } + + GST_DEBUG_OBJECT (camera, "setting %dx%d filter to maintain aspect ratio", + target_w, target_h); + ar_caps = gst_caps_copy (new_caps); + gst_caps_set_simple (ar_caps, "width", G_TYPE_INT, target_w, "height", + G_TYPE_INT, target_h, NULL); + } else { + GST_DEBUG_OBJECT (camera, "no scaling"); + ar_caps = new_caps; + } + + GST_DEBUG_OBJECT (camera, "aspect ratio filter caps %" GST_PTR_FORMAT, + ar_caps); + g_object_set (G_OBJECT (camera->aspect_filter), "caps", ar_caps, NULL); + if (ar_caps != new_caps) + gst_caps_unref (ar_caps); + } +#endif +} + + +/** + * set_capsfilter_caps: + * @self: camerasrc object + * @new_caps: pointer to caps object to set + * + * Set given caps to camerabin capsfilters. + */ +static void +set_capsfilter_caps (GstV4l2CameraSrc * self, GstCaps * new_caps) +{ + GST_INFO_OBJECT (self, "new_caps:%" GST_PTR_FORMAT, new_caps); + + configure_format (self, new_caps); + + /* Update zoom */ + gst_base_camera_src_setup_zoom (GST_BASE_CAMERA_SRC (self)); + + /* Update capsfilters */ + g_object_set (G_OBJECT (self->src_filter), "caps", new_caps, NULL); + if (self->src_zoom_filter) + g_object_set (G_OBJECT (self->src_zoom_filter), "caps", new_caps, NULL); + update_aspect_filter (self, new_caps); + GST_INFO_OBJECT (self, "udpated"); +} + +static void +gst_v4l2_camera_src_finish_image_capture (GstBaseCameraSrc * bcamsrc) +{ + GstV4l2CameraSrc *self = GST_V4L2_CAMERA_SRC (bcamsrc); + + if (self->image_capture_caps) { + /* If we used specific caps for image capture we need to + restore the caps and zoom/crop for view finder mode */ + if (self->src_zoom_crop) { + GST_DEBUG_OBJECT (self, "resetting crop in camerabin"); + g_object_set (self->src_zoom_crop, "left", 0, "right", 0, + "top", 0, "bottom", 0, NULL); + } + self->base_crop_left = 0; + self->base_crop_right = 0; + self->base_crop_top = 0; + self->base_crop_bottom = 0; + set_capsfilter_caps (self, self->view_finder_caps); + } +} + +static void +gst_v4l2_camera_src_base_init (gpointer g_class) +{ + GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class); + +// GST_DEBUG_CATEGORY_INIT (v4l2_camera_src_debug, "v4l2_camera_src", 0, +// "V4l2 camera src"); + + gst_element_class_set_details_simple (gstelement_class, + "V4l2 camera src element for camerabin", "Source/Video", + "V4l2 camera src element for camerabin", "Rob Clark "); +} + +static void +gst_v4l2_camera_src_class_init (GstV4l2CameraSrcClass * klass) +{ + GObjectClass *gobject_class; + GstBaseCameraSrcClass *gstbasecamerasrc_class; + + gobject_class = G_OBJECT_CLASS (klass); + gstbasecamerasrc_class = GST_BASE_CAMERA_SRC_CLASS (klass); + + gobject_class->dispose = gst_v4l2_camera_src_dispose; + gobject_class->finalize = (GObjectFinalizeFunc) gst_v4l2_camera_src_finalize; + gobject_class->set_property = gst_v4l2_camera_src_set_property; + gobject_class->get_property = gst_v4l2_camera_src_get_property; + + // g_object_class_install_property .... + + gstbasecamerasrc_class->construct_pipeline = + gst_v4l2_camera_src_construct_pipeline; + gstbasecamerasrc_class->setup_pipeline = gst_v4l2_camera_src_setup_pipeline; + gstbasecamerasrc_class->set_zoom = gst_v4l2_camera_src_set_zoom; + gstbasecamerasrc_class->set_mode = gst_v4l2_camera_src_set_mode; + gstbasecamerasrc_class->get_allowed_input_caps = + gst_v4l2_camera_src_get_allowed_input_caps; + gstbasecamerasrc_class->finish_image_capture = + gst_v4l2_camera_src_finish_image_capture; +} + +static void +gst_v4l2_camera_src_init (GstV4l2CameraSrc * self, + GstV4l2CameraSrcClass * klass) +{ + self->mode = MODE_PREVIEW; +} + +gboolean +gst_v4l2_camera_src_plugin_init (GstPlugin * plugin) +{ + return gst_element_register (plugin, "v4l2camerasrc", GST_RANK_NONE, + gst_v4l2_camera_src_get_type ()); +} diff --git a/gst/camerabin2/gstv4l2camerasrc.h b/gst/camerabin2/gstv4l2camerasrc.h new file mode 100644 index 0000000000..dd3ea4ea49 --- /dev/null +++ b/gst/camerabin2/gstv4l2camerasrc.h @@ -0,0 +1,112 @@ +/* + * GStreamer + * Copyright (C) 2010 Texas Instruments, Inc + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef __GST_V4L2_CAMERA_SRC_H__ +#define __GST_V4L2_CAMERA_SRC_H__ + +#include +#include "gstbasecamerasrc.h" + +G_BEGIN_DECLS +#define GST_TYPE_V4L2_CAMERA_SRC \ + (gst_v4l2_camera_src_get_type()) +#define GST_V4L2_CAMERA_SRC(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_V4L2_CAMERA_SRC,GstV4l2CameraSrc)) +#define GST_V4L2_CAMERA_SRC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_V4L2_CAMERA_SRC,GstV4l2CameraSrcClass)) +#define GST_IS_V4L2_CAMERA_SRC(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_V4L2_CAMERA_SRC)) +#define GST_IS_V4L2_CAMERA_SRC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_V4L2_CAMERA_SRC)) + GType gst_v4l2_camera_src_get_type (void); + +typedef struct _GstV4l2CameraSrc GstV4l2CameraSrc; +typedef struct _GstV4l2CameraSrcClass GstV4l2CameraSrcClass; + + +/** + * GstV4l2CameraSrc: + * + */ +struct _GstV4l2CameraSrc +{ + GstBaseCameraSrc parent; + + GstCameraBinMode mode; + + /* source elements */ + GstElement *src_vid_src; + GstElement *src_filter; + GstElement *src_zoom_crop; + GstElement *src_zoom_scale; + GstElement *src_zoom_filter; + GstElement *src_out_sel; + + /* srcpads of tee */ + GstPad *tee_vf_srcpad; + GstPad *tee_image_srcpad; + GstPad *tee_video_srcpad; + + /* Application configurable elements */ + GstElement *app_vid_src; + GstElement *app_video_filter; + + /* Caps that videosrc supports */ + GstCaps *allowed_caps; + + /* Optional base crop for frames. Used to crop frames e.g. + due to wrong aspect ratio, before the crop related to zooming. */ + gint base_crop_top; + gint base_crop_bottom; + gint base_crop_left; + gint base_crop_right; + + /* Caps applied to capsfilters when in view finder mode */ + GstCaps *view_finder_caps; + + /* Caps applied to capsfilters when taking still image */ + GstCaps *image_capture_caps; + gboolean image_capture_caps_update; // XXX where does this get set.. + + /* if GstV4l2CameraSrc is moved into camerabin plugin, then this isn't + * needed: + */ + gpointer _gst_reserved[GST_PADDING_LARGE]; +}; + + +/** + * GstV4l2CameraSrcClass: + * + */ +struct _GstV4l2CameraSrcClass +{ + GstBaseCameraSrcClass parent; + + /* if GstV4l2CameraSrc is moved into camerabin plugin, then this isn't + * needed: + */ + gpointer _gst_reserved[GST_PADDING_LARGE]; +}; + +gboolean gst_v4l2_camera_src_plugin_init (GstPlugin * plugin); + +#endif /* __GST_V4L2_CAMERA_SRC_H__ */ From 0dce17a4e8e7d93f3246eab3d25b079d0eb25f6c Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Thu, 25 Nov 2010 14:57:13 -0300 Subject: [PATCH 043/448] camerabin2: Adds video recording bin Adds an bin that is responsible for encoding and saving video streams to files. For now it is simply a ffmpegcolorspace ! theoraenc ! oggmux ! filesink bin. Still uncapable of recording audio. --- gst/camerabin2/Makefile.am | 2 + gst/camerabin2/gstplugin.c | 3 + gst/camerabin2/gstvideorecordingbin.c | 184 ++++++++++++++++++++++++++ gst/camerabin2/gstvideorecordingbin.h | 55 ++++++++ 4 files changed, 244 insertions(+) create mode 100644 gst/camerabin2/gstvideorecordingbin.c create mode 100644 gst/camerabin2/gstvideorecordingbin.h diff --git a/gst/camerabin2/Makefile.am b/gst/camerabin2/Makefile.am index 25b1e61ed6..e1278f4bbe 100644 --- a/gst/camerabin2/Makefile.am +++ b/gst/camerabin2/Makefile.am @@ -2,6 +2,7 @@ plugin_LTLIBRARIES = libgstcamerabin2.la libgstcamerabin2_la_SOURCES = gstviewfinderbin.c \ gstimagecapturebin.c \ + gstvideorecordingbin.c \ camerabingeneral.c \ gstbasecamerasrc.c \ gstcamerabin-enum.c \ @@ -23,6 +24,7 @@ libgstcamerabin2_la_LIBTOOLFLAGS = --tag=disable-static noinst_HEADERS = gstviewfinderbin.h \ gstimagecapturebin.h \ + gstvideorecordingbin.h \ camerabingeneral.h \ gstbasecamerasrc.h \ gstv4l2camerasrc.h \ diff --git a/gst/camerabin2/gstplugin.c b/gst/camerabin2/gstplugin.c index c88ad8d038..872ad1e637 100644 --- a/gst/camerabin2/gstplugin.c +++ b/gst/camerabin2/gstplugin.c @@ -25,6 +25,7 @@ #include "gstviewfinderbin.h" #include "gstimagecapturebin.h" +#include "gstvideorecordingbin.h" #include "gstv4l2camerasrc.h" static gboolean @@ -34,6 +35,8 @@ plugin_init (GstPlugin * plugin) return FALSE; if (!gst_image_capture_bin_plugin_init (plugin)) return FALSE; + if (!gst_video_recording_bin_plugin_init (plugin)) + return FALSE; if (!gst_v4l2_camera_src_plugin_init (plugin)) return FALSE; diff --git a/gst/camerabin2/gstvideorecordingbin.c b/gst/camerabin2/gstvideorecordingbin.c new file mode 100644 index 0000000000..4e5a8782d5 --- /dev/null +++ b/gst/camerabin2/gstvideorecordingbin.c @@ -0,0 +1,184 @@ +/* GStreamer + * Copyright (C) 2010 Thiago Santos + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +/** + * SECTION:element-gstvideorecordingbin + * + * The gstvideorecordingbin element does FIXME stuff. + * + * + * Example launch line + * |[ + * gst-launch -v videotestsrc num-buffers=3 ! videorecordingbin + * ]| + * FIXME Describe what the pipeline does. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstvideorecordingbin.h" + +/* prototypes */ + + +enum +{ + PROP_0 +}; + +/* pad templates */ + +static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("video/x-raw-yuv; video/x-raw-rgb") + ); + +/* class initialization */ + +GST_BOILERPLATE (GstVideoRecordingBin, gst_video_recording_bin, GstBin, + GST_TYPE_BIN); + +/* Element class functions */ +static GstStateChangeReturn +gst_video_recording_bin_change_state (GstElement * element, + GstStateChange trans); + +static void +gst_video_recording_bin_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&sink_template)); + + gst_element_class_set_details_simple (element_class, "Video Recording Bin", + "Sink/Video", "Video Recording Bin used in camerabin2", + "Thiago Santos "); +} + +static void +gst_video_recording_bin_class_init (GstVideoRecordingBinClass * klass) +{ + GstElementClass *element_class; + + element_class = GST_ELEMENT_CLASS (klass); + + element_class->change_state = + GST_DEBUG_FUNCPTR (gst_video_recording_bin_change_state); +} + +static void +gst_video_recording_bin_init (GstVideoRecordingBin * video_recordingbin, + GstVideoRecordingBinClass * video_recordingbin_class) +{ + video_recordingbin->ghostpad = + gst_ghost_pad_new_no_target_from_template ("sink", + gst_static_pad_template_get (&sink_template)); + gst_element_add_pad (GST_ELEMENT_CAST (video_recordingbin), + video_recordingbin->ghostpad); +} + +static gboolean +gst_video_recording_bin_create_elements (GstVideoRecordingBin * vrbin) +{ + GstElement *csp; + GstElement *enc; + GstElement *mux; + GstElement *sink; + GstPad *pad = NULL; + + if (vrbin->elements_created) + return TRUE; + + /* create elements */ + csp = gst_element_factory_make ("ffmpegcolorspace", "vrbin-csp"); + if (!csp) + goto error; + + enc = gst_element_factory_make ("theoraenc", "vrbin-enc"); + if (!enc) + goto error; + + mux = gst_element_factory_make ("oggmux", "vrbin-mux"); + if (!mux) + goto error; + + sink = gst_element_factory_make ("filesink", "vrbin-sink"); + if (!sink) + goto error; + + g_object_set (sink, "location", "cap.ogg", NULL); + + /* add and link */ + gst_bin_add_many (GST_BIN_CAST (vrbin), csp, enc, mux, sink, NULL); + if (!gst_element_link_many (csp, enc, mux, sink, NULL)) + goto error; + + /* add ghostpad */ + pad = gst_element_get_static_pad (csp, "sink"); + if (!gst_ghost_pad_set_target (GST_GHOST_PAD (vrbin->ghostpad), pad)) + goto error; + + vrbin->elements_created = TRUE; + return TRUE; + +error: + if (pad) + gst_object_unref (pad); + return FALSE; +} + +static GstStateChangeReturn +gst_video_recording_bin_change_state (GstElement * element, + GstStateChange trans) +{ + GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; + GstVideoRecordingBin *vrbin = GST_VIDEO_RECORDING_BIN_CAST (element); + + switch (trans) { + case GST_STATE_CHANGE_NULL_TO_READY: + if (!gst_video_recording_bin_create_elements (vrbin)) { + return GST_STATE_CHANGE_FAILURE; + } + break; + default: + break; + } + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, trans); + + switch (trans) { + case GST_STATE_CHANGE_READY_TO_NULL: + break; + default: + break; + } + + return ret; +} + +gboolean +gst_video_recording_bin_plugin_init (GstPlugin * plugin) +{ + return gst_element_register (plugin, "videorecordingbin", GST_RANK_NONE, + gst_video_recording_bin_get_type ()); +} diff --git a/gst/camerabin2/gstvideorecordingbin.h b/gst/camerabin2/gstvideorecordingbin.h new file mode 100644 index 0000000000..88651fad56 --- /dev/null +++ b/gst/camerabin2/gstvideorecordingbin.h @@ -0,0 +1,55 @@ +/* GStreamer + * Copyright (C) 2010 Thiago Santos + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef _GST_VIDEO_RECORDING_BIN_H_ +#define _GST_VIDEO_RECORDING_BIN_H_ + +#include + +G_BEGIN_DECLS + +#define GST_TYPE_VIDEO_RECORDING_BIN (gst_video_recording_bin_get_type()) +#define GST_VIDEO_RECORDING_BIN(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VIDEO_RECORDING_BIN,GstVideoRecordingBin)) +#define GST_VIDEO_RECORDING_BIN_CAST(obj) ((GstVideoRecordingBin *) obj) +#define GST_VIDEO_RECORDING_BIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VIDEO_RECORDING_BIN,GstVideoRecordingBinClass)) +#define GST_IS_VIDEO_RECORDING_BIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VIDEO_RECORDING_BIN)) +#define GST_IS_VIDEO_RECORDING_BIN_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VIDEO_RECORDING_BIN)) + +typedef struct _GstVideoRecordingBin GstVideoRecordingBin; +typedef struct _GstVideoRecordingBinClass GstVideoRecordingBinClass; + +struct _GstVideoRecordingBin +{ + GstBin bin; + + GstPad *ghostpad; + + gboolean elements_created; +}; + +struct _GstVideoRecordingBinClass +{ + GstBinClass bin_class; +}; + +GType gst_video_recording_bin_get_type (void); +gboolean gst_video_recording_bin_plugin_init (GstPlugin * plugin); + +G_END_DECLS + +#endif From fcf80d0253488a610bbb7acdd1fbafc2f0907a65 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Thu, 25 Nov 2010 20:53:04 -0300 Subject: [PATCH 044/448] camerabin2: v4l2camerasrc: Remove unused variable Removed unused leftover variable --- gst/camerabin2/gstv4l2camerasrc.c | 5 ----- gst/camerabin2/gstv4l2camerasrc.h | 1 - 2 files changed, 6 deletions(-) diff --git a/gst/camerabin2/gstv4l2camerasrc.c b/gst/camerabin2/gstv4l2camerasrc.c index 1cc4ca81d3..6cd2eb1c35 100644 --- a/gst/camerabin2/gstv4l2camerasrc.c +++ b/gst/camerabin2/gstv4l2camerasrc.c @@ -613,9 +613,6 @@ img_capture_prepared (gpointer data, GstCaps * caps) } else { set_capsfilter_caps (self, self->image_capture_caps); } - -//XXX g_object_set (G_OBJECT (camera->src_out_sel), "resend-latest", FALSE, -//XXX "active-pad", camera->pad_src_img, NULL); } static void @@ -676,8 +673,6 @@ start_image_capture (GstV4l2CameraSrc * self) self->image_capture_caps, self); } else { -//XXX g_object_set (G_OBJECT (camera->src_out_sel), "resend-latest", TRUE, -//XXX "active-pad", camera->pad_src_img, NULL); ret = TRUE; } diff --git a/gst/camerabin2/gstv4l2camerasrc.h b/gst/camerabin2/gstv4l2camerasrc.h index dd3ea4ea49..f12dc8c00b 100644 --- a/gst/camerabin2/gstv4l2camerasrc.h +++ b/gst/camerabin2/gstv4l2camerasrc.h @@ -58,7 +58,6 @@ struct _GstV4l2CameraSrc GstElement *src_zoom_crop; GstElement *src_zoom_scale; GstElement *src_zoom_filter; - GstElement *src_out_sel; /* srcpads of tee */ GstPad *tee_vf_srcpad; From 3afa2c3a25c19e4938516e03468e397575802ef0 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Thu, 25 Nov 2010 20:55:36 -0300 Subject: [PATCH 045/448] camerabin2: v4l2camerasrc: Fix property warning Avoid setting a property that doesn't exist. --- gst/camerabin2/gstv4l2camerasrc.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/gst/camerabin2/gstv4l2camerasrc.c b/gst/camerabin2/gstv4l2camerasrc.c index 6cd2eb1c35..29ee132240 100644 --- a/gst/camerabin2/gstv4l2camerasrc.c +++ b/gst/camerabin2/gstv4l2camerasrc.c @@ -865,14 +865,11 @@ configure_format (GstV4l2CameraSrc * self, GstCaps * caps) { GstBaseCameraSrc *bcamsrc = GST_BASE_CAMERA_SRC (self); GstStructure *st; - gint width, height; st = gst_caps_get_structure (caps, 0); - gst_structure_get_int (st, "width", &width); - gst_structure_get_int (st, "height", &height); - - g_object_set (self, "width", width, "height", height, NULL); + gst_structure_get_int (st, "width", &bcamsrc->width); + gst_structure_get_int (st, "height", &bcamsrc->height); if (gst_structure_has_field_typed (st, "framerate", GST_TYPE_FRACTION)) { gst_structure_get_fraction (st, "framerate", &bcamsrc->fps_n, From 7f41c2594d58f913d11575f87dab8c3367d99404 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Thu, 25 Nov 2010 21:49:47 -0300 Subject: [PATCH 046/448] camerabin2: Removing uneeded properties Removing uneeded and unregistered properties. --- gst/camerabin2/gstbasecamerasrc.c | 64 ------------------------------- gst/camerabin2/gstv4l2camerasrc.c | 2 - 2 files changed, 66 deletions(-) diff --git a/gst/camerabin2/gstbasecamerasrc.c b/gst/camerabin2/gstbasecamerasrc.c index aba756e82b..57b5ab7c14 100644 --- a/gst/camerabin2/gstbasecamerasrc.c +++ b/gst/camerabin2/gstbasecamerasrc.c @@ -281,55 +281,6 @@ gst_base_camera_src_set_property (GObject * object, gst_base_camera_src_setup_zoom (self); break; } - case ARG_IMAGE_CAPTURE_WIDTH:{ - gint width = g_value_get_int (value); - - if (width != self->image_capture_width) { - self->image_capture_width = width; -//XXX self->image_capture_caps_update = TRUE; - } - break; - } - case ARG_IMAGE_CAPTURE_HEIGHT:{ - gint height = g_value_get_int (value); - - if (height != self->image_capture_height) { - self->image_capture_height = height; -//XXX self->image_capture_caps_update = TRUE; - } - break; - } - case ARG_VIDEO_CAPTURE_WIDTH:{ - gint width = g_value_get_int (value); - - if (width != self->width) { - self->width = width; -//XXX self->video_capture_caps_update = TRUE; - } - break; - } - case ARG_VIDEO_CAPTURE_HEIGHT:{ - gint height = g_value_get_int (value); - - if (height != self->height) { - self->height = height; -//XXX self->video_capture_caps_update = TRUE; - } - break; - } - case ARG_VIDEO_CAPTURE_FRAMERATE:{ - gint fps_n, fps_d; - - fps_n = gst_value_get_fraction_numerator (value); - fps_d = gst_value_get_fraction_denominator (value); - - if (fps_n != self->fps_n || fps_d != self->fps_d) { - self->fps_n = fps_n; - self->fps_d = fps_d; -//XXX self->video_capture_caps_update = TRUE; - } - break; - } default: G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec); break; @@ -346,21 +297,6 @@ gst_base_camera_src_get_property (GObject * object, case ARG_ZOOM: g_value_set_int (value, g_atomic_int_get (&self->zoom)); break; - case ARG_IMAGE_CAPTURE_WIDTH: - g_value_set_int (value, self->image_capture_width); - break; - case ARG_IMAGE_CAPTURE_HEIGHT: - g_value_set_int (value, self->image_capture_height); - break; - case ARG_VIDEO_CAPTURE_WIDTH: - g_value_set_int (value, self->width); - break; - case ARG_VIDEO_CAPTURE_HEIGHT: - g_value_set_int (value, self->height); - break; - case ARG_VIDEO_CAPTURE_FRAMERATE: - gst_value_set_fraction (value, self->fps_n, self->fps_d); - break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec); break; diff --git a/gst/camerabin2/gstv4l2camerasrc.c b/gst/camerabin2/gstv4l2camerasrc.c index 29ee132240..07a068e6ff 100644 --- a/gst/camerabin2/gstv4l2camerasrc.c +++ b/gst/camerabin2/gstv4l2camerasrc.c @@ -37,8 +37,6 @@ #define CAMERABIN_DEFAULT_VF_CAPS "video/x-raw-yuv,format=(fourcc)I420" -//#define CAMERABIN_MAX_VF_WIDTH 848 -//#define CAMERABIN_MAX_VF_HEIGHT 848 /* Using "bilinear" as default zoom method */ #define CAMERABIN_DEFAULT_ZOOM_METHOD 1 From 39093d2199afdac49917e4eb37ae15c986254bf1 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Thu, 25 Nov 2010 22:05:39 -0300 Subject: [PATCH 047/448] camerabin2: v4l2camerasrc: Remove platform specific code Remove platform specific code --- gst/camerabin2/gstv4l2camerasrc.c | 18 ------------------ 1 file changed, 18 deletions(-) diff --git a/gst/camerabin2/gstv4l2camerasrc.c b/gst/camerabin2/gstv4l2camerasrc.c index 07a068e6ff..8d3f7eb822 100644 --- a/gst/camerabin2/gstv4l2camerasrc.c +++ b/gst/camerabin2/gstv4l2camerasrc.c @@ -41,9 +41,6 @@ /* Using "bilinear" as default zoom method */ #define CAMERABIN_DEFAULT_ZOOM_METHOD 1 -/* FIXME: this is v4l2camsrc specific */ -#define DEFAULT_V4L2CAMSRC_DRIVER_NAME "omap3cam" - //GST_DEBUG_CATEGORY (v4l2_camera_src_debug); //#define GST_CAT_DEFAULT v4l2_camera_src_debug @@ -269,21 +266,6 @@ gst_v4l2_camera_src_construct_pipeline (GstBaseCameraSrc * bcamsrc, g_object_set (G_OBJECT (queue), "leaky", 2, "max-size-buffers", 1, NULL); #endif - /* Set default "driver-name" for v4l2camsrc if not set */ - /* FIXME: v4l2camsrc specific */ - { - gchar *driver_name = NULL; - if (g_object_class_find_property (G_OBJECT_GET_CLASS (self->src_vid_src), - "driver-name")) { - g_object_get (G_OBJECT (self->src_vid_src), "driver-name", - &driver_name, NULL); - if (!driver_name) { - g_object_set (G_OBJECT (self->src_vid_src), "driver-name", - DEFAULT_V4L2CAMSRC_DRIVER_NAME, NULL); - } - } - } - ret = TRUE; done: return ret; From 3db90e1d432196be2852a27f00ba7432b4590656 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Fri, 26 Nov 2010 10:14:46 -0300 Subject: [PATCH 048/448] camerabin2: Adds a stub element for camerabin2 Adds camerabin2 element, it is now a pile of stubs. --- gst/camerabin2/Makefile.am | 2 + gst/camerabin2/gstcamerabin2.c | 171 +++++++++++++++++++++++++++++++++ gst/camerabin2/gstcamerabin2.h | 55 +++++++++++ gst/camerabin2/gstplugin.c | 3 + 4 files changed, 231 insertions(+) create mode 100644 gst/camerabin2/gstcamerabin2.c create mode 100644 gst/camerabin2/gstcamerabin2.h diff --git a/gst/camerabin2/Makefile.am b/gst/camerabin2/Makefile.am index e1278f4bbe..92229d73df 100644 --- a/gst/camerabin2/Makefile.am +++ b/gst/camerabin2/Makefile.am @@ -7,6 +7,7 @@ libgstcamerabin2_la_SOURCES = gstviewfinderbin.c \ gstbasecamerasrc.c \ gstcamerabin-enum.c \ gstv4l2camerasrc.c \ + gstcamerabin2.c \ gstplugin.c libgstcamerabin2_la_CFLAGS = \ @@ -28,4 +29,5 @@ noinst_HEADERS = gstviewfinderbin.h \ camerabingeneral.h \ gstbasecamerasrc.h \ gstv4l2camerasrc.h \ + gstcamerabin2.h \ gstcamerabin-enum.h diff --git a/gst/camerabin2/gstcamerabin2.c b/gst/camerabin2/gstcamerabin2.c new file mode 100644 index 0000000000..39f89a5de3 --- /dev/null +++ b/gst/camerabin2/gstcamerabin2.c @@ -0,0 +1,171 @@ +/* GStreamer + * Copyright (C) 2010 Thiago Santos + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +/** + * SECTION:element-gstcamerabin + * + * The gstcamerabin element does FIXME stuff. + * + * + * Example launch line + * |[ + * gst-launch -v videotestsrc ! camerabin + * ]| + * FIXME Describe what the pipeline does. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstcamerabin2.h" + +/* prototypes */ + + +enum +{ + PROP_0 +}; + +/******************************** + * Standard GObject boilerplate * + ********************************/ + +static GstPipelineClass *parent_class; +static void gst_camera_bin_class_init (GstCameraBinClass * klass); +static void gst_camera_bin_base_init (gpointer klass); +static void gst_camera_bin_init (GstCameraBin * camera); +static void gst_camera_bin_dispose (GObject * object); +static void gst_camera_bin_finalize (GObject * object); + +GType +gst_camera_bin_get_type (void) +{ + static GType gst_camera_bin_type = 0; + + if (!gst_camera_bin_type) { + static const GTypeInfo gst_camera_bin_info = { + sizeof (GstCameraBinClass), + (GBaseInitFunc) gst_camera_bin_base_init, + NULL, + (GClassInitFunc) gst_camera_bin_class_init, + NULL, + NULL, + sizeof (GstCameraBin), + 0, + (GInstanceInitFunc) gst_camera_bin_init, + NULL + }; + + gst_camera_bin_type = + g_type_register_static (GST_TYPE_PIPELINE, "GstCameraBin2", + &gst_camera_bin_info, 0); + } + + return gst_camera_bin_type; +} + +/* Element class functions */ +static GstStateChangeReturn +gst_camera_bin_change_state (GstElement * element, GstStateChange trans); + +static void +gst_camera_bin_dispose (GObject * object) +{ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +gst_camera_bin_finalize (GObject * object) +{ + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +gst_camera_bin_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_set_details_simple (element_class, "CameraBin2", + "Generic/Bin/Camera", "CameraBin2", + "Thiago Santos "); +} + +static void +gst_camera_bin_class_init (GstCameraBinClass * klass) +{ + GObjectClass *object_class; + GstElementClass *element_class; + + parent_class = g_type_class_peek_parent (klass); + object_class = G_OBJECT_CLASS (klass); + element_class = GST_ELEMENT_CLASS (klass); + + object_class->dispose = gst_camera_bin_dispose; + object_class->finalize = gst_camera_bin_finalize; + + element_class->change_state = GST_DEBUG_FUNCPTR (gst_camera_bin_change_state); +} + +static void +gst_camera_bin_init (GstCameraBin * camerabin) +{ +} + +static gboolean +gst_camera_bin_create_elements (GstCameraBin * camera) +{ + return TRUE; +} + +static GstStateChangeReturn +gst_camera_bin_change_state (GstElement * element, GstStateChange trans) +{ + GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; + GstCameraBin *camera = GST_CAMERA_BIN_CAST (element); + + switch (trans) { + case GST_STATE_CHANGE_NULL_TO_READY: + if (!gst_camera_bin_create_elements (camera)) { + return GST_STATE_CHANGE_FAILURE; + } + break; + default: + break; + } + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, trans); + + switch (trans) { + case GST_STATE_CHANGE_READY_TO_NULL: + break; + default: + break; + } + + return ret; +} + +gboolean +gst_camera_bin_plugin_init (GstPlugin * plugin) +{ + return gst_element_register (plugin, "camerabin2", GST_RANK_NONE, + gst_camera_bin_get_type ()); +} diff --git a/gst/camerabin2/gstcamerabin2.h b/gst/camerabin2/gstcamerabin2.h new file mode 100644 index 0000000000..c2927d3600 --- /dev/null +++ b/gst/camerabin2/gstcamerabin2.h @@ -0,0 +1,55 @@ +/* GStreamer + * Copyright (C) 2010 Thiago Santos + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +#ifndef _GST_CAMERA_BIN_H_ +#define _GST_CAMERA_BIN_H_ + +#include + +G_BEGIN_DECLS + +#define GST_TYPE_CAMERA_BIN (gst_camera_bin_get_type()) +#define GST_CAMERA_BIN(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_CAMERA_BIN,GstCameraBin)) +#define GST_CAMERA_BIN_CAST(obj) ((GstCameraBin *) obj) +#define GST_CAMERA_BIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_CAMERA_BIN,GstCameraBinClass)) +#define GST_IS_CAMERA_BIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_CAMERA_BIN)) +#define GST_IS_CAMERA_BIN_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_CAMERA_BIN)) + +typedef struct _GstCameraBin GstCameraBin; +typedef struct _GstCameraBinClass GstCameraBinClass; + +struct _GstCameraBin +{ + GstPipeline pipeline; + + GstPad *ghostpad; + + gboolean elements_created; +}; + +struct _GstCameraBinClass +{ + GstPipelineClass pipeline_class; +}; + +GType gst_camera_bin_get_type (void); +gboolean gst_camera_bin_plugin_init (GstPlugin * plugin); + +G_END_DECLS + +#endif diff --git a/gst/camerabin2/gstplugin.c b/gst/camerabin2/gstplugin.c index 872ad1e637..517f9a6c02 100644 --- a/gst/camerabin2/gstplugin.c +++ b/gst/camerabin2/gstplugin.c @@ -27,6 +27,7 @@ #include "gstimagecapturebin.h" #include "gstvideorecordingbin.h" #include "gstv4l2camerasrc.h" +#include "gstcamerabin2.h" static gboolean plugin_init (GstPlugin * plugin) @@ -39,6 +40,8 @@ plugin_init (GstPlugin * plugin) return FALSE; if (!gst_v4l2_camera_src_plugin_init (plugin)) return FALSE; + if (!gst_camera_bin_plugin_init (plugin)) + return FALSE; return TRUE; } From 1887669d6e7d23555b28ae204dd7a7a08645e1d2 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Fri, 26 Nov 2010 14:51:30 -0300 Subject: [PATCH 049/448] camerabin2: Adding basic elements Instantiating and linking basic elements on camerabin2 so it at least shows the viewfinder when running. --- gst/camerabin2/gstcamerabin2.c | 59 +++++++++++++++++++++++++++++----- 1 file changed, 51 insertions(+), 8 deletions(-) diff --git a/gst/camerabin2/gstcamerabin2.c b/gst/camerabin2/gstcamerabin2.c index 39f89a5de3..4c4d5c7c9c 100644 --- a/gst/camerabin2/gstcamerabin2.c +++ b/gst/camerabin2/gstcamerabin2.c @@ -20,14 +20,6 @@ * SECTION:element-gstcamerabin * * The gstcamerabin element does FIXME stuff. - * - * - * Example launch line - * |[ - * gst-launch -v videotestsrc ! camerabin - * ]| - * FIXME Describe what the pipeline does. - * */ #ifdef HAVE_CONFIG_H @@ -129,9 +121,60 @@ gst_camera_bin_init (GstCameraBin * camerabin) { } +/** + * gst_camera_bin_create_elements: + * @param camera: the #GstCameraBin + * + * Creates all elements inside #GstCameraBin + * + * Each of the pads on the camera source is linked as follows: + * .pad ! queue ! capsfilter ! correspondingbin + * + * Where 'correspondingbin' is the bin appropriate for + * the camera source pad. + */ static gboolean gst_camera_bin_create_elements (GstCameraBin * camera) { + GstElement *src; + GstElement *vid; + GstElement *img; + GstElement *vf; + GstElement *vid_queue; + GstElement *img_queue; + GstElement *vf_queue; + GstElement *vid_capsfilter; + GstElement *img_capsfilter; + GstElement *vf_capsfilter; + + if (camera->elements_created) + return TRUE; + + src = gst_element_factory_make ("v4l2camerasrc", "camerasrc"); + vid = gst_element_factory_make ("videorecordingbin", "video-rec-bin"); + img = gst_element_factory_make ("imagecapturebin", "image-cap-bin"); + vf = gst_element_factory_make ("viewfinderbin", "vf-bin"); + + vid_queue = gst_element_factory_make ("queue", "video-queue"); + img_queue = gst_element_factory_make ("queue", "image-queue"); + vf_queue = gst_element_factory_make ("queue", "vf-queue"); + + vid_capsfilter = gst_element_factory_make ("capsfilter", "video-capsfilter"); + img_capsfilter = gst_element_factory_make ("capsfilter", "image-capsfilter"); + vf_capsfilter = gst_element_factory_make ("capsfilter", "vf-capsfilter"); + + gst_bin_add_many (GST_BIN_CAST (camera), src, vid, img, vf, vid_queue, + img_queue, vf_queue, vid_capsfilter, img_capsfilter, vf_capsfilter, NULL); + + /* Linking can be optimized TODO */ + gst_element_link_many (vid_queue, vid_capsfilter, vid, NULL); + gst_element_link_many (img_queue, img_capsfilter, img, NULL); + gst_element_link_many (vf_queue, vf_capsfilter, vf, NULL); + gst_element_link_pads (src, "vfsrc", vf_queue, "sink"); + gst_element_link_pads (src, "imgsrc", img_queue, "sink"); + gst_element_link_pads (src, "vidsrc", vid_queue, "sink"); + + camera->elements_created = TRUE; return TRUE; } From a938fd91929a814ade9b3d081b37bee98504ea6c Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Fri, 26 Nov 2010 15:55:39 -0300 Subject: [PATCH 050/448] camerabin2: Set filesink's async to FALSE In order to preroll, camerabin2 should have its filesinks in the imagecapturebin and videorecordingbin with async=FALSE. --- gst/camerabin2/gstimagecapturebin.c | 2 +- gst/camerabin2/gstvideorecordingbin.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gst/camerabin2/gstimagecapturebin.c b/gst/camerabin2/gstimagecapturebin.c index 6334a8b3e2..242172aafe 100644 --- a/gst/camerabin2/gstimagecapturebin.c +++ b/gst/camerabin2/gstimagecapturebin.c @@ -125,7 +125,7 @@ gst_image_capture_bin_create_elements (GstImageCaptureBin * icbin) if (!sink) goto error; - g_object_set (sink, "location", "cap_%03d.jpg", NULL); + g_object_set (sink, "location", "cap_%03d.jpg", "async", FALSE, NULL); /* add and link */ gst_bin_add_many (GST_BIN_CAST (icbin), csp, enc, mux, sink, NULL); diff --git a/gst/camerabin2/gstvideorecordingbin.c b/gst/camerabin2/gstvideorecordingbin.c index 4e5a8782d5..f4c423d82e 100644 --- a/gst/camerabin2/gstvideorecordingbin.c +++ b/gst/camerabin2/gstvideorecordingbin.c @@ -126,7 +126,7 @@ gst_video_recording_bin_create_elements (GstVideoRecordingBin * vrbin) if (!sink) goto error; - g_object_set (sink, "location", "cap.ogg", NULL); + g_object_set (sink, "location", "cap.ogg", "async", FALSE, NULL); /* add and link */ gst_bin_add_many (GST_BIN_CAST (vrbin), csp, enc, mux, sink, NULL); From 6c72fed8b460458251cb5acacfdf41f567557abc Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Fri, 26 Nov 2010 17:24:58 -0300 Subject: [PATCH 051/448] camerabin2: Adding basic property and signals Adds mode property to camerabin2, allowing users to select between video and stills capture. Also adds start/stop capture actions to trigger and stop capturing --- gst/camerabin2/gstcamerabin2.c | 174 ++++++++++++++++++++++++++++++++- gst/camerabin2/gstcamerabin2.h | 13 ++- 2 files changed, 185 insertions(+), 2 deletions(-) diff --git a/gst/camerabin2/gstcamerabin2.c b/gst/camerabin2/gstcamerabin2.c index 4c4d5c7c9c..acbe679733 100644 --- a/gst/camerabin2/gstcamerabin2.c +++ b/gst/camerabin2/gstcamerabin2.c @@ -33,13 +33,61 @@ enum { - PROP_0 + PROP_0, + PROP_MODE }; +enum +{ + /* action signals */ + START_CAPTURE_SIGNAL, + STOP_CAPTURE_SIGNAL, + /* emit signals */ + LAST_SIGNAL +}; +static guint camerabin_signals[LAST_SIGNAL]; + +#define DEFAULT_MODE MODE_IMAGE + /******************************** * Standard GObject boilerplate * + * and GObject types * ********************************/ +#define GST_TYPE_CAMERABIN_MODE (gst_camerabin_mode_get_type ()) +/** + * GstCameraBinMode: + * @MODE_PREVIEW: preview only (no capture) mode + * @MODE_IMAGE: image capture + * @MODE_VIDEO: video capture + * + * Capture mode to use. + */ +typedef enum +{ + MODE_PREVIEW = 0, /* TODO do we have an use for this? */ + MODE_IMAGE = 1, + MODE_VIDEO = 2, +} GstCameraBinMode; + +static GType +gst_camerabin_mode_get_type (void) +{ + static GType gtype = 0; + + if (gtype == 0) { + static const GEnumValue values[] = { + {MODE_IMAGE, "Still image capture (default)", "mode-image"}, + {MODE_VIDEO, "Video recording", "mode-video"}, + {0, NULL, NULL} + }; + + gtype = g_enum_register_static ("GstCameraBin2Mode", values); + } + return gtype; +} + + static GstPipelineClass *parent_class; static void gst_camera_bin_class_init (GstCameraBinClass * klass); static void gst_camera_bin_base_init (gpointer klass); @@ -74,13 +122,60 @@ gst_camera_bin_get_type (void) return gst_camera_bin_type; } +/* GObject class functions */ +static void gst_camerabin_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_camerabin_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + /* Element class functions */ static GstStateChangeReturn gst_camera_bin_change_state (GstElement * element, GstStateChange trans); + +/* Camerabin functions */ + +static void +gst_camera_bin_start_capture (GstCameraBin * camerabin) +{ + g_mutex_lock (camerabin->capture_mutex); + if (!camerabin->capturing) { + g_object_set (camerabin->src, "mode", camerabin->mode, NULL); + camerabin->capturing = TRUE; + } else { + GST_WARNING_OBJECT (camerabin, "Capture already ongoing"); + } + g_mutex_unlock (camerabin->capture_mutex); +} + +static void +gst_camera_bin_stop_capture (GstCameraBin * camerabin) +{ + g_mutex_lock (camerabin->capture_mutex); + if (camerabin->capturing) { + g_object_set (camerabin->src, "mode", MODE_PREVIEW, NULL); + camerabin->capturing = FALSE; + } + g_mutex_unlock (camerabin->capture_mutex); +} + +static void +gst_camera_bin_change_mode (GstCameraBin * camerabin, gint mode) +{ + /* stop any ongoing capture */ + gst_camera_bin_stop_capture (camerabin); + + camerabin->mode = mode; +} + static void gst_camera_bin_dispose (GObject * object) { + GstCameraBin *camerabin = GST_CAMERA_BIN_CAST (object); + + gst_object_unref (camerabin->src); + + g_mutex_free (camerabin->capture_mutex); G_OBJECT_CLASS (parent_class)->dispose (object); } @@ -112,13 +207,56 @@ gst_camera_bin_class_init (GstCameraBinClass * klass) object_class->dispose = gst_camera_bin_dispose; object_class->finalize = gst_camera_bin_finalize; + object_class->set_property = gst_camerabin_set_property; + object_class->get_property = gst_camerabin_get_property; element_class->change_state = GST_DEBUG_FUNCPTR (gst_camera_bin_change_state); + + klass->start_capture = gst_camera_bin_start_capture; + klass->stop_capture = gst_camera_bin_stop_capture; + + /** + * GstCameraBin:mode: + * + * Set the mode of operation: still image capturing or video recording. + */ + g_object_class_install_property (object_class, PROP_MODE, + g_param_spec_enum ("mode", "Mode", + "The capture mode (still image capture or video recording)", + GST_TYPE_CAMERABIN_MODE, DEFAULT_MODE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** + * GstCameraBin::capture-start: + * @camera: the camera bin element + * + * Starts image capture or video recording depending on the Mode. + */ + camerabin_signals[START_CAPTURE_SIGNAL] = + g_signal_new ("start-capture", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (GstCameraBinClass, start_capture), + NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + + /** + * GstCameraBin::capture-stop: + * @camera: the camera bin element + */ + camerabin_signals[STOP_CAPTURE_SIGNAL] = + g_signal_new ("stop-capture", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (GstCameraBinClass, stop_capture), + NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); } static void gst_camera_bin_init (GstCameraBin * camerabin) { + camerabin->capturing = FALSE; + camerabin->capture_mutex = g_mutex_new (); + camerabin->mode = MODE_IMAGE; } /** @@ -155,6 +293,8 @@ gst_camera_bin_create_elements (GstCameraBin * camera) img = gst_element_factory_make ("imagecapturebin", "image-cap-bin"); vf = gst_element_factory_make ("viewfinderbin", "vf-bin"); + camera->src = gst_object_ref (src); + vid_queue = gst_element_factory_make ("queue", "video-queue"); img_queue = gst_element_factory_make ("queue", "image-queue"); vf_queue = gst_element_factory_make ("queue", "vf-queue"); @@ -206,6 +346,38 @@ gst_camera_bin_change_state (GstElement * element, GstStateChange trans) return ret; } +static void +gst_camerabin_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstCameraBin *camera = GST_CAMERA_BIN_CAST (object); + + switch (prop_id) { + case PROP_MODE: + gst_camera_bin_change_mode (camera, g_value_get_enum (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_camerabin_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstCameraBin *camera = GST_CAMERA_BIN_CAST (object); + + switch (prop_id) { + case PROP_MODE: + g_value_set_enum (value, camera->mode); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + gboolean gst_camera_bin_plugin_init (GstPlugin * plugin) { diff --git a/gst/camerabin2/gstcamerabin2.h b/gst/camerabin2/gstcamerabin2.h index c2927d3600..f87b34ce8b 100644 --- a/gst/camerabin2/gstcamerabin2.h +++ b/gst/camerabin2/gstcamerabin2.h @@ -37,7 +37,14 @@ struct _GstCameraBin { GstPipeline pipeline; - GstPad *ghostpad; + GstElement *src; + + /* concurrency control */ + GMutex *capture_mutex; + gboolean capturing; + + /* properties */ + gint mode; gboolean elements_created; }; @@ -45,6 +52,10 @@ struct _GstCameraBin struct _GstCameraBinClass { GstPipelineClass pipeline_class; + + /* Action signals */ + void (*start_capture) (GstCameraBin * camera); + void (*stop_capture) (GstCameraBin * camera); }; GType gst_camera_bin_get_type (void); From 8fb882253231d99d80a448f7f8e91c9220201be3 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Fri, 26 Nov 2010 23:55:12 -0300 Subject: [PATCH 052/448] examples: Adds camerabin2 example Adds gtk camerabin2 example app --- configure.ac | 1 + tests/examples/Makefile.am | 4 +- tests/examples/camerabin2/.gitignore | 2 + tests/examples/camerabin2/Makefile.am | 33 +++++ tests/examples/camerabin2/gst-camera2.c | 179 +++++++++++++++++++++++ tests/examples/camerabin2/gst-camera2.h | 48 ++++++ tests/examples/camerabin2/gst-camera2.ui | 109 ++++++++++++++ 7 files changed, 374 insertions(+), 2 deletions(-) create mode 100644 tests/examples/camerabin2/.gitignore create mode 100644 tests/examples/camerabin2/Makefile.am create mode 100644 tests/examples/camerabin2/gst-camera2.c create mode 100644 tests/examples/camerabin2/gst-camera2.h create mode 100644 tests/examples/camerabin2/gst-camera2.ui diff --git a/configure.ac b/configure.ac index 51b6d0e2bc..c8aab6f994 100644 --- a/configure.ac +++ b/configure.ac @@ -1808,6 +1808,7 @@ tests/check/Makefile tests/files/Makefile tests/examples/Makefile tests/examples/camerabin/Makefile +tests/examples/camerabin2/Makefile tests/examples/directfb/Makefile tests/examples/mxf/Makefile tests/examples/scaletempo/Makefile diff --git a/tests/examples/Makefile.am b/tests/examples/Makefile.am index 0e92667d58..218f2c622c 100644 --- a/tests/examples/Makefile.am +++ b/tests/examples/Makefile.am @@ -4,7 +4,7 @@ JACK_EXAMPLES=jack else JACK_EXAMPLES= endif -GTK_EXAMPLES=camerabin mxf scaletempo +GTK_EXAMPLES=camerabin mxf scaletempo camerabin2 else GTK_EXAMPLES= endif @@ -16,4 +16,4 @@ DIRECTFB_DIR= endif SUBDIRS= $(DIRECTFB_DIR) $(GTK_EXAMPLES) $(JACK_EXAMPLES) switch -DIST_SUBDIRS= camerabin directfb jack mxf scaletempo switch +DIST_SUBDIRS= camerabin camerabin2 directfb jack mxf scaletempo switch diff --git a/tests/examples/camerabin2/.gitignore b/tests/examples/camerabin2/.gitignore new file mode 100644 index 0000000000..cf225216fa --- /dev/null +++ b/tests/examples/camerabin2/.gitignore @@ -0,0 +1,2 @@ +gst-camera2 +test_*.jpg diff --git a/tests/examples/camerabin2/Makefile.am b/tests/examples/camerabin2/Makefile.am new file mode 100644 index 0000000000..781f201639 --- /dev/null +++ b/tests/examples/camerabin2/Makefile.am @@ -0,0 +1,33 @@ +GST_CAMERABIN_UI_FILES = gst-camera2.ui + +if HAVE_GTK + +GST_CAMERABIN_GTK_EXAMPLES = gst-camera2 + +gst_camera2_SOURCES = gst-camera2.h gst-camera2.c +gst_camera2_CFLAGS = \ + $(GST_PLUGINS_BAD_CFLAGS) \ + $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) \ + $(GTK_CFLAGS) \ + $(GMODULE_EXPORT_CFLAGS) \ + -DGST_USE_UNSTABLE_API +gst_camera2_LDADD = \ + $(top_builddir)/gst-libs/gst/interfaces/libgstphotography-@GST_MAJORMINOR@.la \ + $(GST_PLUGINS_BASE_LIBS) \ + -lgstinterfaces-@GST_MAJORMINOR@ \ + $(GST_LIBS) \ + $(GTK_LIBS) \ + $(GMODULE_EXPORT_LIBS) + +noinst_DATA = $(GST_CAMERABIN_UI_FILES) + +INCLUDES = -DCAMERA_APPS_UIDIR=\""$(uidir)"\" + +else +GST_CAMERABIN_GTK_EXAMPLES = +endif + +noinst_PROGRAMS = $(GST_CAMERABIN_GTK_EXAMPLES) + +EXTRA_DIST = $(GST_CAMERABIN_UI_FILES) + diff --git a/tests/examples/camerabin2/gst-camera2.c b/tests/examples/camerabin2/gst-camera2.c new file mode 100644 index 0000000000..b079adc309 --- /dev/null +++ b/tests/examples/camerabin2/gst-camera2.c @@ -0,0 +1,179 @@ +/* + * GStreamer + * Copyright (C) 2010 Thiago Santos + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +/* + * This is a demo application to test the camerabin element. + * If you have question don't hesitate in contact me edgard.lima@indt.org.br + */ + +/* + * Includes + */ +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "gst-camera2.h" + +#include +#include +#include +#include +#include + +#define UI_FILE "gst-camera2.ui" + +static GstElement *camera; +static GtkBuilder *builder; + +void +on_mainWindow_delete_event (GtkWidget * widget, GdkEvent * event, gpointer data) +{ + gtk_main_quit (); +} + +void +on_captureButton_clicked (GtkButton * button, gpointer user_data) +{ + g_signal_emit_by_name (camera, "start-capture", NULL); +} + +void +on_stopCaptureButton_clicked (GtkButton * button, gpointer user_data) +{ + g_signal_emit_by_name (camera, "stop-capture", NULL); +} + +void +on_imageRButton_toggled (GtkToggleButton * button, gpointer user_data) +{ + if (gtk_toggle_button_get_active (button)) { + g_object_set (camera, "mode", 1, NULL); /* Image mode */ + } +} + +void +on_videoRButton_toggled (GtkToggleButton * button, gpointer user_data) +{ + if (gtk_toggle_button_get_active (button)) { + g_object_set (camera, "mode", 2, NULL); /* Video mode */ + } +} + +void +on_viewfinderArea_realize (GtkWidget * widget, gpointer data) +{ +#if GTK_CHECK_VERSION (2, 18, 0) + gdk_window_ensure_native (gtk_widget_get_window (widget)); +#endif +} + +static GstBusSyncReply +bus_sync_callback (GstBus * bus, GstMessage * message, gpointer data) +{ + GtkWidget *ui_drawing; + + if (GST_MESSAGE_TYPE (message) != GST_MESSAGE_ELEMENT) + return GST_BUS_PASS; + + if (!gst_structure_has_name (message->structure, "prepare-xwindow-id")) + return GST_BUS_PASS; + + /* FIXME: make sure to get XID in main thread */ + ui_drawing = GTK_WIDGET (gtk_builder_get_object (builder, "viewfinderArea")); + gst_x_overlay_set_window_handle (GST_X_OVERLAY (message->src), + GDK_WINDOW_XWINDOW (gtk_widget_get_window (ui_drawing))); + + gst_message_unref (message); + return GST_BUS_DROP; +} + + +static gboolean +bus_callback (GstBus * bus, GstMessage * message, gpointer data) +{ + switch (GST_MESSAGE_TYPE (message)) { + case GST_MESSAGE_WARNING:{ + GError *err; + gchar *debug; + + gst_message_parse_warning (message, &err, &debug); + g_print ("Warning: %s\n", err->message); + g_error_free (err); + g_free (debug); + break; + } + case GST_MESSAGE_ERROR:{ + //print_error_message (message); + //me_gst_cleanup_element (); + gtk_main_quit (); + break; + } + case GST_MESSAGE_EOS: + /* end-of-stream */ + gtk_main_quit (); + break; + case GST_MESSAGE_ELEMENT: + { + //handle_element_message (message); + break; + } + default: + /* unhandled message */ + break; + } + return TRUE; +} + +int +main (int argc, char *argv[]) +{ + int ret = 0; + GtkWidget *ui_main_window; + GError *error = NULL; + GstBus *bus; + + gst_init (&argc, &argv); + gtk_init (&argc, &argv); + + builder = gtk_builder_new (); + if (!gtk_builder_add_from_file (builder, UI_FILE, &error)) { + g_warning ("Error: %s", error->message); + g_free (error); + return 1; + } + + camera = gst_element_factory_make ("camerabin2", "camera"); + bus = gst_pipeline_get_bus (GST_PIPELINE (camera)); + gst_bus_add_watch (bus, bus_callback, NULL); + gst_bus_set_sync_handler (bus, bus_sync_callback, NULL); + gst_object_unref (bus); + + ui_main_window = GTK_WIDGET (gtk_builder_get_object (builder, "mainWindow")); + gtk_builder_connect_signals (builder, NULL); + gtk_widget_show_all (ui_main_window); + + gst_element_set_state (camera, GST_STATE_PLAYING); + + gtk_main (); + + gst_element_set_state (camera, GST_STATE_NULL); + gst_object_unref (camera); + return ret; +} diff --git a/tests/examples/camerabin2/gst-camera2.h b/tests/examples/camerabin2/gst-camera2.h new file mode 100644 index 0000000000..d96e2de63a --- /dev/null +++ b/tests/examples/camerabin2/gst-camera2.h @@ -0,0 +1,48 @@ +/* + * GStreamer + * Copyright (C) 2008 Nokia Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +/* + * This is a demo application to test the camerabin element. + * If you have question don't hesitate in contact me edgard.lima@indt.org.br + */ + +#ifndef __GST_CAMERA_BIN_H__ +#define __GST_CAMERA_BIN_H__ + +#include + +void +on_mainWindow_delete_event (GtkWidget * widget, GdkEvent * event, gpointer data); + +void +on_captureButton_clicked (GtkButton * button, gpointer user_data); + +void +on_stopCaptureButton_clicked (GtkButton * button, gpointer user_data); + +void +on_imageRButton_toggled (GtkToggleButton * button, gpointer user_data); + +void +on_videoRButton_toggled (GtkToggleButton * button, gpointer user_data); + +void +on_viewfinderArea_realize (GtkWidget * widget, gpointer data); + +#endif /* __GST_CAMERA_BIN_H__ */ diff --git a/tests/examples/camerabin2/gst-camera2.ui b/tests/examples/camerabin2/gst-camera2.ui new file mode 100644 index 0000000000..48fe1410ab --- /dev/null +++ b/tests/examples/camerabin2/gst-camera2.ui @@ -0,0 +1,109 @@ + + + + + + 800 + 600 + + + + True + + + True + + + Image + True + True + False + True + True + + + + 0 + + + + + Video + True + True + False + True + True + imageRButton + + + + 1 + + + + + False + False + 0 + + + + + True + + + True + + + + 0 + + + + + True + + + Capture + True + True + True + + + + False + False + 0 + + + + + Stop Capture + True + True + True + + + + False + False + 1 + + + + + False + False + 1 + + + + + 1 + + + + + + From dee167edc815a41616df6c27fb4e5581e064414a Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Mon, 29 Nov 2010 10:45:30 -0300 Subject: [PATCH 053/448] camerabin2: Adding debug categories Adding debug categories to v4l2camerasrc and camerabin2, also removing generic category from camerabingeneral. --- gst/camerabin2/camerabingeneral.c | 2 -- gst/camerabin2/camerabingeneral.h | 4 ---- gst/camerabin2/gstcamerabin2.c | 8 +++++++- gst/camerabin2/gstv4l2camerasrc.c | 8 ++++---- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/gst/camerabin2/camerabingeneral.c b/gst/camerabin2/camerabingeneral.c index 2a50d9e126..0219a0fe3b 100644 --- a/gst/camerabin2/camerabingeneral.c +++ b/gst/camerabin2/camerabingeneral.c @@ -31,8 +31,6 @@ #include "camerabingeneral.h" #include -GST_DEBUG_CATEGORY (gst_camerabin_debug); - /** * gst_camerabin_add_element: * @bin: add an element to this bin diff --git a/gst/camerabin2/camerabingeneral.h b/gst/camerabin2/camerabingeneral.h index 93520c5a60..7f453aca2f 100644 --- a/gst/camerabin2/camerabingeneral.h +++ b/gst/camerabin2/camerabingeneral.h @@ -35,8 +35,4 @@ void gst_camerabin_remove_elements_from_bin (GstBin * bin); gboolean gst_camerabin_drop_eos_probe (GstPad * pad, GstEvent * event, gpointer u_data); -/* debug logging category */ -GST_DEBUG_CATEGORY_EXTERN (gst_camerabin_debug); -#define GST_CAT_DEFAULT gst_camerabin_debug - #endif /* #ifndef __CAMERABIN_GENERAL_H_ */ diff --git a/gst/camerabin2/gstcamerabin2.c b/gst/camerabin2/gstcamerabin2.c index acbe679733..9ea7bfb1d4 100644 --- a/gst/camerabin2/gstcamerabin2.c +++ b/gst/camerabin2/gstcamerabin2.c @@ -28,8 +28,10 @@ #include "gstcamerabin2.h" -/* prototypes */ +GST_DEBUG_CATEGORY_STATIC (gst_camera_bin_debug); +#define GST_CAT_DEFAULT gst_camera_bin_debug +/* prototypes */ enum { @@ -138,8 +140,10 @@ gst_camera_bin_change_state (GstElement * element, GstStateChange trans); static void gst_camera_bin_start_capture (GstCameraBin * camerabin) { + GST_DEBUG_OBJECT (camerabin, "Received start-capture"); g_mutex_lock (camerabin->capture_mutex); if (!camerabin->capturing) { + GST_INFO_OBJECT (camerabin, "Starting capture, mode: %d", camerabin->mode); g_object_set (camerabin->src, "mode", camerabin->mode, NULL); camerabin->capturing = TRUE; } else { @@ -381,6 +385,8 @@ gst_camerabin_get_property (GObject * object, guint prop_id, gboolean gst_camera_bin_plugin_init (GstPlugin * plugin) { + GST_DEBUG_CATEGORY_INIT (gst_camera_bin_debug, "camerabin2", 0, "CameraBin2"); + return gst_element_register (plugin, "camerabin2", GST_RANK_NONE, gst_camera_bin_get_type ()); } diff --git a/gst/camerabin2/gstv4l2camerasrc.c b/gst/camerabin2/gstv4l2camerasrc.c index 8d3f7eb822..8d4995dcb8 100644 --- a/gst/camerabin2/gstv4l2camerasrc.c +++ b/gst/camerabin2/gstv4l2camerasrc.c @@ -41,8 +41,8 @@ /* Using "bilinear" as default zoom method */ #define CAMERABIN_DEFAULT_ZOOM_METHOD 1 -//GST_DEBUG_CATEGORY (v4l2_camera_src_debug); -//#define GST_CAT_DEFAULT v4l2_camera_src_debug +GST_DEBUG_CATEGORY (v4l2_camera_src_debug); +#define GST_CAT_DEFAULT v4l2_camera_src_debug GST_BOILERPLATE (GstV4l2CameraSrc, gst_v4l2_camera_src, GstBaseCameraSrc, GST_TYPE_BASE_CAMERA_SRC); @@ -999,8 +999,8 @@ gst_v4l2_camera_src_base_init (gpointer g_class) { GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class); -// GST_DEBUG_CATEGORY_INIT (v4l2_camera_src_debug, "v4l2_camera_src", 0, -// "V4l2 camera src"); + GST_DEBUG_CATEGORY_INIT (v4l2_camera_src_debug, "v4l2camerasrc", 0, + "V4l2 camera src"); gst_element_class_set_details_simple (gstelement_class, "V4l2 camera src element for camerabin", "Source/Video", From 9095ee429a28c7f6c3033d0b0f353ca16d12130d Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Mon, 29 Nov 2010 10:46:38 -0300 Subject: [PATCH 054/448] v4l2camerasrc: Adds mode property Adds mode property to v4l2camerasrc --- gst/camerabin2/gstv4l2camerasrc.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/gst/camerabin2/gstv4l2camerasrc.c b/gst/camerabin2/gstv4l2camerasrc.c index 8d4995dcb8..d475c8cbdc 100644 --- a/gst/camerabin2/gstv4l2camerasrc.c +++ b/gst/camerabin2/gstv4l2camerasrc.c @@ -69,6 +69,10 @@ gst_v4l2_camera_src_set_property (GObject * object, GstV4l2CameraSrc *self = GST_V4L2_CAMERA_SRC (object); switch (prop_id) { + case ARG_MODE: + self->mode = g_value_get_enum (value); + gst_base_camera_src_set_mode (GST_BASE_CAMERA_SRC (self), self->mode); + break; case ARG_FILTER_CAPS: GST_OBJECT_LOCK (self); gst_caps_replace (&self->view_finder_caps, @@ -112,6 +116,9 @@ gst_v4l2_camera_src_get_property (GObject * object, GstV4l2CameraSrc *self = GST_V4L2_CAMERA_SRC (object); switch (prop_id) { + case ARG_MODE: + g_value_set_enum (value, self->mode); + break; case ARG_FILTER_CAPS: gst_value_set_caps (value, self->view_finder_caps); break; @@ -1022,6 +1029,12 @@ gst_v4l2_camera_src_class_init (GstV4l2CameraSrcClass * klass) gobject_class->get_property = gst_v4l2_camera_src_get_property; // g_object_class_install_property .... + g_object_class_install_property (gobject_class, ARG_MODE, + g_param_spec_enum ("mode", "Mode", + "The capture mode (still image capture, video recording or " + "viewfinder)", + GST_TYPE_CAMERABIN_MODE, MODE_PREVIEW, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); gstbasecamerasrc_class->construct_pipeline = gst_v4l2_camera_src_construct_pipeline; From 6c7d7946f53aed028d66cf48e81edd39b2a433e6 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Mon, 29 Nov 2010 11:31:26 -0300 Subject: [PATCH 055/448] camerabin2: Keep mode definition at -enum file Use 'mode' enum definition from gstcamerabin-enum file to avoid conflicts between v4l2camerasrc and gstcamerabin2 modes. For now there is a MODE_PREVIEW there that is only used on the camerasrc, not sure if we are keeping it at the future, but for now this works. --- gst/camerabin2/gstcamerabin-enum.c | 2 +- gst/camerabin2/gstcamerabin2.c | 35 +----------------------------- 2 files changed, 2 insertions(+), 35 deletions(-) diff --git a/gst/camerabin2/gstcamerabin-enum.c b/gst/camerabin2/gstcamerabin-enum.c index 8d1d0c92d3..ac80d0b0a3 100644 --- a/gst/camerabin2/gstcamerabin-enum.c +++ b/gst/camerabin2/gstcamerabin-enum.c @@ -72,7 +72,7 @@ gst_camerabin_mode_get_type (void) {0, NULL, NULL} }; - gtype = g_enum_register_static ("GstCameraBinMode", values); + gtype = g_enum_register_static ("GstCameraBin2Mode", values); } return gtype; } diff --git a/gst/camerabin2/gstcamerabin2.c b/gst/camerabin2/gstcamerabin2.c index 9ea7bfb1d4..b6705d803d 100644 --- a/gst/camerabin2/gstcamerabin2.c +++ b/gst/camerabin2/gstcamerabin2.c @@ -27,6 +27,7 @@ #endif #include "gstcamerabin2.h" +#include "gstcamerabin-enum.h" GST_DEBUG_CATEGORY_STATIC (gst_camera_bin_debug); #define GST_CAT_DEFAULT gst_camera_bin_debug @@ -56,40 +57,6 @@ static guint camerabin_signals[LAST_SIGNAL]; * and GObject types * ********************************/ -#define GST_TYPE_CAMERABIN_MODE (gst_camerabin_mode_get_type ()) -/** - * GstCameraBinMode: - * @MODE_PREVIEW: preview only (no capture) mode - * @MODE_IMAGE: image capture - * @MODE_VIDEO: video capture - * - * Capture mode to use. - */ -typedef enum -{ - MODE_PREVIEW = 0, /* TODO do we have an use for this? */ - MODE_IMAGE = 1, - MODE_VIDEO = 2, -} GstCameraBinMode; - -static GType -gst_camerabin_mode_get_type (void) -{ - static GType gtype = 0; - - if (gtype == 0) { - static const GEnumValue values[] = { - {MODE_IMAGE, "Still image capture (default)", "mode-image"}, - {MODE_VIDEO, "Video recording", "mode-video"}, - {0, NULL, NULL} - }; - - gtype = g_enum_register_static ("GstCameraBin2Mode", values); - } - return gtype; -} - - static GstPipelineClass *parent_class; static void gst_camera_bin_class_init (GstCameraBinClass * klass); static void gst_camera_bin_base_init (gpointer klass); From 596422d19c645de5b96d9862b3f99956fadff03f Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Mon, 29 Nov 2010 12:57:21 -0300 Subject: [PATCH 056/448] v4l2camerasrc: Fix image capture Once a image is captured, v4l2camerasrc should return to the preview mode and stop capturing. --- gst/camerabin2/gstv4l2camerasrc.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/gst/camerabin2/gstv4l2camerasrc.c b/gst/camerabin2/gstv4l2camerasrc.c index d475c8cbdc..d13e148e27 100644 --- a/gst/camerabin2/gstv4l2camerasrc.c +++ b/gst/camerabin2/gstv4l2camerasrc.c @@ -147,8 +147,15 @@ gst_v4l2_camera_src_imgsrc_probe (GstPad * pad, GstBuffer * buffer, gpointer data) { GstV4l2CameraSrc *self = GST_V4L2_CAMERA_SRC (data); + gboolean ret; GST_DEBUG_OBJECT (self, "pass buffer: %d", self->mode == MODE_IMAGE); - return self->mode == MODE_IMAGE; + + ret = self->mode == MODE_IMAGE; + if (ret) { + self->mode = MODE_PREVIEW; + g_object_notify (G_OBJECT (self), "mode"); + } + return ret; } /** From 91b7f2d99ed68f5c66aa3baf7a4cbfb9bd0bc5a8 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Mon, 29 Nov 2010 15:49:26 -0300 Subject: [PATCH 057/448] v4l2camerasrc: Implement video capture Implements video capture on v4l2camerasrc by using the mode property, when mode is set to video, the pad probe pushes a new segment and starts pushing buffers on the pad, when it the property is sent back to preview, the pad probe pushes an EOS and stops pushing buffers. This is controlled by a Recording State variable, that is protected by the GST_OBJECT_LOCK. I don't think locking for every buffer is nice, so we could find an alternative lockless way here. --- gst/camerabin2/gstv4l2camerasrc.c | 67 ++++++++++++++++++++++++++----- gst/camerabin2/gstv4l2camerasrc.h | 10 +++++ 2 files changed, 66 insertions(+), 11 deletions(-) diff --git a/gst/camerabin2/gstv4l2camerasrc.c b/gst/camerabin2/gstv4l2camerasrc.c index d13e148e27..1b245e6be8 100644 --- a/gst/camerabin2/gstv4l2camerasrc.c +++ b/gst/camerabin2/gstv4l2camerasrc.c @@ -70,8 +70,8 @@ gst_v4l2_camera_src_set_property (GObject * object, switch (prop_id) { case ARG_MODE: - self->mode = g_value_get_enum (value); - gst_base_camera_src_set_mode (GST_BASE_CAMERA_SRC (self), self->mode); + gst_base_camera_src_set_mode (GST_BASE_CAMERA_SRC (self), + g_value_get_enum (value)); break; case ARG_FILTER_CAPS: GST_OBJECT_LOCK (self); @@ -168,8 +168,36 @@ gst_v4l2_camera_src_vidsrc_probe (GstPad * pad, GstBuffer * buffer, gpointer data) { GstV4l2CameraSrc *self = GST_V4L2_CAMERA_SRC (data); + gboolean ret = FALSE; + GST_DEBUG_OBJECT (self, "pass buffer: %d", self->mode == MODE_VIDEO); - return self->mode == MODE_VIDEO; + + /* TODO do we want to lock for every buffer? */ + /* + * Note that we can use gst_pad_push_event here because we are a buffer + * probe. + */ + if (self->mode == MODE_VIDEO) { + GST_OBJECT_LOCK (self); + if (self->video_rec_status == GST_VIDEO_RECORDING_STATUS_STARTING) { + /* send the newseg */ + gst_pad_push_event (pad, gst_event_new_new_segment (FALSE, 1.0, + GST_FORMAT_TIME, GST_BUFFER_TIMESTAMP (buffer), -1, 0)); + self->video_rec_status = GST_VIDEO_RECORDING_STATUS_RUNNING; + ret = TRUE; + } else if (self->video_rec_status == GST_VIDEO_RECORDING_STATUS_FINISHING) { + /* send eos */ + gst_pad_push_event (pad, gst_event_new_eos ()); + self->video_rec_status = GST_VIDEO_RECORDING_STATUS_DONE; + self->mode = MODE_PREVIEW; + g_object_notify (G_OBJECT (self), "mode"); + } else { + ret = TRUE; + } + GST_OBJECT_UNLOCK (self); + } + + return ret; } /** @@ -678,6 +706,7 @@ gst_v4l2_camera_src_set_mode (GstBaseCameraSrc * bcamsrc, GstCameraBinMode mode) { GstV4l2CameraSrc *self = GST_V4L2_CAMERA_SRC (bcamsrc); GstPhotography *photography = gst_base_camera_src_get_photography (bcamsrc); + gint ret = TRUE; if (photography) { if (g_object_class_find_property (G_OBJECT_GET_CLASS (photography), @@ -686,20 +715,34 @@ gst_v4l2_camera_src_set_mode (GstBaseCameraSrc * bcamsrc, GstCameraBinMode mode) } } - self->mode = mode; - switch (mode) { case MODE_PREVIEW: - return TRUE; // XXX + if (self->mode == MODE_VIDEO) { + GST_OBJECT_LOCK (self); + if (self->video_rec_status == GST_VIDEO_RECORDING_STATUS_STARTING) + self->video_rec_status = GST_VIDEO_RECORDING_STATUS_DONE; + else if (self->video_rec_status == GST_VIDEO_RECORDING_STATUS_RUNNING) + self->video_rec_status = GST_VIDEO_RECORDING_STATUS_FINISHING; + GST_OBJECT_UNLOCK (self); + } + break; case MODE_IMAGE: - return start_image_capture (GST_V4L2_CAMERA_SRC (bcamsrc)); + ret = start_image_capture (GST_V4L2_CAMERA_SRC (bcamsrc)); + break; case MODE_VIDEO: - return TRUE; // XXX + GST_OBJECT_LOCK (self); + if (self->video_rec_status == GST_VIDEO_RECORDING_STATUS_DONE) + self->video_rec_status = GST_VIDEO_RECORDING_STATUS_STARTING; + GST_OBJECT_UNLOCK (self); + break; + default: + g_assert_not_reached (); + ret = FALSE; } - g_assert_not_reached (); - - return FALSE; + if (ret) + self->mode = mode; + return ret; } static gboolean @@ -1058,7 +1101,9 @@ static void gst_v4l2_camera_src_init (GstV4l2CameraSrc * self, GstV4l2CameraSrcClass * klass) { + /* TODO where are variables reset? */ self->mode = MODE_PREVIEW; + self->video_rec_status = GST_VIDEO_RECORDING_STATUS_DONE; } gboolean diff --git a/gst/camerabin2/gstv4l2camerasrc.h b/gst/camerabin2/gstv4l2camerasrc.h index f12dc8c00b..9e40ffaee5 100644 --- a/gst/camerabin2/gstv4l2camerasrc.h +++ b/gst/camerabin2/gstv4l2camerasrc.h @@ -41,6 +41,13 @@ G_BEGIN_DECLS typedef struct _GstV4l2CameraSrc GstV4l2CameraSrc; typedef struct _GstV4l2CameraSrcClass GstV4l2CameraSrcClass; +enum GstVideoRecordingStatus { + GST_VIDEO_RECORDING_STATUS_DONE, + GST_VIDEO_RECORDING_STATUS_STARTING, + GST_VIDEO_RECORDING_STATUS_RUNNING, + GST_VIDEO_RECORDING_STATUS_FINISHING +}; + /** * GstV4l2CameraSrc: @@ -52,6 +59,9 @@ struct _GstV4l2CameraSrc GstCameraBinMode mode; + /* video recording controls */ + gint video_rec_status; + /* source elements */ GstElement *src_vid_src; GstElement *src_filter; From 9df40915d60843e48a26315286688005dace6905 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Mon, 29 Nov 2010 18:24:35 -0300 Subject: [PATCH 058/448] v4l2camerasrc: Remove unnecessary padding --- gst/camerabin2/gstv4l2camerasrc.h | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/gst/camerabin2/gstv4l2camerasrc.h b/gst/camerabin2/gstv4l2camerasrc.h index 9e40ffaee5..e4863bb913 100644 --- a/gst/camerabin2/gstv4l2camerasrc.h +++ b/gst/camerabin2/gstv4l2camerasrc.h @@ -94,11 +94,6 @@ struct _GstV4l2CameraSrc /* Caps applied to capsfilters when taking still image */ GstCaps *image_capture_caps; gboolean image_capture_caps_update; // XXX where does this get set.. - - /* if GstV4l2CameraSrc is moved into camerabin plugin, then this isn't - * needed: - */ - gpointer _gst_reserved[GST_PADDING_LARGE]; }; @@ -109,11 +104,6 @@ struct _GstV4l2CameraSrc struct _GstV4l2CameraSrcClass { GstBaseCameraSrcClass parent; - - /* if GstV4l2CameraSrc is moved into camerabin plugin, then this isn't - * needed: - */ - gpointer _gst_reserved[GST_PADDING_LARGE]; }; gboolean gst_v4l2_camera_src_plugin_init (GstPlugin * plugin); From b4d73cb9a87860488d0a46ac57eda1f96b7f0a35 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Mon, 29 Nov 2010 18:53:34 -0300 Subject: [PATCH 059/448] camerabin2: Cleanup capturing flag Cleanup capturing flag when the source switches back to the viewfinder mode --- gst/camerabin2/gstcamerabin2.c | 30 ++++++++++++++++++++++++++---- gst/camerabin2/gstcamerabin2.h | 1 + 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/gst/camerabin2/gstcamerabin2.c b/gst/camerabin2/gstcamerabin2.c index b6705d803d..bfead866f6 100644 --- a/gst/camerabin2/gstcamerabin2.c +++ b/gst/camerabin2/gstcamerabin2.c @@ -122,12 +122,12 @@ gst_camera_bin_start_capture (GstCameraBin * camerabin) static void gst_camera_bin_stop_capture (GstCameraBin * camerabin) { - g_mutex_lock (camerabin->capture_mutex); + /* TODO do we need a lock here? it is just an if */ if (camerabin->capturing) { + /* Capturing is cleaned on the notify function because it works + * both for images and videos */ g_object_set (camerabin->src, "mode", MODE_PREVIEW, NULL); - camerabin->capturing = FALSE; } - g_mutex_unlock (camerabin->capture_mutex); } static void @@ -144,7 +144,10 @@ gst_camera_bin_dispose (GObject * object) { GstCameraBin *camerabin = GST_CAMERA_BIN_CAST (object); - gst_object_unref (camerabin->src); + if (camerabin->src_mode_notify_id) + g_signal_handler_disconnect (camerabin->src, camerabin->src_mode_notify_id); + if (camerabin->src) + gst_object_unref (camerabin->src); g_mutex_free (camerabin->capture_mutex); G_OBJECT_CLASS (parent_class)->dispose (object); @@ -230,6 +233,23 @@ gst_camera_bin_init (GstCameraBin * camerabin) camerabin->mode = MODE_IMAGE; } +static void +gst_camera_bin_src_notify_mode (GObject * src, GParamSpec * pspec, + gpointer data) +{ + GstCameraBin *camera = GST_CAMERA_BIN_CAST (data); + gint mode; + + g_object_get (src, "mode", &mode, NULL); + + if (mode == MODE_PREVIEW) { + g_mutex_lock (camera->capture_mutex); + g_assert (camera->capturing); + camera->capturing = FALSE; + g_mutex_unlock (camera->capture_mutex); + } +} + /** * gst_camera_bin_create_elements: * @param camera: the #GstCameraBin @@ -265,6 +285,8 @@ gst_camera_bin_create_elements (GstCameraBin * camera) vf = gst_element_factory_make ("viewfinderbin", "vf-bin"); camera->src = gst_object_ref (src); + camera->src_mode_notify_id = g_signal_connect (src, "notify::mode", + (GCallback) gst_camera_bin_src_notify_mode, camera); vid_queue = gst_element_factory_make ("queue", "video-queue"); img_queue = gst_element_factory_make ("queue", "image-queue"); diff --git a/gst/camerabin2/gstcamerabin2.h b/gst/camerabin2/gstcamerabin2.h index f87b34ce8b..c0c1981a09 100644 --- a/gst/camerabin2/gstcamerabin2.h +++ b/gst/camerabin2/gstcamerabin2.h @@ -38,6 +38,7 @@ struct _GstCameraBin GstPipeline pipeline; GstElement *src; + gulong src_mode_notify_id; /* concurrency control */ GMutex *capture_mutex; From bd89d22da93388b952669ba5e9e1f21a7b443e56 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Tue, 30 Nov 2010 09:28:50 -0300 Subject: [PATCH 060/448] camerabin2: Update v4l2camerasrc to use start/stop signals Removes the old logic for v4l2camerasrc that used the mode property switching to start/stop captures to make it identical to camerabin2 behavior and to allow the future addition of pausing a video recording. This also removes the MODE_PREVIEW as it became useless. --- gst/camerabin2/gstcamerabin-enum.c | 2 +- gst/camerabin2/gstcamerabin-enum.h | 8 +- gst/camerabin2/gstcamerabin2.c | 46 +------- gst/camerabin2/gstcamerabin2.h | 5 - gst/camerabin2/gstv4l2camerasrc.c | 178 +++++++++++++++++++---------- gst/camerabin2/gstv4l2camerasrc.h | 9 ++ 6 files changed, 134 insertions(+), 114 deletions(-) diff --git a/gst/camerabin2/gstcamerabin-enum.c b/gst/camerabin2/gstcamerabin-enum.c index ac80d0b0a3..bf13890855 100644 --- a/gst/camerabin2/gstcamerabin-enum.c +++ b/gst/camerabin2/gstcamerabin-enum.c @@ -66,7 +66,7 @@ gst_camerabin_mode_get_type (void) if (gtype == 0) { static const GEnumValue values[] = { - {MODE_PREVIEW, "Preview mode (should be default?)", "mode-preview"}, + /* {MODE_PREVIEW, "Preview mode (should be default?)", "mode-preview"}, */ {MODE_IMAGE, "Still image capture (default)", "mode-image"}, {MODE_VIDEO, "Video recording", "mode-video"}, {0, NULL, NULL} diff --git a/gst/camerabin2/gstcamerabin-enum.h b/gst/camerabin2/gstcamerabin-enum.h index cd1707dd2e..b7957fb9ac 100644 --- a/gst/camerabin2/gstcamerabin-enum.h +++ b/gst/camerabin2/gstcamerabin-enum.h @@ -113,7 +113,6 @@ GType gst_camerabin_flags_get_type (void); /** * GstCameraBinMode: - * @MODE_PREVIEW: preview only (no capture) mode * @MODE_IMAGE: image capture * @MODE_VIDEO: video capture * @@ -121,12 +120,7 @@ GType gst_camerabin_flags_get_type (void); */ typedef enum { - /* note: changed to align with 'capture-mode' property (even though - * I have no idea where this property comes from..) But it somehow - * seems more logical for preview to be mode==0 even if it is an ABI - * break.. - */ - MODE_PREVIEW = 0, + /* MODE_PREVIEW = 0, No use for this */ MODE_IMAGE = 1, MODE_VIDEO = 2, } GstCameraBinMode; diff --git a/gst/camerabin2/gstcamerabin2.c b/gst/camerabin2/gstcamerabin2.c index bfead866f6..9029b5d722 100644 --- a/gst/camerabin2/gstcamerabin2.c +++ b/gst/camerabin2/gstcamerabin2.c @@ -108,35 +108,25 @@ static void gst_camera_bin_start_capture (GstCameraBin * camerabin) { GST_DEBUG_OBJECT (camerabin, "Received start-capture"); - g_mutex_lock (camerabin->capture_mutex); - if (!camerabin->capturing) { - GST_INFO_OBJECT (camerabin, "Starting capture, mode: %d", camerabin->mode); - g_object_set (camerabin->src, "mode", camerabin->mode, NULL); - camerabin->capturing = TRUE; - } else { - GST_WARNING_OBJECT (camerabin, "Capture already ongoing"); - } - g_mutex_unlock (camerabin->capture_mutex); + g_signal_emit_by_name (camerabin->src, "start-capture", NULL); } static void gst_camera_bin_stop_capture (GstCameraBin * camerabin) { - /* TODO do we need a lock here? it is just an if */ - if (camerabin->capturing) { - /* Capturing is cleaned on the notify function because it works - * both for images and videos */ - g_object_set (camerabin->src, "mode", MODE_PREVIEW, NULL); - } + g_signal_emit_by_name (camerabin->src, "stop-capture", NULL); } static void gst_camera_bin_change_mode (GstCameraBin * camerabin, gint mode) { + if (mode == camerabin->mode) + return; + /* stop any ongoing capture */ gst_camera_bin_stop_capture (camerabin); - camerabin->mode = mode; + g_object_set (camerabin->src, "mode", mode, NULL); } static void @@ -144,12 +134,9 @@ gst_camera_bin_dispose (GObject * object) { GstCameraBin *camerabin = GST_CAMERA_BIN_CAST (object); - if (camerabin->src_mode_notify_id) - g_signal_handler_disconnect (camerabin->src, camerabin->src_mode_notify_id); if (camerabin->src) gst_object_unref (camerabin->src); - g_mutex_free (camerabin->capture_mutex); G_OBJECT_CLASS (parent_class)->dispose (object); } @@ -228,28 +215,9 @@ gst_camera_bin_class_init (GstCameraBinClass * klass) static void gst_camera_bin_init (GstCameraBin * camerabin) { - camerabin->capturing = FALSE; - camerabin->capture_mutex = g_mutex_new (); camerabin->mode = MODE_IMAGE; } -static void -gst_camera_bin_src_notify_mode (GObject * src, GParamSpec * pspec, - gpointer data) -{ - GstCameraBin *camera = GST_CAMERA_BIN_CAST (data); - gint mode; - - g_object_get (src, "mode", &mode, NULL); - - if (mode == MODE_PREVIEW) { - g_mutex_lock (camera->capture_mutex); - g_assert (camera->capturing); - camera->capturing = FALSE; - g_mutex_unlock (camera->capture_mutex); - } -} - /** * gst_camera_bin_create_elements: * @param camera: the #GstCameraBin @@ -285,8 +253,6 @@ gst_camera_bin_create_elements (GstCameraBin * camera) vf = gst_element_factory_make ("viewfinderbin", "vf-bin"); camera->src = gst_object_ref (src); - camera->src_mode_notify_id = g_signal_connect (src, "notify::mode", - (GCallback) gst_camera_bin_src_notify_mode, camera); vid_queue = gst_element_factory_make ("queue", "video-queue"); img_queue = gst_element_factory_make ("queue", "image-queue"); diff --git a/gst/camerabin2/gstcamerabin2.h b/gst/camerabin2/gstcamerabin2.h index c0c1981a09..beafd4cd34 100644 --- a/gst/camerabin2/gstcamerabin2.h +++ b/gst/camerabin2/gstcamerabin2.h @@ -38,11 +38,6 @@ struct _GstCameraBin GstPipeline pipeline; GstElement *src; - gulong src_mode_notify_id; - - /* concurrency control */ - GMutex *capture_mutex; - gboolean capturing; /* properties */ gint mode; diff --git a/gst/camerabin2/gstv4l2camerasrc.c b/gst/camerabin2/gstv4l2camerasrc.c index 1b245e6be8..13fa13fc0b 100644 --- a/gst/camerabin2/gstv4l2camerasrc.c +++ b/gst/camerabin2/gstv4l2camerasrc.c @@ -35,6 +35,15 @@ #include "camerabingeneral.h" #include "gstcamerabin-enum.h" +enum +{ + /* action signals */ + START_CAPTURE_SIGNAL, + STOP_CAPTURE_SIGNAL, + /* emit signals */ + IMG_DONE_SIGNAL, + LAST_SIGNAL +}; #define CAMERABIN_DEFAULT_VF_CAPS "video/x-raw-yuv,format=(fourcc)I420" @@ -44,6 +53,8 @@ GST_DEBUG_CATEGORY (v4l2_camera_src_debug); #define GST_CAT_DEFAULT v4l2_camera_src_debug +static guint v4l2camerasrc_signals[LAST_SIGNAL]; + GST_BOILERPLATE (GstV4l2CameraSrc, gst_v4l2_camera_src, GstBaseCameraSrc, GST_TYPE_BASE_CAMERA_SRC); @@ -53,6 +64,9 @@ static void set_capsfilter_caps (GstV4l2CameraSrc * self, GstCaps * new_caps); static void gst_v4l2_camera_src_dispose (GObject * object) { + GstV4l2CameraSrc *src = GST_V4L2_CAMERA_SRC (object); + + g_mutex_free (src->capturing_mutex); G_OBJECT_CLASS (parent_class)->dispose (object); } @@ -147,14 +161,17 @@ gst_v4l2_camera_src_imgsrc_probe (GstPad * pad, GstBuffer * buffer, gpointer data) { GstV4l2CameraSrc *self = GST_V4L2_CAMERA_SRC (data); - gboolean ret; - GST_DEBUG_OBJECT (self, "pass buffer: %d", self->mode == MODE_IMAGE); + gboolean ret = FALSE; - ret = self->mode == MODE_IMAGE; - if (ret) { - self->mode = MODE_PREVIEW; - g_object_notify (G_OBJECT (self), "mode"); + GST_DEBUG_OBJECT (self, "pass buffer: %d", self->mode == MODE_IMAGE); + g_mutex_lock (self->capturing_mutex); + if (self->image_capture_count > 0) { + ret = TRUE; + self->image_capture_count--; + if (self->image_capture_count == 0) + self->capturing = FALSE; } + g_mutex_unlock (self->capturing_mutex); return ret; } @@ -170,33 +187,29 @@ gst_v4l2_camera_src_vidsrc_probe (GstPad * pad, GstBuffer * buffer, GstV4l2CameraSrc *self = GST_V4L2_CAMERA_SRC (data); gboolean ret = FALSE; - GST_DEBUG_OBJECT (self, "pass buffer: %d", self->mode == MODE_VIDEO); - /* TODO do we want to lock for every buffer? */ /* * Note that we can use gst_pad_push_event here because we are a buffer * probe. */ - if (self->mode == MODE_VIDEO) { - GST_OBJECT_LOCK (self); - if (self->video_rec_status == GST_VIDEO_RECORDING_STATUS_STARTING) { - /* send the newseg */ - gst_pad_push_event (pad, gst_event_new_new_segment (FALSE, 1.0, - GST_FORMAT_TIME, GST_BUFFER_TIMESTAMP (buffer), -1, 0)); - self->video_rec_status = GST_VIDEO_RECORDING_STATUS_RUNNING; - ret = TRUE; - } else if (self->video_rec_status == GST_VIDEO_RECORDING_STATUS_FINISHING) { - /* send eos */ - gst_pad_push_event (pad, gst_event_new_eos ()); - self->video_rec_status = GST_VIDEO_RECORDING_STATUS_DONE; - self->mode = MODE_PREVIEW; - g_object_notify (G_OBJECT (self), "mode"); - } else { - ret = TRUE; - } - GST_OBJECT_UNLOCK (self); + g_mutex_lock (self->capturing_mutex); + if (self->video_rec_status == GST_VIDEO_RECORDING_STATUS_DONE) { + /* NOP */ + } else if (self->video_rec_status == GST_VIDEO_RECORDING_STATUS_STARTING) { + /* send the newseg */ + gst_pad_push_event (pad, gst_event_new_new_segment (FALSE, 1.0, + GST_FORMAT_TIME, GST_BUFFER_TIMESTAMP (buffer), -1, 0)); + self->video_rec_status = GST_VIDEO_RECORDING_STATUS_RUNNING; + ret = TRUE; + } else if (self->video_rec_status == GST_VIDEO_RECORDING_STATUS_FINISHING) { + /* send eos */ + gst_pad_push_event (pad, gst_event_new_eos ()); + self->video_rec_status = GST_VIDEO_RECORDING_STATUS_DONE; + self->capturing = FALSE; + } else { + ret = TRUE; } - + g_mutex_unlock (self->capturing_mutex); return ret; } @@ -706,7 +719,6 @@ gst_v4l2_camera_src_set_mode (GstBaseCameraSrc * bcamsrc, GstCameraBinMode mode) { GstV4l2CameraSrc *self = GST_V4L2_CAMERA_SRC (bcamsrc); GstPhotography *photography = gst_base_camera_src_get_photography (bcamsrc); - gint ret = TRUE; if (photography) { if (g_object_class_find_property (G_OBJECT_GET_CLASS (photography), @@ -715,34 +727,8 @@ gst_v4l2_camera_src_set_mode (GstBaseCameraSrc * bcamsrc, GstCameraBinMode mode) } } - switch (mode) { - case MODE_PREVIEW: - if (self->mode == MODE_VIDEO) { - GST_OBJECT_LOCK (self); - if (self->video_rec_status == GST_VIDEO_RECORDING_STATUS_STARTING) - self->video_rec_status = GST_VIDEO_RECORDING_STATUS_DONE; - else if (self->video_rec_status == GST_VIDEO_RECORDING_STATUS_RUNNING) - self->video_rec_status = GST_VIDEO_RECORDING_STATUS_FINISHING; - GST_OBJECT_UNLOCK (self); - } - break; - case MODE_IMAGE: - ret = start_image_capture (GST_V4L2_CAMERA_SRC (bcamsrc)); - break; - case MODE_VIDEO: - GST_OBJECT_LOCK (self); - if (self->video_rec_status == GST_VIDEO_RECORDING_STATUS_DONE) - self->video_rec_status = GST_VIDEO_RECORDING_STATUS_STARTING; - GST_OBJECT_UNLOCK (self); - break; - default: - g_assert_not_reached (); - ret = FALSE; - } - - if (ret) - self->mode = mode; - return ret; + self->mode = mode; + return TRUE; } static gboolean @@ -1051,6 +1037,56 @@ gst_v4l2_camera_src_finish_image_capture (GstBaseCameraSrc * bcamsrc) } } +static void +gst_v4l2_camera_src_start_capture (GstV4l2CameraSrc * src) +{ + g_mutex_lock (src->capturing_mutex); + if (src->capturing) { + GST_WARNING_OBJECT (src, "Capturing already ongoing"); + g_mutex_unlock (src->capturing_mutex); + return; + } + + src->capturing = TRUE; + if (src->mode == MODE_IMAGE) { + src->image_capture_count = 1; + start_image_capture (src); + } else if (src->mode == MODE_VIDEO) { + if (src->video_rec_status == GST_VIDEO_RECORDING_STATUS_DONE) { + src->video_rec_status = GST_VIDEO_RECORDING_STATUS_STARTING; + } + } else { + g_assert_not_reached (); + src->capturing = FALSE; + } + g_mutex_unlock (src->capturing_mutex); +} + +static void +gst_v4l2_camera_src_stop_capture (GstV4l2CameraSrc * src) +{ + g_mutex_lock (src->capturing_mutex); + if (!src->capturing) { + GST_DEBUG_OBJECT (src, "No ongoing capture"); + g_mutex_unlock (src->capturing_mutex); + return; + } + if (src->mode == MODE_VIDEO) { + if (src->video_rec_status == GST_VIDEO_RECORDING_STATUS_STARTING) { + GST_DEBUG_OBJECT (src, "Aborting not started recording"); + src->video_rec_status = GST_VIDEO_RECORDING_STATUS_DONE; + + } else if (src->video_rec_status == GST_VIDEO_RECORDING_STATUS_RUNNING) { + GST_DEBUG_OBJECT (src, "Marking video recording as finishing"); + src->video_rec_status = GST_VIDEO_RECORDING_STATUS_FINISHING; + } + } else { + src->image_capture_count = 0; + src->capturing = FALSE; + } + g_mutex_unlock (src->capturing_mutex); +} + static void gst_v4l2_camera_src_base_init (gpointer g_class) { @@ -1078,14 +1114,31 @@ gst_v4l2_camera_src_class_init (GstV4l2CameraSrcClass * klass) gobject_class->set_property = gst_v4l2_camera_src_set_property; gobject_class->get_property = gst_v4l2_camera_src_get_property; - // g_object_class_install_property .... + /* g_object_class_install_property .... */ g_object_class_install_property (gobject_class, ARG_MODE, g_param_spec_enum ("mode", "Mode", - "The capture mode (still image capture, video recording or " - "viewfinder)", - GST_TYPE_CAMERABIN_MODE, MODE_PREVIEW, + "The capture mode (still image capture or video recording)", + GST_TYPE_CAMERABIN_MODE, MODE_IMAGE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /* Signals */ + v4l2camerasrc_signals[START_CAPTURE_SIGNAL] = + g_signal_new ("start-capture", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (GstV4l2CameraSrcClass, start_capture), + NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + + v4l2camerasrc_signals[STOP_CAPTURE_SIGNAL] = + g_signal_new ("stop-capture", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (GstV4l2CameraSrcClass, stop_capture), + NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + + klass->start_capture = gst_v4l2_camera_src_start_capture; + klass->stop_capture = gst_v4l2_camera_src_stop_capture; + gstbasecamerasrc_class->construct_pipeline = gst_v4l2_camera_src_construct_pipeline; gstbasecamerasrc_class->setup_pipeline = gst_v4l2_camera_src_setup_pipeline; @@ -1102,8 +1155,11 @@ gst_v4l2_camera_src_init (GstV4l2CameraSrc * self, GstV4l2CameraSrcClass * klass) { /* TODO where are variables reset? */ - self->mode = MODE_PREVIEW; + self->mode = MODE_IMAGE; + self->image_capture_count = 0; self->video_rec_status = GST_VIDEO_RECORDING_STATUS_DONE; + self->capturing_mutex = g_mutex_new (); + self->capturing = FALSE; } gboolean diff --git a/gst/camerabin2/gstv4l2camerasrc.h b/gst/camerabin2/gstv4l2camerasrc.h index e4863bb913..cd1a8fe257 100644 --- a/gst/camerabin2/gstv4l2camerasrc.h +++ b/gst/camerabin2/gstv4l2camerasrc.h @@ -59,9 +59,15 @@ struct _GstV4l2CameraSrc GstCameraBinMode mode; + gboolean capturing; + GMutex *capturing_mutex; + /* video recording controls */ gint video_rec_status; + /* image capture controls */ + gint image_capture_count; + /* source elements */ GstElement *src_vid_src; GstElement *src_filter; @@ -104,6 +110,9 @@ struct _GstV4l2CameraSrc struct _GstV4l2CameraSrcClass { GstBaseCameraSrcClass parent; + + void (*start_capture) (GstV4l2CameraSrc * src); + void (*stop_capture) (GstV4l2CameraSrc * src); }; gboolean gst_v4l2_camera_src_plugin_init (GstPlugin * plugin); From 5be441adff6459ce2567751ec438156babc68782 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Tue, 30 Nov 2010 11:06:33 -0300 Subject: [PATCH 061/448] v4l2camerasrc: Add ready-for-capture property Adds property that informs if v4l2camerasrc is available for starting a new capture. It is useful for applications to know (via deep-notify) when the property changes and a new capture is possible. Note, however, that starting a new capture from the notify callback will cause a deadlock. --- gst/camerabin2/gstcamerabin-enum.h | 1 + gst/camerabin2/gstv4l2camerasrc.c | 27 ++++++++++++++++++++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/gst/camerabin2/gstcamerabin-enum.h b/gst/camerabin2/gstcamerabin-enum.h index b7957fb9ac..436263c15f 100644 --- a/gst/camerabin2/gstcamerabin-enum.h +++ b/gst/camerabin2/gstcamerabin-enum.h @@ -31,6 +31,7 @@ enum ARG_0, ARG_FILENAME, ARG_MODE, + ARG_READY_FOR_CAPTURE, ARG_FLAGS, ARG_MUTE, ARG_ZOOM, diff --git a/gst/camerabin2/gstv4l2camerasrc.c b/gst/camerabin2/gstv4l2camerasrc.c index 13fa13fc0b..4b100e7a85 100644 --- a/gst/camerabin2/gstv4l2camerasrc.c +++ b/gst/camerabin2/gstv4l2camerasrc.c @@ -133,6 +133,9 @@ gst_v4l2_camera_src_get_property (GObject * object, case ARG_MODE: g_value_set_enum (value, self->mode); break; + case ARG_READY_FOR_CAPTURE: + g_value_set_boolean (value, !self->capturing); + break; case ARG_FILTER_CAPS: gst_value_set_caps (value, self->view_finder_caps); break; @@ -168,8 +171,10 @@ gst_v4l2_camera_src_imgsrc_probe (GstPad * pad, GstBuffer * buffer, if (self->image_capture_count > 0) { ret = TRUE; self->image_capture_count--; - if (self->image_capture_count == 0) + if (self->image_capture_count == 0) { self->capturing = FALSE; + g_object_notify (G_OBJECT (self), "ready-for-capture"); + } } g_mutex_unlock (self->capturing_mutex); return ret; @@ -206,6 +211,7 @@ gst_v4l2_camera_src_vidsrc_probe (GstPad * pad, GstBuffer * buffer, gst_pad_push_event (pad, gst_event_new_eos ()); self->video_rec_status = GST_VIDEO_RECORDING_STATUS_DONE; self->capturing = FALSE; + g_object_notify (G_OBJECT (self), "ready-for-capture"); } else { ret = TRUE; } @@ -1059,6 +1065,8 @@ gst_v4l2_camera_src_start_capture (GstV4l2CameraSrc * src) g_assert_not_reached (); src->capturing = FALSE; } + if (src->capturing) + g_object_notify (G_OBJECT (src), "ready-for-capture"); g_mutex_unlock (src->capturing_mutex); } @@ -1083,6 +1091,7 @@ gst_v4l2_camera_src_stop_capture (GstV4l2CameraSrc * src) } else { src->image_capture_count = 0; src->capturing = FALSE; + g_object_notify (G_OBJECT (src), "ready-for-capture"); } g_mutex_unlock (src->capturing_mutex); } @@ -1121,6 +1130,22 @@ gst_v4l2_camera_src_class_init (GstV4l2CameraSrcClass * klass) GST_TYPE_CAMERABIN_MODE, MODE_IMAGE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** + * GstV4l2CameraSrc:ready-for-capture: + * + * When TRUE new capture can be prepared. If FALSE capturing is ongoing + * and starting a new capture immediately is not possible. + * + * Note that calling start-capture from the notify callback of this property + * will cause a deadlock. If you need to react like this on the notify + * function, please schedule a new thread to do it. If you're using glib's + * mainloop you can use g_idle_add() for example. + */ + g_object_class_install_property (gobject_class, ARG_READY_FOR_CAPTURE, + g_param_spec_boolean ("ready-for-capture", "Ready for capture", + "Informs this element is ready for starting another capture", + TRUE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + /* Signals */ v4l2camerasrc_signals[START_CAPTURE_SIGNAL] = g_signal_new ("start-capture", From 0ae8df431212bc90985fdf1b50745b68c53df5a6 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Tue, 30 Nov 2010 11:40:18 -0300 Subject: [PATCH 062/448] camerabin2: Keep it under --enable-experimental camerabin2 is still under heavy development, activate it only if the --enable-experimental flag is on. Also add a note to the docs. --- configure.ac | 5 +++-- gst/camerabin2/gstcamerabin2.c | 7 +++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index c8aab6f994..3beb627c47 100644 --- a/configure.ac +++ b/configure.ac @@ -358,8 +358,9 @@ if test "x$HAVE_CPU_I386" != "xyes" && test "x$HAVE_CPU_X86_64" != "xyes"; then fi dnl disable experimental plug-ins -dnl if test "x$BUILD_EXPERIMENTAL" != "xyes"; then -dnl fi +if test "x$BUILD_EXPERIMENTAL" != "xyes"; then + AG_GST_DISABLE_PLUGIN(camerabin2) +fi # This will always succeed because we depend on GLib >= 2.16 PKG_CHECK_MODULES(GIO, gio-2.0 >= 2.16, HAVE_GIO=yes, HAVE_GIO=no) diff --git a/gst/camerabin2/gstcamerabin2.c b/gst/camerabin2/gstcamerabin2.c index 9029b5d722..c967a1c45e 100644 --- a/gst/camerabin2/gstcamerabin2.c +++ b/gst/camerabin2/gstcamerabin2.c @@ -17,9 +17,12 @@ * Boston, MA 02111-1307, USA. */ /** - * SECTION:element-gstcamerabin + * SECTION:element-gstcamerabin2 * - * The gstcamerabin element does FIXME stuff. + * The gstcamerabin2 element does FIXME stuff. + * + * Note that camerabin2 is still UNSTABLE, EXPERIMENTAL and under heavy + * development. */ #ifdef HAVE_CONFIG_H From cb915196e2882a68dc8435791d78c3a7dfa330a3 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Tue, 30 Nov 2010 18:19:20 -0300 Subject: [PATCH 063/448] camerabin2: Handle vidbin state change individually Keep vidbin state locked to avoid it going to playing without being used and leaving an empty file created. Check the docs on the code for details on the handling. --- gst/camerabin2/gstcamerabin2.c | 58 ++++++++++++++++++++++++++++++++++ gst/camerabin2/gstcamerabin2.h | 3 ++ 2 files changed, 61 insertions(+) diff --git a/gst/camerabin2/gstcamerabin2.c b/gst/camerabin2/gstcamerabin2.c index c967a1c45e..a127622e35 100644 --- a/gst/camerabin2/gstcamerabin2.c +++ b/gst/camerabin2/gstcamerabin2.c @@ -25,6 +25,26 @@ * development. */ +/* + * Detail Topics: + * + * videorecordingbin state management (for now on vidbin) + * - The problem: keeping vidbin state in sync with camerabin will make it + * go to playing when it might not be used, causing its internal + * filesink to open a file that might be left blank. + * - The solution: vidbin state is set to locked upon its creation and camerabin + * registers itself on the notify::ready-for-capture of the src. + * Whenever the src readyness goes to FALSE it means a new + * capture is starting. If we are on video mode, the vidbin's + * state is set to NULL and then PLAYING (in between this we + * have room to set the destination filename). + * There is no problem to leave it on playing after an EOS, so + * no action is taken on stop-capture. + * - TODO: What happens when an error pops? + * + * + */ + #ifdef HAVE_CONFIG_H #include "config.h" #endif @@ -132,14 +152,37 @@ gst_camera_bin_change_mode (GstCameraBin * camerabin, gint mode) g_object_set (camerabin->src, "mode", mode, NULL); } +static void +gst_camera_bin_src_notify_readyforcapture (GObject * obj, GParamSpec * pspec, + gpointer user_data) +{ + GstCameraBin *camera = GST_CAMERA_BIN_CAST (user_data); + gboolean ready; + + if (camera->mode == MODE_VIDEO) { + g_object_get (camera->src, "ready-for-capture", &ready, NULL); + if (!ready) { + /* a video recording is about to start, we reset the videobin */ + gst_element_set_state (camera->vidbin, GST_STATE_NULL); + gst_element_set_state (camera->vidbin, GST_STATE_PLAYING); + } + } +} + static void gst_camera_bin_dispose (GObject * object) { GstCameraBin *camerabin = GST_CAMERA_BIN_CAST (object); + if (camerabin->src_capture_notify_id) + g_signal_handler_disconnect (camerabin->src, + camerabin->src_capture_notify_id); if (camerabin->src) gst_object_unref (camerabin->src); + if (camerabin->vidbin) + gst_object_unref (camerabin->vidbin); + G_OBJECT_CLASS (parent_class)->dispose (object); } @@ -256,6 +299,7 @@ gst_camera_bin_create_elements (GstCameraBin * camera) vf = gst_element_factory_make ("viewfinderbin", "vf-bin"); camera->src = gst_object_ref (src); + camera->vidbin = gst_object_ref (vid); vid_queue = gst_element_factory_make ("queue", "video-queue"); img_queue = gst_element_factory_make ("queue", "image-queue"); @@ -276,6 +320,20 @@ gst_camera_bin_create_elements (GstCameraBin * camera) gst_element_link_pads (src, "imgsrc", img_queue, "sink"); gst_element_link_pads (src, "vidsrc", vid_queue, "sink"); + /* + * Video can't get into playing as its internal filesink will open + * a file for writing and leave it empty if unused. + * + * Its state is managed using the current mode and the source's + * ready-for-capture notify callback. When we are at video mode and + * the source's ready-for-capture goes to FALSE it means it is + * starting recording, so we should prepare the video bin. + */ + gst_element_set_locked_state (vid, TRUE); + camera->src_capture_notify_id = g_signal_connect (G_OBJECT (src), + "notify::ready-for-capture", + G_CALLBACK (gst_camera_bin_src_notify_readyforcapture), camera); + camera->elements_created = TRUE; return TRUE; } diff --git a/gst/camerabin2/gstcamerabin2.h b/gst/camerabin2/gstcamerabin2.h index beafd4cd34..a859d80f3b 100644 --- a/gst/camerabin2/gstcamerabin2.h +++ b/gst/camerabin2/gstcamerabin2.h @@ -38,6 +38,9 @@ struct _GstCameraBin GstPipeline pipeline; GstElement *src; + gulong src_capture_notify_id; + + GstElement *vidbin; /* properties */ gint mode; From 5b3deecab9d9a2dbb397aec1e7a4f1d70f37ff1b Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Tue, 30 Nov 2010 20:15:47 -0300 Subject: [PATCH 064/448] camerabin2: Fix set/get property function names Add more consistency to the function names by using gst_camera_bin as the other functions. --- gst/camerabin2/gstcamerabin2.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/gst/camerabin2/gstcamerabin2.c b/gst/camerabin2/gstcamerabin2.c index a127622e35..0c0024f41b 100644 --- a/gst/camerabin2/gstcamerabin2.c +++ b/gst/camerabin2/gstcamerabin2.c @@ -115,9 +115,9 @@ gst_camera_bin_get_type (void) } /* GObject class functions */ -static void gst_camerabin_set_property (GObject * object, guint prop_id, +static void gst_camera_bin_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec); -static void gst_camerabin_get_property (GObject * object, guint prop_id, +static void gst_camera_bin_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); /* Element class functions */ @@ -214,8 +214,8 @@ gst_camera_bin_class_init (GstCameraBinClass * klass) object_class->dispose = gst_camera_bin_dispose; object_class->finalize = gst_camera_bin_finalize; - object_class->set_property = gst_camerabin_set_property; - object_class->get_property = gst_camerabin_get_property; + object_class->set_property = gst_camera_bin_set_property; + object_class->get_property = gst_camera_bin_get_property; element_class->change_state = GST_DEBUG_FUNCPTR (gst_camera_bin_change_state); @@ -367,7 +367,7 @@ gst_camera_bin_change_state (GstElement * element, GstStateChange trans) } static void -gst_camerabin_set_property (GObject * object, guint prop_id, +gst_camera_bin_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { GstCameraBin *camera = GST_CAMERA_BIN_CAST (object); @@ -383,7 +383,7 @@ gst_camerabin_set_property (GObject * object, guint prop_id, } static void -gst_camerabin_get_property (GObject * object, guint prop_id, +gst_camera_bin_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { GstCameraBin *camera = GST_CAMERA_BIN_CAST (object); From ba878c95b2fad981fd73dec75203462d35a2ade9 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Tue, 30 Nov 2010 20:13:27 -0300 Subject: [PATCH 065/448] camerabin2: adds location property Adds a location property to enable applications to select the captured files names. Locations are handled just like multifilesink ones Also disables -Wformat-nonliteral to allow to use non-literals on g_strdup_printf on camerabin and generate a sequence of locations for captures. --- configure.ac | 2 +- gst/camerabin2/gstcamerabin2.c | 54 +++++++++++++++++++++++++- gst/camerabin2/gstcamerabin2.h | 5 +++ gst/camerabin2/gstimagecapturebin.c | 56 ++++++++++++++++++++++++++- gst/camerabin2/gstimagecapturebin.h | 4 ++ gst/camerabin2/gstvideorecordingbin.c | 55 +++++++++++++++++++++++++- gst/camerabin2/gstvideorecordingbin.h | 4 ++ 7 files changed, 173 insertions(+), 7 deletions(-) diff --git a/configure.ac b/configure.ac index 3beb627c47..85fc6a3708 100644 --- a/configure.ac +++ b/configure.ac @@ -266,7 +266,7 @@ dnl -Waggregate-return - libexif returns aggregates dnl -Wundef - Windows headers check _MSC_VER unconditionally AG_GST_SET_ERROR_CFLAGS($GST_GIT, [ -Wmissing-declarations -Wmissing-prototypes -Wredundant-decls - -Wwrite-strings -Wformat-nonliteral -Wformat-security -Wold-style-definition + -Wwrite-strings -Wformat-security -Wold-style-definition -Winit-self -Wmissing-include-dirs -Waddress -Wno-multichar -Wnested-externs]) diff --git a/gst/camerabin2/gstcamerabin2.c b/gst/camerabin2/gstcamerabin2.c index 0c0024f41b..a7bd139ae9 100644 --- a/gst/camerabin2/gstcamerabin2.c +++ b/gst/camerabin2/gstcamerabin2.c @@ -60,7 +60,8 @@ GST_DEBUG_CATEGORY_STATIC (gst_camera_bin_debug); enum { PROP_0, - PROP_MODE + PROP_MODE, + PROP_LOCATION }; enum @@ -74,6 +75,8 @@ enum static guint camerabin_signals[LAST_SIGNAL]; #define DEFAULT_MODE MODE_IMAGE +#define DEFAULT_VID_LOCATION "vid_%d" +#define DEFAULT_IMG_LOCATION "img_%d" /******************************** * Standard GObject boilerplate * @@ -162,8 +165,13 @@ gst_camera_bin_src_notify_readyforcapture (GObject * obj, GParamSpec * pspec, if (camera->mode == MODE_VIDEO) { g_object_get (camera->src, "ready-for-capture", &ready, NULL); if (!ready) { + gchar *location; + /* a video recording is about to start, we reset the videobin */ gst_element_set_state (camera->vidbin, GST_STATE_NULL); + location = g_strdup_printf (camera->vid_location, camera->vid_index++); + g_object_set (camera->vidbin, "location", location, NULL); + g_free (location); gst_element_set_state (camera->vidbin, GST_STATE_PLAYING); } } @@ -174,6 +182,9 @@ gst_camera_bin_dispose (GObject * object) { GstCameraBin *camerabin = GST_CAMERA_BIN_CAST (object); + g_free (camerabin->img_location); + g_free (camerabin->vid_location); + if (camerabin->src_capture_notify_id) g_signal_handler_disconnect (camerabin->src, camerabin->src_capture_notify_id); @@ -183,6 +194,9 @@ gst_camera_bin_dispose (GObject * object) if (camerabin->vidbin) gst_object_unref (camerabin->vidbin); + if (camerabin->imgbin) + gst_object_unref (camerabin->imgbin); + G_OBJECT_CLASS (parent_class)->dispose (object); } @@ -233,6 +247,13 @@ gst_camera_bin_class_init (GstCameraBinClass * klass) GST_TYPE_CAMERABIN_MODE, DEFAULT_MODE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (object_class, PROP_LOCATION, + g_param_spec_string ("location", "Location", + "Location to save the captured files. A %d might be used on the" + "filename as a placeholder for a numeric index of the capture." + "Default for images is img_%d and vid_%d for videos", + DEFAULT_IMG_LOCATION, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** * GstCameraBin::capture-start: * @camera: the camera bin element @@ -261,7 +282,9 @@ gst_camera_bin_class_init (GstCameraBinClass * klass) static void gst_camera_bin_init (GstCameraBin * camerabin) { - camerabin->mode = MODE_IMAGE; + camerabin->mode = DEFAULT_MODE; + camerabin->vid_location = g_strdup (DEFAULT_VID_LOCATION); + camerabin->img_location = g_strdup (DEFAULT_IMG_LOCATION); } /** @@ -300,6 +323,7 @@ gst_camera_bin_create_elements (GstCameraBin * camera) camera->src = gst_object_ref (src); camera->vidbin = gst_object_ref (vid); + camera->imgbin = gst_object_ref (img); vid_queue = gst_element_factory_make ("queue", "video-queue"); img_queue = gst_element_factory_make ("queue", "image-queue"); @@ -334,6 +358,9 @@ gst_camera_bin_create_elements (GstCameraBin * camera) "notify::ready-for-capture", G_CALLBACK (gst_camera_bin_src_notify_readyforcapture), camera); + g_object_set (vid, "location", camera->vid_location, NULL); + g_object_set (img, "location", camera->img_location, NULL); + camera->elements_created = TRUE; return TRUE; } @@ -366,6 +393,19 @@ gst_camera_bin_change_state (GstElement * element, GstStateChange trans) return ret; } +static void +gst_camera_bin_set_location (GstCameraBin * camera, const gchar * location) +{ + if (camera->mode == MODE_IMAGE) { + g_object_set (camera->imgbin, "location", location, NULL); + g_free (camera->img_location); + camera->img_location = g_strdup (location); + } else { + g_free (camera->vid_location); + camera->vid_location = g_strdup (location); + } +} + static void gst_camera_bin_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) @@ -376,6 +416,9 @@ gst_camera_bin_set_property (GObject * object, guint prop_id, case PROP_MODE: gst_camera_bin_change_mode (camera, g_value_get_enum (value)); break; + case PROP_LOCATION: + gst_camera_bin_set_location (camera, g_value_get_string (value)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -392,6 +435,13 @@ gst_camera_bin_get_property (GObject * object, guint prop_id, case PROP_MODE: g_value_set_enum (value, camera->mode); break; + case PROP_LOCATION: + if (camera->mode == MODE_VIDEO) { + g_value_set_string (value, camera->vid_location); + } else { + g_value_set_string (value, camera->img_location); + } + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; diff --git a/gst/camerabin2/gstcamerabin2.h b/gst/camerabin2/gstcamerabin2.h index a859d80f3b..247e186092 100644 --- a/gst/camerabin2/gstcamerabin2.h +++ b/gst/camerabin2/gstcamerabin2.h @@ -41,9 +41,14 @@ struct _GstCameraBin gulong src_capture_notify_id; GstElement *vidbin; + GstElement *imgbin; + + gint vid_index; /* properties */ gint mode; + gchar *vid_location; + gchar *img_location; gboolean elements_created; }; diff --git a/gst/camerabin2/gstimagecapturebin.c b/gst/camerabin2/gstimagecapturebin.c index 242172aafe..df253d06be 100644 --- a/gst/camerabin2/gstimagecapturebin.c +++ b/gst/camerabin2/gstimagecapturebin.c @@ -41,9 +41,12 @@ enum { - PROP_0 + PROP_0, + PROP_LOCATION }; +#define DEFAULT_LOCATION "img_%d" + /* pad templates */ static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", @@ -61,6 +64,41 @@ GST_BOILERPLATE (GstImageCaptureBin, gst_image_capture_bin, GstBin, static GstStateChangeReturn gst_image_capture_bin_change_state (GstElement * element, GstStateChange trans); +static void +gst_image_capture_bin_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstImageCaptureBin *imgbin = GST_IMAGE_CAPTURE_BIN_CAST (object); + + switch (prop_id) { + case PROP_LOCATION: + imgbin->location = g_value_dup_string (value); + if (imgbin->sink) { + g_object_set (imgbin, "location", imgbin->location, NULL); + } + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_image_capture_bin_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstImageCaptureBin *imgbin = GST_IMAGE_CAPTURE_BIN_CAST (object); + + switch (prop_id) { + case PROP_LOCATION: + g_value_set_string (value, imgbin->location); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + static void gst_image_capture_bin_base_init (gpointer g_class) { @@ -77,12 +115,23 @@ gst_image_capture_bin_base_init (gpointer g_class) static void gst_image_capture_bin_class_init (GstImageCaptureBinClass * klass) { + GObjectClass *gobject_class; GstElementClass *element_class; + gobject_class = G_OBJECT_CLASS (klass); element_class = GST_ELEMENT_CLASS (klass); + gobject_class->set_property = gst_image_capture_bin_set_property; + gobject_class->get_property = gst_image_capture_bin_get_property; + element_class->change_state = GST_DEBUG_FUNCPTR (gst_image_capture_bin_change_state); + + g_object_class_install_property (gobject_class, PROP_LOCATION, + g_param_spec_string ("location", "Location", + "Location to save the captured files. A %%d can be used as a " + "placeholder for a capture count", + DEFAULT_LOCATION, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); } static void @@ -94,6 +143,8 @@ gst_image_capture_bin_init (GstImageCaptureBin * image_capturebin, gst_static_pad_template_get (&sink_template)); gst_element_add_pad (GST_ELEMENT_CAST (image_capturebin), image_capturebin->ghostpad); + + image_capturebin->location = g_strdup (DEFAULT_LOCATION); } static gboolean @@ -125,7 +176,8 @@ gst_image_capture_bin_create_elements (GstImageCaptureBin * icbin) if (!sink) goto error; - g_object_set (sink, "location", "cap_%03d.jpg", "async", FALSE, NULL); + icbin->sink = gst_object_ref (sink); + g_object_set (sink, "location", icbin->location, "async", FALSE, NULL); /* add and link */ gst_bin_add_many (GST_BIN_CAST (icbin), csp, enc, mux, sink, NULL); diff --git a/gst/camerabin2/gstimagecapturebin.h b/gst/camerabin2/gstimagecapturebin.h index b1f5f168d2..912dec0992 100644 --- a/gst/camerabin2/gstimagecapturebin.h +++ b/gst/camerabin2/gstimagecapturebin.h @@ -38,6 +38,10 @@ struct _GstImageCaptureBin GstBin bin; GstPad *ghostpad; + GstElement *sink; + + /* props */ + gchar *location; gboolean elements_created; }; diff --git a/gst/camerabin2/gstvideorecordingbin.c b/gst/camerabin2/gstvideorecordingbin.c index f4c423d82e..d1753e0a36 100644 --- a/gst/camerabin2/gstvideorecordingbin.c +++ b/gst/camerabin2/gstvideorecordingbin.c @@ -41,9 +41,12 @@ enum { - PROP_0 + PROP_0, + PROP_LOCATION }; +#define DEFAULT_LOCATION "vidcap" + /* pad templates */ static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", @@ -62,6 +65,41 @@ static GstStateChangeReturn gst_video_recording_bin_change_state (GstElement * element, GstStateChange trans); +static void +gst_video_recording_bin_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstVideoRecordingBin *vidbin = GST_VIDEO_RECORDING_BIN_CAST (object); + + switch (prop_id) { + case PROP_LOCATION: + vidbin->location = g_value_dup_string (value); + if (vidbin->sink) { + g_object_set (vidbin, "location", vidbin->location, NULL); + } + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_video_recording_bin_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstVideoRecordingBin *vidbin = GST_VIDEO_RECORDING_BIN_CAST (object); + + switch (prop_id) { + case PROP_LOCATION: + g_value_set_string (value, vidbin->location); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + static void gst_video_recording_bin_base_init (gpointer g_class) { @@ -78,12 +116,22 @@ gst_video_recording_bin_base_init (gpointer g_class) static void gst_video_recording_bin_class_init (GstVideoRecordingBinClass * klass) { + GObjectClass *gobject_class; GstElementClass *element_class; + gobject_class = G_OBJECT_CLASS (klass); element_class = GST_ELEMENT_CLASS (klass); + gobject_class->set_property = gst_video_recording_bin_set_property; + gobject_class->get_property = gst_video_recording_bin_get_property; + element_class->change_state = GST_DEBUG_FUNCPTR (gst_video_recording_bin_change_state); + + g_object_class_install_property (gobject_class, PROP_LOCATION, + g_param_spec_string ("location", "Location", + "Location to save the captured files.", + DEFAULT_LOCATION, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); } static void @@ -95,6 +143,8 @@ gst_video_recording_bin_init (GstVideoRecordingBin * video_recordingbin, gst_static_pad_template_get (&sink_template)); gst_element_add_pad (GST_ELEMENT_CAST (video_recordingbin), video_recordingbin->ghostpad); + + video_recordingbin->location = g_strdup (DEFAULT_LOCATION); } static gboolean @@ -126,7 +176,8 @@ gst_video_recording_bin_create_elements (GstVideoRecordingBin * vrbin) if (!sink) goto error; - g_object_set (sink, "location", "cap.ogg", "async", FALSE, NULL); + vrbin->sink = gst_object_ref (sink); + g_object_set (sink, "location", vrbin->location, "async", FALSE, NULL); /* add and link */ gst_bin_add_many (GST_BIN_CAST (vrbin), csp, enc, mux, sink, NULL); diff --git a/gst/camerabin2/gstvideorecordingbin.h b/gst/camerabin2/gstvideorecordingbin.h index 88651fad56..cf4de898ff 100644 --- a/gst/camerabin2/gstvideorecordingbin.h +++ b/gst/camerabin2/gstvideorecordingbin.h @@ -38,6 +38,10 @@ struct _GstVideoRecordingBin GstBin bin; GstPad *ghostpad; + GstElement *sink; + + /* props */ + gchar *location; gboolean elements_created; }; From 19e52f35ee7a05738499a83cf4ce08252ff3fa57 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Thu, 2 Dec 2010 00:19:05 -0300 Subject: [PATCH 066/448] camerabin2: remove unused code General cleanup, removing unused bits --- gst/camerabin2/gstcamerabin-enum.c | 39 ------------------------------ gst/camerabin2/gstcamerabin-enum.h | 32 ------------------------ 2 files changed, 71 deletions(-) diff --git a/gst/camerabin2/gstcamerabin-enum.c b/gst/camerabin2/gstcamerabin-enum.c index bf13890855..ba09dcf3ee 100644 --- a/gst/camerabin2/gstcamerabin-enum.c +++ b/gst/camerabin2/gstcamerabin-enum.c @@ -20,45 +20,6 @@ #include "gstcamerabin-enum.h" -#define C_FLAGS(v) ((guint) v) - -static void -register_gst_camerabin_flags (GType * id) -{ - static const GFlagsValue values[] = { - {C_FLAGS (GST_CAMERABIN_FLAG_SOURCE_RESIZE), - "Enable source crop and scale", "source-resize"}, - {C_FLAGS (GST_CAMERABIN_FLAG_SOURCE_COLOR_CONVERSION), - "Enable colorspace conversion for video source", - "source-colorspace-conversion"}, - {C_FLAGS (GST_CAMERABIN_FLAG_VIEWFINDER_COLOR_CONVERSION), - "Enable colorspace conversion for viewfinder", - "viewfinder-colorspace-conversion"}, - {C_FLAGS (GST_CAMERABIN_FLAG_VIEWFINDER_SCALE), - "Enable scale for viewfinder", "viewfinder-scale"}, - {C_FLAGS (GST_CAMERABIN_FLAG_AUDIO_CONVERSION), - "Enable audio conversion for video capture", "audio-conversion"}, - {C_FLAGS (GST_CAMERABIN_FLAG_DISABLE_AUDIO), - "Disable audio elements for video capture", "disable-audio"}, - {C_FLAGS (GST_CAMERABIN_FLAG_IMAGE_COLOR_CONVERSION), - "Enable colorspace conversion for still image", - "image-colorspace-conversion"}, - {0, NULL, NULL} - }; - *id = g_flags_register_static ("GstCameraBinFlags", values); -} - -GType -gst_camerabin_flags_get_type (void) -{ - static GType id; - static GOnce once = G_ONCE_INIT; - - g_once (&once, (GThreadFunc) register_gst_camerabin_flags, &id); - return id; -} - - GType gst_camerabin_mode_get_type (void) { diff --git a/gst/camerabin2/gstcamerabin-enum.h b/gst/camerabin2/gstcamerabin-enum.h index 436263c15f..299e05c7b0 100644 --- a/gst/camerabin2/gstcamerabin-enum.h +++ b/gst/camerabin2/gstcamerabin-enum.h @@ -80,38 +80,6 @@ enum #define DEFAULT_ZOOM MIN_ZOOM -/** - * GstCameraBinFlags: - * @GST_CAMERABIN_FLAG_SOURCE_RESIZE: enable video crop and scale - * after capture - * @GST_CAMERABIN_FLAG_SOURCE_COLOR_CONVERSION: enable conversion - * of native video format by enabling ffmpegcolorspace - * @GST_CAMERABIN_FLAG_VIEWFINDER_COLOR_CONVERSION: enable color - * conversion for viewfinder element - * @GST_CAMERABIN_FLAG_VIEWFINDER_SCALE: enable scaling in - * viewfinder element retaining aspect ratio - * @GST_CAMERABIN_FLAG_AUDIO_CONVERSION: enable audioconvert and - * audioresample elements - * @GST_CAMERABIN_FLAG_DISABLE_AUDIO: disable audio elements - * @GST_CAMERABIN_FLAG_IMAGE_COLOR_CONVERSION: enable color - * conversion for image output element - * - * Extra flags to configure the behaviour of the sinks. - */ -typedef enum { - GST_CAMERABIN_FLAG_SOURCE_RESIZE = (1 << 0), - GST_CAMERABIN_FLAG_SOURCE_COLOR_CONVERSION = (1 << 1), - GST_CAMERABIN_FLAG_VIEWFINDER_COLOR_CONVERSION = (1 << 2), - GST_CAMERABIN_FLAG_VIEWFINDER_SCALE = (1 << 3), - GST_CAMERABIN_FLAG_AUDIO_CONVERSION = (1 << 4), - GST_CAMERABIN_FLAG_DISABLE_AUDIO = (1 << 5), - GST_CAMERABIN_FLAG_IMAGE_COLOR_CONVERSION = (1 << 6) -} GstCameraBinFlags; - -#define GST_TYPE_CAMERABIN_FLAGS (gst_camerabin_flags_get_type()) -GType gst_camerabin_flags_get_type (void); - - /** * GstCameraBinMode: * @MODE_IMAGE: image capture From 0685b8921e45032baa63912ff5e0b3deee6757e1 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Thu, 2 Dec 2010 01:33:19 -0300 Subject: [PATCH 067/448] viewfinderbin: Improve elements creation Be more careful with cleanup of elements. Also add some logs and improve docs a little. --- gst/camerabin2/gstviewfinderbin.c | 33 ++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/gst/camerabin2/gstviewfinderbin.c b/gst/camerabin2/gstviewfinderbin.c index 5d92526ad4..1910bbbd83 100644 --- a/gst/camerabin2/gstviewfinderbin.c +++ b/gst/camerabin2/gstviewfinderbin.c @@ -19,14 +19,14 @@ /** * SECTION:element-gstviewfinderbin * - * The gstviewfinderbin element does FIXME stuff. + * The gstviewfinderbin element is a displaying element for camerabin2. * * * Example launch line * |[ * gst-launch -v videotestsrc ! viewfinderbin * ]| - * FIXME Describe what the pipeline does. + * Feeds the viewfinderbin with video test data. * */ @@ -36,6 +36,9 @@ #include "gstviewfinderbin.h" +GST_DEBUG_CATEGORY_STATIC (gst_viewfinder_bin_debug); +#define GST_CAT_DEFAULT gst_viewfinder_bin_debug + /* prototypes */ @@ -97,10 +100,13 @@ gst_viewfinder_bin_init (GstViewfinderBin * viewfinderbin, static gboolean gst_viewfinder_bin_create_elements (GstViewfinderBin * vfbin) { - GstElement *csp; - GstElement *videoscale; - GstElement *sink; + GstElement *csp = NULL; + GstElement *videoscale = NULL; + GstElement *sink = NULL; GstPad *pad = NULL; + gboolean added = FALSE; + + GST_DEBUG_OBJECT (vfbin, "Creating internal elements"); if (vfbin->elements_created) return TRUE; @@ -118,8 +124,11 @@ gst_viewfinder_bin_create_elements (GstViewfinderBin * vfbin) if (!sink) goto error; + GST_DEBUG_OBJECT (vfbin, "Internal elements created, proceding to linking"); + /* add and link */ gst_bin_add_many (GST_BIN_CAST (vfbin), csp, videoscale, sink, NULL); + added = TRUE; if (!gst_element_link_many (csp, videoscale, sink, NULL)) goto error; @@ -129,11 +138,23 @@ gst_viewfinder_bin_create_elements (GstViewfinderBin * vfbin) goto error; vfbin->elements_created = TRUE; + GST_DEBUG_OBJECT (vfbin, "Elements succesfully created and linked"); return TRUE; error: + GST_WARNING_OBJECT (vfbin, "Creating internal elements failed"); if (pad) gst_object_unref (pad); + if (!added) { + if (csp) + gst_object_unref (csp); + if (videoscale) + gst_object_unref (videoscale); + if (sink) + gst_object_unref (sink); + } else { + gst_bin_remove_many (GST_BIN_CAST (vfbin), csp, videoscale, sink, NULL); + } return FALSE; } @@ -168,6 +189,8 @@ gst_viewfinder_bin_change_state (GstElement * element, GstStateChange trans) gboolean gst_viewfinder_bin_plugin_init (GstPlugin * plugin) { + GST_DEBUG_CATEGORY_INIT (gst_viewfinder_bin_debug, "viewfinderbin", 0, + "ViewFinderBin"); return gst_element_register (plugin, "viewfinderbin", GST_RANK_NONE, gst_viewfinder_bin_get_type ()); } From c7bdfa86af7e7be1bdd63e390ed959be327bd62e Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Thu, 2 Dec 2010 02:21:49 -0300 Subject: [PATCH 068/448] tests: camerabin2: adds tests for elements Adds basic tests for both imagecapturebin and for videorecordingbin elements --- tests/check/Makefile.am | 2 + tests/check/elements/.gitignore | 2 + tests/check/elements/imagecapturebin.c | 133 +++++++++++++++++++++++ tests/check/elements/videorecordingbin.c | 125 +++++++++++++++++++++ 4 files changed, 262 insertions(+) create mode 100644 tests/check/elements/imagecapturebin.c create mode 100644 tests/check/elements/videorecordingbin.c diff --git a/tests/check/Makefile.am b/tests/check/Makefile.am index 695af11895..f664924af7 100644 --- a/tests/check/Makefile.am +++ b/tests/check/Makefile.am @@ -150,6 +150,7 @@ check_PROGRAMS = \ elements/camerabin \ elements/dataurisrc \ elements/flacparse \ + elements/imagecapturebin \ elements/legacyresample \ $(check_jifmux) \ elements/jpegparse \ @@ -164,6 +165,7 @@ check_PROGRAMS = \ elements/rtpmux \ $(check_schro) \ elements/valve \ + elements/videorecordingbin \ $(check_vp8) \ $(check_zbar) \ $(check_orc) \ diff --git a/tests/check/elements/.gitignore b/tests/check/elements/.gitignore index 7c1133db48..175b0bea08 100644 --- a/tests/check/elements/.gitignore +++ b/tests/check/elements/.gitignore @@ -14,6 +14,7 @@ flacparse gdpdepay gdppay id3mux +imagecapturebin interleave jifmux jpegparse @@ -36,6 +37,7 @@ spectrum timidity y4menc valve +videorecordingbin vp8dec vp8enc zbar diff --git a/tests/check/elements/imagecapturebin.c b/tests/check/elements/imagecapturebin.c new file mode 100644 index 0000000000..860e3f5aa7 --- /dev/null +++ b/tests/check/elements/imagecapturebin.c @@ -0,0 +1,133 @@ +/* GStreamer unit test for the imagecapturebin element + * Copyright (C) 2010 Thiago Santos + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#define N_BUFFERS 3 + +typedef struct +{ + GstElement *pipe; + GstElement *src; + GstElement *icbin; +} GstImageCaptureBinTestContext; + +static void +gstimagecapturebin_init_test_context (GstImageCaptureBinTestContext * ctx, + gint num_buffers) +{ + fail_unless (ctx != NULL); + + ctx->pipe = gst_pipeline_new ("pipeline"); + fail_unless (ctx->pipe != NULL); + ctx->src = gst_element_factory_make ("videotestsrc", "src"); + fail_unless (ctx->src != NULL, "Failed to create videotestsrc element"); + ctx->icbin = gst_element_factory_make ("imagecapturebin", "icbin"); + fail_unless (ctx->icbin != NULL, "Failed to create imagecapturebin element"); + + if (num_buffers > 0) + g_object_set (ctx->src, "num-buffers", num_buffers, NULL); + + fail_unless (gst_bin_add (GST_BIN (ctx->pipe), ctx->src)); + fail_unless (gst_bin_add (GST_BIN (ctx->pipe), ctx->icbin)); + fail_unless (gst_element_link (ctx->src, ctx->icbin)); +} + +static void +gstimagecapturebin_unset_test_context (GstImageCaptureBinTestContext * ctx) +{ + gst_element_set_state (ctx->pipe, GST_STATE_NULL); + gst_object_unref (ctx->pipe); + memset (ctx, 0, sizeof (GstImageCaptureBinTestContext)); +} + +static gchar * +make_test_file_name (void) +{ + return g_strdup_printf ("%s" G_DIR_SEPARATOR_S + "imagecapturbintest_%%d.cap", g_get_tmp_dir ()); +} + +GST_START_TEST (test_simple_capture) +{ + GstImageCaptureBinTestContext ctx; + GstBus *bus; + GstMessage *msg; + gchar *test_file_name; + gint i; + + gstimagecapturebin_init_test_context (&ctx, N_BUFFERS); + bus = gst_element_get_bus (ctx.pipe); + + test_file_name = make_test_file_name (); + g_object_set (ctx.icbin, "location", test_file_name, NULL); + + fail_if (gst_element_set_state (ctx.pipe, GST_STATE_PLAYING) == + GST_STATE_CHANGE_FAILURE); + + msg = gst_bus_timed_pop_filtered (bus, GST_SECOND * 10, + GST_MESSAGE_EOS | GST_MESSAGE_ERROR); + fail_unless (msg != NULL); + fail_unless (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_EOS); + + /* check there are N_BUFFERS files */ + for (i = 0; i < N_BUFFERS; i++) { + gchar *filename; + FILE *f; + + filename = g_strdup_printf (test_file_name, i); + + fail_unless (g_file_test (filename, G_FILE_TEST_EXISTS)); + fail_unless (g_file_test (filename, G_FILE_TEST_IS_REGULAR)); + fail_if (g_file_test (filename, G_FILE_TEST_IS_SYMLINK)); + + /* check the file isn't empty */ + f = fopen (filename, "r"); + fseek (f, 0, SEEK_END); + fail_unless (ftell (f) > 0); + fclose (f); + + g_free (filename); + } + + gstimagecapturebin_unset_test_context (&ctx); + gst_object_unref (bus); + g_free (test_file_name); +} + +GST_END_TEST; + +static Suite * +imagecapturebin_suite (void) +{ + Suite *s = suite_create ("imagecapturebin"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_simple_capture); + + return s; +} + +GST_CHECK_MAIN (imagecapturebin); diff --git a/tests/check/elements/videorecordingbin.c b/tests/check/elements/videorecordingbin.c new file mode 100644 index 0000000000..c002e3d8e9 --- /dev/null +++ b/tests/check/elements/videorecordingbin.c @@ -0,0 +1,125 @@ +/* GStreamer unit test for the videorecordingbin element + * Copyright (C) 2010 Thiago Santos + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#define N_BUFFERS 100 + +typedef struct +{ + GstElement *pipe; + GstElement *src; + GstElement *vrbin; +} GstVideoRecordingBinTestContext; + +static void +gstvideorecordingbin_init_test_context (GstVideoRecordingBinTestContext * ctx, + gint num_buffers) +{ + fail_unless (ctx != NULL); + + ctx->pipe = gst_pipeline_new ("pipeline"); + fail_unless (ctx->pipe != NULL); + ctx->src = gst_element_factory_make ("videotestsrc", "src"); + fail_unless (ctx->src != NULL, "Failed to create videotestsrc element"); + ctx->vrbin = gst_element_factory_make ("videorecordingbin", "icbin"); + fail_unless (ctx->vrbin != NULL, + "Failed to create videorecordingbin element"); + + if (num_buffers > 0) + g_object_set (ctx->src, "num-buffers", num_buffers, NULL); + + fail_unless (gst_bin_add (GST_BIN (ctx->pipe), ctx->src)); + fail_unless (gst_bin_add (GST_BIN (ctx->pipe), ctx->vrbin)); + fail_unless (gst_element_link (ctx->src, ctx->vrbin)); +} + +static void +gstvideorecordingbin_unset_test_context (GstVideoRecordingBinTestContext * ctx) +{ + gst_element_set_state (ctx->pipe, GST_STATE_NULL); + gst_object_unref (ctx->pipe); + memset (ctx, 0, sizeof (GstVideoRecordingBinTestContext)); +} + +static gchar * +make_test_file_name (gint num) +{ + return g_strdup_printf ("%s" G_DIR_SEPARATOR_S + "videorecordingbintest_%d.cap", g_get_tmp_dir (), num); +} + +GST_START_TEST (test_simple_recording) +{ + GstVideoRecordingBinTestContext ctx; + GstBus *bus; + GstMessage *msg; + gchar *test_file_name; + FILE *f; + + gstvideorecordingbin_init_test_context (&ctx, N_BUFFERS); + bus = gst_element_get_bus (ctx.pipe); + + test_file_name = make_test_file_name (0); + g_object_set (ctx.vrbin, "location", test_file_name, NULL); + + fail_if (gst_element_set_state (ctx.pipe, GST_STATE_PLAYING) == + GST_STATE_CHANGE_FAILURE); + + msg = gst_bus_timed_pop_filtered (bus, GST_SECOND * 10, + GST_MESSAGE_EOS | GST_MESSAGE_ERROR); + fail_unless (msg != NULL); + fail_unless (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_EOS); + + /* check there is a recorded file */ + fail_unless (g_file_test (test_file_name, G_FILE_TEST_EXISTS)); + fail_unless (g_file_test (test_file_name, G_FILE_TEST_IS_REGULAR)); + fail_if (g_file_test (test_file_name, G_FILE_TEST_IS_SYMLINK)); + + /* check the file isn't empty */ + f = fopen (test_file_name, "r"); + fseek (f, 0, SEEK_END); + fail_unless (ftell (f) > 0); + fclose (f); + + gstvideorecordingbin_unset_test_context (&ctx); + gst_object_unref (bus); + g_free (test_file_name); +} + +GST_END_TEST; + +static Suite * +videorecordingbin_suite (void) +{ + Suite *s = suite_create ("videorecordingbin"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_simple_recording); + + return s; +} + +GST_CHECK_MAIN (videorecordingbin); From fb497590c71fbf5bb03950b44b85a75195490c97 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Thu, 2 Dec 2010 03:08:52 -0300 Subject: [PATCH 069/448] camerabin2: Adding tests for camerabin2 Adds some basic tests for camerabin2 --- tests/check/Makefile.am | 3 +- tests/check/elements/camerabin2.c | 314 ++++++++++++++++++++++++++++++ 2 files changed, 316 insertions(+), 1 deletion(-) create mode 100644 tests/check/elements/camerabin2.c diff --git a/tests/check/Makefile.am b/tests/check/Makefile.am index f664924af7..e045129cbd 100644 --- a/tests/check/Makefile.am +++ b/tests/check/Makefile.am @@ -14,7 +14,7 @@ TESTS_ENVIRONMENT = \ GST_PLUGIN_SYSTEM_PATH= \ GST_PLUGIN_PATH=$(top_builddir)/gst:$(top_builddir)/sys:$(top_builddir)/ext:$(GST_PLUGINS_FFMPEG_DIR):$(GST_PLUGINS_UGLY_DIR):$(GST_PLUGINS_GOOD_DIR):$(GST_PLUGINS_BASE_DIR):$(GST_PLUGINS_DIR) \ GST_PLUGIN_LOADING_WHITELIST="gstreamer@$(GST_PLUGINS_DIR):gst-plugins-base@$(GSTPB_PLUGINS_DIR):gst-plugins-good:gst-plugins-ugly:gst-ffmpeg:gst-plugins-bad@$(top_builddir)" \ - GST_STATE_IGNORE_ELEMENTS="apexsink camerabin cdaudio dc1394src dccpclientsrc dccpclientsink dccpserversrc dccpserversink dvbsrc dvbbasebin dfbvideosink festival gsettingsvideosrc gsettingsvideosink gsettingsaudiosrc gsettingsaudiosink nassink rsndvdbin sdlaudiosink sdlvideosink vcdsrc rfbsrc vdpauyuvvideo vdpauvideoyuv vdpaumpegdec neonhttpsrc" + GST_STATE_IGNORE_ELEMENTS="apexsink camerabin camerabin2 cdaudio dc1394src dccpclientsrc dccpclientsink dccpserversrc dccpserversink dvbsrc dvbbasebin dfbvideosink festival gsettingsvideosrc gsettingsvideosink gsettingsaudiosrc gsettingsaudiosink nassink rsndvdbin sdlaudiosink sdlvideosink vcdsrc rfbsrc vdpauyuvvideo vdpauvideoyuv vdpaumpegdec neonhttpsrc" plugindir = $(libdir)/gstreamer-@GST_MAJORMINOR@ @@ -148,6 +148,7 @@ check_PROGRAMS = \ elements/autoconvert \ elements/asfmux \ elements/camerabin \ + elements/camerabin2 \ elements/dataurisrc \ elements/flacparse \ elements/imagecapturebin \ diff --git a/tests/check/elements/camerabin2.c b/tests/check/elements/camerabin2.c new file mode 100644 index 0000000000..d6f44051c6 --- /dev/null +++ b/tests/check/elements/camerabin2.c @@ -0,0 +1,314 @@ +/* GStreamer + * + * unit test for camerabin2 basic operations + * Copyright (C) 2010 Nokia Corporation + * Copyright (C) 2010 Thiago Santos + * + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include +#include + +#define IMAGE_FILENAME "image" +#define VIDEO_FILENAME "video" +#define CAPTURE_COUNT 3 +#define VIDEO_DURATION 5 + +static GstElement *camera; +static GMainLoop *main_loop; + +/* helper function for filenames */ +static const gchar * +make_test_file_name (const gchar * base_name, gint num) +{ + static gchar file_name[1000]; + + g_snprintf (file_name, 999, "%s" G_DIR_SEPARATOR_S + "gstcamerabin2test_%s_%03d.cap", g_get_tmp_dir (), base_name, num); + + GST_INFO ("capturing to: %s", file_name); + return file_name; +} + +/* configuration */ + +static gboolean +capture_bus_cb (GstBus * bus, GstMessage * message, gpointer data) +{ + GMainLoop *loop = (GMainLoop *) data; + const GstStructure *st; + + switch (GST_MESSAGE_TYPE (message)) { + case GST_MESSAGE_ERROR:{ + GError *err = NULL; + gchar *debug = NULL; + + gst_message_parse_error (message, &err, &debug); + GST_WARNING ("ERROR: %s [%s]", err->message, debug); + g_error_free (err); + g_free (debug); + /* Write debug graph to file */ + GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (camera), + GST_DEBUG_GRAPH_SHOW_ALL, "camerabin.error"); + + fail_if (TRUE, "error while capturing"); + g_main_loop_quit (loop); + break; + } + case GST_MESSAGE_WARNING:{ + GError *err = NULL; + gchar *debug = NULL; + + gst_message_parse_warning (message, &err, &debug); + GST_WARNING ("WARNING: %s [%s]", err->message, debug); + g_error_free (err); + g_free (debug); + /* Write debug graph to file */ + GST_DEBUG_BIN_TO_DOT_FILE_WITH_TS (GST_BIN (camera), + GST_DEBUG_GRAPH_SHOW_ALL, "camerabin.warning"); + break; + } + case GST_MESSAGE_EOS: + GST_DEBUG ("eos"); + g_main_loop_quit (loop); + break; + default: + st = gst_message_get_structure (message); + if (st && gst_structure_has_name (st, "image-captured")) { + gboolean ready = FALSE; + GST_INFO ("image captured"); + g_object_get (camera, "ready-for-capture", &ready, NULL); + fail_if (!ready, "not ready for capture"); + } + break; + } + return TRUE; +} + +static void +setup (void) +{ + GstBus *bus; + + GST_INFO ("init"); + + main_loop = g_main_loop_new (NULL, TRUE); + + camera = gst_check_setup_element ("camerabin2"); + + bus = gst_pipeline_get_bus (GST_PIPELINE (camera)); + gst_bus_add_watch (bus, (GstBusFunc) capture_bus_cb, main_loop); + gst_object_unref (bus); + + GST_INFO ("init finished"); +} + +static void +teardown (void) +{ + gst_element_set_state (camera, GST_STATE_NULL); + + if (camera) + gst_check_teardown_element (camera); + + GST_INFO ("done"); +} + +static gboolean +validity_bus_cb (GstBus * bus, GstMessage * message, gpointer data) +{ + GMainLoop *loop = (GMainLoop *) data; + switch (GST_MESSAGE_TYPE (message)) { + case GST_MESSAGE_ERROR: + fail_if (TRUE, "validating captured data failed"); + g_main_loop_quit (loop); + break; + case GST_MESSAGE_EOS: + g_main_loop_quit (loop); + GST_DEBUG ("eos"); + break; + default: + break; + } + return TRUE; +} + +/* Validate captured files by playing them with playbin + * and checking that no errors occur. */ +static gboolean +check_file_validity (const gchar * filename, gint num, GstTagList * taglist) +{ + GstBus *bus; + GMainLoop *loop = g_main_loop_new (NULL, FALSE); + GstElement *playbin = gst_element_factory_make ("playbin2", NULL); + GstElement *fakevideo = gst_element_factory_make ("fakesink", NULL); + GstElement *fakeaudio = gst_element_factory_make ("fakesink", NULL); + gchar *uri = g_strconcat ("file://", make_test_file_name (filename, num), + NULL); + + GST_DEBUG ("checking uri: %s", uri); + g_object_set (G_OBJECT (playbin), "uri", uri, "video-sink", fakevideo, + "audio-sink", fakeaudio, NULL); + + bus = gst_pipeline_get_bus (GST_PIPELINE (playbin)); + gst_bus_add_watch (bus, (GstBusFunc) validity_bus_cb, loop); + + gst_element_set_state (playbin, GST_STATE_PLAYING); + g_main_loop_run (loop); + gst_element_set_state (playbin, GST_STATE_NULL); + + g_free (uri); + gst_object_unref (bus); + gst_object_unref (playbin); + + return TRUE; +} + +GST_START_TEST (test_single_image_capture) +{ + if (!camera) + return; + + /* set still image mode */ + g_object_set (camera, "mode", 1, + "location", make_test_file_name (IMAGE_FILENAME, 0), NULL); + + if (gst_element_set_state (GST_ELEMENT (camera), GST_STATE_PLAYING) == + GST_STATE_CHANGE_FAILURE) { + GST_WARNING ("setting camerabin to PLAYING failed"); + gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL); + gst_object_unref (camera); + camera = NULL; + } + GST_INFO ("starting capture"); + fail_unless (camera != NULL); + g_signal_emit_by_name (camera, "start-capture", NULL); + + g_usleep (G_USEC_PER_SEC * 3); + + gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL); + check_file_validity (IMAGE_FILENAME, 0, NULL); +} + +GST_END_TEST; + +GST_START_TEST (test_video_recording) +{ + if (!camera) + return; + + /* Set video recording mode */ + g_object_set (camera, "mode", 2, + "location", make_test_file_name (VIDEO_FILENAME, 0), NULL); + + if (gst_element_set_state (GST_ELEMENT (camera), GST_STATE_PLAYING) == + GST_STATE_CHANGE_FAILURE) { + GST_WARNING ("setting camerabin to PLAYING failed"); + gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL); + gst_object_unref (camera); + camera = NULL; + } + + GST_INFO ("starting capture"); + fail_unless (camera != NULL); + g_signal_emit_by_name (camera, "start-capture", NULL); + + /* Record for one seconds */ + g_usleep (VIDEO_DURATION * G_USEC_PER_SEC); + + g_signal_emit_by_name (camera, "stop-capture", NULL); + + gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL); + + check_file_validity (VIDEO_FILENAME, 0, NULL); +} + +GST_END_TEST; + +GST_START_TEST (test_image_video_cycle) +{ + gint i; + + if (!camera) + return; + + /* set filepaths for image and videos */ + g_object_set (camera, "mode", 1, NULL); + g_object_set (camera, "location", make_test_file_name (IMAGE_FILENAME, 0), + NULL); + g_object_set (camera, "mode", 2, NULL); + g_object_set (camera, "location", make_test_file_name (VIDEO_FILENAME, 0), + NULL); + + if (gst_element_set_state (GST_ELEMENT (camera), GST_STATE_PLAYING) == + GST_STATE_CHANGE_FAILURE) { + GST_WARNING ("setting camerabin to PLAYING failed"); + gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL); + gst_object_unref (camera); + camera = NULL; + } + + GST_INFO ("starting capture"); + for (i = 0; i < 2; i++) { + /* take a picture */ + g_object_set (camera, "mode", 1, NULL); + g_signal_emit_by_name (camera, "start-capture", NULL); + g_usleep (G_USEC_PER_SEC * 3); + + /* now go to video */ + g_object_set (camera, "mode", 2, NULL); + g_signal_emit_by_name (camera, "start-capture", NULL); + g_usleep (G_USEC_PER_SEC * 5); + g_signal_emit_by_name (camera, "stop-capture", NULL); + } + gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL); + + /* validate all the files */ + for (i = 0; i < 2; i++) { + check_file_validity (IMAGE_FILENAME, i, NULL); + check_file_validity (VIDEO_FILENAME, i, NULL); + } +} + +GST_END_TEST; + +static Suite * +camerabin_suite (void) +{ + Suite *s = suite_create ("camerabin2"); + TCase *tc_basic = tcase_create ("general"); + + /* Test that basic operations run without errors */ + suite_add_tcase (s, tc_basic); + /* Increase timeout due to video recording */ + tcase_set_timeout (tc_basic, 30); + tcase_add_checked_fixture (tc_basic, setup, teardown); + tcase_add_test (tc_basic, test_single_image_capture); + tcase_add_test (tc_basic, test_video_recording); + tcase_add_test (tc_basic, test_image_video_cycle); + + return s; +} + +GST_CHECK_MAIN (camerabin); From 122a7bd556c90f6bd7af94c0f6a6dec9f289d1a3 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Thu, 2 Dec 2010 03:44:37 -0300 Subject: [PATCH 070/448] camerabin2: Various fixes As video recording bin's state is locked, we should always remember of setting it to NULL when camerabin2 goes to NULL Be more careful when using elements that might not have been created yet And do not set location property recursively on videorecordingbin --- gst/camerabin2/gstcamerabin2.c | 11 ++++++++--- gst/camerabin2/gstvideorecordingbin.c | 2 +- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/gst/camerabin2/gstcamerabin2.c b/gst/camerabin2/gstcamerabin2.c index a7bd139ae9..171c5bf1c2 100644 --- a/gst/camerabin2/gstcamerabin2.c +++ b/gst/camerabin2/gstcamerabin2.c @@ -140,7 +140,8 @@ gst_camera_bin_start_capture (GstCameraBin * camerabin) static void gst_camera_bin_stop_capture (GstCameraBin * camerabin) { - g_signal_emit_by_name (camerabin->src, "stop-capture", NULL); + if (camerabin->src) + g_signal_emit_by_name (camerabin->src, "stop-capture", NULL); } static void @@ -152,7 +153,8 @@ gst_camera_bin_change_mode (GstCameraBin * camerabin, gint mode) /* stop any ongoing capture */ gst_camera_bin_stop_capture (camerabin); camerabin->mode = mode; - g_object_set (camerabin->src, "mode", mode, NULL); + if (camerabin->src) + g_object_set (camerabin->src, "mode", mode, NULL); } static void @@ -358,6 +360,7 @@ gst_camera_bin_create_elements (GstCameraBin * camera) "notify::ready-for-capture", G_CALLBACK (gst_camera_bin_src_notify_readyforcapture), camera); + g_object_set (src, "mode", camera->mode, NULL); g_object_set (vid, "location", camera->vid_location, NULL); g_object_set (img, "location", camera->img_location, NULL); @@ -385,6 +388,7 @@ gst_camera_bin_change_state (GstElement * element, GstStateChange trans) switch (trans) { case GST_STATE_CHANGE_READY_TO_NULL: + gst_element_set_state (camera->vidbin, GST_STATE_NULL); break; default: break; @@ -397,7 +401,8 @@ static void gst_camera_bin_set_location (GstCameraBin * camera, const gchar * location) { if (camera->mode == MODE_IMAGE) { - g_object_set (camera->imgbin, "location", location, NULL); + if (camera->imgbin) + g_object_set (camera->imgbin, "location", location, NULL); g_free (camera->img_location); camera->img_location = g_strdup (location); } else { diff --git a/gst/camerabin2/gstvideorecordingbin.c b/gst/camerabin2/gstvideorecordingbin.c index d1753e0a36..ba78a3e2a3 100644 --- a/gst/camerabin2/gstvideorecordingbin.c +++ b/gst/camerabin2/gstvideorecordingbin.c @@ -75,7 +75,7 @@ gst_video_recording_bin_set_property (GObject * object, guint prop_id, case PROP_LOCATION: vidbin->location = g_value_dup_string (value); if (vidbin->sink) { - g_object_set (vidbin, "location", vidbin->location, NULL); + g_object_set (vidbin->sink, "location", vidbin->location, NULL); } break; default: From 397f7fcceb1766f6d9524fbfaff6bcb352450656 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Fri, 3 Dec 2010 12:11:59 -0300 Subject: [PATCH 071/448] examples: camerabin2: Print more info Add some printing for error/eos cases. --- tests/examples/camerabin2/gst-camera2.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/tests/examples/camerabin2/gst-camera2.c b/tests/examples/camerabin2/gst-camera2.c index b079adc309..68d9b20870 100644 --- a/tests/examples/camerabin2/gst-camera2.c +++ b/tests/examples/camerabin2/gst-camera2.c @@ -120,13 +120,20 @@ bus_callback (GstBus * bus, GstMessage * message, gpointer data) break; } case GST_MESSAGE_ERROR:{ - //print_error_message (message); - //me_gst_cleanup_element (); + GError *err = NULL; + gchar *debug = NULL; + + gst_message_parse_error (message, &err, &debug); + g_print ("Error: %s : %s\n", err->message, debug); + g_error_free (err); + g_free (debug); + gtk_main_quit (); break; } case GST_MESSAGE_EOS: /* end-of-stream */ + g_print ("Eos\n"); gtk_main_quit (); break; case GST_MESSAGE_ELEMENT: From 5776a17c8690eb29e023d1fb7f1c74c0d9b3118d Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Fri, 3 Dec 2010 12:12:32 -0300 Subject: [PATCH 072/448] camerabin2: More debug logs Sprinkle some more debugging logs --- gst/camerabin2/gstcamerabin2.c | 5 +++++ gst/camerabin2/gstv4l2camerasrc.c | 5 +++-- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/gst/camerabin2/gstcamerabin2.c b/gst/camerabin2/gstcamerabin2.c index 171c5bf1c2..cc7358ec08 100644 --- a/gst/camerabin2/gstcamerabin2.c +++ b/gst/camerabin2/gstcamerabin2.c @@ -150,6 +150,8 @@ gst_camera_bin_change_mode (GstCameraBin * camerabin, gint mode) if (mode == camerabin->mode) return; + GST_DEBUG_OBJECT (camerabin, "Changing mode to %d", mode); + /* stop any ongoing capture */ gst_camera_bin_stop_capture (camerabin); camerabin->mode = mode; @@ -172,6 +174,7 @@ gst_camera_bin_src_notify_readyforcapture (GObject * obj, GParamSpec * pspec, /* a video recording is about to start, we reset the videobin */ gst_element_set_state (camera->vidbin, GST_STATE_NULL); location = g_strdup_printf (camera->vid_location, camera->vid_index++); + GST_DEBUG_OBJECT (camera, "Switching vidbin location to %s", location); g_object_set (camera->vidbin, "location", location, NULL); g_free (location); gst_element_set_state (camera->vidbin, GST_STATE_PLAYING); @@ -400,6 +403,8 @@ gst_camera_bin_change_state (GstElement * element, GstStateChange trans) static void gst_camera_bin_set_location (GstCameraBin * camera, const gchar * location) { + GST_DEBUG_OBJECT (camera, "Setting mode %d location to %s", camera->mode, + location); if (camera->mode == MODE_IMAGE) { if (camera->imgbin) g_object_set (camera->imgbin, "location", location, NULL); diff --git a/gst/camerabin2/gstv4l2camerasrc.c b/gst/camerabin2/gstv4l2camerasrc.c index 4b100e7a85..878fa5a3fa 100644 --- a/gst/camerabin2/gstv4l2camerasrc.c +++ b/gst/camerabin2/gstv4l2camerasrc.c @@ -166,7 +166,6 @@ gst_v4l2_camera_src_imgsrc_probe (GstPad * pad, GstBuffer * buffer, GstV4l2CameraSrc *self = GST_V4L2_CAMERA_SRC (data); gboolean ret = FALSE; - GST_DEBUG_OBJECT (self, "pass buffer: %d", self->mode == MODE_IMAGE); g_mutex_lock (self->capturing_mutex); if (self->image_capture_count > 0) { ret = TRUE; @@ -202,12 +201,14 @@ gst_v4l2_camera_src_vidsrc_probe (GstPad * pad, GstBuffer * buffer, /* NOP */ } else if (self->video_rec_status == GST_VIDEO_RECORDING_STATUS_STARTING) { /* send the newseg */ + GST_DEBUG_OBJECT (self, "Starting video recording, pushing newsegment"); gst_pad_push_event (pad, gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME, GST_BUFFER_TIMESTAMP (buffer), -1, 0)); self->video_rec_status = GST_VIDEO_RECORDING_STATUS_RUNNING; ret = TRUE; } else if (self->video_rec_status == GST_VIDEO_RECORDING_STATUS_FINISHING) { /* send eos */ + GST_DEBUG_OBJECT (self, "Finishing video recording, pushing eos"); gst_pad_push_event (pad, gst_event_new_eos ()); self->video_rec_status = GST_VIDEO_RECORDING_STATUS_DONE; self->capturing = FALSE; @@ -1081,7 +1082,7 @@ gst_v4l2_camera_src_stop_capture (GstV4l2CameraSrc * src) } if (src->mode == MODE_VIDEO) { if (src->video_rec_status == GST_VIDEO_RECORDING_STATUS_STARTING) { - GST_DEBUG_OBJECT (src, "Aborting not started recording"); + GST_DEBUG_OBJECT (src, "Aborting, had not started recording"); src->video_rec_status = GST_VIDEO_RECORDING_STATUS_DONE; } else if (src->video_rec_status == GST_VIDEO_RECORDING_STATUS_RUNNING) { From b57405665a4f6440fd17ca94134c86f30aa51f18 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Fri, 3 Dec 2010 12:13:07 -0300 Subject: [PATCH 073/448] camerabin2: Fix tests capture location creation Fixes capture location creation to use multifilesink location like strings. E.g. using capture_%d instead of capture_0 to let camerabin2 handle the %d replacing --- tests/check/elements/camerabin2.c | 34 ++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/tests/check/elements/camerabin2.c b/tests/check/elements/camerabin2.c index d6f44051c6..4c451610cc 100644 --- a/tests/check/elements/camerabin2.c +++ b/tests/check/elements/camerabin2.c @@ -44,8 +44,15 @@ make_test_file_name (const gchar * base_name, gint num) { static gchar file_name[1000]; - g_snprintf (file_name, 999, "%s" G_DIR_SEPARATOR_S - "gstcamerabin2test_%s_%03d.cap", g_get_tmp_dir (), base_name, num); + /* num == -1 means to keep the %d in the resulting string to be used on + * multifilesink like location */ + if (num == -1) { + g_snprintf (file_name, 999, "%s" G_DIR_SEPARATOR_S + "gstcamerabin2test_%s_%%03d.cap", g_get_tmp_dir (), base_name); + } else { + g_snprintf (file_name, 999, "%s" G_DIR_SEPARATOR_S + "gstcamerabin2test_%s_%03d.cap", g_get_tmp_dir (), base_name, num); + } GST_INFO ("capturing to: %s", file_name); return file_name; @@ -140,9 +147,19 @@ validity_bus_cb (GstBus * bus, GstMessage * message, gpointer data) { GMainLoop *loop = (GMainLoop *) data; switch (GST_MESSAGE_TYPE (message)) { - case GST_MESSAGE_ERROR: + case GST_MESSAGE_ERROR:{ + GError *err = NULL; + gchar *debug = NULL; + + gst_message_parse_error (message, &err, &debug); + + GST_ERROR ("Error: %s : %s", err->message, debug); + g_error_free (err); + g_free (debug); + fail_if (TRUE, "validating captured data failed"); g_main_loop_quit (loop); + } break; case GST_MESSAGE_EOS: g_main_loop_quit (loop); @@ -192,7 +209,7 @@ GST_START_TEST (test_single_image_capture) /* set still image mode */ g_object_set (camera, "mode", 1, - "location", make_test_file_name (IMAGE_FILENAME, 0), NULL); + "location", make_test_file_name (IMAGE_FILENAME, -1), NULL); if (gst_element_set_state (GST_ELEMENT (camera), GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) { @@ -220,7 +237,7 @@ GST_START_TEST (test_video_recording) /* Set video recording mode */ g_object_set (camera, "mode", 2, - "location", make_test_file_name (VIDEO_FILENAME, 0), NULL); + "location", make_test_file_name (VIDEO_FILENAME, -1), NULL); if (gst_element_set_state (GST_ELEMENT (camera), GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) { @@ -255,10 +272,10 @@ GST_START_TEST (test_image_video_cycle) /* set filepaths for image and videos */ g_object_set (camera, "mode", 1, NULL); - g_object_set (camera, "location", make_test_file_name (IMAGE_FILENAME, 0), + g_object_set (camera, "location", make_test_file_name (IMAGE_FILENAME, -1), NULL); g_object_set (camera, "mode", 2, NULL); - g_object_set (camera, "location", make_test_file_name (VIDEO_FILENAME, 0), + g_object_set (camera, "location", make_test_file_name (VIDEO_FILENAME, -1), NULL); if (gst_element_set_state (GST_ELEMENT (camera), GST_STATE_PLAYING) == @@ -281,6 +298,9 @@ GST_START_TEST (test_image_video_cycle) g_signal_emit_by_name (camera, "start-capture", NULL); g_usleep (G_USEC_PER_SEC * 5); g_signal_emit_by_name (camera, "stop-capture", NULL); + + /* wait for capture to finish */ + g_usleep (G_USEC_PER_SEC); } gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL); From b11342d325fa68e73bd408e6dd15dd7109c3c45f Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Sat, 4 Dec 2010 00:27:17 -0300 Subject: [PATCH 074/448] camerabin2: Reset all elements on video recording branch before capture We need to reset the elements from the video recording branch, including the queue and capsfilter in order to clear the eos state and activate the pads. This makes it possible to record multiple videos with camerabin2 in a sequence, otherwise the source would get a unexpected return and push EOS, stopping the whole pipeline. --- gst/camerabin2/gstcamerabin2.c | 14 +++++++++++++- gst/camerabin2/gstcamerabin2.h | 3 +++ 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/gst/camerabin2/gstcamerabin2.c b/gst/camerabin2/gstcamerabin2.c index cc7358ec08..0a9c0cd345 100644 --- a/gst/camerabin2/gstcamerabin2.c +++ b/gst/camerabin2/gstcamerabin2.c @@ -171,13 +171,18 @@ gst_camera_bin_src_notify_readyforcapture (GObject * obj, GParamSpec * pspec, if (!ready) { gchar *location; - /* a video recording is about to start, we reset the videobin */ + /* a video recording is about to start, we reset the videobin to clear eos/flushing state + * also need to clean the queue ! capsfilter before it */ gst_element_set_state (camera->vidbin, GST_STATE_NULL); + gst_element_set_state (camera->vid_queue, GST_STATE_NULL); + gst_element_set_state (camera->vid_capsfilter, GST_STATE_NULL); location = g_strdup_printf (camera->vid_location, camera->vid_index++); GST_DEBUG_OBJECT (camera, "Switching vidbin location to %s", location); g_object_set (camera->vidbin, "location", location, NULL); g_free (location); gst_element_set_state (camera->vidbin, GST_STATE_PLAYING); + gst_element_set_state (camera->vid_capsfilter, GST_STATE_PLAYING); + gst_element_set_state (camera->vid_queue, GST_STATE_PLAYING); } } } @@ -198,6 +203,10 @@ gst_camera_bin_dispose (GObject * object) if (camerabin->vidbin) gst_object_unref (camerabin->vidbin); + if (camerabin->vid_queue) + gst_object_unref (camerabin->vid_queue); + if (camerabin->vid_capsfilter) + gst_object_unref (camerabin->vid_capsfilter); if (camerabin->imgbin) gst_object_unref (camerabin->imgbin); @@ -349,6 +358,9 @@ gst_camera_bin_create_elements (GstCameraBin * camera) gst_element_link_pads (src, "imgsrc", img_queue, "sink"); gst_element_link_pads (src, "vidsrc", vid_queue, "sink"); + camera->vid_queue = gst_object_ref (vid_queue); + camera->vid_capsfilter = gst_object_ref (vid_capsfilter); + /* * Video can't get into playing as its internal filesink will open * a file for writing and leave it empty if unused. diff --git a/gst/camerabin2/gstcamerabin2.h b/gst/camerabin2/gstcamerabin2.h index 247e186092..a4c7bb4c9d 100644 --- a/gst/camerabin2/gstcamerabin2.h +++ b/gst/camerabin2/gstcamerabin2.h @@ -41,6 +41,9 @@ struct _GstCameraBin gulong src_capture_notify_id; GstElement *vidbin; + GstElement *vid_queue; + GstElement *vid_capsfilter; + GstElement *imgbin; gint vid_index; From 87eddd54d5479baaca552e1667a4b2028b4f8760 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Sat, 4 Dec 2010 10:15:34 -0300 Subject: [PATCH 075/448] basecamerasrc: Add mode property Move mode property from v4l2camerasrc to basecamerasrc, as all camera sources should handle it. --- gst/camerabin2/gstbasecamerasrc.c | 19 ++++++++++++++++++- gst/camerabin2/gstbasecamerasrc.h | 6 +++++- gst/camerabin2/gstv4l2camerasrc.c | 25 ++++++------------------- gst/camerabin2/gstv4l2camerasrc.h | 2 -- 4 files changed, 29 insertions(+), 23 deletions(-) diff --git a/gst/camerabin2/gstbasecamerasrc.c b/gst/camerabin2/gstbasecamerasrc.c index 57b5ab7c14..fd4dc4b6f7 100644 --- a/gst/camerabin2/gstbasecamerasrc.c +++ b/gst/camerabin2/gstbasecamerasrc.c @@ -125,7 +125,11 @@ gst_base_camera_src_set_mode (GstBaseCameraSrc * self, GstCameraBinMode mode) g_return_val_if_fail (bclass->set_mode, FALSE); - return bclass->set_mode (self, mode); + if (bclass->set_mode (self, mode)) { + self->mode = mode; + return TRUE; + } + return FALSE; } /** @@ -274,6 +278,10 @@ gst_base_camera_src_set_property (GObject * object, GstBaseCameraSrc *self = GST_BASE_CAMERA_SRC (object); switch (prop_id) { + case ARG_MODE: + gst_base_camera_src_set_mode (GST_BASE_CAMERA_SRC (self), + g_value_get_enum (value)); + break; case ARG_ZOOM:{ g_atomic_int_set (&self->zoom, g_value_get_int (value)); /* does not set it if in NULL, the src is not created yet */ @@ -294,6 +302,9 @@ gst_base_camera_src_get_property (GObject * object, GstBaseCameraSrc *self = GST_BASE_CAMERA_SRC (object); switch (prop_id) { + case ARG_MODE: + g_value_set_enum (value, self->mode); + break; case ARG_ZOOM: g_value_set_int (value, g_atomic_int_get (&self->zoom)); break; @@ -414,6 +425,11 @@ gst_base_camera_src_class_init (GstBaseCameraSrcClass * klass) gobject_class->get_property = gst_base_camera_src_get_property; // g_object_class_install_property .... + g_object_class_install_property (gobject_class, ARG_MODE, + g_param_spec_enum ("mode", "Mode", + "The capture mode (still image capture or video recording)", + GST_TYPE_CAMERABIN_MODE, MODE_IMAGE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); gstelement_class->change_state = gst_base_camera_src_change_state; @@ -437,6 +453,7 @@ gst_base_camera_src_init (GstBaseCameraSrc * self, self->zoom = DEFAULT_ZOOM; self->image_capture_width = 0; self->image_capture_height = 0; + self->mode = MODE_IMAGE; self->night_mode = FALSE; diff --git a/gst/camerabin2/gstbasecamerasrc.h b/gst/camerabin2/gstbasecamerasrc.h index 75ef0222ac..2f22d813da 100644 --- a/gst/camerabin2/gstbasecamerasrc.h +++ b/gst/camerabin2/gstbasecamerasrc.h @@ -41,7 +41,9 @@ G_BEGIN_DECLS (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_BASE_CAMERA_SRC)) #define GST_IS_BASE_CAMERA_SRC_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_BASE_CAMERA_SRC)) - GType gst_base_camera_src_get_type (void); +#define GST_BASE_CAMERA_SRC_CAST(obj) \ + ((GstBaseCameraSrc *) (obj)) +GType gst_base_camera_src_get_type (void); typedef struct _GstBaseCameraSrc GstBaseCameraSrc; typedef struct _GstBaseCameraSrcClass GstBaseCameraSrcClass; @@ -58,6 +60,8 @@ struct _GstBaseCameraSrc GstPad *imgsrc; GstPad *vidsrc; + gint mode; + /* XXX preview pads? */ /* Resolution of the buffers configured to camerabin */ diff --git a/gst/camerabin2/gstv4l2camerasrc.c b/gst/camerabin2/gstv4l2camerasrc.c index 878fa5a3fa..00b6a50ab3 100644 --- a/gst/camerabin2/gstv4l2camerasrc.c +++ b/gst/camerabin2/gstv4l2camerasrc.c @@ -83,10 +83,6 @@ gst_v4l2_camera_src_set_property (GObject * object, GstV4l2CameraSrc *self = GST_V4L2_CAMERA_SRC (object); switch (prop_id) { - case ARG_MODE: - gst_base_camera_src_set_mode (GST_BASE_CAMERA_SRC (self), - g_value_get_enum (value)); - break; case ARG_FILTER_CAPS: GST_OBJECT_LOCK (self); gst_caps_replace (&self->view_finder_caps, @@ -130,9 +126,6 @@ gst_v4l2_camera_src_get_property (GObject * object, GstV4l2CameraSrc *self = GST_V4L2_CAMERA_SRC (object); switch (prop_id) { - case ARG_MODE: - g_value_set_enum (value, self->mode); - break; case ARG_READY_FOR_CAPTURE: g_value_set_boolean (value, !self->capturing); break; @@ -724,7 +717,6 @@ start_image_capture (GstV4l2CameraSrc * self) static gboolean gst_v4l2_camera_src_set_mode (GstBaseCameraSrc * bcamsrc, GstCameraBinMode mode) { - GstV4l2CameraSrc *self = GST_V4L2_CAMERA_SRC (bcamsrc); GstPhotography *photography = gst_base_camera_src_get_photography (bcamsrc); if (photography) { @@ -733,8 +725,6 @@ gst_v4l2_camera_src_set_mode (GstBaseCameraSrc * bcamsrc, GstCameraBinMode mode) g_object_set (G_OBJECT (photography), "capture-mode", mode, NULL); } } - - self->mode = mode; return TRUE; } @@ -1047,6 +1037,7 @@ gst_v4l2_camera_src_finish_image_capture (GstBaseCameraSrc * bcamsrc) static void gst_v4l2_camera_src_start_capture (GstV4l2CameraSrc * src) { + GstBaseCameraSrc *camerasrc = GST_BASE_CAMERA_SRC_CAST (src); g_mutex_lock (src->capturing_mutex); if (src->capturing) { GST_WARNING_OBJECT (src, "Capturing already ongoing"); @@ -1055,10 +1046,11 @@ gst_v4l2_camera_src_start_capture (GstV4l2CameraSrc * src) } src->capturing = TRUE; - if (src->mode == MODE_IMAGE) { + /* TODO should we use a macro? */ + if (camerasrc->mode == MODE_IMAGE) { src->image_capture_count = 1; start_image_capture (src); - } else if (src->mode == MODE_VIDEO) { + } else if (camerasrc->mode == MODE_VIDEO) { if (src->video_rec_status == GST_VIDEO_RECORDING_STATUS_DONE) { src->video_rec_status = GST_VIDEO_RECORDING_STATUS_STARTING; } @@ -1074,13 +1066,14 @@ gst_v4l2_camera_src_start_capture (GstV4l2CameraSrc * src) static void gst_v4l2_camera_src_stop_capture (GstV4l2CameraSrc * src) { + GstBaseCameraSrc *camerasrc = GST_BASE_CAMERA_SRC_CAST (src); g_mutex_lock (src->capturing_mutex); if (!src->capturing) { GST_DEBUG_OBJECT (src, "No ongoing capture"); g_mutex_unlock (src->capturing_mutex); return; } - if (src->mode == MODE_VIDEO) { + if (camerasrc->mode == MODE_VIDEO) { if (src->video_rec_status == GST_VIDEO_RECORDING_STATUS_STARTING) { GST_DEBUG_OBJECT (src, "Aborting, had not started recording"); src->video_rec_status = GST_VIDEO_RECORDING_STATUS_DONE; @@ -1125,11 +1118,6 @@ gst_v4l2_camera_src_class_init (GstV4l2CameraSrcClass * klass) gobject_class->get_property = gst_v4l2_camera_src_get_property; /* g_object_class_install_property .... */ - g_object_class_install_property (gobject_class, ARG_MODE, - g_param_spec_enum ("mode", "Mode", - "The capture mode (still image capture or video recording)", - GST_TYPE_CAMERABIN_MODE, MODE_IMAGE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); /** * GstV4l2CameraSrc:ready-for-capture: @@ -1181,7 +1169,6 @@ gst_v4l2_camera_src_init (GstV4l2CameraSrc * self, GstV4l2CameraSrcClass * klass) { /* TODO where are variables reset? */ - self->mode = MODE_IMAGE; self->image_capture_count = 0; self->video_rec_status = GST_VIDEO_RECORDING_STATUS_DONE; self->capturing_mutex = g_mutex_new (); diff --git a/gst/camerabin2/gstv4l2camerasrc.h b/gst/camerabin2/gstv4l2camerasrc.h index cd1a8fe257..e996920fff 100644 --- a/gst/camerabin2/gstv4l2camerasrc.h +++ b/gst/camerabin2/gstv4l2camerasrc.h @@ -57,8 +57,6 @@ struct _GstV4l2CameraSrc { GstBaseCameraSrc parent; - GstCameraBinMode mode; - gboolean capturing; GMutex *capturing_mutex; From 24bc280806235dc3d756750ca0b922c7f7090e39 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Sun, 5 Dec 2010 11:18:09 -0300 Subject: [PATCH 076/448] basecamerasrc: Move start/stop capture signals to basecamerasrc Move start/stop signals and ready-for-capture to basecamerasrc as this should be present on all camera sources --- gst/camerabin2/gstbasecamerasrc.c | 110 +++++++++++++++++++++++++++++- gst/camerabin2/gstbasecamerasrc.h | 12 ++++ gst/camerabin2/gstv4l2camerasrc.c | 109 ++++++----------------------- gst/camerabin2/gstv4l2camerasrc.h | 6 -- 4 files changed, 142 insertions(+), 95 deletions(-) diff --git a/gst/camerabin2/gstbasecamerasrc.c b/gst/camerabin2/gstbasecamerasrc.c index fd4dc4b6f7..87cec67fd8 100644 --- a/gst/camerabin2/gstbasecamerasrc.c +++ b/gst/camerabin2/gstbasecamerasrc.c @@ -34,6 +34,17 @@ #include "gstbasecamerasrc.h" +enum +{ + /* action signals */ + START_CAPTURE_SIGNAL, + STOP_CAPTURE_SIGNAL, + /* emit signals */ + LAST_SIGNAL +}; + +static guint basecamerasrc_signals[LAST_SIGNAL]; + GST_DEBUG_CATEGORY (base_camera_src_debug); #define GST_CAT_DEFAULT base_camera_src_debug @@ -256,12 +267,65 @@ gst_base_camera_src_find_better_framerate (GstBaseCameraSrc * self, return framerate; } +static void +gst_base_camera_src_start_capture (GstBaseCameraSrc * src) +{ + GstBaseCameraSrcClass *klass = GST_BASE_CAMERA_SRC_GET_CLASS (src); + + g_return_if_fail (klass->start_capture != NULL); + + g_mutex_lock (src->capturing_mutex); + if (src->capturing) { + GST_WARNING_OBJECT (src, "Capturing already ongoing"); + g_mutex_unlock (src->capturing_mutex); + return; + } + + if (klass->start_capture (src)) { + src->capturing = TRUE; + g_object_notify (G_OBJECT (src), "ready-for-capture"); + } else { + GST_WARNING_OBJECT (src, "Failed to start capture"); + } + g_mutex_unlock (src->capturing_mutex); +} + +static void +gst_base_camera_src_stop_capture (GstBaseCameraSrc * src) +{ + GstBaseCameraSrcClass *klass = GST_BASE_CAMERA_SRC_GET_CLASS (src); + + g_return_if_fail (klass->stop_capture != NULL); + + g_mutex_lock (src->capturing_mutex); + if (!src->capturing) { + GST_DEBUG_OBJECT (src, "No ongoing capture"); + g_mutex_unlock (src->capturing_mutex); + return; + } + klass->stop_capture (src); + g_mutex_unlock (src->capturing_mutex); +} + +void +gst_base_camera_src_finish_capture (GstBaseCameraSrc * self) +{ + g_return_if_fail (self->capturing); + self->capturing = FALSE; + g_object_notify (G_OBJECT (self), "ready-for-capture"); +} + + /** * */ static void gst_base_camera_src_dispose (GObject * object) { + GstBaseCameraSrc *src = GST_BASE_CAMERA_SRC_CAST (object); + + g_mutex_free (src->capturing_mutex); + G_OBJECT_CLASS (parent_class)->dispose (object); } @@ -305,6 +369,9 @@ gst_base_camera_src_get_property (GObject * object, case ARG_MODE: g_value_set_enum (value, self->mode); break; + case ARG_READY_FOR_CAPTURE: + g_value_set_boolean (value, !self->capturing); + break; case ARG_ZOOM: g_value_set_int (value, g_atomic_int_get (&self->zoom)); break; @@ -431,8 +498,46 @@ gst_base_camera_src_class_init (GstBaseCameraSrcClass * klass) GST_TYPE_CAMERABIN_MODE, MODE_IMAGE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - gstelement_class->change_state = gst_base_camera_src_change_state; + /** + * GstBaseCameraSrc:ready-for-capture: + * + * When TRUE new capture can be prepared. If FALSE capturing is ongoing + * and starting a new capture immediately is not possible. + * + * Note that calling start-capture from the notify callback of this property + * will cause a deadlock. If you need to react like this on the notify + * function, please schedule a new thread to do it. If you're using glib's + * mainloop you can use g_idle_add() for example. + */ + g_object_class_install_property (gobject_class, ARG_READY_FOR_CAPTURE, + g_param_spec_boolean ("ready-for-capture", "Ready for capture", + "Informs this element is ready for starting another capture", + TRUE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + /* Signals */ + basecamerasrc_signals[START_CAPTURE_SIGNAL] = + g_signal_new ("start-capture", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (GstBaseCameraSrcClass, private_start_capture), + NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + + basecamerasrc_signals[STOP_CAPTURE_SIGNAL] = + g_signal_new ("stop-capture", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (GstBaseCameraSrcClass, private_stop_capture), + NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); + + /* TODO these should be moved to a private struct + * that is allocated sequentially to the main struct as said at: + * http://library.gnome.org/devel/gobject/unstable/gobject-Type-Information.html#g-type-add-class-private + */ + klass->private_start_capture = gst_base_camera_src_start_capture; + klass->private_stop_capture = gst_base_camera_src_stop_capture; + + gstelement_class->change_state = gst_base_camera_src_change_state; } static void @@ -459,4 +564,7 @@ gst_base_camera_src_init (GstBaseCameraSrc * self, self->fps_n = DEFAULT_FPS_N; self->fps_d = DEFAULT_FPS_D; + + self->capturing = FALSE; + self->capturing_mutex = g_mutex_new (); } diff --git a/gst/camerabin2/gstbasecamerasrc.h b/gst/camerabin2/gstbasecamerasrc.h index 2f22d813da..8a212b158d 100644 --- a/gst/camerabin2/gstbasecamerasrc.h +++ b/gst/camerabin2/gstbasecamerasrc.h @@ -62,6 +62,9 @@ struct _GstBaseCameraSrc gint mode; + gboolean capturing; + GMutex *capturing_mutex; + /* XXX preview pads? */ /* Resolution of the buffers configured to camerabin */ @@ -127,6 +130,12 @@ struct _GstBaseCameraSrcClass void (*finish_image_capture) (GstBaseCameraSrc * self); + void (*private_start_capture) (GstBaseCameraSrc * src); + void (*private_stop_capture) (GstBaseCameraSrc * src); + gboolean (*start_capture) (GstBaseCameraSrc * src); + void (*stop_capture) (GstBaseCameraSrc * src); + + gpointer _gst_reserved[GST_PADDING_LARGE]; }; @@ -145,6 +154,9 @@ void gst_base_camera_src_finish_image_capture (GstBaseCameraSrc * self); const GValue * gst_base_camera_src_find_better_framerate ( GstBaseCameraSrc * self, GstStructure * st, const GValue * orig_framerate); +void gst_base_camera_src_finish_capture (GstBaseCameraSrc *self); + + // XXX add methods to get/set img capture and vid capture caps.. #endif /* __GST_BASE_CAMERA_SRC_H__ */ diff --git a/gst/camerabin2/gstv4l2camerasrc.c b/gst/camerabin2/gstv4l2camerasrc.c index 00b6a50ab3..a85d83b6ab 100644 --- a/gst/camerabin2/gstv4l2camerasrc.c +++ b/gst/camerabin2/gstv4l2camerasrc.c @@ -35,16 +35,6 @@ #include "camerabingeneral.h" #include "gstcamerabin-enum.h" -enum -{ - /* action signals */ - START_CAPTURE_SIGNAL, - STOP_CAPTURE_SIGNAL, - /* emit signals */ - IMG_DONE_SIGNAL, - LAST_SIGNAL -}; - #define CAMERABIN_DEFAULT_VF_CAPS "video/x-raw-yuv,format=(fourcc)I420" /* Using "bilinear" as default zoom method */ @@ -53,8 +43,6 @@ enum GST_DEBUG_CATEGORY (v4l2_camera_src_debug); #define GST_CAT_DEFAULT v4l2_camera_src_debug -static guint v4l2camerasrc_signals[LAST_SIGNAL]; - GST_BOILERPLATE (GstV4l2CameraSrc, gst_v4l2_camera_src, GstBaseCameraSrc, GST_TYPE_BASE_CAMERA_SRC); @@ -64,9 +52,6 @@ static void set_capsfilter_caps (GstV4l2CameraSrc * self, GstCaps * new_caps); static void gst_v4l2_camera_src_dispose (GObject * object) { - GstV4l2CameraSrc *src = GST_V4L2_CAMERA_SRC (object); - - g_mutex_free (src->capturing_mutex); G_OBJECT_CLASS (parent_class)->dispose (object); } @@ -126,9 +111,6 @@ gst_v4l2_camera_src_get_property (GObject * object, GstV4l2CameraSrc *self = GST_V4L2_CAMERA_SRC (object); switch (prop_id) { - case ARG_READY_FOR_CAPTURE: - g_value_set_boolean (value, !self->capturing); - break; case ARG_FILTER_CAPS: gst_value_set_caps (value, self->view_finder_caps); break; @@ -157,18 +139,18 @@ gst_v4l2_camera_src_imgsrc_probe (GstPad * pad, GstBuffer * buffer, gpointer data) { GstV4l2CameraSrc *self = GST_V4L2_CAMERA_SRC (data); + GstBaseCameraSrc *camerasrc = GST_BASE_CAMERA_SRC (data); gboolean ret = FALSE; - g_mutex_lock (self->capturing_mutex); + g_mutex_lock (camerasrc->capturing_mutex); if (self->image_capture_count > 0) { ret = TRUE; self->image_capture_count--; if (self->image_capture_count == 0) { - self->capturing = FALSE; - g_object_notify (G_OBJECT (self), "ready-for-capture"); + gst_base_camera_src_finish_capture (camerasrc); } } - g_mutex_unlock (self->capturing_mutex); + g_mutex_unlock (camerasrc->capturing_mutex); return ret; } @@ -182,6 +164,7 @@ gst_v4l2_camera_src_vidsrc_probe (GstPad * pad, GstBuffer * buffer, gpointer data) { GstV4l2CameraSrc *self = GST_V4L2_CAMERA_SRC (data); + GstBaseCameraSrc *camerasrc = GST_BASE_CAMERA_SRC_CAST (self); gboolean ret = FALSE; /* TODO do we want to lock for every buffer? */ @@ -189,7 +172,8 @@ gst_v4l2_camera_src_vidsrc_probe (GstPad * pad, GstBuffer * buffer, * Note that we can use gst_pad_push_event here because we are a buffer * probe. */ - g_mutex_lock (self->capturing_mutex); + /* TODO shouldn't access this directly */ + g_mutex_lock (camerasrc->capturing_mutex); if (self->video_rec_status == GST_VIDEO_RECORDING_STATUS_DONE) { /* NOP */ } else if (self->video_rec_status == GST_VIDEO_RECORDING_STATUS_STARTING) { @@ -204,12 +188,11 @@ gst_v4l2_camera_src_vidsrc_probe (GstPad * pad, GstBuffer * buffer, GST_DEBUG_OBJECT (self, "Finishing video recording, pushing eos"); gst_pad_push_event (pad, gst_event_new_eos ()); self->video_rec_status = GST_VIDEO_RECORDING_STATUS_DONE; - self->capturing = FALSE; - g_object_notify (G_OBJECT (self), "ready-for-capture"); + gst_base_camera_src_finish_capture (camerasrc); } else { ret = TRUE; } - g_mutex_unlock (self->capturing_mutex); + g_mutex_unlock (camerasrc->capturing_mutex); return ret; } @@ -1034,19 +1017,12 @@ gst_v4l2_camera_src_finish_image_capture (GstBaseCameraSrc * bcamsrc) } } -static void -gst_v4l2_camera_src_start_capture (GstV4l2CameraSrc * src) +static gboolean +gst_v4l2_camera_src_start_capture (GstBaseCameraSrc * camerasrc) { - GstBaseCameraSrc *camerasrc = GST_BASE_CAMERA_SRC_CAST (src); - g_mutex_lock (src->capturing_mutex); - if (src->capturing) { - GST_WARNING_OBJECT (src, "Capturing already ongoing"); - g_mutex_unlock (src->capturing_mutex); - return; - } + GstV4l2CameraSrc *src = GST_V4L2_CAMERA_SRC (camerasrc); - src->capturing = TRUE; - /* TODO should we use a macro? */ + /* TODO shoud we access this directly? Maybe a macro is better? */ if (camerasrc->mode == MODE_IMAGE) { src->image_capture_count = 1; start_image_capture (src); @@ -1056,23 +1032,17 @@ gst_v4l2_camera_src_start_capture (GstV4l2CameraSrc * src) } } else { g_assert_not_reached (); - src->capturing = FALSE; + return FALSE; } - if (src->capturing) - g_object_notify (G_OBJECT (src), "ready-for-capture"); - g_mutex_unlock (src->capturing_mutex); + return TRUE; } static void -gst_v4l2_camera_src_stop_capture (GstV4l2CameraSrc * src) +gst_v4l2_camera_src_stop_capture (GstBaseCameraSrc * camerasrc) { - GstBaseCameraSrc *camerasrc = GST_BASE_CAMERA_SRC_CAST (src); - g_mutex_lock (src->capturing_mutex); - if (!src->capturing) { - GST_DEBUG_OBJECT (src, "No ongoing capture"); - g_mutex_unlock (src->capturing_mutex); - return; - } + GstV4l2CameraSrc *src = GST_V4L2_CAMERA_SRC (camerasrc); + + /* TODO shoud we access this directly? Maybe a macro is better? */ if (camerasrc->mode == MODE_VIDEO) { if (src->video_rec_status == GST_VIDEO_RECORDING_STATUS_STARTING) { GST_DEBUG_OBJECT (src, "Aborting, had not started recording"); @@ -1084,10 +1054,7 @@ gst_v4l2_camera_src_stop_capture (GstV4l2CameraSrc * src) } } else { src->image_capture_count = 0; - src->capturing = FALSE; - g_object_notify (G_OBJECT (src), "ready-for-capture"); } - g_mutex_unlock (src->capturing_mutex); } static void @@ -1119,40 +1086,6 @@ gst_v4l2_camera_src_class_init (GstV4l2CameraSrcClass * klass) /* g_object_class_install_property .... */ - /** - * GstV4l2CameraSrc:ready-for-capture: - * - * When TRUE new capture can be prepared. If FALSE capturing is ongoing - * and starting a new capture immediately is not possible. - * - * Note that calling start-capture from the notify callback of this property - * will cause a deadlock. If you need to react like this on the notify - * function, please schedule a new thread to do it. If you're using glib's - * mainloop you can use g_idle_add() for example. - */ - g_object_class_install_property (gobject_class, ARG_READY_FOR_CAPTURE, - g_param_spec_boolean ("ready-for-capture", "Ready for capture", - "Informs this element is ready for starting another capture", - TRUE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); - - /* Signals */ - v4l2camerasrc_signals[START_CAPTURE_SIGNAL] = - g_signal_new ("start-capture", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, - G_STRUCT_OFFSET (GstV4l2CameraSrcClass, start_capture), - NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); - - v4l2camerasrc_signals[STOP_CAPTURE_SIGNAL] = - g_signal_new ("stop-capture", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, - G_STRUCT_OFFSET (GstV4l2CameraSrcClass, stop_capture), - NULL, NULL, g_cclosure_marshal_VOID__VOID, G_TYPE_NONE, 0); - - klass->start_capture = gst_v4l2_camera_src_start_capture; - klass->stop_capture = gst_v4l2_camera_src_stop_capture; - gstbasecamerasrc_class->construct_pipeline = gst_v4l2_camera_src_construct_pipeline; gstbasecamerasrc_class->setup_pipeline = gst_v4l2_camera_src_setup_pipeline; @@ -1162,6 +1095,8 @@ gst_v4l2_camera_src_class_init (GstV4l2CameraSrcClass * klass) gst_v4l2_camera_src_get_allowed_input_caps; gstbasecamerasrc_class->finish_image_capture = gst_v4l2_camera_src_finish_image_capture; + gstbasecamerasrc_class->start_capture = gst_v4l2_camera_src_start_capture; + gstbasecamerasrc_class->stop_capture = gst_v4l2_camera_src_stop_capture; } static void @@ -1171,8 +1106,6 @@ gst_v4l2_camera_src_init (GstV4l2CameraSrc * self, /* TODO where are variables reset? */ self->image_capture_count = 0; self->video_rec_status = GST_VIDEO_RECORDING_STATUS_DONE; - self->capturing_mutex = g_mutex_new (); - self->capturing = FALSE; } gboolean diff --git a/gst/camerabin2/gstv4l2camerasrc.h b/gst/camerabin2/gstv4l2camerasrc.h index e996920fff..7bc8285c0d 100644 --- a/gst/camerabin2/gstv4l2camerasrc.h +++ b/gst/camerabin2/gstv4l2camerasrc.h @@ -57,9 +57,6 @@ struct _GstV4l2CameraSrc { GstBaseCameraSrc parent; - gboolean capturing; - GMutex *capturing_mutex; - /* video recording controls */ gint video_rec_status; @@ -108,9 +105,6 @@ struct _GstV4l2CameraSrc struct _GstV4l2CameraSrcClass { GstBaseCameraSrcClass parent; - - void (*start_capture) (GstV4l2CameraSrc * src); - void (*stop_capture) (GstV4l2CameraSrc * src); }; gboolean gst_v4l2_camera_src_plugin_init (GstPlugin * plugin); From db72d691caa0d37409fb684aa5d291ab1977d34b Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Mon, 6 Dec 2010 10:06:37 -0300 Subject: [PATCH 077/448] camerabin2: Cleanup Removing commented code --- gst/camerabin2/gstbasecamerasrc.c | 2 +- gst/camerabin2/gstv4l2camerasrc.c | 70 ++++++------------------------- 2 files changed, 14 insertions(+), 58 deletions(-) diff --git a/gst/camerabin2/gstbasecamerasrc.c b/gst/camerabin2/gstbasecamerasrc.c index 87cec67fd8..86c298e4e9 100644 --- a/gst/camerabin2/gstbasecamerasrc.c +++ b/gst/camerabin2/gstbasecamerasrc.c @@ -465,7 +465,7 @@ gst_base_camera_src_base_init (gpointer g_class) gst_element_class_set_details_simple (gstelement_class, "Base class for camerabin src bin", "Source/Video", - "Abstracts capture device for camerabin", "Rob Clark "); + "Abstracts capture device for camerabin2", "Rob Clark "); gst_element_class_add_pad_template (gstelement_class, gst_static_pad_template_get (&vfsrc_template)); diff --git a/gst/camerabin2/gstv4l2camerasrc.c b/gst/camerabin2/gstv4l2camerasrc.c index a85d83b6ab..68524427c0 100644 --- a/gst/camerabin2/gstv4l2camerasrc.c +++ b/gst/camerabin2/gstv4l2camerasrc.c @@ -230,36 +230,22 @@ gst_v4l2_camera_src_construct_pipeline (GstBaseCameraSrc * bcamsrc, } } -#if 0 - /* XXX srcbin needs to know of some flags, perhaps?? */ - if (camera->flags & GST_CAMERABIN_FLAG_SOURCE_COLOR_CONVERSION) { -#else - if (1) { -#endif - if (!gst_camerabin_create_and_add_element (cbin, "ffmpegcolorspace")) - goto done; - } + if (!gst_camerabin_create_and_add_element (cbin, "ffmpegcolorspace")) + goto done; if (!(self->src_filter = gst_camerabin_create_and_add_element (cbin, "capsfilter"))) goto done; -#if 0 - /* XXX srcbin needs to know of some flags, perhaps?? */ - if (camera->flags & GST_CAMERABIN_FLAG_SOURCE_RESIZE) { -#else - if (1) { -#endif - if (!(self->src_zoom_crop = - gst_camerabin_create_and_add_element (cbin, "videocrop"))) - goto done; - if (!(self->src_zoom_scale = - gst_camerabin_create_and_add_element (cbin, "videoscale"))) - goto done; - if (!(self->src_zoom_filter = - gst_camerabin_create_and_add_element (cbin, "capsfilter"))) - goto done; - } + if (!(self->src_zoom_crop = + gst_camerabin_create_and_add_element (cbin, "videocrop"))) + goto done; + if (!(self->src_zoom_scale = + gst_camerabin_create_and_add_element (cbin, "videoscale"))) + goto done; + if (!(self->src_zoom_filter = + gst_camerabin_create_and_add_element (cbin, "capsfilter"))) + goto done; if (self->app_video_filter) { if (!gst_camerabin_add_element (cbin, self->app_video_filter)) { @@ -283,27 +269,6 @@ gst_v4l2_camera_src_construct_pipeline (GstBaseCameraSrc * bcamsrc, *imgsrc = self->tee_image_srcpad; *vidsrc = self->tee_video_srcpad; -#if 0 - /* XXX another idea... put common parts in GstBaseCameraSrc.. perhaps - * derived class could use some flags, or something like this, to - * indicate which pads in needs vscale and queue on.. (but I think it - * doesn't hurt ot have on all..) - */ - /* XXX perhaps we should keep queues and vscale's in camerabin itself, - * because GstOmxCameraSrc would also probably need the queues.. and - * maybe some OMX camera implementations would want the vscale's (and - * at least the vscale's should become pass-through if OMX camera can - * negotiate the requested sizes.. - */ - queue = gst_element_factory_make ("queue", "viewfinder-queue"); - if (!gst_camerabin_add_element (cbin, queue)) { - goto error; - } - /* Set queue leaky, we don't want to block video encoder feed, but - * prefer leaking view finder buffers instead. */ - g_object_set (G_OBJECT (queue), "leaky", 2, "max-size-buffers", 1, NULL); -#endif - ret = TRUE; done: return ret; @@ -549,17 +514,8 @@ adapt_image_capture (GstV4l2CameraSrc * self, GstCaps * in_caps) /* If new fields have been added, we need to copy them */ gst_structure_foreach (in_st, copy_missing_fields, new_st); -#if 0 - /* XXX srcbin needs to know of some flags, perhaps?? */ - if (!(camera->flags & GST_CAMERABIN_FLAG_SOURCE_RESIZE)) { -#else - if (1) { -#endif - GST_DEBUG_OBJECT (self, - "source-resize flag disabled, unable to adapt resolution"); - gst_structure_set (new_st, "width", G_TYPE_INT, in_width, "height", - G_TYPE_INT, in_height, NULL); - } + gst_structure_set (new_st, "width", G_TYPE_INT, in_width, "height", + G_TYPE_INT, in_height, NULL); GST_LOG_OBJECT (self, "new image capture caps: %" GST_PTR_FORMAT, new_st); From f62e658c10fc011fba5ce5eede79ac09df6a74e2 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Mon, 6 Dec 2010 11:05:17 -0300 Subject: [PATCH 078/448] camerabin2: Only run tests if experimental is enabled Only run camerabin2 tests and build examples if experimental plugins are enabled --- tests/check/Makefile.am | 12 ++++++++---- tests/examples/Makefile.am | 8 +++++++- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/tests/check/Makefile.am b/tests/check/Makefile.am index e045129cbd..d98aaecbcf 100644 --- a/tests/check/Makefile.am +++ b/tests/check/Makefile.am @@ -127,6 +127,12 @@ VALGRIND_TO_FIX = \ VALGRIND_TESTS_DISABLE = \ $(VALGRIND_TO_FIX) +if BUILD_EXPERIMENTAL +EXPERIMENTAL_CHECKS=elements/camerabin2 \ + elements/imagecapturebin \ + elements/videorecordingbin +endif + # these tests don't even pass # neon: too flaky (almost always fails 'the first time') noinst_PROGRAMS = \ @@ -148,10 +154,8 @@ check_PROGRAMS = \ elements/autoconvert \ elements/asfmux \ elements/camerabin \ - elements/camerabin2 \ elements/dataurisrc \ elements/flacparse \ - elements/imagecapturebin \ elements/legacyresample \ $(check_jifmux) \ elements/jpegparse \ @@ -166,11 +170,11 @@ check_PROGRAMS = \ elements/rtpmux \ $(check_schro) \ elements/valve \ - elements/videorecordingbin \ $(check_vp8) \ $(check_zbar) \ $(check_orc) \ - pipelines/tagschecking + pipelines/tagschecking \ + $(EXPERIMENTAL_CHECKS) noinst_HEADERS = elements/mxfdemux.h diff --git a/tests/examples/Makefile.am b/tests/examples/Makefile.am index 218f2c622c..dbd11934c9 100644 --- a/tests/examples/Makefile.am +++ b/tests/examples/Makefile.am @@ -15,5 +15,11 @@ else DIRECTFB_DIR= endif +if BUILD_EXPERIMENTAL +CAMERABIN2=camerabin2 +else +CAMERABIN2= +endif + SUBDIRS= $(DIRECTFB_DIR) $(GTK_EXAMPLES) $(JACK_EXAMPLES) switch -DIST_SUBDIRS= camerabin camerabin2 directfb jack mxf scaletempo switch +DIST_SUBDIRS= camerabin $(CAMERABIN2) directfb jack mxf scaletempo switch From 91d8bbd8a151dca3614bcc8343fc7592e325d4d2 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Tue, 7 Dec 2010 19:12:40 -0300 Subject: [PATCH 079/448] basecamerasrc: Removing ununsed methods Remove one unused method _finish_image_capture() --- gst/camerabin2/gstbasecamerasrc.c | 17 ----------------- gst/camerabin2/gstbasecamerasrc.h | 5 ----- gst/camerabin2/gstv4l2camerasrc.c | 23 ----------------------- 3 files changed, 45 deletions(-) diff --git a/gst/camerabin2/gstbasecamerasrc.c b/gst/camerabin2/gstbasecamerasrc.c index 86c298e4e9..7c24ac394a 100644 --- a/gst/camerabin2/gstbasecamerasrc.c +++ b/gst/camerabin2/gstbasecamerasrc.c @@ -182,23 +182,6 @@ gst_base_camera_src_get_allowed_input_caps (GstBaseCameraSrc * self) return bclass->get_allowed_input_caps (self); } -/** - * gst_base_camera_src_finish_image_capture: - * @self: camerasrc object - * - * Perform finishing operations after image capture is done and - * returning back to view finder mode. - */ -void -gst_base_camera_src_finish_image_capture (GstBaseCameraSrc * self) -{ - GstBaseCameraSrcClass *bclass = GST_BASE_CAMERA_SRC_GET_CLASS (self); - - if (bclass->finish_image_capture) { - bclass->finish_image_capture (self); - } -} - /** * gst_base_camera_src_find_better_framerate: * @self: camerasrc object diff --git a/gst/camerabin2/gstbasecamerasrc.h b/gst/camerabin2/gstbasecamerasrc.h index 8a212b158d..14b2a4d0d7 100644 --- a/gst/camerabin2/gstbasecamerasrc.h +++ b/gst/camerabin2/gstbasecamerasrc.h @@ -126,10 +126,6 @@ struct _GstBaseCameraSrcClass /* */ GstCaps * (*get_allowed_input_caps) (GstBaseCameraSrc * self); - /* optional */ - void (*finish_image_capture) (GstBaseCameraSrc * self); - - void (*private_start_capture) (GstBaseCameraSrc * src); void (*private_stop_capture) (GstBaseCameraSrc * src); gboolean (*start_capture) (GstBaseCameraSrc * src); @@ -150,7 +146,6 @@ GstColorBalance * gst_base_camera_src_get_color_balance (GstBaseCameraSrc *self) gboolean gst_base_camera_src_set_mode (GstBaseCameraSrc *self, GstCameraBinMode mode); void gst_base_camera_src_setup_zoom (GstBaseCameraSrc * self); GstCaps * gst_base_camera_src_get_allowed_input_caps (GstBaseCameraSrc * self); -void gst_base_camera_src_finish_image_capture (GstBaseCameraSrc * self); const GValue * gst_base_camera_src_find_better_framerate ( GstBaseCameraSrc * self, GstStructure * st, const GValue * orig_framerate); diff --git a/gst/camerabin2/gstv4l2camerasrc.c b/gst/camerabin2/gstv4l2camerasrc.c index 68524427c0..feecccfaa0 100644 --- a/gst/camerabin2/gstv4l2camerasrc.c +++ b/gst/camerabin2/gstv4l2camerasrc.c @@ -952,27 +952,6 @@ set_capsfilter_caps (GstV4l2CameraSrc * self, GstCaps * new_caps) GST_INFO_OBJECT (self, "udpated"); } -static void -gst_v4l2_camera_src_finish_image_capture (GstBaseCameraSrc * bcamsrc) -{ - GstV4l2CameraSrc *self = GST_V4L2_CAMERA_SRC (bcamsrc); - - if (self->image_capture_caps) { - /* If we used specific caps for image capture we need to - restore the caps and zoom/crop for view finder mode */ - if (self->src_zoom_crop) { - GST_DEBUG_OBJECT (self, "resetting crop in camerabin"); - g_object_set (self->src_zoom_crop, "left", 0, "right", 0, - "top", 0, "bottom", 0, NULL); - } - self->base_crop_left = 0; - self->base_crop_right = 0; - self->base_crop_top = 0; - self->base_crop_bottom = 0; - set_capsfilter_caps (self, self->view_finder_caps); - } -} - static gboolean gst_v4l2_camera_src_start_capture (GstBaseCameraSrc * camerasrc) { @@ -1049,8 +1028,6 @@ gst_v4l2_camera_src_class_init (GstV4l2CameraSrcClass * klass) gstbasecamerasrc_class->set_mode = gst_v4l2_camera_src_set_mode; gstbasecamerasrc_class->get_allowed_input_caps = gst_v4l2_camera_src_get_allowed_input_caps; - gstbasecamerasrc_class->finish_image_capture = - gst_v4l2_camera_src_finish_image_capture; gstbasecamerasrc_class->start_capture = gst_v4l2_camera_src_start_capture; gstbasecamerasrc_class->stop_capture = gst_v4l2_camera_src_stop_capture; } From b6d5763e05d8dd4067c2c0b4c5f3ac8ac142753a Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Tue, 7 Dec 2010 19:40:28 -0300 Subject: [PATCH 080/448] basecamerasrc: Remove ghostpads Remove ghost pads from basecamerasrc. Different implementations of camera sources might not use ghostpads and use default pads. --- gst/camerabin2/gstbasecamerasrc.c | 41 ++++++------------------------- gst/camerabin2/gstbasecamerasrc.h | 17 ++++--------- gst/camerabin2/gstv4l2camerasrc.c | 36 +++++++++++++++++++++------ gst/camerabin2/gstv4l2camerasrc.h | 4 +++ 4 files changed, 44 insertions(+), 54 deletions(-) diff --git a/gst/camerabin2/gstbasecamerasrc.c b/gst/camerabin2/gstbasecamerasrc.c index 7c24ac394a..fac9c43dee 100644 --- a/gst/camerabin2/gstbasecamerasrc.c +++ b/gst/camerabin2/gstbasecamerasrc.c @@ -50,17 +50,20 @@ GST_DEBUG_CATEGORY (base_camera_src_debug); GST_BOILERPLATE (GstBaseCameraSrc, gst_base_camera_src, GstBin, GST_TYPE_BIN); -static GstStaticPadTemplate vfsrc_template = GST_STATIC_PAD_TEMPLATE ("vfsrc", +static GstStaticPadTemplate vfsrc_template = +GST_STATIC_PAD_TEMPLATE (GST_BASE_CAMERA_SRC_VIEWFINDER_PAD_NAME, GST_PAD_SRC, GST_PAD_ALWAYS, GST_STATIC_CAPS_ANY); -static GstStaticPadTemplate imgsrc_template = GST_STATIC_PAD_TEMPLATE ("imgsrc", +static GstStaticPadTemplate imgsrc_template = +GST_STATIC_PAD_TEMPLATE (GST_BASE_CAMERA_SRC_IMAGE_PAD_NAME, GST_PAD_SRC, GST_PAD_ALWAYS, GST_STATIC_CAPS_ANY); -static GstStaticPadTemplate vidsrc_template = GST_STATIC_PAD_TEMPLATE ("vidsrc", +static GstStaticPadTemplate vidsrc_template = +GST_STATIC_PAD_TEMPLATE (GST_BASE_CAMERA_SRC_VIDEO_PAD_NAME, GST_PAD_SRC, GST_PAD_ALWAYS, GST_STATIC_CAPS_ANY); @@ -368,35 +371,14 @@ static gboolean construct_pipeline (GstBaseCameraSrc * self) { GstBaseCameraSrcClass *bclass = GST_BASE_CAMERA_SRC_GET_CLASS (self); - GstPad *vfsrc = NULL; - GstPad *imgsrc = NULL; - GstPad *vidsrc = NULL; g_return_val_if_fail (bclass->construct_pipeline, FALSE); - if (!bclass->construct_pipeline (self, &vfsrc, &imgsrc, &vidsrc)) { + if (!bclass->construct_pipeline (self)) { GST_ERROR_OBJECT (self, "pipeline construction failed"); return FALSE; } - if (!vfsrc || !imgsrc || !vidsrc) { - GST_ERROR_OBJECT (self, "derived class must return src pads"); - return FALSE; - } - - GST_DEBUG_OBJECT (self, "vfsrc: %" GST_PTR_FORMAT, vfsrc); - GST_DEBUG_OBJECT (self, "imgsrc: %" GST_PTR_FORMAT, imgsrc); - GST_DEBUG_OBJECT (self, "vidsrc: %" GST_PTR_FORMAT, vidsrc); - - /* hook-up the ghostpads */ - gst_ghost_pad_set_target (GST_GHOST_PAD (self->vfsrc), vfsrc); - gst_ghost_pad_set_target (GST_GHOST_PAD (self->imgsrc), imgsrc); - gst_ghost_pad_set_target (GST_GHOST_PAD (self->vidsrc), vidsrc); - - gst_pad_set_active (self->vfsrc, TRUE); - gst_pad_set_active (self->imgsrc, TRUE); /* XXX ??? */ - gst_pad_set_active (self->vidsrc, TRUE); /* XXX ??? */ - return TRUE; } @@ -527,15 +509,6 @@ static void gst_base_camera_src_init (GstBaseCameraSrc * self, GstBaseCameraSrcClass * klass) { - self->vfsrc = gst_ghost_pad_new_no_target ("vfsrc", GST_PAD_SRC); - gst_element_add_pad (GST_ELEMENT (self), self->vfsrc); - - self->imgsrc = gst_ghost_pad_new_no_target ("imgsrc", GST_PAD_SRC); - gst_element_add_pad (GST_ELEMENT (self), self->imgsrc); - - self->vidsrc = gst_ghost_pad_new_no_target ("vidsrc", GST_PAD_SRC); - gst_element_add_pad (GST_ELEMENT (self), self->vidsrc); - self->width = DEFAULT_WIDTH; self->height = DEFAULT_HEIGHT; self->zoom = DEFAULT_ZOOM; diff --git a/gst/camerabin2/gstbasecamerasrc.h b/gst/camerabin2/gstbasecamerasrc.h index 14b2a4d0d7..c40b1b38e4 100644 --- a/gst/camerabin2/gstbasecamerasrc.h +++ b/gst/camerabin2/gstbasecamerasrc.h @@ -48,6 +48,9 @@ GType gst_base_camera_src_get_type (void); typedef struct _GstBaseCameraSrc GstBaseCameraSrc; typedef struct _GstBaseCameraSrcClass GstBaseCameraSrcClass; +#define GST_BASE_CAMERA_SRC_VIEWFINDER_PAD_NAME "vfsrc" +#define GST_BASE_CAMERA_SRC_IMAGE_PAD_NAME "imgsrc" +#define GST_BASE_CAMERA_SRC_VIDEO_PAD_NAME "vidsrc" /** * GstBaseCameraSrc: @@ -56,10 +59,6 @@ struct _GstBaseCameraSrc { GstBin parent; - GstPad *vfsrc; - GstPad *imgsrc; - GstPad *vidsrc; - gint mode; gboolean capturing; @@ -105,13 +104,8 @@ struct _GstBaseCameraSrcClass { GstBinClass parent; - /* construct pipeline must be implemented by derived class, and return by - * reference vfsrc, imgsrc, and vidsrc pads of the contained pipeline, which - * will be ghosted to the src pads of the camerasrc bin (and optionally the - * preview src pads?) */ - gboolean (*construct_pipeline) (GstBaseCameraSrc *self, - GstPad **vfsrc, GstPad **imgsrc, - GstPad **vidsrc); + /* construct pipeline must be implemented by derived class */ + gboolean (*construct_pipeline) (GstBaseCameraSrc *self); /* optional */ gboolean (*setup_pipeline) (GstBaseCameraSrc *self); @@ -131,7 +125,6 @@ struct _GstBaseCameraSrcClass gboolean (*start_capture) (GstBaseCameraSrc * src); void (*stop_capture) (GstBaseCameraSrc * src); - gpointer _gst_reserved[GST_PADDING_LARGE]; }; diff --git a/gst/camerabin2/gstv4l2camerasrc.c b/gst/camerabin2/gstv4l2camerasrc.c index feecccfaa0..c8cd2b2310 100644 --- a/gst/camerabin2/gstv4l2camerasrc.c +++ b/gst/camerabin2/gstv4l2camerasrc.c @@ -199,9 +199,6 @@ gst_v4l2_camera_src_vidsrc_probe (GstPad * pad, GstBuffer * buffer, /** * gst_v4l2_camera_src_construct_pipeline: * @bcamsrc: camerasrc object - * @vfsrc: viewfinder src element (returned by reference) - * @imgsrc: image src element (returned by reference) - * @vidsrc: video src element (returned by reference) * * This function creates and links the elements of the camerasrc bin * videosrc ! cspconv ! capsfilter ! crop ! scale ! capsfilter ! tee ! .. @@ -209,8 +206,7 @@ gst_v4l2_camera_src_vidsrc_probe (GstPad * pad, GstBuffer * buffer, * Returns: TRUE, if elements were successfully created, FALSE otherwise */ static gboolean -gst_v4l2_camera_src_construct_pipeline (GstBaseCameraSrc * bcamsrc, - GstPad ** vfsrc, GstPad ** imgsrc, GstPad ** vidsrc) +gst_v4l2_camera_src_construct_pipeline (GstBaseCameraSrc * bcamsrc) { GstV4l2CameraSrc *self = GST_V4L2_CAMERA_SRC (bcamsrc); GstBin *cbin = GST_BIN (bcamsrc); @@ -265,9 +261,17 @@ gst_v4l2_camera_src_construct_pipeline (GstBaseCameraSrc * bcamsrc, gst_pad_add_buffer_probe (self->tee_video_srcpad, G_CALLBACK (gst_v4l2_camera_src_vidsrc_probe), self); - *vfsrc = self->tee_vf_srcpad; - *imgsrc = self->tee_image_srcpad; - *vidsrc = self->tee_video_srcpad; + /* hook-up the ghostpads */ + gst_ghost_pad_set_target (GST_GHOST_PAD (self->vfsrc), self->tee_vf_srcpad); + gst_ghost_pad_set_target (GST_GHOST_PAD (self->imgsrc), + self->tee_image_srcpad); + gst_ghost_pad_set_target (GST_GHOST_PAD (self->vidsrc), + self->tee_video_srcpad); + + gst_pad_set_active (self->vfsrc, TRUE); + gst_pad_set_active (self->imgsrc, TRUE); /* XXX ??? */ + gst_pad_set_active (self->vidsrc, TRUE); /* XXX ??? */ + ret = TRUE; done: @@ -1036,6 +1040,22 @@ static void gst_v4l2_camera_src_init (GstV4l2CameraSrc * self, GstV4l2CameraSrcClass * klass) { + self->vfsrc = + gst_ghost_pad_new_no_target (GST_BASE_CAMERA_SRC_VIEWFINDER_PAD_NAME, + GST_PAD_SRC); + gst_element_add_pad (GST_ELEMENT (self), self->vfsrc); + + self->imgsrc = + gst_ghost_pad_new_no_target (GST_BASE_CAMERA_SRC_IMAGE_PAD_NAME, + GST_PAD_SRC); + gst_element_add_pad (GST_ELEMENT (self), self->imgsrc); + + self->vidsrc = + gst_ghost_pad_new_no_target (GST_BASE_CAMERA_SRC_VIDEO_PAD_NAME, + GST_PAD_SRC); + gst_element_add_pad (GST_ELEMENT (self), self->vidsrc); + + /* TODO where are variables reset? */ self->image_capture_count = 0; self->video_rec_status = GST_VIDEO_RECORDING_STATUS_DONE; diff --git a/gst/camerabin2/gstv4l2camerasrc.h b/gst/camerabin2/gstv4l2camerasrc.h index 7bc8285c0d..5f476fcc20 100644 --- a/gst/camerabin2/gstv4l2camerasrc.h +++ b/gst/camerabin2/gstv4l2camerasrc.h @@ -57,6 +57,10 @@ struct _GstV4l2CameraSrc { GstBaseCameraSrc parent; + GstPad *vfsrc; + GstPad *imgsrc; + GstPad *vidsrc; + /* video recording controls */ gint video_rec_status; From ec6c307334938dc036a3cb2e24fbbb2dddc359d6 Mon Sep 17 00:00:00 2001 From: Alessandro Decina Date: Thu, 9 Dec 2010 11:04:19 +0100 Subject: [PATCH 081/448] qtkitvideosrc: run the mainRunLoop for a while if not running. QTCaptureSession::addInput and QTCaptureSession::addOutput call NSObject::performSelectorOnMainThread internally so they need the mainRunLoop to run at least for a while to complete. --- sys/applemedia/qtkitvideosrc.m | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/sys/applemedia/qtkitvideosrc.m b/sys/applemedia/qtkitvideosrc.m index 7e2ceefd3f..2f9d0b20b3 100644 --- a/sys/applemedia/qtkitvideosrc.m +++ b/sys/applemedia/qtkitvideosrc.m @@ -241,6 +241,7 @@ openFailed: GstStructure *s; NSDictionary *outputAttrs; BOOL success; + NSRunLoop *mainRunLoop; g_assert (device != nil); @@ -276,6 +277,16 @@ openFailed: [output setDelegate:self]; [session startRunning]; + mainRunLoop = [NSRunLoop mainRunLoop]; + if ([mainRunLoop currentMode] == nil) { + /* QTCaptureSession::addInput and QTCaptureSession::addOutput call + * NSObject::performSelectorOnMainThread internally. If the mainRunLoop is + * not running we need to run it for a while for those methods to complete + */ + GST_INFO ("mainRunLoop not running"); + [[NSRunLoop mainRunLoop] runUntilDate:[NSDate dateWithTimeIntervalSinceNow:1]]; + } + return YES; } From 0b6e0b7b1397834c7e0e563f115bd4402b43173b Mon Sep 17 00:00:00 2001 From: Alessandro Decina Date: Thu, 9 Dec 2010 11:54:17 +0100 Subject: [PATCH 082/448] qtkitvideosrc: reset the queue condition to NO_FRAMES in unlockStop. Fixes a segfault in create: when going PLAYING -> PAUSED -> PLAYING. --- sys/applemedia/qtkitvideosrc.m | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sys/applemedia/qtkitvideosrc.m b/sys/applemedia/qtkitvideosrc.m index 2f9d0b20b3..8e80cae8d6 100644 --- a/sys/applemedia/qtkitvideosrc.m +++ b/sys/applemedia/qtkitvideosrc.m @@ -245,6 +245,8 @@ openFailed: g_assert (device != nil); + GST_INFO ("setting up session"); + s = gst_caps_get_structure (caps, 0); gst_structure_get_int (s, "width", &width); gst_structure_get_int (s, "height", &height); @@ -351,7 +353,7 @@ openFailed: { [queueLock lock]; stopRequest = NO; - [queueLock unlock]; + [queueLock unlockWithCondition:NO_FRAMES]; return YES; } @@ -385,6 +387,8 @@ openFailed: return; } + GST_INFO ("got new frame"); + if ([queue count] == FRAME_QUEUE_SIZE) [queue removeLastObject]; From 0c36c70f63ddc2e8689fa3762e4e21fa572a1dd7 Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Thu, 9 Dec 2010 18:06:38 +0100 Subject: [PATCH 083/448] jasperdec: don't fail hard on decoding error don't post an error and return GST_FLOW_ERROR on a simple decoding error. We can just resume and continue decoding the next image. --- ext/jp2k/gstjasperdec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/jp2k/gstjasperdec.c b/ext/jp2k/gstjasperdec.c index 05c1963acd..588a98ff4d 100644 --- a/ext/jp2k/gstjasperdec.c +++ b/ext/jp2k/gstjasperdec.c @@ -535,8 +535,8 @@ fail: if (*outbuf) gst_buffer_unref (*outbuf); *outbuf = NULL; - GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL), (NULL)); - ret = GST_FLOW_ERROR; + GST_ELEMENT_WARNING (dec, STREAM, DECODE, (NULL), (NULL)); + ret = GST_FLOW_OK; goto done; } no_buffer: From 6cf92cd25c0322058e9e59cd840e46a9dca98c97 Mon Sep 17 00:00:00 2001 From: Christian Berentsen Date: Mon, 29 Nov 2010 13:47:11 +0100 Subject: [PATCH 084/448] winks: fix framerate fraction range mapping Min and max may be slightly different but compress to the same fraction. --- sys/winks/ksvideohelpers.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/sys/winks/ksvideohelpers.c b/sys/winks/ksvideohelpers.c index 8399762e60..1772e5bcc1 100644 --- a/sys/winks/ksvideohelpers.c +++ b/sys/winks/ksvideohelpers.c @@ -309,6 +309,7 @@ ks_video_append_video_stream_cfg_fields (GstStructure * structure, const KS_VIDEO_STREAM_CONFIG_CAPS * vscc) { GValue val = { 0, }; + gint64 min_n, min_d; gint64 max_n, max_d; g_return_val_if_fail (structure, FALSE); @@ -335,16 +336,13 @@ ks_video_append_video_stream_cfg_fields (GstStructure * structure, } /* framerate */ + compress_fraction (NANOSECONDS, vscc->MinFrameInterval, &min_n, &min_d); compress_fraction (NANOSECONDS, vscc->MaxFrameInterval, &max_n, &max_d); - if (vscc->MinFrameInterval == vscc->MaxFrameInterval) { + if (min_n == max_n && min_d == max_d) { g_value_init (&val, GST_TYPE_FRACTION); gst_value_set_fraction (&val, max_n, max_d); } else { - gint64 min_n, min_d; - - compress_fraction (NANOSECONDS, vscc->MinFrameInterval, &min_n, &min_d); - g_value_init (&val, GST_TYPE_FRACTION_RANGE); gst_value_set_fraction_range_full (&val, max_n, max_d, min_n, min_d); } From f7e5878c9e4c905ffab0de443ac92715db500cb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ole=20Andr=C3=A9=20Vadla=20Ravn=C3=A5s?= Date: Fri, 19 Nov 2010 15:53:55 +0100 Subject: [PATCH 085/448] applemedia: bring back Leopard compatibility At least as far as miovideosrc is concerned. Turns out that CoreVideo's CVPixelBufferGetIOSurface is not present in Leopard's version of CoreVideo. We solve this by making it possible for symbols to be marked as optional. --- sys/applemedia/coremediactx.h | 3 --- sys/applemedia/cvapi.c | 3 ++- sys/applemedia/dynapi-internal.h | 1 + sys/applemedia/dynapi.c | 7 ++++--- sys/applemedia/dynapi.h | 4 +++- 5 files changed, 10 insertions(+), 8 deletions(-) diff --git a/sys/applemedia/coremediactx.h b/sys/applemedia/coremediactx.h index 4125ecdf56..0220b3e19b 100644 --- a/sys/applemedia/coremediactx.h +++ b/sys/applemedia/coremediactx.h @@ -46,9 +46,6 @@ G_BEGIN_DECLS #define GST_IS_CORE_MEDIA_CTX_CLASS(klass) \ (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_CORE_MEDIA_CTX)) -#define GST_DYN_SYM_SPEC(type, name) \ - { G_STRINGIFY (name), G_STRUCT_OFFSET (type, name) } - typedef struct _GstCoreMediaCtx GstCoreMediaCtx; typedef struct _GstCoreMediaCtxClass GstCoreMediaCtxClass; diff --git a/sys/applemedia/cvapi.c b/sys/applemedia/cvapi.c index 73186f8f5b..4307f07376 100644 --- a/sys/applemedia/cvapi.c +++ b/sys/applemedia/cvapi.c @@ -37,6 +37,7 @@ gst_cv_api_class_init (GstCVApiClass * klass) } #define SYM_SPEC(name) GST_DYN_SYM_SPEC (GstCVApi, name) +#define SYM_SPEC_OPTIONAL(name) GST_DYN_SYM_SPEC_OPTIONAL (GstCVApi, name) GstCVApi * gst_cv_api_obtain (GError ** error) @@ -53,7 +54,7 @@ gst_cv_api_obtain (GError ** error) SYM_SPEC (CVPixelBufferGetBytesPerRowOfPlane), SYM_SPEC (CVPixelBufferGetHeight), SYM_SPEC (CVPixelBufferGetHeightOfPlane), - SYM_SPEC (CVPixelBufferGetIOSurface), + SYM_SPEC_OPTIONAL (CVPixelBufferGetIOSurface), SYM_SPEC (CVPixelBufferGetPlaneCount), SYM_SPEC (CVPixelBufferGetTypeID), SYM_SPEC (CVPixelBufferIsPlanar), diff --git a/sys/applemedia/dynapi-internal.h b/sys/applemedia/dynapi-internal.h index b584ea76b3..d6624d100a 100644 --- a/sys/applemedia/dynapi-internal.h +++ b/sys/applemedia/dynapi-internal.h @@ -30,6 +30,7 @@ struct _GstDynSymSpec { const gchar * name; guint offset; + gboolean is_required; }; gpointer _gst_dyn_api_new (GType derived_type, const gchar * filename, diff --git a/sys/applemedia/dynapi.c b/sys/applemedia/dynapi.c index 87ff10ccb6..139fabd66e 100644 --- a/sys/applemedia/dynapi.c +++ b/sys/applemedia/dynapi.c @@ -142,9 +142,10 @@ _gst_dyn_api_new (GType derived_type, const gchar * filename, names_not_found = g_array_new (TRUE, FALSE, sizeof (gchar *)); for (i = 0; symbols[i].name != NULL; i++) { - if (!g_module_symbol (priv->module, symbols[i].name, - (gpointer *) (((guint8 *) api) + symbols[i].offset))) { - g_array_append_val (names_not_found, symbols[i].name); + const GstDynSymSpec *s = &symbols[i]; + if (!g_module_symbol (priv->module, s->name, + (gpointer *) (((guint8 *) api) + s->offset)) && s->is_required) { + g_array_append_val (names_not_found, s->name); } } diff --git a/sys/applemedia/dynapi.h b/sys/applemedia/dynapi.h index 2b125ba8c3..4be83b2c0e 100644 --- a/sys/applemedia/dynapi.h +++ b/sys/applemedia/dynapi.h @@ -38,7 +38,9 @@ G_BEGIN_DECLS (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_DYN_API)) #define GST_DYN_SYM_SPEC(type, name) \ - { G_STRINGIFY (name), G_STRUCT_OFFSET (type, name) } + { G_STRINGIFY (name), G_STRUCT_OFFSET (type, name), TRUE } +#define GST_DYN_SYM_SPEC_OPTIONAL(type, name) \ + { G_STRINGIFY (name), G_STRUCT_OFFSET (type, name), FALSE } typedef struct _GstDynApi GstDynApi; typedef struct _GstDynApiClass GstDynApiClass; From f3d8e3920dfc4126a8c98e4e376b8f2fb21d560c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ole=20Andr=C3=A9=20Vadla=20Ravn=C3=A5s?= Date: Fri, 10 Dec 2010 00:58:58 +0100 Subject: [PATCH 086/448] applemedia: only enqueue buffers in the VideoToolbox callbacks These callbacks may fire from any thread, hence we should only enqueue buffers and let the streaming thread take care of the rest as soon as the blocking encode or decode operation has finished. --- sys/applemedia/vtdec.c | 21 ++++++++++++--------- sys/applemedia/vtenc.c | 25 ++++++++++++++----------- 2 files changed, 26 insertions(+), 20 deletions(-) diff --git a/sys/applemedia/vtdec.c b/sys/applemedia/vtdec.c index eb5d2f1ac3..22db2e8696 100644 --- a/sys/applemedia/vtdec.c +++ b/sys/applemedia/vtdec.c @@ -45,7 +45,7 @@ static VTDecompressionSessionRef gst_vtdec_create_session (GstVTDec * self, static void gst_vtdec_destroy_session (GstVTDec * self, VTDecompressionSessionRef * session); static GstFlowReturn gst_vtdec_decode_buffer (GstVTDec * self, GstBuffer * buf); -static void gst_vtdec_output_frame (void *data, gsize unk1, VTStatus result, +static void gst_vtdec_enqueue_frame (void *data, gsize unk1, VTStatus result, gsize unk2, CVBufferRef cvbuf); static CMSampleBufferRef gst_vtdec_sample_buffer_from (GstVTDec * self, @@ -358,7 +358,7 @@ gst_vtdec_create_session (GstVTDec * self, CMFormatDescriptionRef fmt_desc) gst_vtutil_dict_set_i32 (pb_attrs, *(cv->kCVPixelBufferBytesPerRowAlignmentKey), 2 * self->negotiated_width); - callback.func = gst_vtdec_output_frame; + callback.func = gst_vtdec_enqueue_frame; callback.data = self; status = self->ctx->vt->VTDecompressionSessionCreate (NULL, fmt_desc, @@ -407,13 +407,20 @@ gst_vtdec_decode_buffer (GstVTDec * self, GstBuffer * buf) self->cur_inbuf = NULL; gst_buffer_unref (buf); + if (self->cur_outbufs->len > 0) { + if (!gst_vtdec_negotiate_downstream (self)) + ret = GST_FLOW_NOT_NEGOTIATED; + } + for (i = 0; i != self->cur_outbufs->len; i++) { GstBuffer *buf = g_ptr_array_index (self->cur_outbufs, i); - if (ret == GST_FLOW_OK) + if (ret == GST_FLOW_OK) { + gst_buffer_set_caps (buf, GST_PAD_CAPS (self->srcpad)); ret = gst_pad_push (self->srcpad, buf); - else + } else { gst_buffer_unref (buf); + } } g_ptr_array_set_size (self->cur_outbufs, 0); @@ -421,7 +428,7 @@ gst_vtdec_decode_buffer (GstVTDec * self, GstBuffer * buf) } static void -gst_vtdec_output_frame (void *data, gsize unk1, VTStatus result, gsize unk2, +gst_vtdec_enqueue_frame (void *data, gsize unk1, VTStatus result, gsize unk2, CVBufferRef cvbuf) { GstVTDec *self = GST_VTDEC_CAST (data); @@ -430,11 +437,7 @@ gst_vtdec_output_frame (void *data, gsize unk1, VTStatus result, gsize unk2, if (result != kVTSuccess) goto beach; - if (!gst_vtdec_negotiate_downstream (self)) - goto beach; - buf = gst_core_video_buffer_new (self->ctx, cvbuf); - gst_buffer_set_caps (buf, GST_PAD_CAPS (self->srcpad)); gst_buffer_copy_metadata (buf, self->cur_inbuf, GST_BUFFER_COPY_FLAGS | GST_BUFFER_COPY_TIMESTAMPS); diff --git a/sys/applemedia/vtenc.c b/sys/applemedia/vtenc.c index 43a16229e1..c7878482c3 100644 --- a/sys/applemedia/vtenc.c +++ b/sys/applemedia/vtenc.c @@ -77,7 +77,7 @@ static VTStatus gst_vtenc_session_configure_property_double (GstVTEnc * self, VTCompressionSessionRef session, CFStringRef name, gdouble value); static GstFlowReturn gst_vtenc_encode_frame (GstVTEnc * self, GstBuffer * buf); -static VTStatus gst_vtenc_output_buffer (void *data, int a2, int a3, int a4, +static VTStatus gst_vtenc_enqueue_buffer (void *data, int a2, int a3, int a4, CMSampleBufferRef sbuf, int a6, int a7); static gboolean gst_vtenc_buffer_is_keyframe (GstVTEnc * self, CMSampleBufferRef sbuf); @@ -411,9 +411,7 @@ gst_vtenc_negotiate_downstream (GstVTEnc * self, CMSampleBufferRef sbuf) gst_buffer_unref (codec_data); } - GST_OBJECT_UNLOCK (self); result = gst_pad_set_caps (self->srcpad, caps); - GST_OBJECT_LOCK (self); gst_caps_unref (caps); @@ -502,7 +500,7 @@ gst_vtenc_create_session (GstVTEnc * self) gst_vtutil_dict_set_i32 (pb_attrs, *(cv->kCVPixelBufferHeightKey), self->negotiated_height); - callback.func = gst_vtenc_output_buffer; + callback.func = gst_vtenc_enqueue_buffer; callback.data = self; status = vt->VTCompressionSessionCreate (NULL, @@ -770,13 +768,22 @@ gst_vtenc_encode_frame (GstVTEnc * self, GstBuffer * buf) self->cur_inbuf = NULL; gst_buffer_unref (buf); + if (self->cur_outbufs->len > 0) { + GstCoreMediaBuffer *cmbuf = + GST_CORE_MEDIA_BUFFER_CAST (g_ptr_array_index (self->cur_outbufs, 0)); + if (!gst_vtenc_negotiate_downstream (self, cmbuf->sample_buf)) + ret = GST_FLOW_NOT_NEGOTIATED; + } + for (i = 0; i != self->cur_outbufs->len; i++) { GstBuffer *buf = g_ptr_array_index (self->cur_outbufs, i); - if (ret == GST_FLOW_OK) + if (ret == GST_FLOW_OK) { + gst_buffer_set_caps (buf, GST_PAD_CAPS (self->srcpad)); ret = gst_pad_push (self->srcpad, buf); - else + } else { gst_buffer_unref (buf); + } } g_ptr_array_set_size (self->cur_outbufs, 0); @@ -792,7 +799,7 @@ cv_error: } static VTStatus -gst_vtenc_output_buffer (void *data, int a2, int a3, int a4, +gst_vtenc_enqueue_buffer (void *data, int a2, int a3, int a4, CMSampleBufferRef sbuf, int a6, int a7) { GstVTEnc *self = data; @@ -812,11 +819,7 @@ gst_vtenc_output_buffer (void *data, int a2, int a3, int a4, } self->expect_keyframe = FALSE; - if (!gst_vtenc_negotiate_downstream (self, sbuf)) - goto beach; - buf = gst_core_media_buffer_new (self->ctx, sbuf); - gst_buffer_set_caps (buf, GST_PAD_CAPS (self->srcpad)); gst_buffer_copy_metadata (buf, self->cur_inbuf, GST_BUFFER_COPY_TIMESTAMPS); if (is_keyframe) { GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT); From c12fc9edda9e5010b443e40cb76b2d3e1ee56183 Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Tue, 16 Nov 2010 17:09:06 +1100 Subject: [PATCH 087/448] resindvd: Fix silly typo in button state tracking. --- ext/resindvd/resindvdsrc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/resindvd/resindvdsrc.c b/ext/resindvd/resindvdsrc.c index 72c8d2544e..3e48e813bd 100644 --- a/ext/resindvd/resindvdsrc.c +++ b/ext/resindvd/resindvdsrc.c @@ -61,7 +61,7 @@ typedef enum RSN_BTN_LEFT = 0x01, RSN_BTN_RIGHT = 0x02, RSN_BTN_UP = 0x04, - RSN_BTN_DOWN = 0x04 + RSN_BTN_DOWN = 0x08 } RsnBtnMask; enum From 4810fa4c5186eb25b06673cfe95bef1baab7bba7 Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Tue, 16 Nov 2010 17:18:33 +1100 Subject: [PATCH 088/448] resindvd: Attempt to use glib language setting for DVD menus/audio --- ext/resindvd/resindvdsrc.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/ext/resindvd/resindvdsrc.c b/ext/resindvd/resindvdsrc.c index 3e48e813bd..45bd56f7b1 100644 --- a/ext/resindvd/resindvdsrc.c +++ b/ext/resindvd/resindvdsrc.c @@ -36,6 +36,7 @@ GST_DEBUG_CATEGORY_STATIC (rsndvdsrc_debug); #define DEFAULT_DEVICE "/dev/dvd" #define DEFAULT_FASTSTART TRUE +#define DEFAULT_LANG "en" #define GST_FLOW_WOULD_BLOCK GST_FLOW_CUSTOM_SUCCESS @@ -354,6 +355,8 @@ static gboolean rsn_dvdsrc_start (GstBaseSrc * bsrc) { resinDvdSrc *src = RESINDVDSRC (bsrc); + const gchar *const *langs, *const *cur; + gchar lang[8]; g_mutex_lock (src->dvd_lock); if (!read_vts_info (src)) { @@ -374,6 +377,21 @@ rsn_dvdsrc_start (GstBaseSrc * bsrc) goto fail; } + /* Attempt to set DVD menu, audio and spu languages */ + langs = g_get_language_names (); + strncpy (lang, DEFAULT_LANG, 8); + for (cur = langs; *cur != NULL; cur++) { + /* Look for a 2 char iso-639 lang */ + if (strlen (*cur) == 2) { + strncpy (lang, *cur, 8); + break; + } + } + /* Set the user's preferred language */ + dvdnav_menu_language_select (src->dvdnav, lang); + dvdnav_audio_language_select (src->dvdnav, lang); + dvdnav_spu_language_select (src->dvdnav, lang); + if (src->faststart) { if (dvdnav_title_play (src->dvdnav, 1) != DVDNAV_STATUS_OK || (dvdnav_menu_call (src->dvdnav, DVD_MENU_Title) != DVDNAV_STATUS_OK && @@ -1058,11 +1076,11 @@ rsn_dvdsrc_step (resinDvdSrc * src, gboolean have_dvd_lock) dvdnav_audio_stream_change_event_t *event = (dvdnav_audio_stream_change_event_t *) data; + rsn_dvdsrc_prepare_audio_stream_event (src, + event->logical, event->physical); GST_DEBUG_OBJECT (src, " physical: %d", event->physical); GST_DEBUG_OBJECT (src, " logical: %d", event->logical); - rsn_dvdsrc_prepare_audio_stream_event (src, - event->logical, event->physical); break; } case DVDNAV_SPU_STREAM_CHANGE:{ @@ -2369,7 +2387,7 @@ rsn_dvdsrc_src_event (GstBaseSrc * basesrc, GstEvent * event) GST_LOG_OBJECT (src, "handling seek event"); gst_event_parse_seek (event, NULL, NULL, &flags, NULL, NULL, NULL, NULL); - src->flushing_seek = ! !(flags & GST_SEEK_FLAG_FLUSH); + src->flushing_seek = !!(flags & GST_SEEK_FLAG_FLUSH); GST_DEBUG_OBJECT (src, "%s seek event", src->flushing_seek ? "flushing" : "non-flushing"); From 7e3472d772573cb4d645845d2242f24f61b51b72 Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Sun, 12 Dec 2010 02:16:49 +1100 Subject: [PATCH 089/448] resindvd: Defer pushing tag updates until streaming. Push tag/title info updates in the streaming thread, avoiding spurious losses of the downstream events when flushing. See: https://bugzilla.gnome.org/show_bug.cgi?id=594222 --- ext/resindvd/resindvdsrc.c | 29 +++++++++++++++++++++-------- ext/resindvd/resindvdsrc.h | 1 + 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/ext/resindvd/resindvdsrc.c b/ext/resindvd/resindvdsrc.c index 45bd56f7b1..e4bdd7eec6 100644 --- a/ext/resindvd/resindvdsrc.c +++ b/ext/resindvd/resindvdsrc.c @@ -409,6 +409,7 @@ rsn_dvdsrc_start (GstBaseSrc * bsrc) src->branching = FALSE; src->discont = TRUE; src->need_segment = TRUE; + src->need_tag_update = TRUE; src->cur_position = GST_CLOCK_TIME_NONE; src->pgc_duration = GST_CLOCK_TIME_NONE; @@ -810,8 +811,8 @@ get_current_pgc (resinDvdSrc * src) return pgc; } -static void -update_title_info (resinDvdSrc * src) +static GstTagList * +update_title_info (resinDvdSrc * src, gboolean force) { gint n_angles, cur_agl; gint title_n, part_n; @@ -825,14 +826,14 @@ update_title_info (resinDvdSrc * src) if (dvdnav_current_title_info (src->dvdnav, &title_n, &part_n) != DVDNAV_STATUS_OK) { if (!src->in_menu) - return; /* Can't update now */ + return NULL; /* Can't update now */ /* Must be in the first play sequence */ title_n = -1; part_n = 0; } if (title_n != src->title_n || part_n != src->part_n || - src->n_angles != n_angles || src->cur_angle != cur_agl) { + src->n_angles != n_angles || src->cur_angle != cur_agl || force) { gchar *title_str = NULL; src->title_n = title_n; @@ -870,9 +871,11 @@ update_title_info (resinDvdSrc * src) gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, GST_TAG_TITLE, title_str, NULL); g_free (title_str); - gst_element_found_tags (GST_ELEMENT_CAST (src), tags); + return tags; } } + + return NULL; } /* we don't cache the result on purpose */ @@ -1046,8 +1049,7 @@ rsn_dvdsrc_step (resinDvdSrc * src, gboolean have_dvd_lock) GST_TIME_ARGS (src->cur_position)); rsn_dvdsrc_prepare_streamsinfo_event (src); - - update_title_info (src); + src->need_tag_update = TRUE; break; } @@ -1294,6 +1296,7 @@ rsn_dvdsrc_create (GstBaseSrc * bsrc, guint64 offset, GstEvent *audio_select_event = NULL; GstEvent *highlight_event = NULL; GstMessage *angles_msg = NULL; + GstTagList *tags = NULL; gboolean cmds_changed = FALSE; *outbuf = NULL; @@ -1331,6 +1334,11 @@ rsn_dvdsrc_create (GstBaseSrc * bsrc, guint64 offset, cmds_changed = src->commands_changed; src->commands_changed = FALSE; + if (src->need_tag_update) { + tags = update_title_info (src, FALSE); + src->need_tag_update = FALSE; + } + g_mutex_unlock (src->dvd_lock); /* Push in-band events now that we've dropped the dvd_lock, before @@ -1377,6 +1385,11 @@ rsn_dvdsrc_create (GstBaseSrc * bsrc, guint64 offset, if (src->cur_end_ts != GST_CLOCK_TIME_NONE) gst_segment_set_last_stop (segment, GST_FORMAT_TIME, src->cur_end_ts); + if (tags) { + gst_element_found_tags_for_pad (GST_ELEMENT_CAST (src), + GST_BASE_SRC_PAD (src), tags); + tags = NULL; + } g_mutex_lock (src->dvd_lock); if (src->next_buf != NULL) { @@ -1784,7 +1797,7 @@ rsn_dvdsrc_handle_navigation_event (resinDvdSrc * src, GstEvent * event) } src->angles_changed = FALSE; - update_title_info (src); + src->need_tag_update = TRUE; } cmds_changed = src->commands_changed; diff --git a/ext/resindvd/resindvdsrc.h b/ext/resindvd/resindvdsrc.h index c3985b6cf4..5e6e3c7a00 100644 --- a/ext/resindvd/resindvdsrc.h +++ b/ext/resindvd/resindvdsrc.h @@ -84,6 +84,7 @@ struct _resinDvdSrc gboolean first_seek; gboolean flushing_seek; gboolean need_segment; + gboolean need_tag_update; gboolean active_highlight; gboolean in_still_state; gboolean in_playing; From a4f2ab78ffe9a5f0bd8a29e778ca9ea7688de792 Mon Sep 17 00:00:00 2001 From: Jan Schmidt Date: Sun, 12 Dec 2010 02:24:00 +1100 Subject: [PATCH 090/448] gaudieffects: Avoid divide by 0 in burn element --- gst/gaudieffects/burn-example.py | 23 +++++++++++++++++++++++ gst/gaudieffects/gstburn.c | 31 +++++++++++-------------------- 2 files changed, 34 insertions(+), 20 deletions(-) create mode 100644 gst/gaudieffects/burn-example.py diff --git a/gst/gaudieffects/burn-example.py b/gst/gaudieffects/burn-example.py new file mode 100644 index 0000000000..01080b909a --- /dev/null +++ b/gst/gaudieffects/burn-example.py @@ -0,0 +1,23 @@ +#!/usr/bin/python +import gobject; gobject.threads_init() +import pygst; pygst.require("0.10") +import gst + +p = gst.parse_launch (""" + v4l2src ! + ffmpegcolorspace ! queue ! video/x-raw-rgb,width=320,height=240,framerate=30/1 ! burn qos=true name=vf ! ffmpegcolorspace ! + timeoverlay ! xvimagesink + """) + +m = p.get_by_name ("vf") +m.set_property ("adjustment", 128) + +control = gst.Controller(m, "adjustment") +control.set_interpolation_mode("adjustment", gst.INTERPOLATE_LINEAR) +control.set("adjustment", 0 * gst.SECOND, 128) +control.set("adjustment", 5 * gst.SECOND, 256) +control.set("adjustment", 25 * gst.SECOND, 0) + +p.set_state (gst.STATE_PLAYING) + +gobject.MainLoop().run() diff --git a/gst/gaudieffects/gstburn.c b/gst/gaudieffects/gstburn.c index 582d5e85b0..3d769356a0 100644 --- a/gst/gaudieffects/gstburn.c +++ b/gst/gaudieffects/gstburn.c @@ -96,7 +96,6 @@ enum #define DEFAULT_ADJUSTMENT 175 -static gint gate_int (gint value, gint min, gint max); static void transform (guint32 * src, guint32 * dest, gint video_area, gint adjustment); @@ -289,24 +288,13 @@ gst_burn_plugin_init (GstPlugin * burn) } /*** Now the image processing work.... ***/ -/* Keep the values inbounds. */ -static gint -gate_int (gint value, gint min, gint max) -{ - if (value < min) { - return min; - } else if (value > max) { - return max; - } else { - return value; - } -} /* Transform processes each frame. */ static void transform (guint32 * src, guint32 * dest, gint video_area, gint adjustment) { - guint32 in, red, green, blue; + guint32 in; + gint red, green, blue, c; gint x; for (x = 0; x < video_area; x++) { @@ -316,13 +304,16 @@ transform (guint32 * src, guint32 * dest, gint video_area, gint adjustment) green = (in >> 8) & 0xff; blue = (in) & 0xff; - red = 256 - ((256 * (255 - red)) / (red + adjustment)); - green = 256 - ((256 * (255 - green)) / (green + adjustment)); - blue = 256 - ((256 * (255 - blue)) / (blue + adjustment)); + c = (red + adjustment); + red = c ? (256 - (256 * (255 - red) / c)) : 0; + c = (green + adjustment); + green = c ? (256 - (256 * (255 - green) / c)) : 0; + c = (blue + adjustment); + blue = c ? (256 - (256 * (255 - blue) / c)) : 0; - red = gate_int (red, 0, 255); - green = gate_int (green, 0, 255); - blue = gate_int (blue, 0, 255); + red = CLAMP (red, 0, 255); + green = CLAMP (green, 0, 255); + blue = CLAMP (blue, 0, 255); *dest++ = (red << 16) | (green << 8) | blue; } From ec300d007ddce9044afd5067d3ac249e7506396c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Sun, 12 Dec 2010 12:01:38 +0100 Subject: [PATCH 091/448] ssim: Set classification to Filter/Analyzer/Video instead of Filter/Converter/Video Fixes bug #636109. --- gst/videomeasure/gstvideomeasure_ssim.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst/videomeasure/gstvideomeasure_ssim.c b/gst/videomeasure/gstvideomeasure_ssim.c index acbe781a23..a99fa9ff3a 100644 --- a/gst/videomeasure/gstvideomeasure_ssim.c +++ b/gst/videomeasure/gstvideomeasure_ssim.c @@ -1110,7 +1110,7 @@ gst_ssim_class_init (GstSSimClass * klass) gst_element_class_add_pad_template (gstelement_class, gst_static_pad_template_get (&gst_ssim_sink_modified_template)); gst_element_class_set_details_simple (gstelement_class, "SSim", - "Filter/Converter/Video", + "Filter/Analyzer/Video", "Calculate Y-SSIM for n+2 YUV video streams", "Руслан Ижбулатов "); From 2056f4a63344836d717eecdac4bb2bbf47e6a3a5 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Sun, 12 Dec 2010 22:13:13 +0100 Subject: [PATCH 092/448] jpegparse: avoid leaking converted comment string --- gst/jpegformat/gstjpegparse.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/gst/jpegformat/gstjpegparse.c b/gst/jpegformat/gstjpegparse.c index 8dbc511c31..c1c65391be 100644 --- a/gst/jpegformat/gstjpegparse.c +++ b/gst/jpegformat/gstjpegparse.c @@ -562,7 +562,7 @@ gst_jpeg_parse_read_header (GstJpegParse * parse, GstBuffer * buffer) case COM:{ /* read comment and post as tag */ const guint8 *comment = NULL; - const gchar *comm; + gchar *comm; const gchar *env_vars[] = { "GST_JPEG_TAG_ENCODING", "GST_TAG_ENCODING", NULL }; @@ -572,7 +572,7 @@ gst_jpeg_parse_read_header (GstJpegParse * parse, GstBuffer * buffer) if (!gst_byte_reader_get_data (&reader, size - 2, &comment)) goto error; - comm = (const gchar *) comment; + comm = (gchar *) comment; comm = gst_tag_freeform_string_to_utf8 (comm, size - 2, env_vars); if (comm) { @@ -580,6 +580,7 @@ gst_jpeg_parse_read_header (GstJpegParse * parse, GstBuffer * buffer) parse->priv->tags = gst_tag_list_new (); gst_tag_list_add (parse->priv->tags, GST_TAG_MERGE_REPLACE, GST_TAG_COMMENT, comm, NULL); + g_free (comm); } break; } From 51c63587a16518fa322eb4fcdcc08102c8b0cc3e Mon Sep 17 00:00:00 2001 From: Matthew Ife Date: Sun, 12 Dec 2010 23:34:02 +0000 Subject: [PATCH 093/448] rfbsrc: fail more gracefully if source gets disconnected or geometry changes Don't get caught in an infinite loop if the source gets disconnected and also support gracefully failing upon detecting the frame geometry has increased (rather than segfaulting). https://bugzilla.gnome.org/show_bug.cgi?id=635397 --- gst/librfb/rfbdecoder.c | 14 +++++++++++++- gst/librfb/rfbdecoder.h | 1 + 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/gst/librfb/rfbdecoder.c b/gst/librfb/rfbdecoder.c index 36e47aa411..53de8d14aa 100644 --- a/gst/librfb/rfbdecoder.c +++ b/gst/librfb/rfbdecoder.c @@ -79,6 +79,7 @@ rfb_decoder_new (void) decoder->rect_width = 0; decoder->rect_height = 0; decoder->shared_flag = TRUE; + decoder->disconnected = FALSE; decoder->data = NULL; decoder->data_len = 0; @@ -129,6 +130,9 @@ rfb_decoder_connect_tcp (RfbDecoder * decoder, gchar * addr, guint port) return FALSE; } //rfb_decoder_use_file_descriptor (decoder, fd); + + decoder->disconnected = FALSE; + return TRUE; } @@ -178,6 +182,7 @@ rfb_decoder_read (RfbDecoder * decoder, guint32 len) now = recv (decoder->fd, (char *) decoder->data + total, len - total, 0); #endif if (now <= 0) { + decoder->disconnected = TRUE; GST_WARNING ("rfb read error on socket"); return NULL; } @@ -620,6 +625,13 @@ rfb_decoder_state_framebuffer_update_rectangle (RfbDecoder * decoder) GST_DEBUG ("w:%d h:%d", w, h); GST_DEBUG ("encoding: %d", encoding); + if (((w * h) + (x * y)) > (decoder->width * decoder->height)) { + GST_ERROR ("Desktop resize is unsupported."); + decoder->state = NULL; + decoder->disconnected = TRUE; + return TRUE; + } + switch (encoding) { case ENCODING_TYPE_RAW: rfb_decoder_raw_encoding (decoder, x, y, w, h); @@ -641,7 +653,7 @@ rfb_decoder_state_framebuffer_update_rectangle (RfbDecoder * decoder) break; } decoder->n_rects--; - if (decoder->n_rects == 0) { + if (decoder->n_rects == 0 || decoder->disconnected == TRUE) { decoder->state = NULL; } else { decoder->state = rfb_decoder_state_framebuffer_update_rectangle; diff --git a/gst/librfb/rfbdecoder.h b/gst/librfb/rfbdecoder.h index c9fb5f55dc..33323ac260 100644 --- a/gst/librfb/rfbdecoder.h +++ b/gst/librfb/rfbdecoder.h @@ -48,6 +48,7 @@ struct _RfbDecoder /* settable properties */ gboolean shared_flag; + gboolean disconnected; /* readable properties */ gboolean inited; From 25007c3c9d67076b7873de7cd6ae2ca24d775543 Mon Sep 17 00:00:00 2001 From: Stefan Kost Date: Mon, 13 Dec 2010 16:23:45 +0200 Subject: [PATCH 094/448] Automatic update of common submodule From 011bcc8 to 20742ae --- common | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common b/common index 011bcc8a0f..20742aee03 160000 --- a/common +++ b/common @@ -1 +1 @@ -Subproject commit 011bcc8a0fc7f798ee874a7ba899123fb2470e22 +Subproject commit 20742aee033cc7c4aa9a817df005d15d5fa6ba85 From 01e9b677a814f95a22bf9f242422865e0ca3df92 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Mon, 13 Dec 2010 15:17:29 +0100 Subject: [PATCH 095/448] ac3parse: relax bsid checking ... to the widest possible spec interpretation. Fixes #637062. --- gst/audioparsers/gstac3parse.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/gst/audioparsers/gstac3parse.c b/gst/audioparsers/gstac3parse.c index 96e9a911ea..7e3a8b49c7 100644 --- a/gst/audioparsers/gstac3parse.c +++ b/gst/audioparsers/gstac3parse.c @@ -262,10 +262,13 @@ gst_ac3_parse_frame_header_ac3 (GstAc3Parse * ac3parse, GstBuffer * buf, bsmod = gst_bit_reader_get_bits_uint8_unchecked (&bits, 3); acmod = gst_bit_reader_get_bits_uint8_unchecked (&bits, 3); - /* FIXME: are other bsids ok as well? check spec */ - if (bsid != 8 && bsid != 6) { + /* spec not quite clear here: decoder should decode if less than 8, + * but seemingly only defines 6 and 8 cases */ + if (bsid > 8) { GST_DEBUG_OBJECT (ac3parse, "unexpected bsid=%d", bsid); return FALSE; + } else if (bsid != 8 && bsid != 6) { + GST_DEBUG_OBJECT (ac3parse, "undefined bsid=%d", bsid); } if ((acmod & 0x1) && (acmod != 0x1)) /* 3 front channels */ From aae382bcc6fe579a3df3315024016d2708423624 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Mon, 13 Dec 2010 16:23:37 +0100 Subject: [PATCH 096/448] jpegparse: avoid leaking tag event --- gst/jpegformat/gstjpegparse.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/gst/jpegformat/gstjpegparse.c b/gst/jpegformat/gstjpegparse.c index c1c65391be..5c54776a02 100644 --- a/gst/jpegformat/gstjpegparse.c +++ b/gst/jpegformat/gstjpegparse.c @@ -934,15 +934,17 @@ gst_jpeg_parse_sink_event (GstPad * pad, GstEvent * event) parse->priv->new_segment = TRUE; break; case GST_EVENT_TAG:{ - GstTagList *taglist = NULL; - gst_event_parse_tag (event, &taglist); if (!parse->priv->new_segment) res = gst_pad_event_default (pad, event); else { + GstTagList *taglist = NULL; + + gst_event_parse_tag (event, &taglist); /* Hold on to the tags till the srcpad caps are definitely set */ if (!parse->priv->tags) parse->priv->tags = gst_tag_list_new (); gst_tag_list_insert (parse->priv->tags, taglist, GST_TAG_MERGE_REPLACE); + gst_event_unref (event); } break; } From 6792b0fb1661fb85ccb69cc2a3233cd38bfe69c2 Mon Sep 17 00:00:00 2001 From: Francis Rammeloo Date: Mon, 13 Dec 2010 23:15:05 +0000 Subject: [PATCH 097/448] gdiscreencapsrc: fix memory leak Structure members of ICONINFO struct filled by GetIconInfo() must be deleted when no longer needed according to the API reference. https://bugzilla.gnome.org/show_bug.cgi?id=611428 --- sys/winscreencap/gstgdiscreencapsrc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sys/winscreencap/gstgdiscreencapsrc.c b/sys/winscreencap/gstgdiscreencapsrc.c index 3ead8a9a47..ff9ea7b723 100644 --- a/sys/winscreencap/gstgdiscreencapsrc.c +++ b/sys/winscreencap/gstgdiscreencapsrc.c @@ -541,12 +541,16 @@ gst_gdiscreencapsrc_screen_capture (GstGDIScreenCapSrc * src, GstBuffer * buf) GetCursorInfo (&ci); if (ci.flags & CURSOR_SHOWING) { ICONINFO ii; + GetIconInfo (ci.hCursor, &ii); DrawIconEx (src->memDC, ci.ptScreenPos.x - src->src_rect.left - ii.xHotspot, ci.ptScreenPos.y - src->src_rect.top - ii.yHotspot, ci.hCursor, 0, 0, 0, NULL, DI_DEFAULTSIZE | DI_NORMAL | DI_COMPAT); + + DeleteObject (ii.hbmColor); + DeleteObject (ii.hbmMask); } } From 9fd41486a2406398a8589e7b79760f8c9e4e4d02 Mon Sep 17 00:00:00 2001 From: David Schleef Date: Mon, 13 Dec 2010 23:32:30 -0800 Subject: [PATCH 098/448] y4mdec: Add y4mdec Feel the y4m love. It seeks. It works in pitivi. --- configure.ac | 2 + gst/y4m/Makefile.am | 13 + gst/y4m/gsty4mdec.c | 747 ++++++++++++++++++++++++++++++++++++++++++++ gst/y4m/gsty4mdec.h | 76 +++++ 4 files changed, 838 insertions(+) create mode 100644 gst/y4m/Makefile.am create mode 100644 gst/y4m/gsty4mdec.c create mode 100644 gst/y4m/gsty4mdec.h diff --git a/configure.ac b/configure.ac index 85fc6a3708..8e92c688f8 100644 --- a/configure.ac +++ b/configure.ac @@ -348,6 +348,7 @@ AG_GST_CHECK_PLUGIN(videomaxrate) AG_GST_CHECK_PLUGIN(videomeasure) AG_GST_CHECK_PLUGIN(videosignal) AG_GST_CHECK_PLUGIN(vmnc) +AG_GST_CHECK_PLUGIN(y4m) dnl *** plug-ins to exclude *** @@ -1777,6 +1778,7 @@ gst/videomaxrate/Makefile gst/videomeasure/Makefile gst/videosignal/Makefile gst/vmnc/Makefile +gst/y4m/Makefile gst-libs/Makefile gst-libs/gst/Makefile gst-libs/gst/interfaces/Makefile diff --git a/gst/y4m/Makefile.am b/gst/y4m/Makefile.am new file mode 100644 index 0000000000..e8e52421d8 --- /dev/null +++ b/gst/y4m/Makefile.am @@ -0,0 +1,13 @@ + +plugin_LTLIBRARIES = libgsty4mdec.la + +libgsty4mdec_la_SOURCES = gsty4mdec.c +libgsty4mdec_la_CFLAGS = $(GST_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) +libgsty4mdec_la_LIBADD = \ + $(GST_BASE_PLUGINS_LIBS) -lgstvideo-@GST_MAJORMINOR@ \ + $(GST_BASE_LIBS) -lgstbase-@GST_MAJORMINOR@ \ + $(GST_LIBS) +libgsty4mdec_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) +libgsty4mdec_la_LIBTOOLFLAGS = --tag=disable-static + +noinst_HEADERS = gsty4mdec.h diff --git a/gst/y4m/gsty4mdec.c b/gst/y4m/gsty4mdec.c new file mode 100644 index 0000000000..958512fb32 --- /dev/null +++ b/gst/y4m/gsty4mdec.c @@ -0,0 +1,747 @@ +/* GStreamer + * Copyright (C) 2010 David Schleef + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +/** + * SECTION:element-gsty4mdec + * + * The gsty4mdec element decodes uncompressed video in YUV4MPEG format. + * + * + * Example launch line + * |[ + * gst-launch -v filesrc location=file.y4m ! y4mdec ! xvimagesink + * ]| + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include "gsty4mdec.h" + +#include +#include + +#define MAX_SIZE 32768 + +GST_DEBUG_CATEGORY (y4mdec_debug); +#define GST_CAT_DEFAULT y4mdec_debug + +/* prototypes */ + + +static void gst_y4m_dec_set_property (GObject * object, + guint property_id, const GValue * value, GParamSpec * pspec); +static void gst_y4m_dec_get_property (GObject * object, + guint property_id, GValue * value, GParamSpec * pspec); +static void gst_y4m_dec_dispose (GObject * object); +static void gst_y4m_dec_finalize (GObject * object); + +static GstFlowReturn gst_y4m_dec_chain (GstPad * pad, GstBuffer * buffer); +static gboolean gst_y4m_dec_sink_event (GstPad * pad, GstEvent * event); + +static gboolean gst_y4m_dec_src_event (GstPad * pad, GstEvent * event); +static gboolean gst_y4m_dec_src_query (GstPad * pad, GstQuery * query); + +static GstStateChangeReturn +gst_y4m_dec_change_state (GstElement * element, GstStateChange transition); + +enum +{ + PROP_0 +}; + +/* pad templates */ + +static GstStaticPadTemplate gst_y4m_dec_sink_template = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("application/x-yuv4mpeg, y4mversion=2") + ); + +static GstStaticPadTemplate gst_y4m_dec_src_template = +GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS (GST_VIDEO_CAPS_YUV ("{I420,Y42B,Y444}")) + ); + +/* class initialization */ + +GST_BOILERPLATE (GstY4mDec, gst_y4m_dec, GstElement, GST_TYPE_ELEMENT); + +static void +gst_y4m_dec_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_y4m_dec_src_template)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_y4m_dec_sink_template)); + + gst_element_class_set_details_simple (element_class, + "YUV4MPEG demuxer/decoder", "Codec/Demuxer", + "Demuxes/decodes YUV4MPEG streams", "David Schleef "); +} + +static void +gst_y4m_dec_class_init (GstY4mDecClass * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + + gobject_class->set_property = gst_y4m_dec_set_property; + gobject_class->get_property = gst_y4m_dec_get_property; + gobject_class->dispose = gst_y4m_dec_dispose; + gobject_class->finalize = gst_y4m_dec_finalize; + element_class->change_state = GST_DEBUG_FUNCPTR (gst_y4m_dec_change_state); + +} + +static void +gst_y4m_dec_init (GstY4mDec * y4mdec, GstY4mDecClass * y4mdec_class) +{ + y4mdec->adapter = gst_adapter_new (); + + y4mdec->sinkpad = + gst_pad_new_from_static_template (&gst_y4m_dec_sink_template, "sink"); + gst_pad_set_event_function (y4mdec->sinkpad, + GST_DEBUG_FUNCPTR (gst_y4m_dec_sink_event)); + gst_pad_set_chain_function (y4mdec->sinkpad, + GST_DEBUG_FUNCPTR (gst_y4m_dec_chain)); + gst_element_add_pad (GST_ELEMENT (y4mdec), y4mdec->sinkpad); + + y4mdec->srcpad = gst_pad_new_from_static_template (&gst_y4m_dec_src_template, + "src"); + gst_pad_set_event_function (y4mdec->srcpad, + GST_DEBUG_FUNCPTR (gst_y4m_dec_src_event)); + gst_pad_set_query_function (y4mdec->srcpad, + GST_DEBUG_FUNCPTR (gst_y4m_dec_src_query)); + gst_pad_use_fixed_caps (y4mdec->srcpad); + gst_element_add_pad (GST_ELEMENT (y4mdec), y4mdec->srcpad); + +} + +void +gst_y4m_dec_set_property (GObject * object, guint property_id, + const GValue * value, GParamSpec * pspec) +{ + GstY4mDec *y4mdec; + + g_return_if_fail (GST_IS_Y4M_DEC (object)); + y4mdec = GST_Y4M_DEC (object); + + switch (property_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +void +gst_y4m_dec_get_property (GObject * object, guint property_id, + GValue * value, GParamSpec * pspec) +{ + GstY4mDec *y4mdec; + + g_return_if_fail (GST_IS_Y4M_DEC (object)); + y4mdec = GST_Y4M_DEC (object); + + switch (property_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +void +gst_y4m_dec_dispose (GObject * object) +{ + GstY4mDec *y4mdec; + + g_return_if_fail (GST_IS_Y4M_DEC (object)); + y4mdec = GST_Y4M_DEC (object); + + /* clean up as possible. may be called multiple times */ + if (y4mdec->adapter) { + g_object_unref (y4mdec->adapter); + y4mdec->adapter = NULL; + } + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +void +gst_y4m_dec_finalize (GObject * object) +{ + GstY4mDec *y4mdec; + + g_return_if_fail (GST_IS_Y4M_DEC (object)); + y4mdec = GST_Y4M_DEC (object); + + /* clean up object here */ + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static GstStateChangeReturn +gst_y4m_dec_change_state (GstElement * element, GstStateChange transition) +{ + GstY4mDec *y4mdec; + GstStateChangeReturn ret; + + g_return_val_if_fail (GST_IS_Y4M_DEC (element), GST_STATE_CHANGE_FAILURE); + y4mdec = GST_Y4M_DEC (element); + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + break; + case GST_STATE_CHANGE_READY_TO_PAUSED: + break; + case GST_STATE_CHANGE_PAUSED_TO_PLAYING: + break; + default: + break; + } + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + + switch (transition) { + case GST_STATE_CHANGE_PLAYING_TO_PAUSED: + break; + case GST_STATE_CHANGE_PAUSED_TO_READY: + break; + case GST_STATE_CHANGE_READY_TO_NULL: + break; + default: + break; + } + + return ret; +} + +static GstClockTime +gst_y4m_dec_frames_to_timestamp (GstY4mDec * y4mdec, int frame_index) +{ + return gst_util_uint64_scale (frame_index, GST_SECOND * y4mdec->fps_d, + y4mdec->fps_n); +} + +static int +gst_y4m_dec_timestamp_to_frames (GstY4mDec * y4mdec, GstClockTime timestamp) +{ + return gst_util_uint64_scale (timestamp, y4mdec->fps_n, + GST_SECOND * y4mdec->fps_d); +} + +static int +gst_y4m_dec_bytes_to_frames (GstY4mDec * y4mdec, gint64 bytes) +{ + if (bytes < y4mdec->header_size) + return 0; + return (bytes - y4mdec->header_size) / (y4mdec->frame_size + 6); +} + +static gint64 +gst_y4m_dec_frames_to_bytes (GstY4mDec * y4mdec, int frame_index) +{ + return y4mdec->header_size + (y4mdec->frame_size + 6) * frame_index; +} + +static GstClockTime +gst_y4m_dec_bytes_to_timestamp (GstY4mDec * y4mdec, gint64 bytes) +{ + return gst_y4m_dec_frames_to_timestamp (y4mdec, + gst_y4m_dec_bytes_to_frames (y4mdec, bytes)); +} + + +static gboolean +gst_y4m_dec_parse_header (GstY4mDec * y4mdec, char *header) +{ + char *end; + int format = -1; + int interlaced_char; + + if (memcmp (header, "YUV4MPEG2 ", 10) != 0) { + return FALSE; + } + + header += 10; + while (*header) { + GST_DEBUG_OBJECT (y4mdec, "parsing at '%s'", header); + switch (*header) { + case ' ': + header++; + break; + case 'C': + header++; + format = strtoul (header, &end, 10); + if (end == header) + goto error; + header = end; + break; + case 'W': + header++; + y4mdec->width = strtoul (header, &end, 10); + if (end == header) + goto error; + header = end; + break; + case 'H': + header++; + y4mdec->height = strtoul (header, &end, 10); + if (end == header) + goto error; + header = end; + break; + case 'I': + header++; + if (header[0] == 0) { + GST_WARNING_OBJECT (y4mdec, "Expecting interlaced flag"); + return FALSE; + } + interlaced_char = header[0]; + header++; + break; + case 'F': + header++; + y4mdec->fps_n = strtoul (header, &end, 10); + if (end == header) + goto error; + header = end; + if (header[0] != ':') { + GST_WARNING_OBJECT (y4mdec, "Expecting :"); + return FALSE; + } + header++; + y4mdec->fps_d = strtoul (header, &end, 10); + if (end == header) + goto error; + header = end; + break; + case 'A': + header++; + y4mdec->par_n = strtoul (header, &end, 10); + if (end == header) + goto error; + header = end; + if (header[0] != ':') { + GST_WARNING_OBJECT (y4mdec, "Expecting :"); + return FALSE; + } + header++; + y4mdec->par_d = strtoul (header, &end, 10); + if (end == header) + goto error; + header = end; + break; + default: + GST_WARNING_OBJECT (y4mdec, "Unknown y4m header field '%c', ignoring", + *header); + while (*header && *header != ' ') + header++; + break; + } + } + + switch (format) { + case 420: + y4mdec->format = GST_VIDEO_FORMAT_I420; + break; + case 422: + y4mdec->format = GST_VIDEO_FORMAT_Y42B; + break; + case 444: + y4mdec->format = GST_VIDEO_FORMAT_Y444; + break; + default: + GST_WARNING_OBJECT (y4mdec, "unknown y4m format %d", format); + return FALSE; + } + + if (y4mdec->width <= 0 || y4mdec->width > MAX_SIZE || + y4mdec->height <= 0 || y4mdec->height > MAX_SIZE) { + GST_WARNING_OBJECT (y4mdec, "Dimensions %dx%d out of range", + y4mdec->width, y4mdec->height); + return FALSE; + } + + y4mdec->frame_size = gst_video_format_get_size (y4mdec->format, + y4mdec->width, y4mdec->height); + + switch (interlaced_char) { + case 0: + case '?': + case 'p': + y4mdec->interlaced = FALSE; + break; + case 't': + case 'b': + y4mdec->interlaced = TRUE; + y4mdec->tff = (interlaced_char == 't'); + break; + default: + GST_WARNING_OBJECT (y4mdec, "Unknown interlaced char '%c'", + interlaced_char); + return FALSE; + break; + } + + if (y4mdec->fps_n == 0) + y4mdec->fps_n = 1; + if (y4mdec->fps_d == 0) + y4mdec->fps_d = 1; + if (y4mdec->par_n == 0) + y4mdec->par_n = 1; + if (y4mdec->par_d == 0) + y4mdec->par_d = 1; + + return TRUE; +error: + GST_WARNING_OBJECT (y4mdec, "Expecting number y4m header at '%s'", header); + return FALSE; +} + +static GstFlowReturn +gst_y4m_dec_chain (GstPad * pad, GstBuffer * buffer) +{ + GstY4mDec *y4mdec; + int n_avail; + GstFlowReturn flow_ret = GST_FLOW_OK; +#define MAX_HEADER_LENGTH 80 + char header[MAX_HEADER_LENGTH]; + int i; + int len; + + y4mdec = GST_Y4M_DEC (gst_pad_get_parent (pad)); + + GST_DEBUG_OBJECT (y4mdec, "chain"); + + if (GST_BUFFER_IS_DISCONT (buffer)) { + GST_DEBUG ("got discont"); + gst_adapter_clear (y4mdec->adapter); + } + + gst_adapter_push (y4mdec->adapter, buffer); + n_avail = gst_adapter_available (y4mdec->adapter); + + if (!y4mdec->have_header) { + gboolean ret; + GstCaps *caps; + + if (n_avail < MAX_HEADER_LENGTH) + return GST_FLOW_OK; + + gst_adapter_copy (y4mdec->adapter, (guint8 *) header, 0, MAX_HEADER_LENGTH); + + header[MAX_HEADER_LENGTH - 1] = 0; + for (i = 0; i < MAX_HEADER_LENGTH; i++) { + if (header[i] == 0x0a) + header[i] = 0; + } + + ret = gst_y4m_dec_parse_header (y4mdec, header); + if (!ret) { + GST_ELEMENT_ERROR (y4mdec, STREAM, DECODE, + ("Failed to parse YUV4MPEG header"), (NULL)); + return GST_FLOW_ERROR; + } + + y4mdec->header_size = strlen (header) + 1; + gst_adapter_flush (y4mdec->adapter, y4mdec->header_size); + + caps = gst_video_format_new_caps_interlaced (y4mdec->format, + y4mdec->width, y4mdec->height, + y4mdec->fps_n, y4mdec->fps_d, + y4mdec->par_n, y4mdec->par_d, y4mdec->interlaced); + ret = gst_pad_set_caps (y4mdec->srcpad, caps); + gst_caps_unref (caps); + if (!ret) { + GST_DEBUG_OBJECT (y4mdec, "Couldn't set caps on src pad"); + return GST_FLOW_ERROR; + } + + y4mdec->have_header = TRUE; + } + + if (y4mdec->have_new_segment) { + GstEvent *event; + GstClockTime start = gst_y4m_dec_bytes_to_timestamp (y4mdec, + y4mdec->segment_start); + GstClockTime stop = gst_y4m_dec_bytes_to_timestamp (y4mdec, + y4mdec->segment_stop); + GstClockTime position = gst_y4m_dec_bytes_to_timestamp (y4mdec, + y4mdec->segment_position); + + event = gst_event_new_new_segment (FALSE, 1.0, + GST_FORMAT_TIME, start, stop, position); + + gst_pad_push_event (y4mdec->srcpad, event); + //gst_event_unref (event); + + y4mdec->have_new_segment = FALSE; + y4mdec->frame_index = gst_y4m_dec_bytes_to_frames (y4mdec, + y4mdec->segment_position); + GST_DEBUG ("new frame_index %d", y4mdec->frame_index); + + } + + while (1) { + n_avail = gst_adapter_available (y4mdec->adapter); + if (n_avail < MAX_HEADER_LENGTH) + break; + + gst_adapter_copy (y4mdec->adapter, (guint8 *) header, 0, MAX_HEADER_LENGTH); + header[MAX_HEADER_LENGTH - 1] = 0; + for (i = 0; i < MAX_HEADER_LENGTH; i++) { + if (header[i] == 0x0a) + header[i] = 0; + } + if (memcmp (header, "FRAME", 5) != 0) { + GST_ELEMENT_ERROR (y4mdec, STREAM, DECODE, + ("Failed to parse YUV4MPEG frame"), (NULL)); + flow_ret = GST_FLOW_ERROR; + break; + } + + len = strlen (header); + if (n_avail < y4mdec->frame_size + len + 1) { + /* not enough data */ + GST_DEBUG ("not enough data for frame %d < %d", + n_avail, y4mdec->frame_size + len + 1); + break; + } + + gst_adapter_flush (y4mdec->adapter, len + 1); + + buffer = gst_adapter_take_buffer (y4mdec->adapter, y4mdec->frame_size); + + GST_BUFFER_CAPS (buffer) = gst_caps_ref (GST_PAD_CAPS (y4mdec->srcpad)); + GST_BUFFER_TIMESTAMP (buffer) = + gst_y4m_dec_frames_to_timestamp (y4mdec, y4mdec->frame_index); + GST_BUFFER_DURATION (buffer) = + gst_y4m_dec_frames_to_timestamp (y4mdec, y4mdec->frame_index) - + GST_BUFFER_TIMESTAMP (buffer); + if (y4mdec->interlaced && y4mdec->tff) { + GST_BUFFER_FLAG_SET (buffer, GST_VIDEO_BUFFER_TFF); + } + + y4mdec->frame_index++; + + flow_ret = gst_pad_push (y4mdec->srcpad, buffer); + if (flow_ret != GST_FLOW_OK) + break; + } + + gst_object_unref (y4mdec); + GST_DEBUG ("returning %d", flow_ret); + return flow_ret; +} + +static gboolean +gst_y4m_dec_sink_event (GstPad * pad, GstEvent * event) +{ + gboolean res; + GstY4mDec *y4mdec; + + y4mdec = GST_Y4M_DEC (gst_pad_get_parent (pad)); + + GST_DEBUG_OBJECT (y4mdec, "event"); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_FLUSH_START: + res = gst_pad_push_event (y4mdec->srcpad, event); + break; + case GST_EVENT_FLUSH_STOP: + res = gst_pad_push_event (y4mdec->srcpad, event); + break; + case GST_EVENT_NEWSEGMENT: + { + gboolean update; + gdouble rate; + gdouble applied_rate; + GstFormat format; + gint64 start; + gint64 stop; + gint64 position; + + gst_event_parse_new_segment_full (event, &update, &rate, + &applied_rate, &format, &start, &stop, &position); + + GST_DEBUG ("new_segment: update: %d rate: %g applied_rate: %g " + "format: %d start: %" G_GUINT64_FORMAT " stop: %" G_GUINT64_FORMAT + " position %" G_GUINT64_FORMAT, + update, rate, applied_rate, format, start, stop, position); + + if (format == GST_FORMAT_BYTES) { + y4mdec->segment_start = start; + y4mdec->segment_stop = stop; + y4mdec->segment_position = position; + y4mdec->have_new_segment = TRUE; + } + + res = TRUE; + //res = gst_pad_push_event (y4mdec->srcpad, event); + } + break; + case GST_EVENT_EOS: + res = gst_pad_push_event (y4mdec->srcpad, event); + break; + default: + res = gst_pad_push_event (y4mdec->srcpad, event); + break; + } + + gst_object_unref (y4mdec); + return res; +} + +static gboolean +gst_y4m_dec_src_event (GstPad * pad, GstEvent * event) +{ + gboolean res; + GstY4mDec *y4mdec; + + y4mdec = GST_Y4M_DEC (gst_pad_get_parent (pad)); + + GST_DEBUG_OBJECT (y4mdec, "event"); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_SEEK: + { + gdouble rate; + GstFormat format; + GstSeekFlags flags; + GstSeekType start_type, stop_type; + gint64 start, stop; + int framenum; + guint64 byte; + + gst_event_parse_seek (event, &rate, &format, &flags, &start_type, + &start, &stop_type, &stop); + + if (format != GST_FORMAT_TIME) { + res = FALSE; + break; + } + + framenum = gst_y4m_dec_timestamp_to_frames (y4mdec, start); + GST_DEBUG ("seeking to frame %d", framenum); + + byte = gst_y4m_dec_frames_to_bytes (y4mdec, framenum); + GST_DEBUG ("offset %d", (int) byte); + + gst_event_unref (event); + event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flags, + start_type, byte, stop_type, -1); + + res = gst_pad_push_event (y4mdec->sinkpad, event); + } + break; + default: + res = gst_pad_push_event (y4mdec->sinkpad, event); + break; + } + + gst_object_unref (y4mdec); + return res; +} + +static gboolean +gst_y4m_dec_src_query (GstPad * pad, GstQuery * query) +{ + GstY4mDec *y4mdec = GST_Y4M_DEC (gst_pad_get_parent (pad)); + gboolean res = FALSE; + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_DURATION: + { + GstFormat format; + GstPad *peer; + + GST_DEBUG ("duration query"); + + gst_query_parse_duration (query, &format, NULL); + + if (format != GST_FORMAT_TIME) { + res = FALSE; + GST_DEBUG_OBJECT (y4mdec, "not handling duration query in format %d", + format); + break; + } + + peer = gst_pad_get_peer (y4mdec->sinkpad); + if (peer) { + GstQuery *peer_query = gst_query_new_duration (GST_FORMAT_BYTES); + + res = gst_pad_query (peer, peer_query); + if (res) { + gint64 duration; + int n_frames; + + gst_query_parse_duration (peer_query, &format, &duration); + + n_frames = gst_y4m_dec_bytes_to_frames (y4mdec, duration); + GST_DEBUG ("duration in frames %d", n_frames); + + duration = gst_y4m_dec_frames_to_timestamp (y4mdec, n_frames); + GST_DEBUG ("duration in time %" GST_TIME_FORMAT, + GST_TIME_ARGS (duration)); + + gst_query_set_duration (query, GST_FORMAT_TIME, duration); + res = TRUE; + } + + gst_query_unref (peer_query); + gst_object_unref (peer); + } + break; + } + default: + res = gst_pad_query_default (pad, query); + break; + } + + gst_object_unref (y4mdec); + return res; +} + + +static gboolean +plugin_init (GstPlugin * plugin) +{ + + gst_element_register (plugin, "y4mdec", GST_RANK_SECONDARY, + gst_y4m_dec_get_type ()); + + GST_DEBUG_CATEGORY_INIT (y4mdec_debug, "y4mdec", 0, "y4mdec element"); + + return TRUE; +} + + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "y4mdec", + "FIXME", plugin_init, VERSION, "LGPL", PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/gst/y4m/gsty4mdec.h b/gst/y4m/gsty4mdec.h new file mode 100644 index 0000000000..590a2d6427 --- /dev/null +++ b/gst/y4m/gsty4mdec.h @@ -0,0 +1,76 @@ +/* GStreamer + * Copyright (C) 2010 REAL_NAME + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _GST_Y4M_DEC_H_ +#define _GST_Y4M_DEC_H_ + +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_Y4M_DEC (gst_y4m_dec_get_type()) +#define GST_Y4M_DEC(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_Y4M_DEC,GstY4mDec)) +#define GST_Y4M_DEC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_Y4M_DEC,GstY4mDecClass)) +#define GST_IS_Y4M_DEC(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_Y4M_DEC)) +#define GST_IS_Y4M_DEC_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_Y4M_DEC)) + +typedef struct _GstY4mDec GstY4mDec; +typedef struct _GstY4mDecClass GstY4mDecClass; + +struct _GstY4mDec +{ + GstElement base_y4mdec; + + GstPad *sinkpad; + GstPad *srcpad; + GstAdapter *adapter; + + /* state */ + gboolean have_header; + int frame_index; + int header_size; + + gboolean have_new_segment; + gint64 segment_start; + gint64 segment_stop; + gint64 segment_position; + + int width; + int height; + GstVideoFormat format; + gboolean interlaced; + gboolean tff; + int fps_n; + int fps_d; + int par_n; + int par_d; + int frame_size; +}; + +struct _GstY4mDecClass +{ + GstElementClass base_y4mdec_class; +}; + +GType gst_y4m_dec_get_type (void); + +G_END_DECLS + +#endif From da1fe1e0ddc95b14d132f063c4ddedf4b669f009 Mon Sep 17 00:00:00 2001 From: David Schleef Date: Tue, 14 Dec 2010 19:03:09 -0800 Subject: [PATCH 099/448] element-maker: improve generation of several classes Better creation of pads, test and fix many other classes. Most classes work now, although might not create functional elements. --- tools/Makefile.am | 6 +- tools/element-maker | 78 ++++++--- tools/gstaudiofilter.c | 2 + tools/gstaudiosink.c | 46 ++++-- tools/gstaudiosrc.c | 46 ++++-- tools/gstbaseaudiosink.c | 8 +- tools/gstbaseaudiosrc.c | 7 +- tools/gstbasertpdepayload.c | 2 + tools/gstbasertppayload.c | 2 + tools/gstbasesink.c | 2 + tools/gstbasesrc.c | 2 + tools/gstbasetransform.c | 4 + tools/gstcddabasesrc.c | 2 + tools/gstelement.c | 68 ++++---- tools/gstpushsrc.c | 7 +- tools/gsttagdemux.c | 2 + tools/gstvideosink.c | 2 + tools/sinkpad-simple.c | 23 +++ tools/sinkpad.c | 311 ++++++++++++++++++++++++++++++++++++ tools/srcpad-simple.c | 23 +++ tools/srcpad.c | 274 +++++++++++++++++++++++++++++++ 21 files changed, 816 insertions(+), 101 deletions(-) create mode 100644 tools/sinkpad-simple.c create mode 100644 tools/sinkpad.c create mode 100644 tools/srcpad-simple.c create mode 100644 tools/srcpad.c diff --git a/tools/Makefile.am b/tools/Makefile.am index 54cdae13ec..f501ef3530 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -17,4 +17,8 @@ EXTRA_DIST = \ gstelement.c \ gstpushsrc.c \ gsttagdemux.c \ - gstvideosink.c + gstvideosink.c \ + sinkpad.c \ + sinkpad-simple.c \ + srcpad.c \ + srcpad-simple.c diff --git a/tools/element-maker b/tools/element-maker index 02127a97af..60dc35d3be 100755 --- a/tools/element-maker +++ b/tools/element-maker @@ -73,6 +73,7 @@ source=gst$class.c pkg=`grep -A 10000 '^% pkg-config' $source | tail -n +2|grep -m 1 -B 10000 '^%'|head -n -1` GST_TYPE_BASE_REPLACE=`grep -A 10000 '^% TYPE_CLASS_NAME' $source | tail -n +2|grep -m 1 -B 10000 '^%'|head -n -1` GstBaseReplace=`grep -A 10000 '^% ClassName' $source | tail -n +2|grep -m 1 -B 10000 '^%'|head -n -1` +pads=`grep -A 10000 '^% pads' $source | tail -n +2|grep -m 1 -B 10000 '^%'|head -n -1` generate () { @@ -102,12 +103,12 @@ cat <<-EOF /** * SECTION:element-$gstreplace * - * The $gstreplace element does FIXME stuff. + * The $replace element does FIXME stuff. * * * Example launch line * |[ - * gst-launch -v fakesrc ! $gstreplace ! FIXME ! fakesink + * gst-launch -v fakesrc ! $replace ! FIXME ! fakesink * ]| * FIXME Describe what the pipeline does. * @@ -138,6 +139,10 @@ EOF grep -A 10000 '^% prototypes' base.c | tail -n +2|grep -m 1 -B 10000 '^%'|head -n -1 grep -A 10000 '^% prototypes' gobject.c | tail -n +2|grep -m 1 -B 10000 '^%'|head -n -1 grep -A 10000 '^% prototypes' $source | tail -n +2|grep -m 1 -B 10000 '^%'|head -n -1 +for each in $pads +do + grep -A 10000 '^% prototypes' $each.c | tail -n +2|grep -m 1 -B 10000 '^%'|head -n -1 +done cat <"); +for each in $pads +do + grep -A 10000 '^% base-init' $each.c | tail -n +2|grep -m 1 -B 10000 '^%'|head -n -1 +done + +cat <"); } static void @@ -202,7 +206,15 @@ cat < % prototypes -static gboolean gst_replace_open (GstAudioSrc * src); +static gboolean gst_replace_open (GstAudioSink * sink); static gboolean -gst_replace_prepare (GstAudioSrc * src, GstRingBufferSpec * spec); -static gboolean gst_replace_unprepare (GstAudioSrc * src); -static gboolean gst_replace_close (GstAudioSrc * src); -static guint gst_replace_read (GstAudioSrc * src, gpointer data, guint length); -static guint gst_replace_delay (GstAudioSrc * src); -static void gst_replace_reset (GstAudioSrc * src); +gst_replace_prepare (GstAudioSink * sink, GstRingBufferSpec * spec); +static gboolean gst_replace_unprepare (GstAudioSink * sink); +static gboolean gst_replace_close (GstAudioSink * sink); +static guint gst_replace_write (GstAudioSink * sink, gpointer data, guint length); +static guint gst_replace_delay (GstAudioSink * sink); +static void gst_replace_reset (GstAudioSink * sink); % declare-class - GstAudioSink *audio_sink_class = GST_AUDIO_SINK (klass); + GstAudioSinkClass *audio_sink_class = GST_AUDIO_SINK_CLASS (klass); % set-methods - audio_sink_class-> = GST_DEBUG_FUNCPTR (gst_replace_); + audio_sink_class->open = GST_DEBUG_FUNCPTR (gst_replace_open); + audio_sink_class->prepare = GST_DEBUG_FUNCPTR (gst_replace_prepare); + audio_sink_class->unprepare = GST_DEBUG_FUNCPTR (gst_replace_unprepare); + audio_sink_class->close = GST_DEBUG_FUNCPTR (gst_replace_close); + audio_sink_class->write = GST_DEBUG_FUNCPTR (gst_replace_write); + audio_sink_class->delay = GST_DEBUG_FUNCPTR (gst_replace_delay); + audio_sink_class->reset = GST_DEBUG_FUNCPTR (gst_replace_reset); % methods static gboolean -gst_replace_open (GstAudioSrc * src) +gst_replace_open (GstAudioSink * sink) { + return FALSE; } static gboolean -gst_replace_prepare (GstAudioSrc * src, GstRingBufferSpec * spec) +gst_replace_prepare (GstAudioSink * sink, GstRingBufferSpec * spec) { + return FALSE; } static gboolean -gst_replace_unprepare (GstAudioSrc * src) +gst_replace_unprepare (GstAudioSink * sink) { + return FALSE; } static gboolean -gst_replace_close (GstAudioSrc * src) +gst_replace_close (GstAudioSink * sink) { + return FALSE; } static guint -gst_replace_read (GstAudioSrc * src, gpointer data, guint length) +gst_replace_write (GstAudioSink * sink, gpointer data, guint length) { + return 0; } static guint -gst_replace_delay (GstAudioSrc * src) +gst_replace_delay (GstAudioSink * sink) { + return 0; } static void -gst_replace_reset (GstAudioSrc * src) +gst_replace_reset (GstAudioSink * sink) { } % end diff --git a/tools/gstaudiosrc.c b/tools/gstaudiosrc.c index 95f20e7523..051211e563 100644 --- a/tools/gstaudiosrc.c +++ b/tools/gstaudiosrc.c @@ -2,58 +2,72 @@ GstAudioSrc % TYPE_CLASS_NAME GST_TYPE_AUDIO_SRC +% pads +srcpad-simple % pkg-config gstreamer-audio-0.10 % includes #include % prototypes -static gboolean gst_replace_open (GstAudioSink * sink); +static gboolean gst_replace_open (GstAudioSrc * src); static gboolean -gst_replace_prepare (GstAudioSink * sink, GstRingBufferSpec * spec); -static gboolean gst_replace_unprepare (GstAudioSink * sink); -static gboolean gst_replace_close (GstAudioSink * sink); +gst_replace_prepare (GstAudioSrc * src, GstRingBufferSpec * spec); +static gboolean gst_replace_unprepare (GstAudioSrc * src); +static gboolean gst_replace_close (GstAudioSrc * src); static guint -gst_replace_write (GstAudioSink * sink, gpointer data, guint length); -static guint gst_replace_delay (GstAudioSink * sink); -static void gst_replace_reset (GstAudioSink * sink); +gst_replace_read (GstAudioSrc * src, gpointer data, guint length); +static guint gst_replace_delay (GstAudioSrc * src); +static void gst_replace_reset (GstAudioSrc * src); % declare-class - GstAudioSrc *audio_src_class = GST_AUDIO_SRC (klass); + GstAudioSrcClass *audio_src_class = GST_AUDIO_SRC_CLASS (klass); % set-methods - audio_src_class-> = GST_DEBUG_FUNCPTR (gst_replace_); + audio_src_class->open = GST_DEBUG_FUNCPTR (gst_replace_open); + audio_src_class->prepare = GST_DEBUG_FUNCPTR (gst_replace_prepare); + audio_src_class->unprepare = GST_DEBUG_FUNCPTR (gst_replace_unprepare); + audio_src_class->close = GST_DEBUG_FUNCPTR (gst_replace_close); + audio_src_class->read = GST_DEBUG_FUNCPTR (gst_replace_read); + audio_src_class->delay = GST_DEBUG_FUNCPTR (gst_replace_delay); + audio_src_class->reset = GST_DEBUG_FUNCPTR (gst_replace_reset); % methods static gboolean -gst_replace_open (GstAudioSink * sink) +gst_replace_open (GstAudioSrc * src) { + return FALSE; } static gboolean -gst_replace_prepare (GstAudioSink * sink, GstRingBufferSpec * spec) +gst_replace_prepare (GstAudioSrc * src, GstRingBufferSpec * spec) { + return FALSE; } static gboolean -gst_replace_unprepare (GstAudioSink * sink) +gst_replace_unprepare (GstAudioSrc * src) { + return FALSE; } static gboolean -gst_replace_close (GstAudioSink * sink) +gst_replace_close (GstAudioSrc * src) { + return FALSE; } static guint -gst_replace_write (GstAudioSink * sink, gpointer data, guint length) +gst_replace_read (GstAudioSrc * src, gpointer data, guint length) { + return 0; } static guint -gst_replace_delay (GstAudioSink * sink) +gst_replace_delay (GstAudioSrc * src) { + return 0; } static void -gst_replace_reset (GstAudioSink * sink) +gst_replace_reset (GstAudioSrc * src) { } % end diff --git a/tools/gstbaseaudiosink.c b/tools/gstbaseaudiosink.c index 2f36e84c97..695b685fb0 100644 --- a/tools/gstbaseaudiosink.c +++ b/tools/gstbaseaudiosink.c @@ -2,6 +2,8 @@ GstBaseAudioSink % TYPE_CLASS_NAME GST_TYPE_BASE_AUDIO_SINK +% pads +sinkpad-simple % pkg-config gstreamer-audio-0.10 % includes @@ -9,14 +11,14 @@ gstreamer-audio-0.10 % prototypes static GstRingBuffer *gst_replace_create_ringbuffer (GstBaseAudioSink * sink); % declare-class - GstBaseAudioSink *base_audio_sink_class = GST_BASE_AUDIO_SINK (klass); + GstBaseAudioSinkClass *base_audio_sink_class = GST_BASE_AUDIO_SINK_CLASS (klass); % set-methods - base_audio_sink_class-> = GST_DEBUG_FUNCPTR (gst_replace_); + base_audio_sink_class->create_ringbuffer = GST_DEBUG_FUNCPTR (gst_replace_create_ringbuffer); % methods static GstRingBuffer * gst_replace_create_ringbuffer (GstBaseAudioSink * sink) { - + return NULL; } % end diff --git a/tools/gstbaseaudiosrc.c b/tools/gstbaseaudiosrc.c index c87bb32c02..6ef302b0ef 100644 --- a/tools/gstbaseaudiosrc.c +++ b/tools/gstbaseaudiosrc.c @@ -2,6 +2,8 @@ GstBaseAudioSrc % TYPE_CLASS_NAME GST_TYPE_BASE_AUDIO_SRC +% pads +srcpad-simple % pkg-config gstreamer-audio-0.10 % includes @@ -9,14 +11,15 @@ gstreamer-audio-0.10 % prototypes static GstRingBuffer *gst_replace_create_ringbuffer (GstBaseAudioSrc * src); % declare-class - GstBaseAudioSrc *base_audio_src_class = GST_BASE_AUDIO_SRC (klass); + GstBaseAudioSrcClass *base_audio_src_class = GST_BASE_AUDIO_SRC_CLASS (klass); % set-methods - base_audio_src_class-> = GST_DEBUG_FUNCPTR (gst_replace_); + base_audio_src_class->create_ringbuffer = GST_DEBUG_FUNCPTR (gst_replace_create_ringbuffer); % methods static GstRingBuffer * gst_replace_create_ringbuffer (GstBaseAudioSrc * src) { + return NULL; } % end diff --git a/tools/gstbasertpdepayload.c b/tools/gstbasertpdepayload.c index b0810be259..8257a32719 100644 --- a/tools/gstbasertpdepayload.c +++ b/tools/gstbasertpdepayload.c @@ -2,6 +2,8 @@ GstBaseRTPDepayload % TYPE_CLASS_NAME GST_TYPE_BASE_RTP_DEPAYLOAD +% pads +sinkpad-simple srcpad-simple % pkg-config gstreamer-rtp-0.10 % includes diff --git a/tools/gstbasertppayload.c b/tools/gstbasertppayload.c index a871e901c2..65d216f64c 100644 --- a/tools/gstbasertppayload.c +++ b/tools/gstbasertppayload.c @@ -2,6 +2,8 @@ GstBaseRTPPayload % TYPE_CLASS_NAME GST_TYPE_BASE_RTP_PAYLOAD +% pads +sinkpad-simple srcpad-simple % pkg-config gstreamer-rtp-0.10 % includes diff --git a/tools/gstbasesink.c b/tools/gstbasesink.c index 6646dd9f9e..26ad3f9218 100644 --- a/tools/gstbasesink.c +++ b/tools/gstbasesink.c @@ -2,6 +2,8 @@ GstBaseSink % TYPE_CLASS_NAME GST_TYPE_BASE_SINK +% pads +sinkpad-simple % pkg-config gstreamer-base-0.10 % includes diff --git a/tools/gstbasesrc.c b/tools/gstbasesrc.c index 240a16d258..048e274dd1 100644 --- a/tools/gstbasesrc.c +++ b/tools/gstbasesrc.c @@ -2,6 +2,8 @@ GstBaseSrc % TYPE_CLASS_NAME GST_TYPE_BASE_SRC +% pads +srcpad-simple % pkg-config gstreamer-base-0.10 % includes diff --git a/tools/gstbasetransform.c b/tools/gstbasetransform.c index 47d42d39fe..7dcbc8588a 100644 --- a/tools/gstbasetransform.c +++ b/tools/gstbasetransform.c @@ -2,8 +2,12 @@ GstBaseTransform % TYPE_CLASS_NAME GST_TYPE_BASE_TRANSFORM +% pads +sinkpad-simple srcpad-simple % pkg-config gstreamer-base-0.10 +% pads +sinkpad-simple srcpad-simple % includes #include % prototypes diff --git a/tools/gstcddabasesrc.c b/tools/gstcddabasesrc.c index d0e0a804f3..201a843c96 100644 --- a/tools/gstcddabasesrc.c +++ b/tools/gstcddabasesrc.c @@ -2,6 +2,8 @@ GstCddaBaseSrc % TYPE_CLASS_NAME GST_TYPE_CDDA_BASE_SRC +% pads +srcpad-simple % pkg-config gstreamer-cdda-0.10 % includes diff --git a/tools/gstelement.c b/tools/gstelement.c index 293341cdd9..c9e05c66c0 100644 --- a/tools/gstelement.c +++ b/tools/gstelement.c @@ -2,6 +2,8 @@ GstElement % TYPE_CLASS_NAME GST_TYPE_ELEMENT +% pads +sinkpad srcpad % pkg-config gstreamer-0.10 % includes @@ -11,35 +13,24 @@ static GstPad *gst_replace_request_new_pad (GstElement * element, GstPadTemplate * templ, const gchar * name); static void gst_replace_release_pad (GstElement * element, GstPad * pad); static GstStateChangeReturn -gst_replace_get_state (GstElement * element, GstState * state, - GstState * pending, GstClockTime timeout); -static GstStateChangeReturn -gst_replace_set_state (GstElement * element, GstState state); -static GstStateChangeReturn gst_replace_change_state (GstElement * element, GstStateChange transition); -static void gst_replace_set_bus (GstElement * element, GstBus * bus); static GstClock *gst_replace_provide_clock (GstElement * element); static gboolean gst_replace_set_clock (GstElement * element, GstClock * clock); static GstIndex *gst_replace_get_index (GstElement * element); static void gst_replace_set_index (GstElement * element, GstIndex * index); static gboolean gst_replace_send_event (GstElement * element, GstEvent * event); -static const GstQueryType *gst_replace_get_query_types (GstElement * element); static gboolean gst_replace_query (GstElement * element, GstQuery * query); % declare-class GstElementClass *element_class = GST_ELEMENT_CLASS (klass); % set-methods element_class->request_new_pad = GST_DEBUG_FUNCPTR (gst_replace_request_new_pad); element_class->release_pad = GST_DEBUG_FUNCPTR (gst_replace_release_pad); - element_class->get_state = GST_DEBUG_FUNCPTR (gst_replace_get_state); - element_class->set_state = GST_DEBUG_FUNCPTR (gst_replace_set_state); element_class->change_state = GST_DEBUG_FUNCPTR (gst_replace_change_state); - element_class->set_bus = GST_DEBUG_FUNCPTR (gst_replace_set_bus); element_class->provide_clock = GST_DEBUG_FUNCPTR (gst_replace_provide_clock); element_class->set_clock = GST_DEBUG_FUNCPTR (gst_replace_set_clock); element_class->get_index = GST_DEBUG_FUNCPTR (gst_replace_get_index); element_class->set_index = GST_DEBUG_FUNCPTR (gst_replace_set_index); element_class->send_event = GST_DEBUG_FUNCPTR (gst_replace_send_event); - element_class->get_query_types = GST_DEBUG_FUNCPTR (gst_replace_get_query_types); element_class->query = GST_DEBUG_FUNCPTR (gst_replace_query); % methods @@ -58,32 +49,40 @@ gst_replace_release_pad (GstElement * element, GstPad * pad) } -static GstStateChangeReturn -gst_replace_get_state (GstElement * element, GstState * state, - GstState * pending, GstClockTime timeout) -{ - - return GST_STATE_CHANGE_SUCCESS; -} - -static GstStateChangeReturn -gst_replace_set_state (GstElement * element, GstState state) -{ - - return GST_STATE_CHANGE_SUCCESS; -} - static GstStateChangeReturn gst_replace_change_state (GstElement * element, GstStateChange transition) { + GstReplace *replace; + GstStateChangeReturn ret; - return GST_STATE_CHANGE_SUCCESS; -} + g_return_val_if_fail (GST_IS_REPLACE (element), GST_STATE_CHANGE_FAILURE); + replace = GST_REPLACE (element); -static void -gst_replace_set_bus (GstElement * element, GstBus * bus) -{ + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + break; + case GST_STATE_CHANGE_READY_TO_PAUSED: + break; + case GST_STATE_CHANGE_PAUSED_TO_PLAYING: + break; + default: + break; + } + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + + switch (transition) { + case GST_STATE_CHANGE_PLAYING_TO_PAUSED: + break; + case GST_STATE_CHANGE_PAUSED_TO_READY: + break; + case GST_STATE_CHANGE_READY_TO_NULL: + break; + default: + break; + } + + return ret; } static GstClock * @@ -120,13 +119,6 @@ gst_replace_send_event (GstElement * element, GstEvent * event) return TRUE; } -static const GstQueryType * -gst_replace_get_query_types (GstElement * element) -{ - - return NULL; -} - static gboolean gst_replace_query (GstElement * element, GstQuery * query) { diff --git a/tools/gstpushsrc.c b/tools/gstpushsrc.c index 5db8e76302..a35595085b 100644 --- a/tools/gstpushsrc.c +++ b/tools/gstpushsrc.c @@ -2,6 +2,8 @@ GstPushSrc % TYPE_CLASS_NAME GST_TYPE_PUSH_SRC +% pads +srcpad-simple % pkg-config gstreamer-base-0.10 % includes @@ -9,14 +11,15 @@ gstreamer-base-0.10 % prototypes static GstFlowReturn gst_replace_create (GstPushSrc * src, GstBuffer ** buf); % declare-class - GstPushSrc *pushsrc_class = GST_PUSHSRC (klass); + GstPushSrcClass *pushsrc_class = GST_PUSH_SRC_CLASS (klass); % set-methods - pushsrc_class-> = GST_DEBUG_FUNCPTR (gst_replace_); + pushsrc_class->create = GST_DEBUG_FUNCPTR (gst_replace_create); % methods static GstFlowReturn gst_replace_create (GstPushSrc * src, GstBuffer ** buf) { + return GST_FLOW_OK; } % end diff --git a/tools/gsttagdemux.c b/tools/gsttagdemux.c index 7ddec9d870..6cdfb58d8e 100644 --- a/tools/gsttagdemux.c +++ b/tools/gsttagdemux.c @@ -2,6 +2,8 @@ GstTagDemux % TYPE_CLASS_NAME GST_TYPE_TAG_DEMUX +% pads +sinkpad-simple srcpad-simple % pkg-config gstreamer-tag-0.10 % includes diff --git a/tools/gstvideosink.c b/tools/gstvideosink.c index ce12a07f3e..72a9e88789 100644 --- a/tools/gstvideosink.c +++ b/tools/gstvideosink.c @@ -2,6 +2,8 @@ GstVideoSink % TYPE_CLASS_NAME GST_TYPE_VIDEO_SINK +% pads +sinkpad-simple % pkg-config gstreamer-video-0.10 % includes diff --git a/tools/sinkpad-simple.c b/tools/sinkpad-simple.c new file mode 100644 index 0000000000..9a031fc150 --- /dev/null +++ b/tools/sinkpad-simple.c @@ -0,0 +1,23 @@ + +% instance-members + GstPad *sinkpad; +% prototypes +% pad-template +static GstStaticPadTemplate gst_replace_sink_template = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("application/unknown") + ); + +% base-init + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_replace_sink_template)); +% instance-init + + replace->sinkpad = gst_pad_new_from_static_template (&gst_replace_sink_template + , + "sink"); +% methods +% end + diff --git a/tools/sinkpad.c b/tools/sinkpad.c new file mode 100644 index 0000000000..87babbc7f9 --- /dev/null +++ b/tools/sinkpad.c @@ -0,0 +1,311 @@ + +% instance-members + GstPad *sinkpad; +% prototypes + +static GstCaps* gst_replace_sink_getcaps (GstPad *pad); +static gboolean gst_replace_sink_setcaps (GstPad *pad, GstCaps *caps); +static gboolean gst_replace_sink_acceptcaps (GstPad *pad, GstCaps *caps); +static void gst_replace_sink_fixatecaps (GstPad *pad, GstCaps *caps); +static gboolean gst_replace_sink_activate (GstPad *pad); +static gboolean gst_replace_sink_activatepush (GstPad *pad, gboolean active); +static gboolean gst_replace_sink_activatepull (GstPad *pad, gboolean active); +static GstPadLinkReturn gst_replace_sink_link (GstPad *pad, GstPad *peer); +static void gst_replace_sink_unlink (GstPad *pad); +static GstFlowReturn gst_replace_sink_chain (GstPad *pad, GstBuffer *buffer); +static GstFlowReturn gst_replace_sink_chainlist (GstPad *pad, GstBufferList *bufferlist); +static gboolean gst_replace_sink_event (GstPad *pad, GstEvent *event); +static gboolean gst_replace_sink_query (GstPad *pad, GstQuery *query); +static GstFlowReturn gst_replace_sink_bufferalloc (GstPad *pad, guint64 offset, guint size, + GstCaps *caps, GstBuffer **buf); +static GstIterator * gst_replace_sink_iterintlink (GstPad *pad); + +% pad-template +static GstStaticPadTemplate gst_replace_sink_template = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("application/unknown") + ); + +% base-init + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_replace_sink_template)); +% instance-init + + replace->sinkpad = gst_pad_new_from_static_template (&gst_replace_sink_template + , + "sink"); + gst_pad_set_getcaps_function (replace->sinkpad, + GST_DEBUG_FUNCPTR(gst_replace_sink_getcaps)); + gst_pad_set_setcaps_function (replace->sinkpad, + GST_DEBUG_FUNCPTR(gst_replace_sink_setcaps)); + gst_pad_set_acceptcaps_function (replace->sinkpad, + GST_DEBUG_FUNCPTR(gst_replace_sink_acceptcaps)); + gst_pad_set_fixatecaps_function (replace->sinkpad, + GST_DEBUG_FUNCPTR(gst_replace_sink_fixatecaps)); + gst_pad_set_activate_function (replace->sinkpad, + GST_DEBUG_FUNCPTR(gst_replace_sink_activate)); + gst_pad_set_activatepush_function (replace->sinkpad, + GST_DEBUG_FUNCPTR(gst_replace_sink_activatepush)); + gst_pad_set_activatepull_function (replace->sinkpad, + GST_DEBUG_FUNCPTR(gst_replace_sink_activatepull)); + gst_pad_set_link_function (replace->sinkpad, + GST_DEBUG_FUNCPTR(gst_replace_sink_link)); + gst_pad_set_unlink_function (replace->sinkpad, + GST_DEBUG_FUNCPTR(gst_replace_sink_unlink)); + gst_pad_set_chain_function (replace->sinkpad, + GST_DEBUG_FUNCPTR(gst_replace_sink_chain)); + gst_pad_set_chain_list_function (replace->sinkpad, + GST_DEBUG_FUNCPTR(gst_replace_sink_chainlist)); + gst_pad_set_event_function (replace->sinkpad, + GST_DEBUG_FUNCPTR(gst_replace_sink_event)); + gst_pad_set_query_function (replace->sinkpad, + GST_DEBUG_FUNCPTR(gst_replace_sink_query)); + gst_pad_set_bufferalloc_function (replace->sinkpad, + GST_DEBUG_FUNCPTR(gst_replace_sink_bufferalloc)); + gst_pad_set_iterate_internal_links_function (replace->sinkpad, + GST_DEBUG_FUNCPTR(gst_replace_sink_iterintlink)); + gst_element_add_pad (GST_ELEMENT(replace), replace->sinkpad); + + +% methods + +static GstCaps* +gst_replace_sink_getcaps (GstPad *pad) +{ + GstReplace *replace; + GstCaps *caps; + + replace = GST_REPLACE (gst_pad_get_parent (pad)); + + GST_DEBUG_OBJECT(replace, "getcaps"); + + caps = gst_caps_copy (gst_pad_get_pad_template_caps (pad)); + + gst_object_unref (replace); + return caps; +} + +static gboolean +gst_replace_sink_setcaps (GstPad *pad, GstCaps *caps) +{ + GstReplace *replace; + + replace = GST_REPLACE (gst_pad_get_parent (pad)); + + GST_DEBUG_OBJECT(replace, "setcaps"); + + + gst_object_unref (replace); + return TRUE; +} + +static gboolean +gst_replace_sink_acceptcaps (GstPad *pad, GstCaps *caps) +{ + GstReplace *replace; + + replace = GST_REPLACE (gst_pad_get_parent (pad)); + + GST_DEBUG_OBJECT(replace, "acceptcaps"); + + + gst_object_unref (replace); + return TRUE; +} + +static void +gst_replace_sink_fixatecaps (GstPad *pad, GstCaps *caps) +{ + GstReplace *replace; + + replace = GST_REPLACE (gst_pad_get_parent (pad)); + + GST_DEBUG_OBJECT(replace, "fixatecaps"); + + + gst_object_unref (replace); +} + +static gboolean +gst_replace_sink_activate (GstPad *pad) +{ + GstReplace *replace; + gboolean ret; + + replace = GST_REPLACE (gst_pad_get_parent (pad)); + + GST_DEBUG_OBJECT(replace, "activate"); + + if (gst_pad_check_pull_range (pad)) { + GST_DEBUG_OBJECT (pad, "activating pull"); + ret = gst_pad_activate_pull (pad, TRUE); + } else { + GST_DEBUG_OBJECT (pad, "activating push"); + ret = gst_pad_activate_push (pad, TRUE); + } + + gst_object_unref (replace); + return ret; +} + +static gboolean +gst_replace_sink_activatepush (GstPad *pad, gboolean active) +{ + GstReplace *replace; + + replace = GST_REPLACE (gst_pad_get_parent (pad)); + + GST_DEBUG_OBJECT(replace, "activatepush"); + + + gst_object_unref (replace); + return TRUE; +} + +static gboolean +gst_replace_sink_activatepull (GstPad *pad, gboolean active) +{ + GstReplace *replace; + + replace = GST_REPLACE (gst_pad_get_parent (pad)); + + GST_DEBUG_OBJECT(replace, "activatepull"); + + + gst_object_unref (replace); + return TRUE; +} + +static GstPadLinkReturn +gst_replace_sink_link (GstPad *pad, GstPad *peer) +{ + GstReplace *replace; + + replace = GST_REPLACE (gst_pad_get_parent (pad)); + + GST_DEBUG_OBJECT(replace, "link"); + + + gst_object_unref (replace); + return GST_PAD_LINK_OK; +} + +static void +gst_replace_sink_unlink (GstPad *pad) +{ + GstReplace *replace; + + replace = GST_REPLACE (gst_pad_get_parent (pad)); + + GST_DEBUG_OBJECT(replace, "unlink"); + + + gst_object_unref (replace); +} + +static GstFlowReturn +gst_replace_sink_chain (GstPad *pad, GstBuffer *buffer) +{ + GstReplace *replace; + + replace = GST_REPLACE (gst_pad_get_parent (pad)); + + GST_DEBUG_OBJECT(replace, "chain"); + + + gst_object_unref (replace); + return GST_FLOW_OK; +} + +static GstFlowReturn +gst_replace_sink_chainlist (GstPad *pad, GstBufferList *bufferlist) +{ + GstReplace *replace; + + replace = GST_REPLACE (gst_pad_get_parent (pad)); + + GST_DEBUG_OBJECT(replace, "chainlist"); + + + gst_object_unref (replace); + return GST_FLOW_OK; +} + +static gboolean +gst_replace_sink_event (GstPad *pad, GstEvent *event) +{ + gboolean res; + GstReplace *replace; + + replace = GST_REPLACE (gst_pad_get_parent (pad)); + + GST_DEBUG_OBJECT(replace, "event"); + + switch (GST_EVENT_TYPE (event)) { + default: + res = gst_pad_event_default (pad, event); + break; + } + + gst_object_unref (replace); + return res; +} + +static gboolean +gst_replace_sink_query (GstPad *pad, GstQuery *query) +{ + gboolean res; + GstReplace *replace; + + replace = GST_REPLACE (gst_pad_get_parent (pad)); + + GST_DEBUG_OBJECT(replace, "query"); + + switch (GST_QUERY_TYPE(query)) { + default: + res = gst_pad_query_default (pad, query); + break; + } + + gst_object_unref (replace); + return res; +} + +static GstFlowReturn +gst_replace_sink_bufferalloc (GstPad *pad, guint64 offset, guint size, + GstCaps *caps, GstBuffer **buf) +{ + GstReplace *replace; + + replace = GST_REPLACE (gst_pad_get_parent (pad)); + + GST_DEBUG_OBJECT(replace, "bufferalloc"); + + + *buf = gst_buffer_new_and_alloc (size); + gst_buffer_set_caps (*buf, caps); + + gst_object_unref (replace); + return GST_FLOW_OK; +} + +static GstIterator * +gst_replace_sink_iterintlink (GstPad *pad) +{ + GstReplace *replace; + GstIterator *iter; + + replace = GST_REPLACE (gst_pad_get_parent (pad)); + + GST_DEBUG_OBJECT(replace, "iterintlink"); + + iter = gst_pad_iterate_internal_links_default (pad); + + gst_object_unref (replace); + return iter; +} + +% end + diff --git a/tools/srcpad-simple.c b/tools/srcpad-simple.c new file mode 100644 index 0000000000..42db8d385b --- /dev/null +++ b/tools/srcpad-simple.c @@ -0,0 +1,23 @@ + +% instance-members + GstPad *srcpad; +% prototypes +% pad-template +static GstStaticPadTemplate gst_replace_src_template = +GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("application/unknown") + ); + +% base-init + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_replace_src_template)); +% instance-init + + replace->srcpad = gst_pad_new_from_static_template (&gst_replace_src_template + , + "src"); +% methods +% end + diff --git a/tools/srcpad.c b/tools/srcpad.c new file mode 100644 index 0000000000..61cbd21326 --- /dev/null +++ b/tools/srcpad.c @@ -0,0 +1,274 @@ + +% instance-members + GstPad *srcpad; +% prototypes + +static GstCaps* gst_replace_src_getcaps (GstPad *pad); +static gboolean gst_replace_src_setcaps (GstPad *pad, GstCaps *caps); +static gboolean gst_replace_src_acceptcaps (GstPad *pad, GstCaps *caps); +static void gst_replace_src_fixatecaps (GstPad *pad, GstCaps *caps); +static gboolean gst_replace_src_activate (GstPad *pad); +static gboolean gst_replace_src_activatepush (GstPad *pad, gboolean active); +static gboolean gst_replace_src_activatepull (GstPad *pad, gboolean active); +static GstPadLinkReturn gst_replace_src_link (GstPad *pad, GstPad *peer); +static void gst_replace_src_unlink (GstPad *pad); +static GstFlowReturn gst_replace_src_getrange (GstPad *pad, guint64 offset, guint length, + GstBuffer **buffer); +static gboolean gst_replace_src_event (GstPad *pad, GstEvent *event); +static gboolean gst_replace_src_query (GstPad *pad, GstQuery *query); +static GstIterator * gst_replace_src_iterintlink (GstPad *pad); + +% pad-template +static GstStaticPadTemplate gst_replace_src_template = +GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("application/unknown") + ); + +% base-init + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_replace_src_template)); +% instance-init + + replace->srcpad = gst_pad_new_from_static_template (&gst_replace_src_template + , + "src"); + gst_pad_set_getcaps_function (replace->srcpad, + GST_DEBUG_FUNCPTR(gst_replace_src_getcaps)); + gst_pad_set_setcaps_function (replace->srcpad, + GST_DEBUG_FUNCPTR(gst_replace_src_setcaps)); + gst_pad_set_acceptcaps_function (replace->srcpad, + GST_DEBUG_FUNCPTR(gst_replace_src_acceptcaps)); + gst_pad_set_fixatecaps_function (replace->srcpad, + GST_DEBUG_FUNCPTR(gst_replace_src_fixatecaps)); + gst_pad_set_activate_function (replace->srcpad, + GST_DEBUG_FUNCPTR(gst_replace_src_activate)); + gst_pad_set_activatepush_function (replace->srcpad, + GST_DEBUG_FUNCPTR(gst_replace_src_activatepush)); + gst_pad_set_activatepull_function (replace->srcpad, + GST_DEBUG_FUNCPTR(gst_replace_src_activatepull)); + gst_pad_set_link_function (replace->srcpad, + GST_DEBUG_FUNCPTR(gst_replace_src_link)); + gst_pad_set_unlink_function (replace->srcpad, + GST_DEBUG_FUNCPTR(gst_replace_src_unlink)); + gst_pad_set_getrange_function (replace->srcpad, + GST_DEBUG_FUNCPTR(gst_replace_src_getrange)); + gst_pad_set_event_function (replace->srcpad, + GST_DEBUG_FUNCPTR(gst_replace_src_event)); + gst_pad_set_query_function (replace->srcpad, + GST_DEBUG_FUNCPTR(gst_replace_src_query)); + gst_pad_set_iterate_internal_links_function (replace->srcpad, + GST_DEBUG_FUNCPTR(gst_replace_src_iterintlink)); + gst_element_add_pad (GST_ELEMENT(replace), replace->srcpad); + + +% methods + +static GstCaps* +gst_replace_src_getcaps (GstPad *pad) +{ + GstReplace *replace; + GstCaps *caps; + + replace = GST_REPLACE (gst_pad_get_parent (pad)); + + GST_DEBUG_OBJECT(replace, "getcaps"); + + caps = gst_caps_copy (gst_pad_get_pad_template_caps (pad)); + + gst_object_unref (replace); + return caps; +} + +static gboolean +gst_replace_src_setcaps (GstPad *pad, GstCaps *caps) +{ + GstReplace *replace; + + replace = GST_REPLACE (gst_pad_get_parent (pad)); + + GST_DEBUG_OBJECT(replace, "setcaps"); + + + gst_object_unref (replace); + return TRUE; +} + +static gboolean +gst_replace_src_acceptcaps (GstPad *pad, GstCaps *caps) +{ + GstReplace *replace; + + replace = GST_REPLACE (gst_pad_get_parent (pad)); + + GST_DEBUG_OBJECT(replace, "acceptcaps"); + + + gst_object_unref (replace); + return TRUE; +} + +static void +gst_replace_src_fixatecaps (GstPad *pad, GstCaps *caps) +{ + GstReplace *replace; + + replace = GST_REPLACE (gst_pad_get_parent (pad)); + + GST_DEBUG_OBJECT(replace, "fixatecaps"); + + + gst_object_unref (replace); +} + +static gboolean +gst_replace_src_activate (GstPad *pad) +{ + GstReplace *replace; + gboolean ret; + + replace = GST_REPLACE (gst_pad_get_parent (pad)); + + GST_DEBUG_OBJECT(replace, "activate"); + + if (gst_pad_check_pull_range (pad)) { + GST_DEBUG_OBJECT (pad, "activating pull"); + ret = gst_pad_activate_pull (pad, TRUE); + } else { + GST_DEBUG_OBJECT (pad, "activating push"); + ret = gst_pad_activate_push (pad, TRUE); + } + + gst_object_unref (replace); + return ret; +} + +static gboolean +gst_replace_src_activatepush (GstPad *pad, gboolean active) +{ + GstReplace *replace; + + replace = GST_REPLACE (gst_pad_get_parent (pad)); + + GST_DEBUG_OBJECT(replace, "activatepush"); + + + gst_object_unref (replace); + return TRUE; +} + +static gboolean +gst_replace_src_activatepull (GstPad *pad, gboolean active) +{ + GstReplace *replace; + + replace = GST_REPLACE (gst_pad_get_parent (pad)); + + GST_DEBUG_OBJECT(replace, "activatepull"); + + + gst_object_unref (replace); + return TRUE; +} + +static GstPadLinkReturn +gst_replace_src_link (GstPad *pad, GstPad *peer) +{ + GstReplace *replace; + + replace = GST_REPLACE (gst_pad_get_parent (pad)); + + GST_DEBUG_OBJECT(replace, "link"); + + + gst_object_unref (replace); + return GST_PAD_LINK_OK; +} + +static void +gst_replace_src_unlink (GstPad *pad) +{ + GstReplace *replace; + + replace = GST_REPLACE (gst_pad_get_parent (pad)); + + GST_DEBUG_OBJECT(replace, "unlink"); + + + gst_object_unref (replace); +} + +static GstFlowReturn +gst_replace_src_getrange (GstPad *pad, guint64 offset, guint length, + GstBuffer **buffer) +{ + GstReplace *replace; + + replace = GST_REPLACE (gst_pad_get_parent (pad)); + + GST_DEBUG_OBJECT(replace, "getrange"); + + + gst_object_unref (replace); + return GST_FLOW_OK; +} + +static gboolean +gst_replace_src_event (GstPad *pad, GstEvent *event) +{ + gboolean res; + GstReplace *replace; + + replace = GST_REPLACE (gst_pad_get_parent (pad)); + + GST_DEBUG_OBJECT(replace, "event"); + + switch (GST_EVENT_TYPE (event)) { + default: + res = gst_pad_event_default (pad, event); + break; + } + + gst_object_unref (replace); + return res; +} + +static gboolean +gst_replace_src_query (GstPad *pad, GstQuery *query) +{ + gboolean res; + GstReplace *replace; + + replace = GST_REPLACE (gst_pad_get_parent (pad)); + + GST_DEBUG_OBJECT(replace, "query"); + + switch (GST_QUERY_TYPE(query)) { + default: + res = gst_pad_query_default (pad, query); + break; + } + + gst_object_unref (replace); + return res; +} + +static GstIterator * +gst_replace_src_iterintlink (GstPad *pad) +{ + GstReplace *replace; + GstIterator *iter; + + replace = GST_REPLACE (gst_pad_get_parent (pad)); + + GST_DEBUG_OBJECT(replace, "iterintlink"); + + iter = gst_pad_iterate_internal_links_default (pad); + + gst_object_unref (replace); + return iter; +} + +% end + From e1eb27f18f495a150220c6df85e1464d3cde9de9 Mon Sep 17 00:00:00 2001 From: Stefan Kost Date: Wed, 15 Dec 2010 14:56:19 +0200 Subject: [PATCH 100/448] Automatic update of common submodule From 20742ae to 169462a --- common | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common b/common index 20742aee03..169462a62f 160000 --- a/common +++ b/common @@ -1 +1 @@ -Subproject commit 20742aee033cc7c4aa9a817df005d15d5fa6ba85 +Subproject commit 169462a62f8b3cb91d721092af13530a3f72a462 From a7baa891a90fe20b648d6ad3e84b09a27c0ed162 Mon Sep 17 00:00:00 2001 From: Edward Hervey Date: Wed, 15 Dec 2010 16:48:15 +0100 Subject: [PATCH 101/448] rsvgoverlay: Don't set uint on an int property --- ext/rsvg/gstrsvgoverlay.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/rsvg/gstrsvgoverlay.c b/ext/rsvg/gstrsvgoverlay.c index d5c707824c..60fd1676d2 100644 --- a/ext/rsvg/gstrsvgoverlay.c +++ b/ext/rsvg/gstrsvgoverlay.c @@ -196,10 +196,10 @@ gst_rsvg_overlay_get_property (GObject * object, guint prop_id, GValue * value, switch (prop_id) { case PROP_X: - g_value_set_uint (value, overlay->x_offset); + g_value_set_int (value, overlay->x_offset); break; case PROP_Y: - g_value_set_uint (value, overlay->y_offset); + g_value_set_int (value, overlay->y_offset); break; case PROP_FIT_TO_FRAME: g_value_set_boolean (value, overlay->fit_to_frame); From 2f6f78caa323e76f09fbb1c19b302afd37ccfd2e Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Fri, 10 Dec 2010 12:27:54 +0100 Subject: [PATCH 102/448] dvbsuboverlay: fix luma stride for scaled subtitles (display width != width) --- gst/dvbsuboverlay/gstdvbsuboverlay.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gst/dvbsuboverlay/gstdvbsuboverlay.c b/gst/dvbsuboverlay/gstdvbsuboverlay.c index 3f261e58b4..f18dd0178e 100644 --- a/gst/dvbsuboverlay/gstdvbsuboverlay.c +++ b/gst/dvbsuboverlay/gstdvbsuboverlay.c @@ -667,8 +667,8 @@ blit_i420 (GstDVBSubOverlay * overlay, DVBSubtitles * subs, GstBuffer * buffer) sy += 2 * ystep; - dst_y += y_stride + (y_stride - w); - dst_y2 += y_stride + (y_stride - w); + dst_y += y_stride + (y_stride - dw); + dst_y2 += y_stride + (y_stride - dw); dst_u += u_stride - w2; dst_v += v_stride - w2; } From 83a84ba230763184bd30c036ae2af9598fe1edb4 Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Sat, 11 Dec 2010 17:10:25 +0100 Subject: [PATCH 103/448] dvbsuboverlay: implement display definition segment parsing --- gst/dvbsuboverlay/dvb-sub.c | 57 +++++++++++++++++++++++++++++++++++++ gst/dvbsuboverlay/dvb-sub.h | 28 ++++++++++++++++++ 2 files changed, 85 insertions(+) diff --git a/gst/dvbsuboverlay/dvb-sub.c b/gst/dvbsuboverlay/dvb-sub.c index 4c28ddde95..f9fe13b6d6 100644 --- a/gst/dvbsuboverlay/dvb-sub.c +++ b/gst/dvbsuboverlay/dvb-sub.c @@ -189,6 +189,7 @@ struct _DvbSubPrivate int display_list_size; DVBSubRegionDisplay *display_list; GString *pes_buffer; + DVBSubtitleWindow display_def; }; #define DVB_SUB_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), DVB_TYPE_SUB, DvbSubPrivate)) @@ -329,6 +330,12 @@ dvb_sub_init (DvbSub * self) priv->object_list = NULL; priv->page_time_out = 0; /* FIXME: Maybe 255 instead? */ priv->pes_buffer = g_string_new (NULL); + + /* display/window information */ + priv->display_def.version = -1; + priv->display_def.window_flag = 0; + priv->display_def.display_width = 720; + priv->display_def.display_height = 576; } static void @@ -1248,6 +1255,46 @@ _dvb_sub_parse_object_segment (DvbSub * dvb_sub, guint16 page_id, guint8 * buf, } } +static gint +_dvb_sub_parse_display_definition_segment (DvbSub * dvb_sub, guint8 * buf, + gint buf_size) +{ + int dds_version, info_byte; + DvbSubPrivate *ctx = dvb_sub->private_data; + + if (buf_size < 5) + return -1; + + info_byte = *buf++; + dds_version = info_byte >> 4; + + if (ctx->display_def.version == dds_version) + return 0; /* already have this display definition version */ + + ctx->display_def.version = dds_version; + ctx->display_def.display_width = GST_READ_UINT16_BE (buf) + 1; + buf += 2; + ctx->display_def.display_height = GST_READ_UINT16_BE (buf) + 1; + buf += 2; + + ctx->display_def.window_flag = info_byte & 1 << 3; + + if (buf_size >= 13 && ctx->display_def.window_flag) { + ctx->display_def.window_x = GST_READ_UINT16_BE (buf); + buf += 2; + ctx->display_def.window_y = GST_READ_UINT16_BE (buf); + buf += 2; + ctx->display_def.window_width = + GST_READ_UINT16_BE (buf) - ctx->display_def.window_x + 1; + buf += 2; + ctx->display_def.window_height = + GST_READ_UINT16_BE (buf) - ctx->display_def.window_y + 1; + buf += 2; + } + + return 0; +} + static gint _dvb_sub_parse_end_of_display_set (DvbSub * dvb_sub, guint16 page_id, guint8 * buf, gint buf_size, guint64 pts) @@ -1286,6 +1333,9 @@ _dvb_sub_parse_end_of_display_set (DvbSub * dvb_sub, guint16 page_id, i = 0; + /* copy subtitle display and window information */ + sub->display_def = priv->display_def; + for (display = priv->display_list; display; display = display->next) { region = get_region (dvb_sub, display->region_id); rect = sub->rects[i]; @@ -1405,6 +1455,7 @@ dvb_sub_new (void) #define DVB_SUB_SEGMENT_REGION_COMPOSITION 0x11 #define DVB_SUB_SEGMENT_CLUT_DEFINITION 0x12 #define DVB_SUB_SEGMENT_OBJECT_DATA 0x13 +#define DVB_SUB_SEGMENT_DISPLAY_DEFINITION 0x14 #define DVB_SUB_SEGMENT_END_OF_DISPLAY_SET 0x80 #define DVB_SUB_SEGMENT_STUFFING 0xFF @@ -1503,6 +1554,12 @@ dvb_sub_feed_with_pts (DvbSub * dvb_sub, guint64 pts, guint8 * data, gint len) "Object data segment at buffer pos %u\n", pos); _dvb_sub_parse_object_segment (dvb_sub, page_id, data + pos, segment_len); /* FIXME: Not sure about args */ break; + case DVB_SUB_SEGMENT_DISPLAY_DEFINITION: + dvb_log (DVB_LOG_PACKET, G_LOG_LEVEL_DEBUG, + "display definition segment at buffer pos %u\n", pos); + _dvb_sub_parse_display_definition_segment (dvb_sub, data + pos, + segment_len); + break; case DVB_SUB_SEGMENT_END_OF_DISPLAY_SET: dvb_log (DVB_LOG_PACKET, G_LOG_LEVEL_DEBUG, "End of display set at buffer pos %u\n", pos); diff --git a/gst/dvbsuboverlay/dvb-sub.h b/gst/dvbsuboverlay/dvb-sub.h index ffee9106e8..887ffe80b5 100644 --- a/gst/dvbsuboverlay/dvb-sub.h +++ b/gst/dvbsuboverlay/dvb-sub.h @@ -93,6 +93,33 @@ typedef struct DVBSubtitleRect { DVBSubtitlePicture pict; } DVBSubtitleRect; +/** + * DVBSubtitleWindow + * @version: version + * @display_window_flag: window_* are valid + * @display_width: assumed width of display + * @display_height: assumed height of display + * @window_x: x coordinate of top left corner of the subtitle window + * @window_y: y coordinate of top left corner of the subtitle window + * @window_width: width of the subtitle window + * @window_height: height of the subtitle window + * + * A structure presenting display and window information + * display definition segment from ETSI EN 300 743 V1.3.1 + */ +typedef struct DVBSubtitleWindow { + gint version; + gint window_flag; + + gint display_width; + gint display_height; + + gint window_x; + gint window_y; + gint window_width; + gint window_height; +} DVBSubtitleWindow; + /** * DVBSubtitles: * @num_rects: the number of #DVBSubtitleRect in @rects @@ -105,6 +132,7 @@ typedef struct DVBSubtitles { guint8 page_time_out; unsigned int num_rects; DVBSubtitleRect **rects; + DVBSubtitleWindow display_def; } DVBSubtitles; /** From 4d8220b03335f1dd432d811de6cd3299357f1391 Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Sat, 11 Dec 2010 17:25:29 +0100 Subject: [PATCH 104/448] dvbsuboverlay: scale subtitles according to the display size Display size is either transmitted in the display definition segment or implicitly defined to 720x576. The subtitle window information also present in the display definition segment is not yet used. --- gst/dvbsuboverlay/gstdvbsuboverlay.c | 37 +++++++++++----------------- 1 file changed, 15 insertions(+), 22 deletions(-) diff --git a/gst/dvbsuboverlay/gstdvbsuboverlay.c b/gst/dvbsuboverlay/gstdvbsuboverlay.c index f18dd0178e..9980e677ff 100644 --- a/gst/dvbsuboverlay/gstdvbsuboverlay.c +++ b/gst/dvbsuboverlay/gstdvbsuboverlay.c @@ -480,7 +480,7 @@ blit_i420 (GstDVBSubOverlay * overlay, DVBSubtitles * subs, GstBuffer * buffer) guint32 color; const guint8 *src; guint8 *dst_y, *dst_y2, *dst_u, *dst_v; - gint x, y, w, h; + gint x, y; gint w2, h2; gint width = overlay->width; gint height = overlay->height; @@ -518,7 +518,7 @@ blit_i420 (GstDVBSubOverlay * overlay, DVBSubtitles * subs, GstBuffer * buffer) v_stride = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_I420, 2, width); for (counter = 0; counter < subs->num_rects; counter++) { - gint dw, dh; + gint dw, dh, dx, dy; gint32 sx = 0, sy; /* 16.16 fixed point */ gint32 xstep, ystep; /* 16.16 fixed point */ @@ -527,18 +527,16 @@ blit_i420 (GstDVBSubOverlay * overlay, DVBSubtitles * subs, GstBuffer * buffer) continue; /* blend subtitles onto the video frame */ - w = MIN (sub_region->w, width - sub_region->x); - h = MIN (sub_region->h, height - sub_region->y); + dx = sub_region->x * width / subs->display_def.display_width; + dy = sub_region->y * height / subs->display_def.display_height; - /* TODO - dw = MIN (sub_region->dw, width - sub_region->x); - dh = MIN (sub_region->dh, height - sub_region->y); - */ - dw = w; - dh = h; + dw = MIN (sub_region->w * width / subs->display_def.display_width, + width - dx); + dh = MIN (sub_region->h * height / subs->display_def.display_height, + height - dy); - xstep = (w << 16) / dw; - ystep = (h << 16) / dh; + xstep = (sub_region->w << 16) / dw; + ystep = (sub_region->h << 16) / dh; w2 = (dw + 1) / 2; h2 = (dh + 1) / 2; @@ -546,21 +544,16 @@ blit_i420 (GstDVBSubOverlay * overlay, DVBSubtitles * subs, GstBuffer * buffer) src_stride = sub_region->pict.rowstride; src = sub_region->pict.data; - dst_y = buffer->data + y_offset + sub_region->y * y_stride + sub_region->x; - dst_y2 = - buffer->data + y_offset + (sub_region->y + 1) * y_stride + - sub_region->x; - dst_u = - buffer->data + u_offset + ((sub_region->y + 1) / 2) * u_stride + - (sub_region->x + 1) / 2; - dst_v = - buffer->data + v_offset + ((sub_region->y + 1) / 2) * v_stride + - (sub_region->x + 1) / 2; + dst_y = buffer->data + y_offset + dy * y_stride + dx; + dst_y2 = buffer->data + y_offset + (dy + 1) * y_stride + dx; + dst_u = buffer->data + u_offset + ((dy + 1) / 2) * u_stride + (dx + 1) / 2; + dst_v = buffer->data + v_offset + ((dy + 1) / 2) * v_stride + (dx + 1) / 2; sy = 0; for (y = 0; y < dh - 1; y += 2) { sx = 0; for (x = 0; x < dw - 1; x += 2) { + color = sub_region->pict.palette[src[(sy >> 16) * src_stride + (sx >> 16)]]; a1 = (color >> 24) & 0xff; From 36b101cfb8dc7afb7a4f4ad191d162b16c00df94 Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Tue, 14 Dec 2010 11:11:08 +0100 Subject: [PATCH 105/448] dvbsuboverlay: implement display definition segment subtitle windows simplifies subtitle scaling in blit_i420() --- gst/dvbsuboverlay/gstdvbsuboverlay.c | 38 +++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 6 deletions(-) diff --git a/gst/dvbsuboverlay/gstdvbsuboverlay.c b/gst/dvbsuboverlay/gstdvbsuboverlay.c index 9980e677ff..926de1ba8e 100644 --- a/gst/dvbsuboverlay/gstdvbsuboverlay.c +++ b/gst/dvbsuboverlay/gstdvbsuboverlay.c @@ -488,6 +488,8 @@ blit_i420 (GstDVBSubOverlay * overlay, DVBSubtitles * subs, GstBuffer * buffer) gint y_offset, y_height, y_width, y_stride; gint u_offset, u_height, u_width, u_stride; gint v_offset, v_height, v_width, v_stride; + gint scale = 0; + gint scale_x, scale_y; /* 16.16 fixed point */ y_offset = gst_video_format_get_component_offset (GST_VIDEO_FORMAT_I420, 0, width, @@ -517,6 +519,18 @@ blit_i420 (GstDVBSubOverlay * overlay, DVBSubtitles * subs, GstBuffer * buffer) u_stride = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_I420, 1, width); v_stride = gst_video_format_get_row_stride (GST_VIDEO_FORMAT_I420, 2, width); + if (width != subs->display_def.display_width && + height != subs->display_def.display_height) { + scale = 1; + if (subs->display_def.window_flag) { + scale_x = (width << 16) / subs->display_def.window_width; + scale_y = (height << 16) / subs->display_def.window_height; + } else { + scale_x = (width << 16) / subs->display_def.display_width; + scale_y = (height << 16) / subs->display_def.display_height; + } + } + for (counter = 0; counter < subs->num_rects; counter++) { gint dw, dh, dx, dy; gint32 sx = 0, sy; /* 16.16 fixed point */ @@ -527,13 +541,25 @@ blit_i420 (GstDVBSubOverlay * overlay, DVBSubtitles * subs, GstBuffer * buffer) continue; /* blend subtitles onto the video frame */ - dx = sub_region->x * width / subs->display_def.display_width; - dy = sub_region->y * height / subs->display_def.display_height; + dx = sub_region->x; + dy = sub_region->y; + dw = sub_region->w; + dh = sub_region->h; - dw = MIN (sub_region->w * width / subs->display_def.display_width, - width - dx); - dh = MIN (sub_region->h * height / subs->display_def.display_height, - height - dy); + if (scale) { + dx = (dx * scale_x) >> 16; + dy = (dy * scale_y) >> 16; + dw = (dw * scale_x) >> 16; + dh = (dh * scale_y) >> 16; + /* apply subtitle window offsets after scaling */ + if (subs->display_def.window_flag) { + dx += subs->display_def.window_x; + dy += subs->display_def.window_y; + } + } + + dw = MIN (dw, width - dx); + dh = MIN (dh, height - dx); xstep = (sub_region->w << 16) / dw; ystep = (sub_region->h << 16) / dh; From 533453186e4c2eed4522ee52ca74793875754dc5 Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Tue, 14 Dec 2010 14:28:45 +0100 Subject: [PATCH 106/448] dvbsuboverlay: add property to limit page_time_out to a setable maximum --- gst/dvbsuboverlay/gstdvbsuboverlay.c | 17 ++++++++++++++++- gst/dvbsuboverlay/gstdvbsuboverlay.h | 1 + 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/gst/dvbsuboverlay/gstdvbsuboverlay.c b/gst/dvbsuboverlay/gstdvbsuboverlay.c index 926de1ba8e..28bf84f3ef 100644 --- a/gst/dvbsuboverlay/gstdvbsuboverlay.c +++ b/gst/dvbsuboverlay/gstdvbsuboverlay.c @@ -54,7 +54,8 @@ enum enum { PROP_0, - PROP_ENABLE + PROP_ENABLE, + PROP_MAX_PAGE_TIMEOUT, }; static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src", @@ -144,6 +145,11 @@ gst_dvbsub_overlay_class_init (GstDVBSubOverlayClass * klass) "Enable rendering of subtitles", TRUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_MAX_PAGE_TIMEOUT, + g_param_spec_int ("max-page-timeout", "max-page-timeout", + "Limit maximum display time of a subtitle page (0 - disabled, value in seconds)", + 0, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_dvbsub_overlay_change_state); } @@ -285,6 +291,9 @@ gst_dvbsub_overlay_set_property (GObject * object, guint prop_id, case PROP_ENABLE: overlay->enable = g_value_get_boolean (value); break; + case PROP_MAX_PAGE_TIMEOUT: + g_atomic_int_set (&overlay->max_page_timeout, g_value_get_int (value)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -301,6 +310,9 @@ gst_dvbsub_overlay_get_property (GObject * object, guint prop_id, case PROP_ENABLE: g_value_set_boolean (value, overlay->enable); break; + case PROP_MAX_PAGE_TIMEOUT: + g_value_set_int (value, g_atomic_int_get (&overlay->max_page_timeout)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -815,6 +827,9 @@ new_dvb_subtitles_cb (DvbSub * dvb_sub, DVBSubtitles * subs, gpointer user_data) { GstDVBSubOverlay *overlay = GST_DVBSUB_OVERLAY (user_data); + if (overlay->max_page_timeout > 0) + subs->page_time_out = MIN (subs->page_time_out, overlay->max_page_timeout); + GST_INFO_OBJECT (overlay, "New DVB subtitles arrived with a page_time_out of %d and %d regions for PTS=%" G_GUINT64_FORMAT ", which should be at running time %" GST_TIME_FORMAT, diff --git a/gst/dvbsuboverlay/gstdvbsuboverlay.h b/gst/dvbsuboverlay/gstdvbsuboverlay.h index 1b2b0b0669..19835c6c66 100644 --- a/gst/dvbsuboverlay/gstdvbsuboverlay.h +++ b/gst/dvbsuboverlay/gstdvbsuboverlay.h @@ -43,6 +43,7 @@ struct _GstDVBSubOverlay /* properties */ gboolean enable; + gint max_page_timeout; /* */ GstSegment video_segment; From 9b3b1aedeab86f6567c551c650b36e03a4d98aee Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Tue, 14 Dec 2010 14:34:56 +0100 Subject: [PATCH 107/448] dvbsuboverlay: use atomic instructions to set/get enable property --- gst/dvbsuboverlay/gstdvbsuboverlay.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gst/dvbsuboverlay/gstdvbsuboverlay.c b/gst/dvbsuboverlay/gstdvbsuboverlay.c index 28bf84f3ef..4b8ce840ee 100644 --- a/gst/dvbsuboverlay/gstdvbsuboverlay.c +++ b/gst/dvbsuboverlay/gstdvbsuboverlay.c @@ -289,7 +289,7 @@ gst_dvbsub_overlay_set_property (GObject * object, guint prop_id, switch (prop_id) { case PROP_ENABLE: - overlay->enable = g_value_get_boolean (value); + g_atomic_int_set (&overlay->enable, g_value_get_boolean (value)); break; case PROP_MAX_PAGE_TIMEOUT: g_atomic_int_set (&overlay->max_page_timeout, g_value_get_int (value)); @@ -308,7 +308,7 @@ gst_dvbsub_overlay_get_property (GObject * object, guint prop_id, switch (prop_id) { case PROP_ENABLE: - g_value_set_boolean (value, overlay->enable); + g_value_set_int (value, g_atomic_int_get (&overlay->enable)); break; case PROP_MAX_PAGE_TIMEOUT: g_value_set_int (value, g_atomic_int_get (&overlay->max_page_timeout)); From eaf1b316b0d2b009242db3b792f58f13a326e55a Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Wed, 15 Dec 2010 14:23:58 +0100 Subject: [PATCH 108/448] mpegtsdemux: enable gather_pes only for DVB subtitle private streams --- gst/mpegdemux/gstmpegtsdemux.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/gst/mpegdemux/gstmpegtsdemux.c b/gst/mpegdemux/gstmpegtsdemux.c index 0dd8d7d337..a863fd38d7 100644 --- a/gst/mpegdemux/gstmpegtsdemux.c +++ b/gst/mpegdemux/gstmpegtsdemux.c @@ -1471,12 +1471,18 @@ gst_mpegts_stream_parse_pmt (GstMpegTSStream * stream, /* set adaptor */ GST_LOG ("Initializing PES filter for PID %u", ES_stream->PID); gst_pes_filter_init (&ES_stream->filter, NULL, NULL); + if (ES_stream->stream_type == ST_PRIVATE_DATA) { - GST_FIXME ("Stream type is ST_PRIVATE_DATA, setting " - "filter->gather_pes as a HACK"); - /* FIXME: There's another place where pes filters could get - * initialized. Might need similar temporary hack there as well */ - ES_stream->filter.gather_pes = TRUE; + guint8 *dvb_sub_desc = gst_mpeg_descriptor_find (ES_stream->ES_info, + DESC_DVB_SUBTITLING); + + /* enable gather PES for DVB subtitles since the dvbsuboverlay + * expects complete PES packets */ + if (dvb_sub_desc) { + /* FIXME: There's another place where pes filters could get + * initialized. Might need similar temporary hack there as well */ + ES_stream->filter.gather_pes = TRUE; + } } gst_pes_filter_set_callbacks (&ES_stream->filter, (GstPESFilterData) gst_mpegts_demux_data_cb, From 431ea2c697b92c622bca4a1f3d0cadfebbb88d9a Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Wed, 15 Dec 2010 14:39:56 +0100 Subject: [PATCH 109/448] mpegtsdemux: add DESC_DVB_SUBTITLING descriptor for language parsing --- gst/mpegdemux/gstmpegtsdemux.c | 41 ++++++++++++++++++---------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/gst/mpegdemux/gstmpegtsdemux.c b/gst/mpegdemux/gstmpegtsdemux.c index a863fd38d7..18e1f6b969 100644 --- a/gst/mpegdemux/gstmpegtsdemux.c +++ b/gst/mpegdemux/gstmpegtsdemux.c @@ -948,29 +948,32 @@ gst_mpegts_demux_send_tags_for_stream (GstMpegTSDemux * demux, GstTagList *list = NULL; if (stream->ES_info) { - guint8 *iso639_languages = - gst_mpeg_descriptor_find (stream->ES_info, DESC_ISO_639_LANGUAGE); - if (iso639_languages) { - if (DESC_ISO_639_LANGUAGE_codes_n (iso639_languages)) { - const gchar *lc; - gchar lang_code[4]; - gchar *language_n; + guint8 lang_descs[] = { DESC_ISO_639_LANGUAGE, DESC_DVB_SUBTITLING }; + for (gint i = 0; i < sizeof (lang_descs); i++) { + guint8 *iso639_languages = + gst_mpeg_descriptor_find (stream->ES_info, lang_descs[i]); + if (iso639_languages) { + if (DESC_ISO_639_LANGUAGE_codes_n (iso639_languages)) { + const gchar *lc; + gchar lang_code[4]; + gchar *language_n; - language_n = (gchar *) - DESC_ISO_639_LANGUAGE_language_code_nth (iso639_languages, 0); + language_n = (gchar *) + DESC_ISO_639_LANGUAGE_language_code_nth (iso639_languages, 0); - lang_code[0] = language_n[0]; - lang_code[1] = language_n[1]; - lang_code[2] = language_n[2]; - lang_code[3] = 0; + lang_code[0] = language_n[0]; + lang_code[1] = language_n[1]; + lang_code[2] = language_n[2]; + lang_code[3] = 0; - if (!list) - list = gst_tag_list_new (); + if (!list) + list = gst_tag_list_new (); - /* descriptor contains ISO 639-2 code, we want the ISO 639-1 code */ - lc = gst_tag_get_language_code (lang_code); - gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, - GST_TAG_LANGUAGE_CODE, (lc) ? lc : lang_code, NULL); + /* descriptor contains ISO 639-2 code, we want the ISO 639-1 code */ + lc = gst_tag_get_language_code (lang_code); + gst_tag_list_add (list, GST_TAG_MERGE_REPLACE, + GST_TAG_LANGUAGE_CODE, (lc) ? lc : lang_code, NULL); + } } } } From 61c2b173c6ff0fa26e58c97a142bc7de198fa8a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Wed, 15 Dec 2010 20:49:57 +0100 Subject: [PATCH 110/448] mpegtsdemux: Mark array static const and use G_N_ELEMENTS instead of sizeof --- gst/mpegdemux/gstmpegtsdemux.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/gst/mpegdemux/gstmpegtsdemux.c b/gst/mpegdemux/gstmpegtsdemux.c index 18e1f6b969..b0c872e6b9 100644 --- a/gst/mpegdemux/gstmpegtsdemux.c +++ b/gst/mpegdemux/gstmpegtsdemux.c @@ -948,8 +948,9 @@ gst_mpegts_demux_send_tags_for_stream (GstMpegTSDemux * demux, GstTagList *list = NULL; if (stream->ES_info) { - guint8 lang_descs[] = { DESC_ISO_639_LANGUAGE, DESC_DVB_SUBTITLING }; - for (gint i = 0; i < sizeof (lang_descs); i++) { + static const guint8 lang_descs[] = + { DESC_ISO_639_LANGUAGE, DESC_DVB_SUBTITLING }; + for (gint i = 0; i < G_N_ELEMENTS (lang_descs); i++) { guint8 *iso639_languages = gst_mpeg_descriptor_find (stream->ES_info, lang_descs[i]); if (iso639_languages) { From e9fa2fcd8bdf46f7ce9c9989c2cc7d62d30b9661 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Wed, 15 Dec 2010 20:51:12 +0100 Subject: [PATCH 111/448] dvbsuboverlay: Use g_atomic_int_get() for reading the max_page_timeout field --- gst/dvbsuboverlay/gstdvbsuboverlay.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gst/dvbsuboverlay/gstdvbsuboverlay.c b/gst/dvbsuboverlay/gstdvbsuboverlay.c index 4b8ce840ee..eb825a8896 100644 --- a/gst/dvbsuboverlay/gstdvbsuboverlay.c +++ b/gst/dvbsuboverlay/gstdvbsuboverlay.c @@ -828,7 +828,8 @@ new_dvb_subtitles_cb (DvbSub * dvb_sub, DVBSubtitles * subs, gpointer user_data) GstDVBSubOverlay *overlay = GST_DVBSUB_OVERLAY (user_data); if (overlay->max_page_timeout > 0) - subs->page_time_out = MIN (subs->page_time_out, overlay->max_page_timeout); + subs->page_time_out = MIN (subs->page_time_out, + g_atomic_int_get (&overlay->max_page_timeout)); GST_INFO_OBJECT (overlay, "New DVB subtitles arrived with a page_time_out of %d and %d regions for PTS=%" From 65598884d2296a72c5d34751c983871b04680008 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Wed, 15 Dec 2010 20:53:21 +0100 Subject: [PATCH 112/448] dvbsuboverlay: Add #defines for the property default values --- gst/dvbsuboverlay/gstdvbsuboverlay.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/gst/dvbsuboverlay/gstdvbsuboverlay.c b/gst/dvbsuboverlay/gstdvbsuboverlay.c index eb825a8896..6bd9565077 100644 --- a/gst/dvbsuboverlay/gstdvbsuboverlay.c +++ b/gst/dvbsuboverlay/gstdvbsuboverlay.c @@ -58,6 +58,9 @@ enum PROP_MAX_PAGE_TIMEOUT, }; +#define DEFAULT_ENABLE (TRUE) +#define DEFAULT_MAX_PAGE_TIMEOUT (0) + static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, @@ -142,13 +145,14 @@ gst_dvbsub_overlay_class_init (GstDVBSubOverlayClass * klass) gobject_class->finalize = gst_dvbsub_overlay_finalize; g_object_class_install_property (gobject_class, PROP_ENABLE, g_param_spec_boolean ("enable", "Enable", /* FIXME: "enable" vs "silent"? */ - "Enable rendering of subtitles", TRUE, + "Enable rendering of subtitles", DEFAULT_ENABLE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (gobject_class, PROP_MAX_PAGE_TIMEOUT, g_param_spec_int ("max-page-timeout", "max-page-timeout", "Limit maximum display time of a subtitle page (0 - disabled, value in seconds)", - 0, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + 0, G_MAXINT, DEFAULT_MAX_PAGE_TIMEOUT, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_dvbsub_overlay_change_state); @@ -249,7 +253,8 @@ gst_dvbsub_overlay_init (GstDVBSubOverlay * render, render->current_subtitle = NULL; render->pending_subtitles = g_queue_new (); - render->enable = TRUE; + render->enable = DEFAULT_ENABLE; + render->max_page_timeout = DEFAULT_MAX_PAGE_TIMEOUT; render->dvbsub_mutex = g_mutex_new (); gst_dvbsub_overlay_flush_subtitles (render); From a71c3f7e483209699811f9e9bc2da9479e7f997d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Wed, 15 Dec 2010 20:54:35 +0100 Subject: [PATCH 113/448] dvbsuboverlay: Don't draw anything on the video if the enable property is set to FALSE --- gst/dvbsuboverlay/gstdvbsuboverlay.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst/dvbsuboverlay/gstdvbsuboverlay.c b/gst/dvbsuboverlay/gstdvbsuboverlay.c index 6bd9565077..b9a1d7c428 100644 --- a/gst/dvbsuboverlay/gstdvbsuboverlay.c +++ b/gst/dvbsuboverlay/gstdvbsuboverlay.c @@ -1033,7 +1033,7 @@ gst_dvbsub_overlay_chain_video (GstPad * pad, GstBuffer * buffer) } /* Now render it */ - if (overlay->current_subtitle) { + if (g_atomic_int_get (&overlay->enable) && overlay->current_subtitle) { buffer = gst_buffer_make_writable (buffer); blit_i420 (overlay, overlay->current_subtitle, buffer); } From 18061222b9edeea846dc0dcc0bfb7c3121db9773 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Wed, 15 Dec 2010 21:11:11 +0100 Subject: [PATCH 114/448] mpegtsdemux: Rename DVB subtitling media type to subpicture/x-dvb --- gst/mpegdemux/gstmpegtsdemux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst/mpegdemux/gstmpegtsdemux.c b/gst/mpegdemux/gstmpegtsdemux.c index b0c872e6b9..863547078a 100644 --- a/gst/mpegdemux/gstmpegtsdemux.c +++ b/gst/mpegdemux/gstmpegtsdemux.c @@ -671,7 +671,7 @@ gst_mpegts_demux_fill_stream (GstMpegTSStream * stream, guint8 id, DESC_DVB_SUBTITLING)) { template = klass->private_template; name = g_strdup_printf ("private_%04x", stream->PID); - caps = gst_caps_new_simple ("private/x-dvbsub", NULL); + caps = gst_caps_new_simple ("subpicture/x-dvb", NULL); } break; case ST_HDV_AUX_V: From a99e13cd5a9596137d6d8ba9d2974932f20c296c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Wed, 15 Dec 2010 21:11:29 +0100 Subject: [PATCH 115/448] dvbsuboverlay: Rename DVB subtitling media type to subpicture/x-dvb --- gst/dvbsuboverlay/gstdvbsuboverlay.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gst/dvbsuboverlay/gstdvbsuboverlay.c b/gst/dvbsuboverlay/gstdvbsuboverlay.c index b9a1d7c428..6cf1d78ea6 100644 --- a/gst/dvbsuboverlay/gstdvbsuboverlay.c +++ b/gst/dvbsuboverlay/gstdvbsuboverlay.c @@ -27,7 +27,7 @@ * |[ FIXME * gst-launch -v filesrc location=/path/to/ts ! mpegtsdemux name=d ! queue ! mp3parse ! mad ! audioconvert ! autoaudiosink \ * d. ! queue ! mpeg2dec ! ffmpegcolorspace ! r. \ - * d. ! queue ! "private/x-dvbsub" ! dvbsuboverlay name=r ! ffmpegcolorspace ! autovideosink + * d. ! queue ! "subpicture/x-dvb" ! dvbsuboverlay name=r ! ffmpegcolorspace ! autovideosink * ]| This pipeline demuxes a MPEG-TS file with MPEG2 video, MP3 audio and embedded DVB subtitles and renders the subtitles on top of the video. * */ @@ -78,7 +78,7 @@ static GstStaticPadTemplate text_sink_factory = GST_STATIC_PAD_TEMPLATE ("text_sink", GST_PAD_SINK, GST_PAD_ALWAYS, - GST_STATIC_CAPS ("private/x-dvbsub") + GST_STATIC_CAPS ("subpicture/x-dvb") ); static void gst_dvbsub_overlay_set_property (GObject * object, guint prop_id, @@ -873,7 +873,7 @@ gst_dvbsub_overlay_chain_text (GstPad * pad, GstBuffer * buffer) GstDVBSubOverlay *overlay = GST_DVBSUB_OVERLAY (GST_PAD_PARENT (pad)); GstClockTime sub_running_time; - GST_INFO_OBJECT (overlay, "private/x-dvbsub buffer with size %u", + GST_INFO_OBJECT (overlay, "subpicture/x-dvb buffer with size %u", GST_BUFFER_SIZE (buffer)); GST_LOG_OBJECT (overlay, From 27ac6c3e473bcf5472cfb5c7817c122349d44531 Mon Sep 17 00:00:00 2001 From: Benjamin Gaignard Date: Wed, 15 Dec 2010 21:14:38 +0100 Subject: [PATCH 116/448] autocolorspace: Add autoconvert based video format convert element Fixes bug #636106. --- gst/autoconvert/Makefile.am | 2 +- gst/autoconvert/gstautocolorspace.c | 242 ++++++++++++++++++++++++++++ gst/autoconvert/gstautocolorspace.h | 55 +++++++ gst/autoconvert/gstautoconvert.c | 2 + gst/autoconvert/plugin.c | 46 ++++++ 5 files changed, 346 insertions(+), 1 deletion(-) create mode 100644 gst/autoconvert/gstautocolorspace.c create mode 100644 gst/autoconvert/gstautocolorspace.h create mode 100644 gst/autoconvert/plugin.c diff --git a/gst/autoconvert/Makefile.am b/gst/autoconvert/Makefile.am index 28fc01557e..e92d8a6a70 100644 --- a/gst/autoconvert/Makefile.am +++ b/gst/autoconvert/Makefile.am @@ -1,6 +1,6 @@ plugin_LTLIBRARIES = libgstautoconvert.la -libgstautoconvert_la_SOURCES = gstautoconvert.c gstautoconvert.h +libgstautoconvert_la_SOURCES = gstautoconvert.c gstautoconvert.h gstautocolorspace.c gstautcolorspace.h plugin.c libgstautoconvert_la_CFLAGS = $(GST_CFLAGS) libgstautoconvert_la_LIBADD = $(GST_LIBS) diff --git a/gst/autoconvert/gstautocolorspace.c b/gst/autoconvert/gstautocolorspace.c new file mode 100644 index 0000000000..0ea615a39d --- /dev/null +++ b/gst/autoconvert/gstautocolorspace.c @@ -0,0 +1,242 @@ +/* GStreamer + * Copyright 2010 ST-Ericsson SA + * @author: Benjamin Gaignard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +/* + * test autocolorspace: + * if rgb2bayer is present + * gst-launch videotestsrc num-buffers=2 ! "video/x-raw-rgb,width=100,height=100,framerate=10/1" ! autocolorspace ! "video/x-raw-bayer,width=100,height=100,format=bggr,framerate=10/1" ! fakesink -v + * if bayer2rgb is present + * gst-launch videotestsrc num-buffers=2 ! "video/x-raw-bayer,width=100,height=100,format=bggr,framerate=10/1" ! autocolorspace ! "video/x-raw-rgb,width=100,height=100,framerate=10/1" ! fakesink -v + * test with ffmpegcolorspace + * gst-launch videotestsrc num-buffers=2 ! "video/x-raw-rgb,bpp=32,width=100,height=100,framerate=10/1" ! autocolorspace ! "video/x-raw-rgb,bpp=16,width=100,height=100,framerate=10/1" ! fakesink -v + */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "gstautocolorspace.h" + +GST_DEBUG_CATEGORY (autocolorspace_debug); +#define GST_CAT_DEFAULT (autocolorspace_debug) + +GStaticMutex factories_mutex = G_STATIC_MUTEX_INIT; +guint32 factories_cookie = 0; /* Cookie from last time when factories was updated */ +GList *factories = NULL; /* factories we can use for selecting elements */ + +/* element factory information */ +static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + + +static GstStateChangeReturn gst_auto_color_space_change_state (GstElement * + element, GstStateChange transition); + +void gst_auto_color_space_update_factory_list (GstAutoColorSpace * + autocolorspace); + +static gboolean +gst_auto_color_space_element_filter (GstPluginFeature * feature, + GstAutoColorSpace * autocolorspace) +{ + const gchar *klass; + + /* we only care about element factories */ + if (G_UNLIKELY (!GST_IS_ELEMENT_FACTORY (feature))) + return FALSE; + + klass = gst_element_factory_get_klass (GST_ELEMENT_FACTORY_CAST (feature)); + /* only select color space converter */ + if (strstr (klass, "Filter") && + strstr (klass, "Converter") && strstr (klass, "Video")) { + GST_DEBUG_OBJECT (autocolorspace, + "gst_auto_color_space_element_filter found %s\n", + gst_plugin_feature_get_name (GST_PLUGIN_FEATURE_CAST (feature))); + return TRUE; + } + return FALSE; +} + + +static GList * +gst_auto_color_space_create_factory_list (GstAutoColorSpace * autocolorspace) +{ + GList *result = NULL; + + /* get the feature list using the filter */ + result = gst_default_registry_feature_filter ((GstPluginFeatureFilter) + gst_auto_color_space_element_filter, FALSE, autocolorspace); + + /* sort on rank and name */ + result = g_list_sort (result, gst_plugin_feature_rank_compare_func); + + return result; +} + +void +gst_auto_color_space_update_factory_list (GstAutoColorSpace * autocolorspace) +{ + /* use a static mutex to protect factories list and factories cookie */ + g_static_mutex_lock (&factories_mutex); + + /* test if a factories list already exist or not */ + if (!factories) { + /* no factories list create it */ + factories_cookie = gst_default_registry_get_feature_list_cookie (); + factories = gst_auto_color_space_create_factory_list (autocolorspace); + } else { + /* a factories list exist but is it up to date? */ + if (factories_cookie != gst_default_registry_get_feature_list_cookie ()) { + /* we need to update the factories list */ + /* first free the old one */ + gst_plugin_feature_list_free (factories); + /* then create an updated one */ + factories_cookie = gst_default_registry_get_feature_list_cookie (); + factories = gst_auto_color_space_create_factory_list (autocolorspace); + } + } + + g_static_mutex_unlock (&factories_mutex); +} + +GST_BOILERPLATE (GstAutoColorSpace, gst_auto_color_space, GstBin, GST_TYPE_BIN); + +static void +gst_auto_color_space_base_init (gpointer klass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&srctemplate)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&sinktemplate)); + + gst_element_class_set_details_simple (element_class, + "Select color space convertor based on caps", "Generic/Bin", + "Selects the right color space convertor based on the caps", + "Benjamin Gaignard "); +} + +static void +gst_auto_color_space_dispose (GObject * object) +{ + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +gst_auto_color_space_class_init (GstAutoColorSpaceClass * klass) +{ + GObjectClass *gobject_class = (GObjectClass *) klass; + GstElementClass *gstelement_class = (GstElementClass *) klass; + + gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_auto_color_space_dispose); + + GST_DEBUG_CATEGORY_INIT (autocolorspace_debug, "autocolorspace", 0, + "Auto color space converter"); + + gstelement_class->change_state = + GST_DEBUG_FUNCPTR (gst_auto_color_space_change_state); + +} + +static void +gst_auto_color_space_add_autoconvert (GstAutoColorSpace * autocolorspace) +{ + GstPad *pad; + + autocolorspace->autoconvert = + gst_element_factory_make ("autoconvert", "autoconvertchild"); + + /* first add autoconvert in bin */ + gst_bin_add (GST_BIN (autocolorspace), autocolorspace->autoconvert); + + /* get sinkpad and link it to ghost sink pad */ + pad = gst_element_get_static_pad (autocolorspace->autoconvert, "sink"); + gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (autocolorspace->sinkpad), pad); + gst_object_unref (pad); + + /* get srcpad and link it to ghost src pad */ + pad = gst_element_get_static_pad (autocolorspace->autoconvert, "src"); + gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (autocolorspace->srcpad), pad); + gst_object_unref (pad); +} + +static void +gst_auto_color_space_init (GstAutoColorSpace * autocolorspace, + GstAutoColorSpaceClass * klass) +{ + GstPadTemplate *pad_tmpl; + + /* get sink pad template */ + pad_tmpl = gst_static_pad_template_get (&sinktemplate); + autocolorspace->sinkpad = + gst_ghost_pad_new_no_target_from_template ("sink", pad_tmpl); + /* add sink ghost pad */ + gst_element_add_pad (GST_ELEMENT (autocolorspace), autocolorspace->sinkpad); + + /* get src pad template */ + pad_tmpl = gst_static_pad_template_get (&srctemplate); + autocolorspace->srcpad = + gst_ghost_pad_new_no_target_from_template ("src", pad_tmpl); + /* add src ghost pad */ + gst_element_add_pad (GST_ELEMENT (autocolorspace), autocolorspace->srcpad); + + return; +} + +static GstStateChangeReturn +gst_auto_color_space_change_state (GstElement * element, + GstStateChange transition) +{ + GstAutoColorSpace *autocolorspace = GST_AUTO_COLOR_SPACE (element); + GstStateChangeReturn ret; + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + if (ret == GST_STATE_CHANGE_FAILURE) + return ret; + + switch (transition) { + case GST_STATE_CHANGE_NULL_TO_READY: + { + /* create and add autoconvert in bin */ + gst_auto_color_space_add_autoconvert (autocolorspace); + /* get an updated list of factories */ + gst_auto_color_space_update_factory_list (autocolorspace); + GST_DEBUG_OBJECT (autocolorspace, "set factories list"); + /* give factory list to autoconvert */ + g_object_set (GST_ELEMENT (autocolorspace->autoconvert), "factories", + factories, NULL); + /* synchronize autoconvert state with parent state */ + gst_element_sync_state_with_parent (autocolorspace->autoconvert); + break; + } + default: + break; + } + + return ret; +} diff --git a/gst/autoconvert/gstautocolorspace.h b/gst/autoconvert/gstautocolorspace.h new file mode 100644 index 0000000000..b14e4bd16b --- /dev/null +++ b/gst/autoconvert/gstautocolorspace.h @@ -0,0 +1,55 @@ +/* GStreamer + * Copyright 2010 ST-Ericsson SA + * @author: Benjamin Gaignard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_AUTO_COLOR_SPACE_H__ +#define __GST_AUTO_COLOR_SPACE_H__ + +#include +#include +#include "gstautoconvert.h" + +G_BEGIN_DECLS +#define GST_TYPE_AUTO_COLOR_SPACE (gst_auto_color_space_get_type()) +#define GST_AUTO_COLOR_SPACE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_AUTO_COLOR_SPACE,GstAutoColorSpace)) +#define GST_AUTO_COLOR_SPACE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_AUTO_COLOR_SPACE,GstAutoColorSpaceClass)) +#define GST_IS_AUTO_COLOR_SPACE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_AUTO_COLOR_SPACE)) +#define GST_IS_AUTO_COLOR_SPACE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_AUTO_COLOR_SPACE)) +typedef struct _GstAutoColorSpace GstAutoColorSpace; +typedef struct _GstAutoColorSpaceClass GstAutoColorSpaceClass; + +struct _GstAutoColorSpace +{ + /*< private > */ + GstBin bin; /* we extend GstBin */ + + GstElement *autoconvert; + GstPad *sinkpad; + GstPad *srcpad; +}; + +struct _GstAutoColorSpaceClass +{ + GstBinClass parent_class; +}; + +GType gst_auto_color_space_get_type (void); + +G_END_DECLS +#endif /* __GST_AUTO_COLOR_SPACE_H__ */ diff --git a/gst/autoconvert/gstautoconvert.c b/gst/autoconvert/gstautoconvert.c index 3c254f6de9..5a7a2eea99 100644 --- a/gst/autoconvert/gstautoconvert.c +++ b/gst/autoconvert/gstautoconvert.c @@ -1552,6 +1552,7 @@ gst_auto_convert_internal_src_query_type (GstPad * pad) return ret; } +/* static gboolean gst_auto_convert_plugin_init (GstPlugin * plugin) { @@ -1565,3 +1566,4 @@ GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, "Selects convertor element based on caps", gst_auto_convert_plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) +*/ diff --git a/gst/autoconvert/plugin.c b/gst/autoconvert/plugin.c new file mode 100644 index 0000000000..dd2ca033b7 --- /dev/null +++ b/gst/autoconvert/plugin.c @@ -0,0 +1,46 @@ +/* GStreamer + * Copyright 2010 ST-Ericsson SA + * @author: Benjamin Gaignard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstautoconvert.h" +#include "gstautocolorspace.h" + +static gboolean +plugin_init (GstPlugin * plugin) +{ + gboolean ret; + + ret = gst_element_register (plugin, "autoconvert", + GST_RANK_NONE, GST_TYPE_AUTO_CONVERT); + + ret &= gst_element_register (plugin, "autocolorspace", + GST_RANK_NONE, GST_TYPE_AUTO_COLOR_SPACE); + + return ret; +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "autoconvert", + "Selects convertor element based on caps", + plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) From 8b0c2db425563f3b773825138fcf13c03cca120a Mon Sep 17 00:00:00 2001 From: Benjamin Gaignard Date: Wed, 15 Dec 2010 21:19:55 +0100 Subject: [PATCH 117/448] autocolorspace: Add unit test --- tests/check/Makefile.am | 1 + tests/check/elements/autocolorspace.c | 139 ++++++++++++++++++++++++++ 2 files changed, 140 insertions(+) create mode 100644 tests/check/elements/autocolorspace.c diff --git a/tests/check/Makefile.am b/tests/check/Makefile.am index d98aaecbcf..81c5862e9c 100644 --- a/tests/check/Makefile.am +++ b/tests/check/Makefile.am @@ -152,6 +152,7 @@ check_PROGRAMS = \ elements/ac3parse \ elements/amrparse \ elements/autoconvert \ + elements/autocolorspace \ elements/asfmux \ elements/camerabin \ elements/dataurisrc \ diff --git a/tests/check/elements/autocolorspace.c b/tests/check/elements/autocolorspace.c new file mode 100644 index 0000000000..51371f3b5e --- /dev/null +++ b/tests/check/elements/autocolorspace.c @@ -0,0 +1,139 @@ +/* GStreamer + * + * unit test for autocolorspace element + * Copyright (C) 2009 Jan Schmidt + * Copyright (C) 2010 ST-Ericsson SA + * @author: Benjamin Gaignard + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +typedef struct +{ + GMainLoop *loop; + gboolean eos; +} OnMessageUserData; + +static void +on_message_cb (GstBus * bus, GstMessage * message, gpointer user_data) +{ + OnMessageUserData *d = user_data; + + switch (GST_MESSAGE_TYPE (message)) { + case GST_MESSAGE_ERROR: + case GST_MESSAGE_WARNING: + g_assert_not_reached (); + break; + case GST_MESSAGE_EOS: + g_main_loop_quit (d->loop); + d->eos = TRUE; + break; + default: + break; + } +} + +static void +run_test (const gchar * pipeline_string) +{ + GstElement *pipeline; + GstBus *bus; + GMainLoop *loop; + OnMessageUserData omud = { NULL, }; + GstStateChangeReturn ret; + + GST_DEBUG ("Testing pipeline '%s'", pipeline_string); + + pipeline = gst_parse_launch (pipeline_string, NULL); + fail_unless (pipeline != NULL); + loop = g_main_loop_new (NULL, FALSE); + + bus = gst_element_get_bus (pipeline); + fail_unless (bus != NULL); + gst_bus_add_signal_watch (bus); + + omud.loop = loop; + omud.eos = FALSE; + + g_signal_connect (bus, "message", (GCallback) on_message_cb, &omud); + + gst_object_unref (bus); + + ret = gst_element_set_state (pipeline, GST_STATE_PLAYING); + fail_unless (ret == GST_STATE_CHANGE_SUCCESS + || ret == GST_STATE_CHANGE_ASYNC); + + g_main_loop_run (loop); + + fail_unless (gst_element_set_state (pipeline, + GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS); + + fail_unless (omud.eos == TRUE); + + gst_object_unref (pipeline); + g_main_loop_unref (loop); + +} + +GST_START_TEST (test_autocolorspace_rbg2bayer) +{ + gchar *pipeline; + + pipeline = + g_strdup_printf + ("videotestsrc num-buffers=1 ! video/x-raw-rgb,bpp=32,depth=32,width=100,height=100,framerate=10/1 ! autocolorspace ! video/x-raw-bayer,width=100,height=100,format=bggr,framerate=10/1 ! fakesink"); + + run_test (pipeline); + g_free (pipeline); +} + +GST_END_TEST; + +GST_START_TEST (test_autocolorspace_ffmpegcolorspace) +{ + gchar *pipeline; + + pipeline = + g_strdup_printf + ("videotestsrc num-buffers=1 ! video/x-raw-rgb,bpp=32,width=100,height=100,framerate=10/1 ! autocolorspace ! video/x-raw-rgb,bpp=16,width=100,height=100,framerate=10/1 ! fakesink"); + + run_test (pipeline); + g_free (pipeline); +} + +GST_END_TEST; + +static Suite * +autocolorspace_suite (void) +{ + Suite *s = suite_create ("autocolorspace"); + TCase *tc_basic = tcase_create ("general"); + + suite_add_tcase (s, tc_basic); + tcase_add_test (tc_basic, test_autocolorspace_rbg2bayer); + tcase_add_test (tc_basic, test_autocolorspace_ffmpegcolorspace); + + return s; +} + +GST_CHECK_MAIN (autocolorspace); From c8d9cc5770667828bf4fd56db810851b4636bf29 Mon Sep 17 00:00:00 2001 From: Benjamin Gaignard Date: Wed, 15 Dec 2010 21:28:06 +0100 Subject: [PATCH 118/448] bayer2rgb: Add framerate to the sink caps Fixes bug #637224. --- gst/bayer/gstbayer2rgb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst/bayer/gstbayer2rgb.c b/gst/bayer/gstbayer2rgb.c index c8c0640f48..67aaa42296 100644 --- a/gst/bayer/gstbayer2rgb.c +++ b/gst/bayer/gstbayer2rgb.c @@ -139,7 +139,7 @@ struct _GstBayer2RGBClass GST_VIDEO_CAPS_BGR #define SINK_CAPS "video/x-raw-bayer,format=(string){bggr,grbg,gbrg,rggb}," \ - "width=(int)[1,MAX],height=(int)[1,MAX]" + "width=(int)[1,MAX],height=(int)[1,MAX],framerate=(fraction)[0/1,MAX]" enum { From 7ae4aaaee6831b9c8bad3c25e99d735435a2a1e0 Mon Sep 17 00:00:00 2001 From: David Schleef Date: Wed, 15 Dec 2010 12:45:38 -0800 Subject: [PATCH 119/448] element-maker: Clean up directory --- tools/Makefile.am | 48 +++++++------- .../audiofilter} | 1 + .../audiosink} | 1 + .../audiosrc} | 1 + tools/{base.c => element-templates/base} | 1 + .../baseaudiosink} | 1 + .../baseaudiosrc} | 1 + .../basertpdepayload} | 1 + .../basertppayload} | 1 + .../basesink} | 1 + .../basesrc} | 1 + .../basetransform} | 1 + .../cddabasesrc} | 1 + .../element} | 1 + .../{gobject.c => element-templates/gobject} | 1 + .../pushsrc} | 1 + .../{sinkpad.c => element-templates/sinkpad} | 1 + .../sinkpad-simple} | 1 + tools/{srcpad.c => element-templates/srcpad} | 1 + .../srcpad-simple} | 1 + .../tagdemux} | 1 + .../videosink} | 1 + tools/{element-maker => gst-element-maker} | 65 ++++++++++--------- 23 files changed, 80 insertions(+), 54 deletions(-) rename tools/{gstaudiofilter.c => element-templates/audiofilter} (95%) rename tools/{gstaudiosink.c => element-templates/audiosink} (98%) rename tools/{gstaudiosrc.c => element-templates/audiosrc} (98%) rename tools/{base.c => element-templates/base} (97%) rename tools/{gstbaseaudiosink.c => element-templates/baseaudiosink} (95%) rename tools/{gstbaseaudiosrc.c => element-templates/baseaudiosrc} (95%) rename tools/{gstbasertpdepayload.c => element-templates/basertpdepayload} (98%) rename tools/{gstbasertppayload.c => element-templates/basertppayload} (97%) rename tools/{gstbasesink.c => element-templates/basesink} (99%) rename tools/{gstbasesrc.c => element-templates/basesrc} (99%) rename tools/{gstbasetransform.c => element-templates/basetransform} (99%) rename tools/{gstcddabasesrc.c => element-templates/cddabasesrc} (97%) rename tools/{gstelement.c => element-templates/element} (99%) rename tools/{gobject.c => element-templates/gobject} (98%) rename tools/{gstpushsrc.c => element-templates/pushsrc} (95%) rename tools/{sinkpad.c => element-templates/sinkpad} (99%) rename tools/{sinkpad-simple.c => element-templates/sinkpad-simple} (95%) rename tools/{srcpad.c => element-templates/srcpad} (99%) rename tools/{srcpad-simple.c => element-templates/srcpad-simple} (95%) rename tools/{gsttagdemux.c => element-templates/tagdemux} (97%) rename tools/{gstvideosink.c => element-templates/videosink} (95%) rename tools/{element-maker => gst-element-maker} (67%) diff --git a/tools/Makefile.am b/tools/Makefile.am index f501ef3530..ceb8be87f2 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -1,24 +1,28 @@ +templatefiles=\ + element-templates/audiofilter \ + element-templates/audiosink \ + element-templates/audiosrc \ + element-templates/base \ + element-templates/baseaudiosink \ + element-templates/baseaudiosrc \ + element-templates/basertpdepayload \ + element-templates/basertppayload \ + element-templates/basesink \ + element-templates/basesrc \ + element-templates/basetransform \ + element-templates/cddabasesrc \ + element-templates/element \ + element-templates/gobject \ + element-templates/pushsrc \ + element-templates/sinkpad \ + element-templates/sinkpad-simple \ + element-templates/srcpad \ + element-templates/srcpad-simple \ + element-templates/tagdemux \ + element-templates/videosink + EXTRA_DIST = \ - element-maker \ - base.c \ - gobject.c \ - gstaudiofilter.c \ - gstaudiosink.c \ - gstaudiosrc.c \ - gstbaseaudiosink.c \ - gstbaseaudiosrc.c \ - gstbasertpdepayload.c \ - gstbasertppayload.c \ - gstbasesink.c \ - gstbasesrc.c \ - gstbasetransform.c \ - gstcddabasesrc.c \ - gstelement.c \ - gstpushsrc.c \ - gsttagdemux.c \ - gstvideosink.c \ - sinkpad.c \ - sinkpad-simple.c \ - srcpad.c \ - srcpad-simple.c + gst-element-maker \ + $(templatefiles) + diff --git a/tools/gstaudiofilter.c b/tools/element-templates/audiofilter similarity index 95% rename from tools/gstaudiofilter.c rename to tools/element-templates/audiofilter index 698e756b4e..2d0929364f 100644 --- a/tools/gstaudiofilter.c +++ b/tools/element-templates/audiofilter @@ -1,3 +1,4 @@ +/* vim: set filetype=c: */ % ClassName GstAudioFilter % TYPE_CLASS_NAME diff --git a/tools/gstaudiosink.c b/tools/element-templates/audiosink similarity index 98% rename from tools/gstaudiosink.c rename to tools/element-templates/audiosink index 645993ae09..2a1b7a421b 100644 --- a/tools/gstaudiosink.c +++ b/tools/element-templates/audiosink @@ -1,3 +1,4 @@ +/* vim: set filetype=c: */ % ClassName GstAudioSink % TYPE_CLASS_NAME diff --git a/tools/gstaudiosrc.c b/tools/element-templates/audiosrc similarity index 98% rename from tools/gstaudiosrc.c rename to tools/element-templates/audiosrc index 051211e563..fe4f6129fe 100644 --- a/tools/gstaudiosrc.c +++ b/tools/element-templates/audiosrc @@ -1,3 +1,4 @@ +/* vim: set filetype=c: */ % ClassName GstAudioSrc % TYPE_CLASS_NAME diff --git a/tools/base.c b/tools/element-templates/base similarity index 97% rename from tools/base.c rename to tools/element-templates/base index 990168a319..44d6528923 100644 --- a/tools/base.c +++ b/tools/element-templates/base @@ -1,3 +1,4 @@ +/* vim: set filetype=c: */ % copyright /* GStreamer diff --git a/tools/gstbaseaudiosink.c b/tools/element-templates/baseaudiosink similarity index 95% rename from tools/gstbaseaudiosink.c rename to tools/element-templates/baseaudiosink index 695b685fb0..4d6555d7dd 100644 --- a/tools/gstbaseaudiosink.c +++ b/tools/element-templates/baseaudiosink @@ -1,3 +1,4 @@ +/* vim: set filetype=c: */ % ClassName GstBaseAudioSink % TYPE_CLASS_NAME diff --git a/tools/gstbaseaudiosrc.c b/tools/element-templates/baseaudiosrc similarity index 95% rename from tools/gstbaseaudiosrc.c rename to tools/element-templates/baseaudiosrc index 6ef302b0ef..8b0e4ab0ef 100644 --- a/tools/gstbaseaudiosrc.c +++ b/tools/element-templates/baseaudiosrc @@ -1,3 +1,4 @@ +/* vim: set filetype=c: */ % ClassName GstBaseAudioSrc % TYPE_CLASS_NAME diff --git a/tools/gstbasertpdepayload.c b/tools/element-templates/basertpdepayload similarity index 98% rename from tools/gstbasertpdepayload.c rename to tools/element-templates/basertpdepayload index 8257a32719..8b40e52656 100644 --- a/tools/gstbasertpdepayload.c +++ b/tools/element-templates/basertpdepayload @@ -1,3 +1,4 @@ +/* vim: set filetype=c: */ % ClassName GstBaseRTPDepayload % TYPE_CLASS_NAME diff --git a/tools/gstbasertppayload.c b/tools/element-templates/basertppayload similarity index 97% rename from tools/gstbasertppayload.c rename to tools/element-templates/basertppayload index 65d216f64c..1a5be183d0 100644 --- a/tools/gstbasertppayload.c +++ b/tools/element-templates/basertppayload @@ -1,3 +1,4 @@ +/* vim: set filetype=c: */ % ClassName GstBaseRTPPayload % TYPE_CLASS_NAME diff --git a/tools/gstbasesink.c b/tools/element-templates/basesink similarity index 99% rename from tools/gstbasesink.c rename to tools/element-templates/basesink index 26ad3f9218..bf018283df 100644 --- a/tools/gstbasesink.c +++ b/tools/element-templates/basesink @@ -1,3 +1,4 @@ +/* vim: set filetype=c: */ % ClassName GstBaseSink % TYPE_CLASS_NAME diff --git a/tools/gstbasesrc.c b/tools/element-templates/basesrc similarity index 99% rename from tools/gstbasesrc.c rename to tools/element-templates/basesrc index 048e274dd1..0b7e56fc17 100644 --- a/tools/gstbasesrc.c +++ b/tools/element-templates/basesrc @@ -1,3 +1,4 @@ +/* vim: set filetype=c: */ % ClassName GstBaseSrc % TYPE_CLASS_NAME diff --git a/tools/gstbasetransform.c b/tools/element-templates/basetransform similarity index 99% rename from tools/gstbasetransform.c rename to tools/element-templates/basetransform index 7dcbc8588a..e5fd24cf3a 100644 --- a/tools/gstbasetransform.c +++ b/tools/element-templates/basetransform @@ -1,3 +1,4 @@ +/* vim: set filetype=c: */ % ClassName GstBaseTransform % TYPE_CLASS_NAME diff --git a/tools/gstcddabasesrc.c b/tools/element-templates/cddabasesrc similarity index 97% rename from tools/gstcddabasesrc.c rename to tools/element-templates/cddabasesrc index 201a843c96..d788d19c41 100644 --- a/tools/gstcddabasesrc.c +++ b/tools/element-templates/cddabasesrc @@ -1,3 +1,4 @@ +/* vim: set filetype=c: */ % ClassName GstCddaBaseSrc % TYPE_CLASS_NAME diff --git a/tools/gstelement.c b/tools/element-templates/element similarity index 99% rename from tools/gstelement.c rename to tools/element-templates/element index c9e05c66c0..ed025ee2b2 100644 --- a/tools/gstelement.c +++ b/tools/element-templates/element @@ -1,3 +1,4 @@ +/* vim: set filetype=c: */ % ClassName GstElement % TYPE_CLASS_NAME diff --git a/tools/gobject.c b/tools/element-templates/gobject similarity index 98% rename from tools/gobject.c rename to tools/element-templates/gobject index dc5392d860..4ef34e6c2d 100644 --- a/tools/gobject.c +++ b/tools/element-templates/gobject @@ -1,3 +1,4 @@ +/* vim: set filetype=c: */ % includes % prototypes diff --git a/tools/gstpushsrc.c b/tools/element-templates/pushsrc similarity index 95% rename from tools/gstpushsrc.c rename to tools/element-templates/pushsrc index a35595085b..4dfb678494 100644 --- a/tools/gstpushsrc.c +++ b/tools/element-templates/pushsrc @@ -1,3 +1,4 @@ +/* vim: set filetype=c: */ % ClassName GstPushSrc % TYPE_CLASS_NAME diff --git a/tools/sinkpad.c b/tools/element-templates/sinkpad similarity index 99% rename from tools/sinkpad.c rename to tools/element-templates/sinkpad index 87babbc7f9..6d3bad1fb3 100644 --- a/tools/sinkpad.c +++ b/tools/element-templates/sinkpad @@ -1,3 +1,4 @@ +/* vim: set filetype=c: */ % instance-members GstPad *sinkpad; diff --git a/tools/sinkpad-simple.c b/tools/element-templates/sinkpad-simple similarity index 95% rename from tools/sinkpad-simple.c rename to tools/element-templates/sinkpad-simple index 9a031fc150..e8538b6ece 100644 --- a/tools/sinkpad-simple.c +++ b/tools/element-templates/sinkpad-simple @@ -1,3 +1,4 @@ +/* vim: set filetype=c: */ % instance-members GstPad *sinkpad; diff --git a/tools/srcpad.c b/tools/element-templates/srcpad similarity index 99% rename from tools/srcpad.c rename to tools/element-templates/srcpad index 61cbd21326..d1f799267d 100644 --- a/tools/srcpad.c +++ b/tools/element-templates/srcpad @@ -1,3 +1,4 @@ +/* vim: set filetype=c: */ % instance-members GstPad *srcpad; diff --git a/tools/srcpad-simple.c b/tools/element-templates/srcpad-simple similarity index 95% rename from tools/srcpad-simple.c rename to tools/element-templates/srcpad-simple index 42db8d385b..0fca9157ed 100644 --- a/tools/srcpad-simple.c +++ b/tools/element-templates/srcpad-simple @@ -1,3 +1,4 @@ +/* vim: set filetype=c: */ % instance-members GstPad *srcpad; diff --git a/tools/gsttagdemux.c b/tools/element-templates/tagdemux similarity index 97% rename from tools/gsttagdemux.c rename to tools/element-templates/tagdemux index 6cdfb58d8e..8517c5802f 100644 --- a/tools/gsttagdemux.c +++ b/tools/element-templates/tagdemux @@ -1,3 +1,4 @@ +/* vim: set filetype=c: */ % ClassName GstTagDemux % TYPE_CLASS_NAME diff --git a/tools/gstvideosink.c b/tools/element-templates/videosink similarity index 95% rename from tools/gstvideosink.c rename to tools/element-templates/videosink index 72a9e88789..d26de559b8 100644 --- a/tools/gstvideosink.c +++ b/tools/element-templates/videosink @@ -1,3 +1,4 @@ +/* vim: set filetype=c: */ % ClassName GstVideoSink % TYPE_CLASS_NAME diff --git a/tools/element-maker b/tools/gst-element-maker similarity index 67% rename from tools/element-maker rename to tools/gst-element-maker index 60dc35d3be..816385d965 100755 --- a/tools/element-maker +++ b/tools/gst-element-maker @@ -2,6 +2,7 @@ prefix=gst +templatedir=element-templates while [ "$1" ] ; do case $1 in @@ -43,7 +44,7 @@ if [ "$name" = "" -o "$class" = "" ] ; then exit 1 fi -if [ ! -f "gst$class.c" ] ; then +if [ ! -f "element-templates/$class" ] ; then echo "Template file for $class not found." exit 1 fi @@ -69,11 +70,11 @@ if [ "$EMAIL_ADDRESS" = "" ] ; then EMAIL_ADDRESS=fixme@example.com fi -source=gst$class.c -pkg=`grep -A 10000 '^% pkg-config' $source | tail -n +2|grep -m 1 -B 10000 '^%'|head -n -1` -GST_TYPE_BASE_REPLACE=`grep -A 10000 '^% TYPE_CLASS_NAME' $source | tail -n +2|grep -m 1 -B 10000 '^%'|head -n -1` -GstBaseReplace=`grep -A 10000 '^% ClassName' $source | tail -n +2|grep -m 1 -B 10000 '^%'|head -n -1` -pads=`grep -A 10000 '^% pads' $source | tail -n +2|grep -m 1 -B 10000 '^%'|head -n -1` + +pkg=`grep -A 10000 '^% pkg-config' $templatedir/$class | tail -n +2|grep -m 1 -B 10000 '^%'|head -n -1` +GST_TYPE_BASE_REPLACE=`grep -A 10000 '^% TYPE_CLASS_NAME' $templatedir/$class | tail -n +2|grep -m 1 -B 10000 '^%'|head -n -1` +GstBaseReplace=`grep -A 10000 '^% ClassName' $templatedir/$class | tail -n +2|grep -m 1 -B 10000 '^%'|head -n -1` +pads=`grep -A 10000 '^% pads' $templatedir/$class | tail -n +2|grep -m 1 -B 10000 '^%'|head -n -1` generate () { @@ -115,7 +116,7 @@ cat <<-EOF */ EOF -#grep -A 10000 '^% copyright' base.c | tail -n +2|grep -m 1 -B 10000 '^%'|head -n -1 +#grep -A 10000 '^% copyright' $templatedir/base | tail -n +2|grep -m 1 -B 10000 '^%'|head -n -1 cat < Date: Thu, 16 Dec 2010 09:56:00 +0100 Subject: [PATCH 120/448] autoconvert: Rename autocolorspace to autovideoconvert This doesn't just convert between color spaces. --- gst/autoconvert/Makefile.am | 3 +- ...autocolorspace.c => gstautovideoconvert.c} | 100 ++++++++++-------- ...autocolorspace.h => gstautovideoconvert.h} | 26 ++--- gst/autoconvert/plugin.c | 6 +- 4 files changed, 71 insertions(+), 64 deletions(-) rename gst/autoconvert/{gstautocolorspace.c => gstautovideoconvert.c} (63%) rename gst/autoconvert/{gstautocolorspace.h => gstautovideoconvert.h} (55%) diff --git a/gst/autoconvert/Makefile.am b/gst/autoconvert/Makefile.am index e92d8a6a70..e57b9bc6c1 100644 --- a/gst/autoconvert/Makefile.am +++ b/gst/autoconvert/Makefile.am @@ -1,9 +1,10 @@ plugin_LTLIBRARIES = libgstautoconvert.la -libgstautoconvert_la_SOURCES = gstautoconvert.c gstautoconvert.h gstautocolorspace.c gstautcolorspace.h plugin.c +libgstautoconvert_la_SOURCES = gstautoconvert.c gstautovideoconvert.c plugin.c libgstautoconvert_la_CFLAGS = $(GST_CFLAGS) libgstautoconvert_la_LIBADD = $(GST_LIBS) libgstautoconvert_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) libgstautoconvert_la_LIBTOOLFLAGS = --tag=disable-static +noinst_HEADERS = gstautoconvert.h gstautovideoconvert.h diff --git a/gst/autoconvert/gstautocolorspace.c b/gst/autoconvert/gstautovideoconvert.c similarity index 63% rename from gst/autoconvert/gstautocolorspace.c rename to gst/autoconvert/gstautovideoconvert.c index 0ea615a39d..4dba911d3b 100644 --- a/gst/autoconvert/gstautocolorspace.c +++ b/gst/autoconvert/gstautovideoconvert.c @@ -18,13 +18,13 @@ * Boston, MA 02111-1307, USA. */ /* - * test autocolorspace: + * test autovideoconvert: * if rgb2bayer is present - * gst-launch videotestsrc num-buffers=2 ! "video/x-raw-rgb,width=100,height=100,framerate=10/1" ! autocolorspace ! "video/x-raw-bayer,width=100,height=100,format=bggr,framerate=10/1" ! fakesink -v + * gst-launch videotestsrc num-buffers=2 ! "video/x-raw-rgb,width=100,height=100,framerate=10/1" ! autovideoconvert ! "video/x-raw-bayer,width=100,height=100,format=bggr,framerate=10/1" ! fakesink -v * if bayer2rgb is present - * gst-launch videotestsrc num-buffers=2 ! "video/x-raw-bayer,width=100,height=100,format=bggr,framerate=10/1" ! autocolorspace ! "video/x-raw-rgb,width=100,height=100,framerate=10/1" ! fakesink -v - * test with ffmpegcolorspace - * gst-launch videotestsrc num-buffers=2 ! "video/x-raw-rgb,bpp=32,width=100,height=100,framerate=10/1" ! autocolorspace ! "video/x-raw-rgb,bpp=16,width=100,height=100,framerate=10/1" ! fakesink -v + * gst-launch videotestsrc num-buffers=2 ! "video/x-raw-bayer,width=100,height=100,format=bggr,framerate=10/1" ! autovideoconvert ! "video/x-raw-rgb,width=100,height=100,framerate=10/1" ! fakesink -v + * test with ffmpegvideoconvert + * gst-launch videotestsrc num-buffers=2 ! "video/x-raw-rgb,bpp=32,width=100,height=100,framerate=10/1" ! autovideoconvert ! "video/x-raw-rgb,bpp=16,width=100,height=100,framerate=10/1" ! fakesink -v */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -32,10 +32,10 @@ #include -#include "gstautocolorspace.h" +#include "gstautovideoconvert.h" -GST_DEBUG_CATEGORY (autocolorspace_debug); -#define GST_CAT_DEFAULT (autocolorspace_debug) +GST_DEBUG_CATEGORY (autovideoconvert_debug); +#define GST_CAT_DEFAULT (autovideoconvert_debug) GStaticMutex factories_mutex = G_STATIC_MUTEX_INIT; guint32 factories_cookie = 0; /* Cookie from last time when factories was updated */ @@ -53,15 +53,15 @@ static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", GST_STATIC_CAPS_ANY); -static GstStateChangeReturn gst_auto_color_space_change_state (GstElement * +static GstStateChangeReturn gst_auto_video_convert_change_state (GstElement * element, GstStateChange transition); -void gst_auto_color_space_update_factory_list (GstAutoColorSpace * - autocolorspace); +void gst_auto_video_convert_update_factory_list (GstAutoVideoConvert * + autovideoconvert); static gboolean -gst_auto_color_space_element_filter (GstPluginFeature * feature, - GstAutoColorSpace * autocolorspace) +gst_auto_video_convert_element_filter (GstPluginFeature * feature, + GstAutoVideoConvert * autovideoconvert) { const gchar *klass; @@ -73,8 +73,8 @@ gst_auto_color_space_element_filter (GstPluginFeature * feature, /* only select color space converter */ if (strstr (klass, "Filter") && strstr (klass, "Converter") && strstr (klass, "Video")) { - GST_DEBUG_OBJECT (autocolorspace, - "gst_auto_color_space_element_filter found %s\n", + GST_DEBUG_OBJECT (autovideoconvert, + "gst_auto_video_convert_element_filter found %s\n", gst_plugin_feature_get_name (GST_PLUGIN_FEATURE_CAST (feature))); return TRUE; } @@ -83,13 +83,14 @@ gst_auto_color_space_element_filter (GstPluginFeature * feature, static GList * -gst_auto_color_space_create_factory_list (GstAutoColorSpace * autocolorspace) +gst_auto_video_convert_create_factory_list (GstAutoVideoConvert * + autovideoconvert) { GList *result = NULL; /* get the feature list using the filter */ result = gst_default_registry_feature_filter ((GstPluginFeatureFilter) - gst_auto_color_space_element_filter, FALSE, autocolorspace); + gst_auto_video_convert_element_filter, FALSE, autovideoconvert); /* sort on rank and name */ result = g_list_sort (result, gst_plugin_feature_rank_compare_func); @@ -98,7 +99,8 @@ gst_auto_color_space_create_factory_list (GstAutoColorSpace * autocolorspace) } void -gst_auto_color_space_update_factory_list (GstAutoColorSpace * autocolorspace) +gst_auto_video_convert_update_factory_list (GstAutoVideoConvert * + autovideoconvert) { /* use a static mutex to protect factories list and factories cookie */ g_static_mutex_lock (&factories_mutex); @@ -107,7 +109,7 @@ gst_auto_color_space_update_factory_list (GstAutoColorSpace * autocolorspace) if (!factories) { /* no factories list create it */ factories_cookie = gst_default_registry_get_feature_list_cookie (); - factories = gst_auto_color_space_create_factory_list (autocolorspace); + factories = gst_auto_video_convert_create_factory_list (autovideoconvert); } else { /* a factories list exist but is it up to date? */ if (factories_cookie != gst_default_registry_get_feature_list_cookie ()) { @@ -116,17 +118,18 @@ gst_auto_color_space_update_factory_list (GstAutoColorSpace * autocolorspace) gst_plugin_feature_list_free (factories); /* then create an updated one */ factories_cookie = gst_default_registry_get_feature_list_cookie (); - factories = gst_auto_color_space_create_factory_list (autocolorspace); + factories = gst_auto_video_convert_create_factory_list (autovideoconvert); } } g_static_mutex_unlock (&factories_mutex); } -GST_BOILERPLATE (GstAutoColorSpace, gst_auto_color_space, GstBin, GST_TYPE_BIN); +GST_BOILERPLATE (GstAutoVideoConvert, gst_auto_video_convert, GstBin, + GST_TYPE_BIN); static void -gst_auto_color_space_base_init (gpointer klass) +gst_auto_video_convert_base_init (gpointer klass) { GstElementClass *element_class = GST_ELEMENT_CLASS (klass); @@ -142,77 +145,80 @@ gst_auto_color_space_base_init (gpointer klass) } static void -gst_auto_color_space_dispose (GObject * object) +gst_auto_video_convert_dispose (GObject * object) { G_OBJECT_CLASS (parent_class)->dispose (object); } static void -gst_auto_color_space_class_init (GstAutoColorSpaceClass * klass) +gst_auto_video_convert_class_init (GstAutoVideoConvertClass * klass) { GObjectClass *gobject_class = (GObjectClass *) klass; GstElementClass *gstelement_class = (GstElementClass *) klass; - gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_auto_color_space_dispose); + gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_auto_video_convert_dispose); - GST_DEBUG_CATEGORY_INIT (autocolorspace_debug, "autocolorspace", 0, + GST_DEBUG_CATEGORY_INIT (autovideoconvert_debug, "autovideoconvert", 0, "Auto color space converter"); gstelement_class->change_state = - GST_DEBUG_FUNCPTR (gst_auto_color_space_change_state); + GST_DEBUG_FUNCPTR (gst_auto_video_convert_change_state); } static void -gst_auto_color_space_add_autoconvert (GstAutoColorSpace * autocolorspace) +gst_auto_video_convert_add_autoconvert (GstAutoVideoConvert * autovideoconvert) { GstPad *pad; - autocolorspace->autoconvert = + autovideoconvert->autoconvert = gst_element_factory_make ("autoconvert", "autoconvertchild"); /* first add autoconvert in bin */ - gst_bin_add (GST_BIN (autocolorspace), autocolorspace->autoconvert); + gst_bin_add (GST_BIN (autovideoconvert), autovideoconvert->autoconvert); /* get sinkpad and link it to ghost sink pad */ - pad = gst_element_get_static_pad (autocolorspace->autoconvert, "sink"); - gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (autocolorspace->sinkpad), pad); + pad = gst_element_get_static_pad (autovideoconvert->autoconvert, "sink"); + gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (autovideoconvert->sinkpad), + pad); gst_object_unref (pad); /* get srcpad and link it to ghost src pad */ - pad = gst_element_get_static_pad (autocolorspace->autoconvert, "src"); - gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (autocolorspace->srcpad), pad); + pad = gst_element_get_static_pad (autovideoconvert->autoconvert, "src"); + gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (autovideoconvert->srcpad), pad); gst_object_unref (pad); } static void -gst_auto_color_space_init (GstAutoColorSpace * autocolorspace, - GstAutoColorSpaceClass * klass) +gst_auto_video_convert_init (GstAutoVideoConvert * autovideoconvert, + GstAutoVideoConvertClass * klass) { GstPadTemplate *pad_tmpl; /* get sink pad template */ pad_tmpl = gst_static_pad_template_get (&sinktemplate); - autocolorspace->sinkpad = + autovideoconvert->sinkpad = gst_ghost_pad_new_no_target_from_template ("sink", pad_tmpl); /* add sink ghost pad */ - gst_element_add_pad (GST_ELEMENT (autocolorspace), autocolorspace->sinkpad); + gst_element_add_pad (GST_ELEMENT (autovideoconvert), + autovideoconvert->sinkpad); /* get src pad template */ pad_tmpl = gst_static_pad_template_get (&srctemplate); - autocolorspace->srcpad = + autovideoconvert->srcpad = gst_ghost_pad_new_no_target_from_template ("src", pad_tmpl); /* add src ghost pad */ - gst_element_add_pad (GST_ELEMENT (autocolorspace), autocolorspace->srcpad); + gst_element_add_pad (GST_ELEMENT (autovideoconvert), + autovideoconvert->srcpad); return; } static GstStateChangeReturn -gst_auto_color_space_change_state (GstElement * element, +gst_auto_video_convert_change_state (GstElement * element, GstStateChange transition) { - GstAutoColorSpace *autocolorspace = GST_AUTO_COLOR_SPACE (element); + GstAutoVideoConvert *autovideoconvert = GST_AUTO_VIDEO_CONVERT (element); GstStateChangeReturn ret; ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); @@ -223,15 +229,15 @@ gst_auto_color_space_change_state (GstElement * element, case GST_STATE_CHANGE_NULL_TO_READY: { /* create and add autoconvert in bin */ - gst_auto_color_space_add_autoconvert (autocolorspace); + gst_auto_video_convert_add_autoconvert (autovideoconvert); /* get an updated list of factories */ - gst_auto_color_space_update_factory_list (autocolorspace); - GST_DEBUG_OBJECT (autocolorspace, "set factories list"); + gst_auto_video_convert_update_factory_list (autovideoconvert); + GST_DEBUG_OBJECT (autovideoconvert, "set factories list"); /* give factory list to autoconvert */ - g_object_set (GST_ELEMENT (autocolorspace->autoconvert), "factories", + g_object_set (GST_ELEMENT (autovideoconvert->autoconvert), "factories", factories, NULL); /* synchronize autoconvert state with parent state */ - gst_element_sync_state_with_parent (autocolorspace->autoconvert); + gst_element_sync_state_with_parent (autovideoconvert->autoconvert); break; } default: diff --git a/gst/autoconvert/gstautocolorspace.h b/gst/autoconvert/gstautovideoconvert.h similarity index 55% rename from gst/autoconvert/gstautocolorspace.h rename to gst/autoconvert/gstautovideoconvert.h index b14e4bd16b..9136efaed4 100644 --- a/gst/autoconvert/gstautocolorspace.h +++ b/gst/autoconvert/gstautovideoconvert.h @@ -18,23 +18,23 @@ * Boston, MA 02111-1307, USA. */ -#ifndef __GST_AUTO_COLOR_SPACE_H__ -#define __GST_AUTO_COLOR_SPACE_H__ +#ifndef __GST_AUTO_VIDEO_CONVERT_H__ +#define __GST_AUTO_VIDEO_CONVERT_H__ #include #include #include "gstautoconvert.h" G_BEGIN_DECLS -#define GST_TYPE_AUTO_COLOR_SPACE (gst_auto_color_space_get_type()) -#define GST_AUTO_COLOR_SPACE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_AUTO_COLOR_SPACE,GstAutoColorSpace)) -#define GST_AUTO_COLOR_SPACE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_AUTO_COLOR_SPACE,GstAutoColorSpaceClass)) -#define GST_IS_AUTO_COLOR_SPACE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_AUTO_COLOR_SPACE)) -#define GST_IS_AUTO_COLOR_SPACE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_AUTO_COLOR_SPACE)) -typedef struct _GstAutoColorSpace GstAutoColorSpace; -typedef struct _GstAutoColorSpaceClass GstAutoColorSpaceClass; +#define GST_TYPE_AUTO_VIDEO_CONVERT (gst_auto_video_convert_get_type()) +#define GST_AUTO_VIDEO_CONVERT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_AUTO_VIDEO_CONVERT,GstAutoVideoConvert)) +#define GST_AUTO_VIDEO_CONVERT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_AUTO_VIDEO_CONVERT,GstAutoVideoConvertClass)) +#define GST_IS_AUTO_VIDEO_CONVERT(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_AUTO_VIDEO_CONVERT)) +#define GST_IS_AUTO_VIDEO_CONVERT_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_AUTO_VIDEO_CONVERT)) +typedef struct _GstAutoVideoConvert GstAutoVideoConvert; +typedef struct _GstAutoVideoConvertClass GstAutoVideoConvertClass; -struct _GstAutoColorSpace +struct _GstAutoVideoConvert { /*< private > */ GstBin bin; /* we extend GstBin */ @@ -44,12 +44,12 @@ struct _GstAutoColorSpace GstPad *srcpad; }; -struct _GstAutoColorSpaceClass +struct _GstAutoVideoConvertClass { GstBinClass parent_class; }; -GType gst_auto_color_space_get_type (void); +GType gst_auto_video_convert_get_type (void); G_END_DECLS -#endif /* __GST_AUTO_COLOR_SPACE_H__ */ +#endif /* __GST_AUTO_VIDEO_CONVERT_H__ */ diff --git a/gst/autoconvert/plugin.c b/gst/autoconvert/plugin.c index dd2ca033b7..0de71d3bbc 100644 --- a/gst/autoconvert/plugin.c +++ b/gst/autoconvert/plugin.c @@ -23,7 +23,7 @@ #endif #include "gstautoconvert.h" -#include "gstautocolorspace.h" +#include "gstautovideoconvert.h" static gboolean plugin_init (GstPlugin * plugin) @@ -33,8 +33,8 @@ plugin_init (GstPlugin * plugin) ret = gst_element_register (plugin, "autoconvert", GST_RANK_NONE, GST_TYPE_AUTO_CONVERT); - ret &= gst_element_register (plugin, "autocolorspace", - GST_RANK_NONE, GST_TYPE_AUTO_COLOR_SPACE); + ret &= gst_element_register (plugin, "autovideoconvert", + GST_RANK_NONE, GST_TYPE_AUTO_VIDEO_CONVERT); return ret; } From b191fb2b05bf3a1fa3957badf9c393f3bc1318bf Mon Sep 17 00:00:00 2001 From: Edward Hervey Date: Thu, 16 Dec 2010 11:29:07 +0100 Subject: [PATCH 121/448] dvbsuboverlay: The enable property is a boolean and not an integer --- gst/dvbsuboverlay/gstdvbsuboverlay.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst/dvbsuboverlay/gstdvbsuboverlay.c b/gst/dvbsuboverlay/gstdvbsuboverlay.c index 6cf1d78ea6..9962077457 100644 --- a/gst/dvbsuboverlay/gstdvbsuboverlay.c +++ b/gst/dvbsuboverlay/gstdvbsuboverlay.c @@ -313,7 +313,7 @@ gst_dvbsub_overlay_get_property (GObject * object, guint prop_id, switch (prop_id) { case PROP_ENABLE: - g_value_set_int (value, g_atomic_int_get (&overlay->enable)); + g_value_set_boolean (value, g_atomic_int_get (&overlay->enable)); break; case PROP_MAX_PAGE_TIMEOUT: g_value_set_int (value, g_atomic_int_get (&overlay->max_page_timeout)); From b73ae45460e552040c7f62b61951adb0f08df8e1 Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Thu, 16 Dec 2010 15:33:45 +0000 Subject: [PATCH 122/448] dvbsuboverlay: fix rendering artefacts Initialize source x position for odd height special case. --- gst/dvbsuboverlay/gstdvbsuboverlay.c | 1 + 1 file changed, 1 insertion(+) diff --git a/gst/dvbsuboverlay/gstdvbsuboverlay.c b/gst/dvbsuboverlay/gstdvbsuboverlay.c index 9962077457..56c3a615b2 100644 --- a/gst/dvbsuboverlay/gstdvbsuboverlay.c +++ b/gst/dvbsuboverlay/gstdvbsuboverlay.c @@ -711,6 +711,7 @@ blit_i420 (GstDVBSubOverlay * overlay, DVBSubtitles * subs, GstBuffer * buffer) /* Odd height */ if (y < dh) { + sx = 0; for (x = 0; x < dw - 1; x += 2) { color = sub_region->pict.palette[src[(sy >> 16) * src_stride + (sx >> 16)]]; From d9f83ad938d5902a0002ae80a94d3aa8f70b74c3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Thu, 16 Dec 2010 00:13:18 +0000 Subject: [PATCH 123/448] dvbsuboverlay: fix atomic access --- gst/dvbsuboverlay/gstdvbsuboverlay.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/gst/dvbsuboverlay/gstdvbsuboverlay.c b/gst/dvbsuboverlay/gstdvbsuboverlay.c index 56c3a615b2..a1bfe85637 100644 --- a/gst/dvbsuboverlay/gstdvbsuboverlay.c +++ b/gst/dvbsuboverlay/gstdvbsuboverlay.c @@ -832,10 +832,11 @@ static void new_dvb_subtitles_cb (DvbSub * dvb_sub, DVBSubtitles * subs, gpointer user_data) { GstDVBSubOverlay *overlay = GST_DVBSUB_OVERLAY (user_data); + int max_page_timeout; - if (overlay->max_page_timeout > 0) - subs->page_time_out = MIN (subs->page_time_out, - g_atomic_int_get (&overlay->max_page_timeout)); + max_page_timeout = g_atomic_int_get (&overlay->max_page_timeout); + if (max_page_timeout > 0) + subs->page_time_out = MIN (subs->page_time_out, max_page_timeout); GST_INFO_OBJECT (overlay, "New DVB subtitles arrived with a page_time_out of %d and %d regions for PTS=%" From c64df2ebc24cbf7b857be53238d7fcb08cf6d69b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Thu, 16 Dec 2010 00:19:13 +0000 Subject: [PATCH 124/448] dvbsuboverlay: remove some unused defines --- gst/dvbsuboverlay/ffmpeg-colorspace.h | 59 --------------------------- 1 file changed, 59 deletions(-) diff --git a/gst/dvbsuboverlay/ffmpeg-colorspace.h b/gst/dvbsuboverlay/ffmpeg-colorspace.h index 18bfe5521c..baebe80b70 100644 --- a/gst/dvbsuboverlay/ffmpeg-colorspace.h +++ b/gst/dvbsuboverlay/ffmpeg-colorspace.h @@ -54,63 +54,4 @@ b = cm[(y + b_add) >> SCALEBITS];\ } -#define YUV_TO_RGB1(cb1, cr1)\ -{\ - cb = (cb1) - 128;\ - cr = (cr1) - 128;\ - r_add = FIX(1.40200) * cr + ONE_HALF;\ - g_add = - FIX(0.34414) * cb - FIX(0.71414) * cr + ONE_HALF;\ - b_add = FIX(1.77200) * cb + ONE_HALF;\ -} - -#define YUV_TO_RGB2(r, g, b, y1)\ -{\ - y = (y1) << SCALEBITS;\ - r = cm[(y + r_add) >> SCALEBITS];\ - g = cm[(y + g_add) >> SCALEBITS];\ - b = cm[(y + b_add) >> SCALEBITS];\ -} - -#define Y_CCIR_TO_JPEG(y)\ - cm[((y) * FIX(255.0/219.0) + (ONE_HALF - 16 * FIX(255.0/219.0))) >> SCALEBITS] - -#define Y_JPEG_TO_CCIR(y)\ - (((y) * FIX(219.0/255.0) + (ONE_HALF + (16 << SCALEBITS))) >> SCALEBITS) - -#define C_CCIR_TO_JPEG(y)\ - cm[(((y) - 128) * FIX(127.0/112.0) + (ONE_HALF + (128 << SCALEBITS))) >> SCALEBITS] - -/* NOTE: the clamp is really necessary! */ -static inline int C_JPEG_TO_CCIR(int y) { - y = (((y - 128) * FIX(112.0/127.0) + (ONE_HALF + (128 << SCALEBITS))) >> SCALEBITS); - if (y < 16) - y = 16; - return y; -} - - -#define RGB_TO_Y(r, g, b) \ -((FIX(0.29900) * (r) + FIX(0.58700) * (g) + \ - FIX(0.11400) * (b) + ONE_HALF) >> SCALEBITS) - -#define RGB_TO_U(r1, g1, b1, shift)\ -(((- FIX(0.16874) * r1 - FIX(0.33126) * g1 + \ - FIX(0.50000) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128) - -#define RGB_TO_V(r1, g1, b1, shift)\ -(((FIX(0.50000) * r1 - FIX(0.41869) * g1 - \ - FIX(0.08131) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128) - -#define RGB_TO_Y_CCIR(r, g, b) \ -((FIX(0.29900*219.0/255.0) * (r) + FIX(0.58700*219.0/255.0) * (g) + \ - FIX(0.11400*219.0/255.0) * (b) + (ONE_HALF + (16 << SCALEBITS))) >> SCALEBITS) - -#define RGB_TO_U_CCIR(r1, g1, b1, shift)\ -(((- FIX(0.16874*224.0/255.0) * r1 - FIX(0.33126*224.0/255.0) * g1 + \ - FIX(0.50000*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128) - -#define RGB_TO_V_CCIR(r1, g1, b1, shift)\ -(((FIX(0.50000*224.0/255.0) * r1 - FIX(0.41869*224.0/255.0) * g1 - \ - FIX(0.08131*224.0/255.0) * b1 + (ONE_HALF << shift) - 1) >> (SCALEBITS + shift)) + 128) - #endif /* AVCODEC_COLORSPACE_H */ From 767c29cc2f0352a42f507cb5444d8efea2535ab8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Thu, 16 Dec 2010 15:31:23 +0000 Subject: [PATCH 125/448] dvbsuboverlay: use GST_LOG etc. for logging The dvbsub routines were originally designed as a mini lib with a log callback (which from the looks of it in our case would always be called and always assemble the string even with debug output disabled). Some of these debug statements can probably be removed or cleaned up some more. --- gst/dvbsuboverlay/dvb-sub.c | 352 +++++++++++---------------- gst/dvbsuboverlay/dvb-sub.h | 5 +- gst/dvbsuboverlay/gstdvbsuboverlay.c | 26 +- 3 files changed, 139 insertions(+), 244 deletions(-) diff --git a/gst/dvbsuboverlay/dvb-sub.c b/gst/dvbsuboverlay/dvb-sub.c index f9fe13b6d6..803729dc58 100644 --- a/gst/dvbsuboverlay/dvb-sub.c +++ b/gst/dvbsuboverlay/dvb-sub.c @@ -36,51 +36,14 @@ #include /* GstBitReader */ #include "ffmpeg-colorspace.h" /* YUV_TO_RGB1_CCIR */ /* FIXME: Just give YUV data to gstreamer then? */ -/* FIXME: Convert to GST_LOG and clean up */ -void (*g_log_callback) (GLogLevelFlags log_level, const gchar * format, - va_list args, gpointer user_data) = NULL; -gpointer g_log_callback_user_data = NULL; +GST_DEBUG_CATEGORY_STATIC (dvbsub_debug); +#define GST_CAT_DEFAULT dvbsub_debug -#define DEBUG -#ifdef DEBUG -#define dvb_log(log_type, log_level, format...) real_dvb_log(log_type, log_level, ## format) -typedef enum +void +dvb_sub_init_debug (void) { - /* dvb_log types // DVB_LOG environment variable string */ - DVB_LOG_GENERAL, /* GENERAL */ - DVB_LOG_PAGE, /* PAGE */ - DVB_LOG_REGION, /* REGION */ - DVB_LOG_CLUT, /* CLUT */ - DVB_LOG_OBJECT, /* OBJECT */ - DVB_LOG_PIXEL, /* PIXEL */ - DVB_LOG_RUNLEN, /* RUNLEN */ - DVB_LOG_DISPLAY, /* DISPLAY */ - DVB_LOG_STREAM, /* STREAM - issues in the encoded stream (TV service provider encoder problem) */ - DVB_LOG_PACKET, /* PACKET - messages during raw demuxer data packet handling */ - DVB_LOG_LAST /* sentinel use only */ -} DvbLogTypes; - -static void -real_dvb_log (const gint log_type, GLogLevelFlags log_level, - const gchar * format, ...) -{ - if (g_log_callback) { - va_list va; - va_start (va, format); - switch (log_type) { - default: - g_log_callback (log_level, format, va, g_log_callback_user_data); - break; - case DVB_LOG_PIXEL: - case DVB_LOG_RUNLEN: - break; - } - va_end (va); - } + GST_DEBUG_CATEGORY_INIT (dvbsub_debug, "dvbsub", 0, "dvbsuboverlay parser"); } -#else -#define dvb_log(log_type, log_level, format...) -#endif /* FIXME: Are we waiting for an acquisition point before trying to do things? */ /* FIXME: In the end convert some of the guint8/16 (especially stack variables) back to gint for access efficiency */ @@ -452,14 +415,8 @@ _dvb_sub_parse_page_segment (DvbSub * dvb_sub, guint16 page_id, guint8 * buf, guint8 region_id; guint8 page_state; -#ifdef DEBUG - static int counter = 0; - static const gchar *page_state_str[] = { - "Normal case", - "ACQUISITION POINT", - "Mode Change", - "RESERVED" - }; +#ifndef GST_DISABLE_GST_DEBUG + static int counter = 0; /* FIXME: static counter? I think not.. */ #endif if (buf_size < 1) @@ -468,12 +425,17 @@ _dvb_sub_parse_page_segment (DvbSub * dvb_sub, guint16 page_id, guint8 * buf, priv->page_time_out = *buf++; page_state = ((*buf++) >> 2) & 3; -#ifdef DEBUG - ++counter; - dvb_log (DVB_LOG_PAGE, G_LOG_LEVEL_DEBUG, - "%d: page_id = %u, length = %d, page_time_out = %u seconds, page_state = %s", - counter, page_id, buf_size, priv->page_time_out, - page_state_str[page_state]); +#ifndef GST_DISABLE_GST_DEBUG + { + static const gchar *page_state_str[4] = { + "Normal case", "ACQUISITION POINT", "Mode Change", "RESERVED" + }; + + ++counter; + GST_DEBUG ("PAGE: %d: page_id = %u, length = %d, page_time_out = %u secs, " + "page_state = %s", counter, page_id, buf_size, priv->page_time_out, + page_state_str[page_state]); + } #endif if (page_state == 2) { /* Mode change */ @@ -512,8 +474,7 @@ _dvb_sub_parse_page_segment (DvbSub * dvb_sub, guint16 page_id, guint8 * buf, priv->display_list = display; priv->display_list_size++; - dvb_log (DVB_LOG_PAGE, G_LOG_LEVEL_DEBUG, - "%d: REGION information: ID = %u, address = %ux%u", + GST_LOG ("PAGE %d: REGION information: ID = %u, address = %ux%u", counter, region_id, display->x_pos, display->y_pos); } @@ -574,7 +535,7 @@ _dvb_sub_parse_region_segment (DvbSub * dvb_sub, guint16 page_id, guint8 * buf, region->depth = 1 << (((*buf++) >> 2) & 7); if (region->depth < 2 || region->depth > 8) { - g_warning ("region depth %d is invalid\n", region->depth); + GST_WARNING ("region depth %d is invalid", region->depth); region->depth = 4; /* FIXME: Check from spec this is the default? */ } @@ -591,14 +552,13 @@ _dvb_sub_parse_region_segment (DvbSub * dvb_sub, guint16 page_id, guint8 * buf, region->bgcolor = (((*buf++) >> 2) & 3); } - dvb_log (DVB_LOG_REGION, G_LOG_LEVEL_DEBUG, - "id = %u, (%ux%u)@%u-bit", - region_id, region->width, region->height, region->depth); + GST_DEBUG ("REGION: id = %u, (%ux%u)@%u-bit", region_id, region->width, + region->height, region->depth); if (fill) { memset (region->pbuf, region->bgcolor, region->buf_size); - dvb_log (DVB_LOG_REGION, G_LOG_LEVEL_DEBUG, - "Filling region (%u) with bgcolor = %u", region->id, region->bgcolor); + GST_DEBUG ("REGION: filling region (%u) with bgcolor = %u", region->id, + region->bgcolor); } delete_region_display_list (dvb_sub, region); /* Delete the region display list for current region - FIXME: why? */ @@ -641,14 +601,14 @@ _dvb_sub_parse_region_segment (DvbSub * dvb_sub, guint16 page_id, guint8 * buf, object_display->object_list_next = object->display_list; object->display_list = object_display; - dvb_log (DVB_LOG_REGION, G_LOG_LEVEL_DEBUG, - "REGION DATA: object_id = %u, region_id = %u, pos = %ux%u, obj_type = %u", - object->id, region->id, object_display->x_pos, object_display->y_pos, - object->type); - if (object->type == 1 || object->type == 2) - dvb_log (DVB_LOG_REGION, G_LOG_LEVEL_DEBUG, - "REGION DATA: fgcolor = %u, bgcolor = %u\n", object_display->fgcolor, - object_display->bgcolor); + GST_DEBUG ("REGION DATA: object_id = %u, region_id = %u, pos = %ux%u, " + "obj_type = %u", object->id, region->id, object_display->x_pos, + object_display->y_pos, object->type); + + if (object->type == 1 || object->type == 2) { + GST_DEBUG ("REGION DATA: fgcolor = %u, bgcolor = %u", + object_display->fgcolor, object_display->bgcolor); + } } } @@ -665,10 +625,7 @@ _dvb_sub_parse_clut_segment (DvbSub * dvb_sub, guint16 page_id, guint8 * buf, int y, cr, cb, alpha; int r, g, b, r_add, g_add, b_add; -#ifdef DEBUG_PACKET_CONTENTS - g_print ("DVB clut packet:\n"); - gst_util_dump_mem (buf, buf_size); -#endif + GST_MEMDUMP ("DVB clut packet", buf, buf_size); clut_id = *buf++; buf += 1; @@ -692,7 +649,7 @@ _dvb_sub_parse_clut_segment (DvbSub * dvb_sub, guint16 page_id, guint8 * buf, depth = (*buf) & 0xe0; if (depth == 0) { - g_warning ("Invalid clut depth 0x%x!", *buf); + GST_WARNING ("Invalid clut depth 0x%x!", *buf); return; } @@ -718,8 +675,8 @@ _dvb_sub_parse_clut_segment (DvbSub * dvb_sub, guint16 page_id, guint8 * buf, YUV_TO_RGB1_CCIR (cb, cr); YUV_TO_RGB2_CCIR (r, g, b, y); - dvb_log (DVB_LOG_CLUT, G_LOG_LEVEL_DEBUG, - "CLUT DEFINITION: clut %d := (%d,%d,%d,%d)", entry_id, r, g, b, alpha); + GST_DEBUG ("CLUT DEFINITION: clut %d := (%d,%d,%d,%d)", entry_id, r, g, b, + alpha); if (depth & 0x80) clut->clut4[entry_id] = RGBA (r, g, b, 255 - alpha); @@ -745,13 +702,13 @@ _dvb_sub_read_2bit_string (guint8 * destbuf, gint dbuf_len, static gboolean warning_shown = FALSE; if (!warning_shown) { - g_warning - ("Parsing 2bit color DVB sub-picture. This is not tested at all. If you see this message, " - "please provide the developers with sample media with these subtitles, if possible."); + g_warning ("Parsing 2bit color DVB sub-picture. This is not tested at all. " + "If you see this message, please provide the developers with sample " + "media with these subtitles, if possible."); warning_shown = TRUE; } - dvb_log (DVB_LOG_PIXEL, G_LOG_LEVEL_DEBUG, - "(n=2): Inside %s with dbuf_len = %d", __PRETTY_FUNCTION__, dbuf_len); + + GST_TRACE ("dbuf_len = %d", dbuf_len); while (!stop_parsing && (gst_bit_reader_get_remaining (&gb) > 0)) { guint run_length = 0, clut_index = 0; @@ -811,9 +768,9 @@ _dvb_sub_read_2bit_string (guint8 * destbuf, gint dbuf_len, /* Now we can simply memset run_length count of destination bytes * to clut_index, but only if not non_modifying */ - dvb_log (DVB_LOG_RUNLEN, G_LOG_LEVEL_DEBUG, - "Setting %u pixels to color 0x%x in destination buffer; dbuf_len left is %d pixels", - run_length, clut_index, dbuf_len); + GST_TRACE ("RUNLEN: setting %u pixels to color 0x%x in destination buffer, " + "dbuf_len left is %d pixels", run_length, clut_index, dbuf_len); + if (!(non_mod == 1 && bits == 1)) memset (destbuf, clut_index, run_length); @@ -825,8 +782,7 @@ _dvb_sub_read_2bit_string (guint8 * destbuf, gint dbuf_len, //gst_bit_reader_skip_to_byte (&gb); *srcbuf += (gst_bit_reader_get_pos (&gb) + 7) >> 3; - dvb_log (DVB_LOG_PIXEL, G_LOG_LEVEL_DEBUG, - "Returning from 2bit_string parser with %u pixels read", pixels_read); + GST_TRACE ("PIXEL: returning, read %u pixels", pixels_read); // FIXME: Shouldn't need this variable if tracking things in the loop better return pixels_read; } @@ -843,9 +799,8 @@ _dvb_sub_read_4bit_string (guint8 * destbuf, gint dbuf_len, guint32 bits = 0; guint32 pixels_read = 0; - dvb_log (DVB_LOG_RUNLEN, G_LOG_LEVEL_DEBUG, - "Entering 4bit_string parser at srcbuf position %p with buf_size = %d; destination buffer size is %d @ %p", - *srcbuf, buf_size, dbuf_len, destbuf); + GST_TRACE ("RUNLEN: srcbuf position %p, buf_size = %d; destination buffer " + "size is %d @ %p", *srcbuf, buf_size, dbuf_len, destbuf); while (!stop_parsing && (gst_bit_reader_get_remaining (&gb) > 0)) { guint run_length = 0, clut_index = 0; @@ -910,9 +865,9 @@ _dvb_sub_read_4bit_string (guint8 * destbuf, gint dbuf_len, /* Now we can simply memset run_length count of destination bytes * to clut_index, but only if not non_modifying */ - dvb_log (DVB_LOG_RUNLEN, G_LOG_LEVEL_DEBUG, - "Setting %u pixels to color 0x%x in destination buffer; dbuf_len left is %d pixels", - run_length, clut_index, dbuf_len); + GST_TRACE ("RUNLEN: setting %u pixels to color 0x%x in destination buffer; " + "dbuf_len left is %d pixels", run_length, clut_index, dbuf_len); + if (!(non_mod == 1 && bits == 1)) memset (destbuf, clut_index, run_length); @@ -924,8 +879,8 @@ _dvb_sub_read_4bit_string (guint8 * destbuf, gint dbuf_len, //gst_bit_reader_skip_to_byte (&gb); *srcbuf += (gst_bit_reader_get_pos (&gb) + 7) >> 3; - dvb_log (DVB_LOG_PIXEL, G_LOG_LEVEL_DEBUG, - "Returning from 4bit_string parser with %u pixels read", pixels_read); + GST_LOG ("Returning with %u pixels read", pixels_read); + // FIXME: Shouldn't need this variable if tracking things in the loop better return pixels_read; } @@ -948,8 +903,8 @@ _dvb_sub_read_8bit_string (guint8 * destbuf, gint dbuf_len, "please provide the developers with sample media with these subtitles, if possible."); warning_shown = TRUE; } - dvb_log (DVB_LOG_PIXEL, G_LOG_LEVEL_DEBUG, - "(n=8): Inside %s with dbuf_len = %d", __PRETTY_FUNCTION__, dbuf_len); + + GST_LOG ("dbuf_len = %d", dbuf_len); /* FFMPEG-FIXME: ffmpeg uses a manual byte walking algorithm, which might be more performant, * FFMPEG-FIXME: but it does almost absolutely no buffer length checking, so could walk over @@ -977,14 +932,11 @@ _dvb_sub_read_8bit_string (guint8 * destbuf, gint dbuf_len, /* run_length_3-127 */ gst_bit_reader_get_bits_uint32 (&gb, &run_length, 7); gst_bit_reader_get_bits_uint32 (&gb, &clut_index, 8); -#ifdef DEBUG - /* Emit a debugging message about stream not following specification */ + if (run_length < 3) { - dvb_log (DVB_LOG_STREAM, G_LOG_LEVEL_WARNING, - "8-bit/pixel_code_string::run_length_3-127 value was %u, but the spec requires it must be >=3", - run_length); + GST_WARNING ("runlength value was %u, but the spec requires it " + "must be >=3", run_length); } -#endif } } @@ -1005,9 +957,9 @@ _dvb_sub_read_8bit_string (guint8 * destbuf, gint dbuf_len, /* Now we can simply memset run_length count of destination bytes * to clut_index, but only if not non_modifying */ - dvb_log (DVB_LOG_RUNLEN, G_LOG_LEVEL_DEBUG, - "Setting %u pixels to color 0x%x in destination buffer; dbuf_len left is %d pixels", - run_length, clut_index, dbuf_len); + GST_TRACE ("RUNLEN: setting %u pixels to color 0x%x in destination buffer; " + "dbuf_len left is %d pixels", run_length, clut_index, dbuf_len); + if (!(non_mod == 1 && bits == 1)) memset (destbuf, clut_index, run_length); @@ -1015,8 +967,8 @@ _dvb_sub_read_8bit_string (guint8 * destbuf, gint dbuf_len, pixels_read += run_length; } - dvb_log (DVB_LOG_PIXEL, G_LOG_LEVEL_DEBUG, - "Returning from 8bit_string parser with %u pixels read", pixels_read); + GST_LOG ("Returning with %u pixels read", pixels_read); + // FIXME: Shouldn't need this variable if tracking things in the loop better return pixels_read; } @@ -1040,16 +992,13 @@ _dvb_sub_parse_pixel_data_block (DvbSub * dvb_sub, }; guint8 *map_table; - dvb_log (DVB_LOG_PIXEL, G_LOG_LEVEL_DEBUG, - "(parse_block): DVB pixel block size %d, %s field:", - buf_size, top_bottom ? "bottom" : "top"); + GST_LOG ("DVB pixel block size %d, %s field:", buf_size, + top_bottom ? "bottom" : "top"); -#ifdef DEBUG_PACKET_CONTENTS - gst_util_dump_mem (buf, buf_size); -#endif + GST_MEMDUMP ("packet", buf, buf_size); if (region == NULL) { - g_print ("Region is NULL, returning\n"); + GST_LOG ("Region is NULL, returning"); return; } @@ -1062,11 +1011,11 @@ _dvb_sub_parse_pixel_data_block (DvbSub * dvb_sub, y_pos++; while (buf < buf_end) { - dvb_log (DVB_LOG_PIXEL, G_LOG_LEVEL_DEBUG, - "Iteration start, %u bytes missing from end; buf = %p, buf_end = %p; " - "Region is number %u, with a dimension of %dx%d; We are at position %dx%d", - buf_end - buf, buf, buf_end, + GST_LOG ("Iteration start, %u bytes missing from end; buf = %p, " + "buf_end = %p; Region is number %u, with a dimension of %dx%d; " + "We are at position %dx%d", (guint) (buf_end - buf), buf, buf_end, region->id, region->width, region->height, x_pos, y_pos); + // FFMPEG-FIXME: ffmpeg doesn't check for equality and so can overflow destination buffer later on with bad input data // FFMPEG-FIXME: However that makes it warn on end_of_object_line and map tables as well, so we add the dest_buf_filled tracking // FIXME: Removed x_pos checking here, because we don't want to turn dest_buf_filled to TRUE permanently in that case @@ -1079,9 +1028,11 @@ _dvb_sub_parse_pixel_data_block (DvbSub * dvb_sub, switch (*buf++) { case 0x10: if (dest_buf_filled) { - g_warning ("Invalid object location for data_type 0x%x!\n", *(buf - 1)); /* FIXME: Be more verbose */ - g_print ("Remaining data after invalid object location:\n"); - gst_util_dump_mem (buf, buf_end - buf); + /* FIXME: Be more verbose */ + GST_WARNING ("Invalid object location for data_type 0x%x!", + *(buf - 1)); + GST_MEMDUMP ("Remaining data after invalid object location:", buf, + (guint) (buf_end - buf)); return; } @@ -1100,14 +1051,16 @@ _dvb_sub_parse_pixel_data_block (DvbSub * dvb_sub, break; case 0x11: if (dest_buf_filled) { - g_warning ("Invalid object location for data_type 0x%x!\n", *(buf - 1)); /* FIXME: Be more verbose */ - g_print ("Remaining data after invalid object location:\n"); - gst_util_dump_mem (buf, buf_end - buf); + /* FIXME: Be more verbose */ + GST_WARNING ("Invalid object location for data_type 0x%x!", + *(buf - 1)); + GST_MEMDUMP ("Remaining data after invalid object location:", buf, + buf_end - buf); return; // FIXME: Perhaps tell read_nbit_string that dbuf_len is zero and let it walk the bytes regardless? (Same FIXME for 2bit and 8bit) } if (region->depth < 4) { - g_warning ("4-bit pixel string in %d-bit region!\n", region->depth); + GST_WARNING ("4-bit pixel string in %d-bit region!", region->depth); return; } @@ -1116,27 +1069,27 @@ _dvb_sub_parse_pixel_data_block (DvbSub * dvb_sub, else map_table = NULL; - dvb_log (DVB_LOG_PIXEL, G_LOG_LEVEL_DEBUG, - "READ_nBIT_STRING (4): String data into position %dx%d; buf before is %p\n", - x_pos, y_pos, buf); + GST_LOG ("READ_4BIT_STRING: String data into position %dx%d; " + "buf before is %p", x_pos, y_pos, buf); // FFMPEG-FIXME: ffmpeg code passes buf_size instead of buf_end - buf, and could // FFMPEG-FIXME: therefore potentially walk over the memory area we own x_pos += _dvb_sub_read_4bit_string (pbuf + (y_pos * region->width) + x_pos, region->width - x_pos, &buf, buf_end - buf, non_mod, map_table); - dvb_log (DVB_LOG_PIXEL, G_LOG_LEVEL_DEBUG, - "READ_nBIT_STRING (4) finished: buf pointer now %p", buf); + GST_DEBUG ("READ_4BIT_STRING finished: buf pointer now %p", buf); break; case 0x12: if (dest_buf_filled) { - g_warning ("Invalid object location for data_type 0x%x!\n", *(buf - 1)); /* FIXME: Be more verbose */ - g_print ("Remaining data after invalid object location:\n"); - gst_util_dump_mem (buf, buf_end - buf); + /* FIXME: Be more verbose */ + GST_WARNING ("Invalid object location for data_type 0x%x!", + *(buf - 1)); + GST_MEMDUMP ("Remaining data after invalid object location:", + buf, (guint) (buf_end - buf)); return; } if (region->depth < 8) { - g_warning ("8-bit pixel string in %d-bit region!\n", region->depth); + GST_WARNING ("8-bit pixel string in %d-bit region!", region->depth); return; } // FFMPEG-FIXME: ffmpeg code passes buf_size instead of buf_end - buf, and could @@ -1147,8 +1100,7 @@ _dvb_sub_parse_pixel_data_block (DvbSub * dvb_sub, break; case 0x20: - dvb_log (DVB_LOG_PIXEL, G_LOG_LEVEL_DEBUG, - "(parse_block): handling map2to4 table data"); + GST_DEBUG ("handling map2to4 table data"); /* FIXME: I don't see any guards about buffer size here - buf++ happens with the switch, but * FIXME: buffer is walked without length checks? Same deal in other map table cases */ map2to4[0] = (*buf) >> 4; @@ -1157,27 +1109,23 @@ _dvb_sub_parse_pixel_data_block (DvbSub * dvb_sub, map2to4[3] = (*buf++) & 0xf; break; case 0x21: - dvb_log (DVB_LOG_PIXEL, G_LOG_LEVEL_DEBUG, - "(parse_block): handling map2to8 table data"); + GST_DEBUG ("handling map2to8 table data"); for (i = 0; i < 4; i++) map2to8[i] = *buf++; break; case 0x22: - dvb_log (DVB_LOG_PIXEL, G_LOG_LEVEL_DEBUG, - "(parse_block): handling map4to8 table data"); + GST_DEBUG ("handling map4to8 table data"); for (i = 0; i < 16; i++) map4to8[i] = *buf++; break; - case 0xf0: - dvb_log (DVB_LOG_PIXEL, G_LOG_LEVEL_DEBUG, - "(parse_block): end of object line code encountered"); + GST_DEBUG ("end of object line code encountered"); x_pos = display->x_pos; y_pos += 2; break; default: /* FIXME: Do we consume word align stuffing byte that could follow top/bottom data? */ - g_warning ("Unknown/unsupported pixel block 0x%x", *(buf - 1)); + GST_WARNING ("Unknown/unsupported pixel block 0x%x", *(buf - 1)); } } } @@ -1197,13 +1145,11 @@ _dvb_sub_parse_object_segment (DvbSub * dvb_sub, guint16 page_id, guint8 * buf, object = get_object (dvb_sub, object_id); - dvb_log (DVB_LOG_OBJECT, G_LOG_LEVEL_DEBUG, - "parse_object_segment: A new object segment has occurred for object_id = %u", + GST_DEBUG ("OBJECT: a new object segment has occurred for object_id = %u", object_id); if (!object) { - g_warning - ("Nothing known about object with ID %u yet inside parse_object_segment, bailing out", + GST_WARNING ("Nothing known about object with ID %u yet, bailing out", object_id); return; } @@ -1222,7 +1168,7 @@ _dvb_sub_parse_object_segment (DvbSub * dvb_sub, guint16 page_id, guint8 * buf, buf += 2; if (buf + top_field_len + bottom_field_len > buf_end) { - g_warning ("%s: Field data size too large\n", __PRETTY_FUNCTION__); + GST_WARNING ("Field data size too large"); return; } @@ -1232,9 +1178,10 @@ _dvb_sub_parse_object_segment (DvbSub * dvb_sub, guint16 page_id, guint8 * buf, display = display->object_list_next) { block = buf; - dvb_log (DVB_LOG_OBJECT, G_LOG_LEVEL_DEBUG, - "Parsing top and bottom part of object id %d; top_field_len = %u, bottom_field_len = %u", + GST_DEBUG ("OBJECT: parsing top and bottom part of object id %d; " + "top_field_len = %u, bottom_field_len = %u", display->object_id, top_field_len, bottom_field_len); + _dvb_sub_parse_pixel_data_block (dvb_sub, display, block, top_field_len, TOP_FIELD, non_modifying_color); @@ -1248,10 +1195,9 @@ _dvb_sub_parse_object_segment (DvbSub * dvb_sub, guint16 page_id, guint8 * buf, } } else if (coding_method == 1) { - g_warning ("'a string of characters' coding method not supported (yet?)!"); + GST_FIXME ("'a string of characters' coding method not supported yet!"); } else { - g_warning ("%s: Unknown object coding 0x%x\n", __PRETTY_FUNCTION__, - coding_method); + GST_WARNING ("Unknown object coding 0x%x", coding_method); } } @@ -1310,10 +1256,9 @@ _dvb_sub_parse_end_of_display_set (DvbSub * dvb_sub, guint16 page_id, guint32 *clut_table; int i; - static unsigned counter = 0; /* DEBUG use only */ + static unsigned counter = 0; /* DEBUG use only *//* FIXME: get rid */ - dvb_log (DVB_LOG_DISPLAY, G_LOG_LEVEL_DEBUG, - "END OF DISPLAY SET: page_id = %u, length = %d\n", page_id, buf_size); + GST_DEBUG ("DISPLAY SET END: page_id = %u, length = %d", page_id, buf_size); sub->rects = NULL; #if 0 /* FIXME: PTS stuff not figured out yet */ @@ -1379,23 +1324,19 @@ _dvb_sub_parse_end_of_display_set (DvbSub * dvb_sub, guint16 page_id, rect->pict.palette = g_malloc ((1 << region->depth) * sizeof (guint32)); /* FIXME: Can we use GSlice here? */ memcpy (rect->pict.palette, clut_table, (1 << region->depth) * sizeof (guint32)); -#if 0 - g_print ("rect->pict.data.palette content:\n"); - gst_util_dump_mem (rect->pict.palette, - (1 << region->depth) * sizeof (guint32)); -#endif + + GST_MEMDUMP ("rect->pict.data.palette content", + (guint8 *) rect->pict.palette, (1 << region->depth) * sizeof (guint32)); rect->pict.data = g_malloc (region->buf_size); /* FIXME: Can we use GSlice here? */ memcpy (rect->pict.data, region->pbuf, region->buf_size); ++counter; - dvb_log (DVB_LOG_DISPLAY, G_LOG_LEVEL_DEBUG, - "An object rect created: number %u, iteration %u, pos: %d:%d, size: %dx%d", - counter, i, rect->x, rect->y, rect->w, rect->h); -#if 0 - g_print ("rect->pict.data content:\n"); - gst_util_dump_mem (rect->pict.data, region->buf_size); -#endif + GST_DEBUG ("DISPLAY: an object rect created: number %u, iteration %u, " + "pos: %d:%d, size: %dx%d", counter, i, rect->x, rect->y, rect->w, + rect->h); + + GST_MEMDUMP ("rect->pict.data content", rect->pict.data, region->buf_size); ++i; } @@ -1484,50 +1425,46 @@ dvb_sub_feed_with_pts (DvbSub * dvb_sub, guint64 pts, guint8 * data, gint len) guint16 segment_len; guint16 page_id; - dvb_log (DVB_LOG_PACKET, G_LOG_LEVEL_DEBUG, - "Inside dvb_sub_feed_with_pts with pts=%" G_GUINT64_FORMAT - " and length %d", pts, len); + GST_DEBUG ("pts=%" G_GUINT64_FORMAT " and length %d", pts, len); g_return_val_if_fail (data != NULL, -1); if (len <= 3) { /* len(0x20 0x00 end_of_PES_data_field_marker) */ - g_warning ("Data length too short"); + GST_WARNING ("Data length too short"); return -1; } if (data[pos++] != 0x20) { - g_warning - ("Tried to handle a PES packet private data that isn't a subtitle packet (does not start with 0x20)"); + GST_WARNING ("Tried to handle a PES packet private data that isn't a " + "subtitle packet (does not start with 0x20)"); return -1; } if (data[pos++] != 0x00) { - g_warning - ("'Subtitle stream in this PES packet' was not 0x00, so this is in theory not a DVB subtitle stream (but some other subtitle standard?); bailing out"); + GST_WARNING ("'Subtitle stream in this PES packet' was not 0x00, so this " + "is in theory not a DVB subtitle stream (but some other subtitle " + "standard?); bailing out"); return -1; } while (data[pos++] == DVB_SUB_SYNC_BYTE) { if ((len - pos) < (2 * 2 + 1)) { - g_warning - ("Data after SYNC BYTE too short, less than needed to even get to segment_length"); + GST_WARNING ("Data after SYNC BYTE too short, less than needed to " + "even get to segment_length"); return -2; } segment_type = data[pos++]; - dvb_log (DVB_LOG_PACKET, G_LOG_LEVEL_DEBUG, - "=== Segment type is 0x%x", segment_type); + GST_DEBUG ("=== Segment type is 0x%x", segment_type); page_id = (data[pos] << 8) | data[pos + 1]; - dvb_log (DVB_LOG_PACKET, G_LOG_LEVEL_DEBUG, "page_id is 0x%x", page_id); + GST_DEBUG ("page_id is 0x%x", page_id); pos += 2; segment_len = (data[pos] << 8) | data[pos + 1]; - dvb_log (DVB_LOG_PACKET, G_LOG_LEVEL_DEBUG, - "segment_length is %d (0x%x 0x%x)", segment_len, data[pos], + GST_DEBUG ("segment_length is %d (0x%x 0x%x)", segment_len, data[pos], data[pos + 1]); pos += 2; if ((len - pos) < segment_len) { - g_warning - ("segment_length was told to be %u, but we only have %d bytes left", - segment_len, len - pos); + GST_WARNING ("segment_length was told to be %u, but we only have " + "%d bytes left", segment_len, len - pos); return -2; } // TODO: Parse the segment per type (this is probably a leftover TODO that is now done?) @@ -1535,50 +1472,44 @@ dvb_sub_feed_with_pts (DvbSub * dvb_sub, guint64 pts, guint8 * data, gint len) * FIXME: but we let it slip and just take it for granted in end_of_display_set */ switch (segment_type) { case DVB_SUB_SEGMENT_PAGE_COMPOSITION: - dvb_log (DVB_LOG_PACKET, G_LOG_LEVEL_DEBUG, - "Page composition segment at buffer pos %u\n", pos); + GST_DEBUG ("Page composition segment at buffer pos %u", pos); _dvb_sub_parse_page_segment (dvb_sub, page_id, data + pos, segment_len); /* FIXME: Not sure about args */ break; case DVB_SUB_SEGMENT_REGION_COMPOSITION: - dvb_log (DVB_LOG_PACKET, G_LOG_LEVEL_DEBUG, - "Region composition segment at buffer pos %u\n", pos); + GST_DEBUG ("Region composition segment at buffer pos %u", pos); _dvb_sub_parse_region_segment (dvb_sub, page_id, data + pos, segment_len); /* FIXME: Not sure about args */ break; case DVB_SUB_SEGMENT_CLUT_DEFINITION: - dvb_log (DVB_LOG_PACKET, G_LOG_LEVEL_DEBUG, - "CLUT definition segment at buffer pos %u\n", pos); + GST_DEBUG ("CLUT definition segment at buffer pos %u", pos); _dvb_sub_parse_clut_segment (dvb_sub, page_id, data + pos, segment_len); /* FIXME: Not sure about args */ break; case DVB_SUB_SEGMENT_OBJECT_DATA: - dvb_log (DVB_LOG_PACKET, G_LOG_LEVEL_DEBUG, - "Object data segment at buffer pos %u\n", pos); + GST_DEBUG ("Object data segment at buffer pos %u", pos); _dvb_sub_parse_object_segment (dvb_sub, page_id, data + pos, segment_len); /* FIXME: Not sure about args */ break; case DVB_SUB_SEGMENT_DISPLAY_DEFINITION: - dvb_log (DVB_LOG_PACKET, G_LOG_LEVEL_DEBUG, - "display definition segment at buffer pos %u\n", pos); + GST_DEBUG ("display definition segment at buffer pos %u", pos); _dvb_sub_parse_display_definition_segment (dvb_sub, data + pos, segment_len); break; case DVB_SUB_SEGMENT_END_OF_DISPLAY_SET: - dvb_log (DVB_LOG_PACKET, G_LOG_LEVEL_DEBUG, - "End of display set at buffer pos %u\n", pos); + GST_DEBUG ("End of display set at buffer pos %u", pos); _dvb_sub_parse_end_of_display_set (dvb_sub, page_id, data + pos, segment_len, pts); /* FIXME: Not sure about args */ break; default: - g_warning ("Unhandled segment type 0x%x", segment_type); + GST_FIXME ("Unhandled segment type 0x%x", segment_type); break; } pos += segment_len; if (pos == len) { - g_warning ("Data ended without a PES data end marker"); + GST_WARNING ("Data ended without a PES data end marker"); return 1; } } - g_warning ("Processed %d bytes out of %d\n", pos, len); + GST_LOG ("Processed %d bytes out of %d", pos, len); return pos; } @@ -1605,14 +1536,3 @@ dvb_sub_set_callbacks (DvbSub * dvb_sub, DvbSubCallbacks * callbacks, priv->callbacks = *callbacks; priv->user_data = user_data; } - -void -dvb_sub_set_global_log_cb (void (*log_cb) (GLogLevelFlags log_level, - const gchar * format, va_list args, gpointer user_data), - gpointer user_data) -{ - if (log_cb) { - g_log_callback = log_cb; - g_log_callback_user_data = user_data; - } -} diff --git a/gst/dvbsuboverlay/dvb-sub.h b/gst/dvbsuboverlay/dvb-sub.h index 887ffe80b5..ae7297747c 100644 --- a/gst/dvbsuboverlay/dvb-sub.h +++ b/gst/dvbsuboverlay/dvb-sub.h @@ -153,15 +153,14 @@ typedef struct { gpointer _dvb_sub_reserved[3]; } DvbSubCallbacks; +void dvb_sub_init_debug (void); + GType dvb_sub_get_type (void) G_GNUC_CONST; DvbSub *dvb_sub_new (void); gint dvb_sub_feed_with_pts (DvbSub *dvb_sub, guint64 pts, guint8 *data, gint len); void dvb_sub_set_callbacks (DvbSub *dvb_sub, DvbSubCallbacks *callbacks, gpointer user_data); void dvb_subtitles_free (DVBSubtitles *sub); -void dvb_sub_set_global_log_cb (void (*log_cb) (GLogLevelFlags log_level, const gchar *format, va_list args, gpointer user_data), - gpointer user_data); - G_END_DECLS #endif /* _DVB_SUB_H_ */ diff --git a/gst/dvbsuboverlay/gstdvbsuboverlay.c b/gst/dvbsuboverlay/gstdvbsuboverlay.c index a1bfe85637..80ea604620 100644 --- a/gst/dvbsuboverlay/gstdvbsuboverlay.c +++ b/gst/dvbsuboverlay/gstdvbsuboverlay.c @@ -42,7 +42,6 @@ #include GST_DEBUG_CATEGORY_STATIC (gst_dvbsub_overlay_debug); -GST_DEBUG_CATEGORY_STATIC (gst_dvbsub_overlay_lib_debug); #define GST_CAT_DEFAULT gst_dvbsub_overlay_debug /* Filter signals and props */ @@ -158,27 +157,6 @@ gst_dvbsub_overlay_class_init (GstDVBSubOverlayClass * klass) GST_DEBUG_FUNCPTR (gst_dvbsub_overlay_change_state); } -static void -_dvbsub_log_cb (GLogLevelFlags level, const gchar * fmt, va_list args, - gpointer render) -{ - gchar *message = g_strdup_vprintf (fmt, args); - - if (level & G_LOG_LEVEL_ERROR) - GST_CAT_ERROR (gst_dvbsub_overlay_lib_debug, "%s", message); - else if (level & G_LOG_LEVEL_WARNING) - GST_CAT_WARNING (gst_dvbsub_overlay_lib_debug, "%s", message); - else if (level & G_LOG_LEVEL_INFO) - GST_CAT_INFO (gst_dvbsub_overlay_lib_debug, "%s", message); - else if (level & G_LOG_LEVEL_DEBUG) - GST_CAT_DEBUG (gst_dvbsub_overlay_lib_debug, "%s", message); - else - GST_CAT_LOG (gst_dvbsub_overlay_lib_debug, - "log level %d: %s", level, message); - - g_free (message); -} - static void gst_dvbsub_overlay_flush_subtitles (GstDVBSubOverlay * render) { @@ -1178,10 +1156,8 @@ plugin_init (GstPlugin * plugin) { GST_DEBUG_CATEGORY_INIT (gst_dvbsub_overlay_debug, "dvbsuboverlay", 0, "DVB subtitle overlay"); - GST_DEBUG_CATEGORY_INIT (gst_dvbsub_overlay_lib_debug, "dvbsub_library", - 0, "libdvbsub library"); - dvb_sub_set_global_log_cb (_dvbsub_log_cb, NULL); + dvb_sub_init_debug (); return gst_element_register (plugin, "dvbsuboverlay", GST_RANK_PRIMARY, GST_TYPE_DVBSUB_OVERLAY); From 699e0abd492be2c740e75b3ff569aa84d35e03a7 Mon Sep 17 00:00:00 2001 From: Lasse Laukkanen Date: Fri, 17 Dec 2010 19:41:25 +0200 Subject: [PATCH 126/448] qtmux: allow zero duration tracks --- gst/qtmux/gstqtmux.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/gst/qtmux/gstqtmux.c b/gst/qtmux/gstqtmux.c index 5ef009a7cf..2cd848b222 100644 --- a/gst/qtmux/gstqtmux.c +++ b/gst/qtmux/gstqtmux.c @@ -1645,6 +1645,11 @@ gst_qt_mux_stop_file (GstQTMux * qtmux) GstCollectData *cdata = (GstCollectData *) walk->data; GstQTPad *qtpad = (GstQTPad *) cdata; + if (!qtpad->last_buf) { + GST_DEBUG_OBJECT (qtmux, "Pad %s has no buffers", + GST_PAD_NAME (qtpad->collect.pad)); + continue; + } /* send last buffer */ GST_DEBUG_OBJECT (qtmux, "Sending the last buffer for pad %s", GST_PAD_NAME (qtpad->collect.pad)); From 369f41913cce96658d7a0f26e02f58200ef40af3 Mon Sep 17 00:00:00 2001 From: Leo Singer Date: Sat, 18 Dec 2010 12:48:42 -0800 Subject: [PATCH 127/448] applemedia: fix compiler warning: redundant declaration of 'parent_class' GST_BOILERPLATE_FULL declares parent_class as well. https://bugzilla.gnome.org/show_bug.cgi?id=637532 --- sys/applemedia/miovideosrc.c | 2 -- sys/applemedia/qtkitvideosrc.m | 6 ++---- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/sys/applemedia/miovideosrc.c b/sys/applemedia/miovideosrc.c index a2d1fa6be7..7b0e428c49 100644 --- a/sys/applemedia/miovideosrc.c +++ b/sys/applemedia/miovideosrc.c @@ -83,8 +83,6 @@ static void gst_mio_video_src_probe_interface_init (gpointer g_iface, static void gst_mio_video_src_init_interfaces (GType type); -static GstPushSrcClass *parent_class; - GST_BOILERPLATE_FULL (GstMIOVideoSrc, gst_mio_video_src, GstPushSrc, GST_TYPE_PUSH_SRC, gst_mio_video_src_init_interfaces); diff --git a/sys/applemedia/qtkitvideosrc.m b/sys/applemedia/qtkitvideosrc.m index 8e80cae8d6..67388f051a 100644 --- a/sys/applemedia/qtkitvideosrc.m +++ b/sys/applemedia/qtkitvideosrc.m @@ -86,7 +86,8 @@ typedef enum _QueueState { HAS_FRAME_OR_STOP_REQUEST, } QueueState; -static GstPushSrcClass * parent_class; +GST_BOILERPLATE (GstQTKitVideoSrc, gst_qtkit_video_src, GstPushSrc, + GST_TYPE_PUSH_SRC); @interface GstQTKitVideoSrcImpl : NSObject { GstElement *element; @@ -466,9 +467,6 @@ enum PROP_DEVICE_INDEX }; -GST_BOILERPLATE (GstQTKitVideoSrc, gst_qtkit_video_src, GstPushSrc, - GST_TYPE_PUSH_SRC); - static void gst_qtkit_video_src_finalize (GObject * obj); static void gst_qtkit_video_src_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec); From 1ec5ffbfc9dc5483e5de04a85cf4372a5c2e89dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Sun, 19 Dec 2010 11:17:47 +0100 Subject: [PATCH 128/448] autovideoconvert: Rename and adjust unit test too --- Makefile.am | 1 + tests/check/Makefile.am | 2 +- tests/check/elements/.gitignore | 1 + .../{autocolorspace.c => autovideoconvert.c} | 20 +++++++++---------- 4 files changed, 13 insertions(+), 11 deletions(-) rename tests/check/elements/{autocolorspace.c => autovideoconvert.c} (81%) diff --git a/Makefile.am b/Makefile.am index 37b104d17e..93388d7927 100644 --- a/Makefile.am +++ b/Makefile.am @@ -52,6 +52,7 @@ CRUFT_FILES = \ $(top_builddir)/gst/shapewipe/.libs/*.{so,dll,DLL,dylib} \ $(top_builddir)/gst/imagefreeze/.libs/*.{so,dll,DLL,dylib} \ $(top_builddir)/sys/oss4/.libs/*.{so,dll,DLL,dylib} \ + $(top_builddir)/tests/check/elements/autocolorspace \ $(top_builddir)/tests/check/elements/capssetter \ $(top_builddir)/tests/check/elements/imagefreeze \ $(top_builddir)/tests/check/pipelines/metadata \ diff --git a/tests/check/Makefile.am b/tests/check/Makefile.am index 81c5862e9c..1b698a3ae8 100644 --- a/tests/check/Makefile.am +++ b/tests/check/Makefile.am @@ -152,7 +152,7 @@ check_PROGRAMS = \ elements/ac3parse \ elements/amrparse \ elements/autoconvert \ - elements/autocolorspace \ + elements/autovideoconvert \ elements/asfmux \ elements/camerabin \ elements/dataurisrc \ diff --git a/tests/check/elements/.gitignore b/tests/check/elements/.gitignore index 175b0bea08..95eaceba02 100644 --- a/tests/check/elements/.gitignore +++ b/tests/check/elements/.gitignore @@ -5,6 +5,7 @@ amrparse asfmux assrender autoconvert +autovideoconvert camerabin deinterleave dataurisrc diff --git a/tests/check/elements/autocolorspace.c b/tests/check/elements/autovideoconvert.c similarity index 81% rename from tests/check/elements/autocolorspace.c rename to tests/check/elements/autovideoconvert.c index 51371f3b5e..c4e9e51055 100644 --- a/tests/check/elements/autocolorspace.c +++ b/tests/check/elements/autovideoconvert.c @@ -1,6 +1,6 @@ /* GStreamer * - * unit test for autocolorspace element + * unit test for autovideoconvert element * Copyright (C) 2009 Jan Schmidt * Copyright (C) 2010 ST-Ericsson SA * @author: Benjamin Gaignard @@ -95,13 +95,13 @@ run_test (const gchar * pipeline_string) } -GST_START_TEST (test_autocolorspace_rbg2bayer) +GST_START_TEST (test_autovideoconvert_rbg2bayer) { gchar *pipeline; pipeline = g_strdup_printf - ("videotestsrc num-buffers=1 ! video/x-raw-rgb,bpp=32,depth=32,width=100,height=100,framerate=10/1 ! autocolorspace ! video/x-raw-bayer,width=100,height=100,format=bggr,framerate=10/1 ! fakesink"); + ("videotestsrc num-buffers=1 ! video/x-raw-rgb,bpp=32,depth=32,width=100,height=100,framerate=10/1 ! autovideoconvert ! video/x-raw-bayer,width=100,height=100,format=bggr,framerate=10/1 ! fakesink"); run_test (pipeline); g_free (pipeline); @@ -109,13 +109,13 @@ GST_START_TEST (test_autocolorspace_rbg2bayer) GST_END_TEST; -GST_START_TEST (test_autocolorspace_ffmpegcolorspace) +GST_START_TEST (test_autovideoconvert_ffmpegcolorspace) { gchar *pipeline; pipeline = g_strdup_printf - ("videotestsrc num-buffers=1 ! video/x-raw-rgb,bpp=32,width=100,height=100,framerate=10/1 ! autocolorspace ! video/x-raw-rgb,bpp=16,width=100,height=100,framerate=10/1 ! fakesink"); + ("videotestsrc num-buffers=1 ! video/x-raw-rgb,bpp=32,width=100,height=100,framerate=10/1 ! autovideoconvert ! video/x-raw-rgb,bpp=16,width=100,height=100,framerate=10/1 ! fakesink"); run_test (pipeline); g_free (pipeline); @@ -124,16 +124,16 @@ GST_START_TEST (test_autocolorspace_ffmpegcolorspace) GST_END_TEST; static Suite * -autocolorspace_suite (void) +autovideoconvert_suite (void) { - Suite *s = suite_create ("autocolorspace"); + Suite *s = suite_create ("autovideoconvert"); TCase *tc_basic = tcase_create ("general"); suite_add_tcase (s, tc_basic); - tcase_add_test (tc_basic, test_autocolorspace_rbg2bayer); - tcase_add_test (tc_basic, test_autocolorspace_ffmpegcolorspace); + tcase_add_test (tc_basic, test_autovideoconvert_rbg2bayer); + tcase_add_test (tc_basic, test_autovideoconvert_ffmpegcolorspace); return s; } -GST_CHECK_MAIN (autocolorspace); +GST_CHECK_MAIN (autovideoconvert); From 0df84604192723daebacc007510a2edfaf412946 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Sun, 19 Dec 2010 11:19:38 +0100 Subject: [PATCH 129/448] states: Ignore more vdpau elements in the generic states test --- tests/check/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/check/Makefile.am b/tests/check/Makefile.am index 1b698a3ae8..48052a1f89 100644 --- a/tests/check/Makefile.am +++ b/tests/check/Makefile.am @@ -14,7 +14,7 @@ TESTS_ENVIRONMENT = \ GST_PLUGIN_SYSTEM_PATH= \ GST_PLUGIN_PATH=$(top_builddir)/gst:$(top_builddir)/sys:$(top_builddir)/ext:$(GST_PLUGINS_FFMPEG_DIR):$(GST_PLUGINS_UGLY_DIR):$(GST_PLUGINS_GOOD_DIR):$(GST_PLUGINS_BASE_DIR):$(GST_PLUGINS_DIR) \ GST_PLUGIN_LOADING_WHITELIST="gstreamer@$(GST_PLUGINS_DIR):gst-plugins-base@$(GSTPB_PLUGINS_DIR):gst-plugins-good:gst-plugins-ugly:gst-ffmpeg:gst-plugins-bad@$(top_builddir)" \ - GST_STATE_IGNORE_ELEMENTS="apexsink camerabin camerabin2 cdaudio dc1394src dccpclientsrc dccpclientsink dccpserversrc dccpserversink dvbsrc dvbbasebin dfbvideosink festival gsettingsvideosrc gsettingsvideosink gsettingsaudiosrc gsettingsaudiosink nassink rsndvdbin sdlaudiosink sdlvideosink vcdsrc rfbsrc vdpauyuvvideo vdpauvideoyuv vdpaumpegdec neonhttpsrc" + GST_STATE_IGNORE_ELEMENTS="apexsink camerabin camerabin2 cdaudio dc1394src dccpclientsrc dccpclientsink dccpserversrc dccpserversink dvbsrc dvbbasebin dfbvideosink festival gsettingsvideosrc gsettingsvideosink gsettingsaudiosrc gsettingsaudiosink nassink rsndvdbin sdlaudiosink sdlvideosink vcdsrc rfbsrc vdpauyuvvideo vdpauvideoyuv vdpaumpegdec vdpaumpeg4dec vdpauh264dec vdpauvideopostprocess vdpausink neonhttpsrc" plugindir = $(libdir)/gstreamer-@GST_MAJORMINOR@ From 530eca9984fff283a7bc21d088da2c58a6af5518 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Sun, 19 Dec 2010 11:20:25 +0100 Subject: [PATCH 130/448] autovideoconvert: Add autoconvert child before chaining up to parent state change function ...and remove/unlink autoconvert child when going back to NULL. --- gst/autoconvert/gstautovideoconvert.c | 57 ++++++++++++++++++++++----- 1 file changed, 48 insertions(+), 9 deletions(-) diff --git a/gst/autoconvert/gstautovideoconvert.c b/gst/autoconvert/gstautovideoconvert.c index 4dba911d3b..8e814b46c6 100644 --- a/gst/autoconvert/gstautovideoconvert.c +++ b/gst/autoconvert/gstautovideoconvert.c @@ -166,16 +166,25 @@ gst_auto_video_convert_class_init (GstAutoVideoConvertClass * klass) } -static void +static gboolean gst_auto_video_convert_add_autoconvert (GstAutoVideoConvert * autovideoconvert) { GstPad *pad; + if (autovideoconvert->autoconvert) + return TRUE; + autovideoconvert->autoconvert = gst_element_factory_make ("autoconvert", "autoconvertchild"); + if (!autovideoconvert->autoconvert) { + GST_ERROR_OBJECT (autovideoconvert, + "Could not create autoconvert instance"); + return FALSE; + } /* first add autoconvert in bin */ - gst_bin_add (GST_BIN (autovideoconvert), autovideoconvert->autoconvert); + gst_bin_add (GST_BIN (autovideoconvert), + gst_object_ref (autovideoconvert->autoconvert)); /* get sinkpad and link it to ghost sink pad */ pad = gst_element_get_static_pad (autovideoconvert->autoconvert, "sink"); @@ -187,6 +196,25 @@ gst_auto_video_convert_add_autoconvert (GstAutoVideoConvert * autovideoconvert) pad = gst_element_get_static_pad (autovideoconvert->autoconvert, "src"); gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (autovideoconvert->srcpad), pad); gst_object_unref (pad); + + return TRUE; +} + +static void +gst_auto_video_convert_remove_autoconvert (GstAutoVideoConvert * + autovideoconvert) +{ + if (!autovideoconvert->autoconvert) + return; + + gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (autovideoconvert->srcpad), + NULL); + gst_ghost_pad_set_target (GST_GHOST_PAD_CAST (autovideoconvert->sinkpad), + NULL); + + gst_bin_remove (GST_BIN (autovideoconvert), autovideoconvert->autoconvert); + gst_object_unref (autovideoconvert->autoconvert); + autovideoconvert->autoconvert = NULL; } static void @@ -221,23 +249,34 @@ gst_auto_video_convert_change_state (GstElement * element, GstAutoVideoConvert *autovideoconvert = GST_AUTO_VIDEO_CONVERT (element); GstStateChangeReturn ret; - ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); - if (ret == GST_STATE_CHANGE_FAILURE) - return ret; - switch (transition) { case GST_STATE_CHANGE_NULL_TO_READY: { /* create and add autoconvert in bin */ - gst_auto_video_convert_add_autoconvert (autovideoconvert); + if (!gst_auto_video_convert_add_autoconvert (autovideoconvert)) { + ret = GST_STATE_CHANGE_FAILURE; + return ret; + } /* get an updated list of factories */ gst_auto_video_convert_update_factory_list (autovideoconvert); GST_DEBUG_OBJECT (autovideoconvert, "set factories list"); /* give factory list to autoconvert */ g_object_set (GST_ELEMENT (autovideoconvert->autoconvert), "factories", factories, NULL); - /* synchronize autoconvert state with parent state */ - gst_element_sync_state_with_parent (autovideoconvert->autoconvert); + break; + } + default: + break; + } + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + if (ret == GST_STATE_CHANGE_FAILURE) + return ret; + + switch (transition) { + case GST_STATE_CHANGE_READY_TO_NULL: + { + gst_auto_video_convert_remove_autoconvert (autovideoconvert); break; } default: From ec85dfaa61ff7a5aa54713aa855628997ac8cd2f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Sun, 19 Dec 2010 11:38:03 +0100 Subject: [PATCH 131/448] autovideoconvert: Don't leak pad templates created from static pad templates --- gst/autoconvert/gstautovideoconvert.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gst/autoconvert/gstautovideoconvert.c b/gst/autoconvert/gstautovideoconvert.c index 8e814b46c6..00ee6db47c 100644 --- a/gst/autoconvert/gstautovideoconvert.c +++ b/gst/autoconvert/gstautovideoconvert.c @@ -230,6 +230,7 @@ gst_auto_video_convert_init (GstAutoVideoConvert * autovideoconvert, /* add sink ghost pad */ gst_element_add_pad (GST_ELEMENT (autovideoconvert), autovideoconvert->sinkpad); + gst_object_unref (pad_tmpl); /* get src pad template */ pad_tmpl = gst_static_pad_template_get (&srctemplate); @@ -238,6 +239,7 @@ gst_auto_video_convert_init (GstAutoVideoConvert * autovideoconvert, /* add src ghost pad */ gst_element_add_pad (GST_ELEMENT (autovideoconvert), autovideoconvert->srcpad); + gst_object_unref (pad_tmpl); return; } From 1f8ba27334be4846c2937e10c462d5d330f7bee9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Sun, 19 Dec 2010 12:00:25 +0100 Subject: [PATCH 132/448] jifmux: Don't leak taglist --- gst/jpegformat/gstjifmux.c | 1 + 1 file changed, 1 insertion(+) diff --git a/gst/jpegformat/gstjifmux.c b/gst/jpegformat/gstjifmux.c index 8e1bc267e8..5308969bdf 100644 --- a/gst/jpegformat/gstjifmux.c +++ b/gst/jpegformat/gstjifmux.c @@ -513,6 +513,7 @@ gst_jif_mux_mangle_markers (GstJifMux * self) } if (!tags) { tags = gst_tag_list_new (); + cleanup_tags = TRUE; } GST_DEBUG_OBJECT (self, "Tags to be serialized %" GST_PTR_FORMAT, tags); From 073916c9fb92dd4c18f16a3eb159064bace4c6f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Sun, 19 Dec 2010 12:03:03 +0100 Subject: [PATCH 133/448] imagecapturebin: Don't leak location string --- gst/camerabin2/gstimagecapturebin.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/gst/camerabin2/gstimagecapturebin.c b/gst/camerabin2/gstimagecapturebin.c index df253d06be..367232e325 100644 --- a/gst/camerabin2/gstimagecapturebin.c +++ b/gst/camerabin2/gstimagecapturebin.c @@ -72,6 +72,7 @@ gst_image_capture_bin_set_property (GObject * object, guint prop_id, switch (prop_id) { case PROP_LOCATION: + g_free (imgbin->location); imgbin->location = g_value_dup_string (value); if (imgbin->sink) { g_object_set (imgbin, "location", imgbin->location, NULL); @@ -99,6 +100,16 @@ gst_image_capture_bin_get_property (GObject * object, guint prop_id, } } +static void +gst_image_capture_bin_finalize (GObject * object) +{ + GstImageCaptureBin *imgbin = GST_IMAGE_CAPTURE_BIN_CAST (object); + + g_free (imgbin->location); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + static void gst_image_capture_bin_base_init (gpointer g_class) { @@ -123,6 +134,7 @@ gst_image_capture_bin_class_init (GstImageCaptureBinClass * klass) gobject_class->set_property = gst_image_capture_bin_set_property; gobject_class->get_property = gst_image_capture_bin_get_property; + gobject_class->finalize = gst_image_capture_bin_finalize; element_class->change_state = GST_DEBUG_FUNCPTR (gst_image_capture_bin_change_state); From 9605ff9aa8ebf7473d299555b5a20ee99b383db3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Sun, 19 Dec 2010 12:05:11 +0100 Subject: [PATCH 134/448] imagecapturebin: Don't leak pad template created from static pad template --- gst/camerabin2/gstimagecapturebin.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/gst/camerabin2/gstimagecapturebin.c b/gst/camerabin2/gstimagecapturebin.c index 367232e325..1ff5fe2bce 100644 --- a/gst/camerabin2/gstimagecapturebin.c +++ b/gst/camerabin2/gstimagecapturebin.c @@ -150,9 +150,13 @@ static void gst_image_capture_bin_init (GstImageCaptureBin * image_capturebin, GstImageCaptureBinClass * image_capturebin_class) { + GstPadTemplate *tmpl; + + tmpl = gst_static_pad_template_get (&sink_template); image_capturebin->ghostpad = - gst_ghost_pad_new_no_target_from_template ("sink", - gst_static_pad_template_get (&sink_template)); + gst_ghost_pad_new_no_target_from_template ("sink", tmpl); + gst_object_unref (tmpl); + gst_element_add_pad (GST_ELEMENT_CAST (image_capturebin), image_capturebin->ghostpad); From b297490b2aba0b00aba616c749bef4648d6fdc1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Sun, 19 Dec 2010 12:09:41 +0100 Subject: [PATCH 135/448] imagecapturebin: Don't leak pad and sink --- gst/camerabin2/gstimagecapturebin.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gst/camerabin2/gstimagecapturebin.c b/gst/camerabin2/gstimagecapturebin.c index 1ff5fe2bce..8ee540f49f 100644 --- a/gst/camerabin2/gstimagecapturebin.c +++ b/gst/camerabin2/gstimagecapturebin.c @@ -192,7 +192,7 @@ gst_image_capture_bin_create_elements (GstImageCaptureBin * icbin) if (!sink) goto error; - icbin->sink = gst_object_ref (sink); + icbin->sink = sink; g_object_set (sink, "location", icbin->location, "async", FALSE, NULL); /* add and link */ @@ -204,6 +204,7 @@ gst_image_capture_bin_create_elements (GstImageCaptureBin * icbin) pad = gst_element_get_static_pad (csp, "sink"); if (!gst_ghost_pad_set_target (GST_GHOST_PAD (icbin->ghostpad), pad)) goto error; + gst_object_unref (pad); icbin->elements_created = TRUE; return TRUE; From 16b1b967ada304bed9a212c6e1c655f8adb1aad8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Sun, 19 Dec 2010 12:12:12 +0100 Subject: [PATCH 136/448] imagecapturebin: Don't leak message in the unit test --- tests/check/elements/imagecapturebin.c | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/check/elements/imagecapturebin.c b/tests/check/elements/imagecapturebin.c index 860e3f5aa7..58331c1612 100644 --- a/tests/check/elements/imagecapturebin.c +++ b/tests/check/elements/imagecapturebin.c @@ -90,6 +90,7 @@ GST_START_TEST (test_simple_capture) GST_MESSAGE_EOS | GST_MESSAGE_ERROR); fail_unless (msg != NULL); fail_unless (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_EOS); + gst_message_unref (msg); /* check there are N_BUFFERS files */ for (i = 0; i < N_BUFFERS; i++) { From 7326cb514613ae7c97a74d3515ba4a427a29c559 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Sun, 19 Dec 2010 12:12:25 +0100 Subject: [PATCH 137/448] tagschecking: Fix some more memory leaks --- tests/check/pipelines/tagschecking.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/check/pipelines/tagschecking.c b/tests/check/pipelines/tagschecking.c index ed17c3f1a2..91a556c52f 100644 --- a/tests/check/pipelines/tagschecking.c +++ b/tests/check/pipelines/tagschecking.c @@ -114,6 +114,7 @@ test_mux_tags (const gchar * tag_str, const gchar * caps, sent_tags = gst_structure_from_string (tag_str, NULL); fail_unless (sent_tags != NULL); gst_tag_setter_merge_tags (setter, sent_tags, GST_TAG_MERGE_REPLACE); + gst_tag_list_free (sent_tags); gst_element_set_state (pipeline, GST_STATE_PLAYING); g_main_loop_run (loop); @@ -246,6 +247,7 @@ test_tags (const gchar * tag_str, const gchar * caps, const gchar * muxer, GST_DEBUG ("testing tags : %s", tag_str); test_mux_tags (tag_str, caps, muxer, tmpfile); test_demux_tags (tag_str, demuxer, tmpfile); + g_free (tmpfile); } #define H264_CAPS "video/x-h264, width=(int)320, height=(int)240," \ From 435bc16497cb4f11ee44570487f00018b619368d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Sun, 19 Dec 2010 12:50:30 +0100 Subject: [PATCH 138/448] qtmux: Free tag string after use --- gst/qtmux/gstqtmux.c | 1 + 1 file changed, 1 insertion(+) diff --git a/gst/qtmux/gstqtmux.c b/gst/qtmux/gstqtmux.c index 2cd848b222..8c8ea4251f 100644 --- a/gst/qtmux/gstqtmux.c +++ b/gst/qtmux/gstqtmux.c @@ -723,6 +723,7 @@ gst_qt_mux_add_3gp_keywords (GstQTMux * qtmux, const GstTagList * list, return; kwds = g_strsplit (keywords, ",", 0); + g_free (keywords); size = 0; for (i = 0; kwds[i]; i++) { From 5e5092e92cfdc988fd18cb42f0d697c6771f4fe4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Sun, 19 Dec 2010 12:53:34 +0100 Subject: [PATCH 139/448] qtmux: Free AtomInfo structs --- gst/qtmux/gstqtmux.c | 1 + 1 file changed, 1 insertion(+) diff --git a/gst/qtmux/gstqtmux.c b/gst/qtmux/gstqtmux.c index 8c8ea4251f..ba5b9aca88 100644 --- a/gst/qtmux/gstqtmux.c +++ b/gst/qtmux/gstqtmux.c @@ -359,6 +359,7 @@ gst_qt_mux_reset (GstQTMux * qtmux, gboolean alloc) for (walk = qtmux->extra_atoms; walk; walk = g_slist_next (walk)) { AtomInfo *ainfo = (AtomInfo *) walk->data; ainfo->free_func (ainfo->atom); + g_free (ainfo); } g_slist_free (qtmux->extra_atoms); qtmux->extra_atoms = NULL; From 8c371e5c353b07125d707930cbc6df66412a45d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Sun, 19 Dec 2010 17:16:10 +0530 Subject: [PATCH 140/448] autoconvert: Use gst_caps_can_intersect() --- gst/autoconvert/gstautoconvert.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/gst/autoconvert/gstautoconvert.c b/gst/autoconvert/gstautoconvert.c index 5a7a2eea99..ebe297c112 100644 --- a/gst/autoconvert/gstautoconvert.c +++ b/gst/autoconvert/gstautoconvert.c @@ -707,8 +707,8 @@ factory_can_intersect (GstAutoConvert * autoconvert, GstStaticPadTemplate *template = (GstStaticPadTemplate *) templates->data; if (template->direction == direction) { - GstCaps *intersect = NULL; GstCaps *tmpl_caps = NULL; + gboolean intersect; /* If there is more than one pad in this direction, we return FALSE * Only transform elements (with one sink and one source pad) @@ -723,18 +723,14 @@ factory_can_intersect (GstAutoConvert * autoconvert, has_direction = TRUE; tmpl_caps = gst_static_caps_get (&template->static_caps); - intersect = gst_caps_intersect (tmpl_caps, caps); - GST_DEBUG_OBJECT (autoconvert, "Intersection of factory %" GST_PTR_FORMAT + intersect = gst_caps_can_intersect (tmpl_caps, caps); + GST_DEBUG_OBJECT (autoconvert, "Factories %" GST_PTR_FORMAT " static caps %" GST_PTR_FORMAT " and caps %" GST_PTR_FORMAT - " is %" GST_PTR_FORMAT, factory, tmpl_caps, caps, intersect); + " can%s intersect", factory, tmpl_caps, caps, + intersect ? "" : " not"); gst_caps_unref (tmpl_caps); - if (intersect) { - if (!gst_caps_is_empty (intersect)) - ret = TRUE; - - gst_caps_unref (intersect); - } + ret |= intersect; } templates = g_list_next (templates); } From bf00fb84f38ab72934fcdda6d1a656f170c7f5b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Sun, 19 Dec 2010 17:23:24 +0530 Subject: [PATCH 141/448] tests: Fix leak in autoconvert test --- tests/check/elements/autoconvert.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tests/check/elements/autoconvert.c b/tests/check/elements/autoconvert.c index c36247f700..037795378c 100644 --- a/tests/check/elements/autoconvert.c +++ b/tests/check/elements/autoconvert.c @@ -20,7 +20,7 @@ */ #ifdef HAVE_CONFIG_H -# include "config.h" +#include "config.h" #endif #include @@ -77,6 +77,8 @@ set_autoconvert_factories (GstElement * autoconvert) } g_object_set (G_OBJECT (autoconvert), "factories", factories, NULL); + + g_list_free (factories); } typedef struct From 279cda20d7ad636fba911e818b88456f8e3f7100 Mon Sep 17 00:00:00 2001 From: Hu Gang Date: Mon, 20 Dec 2010 11:14:49 +0200 Subject: [PATCH 142/448] photography: add missing property and cabability flag for noise reduction --- gst-libs/gst/interfaces/photography.c | 10 ++++++++++ gst-libs/gst/interfaces/photography.h | 3 ++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/gst-libs/gst/interfaces/photography.c b/gst-libs/gst/interfaces/photography.c index 6fcf0d9c6a..b61e75eb8d 100644 --- a/gst-libs/gst/interfaces/photography.c +++ b/gst-libs/gst/interfaces/photography.c @@ -613,4 +613,14 @@ gst_photography_iface_class_init (gpointer g_class) "Zoom property", "How much the resulted image will be zoomed", 1.0f, 10.0f, 1.0f, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /* Noise Reduction, Bayer an YCC noise reduction are enabled by default */ + g_object_interface_install_property (g_class, + g_param_spec_uint (GST_PHOTOGRAPHY_PROP_NOISE_REDUCTION, + "Noise Reduction settings", + "Which noise reduction modes are enalbed in Camera (0 = disabled)", + 0, G_MAXUINT32, + GST_PHOTOGRAPHY_NOISE_REDUCTION_YCC | + GST_PHOTOGRAPHY_NOISE_REDUCTION_BAYER, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); } diff --git a/gst-libs/gst/interfaces/photography.h b/gst-libs/gst/interfaces/photography.h index 0198788fd6..1ab652ca73 100644 --- a/gst-libs/gst/interfaces/photography.h +++ b/gst-libs/gst/interfaces/photography.h @@ -174,7 +174,8 @@ typedef enum GST_PHOTOGRAPHY_CAPS_FOCUS = (1 << 7), GST_PHOTOGRAPHY_CAPS_APERTURE = (1 << 8), GST_PHOTOGRAPHY_CAPS_EXPOSURE = (1 << 9), - GST_PHOTOGRAPHY_CAPS_SHAKE = (1 << 10) + GST_PHOTOGRAPHY_CAPS_SHAKE = (1 << 10), + GST_PHOTOGRAPHY_CAPS_NOISE_REDUCTION = (1 << 11) } GstPhotoCaps; typedef enum From 7cbd6c231bdbd1b6d850f6bd535fde1fb5795325 Mon Sep 17 00:00:00 2001 From: Stefan Kost Date: Mon, 20 Dec 2010 13:51:03 +0200 Subject: [PATCH 143/448] photography: use a flags type instead of the uint Also use 0 as default and let the implementation set something that they support. --- gst-libs/gst/interfaces/photography.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/gst-libs/gst/interfaces/photography.c b/gst-libs/gst/interfaces/photography.c index b61e75eb8d..eeaa5d1ea2 100644 --- a/gst-libs/gst/interfaces/photography.c +++ b/gst-libs/gst/interfaces/photography.c @@ -616,11 +616,9 @@ gst_photography_iface_class_init (gpointer g_class) /* Noise Reduction, Bayer an YCC noise reduction are enabled by default */ g_object_interface_install_property (g_class, - g_param_spec_uint (GST_PHOTOGRAPHY_PROP_NOISE_REDUCTION, + g_param_spec_flags (GST_PHOTOGRAPHY_PROP_NOISE_REDUCTION, "Noise Reduction settings", "Which noise reduction modes are enalbed in Camera (0 = disabled)", - 0, G_MAXUINT32, - GST_PHOTOGRAPHY_NOISE_REDUCTION_YCC | - GST_PHOTOGRAPHY_NOISE_REDUCTION_BAYER, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + GST_TYPE_PHOTOGRAPHY_NOISE_REDUCTION, + 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); } From bbf331fb6b6fdc7e87fd4bbd5a6047cb57b011ab Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Mon, 20 Dec 2010 09:37:22 -0300 Subject: [PATCH 144/448] jifmux: Fix leaks on check test Fix leaks in jifmux check test --- tests/check/elements/jifmux.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/check/elements/jifmux.c b/tests/check/elements/jifmux.c index 3ec32dfbab..b481dbf9e0 100644 --- a/tests/check/elements/jifmux.c +++ b/tests/check/elements/jifmux.c @@ -807,6 +807,7 @@ check_content (ExifContent * content, void *user_data) fail_unless (strcmp (str, taglist_str) == 0); test_data->result = TRUE; + g_free (taglist_str); } break; case EXIF_TYPE_RATIONAL:{ @@ -886,6 +887,7 @@ check_content (ExifContent * content, void *user_data) } test_data->result = TRUE; + gst_buffer_unref (buf); } break; default: @@ -927,6 +929,7 @@ generate_jif_file_with_tags_from_taglist (GstTagList * taglist, pipeline = gst_parse_launch (launchline, NULL); fail_unless (pipeline != NULL); + g_free (launchline); jifmux = gst_bin_get_by_name (GST_BIN (pipeline), "jifmux0"); fail_unless (jifmux != NULL); From 9a2149cf02730be9348b48caa81d6cad4d5cd4db Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Mon, 20 Dec 2010 11:06:52 -0300 Subject: [PATCH 145/448] camerabin: Fix caps leaks Fix some caps leaks on unit tests --- tests/check/elements/camerabin.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/check/elements/camerabin.c b/tests/check/elements/camerabin.c index f5dbfdc03f..0df4f9b5bf 100644 --- a/tests/check/elements/camerabin.c +++ b/tests/check/elements/camerabin.c @@ -579,6 +579,7 @@ GST_START_TEST (test_video_recording) /* Set preview-caps */ g_object_set (camera, "preview-caps", preview_caps, NULL); + gst_caps_unref (preview_caps); /* check that the camera is idle */ g_object_get (camera, "idle", &idle, NULL); @@ -626,6 +627,7 @@ GST_START_TEST (test_video_recording_with_flags) /* Set preview-caps */ g_object_set (camera, "preview-caps", preview_caps, NULL); + gst_caps_unref (preview_caps); GST_INFO ("starting capture"); g_signal_emit_by_name (camera, "capture-start", NULL); @@ -712,6 +714,7 @@ GST_START_TEST (test_video_recording_no_audio) /* Set preview-caps */ g_object_set (camera, "preview-caps", preview_caps, NULL); + gst_caps_unref (preview_caps); GST_INFO ("starting capture"); g_signal_emit_by_name (camera, "capture-start", NULL); From 54d6546bda76c54f22c268aab52f8d2780dfbe81 Mon Sep 17 00:00:00 2001 From: Edward Hervey Date: Mon, 20 Dec 2010 17:47:29 +0100 Subject: [PATCH 146/448] Automatic update of common submodule From 169462a to 46445ad --- common | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common b/common index 169462a62f..46445ad50f 160000 --- a/common +++ b/common @@ -1 +1 @@ -Subproject commit 169462a62f8b3cb91d721092af13530a3f72a462 +Subproject commit 46445ad50f184d2640dd205361e0446e9121ba5f From 516c977c76ba4cd86a7147aab7416a33d76f870f Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Mon, 20 Dec 2010 07:19:04 -0800 Subject: [PATCH 147/448] camerabin: fix for latest GTK+ API changes --- tests/examples/camerabin/gst-camera.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/tests/examples/camerabin/gst-camera.c b/tests/examples/camerabin/gst-camera.c index c837ba520e..e439bb88b6 100644 --- a/tests/examples/camerabin/gst-camera.c +++ b/tests/examples/camerabin/gst-camera.c @@ -276,7 +276,11 @@ my_bus_sync_callback (GstBus * bus, GstMessage * message, gpointer data) /* FIXME: make sure to get XID in main thread */ gst_x_overlay_set_window_handle (GST_X_OVERLAY (message->src), +#if GTK_CHECK_VERSION (2, 91, 6) + GDK_WINDOW_XID (gtk_widget_get_window (ui_drawing)); +#else GDK_WINDOW_XWINDOW (gtk_widget_get_window (ui_drawing))); +#endif gst_message_unref (message); return GST_BUS_DROP; @@ -1157,6 +1161,10 @@ create_menu_items_from_structure (GstStructure * structure) for (j = 0; j < num_framerates; j++) { GstCaps *video_caps; +#if GTK_CHECK_VERSION (2, 91, 6) + GtkListStore *sotre; + GtkTreeIter iter; +#endif if (framerate_list) { const GValue *item = gst_value_list_get_value (framerate_list, j); @@ -1167,7 +1175,13 @@ create_menu_items_from_structure (GstStructure * structure) g_string_append_printf (item_str, " (%" GST_FOURCC_FORMAT ")", GST_FOURCC_ARGS (fourcc)); g_string_append_printf (item_str, ", %dx%d at %d/%d", w, h, n, d); +#if GTK_CHECK_VERSION (2, 91, 6) + store = GTK_LIST_STORE (gtk_combo_box_get_model (ui_cbbox_resolution)); + gtk_list_store_append (store, &iter); + gtk_list_store_set (store, &iter, 0, item_str->str, -1); +#else gtk_combo_box_append_text (ui_cbbox_resolution, item_str->str); +#endif video_caps = gst_caps_new_simple (structure_name, "format", GST_TYPE_FOURCC, From 3c2d4a4b0ad483b3610e520b4e262464a595c7d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Tue, 21 Dec 2010 17:03:43 +0100 Subject: [PATCH 148/448] asfmux: Fix buffer leak in the unit test --- tests/check/elements/asfmux.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tests/check/elements/asfmux.c b/tests/check/elements/asfmux.c index 6c3dab5112..abc641f97c 100644 --- a/tests/check/elements/asfmux.c +++ b/tests/check/elements/asfmux.c @@ -156,6 +156,7 @@ check_asfmux_pad (GstStaticPadTemplate * srctemplate, GstBuffer *inbuffer; GstCaps *caps; GstFlowReturn ret; + GList *l; asfmux = setup_asfmux (srctemplate, sinkname); fail_unless (gst_element_set_state (asfmux, @@ -172,6 +173,8 @@ check_asfmux_pad (GstStaticPadTemplate * srctemplate, fail_unless (ret == GST_FLOW_OK, "Pad push returned: %d", ret); cleanup_asfmux (asfmux, sinkname); + for (l = buffers; l; l = l->next) + gst_buffer_unref (l->data); g_list_free (buffers); buffers = NULL; } From f0ebcba6c4ce8a6a04a3b041abbd34610c0dc8e7 Mon Sep 17 00:00:00 2001 From: benjamin gaignard Date: Mon, 20 Dec 2010 15:33:28 +0100 Subject: [PATCH 149/448] autoconvert: Avoid some leaks in autoconvert unref sink and src pad after gst_pad_by_direction calls unref element if gst_auto_convert_activate_element failed. See bug #637553. --- gst/autoconvert/gstautoconvert.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/gst/autoconvert/gstautoconvert.c b/gst/autoconvert/gstautoconvert.c index ebe297c112..97bd8b445e 100644 --- a/gst/autoconvert/gstautoconvert.c +++ b/gst/autoconvert/gstautoconvert.c @@ -576,6 +576,7 @@ gst_auto_convert_add_element (GstAutoConvert * autoconvert, if (!sinkpad) { GST_ERROR_OBJECT (autoconvert, "Could not find sink in %s", GST_OBJECT_NAME (element)); + gst_object_unref (srcpad); goto error; } @@ -652,6 +653,9 @@ gst_auto_convert_add_element (GstAutoConvert * autoconvert, /* Increment the reference count we will return to the caller */ gst_object_ref (element); + /* unref sink and src pad */ + gst_object_unref (srcpad); + gst_object_unref (sinkpad); return element; error: @@ -879,6 +883,8 @@ gst_auto_convert_sink_setcaps (GstPad * pad, GstCaps * caps) /* And make it the current child */ if (gst_auto_convert_activate_element (autoconvert, element, caps)) break; + else + gst_object_unref (element); } get_out: From 825052ba3d0799090ba3bb51a444141896491687 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Tue, 21 Dec 2010 18:01:28 +0100 Subject: [PATCH 150/448] autoconvert: Fix some more leaks and reorganize unref code --- gst/autoconvert/gstautoconvert.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/gst/autoconvert/gstautoconvert.c b/gst/autoconvert/gstautoconvert.c index 97bd8b445e..0cf7e08745 100644 --- a/gst/autoconvert/gstautoconvert.c +++ b/gst/autoconvert/gstautoconvert.c @@ -547,8 +547,8 @@ gst_auto_convert_add_element (GstAutoConvert * autoconvert, GstElement *element = NULL; GstPad *internal_sinkpad = NULL; GstPad *internal_srcpad = NULL; - GstPad *sinkpad; - GstPad *srcpad; + GstPad *sinkpad = NULL; + GstPad *srcpad = NULL; GstPadLinkReturn padlinkret; GST_DEBUG_OBJECT (autoconvert, "Adding element %s to the autoconvert bin", @@ -576,7 +576,6 @@ gst_auto_convert_add_element (GstAutoConvert * autoconvert, if (!sinkpad) { GST_ERROR_OBJECT (autoconvert, "Could not find sink in %s", GST_OBJECT_NAME (element)); - gst_object_unref (srcpad); goto error; } @@ -588,6 +587,10 @@ gst_auto_convert_add_element (GstAutoConvert * autoconvert, if (!internal_sinkpad || !internal_srcpad) { GST_ERROR_OBJECT (autoconvert, "Could not create internal pads"); + if (internal_srcpad) + gst_object_unref (internal_srcpad); + if (internal_sinkpad) + gst_object_unref (internal_sinkpad); goto error; } @@ -661,6 +664,11 @@ gst_auto_convert_add_element (GstAutoConvert * autoconvert, error: gst_bin_remove (GST_BIN (autoconvert), element); + if (srcpad) + gst_object_unref (srcpad); + if (sinkpad) + gst_object_unref (sinkpad); + return NULL; } From bcb8eab616558daa6a95fceb84cdd19cc2df0169 Mon Sep 17 00:00:00 2001 From: Edward Hervey Date: Wed, 22 Dec 2010 18:13:04 +0100 Subject: [PATCH 151/448] id3mux: Set to GST_RANK_PRIMARY We want it to take precedence over any other id3 formatter. --- gst/id3tag/gstid3mux.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gst/id3tag/gstid3mux.c b/gst/id3tag/gstid3mux.c index 30995884cb..43ab1a08b4 100644 --- a/gst/id3tag/gstid3mux.c +++ b/gst/id3tag/gstid3mux.c @@ -214,7 +214,8 @@ plugin_init (GstPlugin * plugin) GST_DEBUG_CATEGORY_INIT (gst_id3_mux_debug, "id3mux", 0, "ID3 v1 and v2 tag muxer"); - if (!gst_element_register (plugin, "id3mux", GST_RANK_NONE, GST_TYPE_ID3_MUX)) + if (!gst_element_register (plugin, "id3mux", GST_RANK_PRIMARY, + GST_TYPE_ID3_MUX)) return FALSE; gst_tag_register_musicbrainz_tags (); From e29a1073b1bceb0c279c0a96c233d11d211f97ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Wed, 22 Dec 2010 21:44:47 +0000 Subject: [PATCH 152/448] mpeg4videoparse: ensure buffer metadata is writable before modifying it https://bugzilla.gnome.org/show_bug.cgi?id=637824 --- gst/mpeg4videoparse/mpeg4videoparse.c | 1 + 1 file changed, 1 insertion(+) diff --git a/gst/mpeg4videoparse/mpeg4videoparse.c b/gst/mpeg4videoparse/mpeg4videoparse.c index 4d3f14d831..d23f2cc1fd 100644 --- a/gst/mpeg4videoparse/mpeg4videoparse.c +++ b/gst/mpeg4videoparse/mpeg4videoparse.c @@ -502,6 +502,7 @@ gst_mpeg4vparse_push (GstMpeg4VParse * parse, gsize size) GstBuffer *out_buf; out_buf = gst_adapter_take_buffer (parse->adapter, parse->offset); + out_buf = gst_buffer_make_metadata_writable (out_buf); GST_BUFFER_TIMESTAMP (out_buf) = parse->timestamp; if (G_LIKELY (out_buf)) { From 17d5914c59adea0bf1385d591eb3b07c4326c2f4 Mon Sep 17 00:00:00 2001 From: Stefan Kost Date: Thu, 9 Dec 2010 12:21:16 +0200 Subject: [PATCH 153/448] basecamerasrc: comment cleanups --- gst/camerabin2/gstbasecamerasrc.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/gst/camerabin2/gstbasecamerasrc.c b/gst/camerabin2/gstbasecamerasrc.c index fac9c43dee..24e37ebf8c 100644 --- a/gst/camerabin2/gstbasecamerasrc.c +++ b/gst/camerabin2/gstbasecamerasrc.c @@ -68,7 +68,7 @@ GST_STATIC_PAD_TEMPLATE (GST_BASE_CAMERA_SRC_VIDEO_PAD_NAME, GST_PAD_ALWAYS, GST_STATIC_CAPS_ANY); -/* note: we could provide a vmethod for derived class to overload to provide +/* NOTE: we could provide a vmethod for derived class to overload to provide * it's own implementation of interface.. but in all cases I can think of at * moment, either the camerasrc itself, or some element within the bin, will * be implementing the interface.. @@ -301,10 +301,6 @@ gst_base_camera_src_finish_capture (GstBaseCameraSrc * self) g_object_notify (G_OBJECT (self), "ready-for-capture"); } - -/** - * - */ static void gst_base_camera_src_dispose (GObject * object) { From 4b23fe6872ab59055f61193eeadd448dadce001c Mon Sep 17 00:00:00 2001 From: Stefan Kost Date: Thu, 9 Dec 2010 12:22:26 +0200 Subject: [PATCH 154/448] basecamerasrc: use the enum type for mode --- gst/camerabin2/gstbasecamerasrc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst/camerabin2/gstbasecamerasrc.h b/gst/camerabin2/gstbasecamerasrc.h index c40b1b38e4..134cdff524 100644 --- a/gst/camerabin2/gstbasecamerasrc.h +++ b/gst/camerabin2/gstbasecamerasrc.h @@ -59,7 +59,7 @@ struct _GstBaseCameraSrc { GstBin parent; - gint mode; + GstCameraBinMode mode; gboolean capturing; GMutex *capturing_mutex; From ba2368d0bca85363cb66631642b1b5b5cf7cbf44 Mon Sep 17 00:00:00 2001 From: Stefan Kost Date: Thu, 9 Dec 2010 12:23:01 +0200 Subject: [PATCH 155/448] basecamerasrc: write more details on the api docs --- gst/camerabin2/gstbasecamerasrc.c | 28 +++++++++++++++++++++++++--- gst/camerabin2/gstbasecamerasrc.h | 7 ++----- 2 files changed, 27 insertions(+), 8 deletions(-) diff --git a/gst/camerabin2/gstbasecamerasrc.c b/gst/camerabin2/gstbasecamerasrc.c index 24e37ebf8c..07487d8f5c 100644 --- a/gst/camerabin2/gstbasecamerasrc.c +++ b/gst/camerabin2/gstbasecamerasrc.c @@ -23,8 +23,30 @@ /** * SECTION:element-basecamerasrc * - * Base class for the camera src bin used by camerabin. Indented to be - * subclassed when plugging in more sophisticated cameras. + * Base class for the camera source bin used by camerabin for capture. + * Sophisticated camera hardware can derive from this baseclass and map the + * features to this interface. + * + * The design mandates that the subclasses implement the following features and + * behaviour: + * + * + * 3 pads: viewfinder, image capture, video capture + * + * + * + * + * + * During construct_pipeline() vmethod a subclass can add several elements into + * the bin and expose 3 srcs pads as ghostpads implementing the 3 pad templates. + * + * It is also possible to add regular pads from the subclass and implement the + * dataflow methods on these pads. This way all functionality can be implemneted + * directly in the subclass without extra elements. + * + * The src will receive the capture mode from #GstCameraBin2 on the + * #GstBaseCameraSrc:mode property. Possible capture modes are defined in + * #GstCameraBinMode. */ @@ -130,7 +152,7 @@ gst_base_camera_src_get_color_balance (GstBaseCameraSrc * self) * @self: the camerasrc bin * @mode: the mode * - * XXX + * Set the chosen #GstCameraBinMode capture mode. */ gboolean gst_base_camera_src_set_mode (GstBaseCameraSrc * self, GstCameraBinMode mode) diff --git a/gst/camerabin2/gstbasecamerasrc.h b/gst/camerabin2/gstbasecamerasrc.h index 134cdff524..dd74ba81a8 100644 --- a/gst/camerabin2/gstbasecamerasrc.h +++ b/gst/camerabin2/gstbasecamerasrc.h @@ -92,11 +92,8 @@ struct _GstBaseCameraSrc /** * GstBaseCameraSrcClass: - * @construct_pipeline: construct pipeline must be implemented by derived - * class, and return by reference vfsrc, imgsrc, and vidsrc pads of the - * contained pipeline, which will be ghosted to the src pads of the - * camerasrc bin (and optionally the preview src pads?) - * @setup_pipeline: + * @construct_pipeline: construct pipeline must be implemented by derived class + * @setup_pipeline: configure pipeline for the chosen settings * @set_zoom: set the zoom * @set_mode: set the mode */ From 80ff9300121b94787e80f19532abe0564f947025 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Thu, 9 Dec 2010 14:13:13 -0300 Subject: [PATCH 156/448] basecamerasrc: Make construct_pipeline optional Construct pipeline should be optional. Subclasses that don't have internal elements don't need it. --- gst/camerabin2/gstbasecamerasrc.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/gst/camerabin2/gstbasecamerasrc.c b/gst/camerabin2/gstbasecamerasrc.c index 07487d8f5c..f0d4e009c6 100644 --- a/gst/camerabin2/gstbasecamerasrc.c +++ b/gst/camerabin2/gstbasecamerasrc.c @@ -390,11 +390,11 @@ construct_pipeline (GstBaseCameraSrc * self) { GstBaseCameraSrcClass *bclass = GST_BASE_CAMERA_SRC_GET_CLASS (self); - g_return_val_if_fail (bclass->construct_pipeline, FALSE); - - if (!bclass->construct_pipeline (self)) { - GST_ERROR_OBJECT (self, "pipeline construction failed"); - return FALSE; + if (bclass->construct_pipeline) { + if (!bclass->construct_pipeline (self)) { + GST_ERROR_OBJECT (self, "pipeline construction failed"); + return FALSE; + } } return TRUE; From 7c47fc497f4191815dba1937619cf36d2c9c68ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Dieb=20Martins?= Date: Fri, 10 Dec 2010 12:08:48 -0300 Subject: [PATCH 157/448] camerabin2: implement viewfinderbin::video-sink property to override default video output --- gst/camerabin2/gstcamerabin2.c | 14 ++++-- gst/camerabin2/gstcamerabin2.h | 2 + gst/camerabin2/gstviewfinderbin.c | 84 +++++++++++++++++++++++++++++-- gst/camerabin2/gstviewfinderbin.h | 2 + tests/check/elements/camerabin2.c | 7 +++ 5 files changed, 100 insertions(+), 9 deletions(-) diff --git a/gst/camerabin2/gstcamerabin2.c b/gst/camerabin2/gstcamerabin2.c index 0a9c0cd345..94b642e0d3 100644 --- a/gst/camerabin2/gstcamerabin2.c +++ b/gst/camerabin2/gstcamerabin2.c @@ -192,6 +192,8 @@ gst_camera_bin_dispose (GObject * object) { GstCameraBin *camerabin = GST_CAMERA_BIN_CAST (object); + gst_object_unref (camerabin->vf_bin); + g_free (camerabin->img_location); g_free (camerabin->vid_location); @@ -299,6 +301,9 @@ gst_camera_bin_init (GstCameraBin * camerabin) camerabin->mode = DEFAULT_MODE; camerabin->vid_location = g_strdup (DEFAULT_VID_LOCATION); camerabin->img_location = g_strdup (DEFAULT_IMG_LOCATION); + camerabin->vf_bin = gst_element_factory_make ("viewfinderbin", "vf-bin"); + + gst_bin_add (GST_BIN (camerabin), gst_object_ref (camerabin->vf_bin)); } /** @@ -319,7 +324,6 @@ gst_camera_bin_create_elements (GstCameraBin * camera) GstElement *src; GstElement *vid; GstElement *img; - GstElement *vf; GstElement *vid_queue; GstElement *img_queue; GstElement *vf_queue; @@ -333,7 +337,6 @@ gst_camera_bin_create_elements (GstCameraBin * camera) src = gst_element_factory_make ("v4l2camerasrc", "camerasrc"); vid = gst_element_factory_make ("videorecordingbin", "video-rec-bin"); img = gst_element_factory_make ("imagecapturebin", "image-cap-bin"); - vf = gst_element_factory_make ("viewfinderbin", "vf-bin"); camera->src = gst_object_ref (src); camera->vidbin = gst_object_ref (vid); @@ -347,13 +350,14 @@ gst_camera_bin_create_elements (GstCameraBin * camera) img_capsfilter = gst_element_factory_make ("capsfilter", "image-capsfilter"); vf_capsfilter = gst_element_factory_make ("capsfilter", "vf-capsfilter"); - gst_bin_add_many (GST_BIN_CAST (camera), src, vid, img, vf, vid_queue, - img_queue, vf_queue, vid_capsfilter, img_capsfilter, vf_capsfilter, NULL); + gst_bin_add_many (GST_BIN_CAST (camera), src, vid, img, + vid_queue, img_queue, vf_queue, vid_capsfilter, img_capsfilter, + vf_capsfilter, NULL); /* Linking can be optimized TODO */ gst_element_link_many (vid_queue, vid_capsfilter, vid, NULL); gst_element_link_many (img_queue, img_capsfilter, img, NULL); - gst_element_link_many (vf_queue, vf_capsfilter, vf, NULL); + gst_element_link_many (vf_queue, vf_capsfilter, camera->vf_bin, NULL); gst_element_link_pads (src, "vfsrc", vf_queue, "sink"); gst_element_link_pads (src, "imgsrc", img_queue, "sink"); gst_element_link_pads (src, "vidsrc", vid_queue, "sink"); diff --git a/gst/camerabin2/gstcamerabin2.h b/gst/camerabin2/gstcamerabin2.h index a4c7bb4c9d..48a0ac31c6 100644 --- a/gst/camerabin2/gstcamerabin2.h +++ b/gst/camerabin2/gstcamerabin2.h @@ -44,6 +44,8 @@ struct _GstCameraBin GstElement *vid_queue; GstElement *vid_capsfilter; + GstElement *vf_bin; + GstElement *imgbin; gint vid_index; diff --git a/gst/camerabin2/gstviewfinderbin.c b/gst/camerabin2/gstviewfinderbin.c index 1910bbbd83..2f29b47411 100644 --- a/gst/camerabin2/gstviewfinderbin.c +++ b/gst/camerabin2/gstviewfinderbin.c @@ -44,7 +44,8 @@ GST_DEBUG_CATEGORY_STATIC (gst_viewfinder_bin_debug); enum { - PROP_0 + PROP_0, + PROP_VIDEO_SINK, }; /* pad templates */ @@ -59,6 +60,15 @@ static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", GST_BOILERPLATE (GstViewfinderBin, gst_viewfinder_bin, GstBin, GST_TYPE_BIN); +static void gst_viewfinder_bin_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * spec); +static void gst_viewfinder_bin_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * spec); + +static void +gst_viewfinder_bin_set_video_sink (GstViewfinderBin * vfbin, GstElement * sink); + + /* Element class functions */ static GstStateChangeReturn gst_viewfinder_bin_change_state (GstElement * element, GstStateChange trans); @@ -79,12 +89,22 @@ gst_viewfinder_bin_base_init (gpointer g_class) static void gst_viewfinder_bin_class_init (GstViewfinderBinClass * klass) { + GObjectClass *gobject_klass; GstElementClass *element_class; + gobject_klass = (GObjectClass *) klass; element_class = GST_ELEMENT_CLASS (klass); element_class->change_state = GST_DEBUG_FUNCPTR (gst_viewfinder_bin_change_state); + + gobject_klass->set_property = gst_viewfinder_bin_set_property; + gobject_klass->get_property = gst_viewfinder_bin_get_property; + + g_object_class_install_property (gobject_klass, PROP_VIDEO_SINK, + g_param_spec_object ("video-sink", "Video Sink", + "the video output element to use (NULL = default)", + GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); } static void @@ -95,6 +115,8 @@ gst_viewfinder_bin_init (GstViewfinderBin * viewfinderbin, gst_static_pad_template_get (&sink_template)); gst_element_add_pad (GST_ELEMENT_CAST (viewfinderbin), viewfinderbin->ghostpad); + + viewfinderbin->video_sink = NULL; } static gboolean @@ -120,9 +142,13 @@ gst_viewfinder_bin_create_elements (GstViewfinderBin * vfbin) if (!videoscale) goto error; - sink = gst_element_factory_make ("autovideosink", "vfbin-sink"); - if (!sink) - goto error; + if (vfbin->video_sink) { + sink = vfbin->video_sink; + } else { + sink = gst_element_factory_make ("autovideosink", "vfbin-sink"); + if (!sink) + goto error; + } GST_DEBUG_OBJECT (vfbin, "Internal elements created, proceding to linking"); @@ -186,6 +212,56 @@ gst_viewfinder_bin_change_state (GstElement * element, GstStateChange trans) return ret; } +static void +gst_viewfinder_bin_set_video_sink (GstViewfinderBin * vfbin, GstElement * sink) +{ + GST_INFO_OBJECT (vfbin, "Setting video sink to %" GST_PTR_FORMAT, sink); + + if (vfbin->video_sink != sink) { + if (sink) + gst_object_ref_sink (sink); + + if (vfbin->video_sink) + gst_object_unref (vfbin->video_sink); + + vfbin->video_sink = sink; + } + + GST_LOG_OBJECT (vfbin, "Video sink is now %" GST_PTR_FORMAT, sink); +} + +static void +gst_viewfinder_bin_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstViewfinderBin *vfbin = GST_VIEWFINDER_BIN_CAST (object); + + switch (prop_id) { + case PROP_VIDEO_SINK: + gst_viewfinder_bin_set_video_sink (vfbin, g_value_get_object (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_viewfinder_bin_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstViewfinderBin *vfbin = GST_VIEWFINDER_BIN_CAST (object); + + switch (prop_id) { + case PROP_VIDEO_SINK: + g_value_take_object (value, vfbin->video_sink); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + gboolean gst_viewfinder_bin_plugin_init (GstPlugin * plugin) { diff --git a/gst/camerabin2/gstviewfinderbin.h b/gst/camerabin2/gstviewfinderbin.h index da5e0efcb8..af6944d8da 100644 --- a/gst/camerabin2/gstviewfinderbin.h +++ b/gst/camerabin2/gstviewfinderbin.h @@ -39,6 +39,8 @@ struct _GstViewfinderBin GstPad *ghostpad; + GstElement *video_sink; + gboolean elements_created; }; diff --git a/tests/check/elements/camerabin2.c b/tests/check/elements/camerabin2.c index 4c451610cc..e30d0253fc 100644 --- a/tests/check/elements/camerabin2.c +++ b/tests/check/elements/camerabin2.c @@ -117,12 +117,19 @@ static void setup (void) { GstBus *bus; + GstElement *vfbin; + GstElement *fakevideosink; GST_INFO ("init"); main_loop = g_main_loop_new (NULL, TRUE); camera = gst_check_setup_element ("camerabin2"); + fakevideosink = gst_check_setup_element ("fakesink"); + + vfbin = gst_bin_get_by_name (GST_BIN (camera), "vf-bin"); + g_object_set (G_OBJECT (vfbin), "video-sink", fakevideosink, NULL); + gst_object_unref (vfbin); bus = gst_pipeline_get_bus (GST_PIPELINE (camera)); gst_bus_add_watch (bus, (GstBusFunc) capture_bus_cb, main_loop); From e5d388698a496549963a8fed8bf7d4b75f4b4dec Mon Sep 17 00:00:00 2001 From: Teemu Katajisto Date: Fri, 10 Dec 2010 17:45:40 +0200 Subject: [PATCH 158/448] camerabin2: remove abreviations from imagecapturebin --- gst/camerabin2/gstimagecapturebin.c | 70 ++++++++++++++--------------- 1 file changed, 35 insertions(+), 35 deletions(-) diff --git a/gst/camerabin2/gstimagecapturebin.c b/gst/camerabin2/gstimagecapturebin.c index 8ee540f49f..0ff4ab7d18 100644 --- a/gst/camerabin2/gstimagecapturebin.c +++ b/gst/camerabin2/gstimagecapturebin.c @@ -68,14 +68,14 @@ static void gst_image_capture_bin_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { - GstImageCaptureBin *imgbin = GST_IMAGE_CAPTURE_BIN_CAST (object); + GstImageCaptureBin *imagebin = GST_IMAGE_CAPTURE_BIN_CAST (object); switch (prop_id) { case PROP_LOCATION: - g_free (imgbin->location); - imgbin->location = g_value_dup_string (value); - if (imgbin->sink) { - g_object_set (imgbin, "location", imgbin->location, NULL); + g_free (imagebin->location); + imagebin->location = g_value_dup_string (value); + if (imagebin->sink) { + g_object_set (imagebin, "location", imagebin->location, NULL); } break; default: @@ -88,11 +88,11 @@ static void gst_image_capture_bin_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { - GstImageCaptureBin *imgbin = GST_IMAGE_CAPTURE_BIN_CAST (object); + GstImageCaptureBin *imagebin = GST_IMAGE_CAPTURE_BIN_CAST (object); switch (prop_id) { case PROP_LOCATION: - g_value_set_string (value, imgbin->location); + g_value_set_string (value, imagebin->location); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -147,66 +147,66 @@ gst_image_capture_bin_class_init (GstImageCaptureBinClass * klass) } static void -gst_image_capture_bin_init (GstImageCaptureBin * image_capturebin, - GstImageCaptureBinClass * image_capturebin_class) +gst_image_capture_bin_init (GstImageCaptureBin * imagebin, + GstImageCaptureBinClass * imagebin_class) { GstPadTemplate *tmpl; tmpl = gst_static_pad_template_get (&sink_template); - image_capturebin->ghostpad = + imagebin->ghostpad = gst_ghost_pad_new_no_target_from_template ("sink", tmpl); gst_object_unref (tmpl); + gst_element_add_pad (GST_ELEMENT_CAST (imagebin), imagebin->ghostpad); - gst_element_add_pad (GST_ELEMENT_CAST (image_capturebin), - image_capturebin->ghostpad); - - image_capturebin->location = g_strdup (DEFAULT_LOCATION); + imagebin->location = g_strdup (DEFAULT_LOCATION); } static gboolean -gst_image_capture_bin_create_elements (GstImageCaptureBin * icbin) +gst_image_capture_bin_create_elements (GstImageCaptureBin * imagebin) { - GstElement *csp; - GstElement *enc; - GstElement *mux; + GstElement *colorspace; + GstElement *encoder; + GstElement *muxer; GstElement *sink; GstPad *pad = NULL; - if (icbin->elements_created) + if (imagebin->elements_created) return TRUE; /* create elements */ - csp = gst_element_factory_make ("ffmpegcolorspace", "icbin-csp"); - if (!csp) + colorspace = + gst_element_factory_make ("ffmpegcolorspace", "imagebin-colorspace"); + if (!colorspace) goto error; - enc = gst_element_factory_make ("jpegenc", "icbin-enc"); - if (!enc) + encoder = gst_element_factory_make ("jpegenc", "imagebin-encoder"); + if (!encoder) goto error; - mux = gst_element_factory_make ("jifmux", "icbin-mux"); - if (!mux) + muxer = gst_element_factory_make ("jifmux", "imagebin-muxer"); + if (!muxer) goto error; - sink = gst_element_factory_make ("multifilesink", "icbin-sink"); + sink = gst_element_factory_make ("multifilesink", "imagebin-sink"); if (!sink) goto error; - icbin->sink = sink; - g_object_set (sink, "location", icbin->location, "async", FALSE, NULL); + imagebin->sink = sink; + g_object_set (sink, "location", imagebin->location, "async", FALSE, NULL); /* add and link */ - gst_bin_add_many (GST_BIN_CAST (icbin), csp, enc, mux, sink, NULL); - if (!gst_element_link_many (csp, enc, mux, sink, NULL)) + gst_bin_add_many (GST_BIN_CAST (imagebin), colorspace, encoder, muxer, sink, + NULL); + if (!gst_element_link_many (colorspace, encoder, muxer, sink, NULL)) goto error; /* add ghostpad */ - pad = gst_element_get_static_pad (csp, "sink"); - if (!gst_ghost_pad_set_target (GST_GHOST_PAD (icbin->ghostpad), pad)) + pad = gst_element_get_static_pad (colorspace, "sink"); + if (!gst_ghost_pad_set_target (GST_GHOST_PAD (imagebin->ghostpad), pad)) goto error; gst_object_unref (pad); - icbin->elements_created = TRUE; + imagebin->elements_created = TRUE; return TRUE; error: @@ -219,11 +219,11 @@ static GstStateChangeReturn gst_image_capture_bin_change_state (GstElement * element, GstStateChange trans) { GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; - GstImageCaptureBin *icbin = GST_IMAGE_CAPTURE_BIN_CAST (element); + GstImageCaptureBin *imagebin = GST_IMAGE_CAPTURE_BIN_CAST (element); switch (trans) { case GST_STATE_CHANGE_NULL_TO_READY: - if (!gst_image_capture_bin_create_elements (icbin)) { + if (!gst_image_capture_bin_create_elements (imagebin)) { return GST_STATE_CHANGE_FAILURE; } break; From 87e0cbff38395e8da54a320830e1194c70253838 Mon Sep 17 00:00:00 2001 From: Teemu Katajisto Date: Mon, 13 Dec 2010 12:08:22 +0200 Subject: [PATCH 159/448] camerabin2: add imagecapturebin::image-encoder property --- gst/camerabin2/gstimagecapturebin.c | 78 +++++++++++++++++++------- gst/camerabin2/gstimagecapturebin.h | 3 + tests/check/elements/imagecapturebin.c | 56 +++++++++++++++++- 3 files changed, 116 insertions(+), 21 deletions(-) diff --git a/gst/camerabin2/gstimagecapturebin.c b/gst/camerabin2/gstimagecapturebin.c index 0ff4ab7d18..62e8272e68 100644 --- a/gst/camerabin2/gstimagecapturebin.c +++ b/gst/camerabin2/gstimagecapturebin.c @@ -35,6 +35,7 @@ #endif #include "gstimagecapturebin.h" +#include "camerabingeneral.h" /* prototypes */ @@ -42,10 +43,15 @@ enum { PROP_0, - PROP_LOCATION + PROP_LOCATION, + PROP_ENCODER }; #define DEFAULT_LOCATION "img_%d" +#define DEFAULT_COLORSPACE "ffmpegcolorspace" +#define DEFAULT_ENCODER "jpegenc" +#define DEFAULT_MUXER "jifmux" +#define DEFAULT_SINK "multifilesink" /* pad templates */ @@ -64,6 +70,22 @@ GST_BOILERPLATE (GstImageCaptureBin, gst_image_capture_bin, GstBin, static GstStateChangeReturn gst_image_capture_bin_change_state (GstElement * element, GstStateChange trans); +static void +gst_image_capture_bin_set_encoder (GstImageCaptureBin * imagebin, + GstElement * encoder) +{ + GST_DEBUG_OBJECT (GST_OBJECT (imagebin), + "Setting image encoder %" GST_PTR_FORMAT, encoder); + + if (imagebin->user_encoder) + g_object_unref (imagebin->user_encoder); + + if (encoder) + g_object_ref (encoder); + + imagebin->user_encoder = encoder; +} + static void gst_image_capture_bin_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) @@ -78,6 +100,9 @@ gst_image_capture_bin_set_property (GObject * object, guint prop_id, g_object_set (imagebin, "location", imagebin->location, NULL); } break; + case PROP_ENCODER: + gst_image_capture_bin_set_encoder (imagebin, g_value_get_object (value)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -94,6 +119,9 @@ gst_image_capture_bin_get_property (GObject * object, guint prop_id, case PROP_LOCATION: g_value_set_string (value, imagebin->location); break; + case PROP_ENCODER: + g_value_set_object (value, imagebin->encoder); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -144,6 +172,11 @@ gst_image_capture_bin_class_init (GstImageCaptureBinClass * klass) "Location to save the captured files. A %%d can be used as a " "placeholder for a capture count", DEFAULT_LOCATION, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_ENCODER, + g_param_spec_object ("image-encoder", "Image encoder", + "Image encoder GStreamer element (default is jpegenc)", + GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); } static void @@ -159,15 +192,14 @@ gst_image_capture_bin_init (GstImageCaptureBin * imagebin, gst_element_add_pad (GST_ELEMENT_CAST (imagebin), imagebin->ghostpad); imagebin->location = g_strdup (DEFAULT_LOCATION); + imagebin->encoder = NULL; + imagebin->user_encoder = NULL; } static gboolean gst_image_capture_bin_create_elements (GstImageCaptureBin * imagebin) { GstElement *colorspace; - GstElement *encoder; - GstElement *muxer; - GstElement *sink; GstPad *pad = NULL; if (imagebin->elements_created) @@ -175,30 +207,36 @@ gst_image_capture_bin_create_elements (GstImageCaptureBin * imagebin) /* create elements */ colorspace = - gst_element_factory_make ("ffmpegcolorspace", "imagebin-colorspace"); + gst_camerabin_create_and_add_element (GST_BIN (imagebin), + DEFAULT_COLORSPACE); if (!colorspace) goto error; - encoder = gst_element_factory_make ("jpegenc", "imagebin-encoder"); - if (!encoder) + if (imagebin->user_encoder) { + imagebin->encoder = imagebin->user_encoder; + if (!gst_camerabin_add_element (GST_BIN (imagebin), imagebin->encoder)) { + goto error; + } + } else { + imagebin->encoder = + gst_camerabin_create_and_add_element (GST_BIN (imagebin), + DEFAULT_ENCODER); + if (!imagebin->encoder) + goto error; + } + + imagebin->muxer = + gst_camerabin_create_and_add_element (GST_BIN (imagebin), DEFAULT_MUXER); + if (!imagebin->muxer) goto error; - muxer = gst_element_factory_make ("jifmux", "imagebin-muxer"); - if (!muxer) + imagebin->sink = + gst_camerabin_create_and_add_element (GST_BIN (imagebin), DEFAULT_SINK); + if (!imagebin->sink) goto error; - sink = gst_element_factory_make ("multifilesink", "imagebin-sink"); - if (!sink) - goto error; - - imagebin->sink = sink; - g_object_set (sink, "location", imagebin->location, "async", FALSE, NULL); - - /* add and link */ - gst_bin_add_many (GST_BIN_CAST (imagebin), colorspace, encoder, muxer, sink, + g_object_set (imagebin->sink, "location", imagebin->location, "async", FALSE, NULL); - if (!gst_element_link_many (colorspace, encoder, muxer, sink, NULL)) - goto error; /* add ghostpad */ pad = gst_element_get_static_pad (colorspace, "sink"); diff --git a/gst/camerabin2/gstimagecapturebin.h b/gst/camerabin2/gstimagecapturebin.h index 912dec0992..63402dbf2d 100644 --- a/gst/camerabin2/gstimagecapturebin.h +++ b/gst/camerabin2/gstimagecapturebin.h @@ -39,9 +39,12 @@ struct _GstImageCaptureBin GstPad *ghostpad; GstElement *sink; + GstElement *muxer; /* props */ gchar *location; + GstElement *encoder; + GstElement *user_encoder; gboolean elements_created; }; diff --git a/tests/check/elements/imagecapturebin.c b/tests/check/elements/imagecapturebin.c index 58331c1612..22197916eb 100644 --- a/tests/check/elements/imagecapturebin.c +++ b/tests/check/elements/imagecapturebin.c @@ -66,7 +66,7 @@ static gchar * make_test_file_name (void) { return g_strdup_printf ("%s" G_DIR_SEPARATOR_S - "imagecapturbintest_%%d.cap", g_get_tmp_dir ()); + "imagecapturebintest_%%d.cap", g_get_tmp_dir ()); } GST_START_TEST (test_simple_capture) @@ -119,6 +119,59 @@ GST_START_TEST (test_simple_capture) GST_END_TEST; +GST_START_TEST (test_setting_encoder) +{ + GstImageCaptureBinTestContext ctx; + GstBus *bus; + GstMessage *msg; + GstElement *encoder; + gchar *test_file_name; + gint i; + + gstimagecapturebin_init_test_context (&ctx, N_BUFFERS); + bus = gst_element_get_bus (ctx.pipe); + + test_file_name = make_test_file_name (); + g_object_set (ctx.icbin, "location", test_file_name, NULL); + + encoder = gst_element_factory_make ("jpegenc", NULL); + g_object_set (ctx.icbin, "image-encoder", encoder, NULL); + + fail_if (gst_element_set_state (ctx.pipe, GST_STATE_PLAYING) == + GST_STATE_CHANGE_FAILURE); + + msg = gst_bus_timed_pop_filtered (bus, GST_SECOND * 10, + GST_MESSAGE_EOS | GST_MESSAGE_ERROR); + fail_unless (msg != NULL); + fail_unless (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_EOS); + + /* check there are N_BUFFERS files */ + for (i = 0; i < N_BUFFERS; i++) { + gchar *filename; + FILE *f; + + filename = g_strdup_printf (test_file_name, i); + + fail_unless (g_file_test (filename, G_FILE_TEST_EXISTS)); + fail_unless (g_file_test (filename, G_FILE_TEST_IS_REGULAR)); + fail_if (g_file_test (filename, G_FILE_TEST_IS_SYMLINK)); + + /* check the file isn't empty */ + f = fopen (filename, "r"); + fseek (f, 0, SEEK_END); + fail_unless (ftell (f) > 0); + fclose (f); + + g_free (filename); + } + + gstimagecapturebin_unset_test_context (&ctx); + gst_object_unref (bus); + g_free (test_file_name); +} + +GST_END_TEST; + static Suite * imagecapturebin_suite (void) { @@ -127,6 +180,7 @@ imagecapturebin_suite (void) suite_add_tcase (s, tc_chain); tcase_add_test (tc_chain, test_simple_capture); + tcase_add_test (tc_chain, test_setting_encoder); return s; } From 89142163b1e1d727ce3c4cf9d23b696d26afbb80 Mon Sep 17 00:00:00 2001 From: Teemu Katajisto Date: Mon, 13 Dec 2010 16:28:58 +0200 Subject: [PATCH 160/448] camerabin2: add imagecapturebin::image-muxer property --- gst/camerabin2/gstimagecapturebin.c | 46 ++++++++++++++++++--- gst/camerabin2/gstimagecapturebin.h | 3 +- tests/check/elements/imagecapturebin.c | 57 ++++++++++++++++++++++++++ 3 files changed, 100 insertions(+), 6 deletions(-) diff --git a/gst/camerabin2/gstimagecapturebin.c b/gst/camerabin2/gstimagecapturebin.c index 62e8272e68..9120d867db 100644 --- a/gst/camerabin2/gstimagecapturebin.c +++ b/gst/camerabin2/gstimagecapturebin.c @@ -44,7 +44,8 @@ enum { PROP_0, PROP_LOCATION, - PROP_ENCODER + PROP_ENCODER, + PROP_MUXER }; #define DEFAULT_LOCATION "img_%d" @@ -86,6 +87,22 @@ gst_image_capture_bin_set_encoder (GstImageCaptureBin * imagebin, imagebin->user_encoder = encoder; } +static void +gst_image_capture_bin_set_muxer (GstImageCaptureBin * imagebin, + GstElement * muxer) +{ + GST_DEBUG_OBJECT (GST_OBJECT (imagebin), + "Setting image muxer %" GST_PTR_FORMAT, muxer); + + if (imagebin->user_muxer) + g_object_unref (imagebin->user_muxer); + + if (muxer) + g_object_ref (muxer); + + imagebin->user_muxer = muxer; +} + static void gst_image_capture_bin_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) @@ -103,6 +120,9 @@ gst_image_capture_bin_set_property (GObject * object, guint prop_id, case PROP_ENCODER: gst_image_capture_bin_set_encoder (imagebin, g_value_get_object (value)); break; + case PROP_MUXER: + gst_image_capture_bin_set_muxer (imagebin, g_value_get_object (value)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -122,6 +142,9 @@ gst_image_capture_bin_get_property (GObject * object, guint prop_id, case PROP_ENCODER: g_value_set_object (value, imagebin->encoder); break; + case PROP_MUXER: + g_value_set_object (value, imagebin->muxer); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -177,6 +200,11 @@ gst_image_capture_bin_class_init (GstImageCaptureBinClass * klass) g_param_spec_object ("image-encoder", "Image encoder", "Image encoder GStreamer element (default is jpegenc)", GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_MUXER, + g_param_spec_object ("image-muxer", "Image muxer", + "Image muxer GStreamer element (default is jifmux)", + GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); } static void @@ -225,10 +253,18 @@ gst_image_capture_bin_create_elements (GstImageCaptureBin * imagebin) goto error; } - imagebin->muxer = - gst_camerabin_create_and_add_element (GST_BIN (imagebin), DEFAULT_MUXER); - if (!imagebin->muxer) - goto error; + if (imagebin->user_muxer) { + imagebin->muxer = imagebin->user_muxer; + if (!gst_camerabin_add_element (GST_BIN (imagebin), imagebin->muxer)) { + goto error; + } + } else { + imagebin->muxer = + gst_camerabin_create_and_add_element (GST_BIN (imagebin), + DEFAULT_MUXER); + if (!imagebin->muxer) + goto error; + } imagebin->sink = gst_camerabin_create_and_add_element (GST_BIN (imagebin), DEFAULT_SINK); diff --git a/gst/camerabin2/gstimagecapturebin.h b/gst/camerabin2/gstimagecapturebin.h index 63402dbf2d..98a28e9831 100644 --- a/gst/camerabin2/gstimagecapturebin.h +++ b/gst/camerabin2/gstimagecapturebin.h @@ -39,12 +39,13 @@ struct _GstImageCaptureBin GstPad *ghostpad; GstElement *sink; - GstElement *muxer; /* props */ gchar *location; GstElement *encoder; GstElement *user_encoder; + GstElement *muxer; + GstElement *user_muxer; gboolean elements_created; }; diff --git a/tests/check/elements/imagecapturebin.c b/tests/check/elements/imagecapturebin.c index 22197916eb..4afe9ce361 100644 --- a/tests/check/elements/imagecapturebin.c +++ b/tests/check/elements/imagecapturebin.c @@ -172,6 +172,62 @@ GST_START_TEST (test_setting_encoder) GST_END_TEST; +GST_START_TEST (test_setting_muxer) +{ + GstImageCaptureBinTestContext ctx; + GstBus *bus; + GstMessage *msg; + GstElement *encoder; + gchar *test_file_name; + gint i; + + gstimagecapturebin_init_test_context (&ctx, N_BUFFERS); + bus = gst_element_get_bus (ctx.pipe); + + test_file_name = make_test_file_name (); + g_object_set (ctx.icbin, "location", test_file_name, NULL); + + encoder = gst_element_factory_make ("pngenc", NULL); + g_object_set (ctx.icbin, "image-encoder", encoder, NULL); + + encoder = gst_element_factory_make ("identity", NULL); + g_object_set (ctx.icbin, "image-muxer", encoder, NULL); + + fail_if (gst_element_set_state (ctx.pipe, GST_STATE_PLAYING) == + GST_STATE_CHANGE_FAILURE); + + msg = gst_bus_timed_pop_filtered (bus, GST_SECOND * 10, + GST_MESSAGE_EOS | GST_MESSAGE_ERROR); + fail_unless (msg != NULL); + fail_unless (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_EOS); + + /* check there are N_BUFFERS files */ + for (i = 0; i < N_BUFFERS; i++) { + gchar *filename; + FILE *f; + + filename = g_strdup_printf (test_file_name, i); + + fail_unless (g_file_test (filename, G_FILE_TEST_EXISTS)); + fail_unless (g_file_test (filename, G_FILE_TEST_IS_REGULAR)); + fail_if (g_file_test (filename, G_FILE_TEST_IS_SYMLINK)); + + /* check the file isn't empty */ + f = fopen (filename, "r"); + fseek (f, 0, SEEK_END); + fail_unless (ftell (f) > 0); + fclose (f); + + g_free (filename); + } + + gstimagecapturebin_unset_test_context (&ctx); + gst_object_unref (bus); + g_free (test_file_name); +} + +GST_END_TEST; + static Suite * imagecapturebin_suite (void) { @@ -181,6 +237,7 @@ imagecapturebin_suite (void) suite_add_tcase (s, tc_chain); tcase_add_test (tc_chain, test_simple_capture); tcase_add_test (tc_chain, test_setting_encoder); + tcase_add_test (tc_chain, test_setting_muxer); return s; } From 014b8f97f8f621e245c4c5014fa80745ddf1b032 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Sun, 12 Dec 2010 19:33:24 -0300 Subject: [PATCH 161/448] viewfinderbin: Fixes to video-sink handling Handle video-sink more carefully, checking if it should be already added to the bin, and removing old ones when replacing. --- gst/camerabin2/gstcamerabin2.c | 3 +- gst/camerabin2/gstviewfinderbin.c | 104 +++++++++++++++++++----------- gst/camerabin2/gstviewfinderbin.h | 1 + tests/check/elements/camerabin2.c | 1 + 4 files changed, 71 insertions(+), 38 deletions(-) diff --git a/gst/camerabin2/gstcamerabin2.c b/gst/camerabin2/gstcamerabin2.c index 94b642e0d3..7036e19085 100644 --- a/gst/camerabin2/gstcamerabin2.c +++ b/gst/camerabin2/gstcamerabin2.c @@ -192,7 +192,8 @@ gst_camera_bin_dispose (GObject * object) { GstCameraBin *camerabin = GST_CAMERA_BIN_CAST (object); - gst_object_unref (camerabin->vf_bin); + if (camerabin->vf_bin) + gst_object_unref (camerabin->vf_bin); g_free (camerabin->img_location); g_free (camerabin->vid_location); diff --git a/gst/camerabin2/gstviewfinderbin.c b/gst/camerabin2/gstviewfinderbin.c index 2f29b47411..b10d1fab1c 100644 --- a/gst/camerabin2/gstviewfinderbin.c +++ b/gst/camerabin2/gstviewfinderbin.c @@ -115,8 +115,6 @@ gst_viewfinder_bin_init (GstViewfinderBin * viewfinderbin, gst_static_pad_template_get (&sink_template)); gst_element_add_pad (GST_ELEMENT_CAST (viewfinderbin), viewfinderbin->ghostpad); - - viewfinderbin->video_sink = NULL; } static gboolean @@ -124,47 +122,65 @@ gst_viewfinder_bin_create_elements (GstViewfinderBin * vfbin) { GstElement *csp = NULL; GstElement *videoscale = NULL; - GstElement *sink = NULL; GstPad *pad = NULL; gboolean added = FALSE; GST_DEBUG_OBJECT (vfbin, "Creating internal elements"); - if (vfbin->elements_created) - return TRUE; - - /* create elements */ - csp = gst_element_factory_make ("ffmpegcolorspace", "vfbin-csp"); - if (!csp) - goto error; - - videoscale = gst_element_factory_make ("videoscale", "vfbin-videoscale"); - if (!videoscale) - goto error; - - if (vfbin->video_sink) { - sink = vfbin->video_sink; - } else { - sink = gst_element_factory_make ("autovideosink", "vfbin-sink"); - if (!sink) + if (!vfbin->elements_created) { + /* create elements */ + csp = gst_element_factory_make ("ffmpegcolorspace", "vfbin-csp"); + if (!csp) goto error; + + videoscale = gst_element_factory_make ("videoscale", "vfbin-videoscale"); + if (!videoscale) + goto error; + + GST_DEBUG_OBJECT (vfbin, "Internal elements created, proceding to linking"); + + /* add and link */ + gst_bin_add_many (GST_BIN_CAST (vfbin), csp, videoscale, NULL); + added = TRUE; + if (!gst_element_link (csp, videoscale)) + goto error; + + /* add ghostpad */ + pad = gst_element_get_static_pad (csp, "sink"); + if (!gst_ghost_pad_set_target (GST_GHOST_PAD (vfbin->ghostpad), pad)) + goto error; + + vfbin->elements_created = TRUE; + GST_DEBUG_OBJECT (vfbin, "Elements succesfully created and linked"); } - GST_DEBUG_OBJECT (vfbin, "Internal elements created, proceding to linking"); + if (vfbin->video_sink) { + /* check if we need to replace the current one */ + if (vfbin->user_video_sink && vfbin->video_sink != vfbin->user_video_sink) { + gst_bin_remove (GST_BIN_CAST (vfbin), vfbin->video_sink); + gst_object_unref (vfbin->video_sink); + vfbin->video_sink = NULL; + } + } - /* add and link */ - gst_bin_add_many (GST_BIN_CAST (vfbin), csp, videoscale, sink, NULL); - added = TRUE; - if (!gst_element_link_many (csp, videoscale, sink, NULL)) - goto error; + if (!vfbin->video_sink) { + if (vfbin->user_video_sink) + vfbin->video_sink = gst_object_ref (vfbin->user_video_sink); + else + vfbin->video_sink = gst_element_factory_make ("autovideosink", + "vfbin-sink"); - /* add ghostpad */ - pad = gst_element_get_static_pad (csp, "sink"); - if (!gst_ghost_pad_set_target (GST_GHOST_PAD (vfbin->ghostpad), pad)) - goto error; + gst_bin_add (GST_BIN_CAST (vfbin), gst_object_ref (vfbin->video_sink)); + + if (!videoscale) + videoscale = gst_bin_get_by_name (GST_BIN_CAST (vfbin), + "vfbin-videoscale"); + + if (!gst_element_link_pads (videoscale, "src", vfbin->video_sink, "sink")) { + GST_WARNING_OBJECT (vfbin, "Failed to link the new sink"); + } + } - vfbin->elements_created = TRUE; - GST_DEBUG_OBJECT (vfbin, "Elements succesfully created and linked"); return TRUE; error: @@ -176,10 +192,8 @@ error: gst_object_unref (csp); if (videoscale) gst_object_unref (videoscale); - if (sink) - gst_object_unref (sink); } else { - gst_bin_remove_many (GST_BIN_CAST (vfbin), csp, videoscale, sink, NULL); + gst_bin_remove_many (GST_BIN_CAST (vfbin), csp, videoscale, NULL); } return FALSE; } @@ -221,10 +235,26 @@ gst_viewfinder_bin_set_video_sink (GstViewfinderBin * vfbin, GstElement * sink) if (sink) gst_object_ref_sink (sink); - if (vfbin->video_sink) + if (vfbin->video_sink) { + gst_bin_remove (GST_BIN_CAST (vfbin), vfbin->video_sink); gst_object_unref (vfbin->video_sink); + } vfbin->video_sink = sink; + if (sink) { + gst_bin_add (GST_BIN_CAST (vfbin), gst_object_ref (sink)); + if (vfbin->elements_created) { + GstElement *videoscale = gst_bin_get_by_name (GST_BIN_CAST (vfbin), + "vfbin-videoscale"); + + g_assert (videoscale != NULL); + + if (!gst_element_link_pads (videoscale, "src", sink, "sink")) { + GST_WARNING_OBJECT (vfbin, "Failed to link the new sink"); + } + } + } + } GST_LOG_OBJECT (vfbin, "Video sink is now %" GST_PTR_FORMAT, sink); @@ -254,7 +284,7 @@ gst_viewfinder_bin_get_property (GObject * object, guint prop_id, switch (prop_id) { case PROP_VIDEO_SINK: - g_value_take_object (value, vfbin->video_sink); + g_value_set_object (value, vfbin->video_sink); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); diff --git a/gst/camerabin2/gstviewfinderbin.h b/gst/camerabin2/gstviewfinderbin.h index af6944d8da..6369219577 100644 --- a/gst/camerabin2/gstviewfinderbin.h +++ b/gst/camerabin2/gstviewfinderbin.h @@ -40,6 +40,7 @@ struct _GstViewfinderBin GstPad *ghostpad; GstElement *video_sink; + GstElement *user_video_sink; gboolean elements_created; }; diff --git a/tests/check/elements/camerabin2.c b/tests/check/elements/camerabin2.c index e30d0253fc..4f46e0c78a 100644 --- a/tests/check/elements/camerabin2.c +++ b/tests/check/elements/camerabin2.c @@ -130,6 +130,7 @@ setup (void) vfbin = gst_bin_get_by_name (GST_BIN (camera), "vf-bin"); g_object_set (G_OBJECT (vfbin), "video-sink", fakevideosink, NULL); gst_object_unref (vfbin); + gst_object_unref (fakevideosink); bus = gst_pipeline_get_bus (GST_PIPELINE (camera)); gst_bus_add_watch (bus, (GstBusFunc) capture_bus_cb, main_loop); From f52d805166fc7043d9bd29e1a91656a59c9be6e2 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Sun, 12 Dec 2010 20:46:16 -0300 Subject: [PATCH 162/448] camerabin2: Put enums inside their classes .c Remove global list of properties' enums and put them inside their classes .c --- gst/camerabin2/gstbasecamerasrc.c | 22 +++++++++----- gst/camerabin2/gstcamerabin-enum.h | 46 ------------------------------ gst/camerabin2/gstv4l2camerasrc.c | 20 +++++++++---- 3 files changed, 29 insertions(+), 59 deletions(-) diff --git a/gst/camerabin2/gstbasecamerasrc.c b/gst/camerabin2/gstbasecamerasrc.c index f0d4e009c6..a5e7053e15 100644 --- a/gst/camerabin2/gstbasecamerasrc.c +++ b/gst/camerabin2/gstbasecamerasrc.c @@ -56,6 +56,14 @@ #include "gstbasecamerasrc.h" +enum +{ + PROP_0, + PROP_MODE, + PROP_ZOOM, + PROP_READY_FOR_CAPTURE +}; + enum { /* action signals */ @@ -346,11 +354,11 @@ gst_base_camera_src_set_property (GObject * object, GstBaseCameraSrc *self = GST_BASE_CAMERA_SRC (object); switch (prop_id) { - case ARG_MODE: + case PROP_MODE: gst_base_camera_src_set_mode (GST_BASE_CAMERA_SRC (self), g_value_get_enum (value)); break; - case ARG_ZOOM:{ + case PROP_ZOOM:{ g_atomic_int_set (&self->zoom, g_value_get_int (value)); /* does not set it if in NULL, the src is not created yet */ if (GST_STATE (self) != GST_STATE_NULL) @@ -370,13 +378,13 @@ gst_base_camera_src_get_property (GObject * object, GstBaseCameraSrc *self = GST_BASE_CAMERA_SRC (object); switch (prop_id) { - case ARG_MODE: + case PROP_MODE: g_value_set_enum (value, self->mode); break; - case ARG_READY_FOR_CAPTURE: + case PROP_READY_FOR_CAPTURE: g_value_set_boolean (value, !self->capturing); break; - case ARG_ZOOM: + case PROP_ZOOM: g_value_set_int (value, g_atomic_int_get (&self->zoom)); break; default: @@ -475,7 +483,7 @@ gst_base_camera_src_class_init (GstBaseCameraSrcClass * klass) gobject_class->get_property = gst_base_camera_src_get_property; // g_object_class_install_property .... - g_object_class_install_property (gobject_class, ARG_MODE, + g_object_class_install_property (gobject_class, PROP_MODE, g_param_spec_enum ("mode", "Mode", "The capture mode (still image capture or video recording)", GST_TYPE_CAMERABIN_MODE, MODE_IMAGE, @@ -492,7 +500,7 @@ gst_base_camera_src_class_init (GstBaseCameraSrcClass * klass) * function, please schedule a new thread to do it. If you're using glib's * mainloop you can use g_idle_add() for example. */ - g_object_class_install_property (gobject_class, ARG_READY_FOR_CAPTURE, + g_object_class_install_property (gobject_class, PROP_READY_FOR_CAPTURE, g_param_spec_boolean ("ready-for-capture", "Ready for capture", "Informs this element is ready for starting another capture", TRUE, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); diff --git a/gst/camerabin2/gstcamerabin-enum.h b/gst/camerabin2/gstcamerabin-enum.h index 299e05c7b0..590cb68826 100644 --- a/gst/camerabin2/gstcamerabin-enum.h +++ b/gst/camerabin2/gstcamerabin-enum.h @@ -25,52 +25,6 @@ G_BEGIN_DECLS -/* XXX find better place for property related enum/defaults */ -enum -{ - ARG_0, - ARG_FILENAME, - ARG_MODE, - ARG_READY_FOR_CAPTURE, - ARG_FLAGS, - ARG_MUTE, - ARG_ZOOM, - ARG_IMAGE_POST, - ARG_IMAGE_ENC, - ARG_VIDEO_POST, - ARG_VIDEO_ENC, - ARG_AUDIO_ENC, - ARG_VIDEO_MUX, - ARG_VF_SINK, - ARG_VIDEO_SRC, - ARG_AUDIO_SRC, - ARG_INPUT_CAPS, - ARG_FILTER_CAPS, - ARG_PREVIEW_CAPS, - ARG_WB_MODE, - ARG_COLOUR_TONE, - ARG_SCENE_MODE, - ARG_FLASH_MODE, - ARG_FOCUS_STATUS, - ARG_CAPABILITIES, - ARG_SHAKE_RISK, - ARG_EV_COMP, - ARG_ISO_SPEED, - ARG_APERTURE, - ARG_EXPOSURE, - ARG_VIDEO_SOURCE_FILTER, - ARG_IMAGE_CAPTURE_SUPPORTED_CAPS, - ARG_VIEWFINDER_FILTER, - ARG_FLICKER_MODE, - ARG_FOCUS_MODE, - ARG_BLOCK_VIEWFINDER, - ARG_IMAGE_CAPTURE_WIDTH, - ARG_IMAGE_CAPTURE_HEIGHT, - ARG_VIDEO_CAPTURE_WIDTH, - ARG_VIDEO_CAPTURE_HEIGHT, - ARG_VIDEO_CAPTURE_FRAMERATE -}; - #define DEFAULT_WIDTH 640 #define DEFAULT_HEIGHT 480 #define DEFAULT_CAPTURE_WIDTH 800 diff --git a/gst/camerabin2/gstv4l2camerasrc.c b/gst/camerabin2/gstv4l2camerasrc.c index c8cd2b2310..451b98f6e2 100644 --- a/gst/camerabin2/gstv4l2camerasrc.c +++ b/gst/camerabin2/gstv4l2camerasrc.c @@ -35,6 +35,14 @@ #include "camerabingeneral.h" #include "gstcamerabin-enum.h" +enum +{ + PROP_0, + PROP_FILTER_CAPS, + PROP_VIDEO_SRC, + PROP_VIDEO_SOURCE_FILTER +}; + #define CAMERABIN_DEFAULT_VF_CAPS "video/x-raw-yuv,format=(fourcc)I420" /* Using "bilinear" as default zoom method */ @@ -68,14 +76,14 @@ gst_v4l2_camera_src_set_property (GObject * object, GstV4l2CameraSrc *self = GST_V4L2_CAMERA_SRC (object); switch (prop_id) { - case ARG_FILTER_CAPS: + case PROP_FILTER_CAPS: GST_OBJECT_LOCK (self); gst_caps_replace (&self->view_finder_caps, (GstCaps *) gst_value_get_caps (value)); GST_OBJECT_UNLOCK (self); configure_format (self, self->view_finder_caps); break; - case ARG_VIDEO_SOURCE_FILTER: + case PROP_VIDEO_SOURCE_FILTER: if (GST_STATE (self) != GST_STATE_NULL) { GST_ELEMENT_ERROR (self, CORE, FAILED, ("camerasrc must be in NULL state when setting the video filter element"), @@ -86,7 +94,7 @@ gst_v4l2_camera_src_set_property (GObject * object, self->app_video_filter = g_value_dup_object (value); } break; - case ARG_VIDEO_SRC: + case PROP_VIDEO_SRC: if (GST_STATE (self) != GST_STATE_NULL) { GST_ELEMENT_ERROR (self, CORE, FAILED, ("camerasrc must be in NULL state when setting the video source element"), @@ -111,13 +119,13 @@ gst_v4l2_camera_src_get_property (GObject * object, GstV4l2CameraSrc *self = GST_V4L2_CAMERA_SRC (object); switch (prop_id) { - case ARG_FILTER_CAPS: + case PROP_FILTER_CAPS: gst_value_set_caps (value, self->view_finder_caps); break; - case ARG_VIDEO_SOURCE_FILTER: + case PROP_VIDEO_SOURCE_FILTER: g_value_set_object (value, self->app_video_filter); break; - case ARG_VIDEO_SRC: + case PROP_VIDEO_SRC: if (self->src_vid_src) g_value_set_object (value, self->src_vid_src); else From 201e9ac221208b49d1de52af2a35da0f3e2d45d9 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Sun, 12 Dec 2010 23:03:21 -0300 Subject: [PATCH 163/448] camerabin2: Add properties for supported capture caps Adds 2 property for getting the supported image/video capture caps from the camera source. --- gst/camerabin2/gstbasecamerasrc.c | 1 - gst/camerabin2/gstcamerabin2.c | 55 ++++++++++++++++++++++++++++++- 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/gst/camerabin2/gstbasecamerasrc.c b/gst/camerabin2/gstbasecamerasrc.c index a5e7053e15..a906840678 100644 --- a/gst/camerabin2/gstbasecamerasrc.c +++ b/gst/camerabin2/gstbasecamerasrc.c @@ -482,7 +482,6 @@ gst_base_camera_src_class_init (GstBaseCameraSrcClass * klass) gobject_class->set_property = gst_base_camera_src_set_property; gobject_class->get_property = gst_base_camera_src_get_property; - // g_object_class_install_property .... g_object_class_install_property (gobject_class, PROP_MODE, g_param_spec_enum ("mode", "Mode", "The capture mode (still image capture or video recording)", diff --git a/gst/camerabin2/gstcamerabin2.c b/gst/camerabin2/gstcamerabin2.c index 7036e19085..4f40072765 100644 --- a/gst/camerabin2/gstcamerabin2.c +++ b/gst/camerabin2/gstcamerabin2.c @@ -49,6 +49,7 @@ #include "config.h" #endif +#include "gstbasecamerasrc.h" #include "gstcamerabin2.h" #include "gstcamerabin-enum.h" @@ -61,7 +62,9 @@ enum { PROP_0, PROP_MODE, - PROP_LOCATION + PROP_LOCATION, + PROP_IMAGE_CAPTURE_SUPPORTED_CAPS, + PROP_VIDEO_CAPTURE_SUPPORTED_CAPS }; enum @@ -271,6 +274,21 @@ gst_camera_bin_class_init (GstCameraBinClass * klass) "Default for images is img_%d and vid_%d for videos", DEFAULT_IMG_LOCATION, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (object_class, + PROP_IMAGE_CAPTURE_SUPPORTED_CAPS, + g_param_spec_boxed ("image-capture-supported-caps", + "Image capture supported caps", + "Formats supported for capturing images represented as GstCaps", + GST_TYPE_CAPS, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (object_class, + PROP_VIDEO_CAPTURE_SUPPORTED_CAPS, + g_param_spec_boxed ("video-capture-supported-caps", + "Video capture supported caps", + "Formats supported for capturing videos represented as GstCaps", + GST_TYPE_CAPS, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + /** * GstCameraBin::capture-start: * @camera: the camera bin element @@ -469,6 +487,41 @@ gst_camera_bin_get_property (GObject * object, guint prop_id, g_value_set_string (value, camera->img_location); } break; + case PROP_VIDEO_CAPTURE_SUPPORTED_CAPS: + case PROP_IMAGE_CAPTURE_SUPPORTED_CAPS:{ + GstPad *pad; + GstCaps *caps; + const gchar *padname; + + if (prop_id == PROP_VIDEO_CAPTURE_SUPPORTED_CAPS) { + padname = GST_BASE_CAMERA_SRC_VIDEO_PAD_NAME; + } else { + padname = GST_BASE_CAMERA_SRC_IMAGE_PAD_NAME; + } + + if (camera->src) { + pad = gst_element_get_static_pad (camera->src, padname); + + g_assert (pad != NULL); + + /* TODO not sure if we want get_caps or get_allowed_caps to already + * consider the full pipeline scenario and avoid picking a caps that + * won't negotiate. Need to take care on the special case of the + * pad being unlinked. + */ + caps = gst_pad_get_caps_reffed (pad); + if (caps) { + gst_value_set_caps (value, caps); + gst_caps_unref (caps); + } + + gst_object_unref (pad); + } else { + GST_DEBUG_OBJECT (camera, "Camera source not created, can't get " + "supported caps"); + } + } + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; From adc3cdc6aa9062e7a508e8edf3ef623dc4bf64f5 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Mon, 13 Dec 2010 11:53:59 -0300 Subject: [PATCH 164/448] camerabin2: Rename variables Use better name for the variables, making the code clearer. Also keep a ref for some internal elements to avoid fetching them by name when needed later. --- gst/camerabin2/gstcamerabin2.c | 164 +++++++++++++++++---------------- gst/camerabin2/gstcamerabin2.h | 21 +++-- 2 files changed, 99 insertions(+), 86 deletions(-) diff --git a/gst/camerabin2/gstcamerabin2.c b/gst/camerabin2/gstcamerabin2.c index 4f40072765..4168501fb2 100644 --- a/gst/camerabin2/gstcamerabin2.c +++ b/gst/camerabin2/gstcamerabin2.c @@ -28,14 +28,14 @@ /* * Detail Topics: * - * videorecordingbin state management (for now on vidbin) - * - The problem: keeping vidbin state in sync with camerabin will make it + * videorecordingbin state management (for now on videobin) + * - The problem: keeping videobin state in sync with camerabin will make it * go to playing when it might not be used, causing its internal * filesink to open a file that might be left blank. - * - The solution: vidbin state is set to locked upon its creation and camerabin + * - The solution: videobin state is set to locked upon its creation and camerabin * registers itself on the notify::ready-for-capture of the src. * Whenever the src readyness goes to FALSE it means a new - * capture is starting. If we are on video mode, the vidbin's + * capture is starting. If we are on video mode, the videobin's * state is set to NULL and then PLAYING (in between this we * have room to set the destination filename). * There is no problem to leave it on playing after an EOS, so @@ -176,16 +176,17 @@ gst_camera_bin_src_notify_readyforcapture (GObject * obj, GParamSpec * pspec, /* a video recording is about to start, we reset the videobin to clear eos/flushing state * also need to clean the queue ! capsfilter before it */ - gst_element_set_state (camera->vidbin, GST_STATE_NULL); - gst_element_set_state (camera->vid_queue, GST_STATE_NULL); - gst_element_set_state (camera->vid_capsfilter, GST_STATE_NULL); - location = g_strdup_printf (camera->vid_location, camera->vid_index++); - GST_DEBUG_OBJECT (camera, "Switching vidbin location to %s", location); - g_object_set (camera->vidbin, "location", location, NULL); + gst_element_set_state (camera->videobin, GST_STATE_NULL); + gst_element_set_state (camera->videobin_queue, GST_STATE_NULL); + gst_element_set_state (camera->videobin_capsfilter, GST_STATE_NULL); + location = + g_strdup_printf (camera->video_location, camera->video_index++); + GST_DEBUG_OBJECT (camera, "Switching videobin location to %s", location); + g_object_set (camera->videobin, "location", location, NULL); g_free (location); - gst_element_set_state (camera->vidbin, GST_STATE_PLAYING); - gst_element_set_state (camera->vid_capsfilter, GST_STATE_PLAYING); - gst_element_set_state (camera->vid_queue, GST_STATE_PLAYING); + gst_element_set_state (camera->videobin, GST_STATE_PLAYING); + gst_element_set_state (camera->videobin_capsfilter, GST_STATE_PLAYING); + gst_element_set_state (camera->videobin_queue, GST_STATE_PLAYING); } } } @@ -195,11 +196,9 @@ gst_camera_bin_dispose (GObject * object) { GstCameraBin *camerabin = GST_CAMERA_BIN_CAST (object); - if (camerabin->vf_bin) - gst_object_unref (camerabin->vf_bin); - g_free (camerabin->img_location); - g_free (camerabin->vid_location); + g_free (camerabin->image_location); + g_free (camerabin->video_location); if (camerabin->src_capture_notify_id) g_signal_handler_disconnect (camerabin->src, @@ -207,15 +206,27 @@ gst_camera_bin_dispose (GObject * object) if (camerabin->src) gst_object_unref (camerabin->src); - if (camerabin->vidbin) - gst_object_unref (camerabin->vidbin); - if (camerabin->vid_queue) - gst_object_unref (camerabin->vid_queue); - if (camerabin->vid_capsfilter) - gst_object_unref (camerabin->vid_capsfilter); + if (camerabin->viewfinderbin) + gst_object_unref (camerabin->viewfinderbin); + if (camerabin->viewfinderbin_queue) + gst_object_unref (camerabin->viewfinderbin_queue); + if (camerabin->viewfinderbin_capsfilter) + gst_object_unref (camerabin->viewfinderbin_capsfilter); - if (camerabin->imgbin) - gst_object_unref (camerabin->imgbin); + + if (camerabin->videobin) + gst_object_unref (camerabin->videobin); + if (camerabin->videobin_queue) + gst_object_unref (camerabin->videobin_queue); + if (camerabin->videobin_capsfilter) + gst_object_unref (camerabin->videobin_capsfilter); + + if (camerabin->imagebin) + gst_object_unref (camerabin->imagebin); + if (camerabin->imagebin_queue) + gst_object_unref (camerabin->imagebin_queue); + if (camerabin->imagebin_capsfilter) + gst_object_unref (camerabin->imagebin_capsfilter); G_OBJECT_CLASS (parent_class)->dispose (object); } @@ -318,11 +329,12 @@ static void gst_camera_bin_init (GstCameraBin * camerabin) { camerabin->mode = DEFAULT_MODE; - camerabin->vid_location = g_strdup (DEFAULT_VID_LOCATION); - camerabin->img_location = g_strdup (DEFAULT_IMG_LOCATION); - camerabin->vf_bin = gst_element_factory_make ("viewfinderbin", "vf-bin"); + camerabin->video_location = g_strdup (DEFAULT_VID_LOCATION); + camerabin->image_location = g_strdup (DEFAULT_IMG_LOCATION); + camerabin->viewfinderbin = gst_element_factory_make ("viewfinderbin", + "vf-bin"); - gst_bin_add (GST_BIN (camerabin), gst_object_ref (camerabin->vf_bin)); + gst_bin_add (GST_BIN (camerabin), gst_object_ref (camerabin->viewfinderbin)); } /** @@ -340,49 +352,45 @@ gst_camera_bin_init (GstCameraBin * camerabin) static gboolean gst_camera_bin_create_elements (GstCameraBin * camera) { - GstElement *src; - GstElement *vid; - GstElement *img; - GstElement *vid_queue; - GstElement *img_queue; - GstElement *vf_queue; - GstElement *vid_capsfilter; - GstElement *img_capsfilter; - GstElement *vf_capsfilter; - if (camera->elements_created) return TRUE; - src = gst_element_factory_make ("v4l2camerasrc", "camerasrc"); - vid = gst_element_factory_make ("videorecordingbin", "video-rec-bin"); - img = gst_element_factory_make ("imagecapturebin", "image-cap-bin"); + camera->src = gst_element_factory_make ("v4l2camerasrc", "camerasrc"); + camera->videobin = gst_element_factory_make ("videorecordingbin", "videobin"); + camera->imagebin = gst_element_factory_make ("imagecapturebin", "imagebin"); - camera->src = gst_object_ref (src); - camera->vidbin = gst_object_ref (vid); - camera->imgbin = gst_object_ref (img); + camera->videobin_queue = gst_element_factory_make ("queue", "videobin-queue"); + camera->imagebin_queue = gst_element_factory_make ("queue", "imagebin-queue"); + camera->viewfinderbin_queue = gst_element_factory_make ("queue", + "viewfinderbin-queue"); - vid_queue = gst_element_factory_make ("queue", "video-queue"); - img_queue = gst_element_factory_make ("queue", "image-queue"); - vf_queue = gst_element_factory_make ("queue", "vf-queue"); + camera->videobin_capsfilter = gst_element_factory_make ("capsfilter", + "videobin-capsfilter"); + camera->imagebin_capsfilter = gst_element_factory_make ("capsfilter", + "imagebin-capsfilter"); + camera->viewfinderbin_capsfilter = gst_element_factory_make ("capsfilter", + "viewfinderbin-capsfilter"); - vid_capsfilter = gst_element_factory_make ("capsfilter", "video-capsfilter"); - img_capsfilter = gst_element_factory_make ("capsfilter", "image-capsfilter"); - vf_capsfilter = gst_element_factory_make ("capsfilter", "vf-capsfilter"); - - gst_bin_add_many (GST_BIN_CAST (camera), src, vid, img, - vid_queue, img_queue, vf_queue, vid_capsfilter, img_capsfilter, - vf_capsfilter, NULL); + gst_bin_add_many (GST_BIN_CAST (camera), gst_object_ref (camera->src), + gst_object_ref (camera->videobin), gst_object_ref (camera->imagebin), + gst_object_ref (camera->videobin_queue), + gst_object_ref (camera->imagebin_queue), + gst_object_ref (camera->viewfinderbin_queue), + gst_object_ref (camera->videobin_capsfilter), + gst_object_ref (camera->imagebin_capsfilter), + gst_object_ref (camera->viewfinderbin_capsfilter), NULL); /* Linking can be optimized TODO */ - gst_element_link_many (vid_queue, vid_capsfilter, vid, NULL); - gst_element_link_many (img_queue, img_capsfilter, img, NULL); - gst_element_link_many (vf_queue, vf_capsfilter, camera->vf_bin, NULL); - gst_element_link_pads (src, "vfsrc", vf_queue, "sink"); - gst_element_link_pads (src, "imgsrc", img_queue, "sink"); - gst_element_link_pads (src, "vidsrc", vid_queue, "sink"); - - camera->vid_queue = gst_object_ref (vid_queue); - camera->vid_capsfilter = gst_object_ref (vid_capsfilter); + gst_element_link_many (camera->videobin_queue, camera->videobin_capsfilter, + camera->videobin, NULL); + gst_element_link_many (camera->imagebin_queue, camera->imagebin_capsfilter, + camera->imagebin, NULL); + gst_element_link_many (camera->viewfinderbin_queue, + camera->viewfinderbin_capsfilter, camera->viewfinderbin, NULL); + gst_element_link_pads (camera->src, "vfsrc", camera->viewfinderbin_queue, + "sink"); + gst_element_link_pads (camera->src, "imgsrc", camera->imagebin_queue, "sink"); + gst_element_link_pads (camera->src, "vidsrc", camera->videobin_queue, "sink"); /* * Video can't get into playing as its internal filesink will open @@ -393,14 +401,14 @@ gst_camera_bin_create_elements (GstCameraBin * camera) * the source's ready-for-capture goes to FALSE it means it is * starting recording, so we should prepare the video bin. */ - gst_element_set_locked_state (vid, TRUE); - camera->src_capture_notify_id = g_signal_connect (G_OBJECT (src), + gst_element_set_locked_state (camera->videobin, TRUE); + camera->src_capture_notify_id = g_signal_connect (G_OBJECT (camera->src), "notify::ready-for-capture", G_CALLBACK (gst_camera_bin_src_notify_readyforcapture), camera); - g_object_set (src, "mode", camera->mode, NULL); - g_object_set (vid, "location", camera->vid_location, NULL); - g_object_set (img, "location", camera->img_location, NULL); + g_object_set (camera->src, "mode", camera->mode, NULL); + g_object_set (camera->videobin, "location", camera->video_location, NULL); + g_object_set (camera->imagebin, "location", camera->image_location, NULL); camera->elements_created = TRUE; return TRUE; @@ -426,7 +434,7 @@ gst_camera_bin_change_state (GstElement * element, GstStateChange trans) switch (trans) { case GST_STATE_CHANGE_READY_TO_NULL: - gst_element_set_state (camera->vidbin, GST_STATE_NULL); + gst_element_set_state (camera->videobin, GST_STATE_NULL); break; default: break; @@ -441,13 +449,13 @@ gst_camera_bin_set_location (GstCameraBin * camera, const gchar * location) GST_DEBUG_OBJECT (camera, "Setting mode %d location to %s", camera->mode, location); if (camera->mode == MODE_IMAGE) { - if (camera->imgbin) - g_object_set (camera->imgbin, "location", location, NULL); - g_free (camera->img_location); - camera->img_location = g_strdup (location); + if (camera->imagebin) + g_object_set (camera->imagebin, "location", location, NULL); + g_free (camera->image_location); + camera->image_location = g_strdup (location); } else { - g_free (camera->vid_location); - camera->vid_location = g_strdup (location); + g_free (camera->video_location); + camera->video_location = g_strdup (location); } } @@ -482,9 +490,9 @@ gst_camera_bin_get_property (GObject * object, guint prop_id, break; case PROP_LOCATION: if (camera->mode == MODE_VIDEO) { - g_value_set_string (value, camera->vid_location); + g_value_set_string (value, camera->video_location); } else { - g_value_set_string (value, camera->img_location); + g_value_set_string (value, camera->image_location); } break; case PROP_VIDEO_CAPTURE_SUPPORTED_CAPS: diff --git a/gst/camerabin2/gstcamerabin2.h b/gst/camerabin2/gstcamerabin2.h index 48a0ac31c6..f887a1bd2d 100644 --- a/gst/camerabin2/gstcamerabin2.h +++ b/gst/camerabin2/gstcamerabin2.h @@ -40,20 +40,25 @@ struct _GstCameraBin GstElement *src; gulong src_capture_notify_id; - GstElement *vidbin; - GstElement *vid_queue; - GstElement *vid_capsfilter; + GstElement *videobin; + GstElement *videobin_queue; + GstElement *videobin_capsfilter; - GstElement *vf_bin; + GstElement *viewfinderbin; + GstElement *viewfinderbin_queue; + GstElement *viewfinderbin_capsfilter; - GstElement *imgbin; + GstElement *imagebin; + GstElement *imagebin_queue; + GstElement *imagebin_capsfilter; - gint vid_index; + /* Index of the auto incrementing file index for video recordings */ + gint video_index; /* properties */ gint mode; - gchar *vid_location; - gchar *img_location; + gchar *video_location; + gchar *image_location; gboolean elements_created; }; From 59c48d34437a411c5687c5705bfa7fce012cf4b0 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Mon, 13 Dec 2010 16:36:19 -0300 Subject: [PATCH 165/448] camerabin2: Add camera-src property Adds a property to select the camera source element to be used. Changing only happens on the next NULL->READY transition --- gst/camerabin2/gstcamerabin2.c | 162 +++++++++++++++++++++++---------- gst/camerabin2/gstcamerabin2.h | 1 + 2 files changed, 113 insertions(+), 50 deletions(-) diff --git a/gst/camerabin2/gstcamerabin2.c b/gst/camerabin2/gstcamerabin2.c index 4168501fb2..f15dddfb2d 100644 --- a/gst/camerabin2/gstcamerabin2.c +++ b/gst/camerabin2/gstcamerabin2.c @@ -63,6 +63,7 @@ enum PROP_0, PROP_MODE, PROP_LOCATION, + PROP_CAMERA_SRC, PROP_IMAGE_CAPTURE_SUPPORTED_CAPS, PROP_VIDEO_CAPTURE_SUPPORTED_CAPS }; @@ -196,7 +197,6 @@ gst_camera_bin_dispose (GObject * object) { GstCameraBin *camerabin = GST_CAMERA_BIN_CAST (object); - g_free (camerabin->image_location); g_free (camerabin->video_location); @@ -205,6 +205,8 @@ gst_camera_bin_dispose (GObject * object) camerabin->src_capture_notify_id); if (camerabin->src) gst_object_unref (camerabin->src); + if (camerabin->user_src) + gst_object_unref (camerabin->user_src); if (camerabin->viewfinderbin) gst_object_unref (camerabin->viewfinderbin); @@ -285,6 +287,11 @@ gst_camera_bin_class_init (GstCameraBinClass * klass) "Default for images is img_%d and vid_%d for videos", DEFAULT_IMG_LOCATION, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (object_class, PROP_CAMERA_SRC, + g_param_spec_object ("camera-src", "Camera source", + "The camera source element to be used", + GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (object_class, PROP_IMAGE_CAPTURE_SUPPORTED_CAPS, g_param_spec_boxed ("image-capture-supported-caps", @@ -352,63 +359,98 @@ gst_camera_bin_init (GstCameraBin * camerabin) static gboolean gst_camera_bin_create_elements (GstCameraBin * camera) { - if (camera->elements_created) - return TRUE; + gboolean new_src = FALSE; - camera->src = gst_element_factory_make ("v4l2camerasrc", "camerasrc"); - camera->videobin = gst_element_factory_make ("videorecordingbin", "videobin"); - camera->imagebin = gst_element_factory_make ("imagecapturebin", "imagebin"); + if (!camera->elements_created) { - camera->videobin_queue = gst_element_factory_make ("queue", "videobin-queue"); - camera->imagebin_queue = gst_element_factory_make ("queue", "imagebin-queue"); - camera->viewfinderbin_queue = gst_element_factory_make ("queue", - "viewfinderbin-queue"); + camera->videobin = + gst_element_factory_make ("videorecordingbin", "videobin"); + camera->imagebin = gst_element_factory_make ("imagecapturebin", "imagebin"); - camera->videobin_capsfilter = gst_element_factory_make ("capsfilter", - "videobin-capsfilter"); - camera->imagebin_capsfilter = gst_element_factory_make ("capsfilter", - "imagebin-capsfilter"); - camera->viewfinderbin_capsfilter = gst_element_factory_make ("capsfilter", - "viewfinderbin-capsfilter"); + camera->videobin_queue = + gst_element_factory_make ("queue", "videobin-queue"); + camera->imagebin_queue = + gst_element_factory_make ("queue", "imagebin-queue"); + camera->viewfinderbin_queue = + gst_element_factory_make ("queue", "viewfinderbin-queue"); - gst_bin_add_many (GST_BIN_CAST (camera), gst_object_ref (camera->src), - gst_object_ref (camera->videobin), gst_object_ref (camera->imagebin), - gst_object_ref (camera->videobin_queue), - gst_object_ref (camera->imagebin_queue), - gst_object_ref (camera->viewfinderbin_queue), - gst_object_ref (camera->videobin_capsfilter), - gst_object_ref (camera->imagebin_capsfilter), - gst_object_ref (camera->viewfinderbin_capsfilter), NULL); + camera->videobin_capsfilter = gst_element_factory_make ("capsfilter", + "videobin-capsfilter"); + camera->imagebin_capsfilter = gst_element_factory_make ("capsfilter", + "imagebin-capsfilter"); + camera->viewfinderbin_capsfilter = gst_element_factory_make ("capsfilter", + "viewfinderbin-capsfilter"); - /* Linking can be optimized TODO */ - gst_element_link_many (camera->videobin_queue, camera->videobin_capsfilter, - camera->videobin, NULL); - gst_element_link_many (camera->imagebin_queue, camera->imagebin_capsfilter, - camera->imagebin, NULL); - gst_element_link_many (camera->viewfinderbin_queue, - camera->viewfinderbin_capsfilter, camera->viewfinderbin, NULL); - gst_element_link_pads (camera->src, "vfsrc", camera->viewfinderbin_queue, - "sink"); - gst_element_link_pads (camera->src, "imgsrc", camera->imagebin_queue, "sink"); - gst_element_link_pads (camera->src, "vidsrc", camera->videobin_queue, "sink"); + gst_bin_add_many (GST_BIN_CAST (camera), + gst_object_ref (camera->videobin), gst_object_ref (camera->imagebin), + gst_object_ref (camera->videobin_queue), + gst_object_ref (camera->imagebin_queue), + gst_object_ref (camera->viewfinderbin_queue), + gst_object_ref (camera->videobin_capsfilter), + gst_object_ref (camera->imagebin_capsfilter), + gst_object_ref (camera->viewfinderbin_capsfilter), NULL); - /* - * Video can't get into playing as its internal filesink will open - * a file for writing and leave it empty if unused. - * - * Its state is managed using the current mode and the source's - * ready-for-capture notify callback. When we are at video mode and - * the source's ready-for-capture goes to FALSE it means it is - * starting recording, so we should prepare the video bin. - */ - gst_element_set_locked_state (camera->videobin, TRUE); - camera->src_capture_notify_id = g_signal_connect (G_OBJECT (camera->src), - "notify::ready-for-capture", - G_CALLBACK (gst_camera_bin_src_notify_readyforcapture), camera); + /* Linking can be optimized TODO */ + gst_element_link_many (camera->videobin_queue, camera->videobin_capsfilter, + camera->videobin, NULL); + gst_element_link_many (camera->imagebin_queue, camera->imagebin_capsfilter, + camera->imagebin, NULL); + gst_element_link_many (camera->viewfinderbin_queue, + camera->viewfinderbin_capsfilter, camera->viewfinderbin, NULL); + /* + * Video can't get into playing as its internal filesink will open + * a file for writing and leave it empty if unused. + * + * Its state is managed using the current mode and the source's + * ready-for-capture notify callback. When we are at video mode and + * the source's ready-for-capture goes to FALSE it means it is + * starting recording, so we should prepare the video bin. + */ + gst_element_set_locked_state (camera->videobin, TRUE); + g_object_set (camera->videobin, "location", camera->video_location, NULL); + g_object_set (camera->imagebin, "location", camera->image_location, NULL); + } + + /* check if we need to replace the camera src */ + + if (camera->src) { + if (camera->user_src && camera->user_src != camera->src) { + + if (camera->src_capture_notify_id) + g_signal_handler_disconnect (camera->src, + camera->src_capture_notify_id); + + gst_bin_remove (GST_BIN_CAST (camera), camera->src); + gst_object_unref (camera->src); + camera->src = NULL; + } + } + + if (!camera->src) { + if (camera->user_src) { + camera->src = gst_object_ref (camera->user_src); + } else { + camera->src = gst_element_factory_make ("v4l2camerasrc", "camerasrc"); + } + + new_src = TRUE; + } + + g_assert (camera->src != NULL); g_object_set (camera->src, "mode", camera->mode, NULL); - g_object_set (camera->videobin, "location", camera->video_location, NULL); - g_object_set (camera->imagebin, "location", camera->image_location, NULL); + if (new_src) { + gst_bin_add (GST_BIN_CAST (camera), gst_object_ref (camera->src)); + camera->src_capture_notify_id = g_signal_connect (G_OBJECT (camera->src), + "notify::ready-for-capture", + G_CALLBACK (gst_camera_bin_src_notify_readyforcapture), camera); + gst_element_link_pads (camera->src, "vfsrc", camera->viewfinderbin_queue, + "sink"); + gst_element_link_pads (camera->src, "imgsrc", camera->imagebin_queue, + "sink"); + gst_element_link_pads (camera->src, "vidsrc", camera->videobin_queue, + "sink"); + } camera->elements_created = TRUE; return TRUE; @@ -459,6 +501,20 @@ gst_camera_bin_set_location (GstCameraBin * camera, const gchar * location) } } +static void +gst_camera_bin_set_camera_src (GstCameraBin * camera, GstElement * src) +{ + GST_DEBUG_OBJECT (GST_OBJECT (camera), + "Setting camera source %" GST_PTR_FORMAT, src); + + if (camera->user_src) + g_object_unref (camera->user_src); + + if (src) + g_object_ref (src); + camera->user_src = src; +} + static void gst_camera_bin_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) @@ -472,6 +528,9 @@ gst_camera_bin_set_property (GObject * object, guint prop_id, case PROP_LOCATION: gst_camera_bin_set_location (camera, g_value_get_string (value)); break; + case PROP_CAMERA_SRC: + gst_camera_bin_set_camera_src (camera, g_value_get_object (value)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -495,6 +554,9 @@ gst_camera_bin_get_property (GObject * object, guint prop_id, g_value_set_string (value, camera->image_location); } break; + case PROP_CAMERA_SRC: + g_value_set_object (value, camera->src); + break; case PROP_VIDEO_CAPTURE_SUPPORTED_CAPS: case PROP_IMAGE_CAPTURE_SUPPORTED_CAPS:{ GstPad *pad; diff --git a/gst/camerabin2/gstcamerabin2.h b/gst/camerabin2/gstcamerabin2.h index f887a1bd2d..5664363784 100644 --- a/gst/camerabin2/gstcamerabin2.h +++ b/gst/camerabin2/gstcamerabin2.h @@ -38,6 +38,7 @@ struct _GstCameraBin GstPipeline pipeline; GstElement *src; + GstElement *user_src; gulong src_capture_notify_id; GstElement *videobin; From 740921105548e4c7446e18fada07f6148f29ad21 Mon Sep 17 00:00:00 2001 From: Teemu Katajisto Date: Tue, 14 Dec 2010 10:48:56 +0200 Subject: [PATCH 166/448] camerabin2: imagecapturebin: release objects and memory allocations --- gst/camerabin2/gstimagecapturebin.c | 32 ++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/gst/camerabin2/gstimagecapturebin.c b/gst/camerabin2/gstimagecapturebin.c index 9120d867db..a1cf3ac131 100644 --- a/gst/camerabin2/gstimagecapturebin.c +++ b/gst/camerabin2/gstimagecapturebin.c @@ -67,6 +67,10 @@ static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", GST_BOILERPLATE (GstImageCaptureBin, gst_image_capture_bin, GstBin, GST_TYPE_BIN); +/* GObject callbacks */ +static void gst_image_capture_bin_dispose (GObject * object); +static void gst_image_capture_bin_finalize (GObject * object); + /* Element class functions */ static GstStateChangeReturn gst_image_capture_bin_change_state (GstElement * element, GstStateChange trans); @@ -113,6 +117,7 @@ gst_image_capture_bin_set_property (GObject * object, guint prop_id, case PROP_LOCATION: g_free (imagebin->location); imagebin->location = g_value_dup_string (value); + if (imagebin->sink) { g_object_set (imagebin, "location", imagebin->location, NULL); } @@ -183,9 +188,10 @@ gst_image_capture_bin_class_init (GstImageCaptureBinClass * klass) gobject_class = G_OBJECT_CLASS (klass); element_class = GST_ELEMENT_CLASS (klass); + gobject_class->dispose = gst_image_capture_bin_dispose; + gobject_class->finalize = gst_image_capture_bin_finalize; gobject_class->set_property = gst_image_capture_bin_set_property; gobject_class->get_property = gst_image_capture_bin_get_property; - gobject_class->finalize = gst_image_capture_bin_finalize; element_class->change_state = GST_DEBUG_FUNCPTR (gst_image_capture_bin_change_state); @@ -214,14 +220,34 @@ gst_image_capture_bin_init (GstImageCaptureBin * imagebin, GstPadTemplate *tmpl; tmpl = gst_static_pad_template_get (&sink_template); - imagebin->ghostpad = - gst_ghost_pad_new_no_target_from_template ("sink", tmpl); + imagebin->ghostpad = gst_ghost_pad_new_no_target_from_template ("sink", tmpl); gst_object_unref (tmpl); gst_element_add_pad (GST_ELEMENT_CAST (imagebin), imagebin->ghostpad); + imagebin->sink = NULL; + imagebin->location = g_strdup (DEFAULT_LOCATION); imagebin->encoder = NULL; imagebin->user_encoder = NULL; + imagebin->muxer = NULL; + imagebin->user_muxer = NULL; +} + +static void +gst_image_capture_bin_dispose (GObject * object) +{ + GstImageCaptureBin *imagebin = GST_IMAGE_CAPTURE_BIN_CAST (object); + + if (imagebin->user_encoder) { + gst_object_unref (imagebin->user_encoder); + imagebin->user_encoder = NULL; + } + + if (imagebin->user_muxer) { + gst_object_unref (imagebin->user_muxer); + imagebin->user_muxer = NULL; + } + G_OBJECT_CLASS (parent_class)->dispose ((GObject *) imagebin); } static gboolean From 78dc07987e3ed831a33eed686b531b5624d4a0fc Mon Sep 17 00:00:00 2001 From: Teemu Katajisto Date: Tue, 14 Dec 2010 09:58:35 +0200 Subject: [PATCH 167/448] camerabin2: remove abbreviations from videorecordingbin --- gst/camerabin2/gstvideorecordingbin.c | 67 ++++++++++++++------------- 1 file changed, 34 insertions(+), 33 deletions(-) diff --git a/gst/camerabin2/gstvideorecordingbin.c b/gst/camerabin2/gstvideorecordingbin.c index ba78a3e2a3..bffb3bc2d6 100644 --- a/gst/camerabin2/gstvideorecordingbin.c +++ b/gst/camerabin2/gstvideorecordingbin.c @@ -69,13 +69,13 @@ static void gst_video_recording_bin_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { - GstVideoRecordingBin *vidbin = GST_VIDEO_RECORDING_BIN_CAST (object); + GstVideoRecordingBin *videobin = GST_VIDEO_RECORDING_BIN_CAST (object); switch (prop_id) { case PROP_LOCATION: - vidbin->location = g_value_dup_string (value); - if (vidbin->sink) { - g_object_set (vidbin->sink, "location", vidbin->location, NULL); + videobin->location = g_value_dup_string (value); + if (videobin->sink) { + g_object_set (videobin->sink, "location", videobin->location, NULL); } break; default: @@ -88,11 +88,11 @@ static void gst_video_recording_bin_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { - GstVideoRecordingBin *vidbin = GST_VIDEO_RECORDING_BIN_CAST (object); + GstVideoRecordingBin *videobin = GST_VIDEO_RECORDING_BIN_CAST (object); switch (prop_id) { case PROP_LOCATION: - g_value_set_string (value, vidbin->location); + g_value_set_string (value, videobin->location); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -135,61 +135,62 @@ gst_video_recording_bin_class_init (GstVideoRecordingBinClass * klass) } static void -gst_video_recording_bin_init (GstVideoRecordingBin * video_recordingbin, - GstVideoRecordingBinClass * video_recordingbin_class) +gst_video_recording_bin_init (GstVideoRecordingBin * videobin, + GstVideoRecordingBinClass * videobin_class) { - video_recordingbin->ghostpad = + videobin->ghostpad = gst_ghost_pad_new_no_target_from_template ("sink", gst_static_pad_template_get (&sink_template)); - gst_element_add_pad (GST_ELEMENT_CAST (video_recordingbin), - video_recordingbin->ghostpad); + gst_element_add_pad (GST_ELEMENT_CAST (videobin), videobin->ghostpad); - video_recordingbin->location = g_strdup (DEFAULT_LOCATION); + videobin->location = g_strdup (DEFAULT_LOCATION); } static gboolean -gst_video_recording_bin_create_elements (GstVideoRecordingBin * vrbin) +gst_video_recording_bin_create_elements (GstVideoRecordingBin * videobin) { - GstElement *csp; - GstElement *enc; - GstElement *mux; + GstElement *colorspace; + GstElement *encoder; + GstElement *muxer; GstElement *sink; GstPad *pad = NULL; - if (vrbin->elements_created) + if (videobin->elements_created) return TRUE; /* create elements */ - csp = gst_element_factory_make ("ffmpegcolorspace", "vrbin-csp"); - if (!csp) + colorspace = + gst_element_factory_make ("ffmpegcolorspace", "videobin-colorspace"); + if (!colorspace) goto error; - enc = gst_element_factory_make ("theoraenc", "vrbin-enc"); - if (!enc) + encoder = gst_element_factory_make ("theoraenc", "videobin-encoder"); + if (!encoder) goto error; - mux = gst_element_factory_make ("oggmux", "vrbin-mux"); - if (!mux) + muxer = gst_element_factory_make ("oggmux", "videobin->muxer"); + if (!muxer) goto error; - sink = gst_element_factory_make ("filesink", "vrbin-sink"); + sink = gst_element_factory_make ("filesink", "videobin-sink"); if (!sink) goto error; - vrbin->sink = gst_object_ref (sink); - g_object_set (sink, "location", vrbin->location, "async", FALSE, NULL); + videobin->sink = gst_object_ref (sink); + g_object_set (sink, "location", videobin->location, "async", FALSE, NULL); /* add and link */ - gst_bin_add_many (GST_BIN_CAST (vrbin), csp, enc, mux, sink, NULL); - if (!gst_element_link_many (csp, enc, mux, sink, NULL)) + gst_bin_add_many (GST_BIN_CAST (videobin), colorspace, encoder, muxer, sink, + NULL); + if (!gst_element_link_many (colorspace, encoder, muxer, sink, NULL)) goto error; /* add ghostpad */ - pad = gst_element_get_static_pad (csp, "sink"); - if (!gst_ghost_pad_set_target (GST_GHOST_PAD (vrbin->ghostpad), pad)) + pad = gst_element_get_static_pad (colorspace, "sink"); + if (!gst_ghost_pad_set_target (GST_GHOST_PAD (videobin->ghostpad), pad)) goto error; - vrbin->elements_created = TRUE; + videobin->elements_created = TRUE; return TRUE; error: @@ -203,11 +204,11 @@ gst_video_recording_bin_change_state (GstElement * element, GstStateChange trans) { GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; - GstVideoRecordingBin *vrbin = GST_VIDEO_RECORDING_BIN_CAST (element); + GstVideoRecordingBin *videobin = GST_VIDEO_RECORDING_BIN_CAST (element); switch (trans) { case GST_STATE_CHANGE_NULL_TO_READY: - if (!gst_video_recording_bin_create_elements (vrbin)) { + if (!gst_video_recording_bin_create_elements (videobin)) { return GST_STATE_CHANGE_FAILURE; } break; From c76aeb77e59865182da9bb6c0568ffc240e2eebd Mon Sep 17 00:00:00 2001 From: Teemu Katajisto Date: Tue, 14 Dec 2010 12:21:57 +0200 Subject: [PATCH 168/448] camerabin2: add videorecordingbin::video-encoder property --- gst/camerabin2/gstvideorecordingbin.c | 105 ++++++++++++++++++++--- gst/camerabin2/gstvideorecordingbin.h | 2 + tests/check/elements/videorecordingbin.c | 45 ++++++++++ 3 files changed, 138 insertions(+), 14 deletions(-) diff --git a/gst/camerabin2/gstvideorecordingbin.c b/gst/camerabin2/gstvideorecordingbin.c index bffb3bc2d6..a3ac745aaf 100644 --- a/gst/camerabin2/gstvideorecordingbin.c +++ b/gst/camerabin2/gstvideorecordingbin.c @@ -35,6 +35,7 @@ #endif #include "gstvideorecordingbin.h" +#include "camerabingeneral.h" /* prototypes */ @@ -42,10 +43,15 @@ enum { PROP_0, - PROP_LOCATION + PROP_LOCATION, + PROP_VIDEO_ENCODER }; #define DEFAULT_LOCATION "vidcap" +#define DEFAULT_COLORSPACE "ffmpegcolorspace" +#define DEFAULT_VIDEO_ENCODER "theoraenc" +#define DEFAULT_MUXER "oggmux" +#define DEFAULT_SINK "filesink" /* pad templates */ @@ -60,11 +66,31 @@ static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", GST_BOILERPLATE (GstVideoRecordingBin, gst_video_recording_bin, GstBin, GST_TYPE_BIN); +/* GObject callbacks */ +static void gst_video_recording_bin_dispose (GObject * object); +static void gst_video_recording_bin_finalize (GObject * object); + /* Element class functions */ static GstStateChangeReturn gst_video_recording_bin_change_state (GstElement * element, GstStateChange trans); +static void +gst_video_recording_bin_set_video_encoder (GstVideoRecordingBin * videobin, + GstElement * encoder) +{ + GST_DEBUG_OBJECT (GST_OBJECT (videobin), + "Setting video encoder %" GST_PTR_FORMAT, encoder); + + if (videobin->user_video_encoder) + g_object_unref (videobin->user_video_encoder); + + if (encoder) + g_object_ref (encoder); + + videobin->user_video_encoder = encoder; +} + static void gst_video_recording_bin_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) @@ -73,11 +99,18 @@ gst_video_recording_bin_set_property (GObject * object, guint prop_id, switch (prop_id) { case PROP_LOCATION: + if (videobin->location) + g_free (videobin->location); + videobin->location = g_value_dup_string (value); if (videobin->sink) { g_object_set (videobin->sink, "location", videobin->location, NULL); } break; + case PROP_VIDEO_ENCODER: + gst_video_recording_bin_set_video_encoder (videobin, + g_value_get_object (value)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -94,6 +127,9 @@ gst_video_recording_bin_get_property (GObject * object, guint prop_id, case PROP_LOCATION: g_value_set_string (value, videobin->location); break; + case PROP_VIDEO_ENCODER: + g_value_set_object (value, videobin->video_encoder); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -122,6 +158,9 @@ gst_video_recording_bin_class_init (GstVideoRecordingBinClass * klass) gobject_class = G_OBJECT_CLASS (klass); element_class = GST_ELEMENT_CLASS (klass); + gobject_class->dispose = gst_video_recording_bin_dispose; + gobject_class->finalize = gst_video_recording_bin_finalize; + gobject_class->set_property = gst_video_recording_bin_set_property; gobject_class->get_property = gst_video_recording_bin_get_property; @@ -132,6 +171,11 @@ gst_video_recording_bin_class_init (GstVideoRecordingBinClass * klass) g_param_spec_string ("location", "Location", "Location to save the captured files.", DEFAULT_LOCATION, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_VIDEO_ENCODER, + g_param_spec_object ("video-encoder", "Video encoder", + "Video encoder GstElement (default is theoraenc).", + GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); } static void @@ -144,13 +188,39 @@ gst_video_recording_bin_init (GstVideoRecordingBin * videobin, gst_element_add_pad (GST_ELEMENT_CAST (videobin), videobin->ghostpad); videobin->location = g_strdup (DEFAULT_LOCATION); + videobin->video_encoder = NULL; + videobin->user_video_encoder = NULL; } +static void +gst_video_recording_bin_dispose (GObject * object) +{ + GstVideoRecordingBin *videobin = GST_VIDEO_RECORDING_BIN_CAST (object); + + if (videobin->user_video_encoder) { + gst_object_unref (videobin->user_video_encoder); + videobin->user_video_encoder = NULL; + } + + G_OBJECT_CLASS (parent_class)->dispose ((GObject *) videobin); +} + +static void +gst_video_recording_bin_finalize (GObject * object) +{ + GstVideoRecordingBin *videobin = GST_VIDEO_RECORDING_BIN_CAST (object); + + g_free (videobin->location); + videobin->location = NULL; + + G_OBJECT_CLASS (parent_class)->finalize ((GObject *) videobin); +} + + static gboolean gst_video_recording_bin_create_elements (GstVideoRecordingBin * videobin) { GstElement *colorspace; - GstElement *encoder; GstElement *muxer; GstElement *sink; GstPad *pad = NULL; @@ -160,31 +230,38 @@ gst_video_recording_bin_create_elements (GstVideoRecordingBin * videobin) /* create elements */ colorspace = - gst_element_factory_make ("ffmpegcolorspace", "videobin-colorspace"); + gst_camerabin_create_and_add_element (GST_BIN (videobin), + DEFAULT_COLORSPACE); if (!colorspace) goto error; - encoder = gst_element_factory_make ("theoraenc", "videobin-encoder"); - if (!encoder) - goto error; + if (videobin->user_video_encoder) { + videobin->video_encoder = videobin->user_video_encoder; + if (!gst_camerabin_add_element (GST_BIN (videobin), + videobin->video_encoder)) { + goto error; + } + } else { + videobin->video_encoder = + gst_camerabin_create_and_add_element (GST_BIN (videobin), + DEFAULT_VIDEO_ENCODER); + if (!videobin->video_encoder) + goto error; + } - muxer = gst_element_factory_make ("oggmux", "videobin->muxer"); + muxer = gst_camerabin_create_and_add_element (GST_BIN (videobin), + DEFAULT_MUXER); if (!muxer) goto error; - sink = gst_element_factory_make ("filesink", "videobin-sink"); + sink = gst_camerabin_create_and_add_element (GST_BIN (videobin), + DEFAULT_SINK); if (!sink) goto error; videobin->sink = gst_object_ref (sink); g_object_set (sink, "location", videobin->location, "async", FALSE, NULL); - /* add and link */ - gst_bin_add_many (GST_BIN_CAST (videobin), colorspace, encoder, muxer, sink, - NULL); - if (!gst_element_link_many (colorspace, encoder, muxer, sink, NULL)) - goto error; - /* add ghostpad */ pad = gst_element_get_static_pad (colorspace, "sink"); if (!gst_ghost_pad_set_target (GST_GHOST_PAD (videobin->ghostpad), pad)) diff --git a/gst/camerabin2/gstvideorecordingbin.h b/gst/camerabin2/gstvideorecordingbin.h index cf4de898ff..afa7db201d 100644 --- a/gst/camerabin2/gstvideorecordingbin.h +++ b/gst/camerabin2/gstvideorecordingbin.h @@ -42,6 +42,8 @@ struct _GstVideoRecordingBin /* props */ gchar *location; + GstElement *video_encoder; + GstElement *user_video_encoder; gboolean elements_created; }; diff --git a/tests/check/elements/videorecordingbin.c b/tests/check/elements/videorecordingbin.c index c002e3d8e9..1f35dd1114 100644 --- a/tests/check/elements/videorecordingbin.c +++ b/tests/check/elements/videorecordingbin.c @@ -110,6 +110,50 @@ GST_START_TEST (test_simple_recording) GST_END_TEST; +GST_START_TEST (test_setting_video_encoder) +{ + GstVideoRecordingBinTestContext ctx; + GstBus *bus; + GstMessage *msg; + GstElement *encoder; + gchar *test_file_name; + FILE *f; + + gstvideorecordingbin_init_test_context (&ctx, N_BUFFERS); + bus = gst_element_get_bus (ctx.pipe); + + test_file_name = make_test_file_name (0); + g_object_set (ctx.vrbin, "location", test_file_name, NULL); + + encoder = gst_element_factory_make ("theoraenc", NULL); + g_object_set (ctx.vrbin, "video-encoder", encoder, NULL); + + fail_if (gst_element_set_state (ctx.pipe, GST_STATE_PLAYING) == + GST_STATE_CHANGE_FAILURE); + + msg = gst_bus_timed_pop_filtered (bus, GST_SECOND * 10, + GST_MESSAGE_EOS | GST_MESSAGE_ERROR); + fail_unless (msg != NULL); + fail_unless (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_EOS); + + /* check there is a recorded file */ + fail_unless (g_file_test (test_file_name, G_FILE_TEST_EXISTS)); + fail_unless (g_file_test (test_file_name, G_FILE_TEST_IS_REGULAR)); + fail_if (g_file_test (test_file_name, G_FILE_TEST_IS_SYMLINK)); + + /* check the file isn't empty */ + f = fopen (test_file_name, "r"); + fseek (f, 0, SEEK_END); + fail_unless (ftell (f) > 0); + fclose (f); + + gstvideorecordingbin_unset_test_context (&ctx); + gst_object_unref (bus); + g_free (test_file_name); +} + +GST_END_TEST; + static Suite * videorecordingbin_suite (void) { @@ -118,6 +162,7 @@ videorecordingbin_suite (void) suite_add_tcase (s, tc_chain); tcase_add_test (tc_chain, test_simple_recording); + tcase_add_test (tc_chain, test_setting_video_encoder); return s; } From 4a28d5f4780ec680ab53579630830a59d862457a Mon Sep 17 00:00:00 2001 From: Teemu Katajisto Date: Tue, 14 Dec 2010 14:28:49 +0200 Subject: [PATCH 169/448] camerabin2: add videorecordingbin::video-muxer property --- gst/camerabin2/gstvideorecordingbin.c | 64 ++++++++++++++++++++---- gst/camerabin2/gstvideorecordingbin.h | 2 + tests/check/elements/videorecordingbin.c | 49 ++++++++++++++++++ 3 files changed, 104 insertions(+), 11 deletions(-) diff --git a/gst/camerabin2/gstvideorecordingbin.c b/gst/camerabin2/gstvideorecordingbin.c index a3ac745aaf..7426375ac6 100644 --- a/gst/camerabin2/gstvideorecordingbin.c +++ b/gst/camerabin2/gstvideorecordingbin.c @@ -44,7 +44,8 @@ enum { PROP_0, PROP_LOCATION, - PROP_VIDEO_ENCODER + PROP_VIDEO_ENCODER, + PROP_MUXER }; #define DEFAULT_LOCATION "vidcap" @@ -91,6 +92,22 @@ gst_video_recording_bin_set_video_encoder (GstVideoRecordingBin * videobin, videobin->user_video_encoder = encoder; } +static void +gst_video_recording_bin_set_muxer (GstVideoRecordingBin * videobin, + GstElement * muxer) +{ + GST_DEBUG_OBJECT (GST_OBJECT (videobin), + "Setting video muxer %" GST_PTR_FORMAT, muxer); + + if (videobin->user_muxer) + g_object_unref (videobin->user_muxer); + + if (muxer) + g_object_ref (muxer); + + videobin->user_muxer = muxer; +} + static void gst_video_recording_bin_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) @@ -111,6 +128,9 @@ gst_video_recording_bin_set_property (GObject * object, guint prop_id, gst_video_recording_bin_set_video_encoder (videobin, g_value_get_object (value)); break; + case PROP_MUXER: + gst_video_recording_bin_set_muxer (videobin, g_value_get_object (value)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -130,6 +150,9 @@ gst_video_recording_bin_get_property (GObject * object, guint prop_id, case PROP_VIDEO_ENCODER: g_value_set_object (value, videobin->video_encoder); break; + case PROP_MUXER: + g_value_set_object (value, videobin->muxer); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -176,6 +199,11 @@ gst_video_recording_bin_class_init (GstVideoRecordingBinClass * klass) g_param_spec_object ("video-encoder", "Video encoder", "Video encoder GstElement (default is theoraenc).", GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_MUXER, + g_param_spec_object ("video-muxer", "Video muxer", + "Video muxer GstElement (default is oggmux).", + GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); } static void @@ -190,6 +218,8 @@ gst_video_recording_bin_init (GstVideoRecordingBin * videobin, videobin->location = g_strdup (DEFAULT_LOCATION); videobin->video_encoder = NULL; videobin->user_video_encoder = NULL; + videobin->muxer = NULL; + videobin->user_muxer = NULL; } static void @@ -202,6 +232,11 @@ gst_video_recording_bin_dispose (GObject * object) videobin->user_video_encoder = NULL; } + if (videobin->user_muxer) { + gst_object_unref (videobin->user_muxer); + videobin->user_muxer = NULL; + } + G_OBJECT_CLASS (parent_class)->dispose ((GObject *) videobin); } @@ -221,8 +256,6 @@ static gboolean gst_video_recording_bin_create_elements (GstVideoRecordingBin * videobin) { GstElement *colorspace; - GstElement *muxer; - GstElement *sink; GstPad *pad = NULL; if (videobin->elements_created) @@ -249,18 +282,26 @@ gst_video_recording_bin_create_elements (GstVideoRecordingBin * videobin) goto error; } - muxer = gst_camerabin_create_and_add_element (GST_BIN (videobin), - DEFAULT_MUXER); - if (!muxer) - goto error; + if (videobin->user_muxer) { + videobin->muxer = videobin->user_muxer; + if (!gst_camerabin_add_element (GST_BIN (videobin), videobin->muxer)) { + goto error; + } + } else { + videobin->muxer = + gst_camerabin_create_and_add_element (GST_BIN (videobin), + DEFAULT_MUXER); + if (!videobin->muxer) + goto error; + } - sink = gst_camerabin_create_and_add_element (GST_BIN (videobin), + videobin->sink = gst_camerabin_create_and_add_element (GST_BIN (videobin), DEFAULT_SINK); - if (!sink) + if (!videobin->sink) goto error; - videobin->sink = gst_object_ref (sink); - g_object_set (sink, "location", videobin->location, "async", FALSE, NULL); + g_object_set (videobin->sink, "location", videobin->location, "async", FALSE, + NULL); /* add ghostpad */ pad = gst_element_get_static_pad (colorspace, "sink"); @@ -271,6 +312,7 @@ gst_video_recording_bin_create_elements (GstVideoRecordingBin * videobin) return TRUE; error: + GST_DEBUG_OBJECT (videobin, "Create elements failed"); if (pad) gst_object_unref (pad); return FALSE; diff --git a/gst/camerabin2/gstvideorecordingbin.h b/gst/camerabin2/gstvideorecordingbin.h index afa7db201d..167da29524 100644 --- a/gst/camerabin2/gstvideorecordingbin.h +++ b/gst/camerabin2/gstvideorecordingbin.h @@ -44,6 +44,8 @@ struct _GstVideoRecordingBin gchar *location; GstElement *video_encoder; GstElement *user_video_encoder; + GstElement *muxer; + GstElement *user_muxer; gboolean elements_created; }; diff --git a/tests/check/elements/videorecordingbin.c b/tests/check/elements/videorecordingbin.c index 1f35dd1114..96ed35119a 100644 --- a/tests/check/elements/videorecordingbin.c +++ b/tests/check/elements/videorecordingbin.c @@ -154,6 +154,54 @@ GST_START_TEST (test_setting_video_encoder) GST_END_TEST; +GST_START_TEST (test_setting_video_muxer) +{ + GstVideoRecordingBinTestContext ctx; + GstBus *bus; + GstMessage *msg; + GstElement *encoder; + GstElement *muxer; + gchar *test_file_name; + FILE *f; + + gstvideorecordingbin_init_test_context (&ctx, N_BUFFERS); + bus = gst_element_get_bus (ctx.pipe); + + test_file_name = make_test_file_name (0); + g_object_set (ctx.vrbin, "location", test_file_name, NULL); + + encoder = gst_element_factory_make ("theoraenc", NULL); + g_object_set (ctx.vrbin, "video-encoder", encoder, NULL); + + muxer = gst_element_factory_make ("oggmux", NULL); + g_object_set (ctx.vrbin, "video-muxer", muxer, NULL); + + fail_if (gst_element_set_state (ctx.pipe, GST_STATE_PLAYING) == + GST_STATE_CHANGE_FAILURE); + + msg = gst_bus_timed_pop_filtered (bus, GST_SECOND * 10, + GST_MESSAGE_EOS | GST_MESSAGE_ERROR); + fail_unless (msg != NULL); + fail_unless (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_EOS); + + /* check there is a recorded file */ + fail_unless (g_file_test (test_file_name, G_FILE_TEST_EXISTS)); + fail_unless (g_file_test (test_file_name, G_FILE_TEST_IS_REGULAR)); + fail_if (g_file_test (test_file_name, G_FILE_TEST_IS_SYMLINK)); + + /* check the file isn't empty */ + f = fopen (test_file_name, "r"); + fseek (f, 0, SEEK_END); + fail_unless (ftell (f) > 0); + fclose (f); + + gstvideorecordingbin_unset_test_context (&ctx); + gst_object_unref (bus); + g_free (test_file_name); +} + +GST_END_TEST; + static Suite * videorecordingbin_suite (void) { @@ -163,6 +211,7 @@ videorecordingbin_suite (void) suite_add_tcase (s, tc_chain); tcase_add_test (tc_chain, test_simple_recording); tcase_add_test (tc_chain, test_setting_video_encoder); + tcase_add_test (tc_chain, test_setting_video_muxer); return s; } From 4938c2e9ea2613d4049dc01756346bbb055eab70 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Mon, 13 Dec 2010 19:36:41 -0300 Subject: [PATCH 170/448] camerabin2: Move basecamerasrc to gst-libs Move the base camera src class to gst-libs/gst/basecamerabinsrc to allow it to be included from the tests. --- configure.ac | 1 + gst-libs/gst/Makefile.am | 8 ++++-- gst-libs/gst/basecamerabinsrc/Makefile.am | 26 +++++++++++++++++++ .../gst/basecamerabinsrc}/gstbasecamerasrc.c | 0 .../gst/basecamerabinsrc}/gstbasecamerasrc.h | 0 .../gst/basecamerabinsrc}/gstcamerabin-enum.c | 0 .../gst/basecamerabinsrc}/gstcamerabin-enum.h | 0 gst/camerabin2/Makefile.am | 7 ++--- gst/camerabin2/gstcamerabin2.c | 3 +-- gst/camerabin2/gstv4l2camerasrc.c | 1 - gst/camerabin2/gstv4l2camerasrc.h | 2 +- tests/check/Makefile.am | 14 ++++++++++ tests/check/elements/camerabin2.c | 1 + 13 files changed, 52 insertions(+), 11 deletions(-) create mode 100644 gst-libs/gst/basecamerabinsrc/Makefile.am rename {gst/camerabin2 => gst-libs/gst/basecamerabinsrc}/gstbasecamerasrc.c (100%) rename {gst/camerabin2 => gst-libs/gst/basecamerabinsrc}/gstbasecamerasrc.h (100%) rename {gst/camerabin2 => gst-libs/gst/basecamerabinsrc}/gstcamerabin-enum.c (100%) rename {gst/camerabin2 => gst-libs/gst/basecamerabinsrc}/gstcamerabin-enum.h (100%) diff --git a/configure.ac b/configure.ac index 8e92c688f8..89cc9cb7e2 100644 --- a/configure.ac +++ b/configure.ac @@ -1781,6 +1781,7 @@ gst/vmnc/Makefile gst/y4m/Makefile gst-libs/Makefile gst-libs/gst/Makefile +gst-libs/gst/basecamerabinsrc/Makefile gst-libs/gst/interfaces/Makefile gst-libs/gst/signalprocessor/Makefile gst-libs/gst/video/Makefile diff --git a/gst-libs/gst/Makefile.am b/gst-libs/gst/Makefile.am index e48cdd802f..561c1f4ea2 100644 --- a/gst-libs/gst/Makefile.am +++ b/gst-libs/gst/Makefile.am @@ -1,5 +1,9 @@ -SUBDIRS = interfaces signalprocessor video +if BUILD_EXPERIMENTAL +EXPERIMENTAL_LIBS=basecamerabinsrc +endif + +SUBDIRS = $(EXPERIMENTAL_LIBS) interfaces signalprocessor video noinst_HEADERS = gst-i18n-plugin.h gettext.h -DIST_SUBDIRS = interfaces signalprocessor video +DIST_SUBDIRS = $(EXPERIMENTAL_LIBS) interfaces signalprocessor video diff --git a/gst-libs/gst/basecamerabinsrc/Makefile.am b/gst-libs/gst/basecamerabinsrc/Makefile.am new file mode 100644 index 0000000000..d0b69b5fef --- /dev/null +++ b/gst-libs/gst/basecamerabinsrc/Makefile.am @@ -0,0 +1,26 @@ + +lib_LTLIBRARIES = libgstbasecamerabinsrc-@GST_MAJORMINOR@.la + +CLEANFILES = $(BUILT_SOURCES) + +libgstbasecamerabinsrc_@GST_MAJORMINOR@_la_SOURCES = \ + gstcamerabin-enum.c \ + gstbasecamerasrc.c + +libgstbasecamerabinsrc_@GST_MAJORMINOR@includedir = $(includedir)/gstreamer-@GST_MAJORMINOR@/gst/basecamerabinsrc +libgstbasecamerabinsrc_@GST_MAJORMINOR@include_HEADERS = \ + gstcamerabin-enum.h \ + gstbasecamerasrc.h + +libgstbasecamerabinsrc_@GST_MAJORMINOR@_la_CFLAGS = \ + $(GST_PLUGINS_BAD_CFLAGS) \ + $(GST_PLUGINS_BASE_CFLAGS) \ + -DGST_USE_UNSTABLE_API \ + $(GST_CFLAGS) +libgstbasecamerabinsrc_@GST_MAJORMINOR@_la_LIBADD = \ + $(top_builddir)/gst-libs/gst/interfaces/libgstphotography-@GST_MAJORMINOR@.la \ + $(GST_PLUGINS_BASE_LIBS) $(GST_BASE_LIBS) $(GST_LIBS) \ + -lgstinterfaces-$(GST_MAJORMINOR) + +libgstbasecamerabinsrc_@GST_MAJORMINOR@_la_LDFLAGS = $(GST_LIB_LDFLAGS) $(GST_ALL_LDFLAGS) $(GST_LT_LDFLAGS) + diff --git a/gst/camerabin2/gstbasecamerasrc.c b/gst-libs/gst/basecamerabinsrc/gstbasecamerasrc.c similarity index 100% rename from gst/camerabin2/gstbasecamerasrc.c rename to gst-libs/gst/basecamerabinsrc/gstbasecamerasrc.c diff --git a/gst/camerabin2/gstbasecamerasrc.h b/gst-libs/gst/basecamerabinsrc/gstbasecamerasrc.h similarity index 100% rename from gst/camerabin2/gstbasecamerasrc.h rename to gst-libs/gst/basecamerabinsrc/gstbasecamerasrc.h diff --git a/gst/camerabin2/gstcamerabin-enum.c b/gst-libs/gst/basecamerabinsrc/gstcamerabin-enum.c similarity index 100% rename from gst/camerabin2/gstcamerabin-enum.c rename to gst-libs/gst/basecamerabinsrc/gstcamerabin-enum.c diff --git a/gst/camerabin2/gstcamerabin-enum.h b/gst-libs/gst/basecamerabinsrc/gstcamerabin-enum.h similarity index 100% rename from gst/camerabin2/gstcamerabin-enum.h rename to gst-libs/gst/basecamerabinsrc/gstcamerabin-enum.h diff --git a/gst/camerabin2/Makefile.am b/gst/camerabin2/Makefile.am index 92229d73df..4cb29bfd29 100644 --- a/gst/camerabin2/Makefile.am +++ b/gst/camerabin2/Makefile.am @@ -4,8 +4,6 @@ libgstcamerabin2_la_SOURCES = gstviewfinderbin.c \ gstimagecapturebin.c \ gstvideorecordingbin.c \ camerabingeneral.c \ - gstbasecamerasrc.c \ - gstcamerabin-enum.c \ gstv4l2camerasrc.c \ gstcamerabin2.c \ gstplugin.c @@ -17,6 +15,7 @@ libgstcamerabin2_la_CFLAGS = \ libgstcamerabin2_la_LIBADD = \ $(top_builddir)/gst-libs/gst/interfaces/libgstphotography-$(GST_MAJORMINOR).la \ + $(top_builddir)/gst-libs/gst/basecamerabinsrc/libgstbasecamerabinsrc-$(GST_MAJORMINOR).la \ $(GST_LIBS) $(GST_BASE_LIBS) $(GST_PLUGINS_BASE_LIBS) \ -lgstinterfaces-$(GST_MAJORMINOR) -lgsttag-$(GST_MAJORMINOR) @@ -27,7 +26,5 @@ noinst_HEADERS = gstviewfinderbin.h \ gstimagecapturebin.h \ gstvideorecordingbin.h \ camerabingeneral.h \ - gstbasecamerasrc.h \ gstv4l2camerasrc.h \ - gstcamerabin2.h \ - gstcamerabin-enum.h + gstcamerabin2.h diff --git a/gst/camerabin2/gstcamerabin2.c b/gst/camerabin2/gstcamerabin2.c index f15dddfb2d..ccb4c1800f 100644 --- a/gst/camerabin2/gstcamerabin2.c +++ b/gst/camerabin2/gstcamerabin2.c @@ -49,9 +49,8 @@ #include "config.h" #endif -#include "gstbasecamerasrc.h" +#include #include "gstcamerabin2.h" -#include "gstcamerabin-enum.h" GST_DEBUG_CATEGORY_STATIC (gst_camera_bin_debug); #define GST_CAT_DEFAULT gst_camera_bin_debug diff --git a/gst/camerabin2/gstv4l2camerasrc.c b/gst/camerabin2/gstv4l2camerasrc.c index 451b98f6e2..5ea070bc62 100644 --- a/gst/camerabin2/gstv4l2camerasrc.c +++ b/gst/camerabin2/gstv4l2camerasrc.c @@ -33,7 +33,6 @@ #include "gstv4l2camerasrc.h" #include "camerabingeneral.h" -#include "gstcamerabin-enum.h" enum { diff --git a/gst/camerabin2/gstv4l2camerasrc.h b/gst/camerabin2/gstv4l2camerasrc.h index 5f476fcc20..580af287ae 100644 --- a/gst/camerabin2/gstv4l2camerasrc.h +++ b/gst/camerabin2/gstv4l2camerasrc.h @@ -23,7 +23,7 @@ #define __GST_V4L2_CAMERA_SRC_H__ #include -#include "gstbasecamerasrc.h" +#include G_BEGIN_DECLS #define GST_TYPE_V4L2_CAMERA_SRC \ diff --git a/tests/check/Makefile.am b/tests/check/Makefile.am index 48052a1f89..864ce0888b 100644 --- a/tests/check/Makefile.am +++ b/tests/check/Makefile.am @@ -197,6 +197,20 @@ elements_camerabin_LDADD = \ -lgstinterfaces-@GST_MAJORMINOR@ elements_camerabin_SOURCES = elements/camerabin.c +if BUILD_EXPERIMENTAL +elements_camerabin2_CFLAGS = \ + -I$(top_builddir)/gst-libs \ + $(GST_CFLAGS) $(GST_BASE_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) \ + $(GST_PLUGINS_BAD_CFLAGS) $(GST_CHECK_CFLAGS) \ + -DGST_USE_UNSTABLE_API +elements_camerabin2_LDADD = \ + $(top_builddir)/gst-libs/gst/interfaces/libgstphotography-@GST_MAJORMINOR@.la \ + $(top_builddir)/gst-libs/gst/basecamerabinsrc/libgstbasecamerabinsrc-@GST_MAJORMINOR@.la \ + $(GST_LIBS) $(GST_BASE_LIBS) $(GST_PLUGINS_BASE_LIBS) \ + $(GST_CHECK_LIBS) +elements_camerabin2_SOURCES = elements/camerabin2.c +endif + elements_jifmux_CFLAGS = $(GST_CHECK_CFLAGS) $(GST_OPTION_CFLAGS) $(AM_CFLAGS) $(EXIF_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) elements_jifmux_LDADD = $(GST_CHECK_LIBS) $(EXIF_LIBS) $(LDADD) $(GST_PLUGINS_BASE_LIBS) -lgsttag-$(GST_MAJORMINOR) elements_jifmux_SOURCES = elements/jifmux.c diff --git a/tests/check/elements/camerabin2.c b/tests/check/elements/camerabin2.c index 4f46e0c78a..95d17275f7 100644 --- a/tests/check/elements/camerabin2.c +++ b/tests/check/elements/camerabin2.c @@ -29,6 +29,7 @@ #include #include #include +#include #define IMAGE_FILENAME "image" #define VIDEO_FILENAME "video" From b81677032c8b5238b559de956e6b21f069bf0254 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Tue, 14 Dec 2010 08:44:36 -0300 Subject: [PATCH 171/448] camerabin2: adds PORTING document Adds a PORTING document to explain the differences from camerabin to camerabin2 and help application developers on porting from one to another. --- gst/camerabin2/PORTING | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 gst/camerabin2/PORTING diff --git a/gst/camerabin2/PORTING b/gst/camerabin2/PORTING new file mode 100644 index 0000000000..fe090b5c1e --- /dev/null +++ b/gst/camerabin2/PORTING @@ -0,0 +1,14 @@ +This document lists the differenced between camerabin and camerabin2 from +the API point of view and should be used to help on porting applications +from camerabin to camerabin2. + +* Setting the location for the captures: +camerabin requires that the path of the file to save the captures is set before +each capture. Camerabin2 allows the application to use a multifilesink-like +approach, the application can set a file with a '%d' marker, this marker +will be automatically replaced by a number and be autoincremented after each +capture. + +* Capture signals +The signals were renamed from capture-start/stop to start/stop-capture as +this is the usual naming on actions. From 4ee773b7dd8dd4a3ed9eb57026873c1c8d94aa34 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Mon, 13 Dec 2010 17:56:14 -0300 Subject: [PATCH 172/448] camerabin2: Add test for supported caps properties Adds tests for checking that the supported caps properties work as expected (using the respective pads get caps function) --- tests/check/elements/camerabin2.c | 177 ++++++++++++++++++++++++++++++ 1 file changed, 177 insertions(+) diff --git a/tests/check/elements/camerabin2.c b/tests/check/elements/camerabin2.c index 95d17275f7..ca745297e8 100644 --- a/tests/check/elements/camerabin2.c +++ b/tests/check/elements/camerabin2.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -36,6 +37,134 @@ #define CAPTURE_COUNT 3 #define VIDEO_DURATION 5 +#define VIDEO_PAD_SUPPORTED_CAPS GST_VIDEO_CAPS_RGB ", width=600, height=480" +#define IMAGE_PAD_SUPPORTED_CAPS GST_VIDEO_CAPS_RGB ", width=800, height=600" + +/* custom test camera src element */ +#define GST_TYPE_TEST_CAMERA_SRC \ + (gst_test_camera_src_get_type()) +#define GST_TEST_CAMERA_SRC(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_TEST_CAMERA_SRC,GstTestCameraSrc)) +#define GST_TEST_CAMERA_SRC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_TEST_CAMERA_SRC,GstTestCameraSrcClass)) +#define GST_IS_TEST_REVERSE_NEGOTIATION_SINK(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_TEST_CAMERA_SRC)) +#define GST_IS_TEST_REVERSE_NEGOTIATION_SINK_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_TEST_CAMERA_SRC)) +#define GST_TEST_CAMERA_SRC_CAST(obj) ((GstTestCameraSrc *)obj) + +typedef struct _GstTestCameraSrc GstTestCameraSrc; +typedef struct _GstTestCameraSrcClass GstTestCameraSrcClass; +struct _GstTestCameraSrc +{ + GstBaseCameraSrc element; + + GstPad *vfpad; + GstPad *vidpad; + GstPad *imgpad; + + GstCameraBinMode mode; +}; + +struct _GstTestCameraSrcClass +{ + GstBaseCameraSrcClass parent_class; +}; + +GType gst_test_camera_src_get_type (void); + +GST_BOILERPLATE (GstTestCameraSrc, + gst_test_camera_src, GstBaseCameraSrc, GST_TYPE_BASE_CAMERA_SRC); + +static gboolean +gst_test_camera_src_set_mode (GstBaseCameraSrc * src, GstCameraBinMode mode) +{ + GstTestCameraSrc *self = GST_TEST_CAMERA_SRC (src); + + self->mode = mode; + return TRUE; +} + +static GstCaps * +gst_test_camera_src_get_caps (GstPad * pad) +{ + GstTestCameraSrc *self = (GstTestCameraSrc *) GST_PAD_PARENT (pad); + GstCaps *result = NULL; + + if (pad == self->vfpad) { + result = gst_caps_new_any (); + } else if (pad == self->vidpad) { + result = gst_caps_from_string (VIDEO_PAD_SUPPORTED_CAPS); + } else if (pad == self->imgpad) { + result = gst_caps_from_string (IMAGE_PAD_SUPPORTED_CAPS); + } else { + g_assert_not_reached (); + } + + return result; +} + +static void +gst_test_camera_src_base_init (gpointer g_class) +{ + GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_set_details_simple (gstelement_class, + "Test Camera Src", + "Camera/Src", + "Some test camera src", + "Thiago Santos "); +} + +static void +gst_test_camera_src_class_init (GstTestCameraSrcClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + GstBaseCameraSrcClass *gstbasecamera_class; + + gobject_class = G_OBJECT_CLASS (klass); + gstelement_class = GST_ELEMENT_CLASS (klass); + gstbasecamera_class = GST_BASE_CAMERA_SRC_CLASS (klass); + + gstbasecamera_class->set_mode = gst_test_camera_src_set_mode; +} + +static void +gst_test_camera_src_init (GstTestCameraSrc * self, + GstTestCameraSrcClass * g_class) +{ + GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class); + GstPadTemplate *template; + + /* create pads */ + template = gst_element_class_get_pad_template (gstelement_class, + GST_BASE_CAMERA_SRC_VIEWFINDER_PAD_NAME); + self->vfpad = gst_pad_new_from_template (template, + GST_BASE_CAMERA_SRC_VIEWFINDER_PAD_NAME); + gst_element_add_pad (GST_ELEMENT_CAST (self), self->vfpad); + + template = gst_element_class_get_pad_template (gstelement_class, + GST_BASE_CAMERA_SRC_IMAGE_PAD_NAME); + self->imgpad = gst_pad_new_from_template (template, + GST_BASE_CAMERA_SRC_IMAGE_PAD_NAME); + gst_element_add_pad (GST_ELEMENT_CAST (self), self->imgpad); + + template = gst_element_class_get_pad_template (gstelement_class, + GST_BASE_CAMERA_SRC_VIDEO_PAD_NAME); + self->vidpad = gst_pad_new_from_template (template, + GST_BASE_CAMERA_SRC_VIDEO_PAD_NAME); + gst_element_add_pad (GST_ELEMENT_CAST (self), self->vidpad); + + /* add get caps functions */ + gst_pad_set_getcaps_function (self->vfpad, gst_test_camera_src_get_caps); + gst_pad_set_getcaps_function (self->vidpad, gst_test_camera_src_get_caps); + gst_pad_set_getcaps_function (self->imgpad, gst_test_camera_src_get_caps); +} + +/* end of custom test camera src element */ + + static GstElement *camera; static GMainLoop *main_loop; @@ -120,6 +249,7 @@ setup (void) GstBus *bus; GstElement *vfbin; GstElement *fakevideosink; + GstElement *src; GST_INFO ("init"); @@ -127,6 +257,7 @@ setup (void) camera = gst_check_setup_element ("camerabin2"); fakevideosink = gst_check_setup_element ("fakesink"); + src = gst_check_setup_element ("v4l2camerasrc"); vfbin = gst_bin_get_by_name (GST_BIN (camera), "vf-bin"); g_object_set (G_OBJECT (vfbin), "video-sink", fakevideosink, NULL); @@ -322,6 +453,51 @@ GST_START_TEST (test_image_video_cycle) GST_END_TEST; +GST_START_TEST (test_supported_caps) +{ + GstCaps *padcaps = NULL; + GstCaps *expectedcaps; + GstElement *src; + + if (!camera) + return; + + src = g_object_new (GST_TYPE_TEST_CAMERA_SRC, NULL); + g_object_set (camera, "camera-src", src, NULL); + gst_object_unref (src); + + if (gst_element_set_state (GST_ELEMENT (camera), GST_STATE_PLAYING) == + GST_STATE_CHANGE_FAILURE) { + GST_WARNING ("setting camerabin to PLAYING failed"); + gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL); + gst_object_unref (camera); + camera = NULL; + } + g_assert (camera != NULL); + + expectedcaps = gst_caps_from_string (VIDEO_PAD_SUPPORTED_CAPS); + g_object_get (G_OBJECT (camera), "video-capture-supported-caps", &padcaps, + NULL); + g_assert (expectedcaps != NULL); + g_assert (padcaps != NULL); + g_assert (gst_caps_is_equal (padcaps, expectedcaps)); + gst_caps_unref (expectedcaps); + gst_caps_unref (padcaps); + + expectedcaps = gst_caps_from_string (IMAGE_PAD_SUPPORTED_CAPS); + g_object_get (G_OBJECT (camera), "image-capture-supported-caps", &padcaps, + NULL); + g_assert (expectedcaps != NULL); + g_assert (padcaps != NULL); + g_assert (gst_caps_is_equal (padcaps, expectedcaps)); + gst_caps_unref (expectedcaps); + gst_caps_unref (padcaps); + + gst_element_set_state (camera, GST_STATE_NULL); +} + +GST_END_TEST; + static Suite * camerabin_suite (void) { @@ -336,6 +512,7 @@ camerabin_suite (void) tcase_add_test (tc_basic, test_single_image_capture); tcase_add_test (tc_basic, test_video_recording); tcase_add_test (tc_basic, test_image_video_cycle); + tcase_add_test (tc_basic, test_supported_caps); return s; } From 07d58dbf84939189e0928398a27081d508be6ca9 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Tue, 14 Dec 2010 14:43:59 -0300 Subject: [PATCH 173/448] v4l2camerasrc: add video-src property Adds a property to select the src element to be used internally on v4l2camerasrc. Yeah, I know, this element should have a better name. --- gst/camerabin2/gstv4l2camerasrc.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/gst/camerabin2/gstv4l2camerasrc.c b/gst/camerabin2/gstv4l2camerasrc.c index 5ea070bc62..566ce4d825 100644 --- a/gst/camerabin2/gstv4l2camerasrc.c +++ b/gst/camerabin2/gstv4l2camerasrc.c @@ -102,7 +102,8 @@ gst_v4l2_camera_src_set_property (GObject * object, if (self->app_vid_src) gst_object_unref (self->app_vid_src); self->app_vid_src = g_value_get_object (value); - gst_object_ref (self->app_vid_src); + if (self->app_vid_src) + gst_object_ref (self->app_vid_src); } break; default: @@ -1031,6 +1032,10 @@ gst_v4l2_camera_src_class_init (GstV4l2CameraSrcClass * klass) gobject_class->get_property = gst_v4l2_camera_src_get_property; /* g_object_class_install_property .... */ + g_object_class_install_property (gobject_class, PROP_VIDEO_SRC, + g_param_spec_object ("video-src", "Video source", + "The video source element to be used", + GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); gstbasecamerasrc_class->construct_pipeline = gst_v4l2_camera_src_construct_pipeline; From 5ce8d0356dc886e1f493c2e4da7b6909288a1054 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Tue, 14 Dec 2010 14:48:28 -0300 Subject: [PATCH 174/448] camerabin2: Use videotestsrc on the tests Use videotestsrc to avoid openning the camera device on the tests. --- tests/check/elements/camerabin2.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/check/elements/camerabin2.c b/tests/check/elements/camerabin2.c index ca745297e8..776333085d 100644 --- a/tests/check/elements/camerabin2.c +++ b/tests/check/elements/camerabin2.c @@ -250,6 +250,7 @@ setup (void) GstElement *vfbin; GstElement *fakevideosink; GstElement *src; + GstElement *testsrc; GST_INFO ("init"); @@ -258,6 +259,13 @@ setup (void) camera = gst_check_setup_element ("camerabin2"); fakevideosink = gst_check_setup_element ("fakesink"); src = gst_check_setup_element ("v4l2camerasrc"); + testsrc = gst_check_setup_element ("videotestsrc"); + + g_object_set (G_OBJECT (testsrc), "is-live", TRUE, NULL); + g_object_set (G_OBJECT (src), "video-src", testsrc, NULL); + g_object_set (G_OBJECT (camera), "camera-src", src, NULL); + gst_object_unref (src); + gst_object_unref (testsrc); vfbin = gst_bin_get_by_name (GST_BIN (camera), "vf-bin"); g_object_set (G_OBJECT (vfbin), "video-sink", fakevideosink, NULL); From 706740845b8fc8be037e302f82a76fad8cb5bfe4 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Thu, 16 Dec 2010 10:51:38 -0300 Subject: [PATCH 175/448] viewfinderbin: Fix video-sink property again Avoid switching the element on the set_property function, instead wait for the next NULL -> READY transition. --- gst/camerabin2/gstviewfinderbin.c | 31 ++++++------------------------- 1 file changed, 6 insertions(+), 25 deletions(-) diff --git a/gst/camerabin2/gstviewfinderbin.c b/gst/camerabin2/gstviewfinderbin.c index b10d1fab1c..c820c0458a 100644 --- a/gst/camerabin2/gstviewfinderbin.c +++ b/gst/camerabin2/gstviewfinderbin.c @@ -231,33 +231,14 @@ gst_viewfinder_bin_set_video_sink (GstViewfinderBin * vfbin, GstElement * sink) { GST_INFO_OBJECT (vfbin, "Setting video sink to %" GST_PTR_FORMAT, sink); - if (vfbin->video_sink != sink) { + if (vfbin->user_video_sink != sink) { + if (vfbin->user_video_sink) { + gst_object_unref (vfbin->user_video_sink); + } + vfbin->user_video_sink = sink; if (sink) - gst_object_ref_sink (sink); - - if (vfbin->video_sink) { - gst_bin_remove (GST_BIN_CAST (vfbin), vfbin->video_sink); - gst_object_unref (vfbin->video_sink); - } - - vfbin->video_sink = sink; - if (sink) { - gst_bin_add (GST_BIN_CAST (vfbin), gst_object_ref (sink)); - if (vfbin->elements_created) { - GstElement *videoscale = gst_bin_get_by_name (GST_BIN_CAST (vfbin), - "vfbin-videoscale"); - - g_assert (videoscale != NULL); - - if (!gst_element_link_pads (videoscale, "src", sink, "sink")) { - GST_WARNING_OBJECT (vfbin, "Failed to link the new sink"); - } - } - } - + gst_object_ref (sink); } - - GST_LOG_OBJECT (vfbin, "Video sink is now %" GST_PTR_FORMAT, sink); } static void From b822ad3cd35bbdd0ad560074c4bcab1a3cd72b50 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Tue, 14 Dec 2010 16:59:54 -0300 Subject: [PATCH 176/448] v4l2camerasrc: remove video filter property code Removes some unused custom video filter element property code --- gst/camerabin2/gstv4l2camerasrc.c | 21 --------------------- gst/camerabin2/gstv4l2camerasrc.h | 1 - 2 files changed, 22 deletions(-) diff --git a/gst/camerabin2/gstv4l2camerasrc.c b/gst/camerabin2/gstv4l2camerasrc.c index 566ce4d825..33bb9e09aa 100644 --- a/gst/camerabin2/gstv4l2camerasrc.c +++ b/gst/camerabin2/gstv4l2camerasrc.c @@ -39,7 +39,6 @@ enum PROP_0, PROP_FILTER_CAPS, PROP_VIDEO_SRC, - PROP_VIDEO_SOURCE_FILTER }; #define CAMERABIN_DEFAULT_VF_CAPS "video/x-raw-yuv,format=(fourcc)I420" @@ -82,17 +81,6 @@ gst_v4l2_camera_src_set_property (GObject * object, GST_OBJECT_UNLOCK (self); configure_format (self, self->view_finder_caps); break; - case PROP_VIDEO_SOURCE_FILTER: - if (GST_STATE (self) != GST_STATE_NULL) { - GST_ELEMENT_ERROR (self, CORE, FAILED, - ("camerasrc must be in NULL state when setting the video filter element"), - (NULL)); - } else { - if (self->app_video_filter) - gst_object_unref (self->app_video_filter); - self->app_video_filter = g_value_dup_object (value); - } - break; case PROP_VIDEO_SRC: if (GST_STATE (self) != GST_STATE_NULL) { GST_ELEMENT_ERROR (self, CORE, FAILED, @@ -122,9 +110,6 @@ gst_v4l2_camera_src_get_property (GObject * object, case PROP_FILTER_CAPS: gst_value_set_caps (value, self->view_finder_caps); break; - case PROP_VIDEO_SOURCE_FILTER: - g_value_set_object (value, self->app_video_filter); - break; case PROP_VIDEO_SRC: if (self->src_vid_src) g_value_set_object (value, self->src_vid_src); @@ -251,12 +236,6 @@ gst_v4l2_camera_src_construct_pipeline (GstBaseCameraSrc * bcamsrc) gst_camerabin_create_and_add_element (cbin, "capsfilter"))) goto done; - if (self->app_video_filter) { - if (!gst_camerabin_add_element (cbin, self->app_video_filter)) { - goto done; - } - } - if (!(tee = gst_camerabin_create_and_add_element (cbin, "tee"))) goto done; diff --git a/gst/camerabin2/gstv4l2camerasrc.h b/gst/camerabin2/gstv4l2camerasrc.h index 580af287ae..5229106f7c 100644 --- a/gst/camerabin2/gstv4l2camerasrc.h +++ b/gst/camerabin2/gstv4l2camerasrc.h @@ -81,7 +81,6 @@ struct _GstV4l2CameraSrc /* Application configurable elements */ GstElement *app_vid_src; - GstElement *app_video_filter; /* Caps that videosrc supports */ GstCaps *allowed_caps; From 99210b0a3a241c73267a7f5e481d041728b3f1a2 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Tue, 14 Dec 2010 17:23:10 -0300 Subject: [PATCH 177/448] camerabin2: Rename v4l2camerasrc to wrappercamerabinsrc Use a better name for the element that wraps single pad src element into a 3pad source required by camerabin2. --- gst/camerabin2/Makefile.am | 4 +- gst/camerabin2/gstcamerabin2.c | 3 +- gst/camerabin2/gstplugin.c | 4 +- ...l2camerasrc.c => gstwrappercamerabinsrc.c} | 145 +++++++++--------- ...l2camerasrc.h => gstwrappercamerabinsrc.h} | 42 ++--- tests/check/elements/camerabin2.c | 2 +- 6 files changed, 103 insertions(+), 97 deletions(-) rename gst/camerabin2/{gstv4l2camerasrc.c => gstwrappercamerabinsrc.c} (86%) rename gst/camerabin2/{gstv4l2camerasrc.h => gstwrappercamerabinsrc.h} (66%) diff --git a/gst/camerabin2/Makefile.am b/gst/camerabin2/Makefile.am index 4cb29bfd29..5f8a53dfae 100644 --- a/gst/camerabin2/Makefile.am +++ b/gst/camerabin2/Makefile.am @@ -4,7 +4,7 @@ libgstcamerabin2_la_SOURCES = gstviewfinderbin.c \ gstimagecapturebin.c \ gstvideorecordingbin.c \ camerabingeneral.c \ - gstv4l2camerasrc.c \ + gstwrappercamerabinsrc.c \ gstcamerabin2.c \ gstplugin.c @@ -26,5 +26,5 @@ noinst_HEADERS = gstviewfinderbin.h \ gstimagecapturebin.h \ gstvideorecordingbin.h \ camerabingeneral.h \ - gstv4l2camerasrc.h \ + gstwrappercamerabinsrc.h \ gstcamerabin2.h diff --git a/gst/camerabin2/gstcamerabin2.c b/gst/camerabin2/gstcamerabin2.c index ccb4c1800f..602cf3a954 100644 --- a/gst/camerabin2/gstcamerabin2.c +++ b/gst/camerabin2/gstcamerabin2.c @@ -430,7 +430,8 @@ gst_camera_bin_create_elements (GstCameraBin * camera) if (camera->user_src) { camera->src = gst_object_ref (camera->user_src); } else { - camera->src = gst_element_factory_make ("v4l2camerasrc", "camerasrc"); + camera->src = + gst_element_factory_make ("wrappercamerabinsrc", "camerasrc"); } new_src = TRUE; diff --git a/gst/camerabin2/gstplugin.c b/gst/camerabin2/gstplugin.c index 517f9a6c02..16f20afedb 100644 --- a/gst/camerabin2/gstplugin.c +++ b/gst/camerabin2/gstplugin.c @@ -26,7 +26,7 @@ #include "gstviewfinderbin.h" #include "gstimagecapturebin.h" #include "gstvideorecordingbin.h" -#include "gstv4l2camerasrc.h" +#include "gstwrappercamerabinsrc.h" #include "gstcamerabin2.h" static gboolean @@ -38,7 +38,7 @@ plugin_init (GstPlugin * plugin) return FALSE; if (!gst_video_recording_bin_plugin_init (plugin)) return FALSE; - if (!gst_v4l2_camera_src_plugin_init (plugin)) + if (!gst_wrapper_camera_bin_src_plugin_init (plugin)) return FALSE; if (!gst_camera_bin_plugin_init (plugin)) return FALSE; diff --git a/gst/camerabin2/gstv4l2camerasrc.c b/gst/camerabin2/gstwrappercamerabinsrc.c similarity index 86% rename from gst/camerabin2/gstv4l2camerasrc.c rename to gst/camerabin2/gstwrappercamerabinsrc.c index 33bb9e09aa..163327f341 100644 --- a/gst/camerabin2/gstv4l2camerasrc.c +++ b/gst/camerabin2/gstwrappercamerabinsrc.c @@ -20,18 +20,17 @@ /** - * SECTION:element-v4l2camerasrc + * SECTION:element-wrappercamerabinsrc * - * A camera src element for camerabin.. currently uses v4l2 directly. - * It could be worthwhile to make this subclassable, so that other - * camera elements with a single src pad could re-use this.. + * A camera bin src element that wraps a default video source with a single + * pad into the 3pad model that camerabin2 expects. */ #ifdef HAVE_CONFIG_H # include #endif -#include "gstv4l2camerasrc.h" +#include "gstwrappercamerabinsrc.h" #include "camerabingeneral.h" enum @@ -46,32 +45,33 @@ enum /* Using "bilinear" as default zoom method */ #define CAMERABIN_DEFAULT_ZOOM_METHOD 1 -GST_DEBUG_CATEGORY (v4l2_camera_src_debug); -#define GST_CAT_DEFAULT v4l2_camera_src_debug +GST_DEBUG_CATEGORY (wrapper_camera_bin_src_debug); +#define GST_CAT_DEFAULT wrapper_camera_bin_src_debug -GST_BOILERPLATE (GstV4l2CameraSrc, gst_v4l2_camera_src, GstBaseCameraSrc, - GST_TYPE_BASE_CAMERA_SRC); +GST_BOILERPLATE (GstWrapperCameraBinSrc, gst_wrapper_camera_bin_src, + GstBaseCameraSrc, GST_TYPE_BASE_CAMERA_SRC); -static void configure_format (GstV4l2CameraSrc * self, GstCaps * caps); -static void set_capsfilter_caps (GstV4l2CameraSrc * self, GstCaps * new_caps); +static void configure_format (GstWrapperCameraBinSrc * self, GstCaps * caps); +static void set_capsfilter_caps (GstWrapperCameraBinSrc * self, + GstCaps * new_caps); static void -gst_v4l2_camera_src_dispose (GObject * object) +gst_wrapper_camera_bin_src_dispose (GObject * object) { G_OBJECT_CLASS (parent_class)->dispose (object); } static void -gst_v4l2_camera_src_finalize (GstV4l2CameraSrc * self) +gst_wrapper_camera_bin_src_finalize (GstWrapperCameraBinSrc * self) { G_OBJECT_CLASS (parent_class)->finalize ((GObject *) (self)); } static void -gst_v4l2_camera_src_set_property (GObject * object, +gst_wrapper_camera_bin_src_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec) { - GstV4l2CameraSrc *self = GST_V4L2_CAMERA_SRC (object); + GstWrapperCameraBinSrc *self = GST_WRAPPER_CAMERA_BIN_SRC (object); switch (prop_id) { case PROP_FILTER_CAPS: @@ -101,10 +101,10 @@ gst_v4l2_camera_src_set_property (GObject * object, } static void -gst_v4l2_camera_src_get_property (GObject * object, +gst_wrapper_camera_bin_src_get_property (GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) { - GstV4l2CameraSrc *self = GST_V4L2_CAMERA_SRC (object); + GstWrapperCameraBinSrc *self = GST_WRAPPER_CAMERA_BIN_SRC (object); switch (prop_id) { case PROP_FILTER_CAPS: @@ -123,15 +123,15 @@ gst_v4l2_camera_src_get_property (GObject * object, } /** - * gst_v4l2_camera_src_imgsrc_probe: + * gst_wrapper_camera_bin_src_imgsrc_probe: * * Buffer probe called before sending each buffer to image queue. */ static gboolean -gst_v4l2_camera_src_imgsrc_probe (GstPad * pad, GstBuffer * buffer, +gst_wrapper_camera_bin_src_imgsrc_probe (GstPad * pad, GstBuffer * buffer, gpointer data) { - GstV4l2CameraSrc *self = GST_V4L2_CAMERA_SRC (data); + GstWrapperCameraBinSrc *self = GST_WRAPPER_CAMERA_BIN_SRC (data); GstBaseCameraSrc *camerasrc = GST_BASE_CAMERA_SRC (data); gboolean ret = FALSE; @@ -148,15 +148,15 @@ gst_v4l2_camera_src_imgsrc_probe (GstPad * pad, GstBuffer * buffer, } /** - * gst_v4l2_camera_src_vidsrc_probe: + * gst_wrapper_camera_bin_src_vidsrc_probe: * * Buffer probe called before sending each buffer to image queue. */ static gboolean -gst_v4l2_camera_src_vidsrc_probe (GstPad * pad, GstBuffer * buffer, +gst_wrapper_camera_bin_src_vidsrc_probe (GstPad * pad, GstBuffer * buffer, gpointer data) { - GstV4l2CameraSrc *self = GST_V4L2_CAMERA_SRC (data); + GstWrapperCameraBinSrc *self = GST_WRAPPER_CAMERA_BIN_SRC (data); GstBaseCameraSrc *camerasrc = GST_BASE_CAMERA_SRC_CAST (self); gboolean ret = FALSE; @@ -190,7 +190,7 @@ gst_v4l2_camera_src_vidsrc_probe (GstPad * pad, GstBuffer * buffer, } /** - * gst_v4l2_camera_src_construct_pipeline: + * gst_wrapper_camera_bin_src_construct_pipeline: * @bcamsrc: camerasrc object * * This function creates and links the elements of the camerasrc bin @@ -199,9 +199,9 @@ gst_v4l2_camera_src_vidsrc_probe (GstPad * pad, GstBuffer * buffer, * Returns: TRUE, if elements were successfully created, FALSE otherwise */ static gboolean -gst_v4l2_camera_src_construct_pipeline (GstBaseCameraSrc * bcamsrc) +gst_wrapper_camera_bin_src_construct_pipeline (GstBaseCameraSrc * bcamsrc) { - GstV4l2CameraSrc *self = GST_V4L2_CAMERA_SRC (bcamsrc); + GstWrapperCameraBinSrc *self = GST_WRAPPER_CAMERA_BIN_SRC (bcamsrc); GstBin *cbin = GST_BIN (bcamsrc); GstElement *tee; gboolean ret = FALSE; @@ -244,9 +244,9 @@ gst_v4l2_camera_src_construct_pipeline (GstBaseCameraSrc * bcamsrc) self->tee_video_srcpad = gst_element_get_request_pad (tee, "src%d"); gst_pad_add_buffer_probe (self->tee_image_srcpad, - G_CALLBACK (gst_v4l2_camera_src_imgsrc_probe), self); + G_CALLBACK (gst_wrapper_camera_bin_src_imgsrc_probe), self); gst_pad_add_buffer_probe (self->tee_video_srcpad, - G_CALLBACK (gst_v4l2_camera_src_vidsrc_probe), self); + G_CALLBACK (gst_wrapper_camera_bin_src_vidsrc_probe), self); /* hook-up the ghostpads */ gst_ghost_pad_set_target (GST_GHOST_PAD (self->vfsrc), self->tee_vf_srcpad); @@ -317,7 +317,7 @@ no_pad: * resolution in @filter_caps. Set found frame rate to @filter_caps. */ static void -set_allowed_framerate (GstV4l2CameraSrc * self, GstCaps * filter_caps) +set_allowed_framerate (GstWrapperCameraBinSrc * self, GstCaps * filter_caps) { GstBaseCameraSrc *bcamsrc = GST_BASE_CAMERA_SRC (self); GstStructure *structure; @@ -378,7 +378,7 @@ set_allowed_framerate (GstV4l2CameraSrc * self, GstCaps * filter_caps) } /** - * gst_v4l2_camera_src_setup_pipeline: + * gst_wrapper_camera_bin_src_setup_pipeline: * @bcamsrc: camerasrc object * * This function updates camerabin capsfilters according @@ -386,9 +386,9 @@ set_allowed_framerate (GstV4l2CameraSrc * self, GstCaps * filter_caps) * to camerabin. */ static gboolean -gst_v4l2_camera_src_setup_pipeline (GstBaseCameraSrc * bcamsrc) +gst_wrapper_camera_bin_src_setup_pipeline (GstBaseCameraSrc * bcamsrc) { - GstV4l2CameraSrc *self = GST_V4L2_CAMERA_SRC (bcamsrc); + GstWrapperCameraBinSrc *self = GST_WRAPPER_CAMERA_BIN_SRC (bcamsrc); GstStructure *st; GstCaps *new_caps; gboolean detect_framerate = FALSE; @@ -478,7 +478,7 @@ copy_missing_fields (GQuark field_id, const GValue * value, gpointer user_data) * */ static void -adapt_image_capture (GstV4l2CameraSrc * self, GstCaps * in_caps) +adapt_image_capture (GstWrapperCameraBinSrc * self, GstCaps * in_caps) { GstBaseCameraSrc *bcamsrc = GST_BASE_CAMERA_SRC (self); GstStructure *in_st, *new_st, *req_st; @@ -568,7 +568,7 @@ adapt_image_capture (GstV4l2CameraSrc * self, GstCaps * in_caps) static void img_capture_prepared (gpointer data, GstCaps * caps) { - GstV4l2CameraSrc *self = GST_V4L2_CAMERA_SRC (data); + GstWrapperCameraBinSrc *self = GST_WRAPPER_CAMERA_BIN_SRC (data); GST_INFO_OBJECT (self, "image capture prepared"); @@ -581,7 +581,7 @@ img_capture_prepared (gpointer data, GstCaps * caps) } static void -set_image_capture_caps (GstV4l2CameraSrc * self, gint width, gint height) +set_image_capture_caps (GstWrapperCameraBinSrc * self, gint width, gint height) { GstStructure *structure; GstCaps *new_caps = NULL; @@ -608,7 +608,7 @@ set_image_capture_caps (GstV4l2CameraSrc * self, gint width, gint height) * */ static gboolean -start_image_capture (GstV4l2CameraSrc * self) +start_image_capture (GstWrapperCameraBinSrc * self) { GstBaseCameraSrc *bcamsrc = GST_BASE_CAMERA_SRC (self); GstPhotography *photography = gst_base_camera_src_get_photography (bcamsrc); @@ -645,7 +645,8 @@ start_image_capture (GstV4l2CameraSrc * self) } static gboolean -gst_v4l2_camera_src_set_mode (GstBaseCameraSrc * bcamsrc, GstCameraBinMode mode) +gst_wrapper_camera_bin_src_set_mode (GstBaseCameraSrc * bcamsrc, + GstCameraBinMode mode) { GstPhotography *photography = gst_base_camera_src_get_photography (bcamsrc); @@ -659,7 +660,7 @@ gst_v4l2_camera_src_set_mode (GstBaseCameraSrc * bcamsrc, GstCameraBinMode mode) } static gboolean -set_videosrc_zoom (GstV4l2CameraSrc * self, gint zoom) +set_videosrc_zoom (GstWrapperCameraBinSrc * self, gint zoom) { gboolean ret = FALSE; @@ -673,7 +674,7 @@ set_videosrc_zoom (GstV4l2CameraSrc * self, gint zoom) } static gboolean -set_element_zoom (GstV4l2CameraSrc * self, gint zoom) +set_element_zoom (GstWrapperCameraBinSrc * self, gint zoom) { gboolean ret = FALSE; GstBaseCameraSrc *bcamsrc = GST_BASE_CAMERA_SRC (self); @@ -720,9 +721,9 @@ set_element_zoom (GstV4l2CameraSrc * self, gint zoom) } static void -gst_v4l2_camera_src_set_zoom (GstBaseCameraSrc * bcamsrc, gint zoom) +gst_wrapper_camera_bin_src_set_zoom (GstBaseCameraSrc * bcamsrc, gint zoom) { - GstV4l2CameraSrc *self = GST_V4L2_CAMERA_SRC (bcamsrc); + GstWrapperCameraBinSrc *self = GST_WRAPPER_CAMERA_BIN_SRC (bcamsrc); GST_INFO_OBJECT (self, "setting zoom %d", zoom); @@ -737,9 +738,9 @@ gst_v4l2_camera_src_set_zoom (GstBaseCameraSrc * bcamsrc, gint zoom) } static GstCaps * -gst_v4l2_camera_src_get_allowed_input_caps (GstBaseCameraSrc * bcamsrc) +gst_wrapper_camera_bin_src_get_allowed_input_caps (GstBaseCameraSrc * bcamsrc) { - GstV4l2CameraSrc *self = GST_V4L2_CAMERA_SRC (bcamsrc); + GstWrapperCameraBinSrc *self = GST_WRAPPER_CAMERA_BIN_SRC (bcamsrc); GstCaps *caps = NULL; GstPad *pad = NULL, *peer_pad = NULL; GstState state; @@ -811,7 +812,7 @@ failed: * Configure internal video format for camerabin. */ static void -configure_format (GstV4l2CameraSrc * self, GstCaps * caps) +configure_format (GstWrapperCameraBinSrc * self, GstCaps * caps) { GstBaseCameraSrc *bcamsrc = GST_BASE_CAMERA_SRC (self); GstStructure *st; @@ -837,7 +838,7 @@ configure_format (GstV4l2CameraSrc * self, GstCaps * caps) * scale frames for showing them in view finder. */ static void -update_aspect_filter (GstV4l2CameraSrc * self, GstCaps * new_caps) +update_aspect_filter (GstWrapperCameraBinSrc * self, GstCaps * new_caps) { // XXX why not instead add a preserve-aspect-ratio property to videoscale? #if 0 @@ -926,7 +927,7 @@ update_aspect_filter (GstV4l2CameraSrc * self, GstCaps * new_caps) * Set given caps to camerabin capsfilters. */ static void -set_capsfilter_caps (GstV4l2CameraSrc * self, GstCaps * new_caps) +set_capsfilter_caps (GstWrapperCameraBinSrc * self, GstCaps * new_caps) { GST_INFO_OBJECT (self, "new_caps:%" GST_PTR_FORMAT, new_caps); @@ -944,9 +945,9 @@ set_capsfilter_caps (GstV4l2CameraSrc * self, GstCaps * new_caps) } static gboolean -gst_v4l2_camera_src_start_capture (GstBaseCameraSrc * camerasrc) +gst_wrapper_camera_bin_src_start_capture (GstBaseCameraSrc * camerasrc) { - GstV4l2CameraSrc *src = GST_V4L2_CAMERA_SRC (camerasrc); + GstWrapperCameraBinSrc *src = GST_WRAPPER_CAMERA_BIN_SRC (camerasrc); /* TODO shoud we access this directly? Maybe a macro is better? */ if (camerasrc->mode == MODE_IMAGE) { @@ -964,9 +965,9 @@ gst_v4l2_camera_src_start_capture (GstBaseCameraSrc * camerasrc) } static void -gst_v4l2_camera_src_stop_capture (GstBaseCameraSrc * camerasrc) +gst_wrapper_camera_bin_src_stop_capture (GstBaseCameraSrc * camerasrc) { - GstV4l2CameraSrc *src = GST_V4L2_CAMERA_SRC (camerasrc); + GstWrapperCameraBinSrc *src = GST_WRAPPER_CAMERA_BIN_SRC (camerasrc); /* TODO shoud we access this directly? Maybe a macro is better? */ if (camerasrc->mode == MODE_VIDEO) { @@ -984,12 +985,12 @@ gst_v4l2_camera_src_stop_capture (GstBaseCameraSrc * camerasrc) } static void -gst_v4l2_camera_src_base_init (gpointer g_class) +gst_wrapper_camera_bin_src_base_init (gpointer g_class) { GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class); - GST_DEBUG_CATEGORY_INIT (v4l2_camera_src_debug, "v4l2camerasrc", 0, - "V4l2 camera src"); + GST_DEBUG_CATEGORY_INIT (wrapper_camera_bin_src_debug, "wrappercamerabinsrc", + 0, "V4l2 camera src"); gst_element_class_set_details_simple (gstelement_class, "V4l2 camera src element for camerabin", "Source/Video", @@ -997,7 +998,7 @@ gst_v4l2_camera_src_base_init (gpointer g_class) } static void -gst_v4l2_camera_src_class_init (GstV4l2CameraSrcClass * klass) +gst_wrapper_camera_bin_src_class_init (GstWrapperCameraBinSrcClass * klass) { GObjectClass *gobject_class; GstBaseCameraSrcClass *gstbasecamerasrc_class; @@ -1005,10 +1006,11 @@ gst_v4l2_camera_src_class_init (GstV4l2CameraSrcClass * klass) gobject_class = G_OBJECT_CLASS (klass); gstbasecamerasrc_class = GST_BASE_CAMERA_SRC_CLASS (klass); - gobject_class->dispose = gst_v4l2_camera_src_dispose; - gobject_class->finalize = (GObjectFinalizeFunc) gst_v4l2_camera_src_finalize; - gobject_class->set_property = gst_v4l2_camera_src_set_property; - gobject_class->get_property = gst_v4l2_camera_src_get_property; + gobject_class->dispose = gst_wrapper_camera_bin_src_dispose; + gobject_class->finalize = + (GObjectFinalizeFunc) gst_wrapper_camera_bin_src_finalize; + gobject_class->set_property = gst_wrapper_camera_bin_src_set_property; + gobject_class->get_property = gst_wrapper_camera_bin_src_get_property; /* g_object_class_install_property .... */ g_object_class_install_property (gobject_class, PROP_VIDEO_SRC, @@ -1017,19 +1019,22 @@ gst_v4l2_camera_src_class_init (GstV4l2CameraSrcClass * klass) GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); gstbasecamerasrc_class->construct_pipeline = - gst_v4l2_camera_src_construct_pipeline; - gstbasecamerasrc_class->setup_pipeline = gst_v4l2_camera_src_setup_pipeline; - gstbasecamerasrc_class->set_zoom = gst_v4l2_camera_src_set_zoom; - gstbasecamerasrc_class->set_mode = gst_v4l2_camera_src_set_mode; + gst_wrapper_camera_bin_src_construct_pipeline; + gstbasecamerasrc_class->setup_pipeline = + gst_wrapper_camera_bin_src_setup_pipeline; + gstbasecamerasrc_class->set_zoom = gst_wrapper_camera_bin_src_set_zoom; + gstbasecamerasrc_class->set_mode = gst_wrapper_camera_bin_src_set_mode; gstbasecamerasrc_class->get_allowed_input_caps = - gst_v4l2_camera_src_get_allowed_input_caps; - gstbasecamerasrc_class->start_capture = gst_v4l2_camera_src_start_capture; - gstbasecamerasrc_class->stop_capture = gst_v4l2_camera_src_stop_capture; + gst_wrapper_camera_bin_src_get_allowed_input_caps; + gstbasecamerasrc_class->start_capture = + gst_wrapper_camera_bin_src_start_capture; + gstbasecamerasrc_class->stop_capture = + gst_wrapper_camera_bin_src_stop_capture; } static void -gst_v4l2_camera_src_init (GstV4l2CameraSrc * self, - GstV4l2CameraSrcClass * klass) +gst_wrapper_camera_bin_src_init (GstWrapperCameraBinSrc * self, + GstWrapperCameraBinSrcClass * klass) { self->vfsrc = gst_ghost_pad_new_no_target (GST_BASE_CAMERA_SRC_VIEWFINDER_PAD_NAME, @@ -1053,8 +1058,8 @@ gst_v4l2_camera_src_init (GstV4l2CameraSrc * self, } gboolean -gst_v4l2_camera_src_plugin_init (GstPlugin * plugin) +gst_wrapper_camera_bin_src_plugin_init (GstPlugin * plugin) { - return gst_element_register (plugin, "v4l2camerasrc", GST_RANK_NONE, - gst_v4l2_camera_src_get_type ()); + return gst_element_register (plugin, "wrappercamerabinsrc", GST_RANK_NONE, + gst_wrapper_camera_bin_src_get_type ()); } diff --git a/gst/camerabin2/gstv4l2camerasrc.h b/gst/camerabin2/gstwrappercamerabinsrc.h similarity index 66% rename from gst/camerabin2/gstv4l2camerasrc.h rename to gst/camerabin2/gstwrappercamerabinsrc.h index 5229106f7c..c06a9bbce7 100644 --- a/gst/camerabin2/gstv4l2camerasrc.h +++ b/gst/camerabin2/gstwrappercamerabinsrc.h @@ -19,27 +19,27 @@ */ -#ifndef __GST_V4L2_CAMERA_SRC_H__ -#define __GST_V4L2_CAMERA_SRC_H__ +#ifndef __GST_WRAPPER_CAMERA_BIN_SRC_H__ +#define __GST_WRAPPER_CAMERA_BIN_SRC_H__ #include #include G_BEGIN_DECLS -#define GST_TYPE_V4L2_CAMERA_SRC \ - (gst_v4l2_camera_src_get_type()) -#define GST_V4L2_CAMERA_SRC(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_V4L2_CAMERA_SRC,GstV4l2CameraSrc)) -#define GST_V4L2_CAMERA_SRC_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_V4L2_CAMERA_SRC,GstV4l2CameraSrcClass)) -#define GST_IS_V4L2_CAMERA_SRC(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_V4L2_CAMERA_SRC)) -#define GST_IS_V4L2_CAMERA_SRC_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_V4L2_CAMERA_SRC)) - GType gst_v4l2_camera_src_get_type (void); +#define GST_TYPE_WRAPPER_CAMERA_BIN_SRC \ + (gst_wrapper_camera_bin_src_get_type()) +#define GST_WRAPPER_CAMERA_BIN_SRC(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_WRAPPER_CAMERA_BIN_SRC,GstWrapperCameraBinSrc)) +#define GST_WRAPPER_CAMERA_BIN_SRC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_WRAPPER_CAMERA_BIN_SRC,GstWrapperCameraBinSrcClass)) +#define GST_IS_WRAPPER_CAMERA_BIN_SRC(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_WRAPPER_CAMERA_BIN_SRC)) +#define GST_IS_WRAPPER_CAMERA_BIN_SRC_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_WRAPPER_CAMERA_BIN_SRC)) + GType gst_wrapper_camera_bin_src_get_type (void); -typedef struct _GstV4l2CameraSrc GstV4l2CameraSrc; -typedef struct _GstV4l2CameraSrcClass GstV4l2CameraSrcClass; +typedef struct _GstWrapperCameraBinSrc GstWrapperCameraBinSrc; +typedef struct _GstWrapperCameraBinSrcClass GstWrapperCameraBinSrcClass; enum GstVideoRecordingStatus { GST_VIDEO_RECORDING_STATUS_DONE, @@ -50,10 +50,10 @@ enum GstVideoRecordingStatus { /** - * GstV4l2CameraSrc: + * GstWrapperCameraBinSrc: * */ -struct _GstV4l2CameraSrc +struct _GstWrapperCameraBinSrc { GstBaseCameraSrc parent; @@ -102,14 +102,14 @@ struct _GstV4l2CameraSrc /** - * GstV4l2CameraSrcClass: + * GstWrapperCameraBinSrcClass: * */ -struct _GstV4l2CameraSrcClass +struct _GstWrapperCameraBinSrcClass { GstBaseCameraSrcClass parent; }; -gboolean gst_v4l2_camera_src_plugin_init (GstPlugin * plugin); +gboolean gst_wrapper_camera_bin_src_plugin_init (GstPlugin * plugin); -#endif /* __GST_V4L2_CAMERA_SRC_H__ */ +#endif /* __GST_WRAPPER_CAMERA_BIN_SRC_H__ */ diff --git a/tests/check/elements/camerabin2.c b/tests/check/elements/camerabin2.c index 776333085d..0d079529d8 100644 --- a/tests/check/elements/camerabin2.c +++ b/tests/check/elements/camerabin2.c @@ -258,7 +258,7 @@ setup (void) camera = gst_check_setup_element ("camerabin2"); fakevideosink = gst_check_setup_element ("fakesink"); - src = gst_check_setup_element ("v4l2camerasrc"); + src = gst_check_setup_element ("wrappercamerabinsrc"); testsrc = gst_check_setup_element ("videotestsrc"); g_object_set (G_OBJECT (testsrc), "is-live", TRUE, NULL); From 029e63a31eeaba98ce7a6239cef25c8324331166 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Wed, 15 Dec 2010 14:07:15 -0300 Subject: [PATCH 178/448] wrappercamerabinsrc: Remove unused variable Remove wait_for_prepara variable that wasn't being used --- gst/camerabin2/gstwrappercamerabinsrc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/gst/camerabin2/gstwrappercamerabinsrc.c b/gst/camerabin2/gstwrappercamerabinsrc.c index 163327f341..b5d2af78b9 100644 --- a/gst/camerabin2/gstwrappercamerabinsrc.c +++ b/gst/camerabin2/gstwrappercamerabinsrc.c @@ -612,10 +612,9 @@ start_image_capture (GstWrapperCameraBinSrc * self) { GstBaseCameraSrc *bcamsrc = GST_BASE_CAMERA_SRC (self); GstPhotography *photography = gst_base_camera_src_get_photography (bcamsrc); - gboolean wait_for_prepare = FALSE, ret = FALSE; + gboolean ret = FALSE; if (photography) { - wait_for_prepare = TRUE; if (!self->image_capture_caps || self->image_capture_caps_update) { if (bcamsrc->image_capture_width && bcamsrc->image_capture_height) { From 539f10f4d99e1a074881289254d1d109159cf9e5 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Wed, 15 Dec 2010 22:35:16 -0300 Subject: [PATCH 179/448] basecamerasrc: More cleanup Remove old legacy code copied from camerabin(1) that should be handled by caps negotiation on camerabin2 --- .../gst/basecamerabinsrc/gstbasecamerasrc.c | 75 ----- .../gst/basecamerabinsrc/gstbasecamerasrc.h | 18 -- gst/camerabin2/gstwrappercamerabinsrc.c | 266 +----------------- 3 files changed, 3 insertions(+), 356 deletions(-) diff --git a/gst-libs/gst/basecamerabinsrc/gstbasecamerasrc.c b/gst-libs/gst/basecamerabinsrc/gstbasecamerasrc.c index a906840678..a05418c588 100644 --- a/gst-libs/gst/basecamerabinsrc/gstbasecamerasrc.c +++ b/gst-libs/gst/basecamerabinsrc/gstbasecamerasrc.c @@ -215,74 +215,6 @@ gst_base_camera_src_get_allowed_input_caps (GstBaseCameraSrc * self) return bclass->get_allowed_input_caps (self); } -/** - * gst_base_camera_src_find_better_framerate: - * @self: camerasrc object - * @st: structure that contains framerate candidates - * @orig_framerate: best framerate so far - * - * Looks for framerate better than @orig_framerate from @st structure. - * In night mode lowest framerate is considered best, otherwise highest is - * best. - * - * Returns: @orig_framerate or better if found - */ -const GValue * -gst_base_camera_src_find_better_framerate (GstBaseCameraSrc * self, - GstStructure * st, const GValue * orig_framerate) -{ - const GValue *framerate = NULL; - guint i, i_best, list_size; - gint res, comparison; - - if (self->night_mode) { - GST_LOG_OBJECT (self, "finding min framerate in %" GST_PTR_FORMAT, st); - comparison = GST_VALUE_LESS_THAN; - } else { - GST_LOG_OBJECT (self, "finding max framerate in %" GST_PTR_FORMAT, st); - comparison = GST_VALUE_GREATER_THAN; - } - - if (gst_structure_has_field (st, "framerate")) { - framerate = gst_structure_get_value (st, "framerate"); - /* Handle framerate lists */ - if (GST_VALUE_HOLDS_LIST (framerate)) { - list_size = gst_value_list_get_size (framerate); - GST_LOG_OBJECT (self, "finding framerate from list"); - for (i = 0, i_best = 0; i < list_size; i++) { - res = gst_value_compare (gst_value_list_get_value (framerate, i), - gst_value_list_get_value (framerate, i_best)); - if (comparison == res) { - i_best = i; - } - } - GST_LOG_OBJECT (self, "found best framerate from index %d", i_best); - framerate = gst_value_list_get_value (framerate, i_best); - } - /* Handle framerate ranges */ - if (GST_VALUE_HOLDS_FRACTION_RANGE (framerate)) { - if (self->night_mode) { - GST_LOG_OBJECT (self, "getting min framerate from range"); - framerate = gst_value_get_fraction_range_min (framerate); - } else { - GST_LOG_OBJECT (self, "getting max framerate from range"); - framerate = gst_value_get_fraction_range_max (framerate); - } - } - } - - /* Check if we found better framerate */ - if (orig_framerate && framerate) { - res = gst_value_compare (orig_framerate, framerate); - if (comparison == res) { - GST_LOG_OBJECT (self, "original framerate was the best"); - framerate = orig_framerate; - } - } - - return framerate; -} - static void gst_base_camera_src_start_capture (GstBaseCameraSrc * src) { @@ -537,15 +469,8 @@ gst_base_camera_src_init (GstBaseCameraSrc * self, self->width = DEFAULT_WIDTH; self->height = DEFAULT_HEIGHT; self->zoom = DEFAULT_ZOOM; - self->image_capture_width = 0; - self->image_capture_height = 0; self->mode = MODE_IMAGE; - self->night_mode = FALSE; - - self->fps_n = DEFAULT_FPS_N; - self->fps_d = DEFAULT_FPS_D; - self->capturing = FALSE; self->capturing_mutex = g_mutex_new (); } diff --git a/gst-libs/gst/basecamerabinsrc/gstbasecamerasrc.h b/gst-libs/gst/basecamerabinsrc/gstbasecamerasrc.h index dd74ba81a8..8ab0008048 100644 --- a/gst-libs/gst/basecamerabinsrc/gstbasecamerasrc.h +++ b/gst-libs/gst/basecamerabinsrc/gstbasecamerasrc.h @@ -64,8 +64,6 @@ struct _GstBaseCameraSrc gboolean capturing; GMutex *capturing_mutex; - /* XXX preview pads? */ - /* Resolution of the buffers configured to camerabin */ gint width; gint height; @@ -73,19 +71,6 @@ struct _GstBaseCameraSrc /* The digital zoom (from 100% to 1000%) */ gint zoom; - /* Image capture resolution */ - gint image_capture_width; - gint image_capture_height; - - /* Frames per second configured to camerabin */ - gint fps_n; - gint fps_d; - - /* Night mode handling */ - gboolean night_mode; - gint pre_night_fps_n; - gint pre_night_fps_d; - gpointer _gst_reserved[GST_PADDING_LARGE]; }; @@ -136,9 +121,6 @@ GstColorBalance * gst_base_camera_src_get_color_balance (GstBaseCameraSrc *self) gboolean gst_base_camera_src_set_mode (GstBaseCameraSrc *self, GstCameraBinMode mode); void gst_base_camera_src_setup_zoom (GstBaseCameraSrc * self); GstCaps * gst_base_camera_src_get_allowed_input_caps (GstBaseCameraSrc * self); -const GValue * gst_base_camera_src_find_better_framerate ( - GstBaseCameraSrc * self, GstStructure * st, const GValue * orig_framerate); - void gst_base_camera_src_finish_capture (GstBaseCameraSrc *self); diff --git a/gst/camerabin2/gstwrappercamerabinsrc.c b/gst/camerabin2/gstwrappercamerabinsrc.c index b5d2af78b9..bcbddc6cfa 100644 --- a/gst/camerabin2/gstwrappercamerabinsrc.c +++ b/gst/camerabin2/gstwrappercamerabinsrc.c @@ -36,7 +36,6 @@ enum { PROP_0, - PROP_FILTER_CAPS, PROP_VIDEO_SRC, }; @@ -51,7 +50,6 @@ GST_DEBUG_CATEGORY (wrapper_camera_bin_src_debug); GST_BOILERPLATE (GstWrapperCameraBinSrc, gst_wrapper_camera_bin_src, GstBaseCameraSrc, GST_TYPE_BASE_CAMERA_SRC); -static void configure_format (GstWrapperCameraBinSrc * self, GstCaps * caps); static void set_capsfilter_caps (GstWrapperCameraBinSrc * self, GstCaps * new_caps); @@ -74,13 +72,6 @@ gst_wrapper_camera_bin_src_set_property (GObject * object, GstWrapperCameraBinSrc *self = GST_WRAPPER_CAMERA_BIN_SRC (object); switch (prop_id) { - case PROP_FILTER_CAPS: - GST_OBJECT_LOCK (self); - gst_caps_replace (&self->view_finder_caps, - (GstCaps *) gst_value_get_caps (value)); - GST_OBJECT_UNLOCK (self); - configure_format (self, self->view_finder_caps); - break; case PROP_VIDEO_SRC: if (GST_STATE (self) != GST_STATE_NULL) { GST_ELEMENT_ERROR (self, CORE, FAILED, @@ -107,9 +98,6 @@ gst_wrapper_camera_bin_src_get_property (GObject * object, GstWrapperCameraBinSrc *self = GST_WRAPPER_CAMERA_BIN_SRC (object); switch (prop_id) { - case PROP_FILTER_CAPS: - gst_value_set_caps (value, self->view_finder_caps); - break; case PROP_VIDEO_SRC: if (self->src_vid_src) g_value_set_object (value, self->src_vid_src); @@ -265,195 +253,6 @@ done: return ret; } -/** - * get_srcpad_current_format: - * @element: element to get the format from - * - * Helper function to get the negotiated fourcc - * format from @element src pad. - * - * Returns: negotiated format (fourcc), 0 if not found - */ -static guint32 -get_srcpad_current_format (GstElement * element) -{ - GstPad *srcpad = NULL; - GstCaps *srccaps = NULL; - GstStructure *structure; - guint32 format = 0; - - g_return_val_if_fail (element != NULL, 0); - - if ((srcpad = gst_element_get_static_pad (element, "src")) == NULL) { - goto no_pad; - } - - if ((srccaps = gst_pad_get_negotiated_caps (srcpad)) == NULL) { - goto no_caps; - } - - GST_LOG ("negotiated caps %" GST_PTR_FORMAT, srccaps); - - structure = gst_caps_get_structure (srccaps, 0); - if (gst_structure_has_field (structure, "format")) { - gst_structure_get_fourcc (structure, "format", &format); - } - - gst_caps_unref (srccaps); -no_caps: - gst_object_unref (srcpad); -no_pad: - GST_DEBUG ("current format for %" GST_PTR_FORMAT ": %" GST_FOURCC_FORMAT, - element, GST_FOURCC_ARGS (format)); - return format; -} - -/** - * set_allowed_framerate: - * @self: camerasrc object - * @filter_caps: update allowed framerate to these caps - * - * Find allowed frame rate from video source that matches with - * resolution in @filter_caps. Set found frame rate to @filter_caps. - */ -static void -set_allowed_framerate (GstWrapperCameraBinSrc * self, GstCaps * filter_caps) -{ - GstBaseCameraSrc *bcamsrc = GST_BASE_CAMERA_SRC (self); - GstStructure *structure; - GstCaps *allowed_caps = NULL, *intersect = NULL, *tmp_caps = NULL; - const GValue *framerate = NULL; - guint caps_size, i; - guint32 format = 0; - - GST_INFO_OBJECT (self, "filter caps:%" GST_PTR_FORMAT, filter_caps); - - structure = gst_structure_copy (gst_caps_get_structure (filter_caps, 0)); - - /* Set fourcc format according to current videosrc format */ - format = get_srcpad_current_format (self->src_vid_src); - if (format) { - GST_DEBUG_OBJECT (self, - "using format %" GST_FOURCC_FORMAT " for matching", - GST_FOURCC_ARGS (format)); - gst_structure_set (structure, "format", GST_TYPE_FOURCC, format, NULL); - } else { - GST_DEBUG_OBJECT (self, "not matching against fourcc format"); - gst_structure_remove_field (structure, "format"); - } - - tmp_caps = gst_caps_new_full (structure, NULL); - - /* Get supported caps from video src that matches with new filter caps */ - allowed_caps = gst_base_camera_src_get_allowed_input_caps (bcamsrc); - intersect = gst_caps_intersect (allowed_caps, tmp_caps); - GST_INFO_OBJECT (self, "intersect caps:%" GST_PTR_FORMAT, intersect); - - /* Find the best framerate from the caps */ - caps_size = gst_caps_get_size (intersect); - for (i = 0; i < caps_size; i++) { - structure = gst_caps_get_structure (intersect, i); - framerate = gst_base_camera_src_find_better_framerate (bcamsrc, - structure, framerate); - } - - /* Set found frame rate to original caps */ - if (GST_VALUE_HOLDS_FRACTION (framerate)) { - gst_caps_set_simple (filter_caps, - "framerate", GST_TYPE_FRACTION, - gst_value_get_fraction_numerator (framerate), - gst_value_get_fraction_denominator (framerate), NULL); - } - - /* Unref helper caps */ - if (allowed_caps) { - gst_caps_unref (allowed_caps); - } - if (intersect) { - gst_caps_unref (intersect); - } - if (tmp_caps) { - gst_caps_unref (tmp_caps); - } -} - -/** - * gst_wrapper_camera_bin_src_setup_pipeline: - * @bcamsrc: camerasrc object - * - * This function updates camerabin capsfilters according - * to fps, resolution and zoom that have been configured - * to camerabin. - */ -static gboolean -gst_wrapper_camera_bin_src_setup_pipeline (GstBaseCameraSrc * bcamsrc) -{ - GstWrapperCameraBinSrc *self = GST_WRAPPER_CAMERA_BIN_SRC (bcamsrc); - GstStructure *st; - GstCaps *new_caps; - gboolean detect_framerate = FALSE; - - /* clear video update status */ -//XXX self->video_capture_caps_update = FALSE; - - if (!self->view_finder_caps) { - st = gst_structure_from_string (CAMERABIN_DEFAULT_VF_CAPS, NULL); - } else { - st = gst_structure_copy (gst_caps_get_structure (self->view_finder_caps, - 0)); - } - - if (bcamsrc->width > 0 && bcamsrc->height > 0) { - gst_structure_set (st, - "width", G_TYPE_INT, bcamsrc->width, - "height", G_TYPE_INT, bcamsrc->height, NULL); - } - - if (bcamsrc->fps_n > 0 && bcamsrc->fps_d > 0) { - if (bcamsrc->night_mode) { - GST_INFO_OBJECT (self, "night mode, lowest allowed fps will be forced"); - bcamsrc->pre_night_fps_n = bcamsrc->fps_n; - bcamsrc->pre_night_fps_d = bcamsrc->fps_d; - detect_framerate = TRUE; - } else { - gst_structure_set (st, - "framerate", GST_TYPE_FRACTION, bcamsrc->fps_n, bcamsrc->fps_d, NULL); - new_caps = gst_caps_new_full (st, NULL); - } - } else { - GST_DEBUG_OBJECT (self, "no framerate specified"); - detect_framerate = TRUE; - } - - if (detect_framerate) { - GST_DEBUG_OBJECT (self, "detecting allowed framerate"); - /* Remove old framerate if any */ - if (gst_structure_has_field (st, "framerate")) { - gst_structure_remove_field (st, "framerate"); - } - new_caps = gst_caps_new_full (st, NULL); - - /* Set allowed framerate for the resolution */ - set_allowed_framerate (self, new_caps); - } - - /* Set default zoom method */ - if (self->src_zoom_scale) { - g_object_set (self->src_zoom_scale, "method", - CAMERABIN_DEFAULT_ZOOM_METHOD, NULL); - } - - /* we create new caps in any way and they take ownership of the structure st */ - gst_caps_replace (&self->view_finder_caps, new_caps); - gst_caps_unref (new_caps); - - /* Set caps for view finder mode */ - /* This also sets zoom */ - set_capsfilter_caps (self, self->view_finder_caps); - - return TRUE; -} - static gboolean copy_missing_fields (GQuark field_id, const GValue * value, gpointer user_data) { @@ -580,30 +379,6 @@ img_capture_prepared (gpointer data, GstCaps * caps) } } -static void -set_image_capture_caps (GstWrapperCameraBinSrc * self, gint width, gint height) -{ - GstStructure *structure; - GstCaps *new_caps = NULL; - - if (width && height && self->view_finder_caps) { - /* Use view finder mode caps as a basis */ - structure = gst_caps_get_structure (self->view_finder_caps, 0); - - /* Set new resolution for image capture */ - new_caps = gst_caps_new_simple (gst_structure_get_name (structure), - "width", G_TYPE_INT, width, "height", G_TYPE_INT, height, NULL); - - /* Set allowed framerate for the resolution. */ - set_allowed_framerate (self, new_caps); - } - - GST_INFO_OBJECT (self, - "init filter caps for image capture %" GST_PTR_FORMAT, new_caps); - gst_caps_replace (&self->image_capture_caps, new_caps); - self->image_capture_caps_update = FALSE; -} - /** * */ @@ -617,15 +392,9 @@ start_image_capture (GstWrapperCameraBinSrc * self) if (photography) { if (!self->image_capture_caps || self->image_capture_caps_update) { - if (bcamsrc->image_capture_width && bcamsrc->image_capture_height) { - /* Resolution is set, but it isn't in use yet */ - set_image_capture_caps (self, bcamsrc->image_capture_width, - bcamsrc->image_capture_height); - } else { - /* Capture resolution not set. Use viewfinder resolution */ - self->image_capture_caps = gst_caps_copy (self->view_finder_caps); - self->image_capture_caps_update = FALSE; - } + /* Capture resolution not set. Use viewfinder resolution */ + self->image_capture_caps = gst_caps_copy (self->view_finder_caps); + self->image_capture_caps_update = FALSE; } /* Start preparations for image capture */ @@ -803,31 +572,6 @@ failed: return caps; } -/** - * configure_format: - * @self: camerasrc object - * @caps: caps describing new format - * - * Configure internal video format for camerabin. - */ -static void -configure_format (GstWrapperCameraBinSrc * self, GstCaps * caps) -{ - GstBaseCameraSrc *bcamsrc = GST_BASE_CAMERA_SRC (self); - GstStructure *st; - - st = gst_caps_get_structure (caps, 0); - - gst_structure_get_int (st, "width", &bcamsrc->width); - gst_structure_get_int (st, "height", &bcamsrc->height); - - if (gst_structure_has_field_typed (st, "framerate", GST_TYPE_FRACTION)) { - gst_structure_get_fraction (st, "framerate", &bcamsrc->fps_n, - &bcamsrc->fps_d); - } -} - - /** * update_aspect_filter: * @self: camerasrc object @@ -930,8 +674,6 @@ set_capsfilter_caps (GstWrapperCameraBinSrc * self, GstCaps * new_caps) { GST_INFO_OBJECT (self, "new_caps:%" GST_PTR_FORMAT, new_caps); - configure_format (self, new_caps); - /* Update zoom */ gst_base_camera_src_setup_zoom (GST_BASE_CAMERA_SRC (self)); @@ -1019,8 +761,6 @@ gst_wrapper_camera_bin_src_class_init (GstWrapperCameraBinSrcClass * klass) gstbasecamerasrc_class->construct_pipeline = gst_wrapper_camera_bin_src_construct_pipeline; - gstbasecamerasrc_class->setup_pipeline = - gst_wrapper_camera_bin_src_setup_pipeline; gstbasecamerasrc_class->set_zoom = gst_wrapper_camera_bin_src_set_zoom; gstbasecamerasrc_class->set_mode = gst_wrapper_camera_bin_src_set_mode; gstbasecamerasrc_class->get_allowed_input_caps = From ea959add31e7c208a8a8b65c7d789fcef11de019 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Thu, 16 Dec 2010 08:47:56 -0300 Subject: [PATCH 180/448] basecamerasrc: Add some more logging Adds some more logging and always assume capture has started before start_capture is called. This helps on image captures that might call finish_capture directly from start_capture or before start_capture finishes. --- gst-libs/gst/basecamerabinsrc/gstbasecamerasrc.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/gst-libs/gst/basecamerabinsrc/gstbasecamerasrc.c b/gst-libs/gst/basecamerabinsrc/gstbasecamerasrc.c index a05418c588..7469f50fb7 100644 --- a/gst-libs/gst/basecamerabinsrc/gstbasecamerasrc.c +++ b/gst-libs/gst/basecamerabinsrc/gstbasecamerasrc.c @@ -222,6 +222,8 @@ gst_base_camera_src_start_capture (GstBaseCameraSrc * src) g_return_if_fail (klass->start_capture != NULL); + GST_DEBUG_OBJECT (src, "Starting capture"); + g_mutex_lock (src->capturing_mutex); if (src->capturing) { GST_WARNING_OBJECT (src, "Capturing already ongoing"); @@ -229,10 +231,12 @@ gst_base_camera_src_start_capture (GstBaseCameraSrc * src) return; } + src->capturing = TRUE; if (klass->start_capture (src)) { - src->capturing = TRUE; + GST_DEBUG_OBJECT (src, "Capture started"); g_object_notify (G_OBJECT (src), "ready-for-capture"); } else { + src->capturing = FALSE; GST_WARNING_OBJECT (src, "Failed to start capture"); } g_mutex_unlock (src->capturing_mutex); @@ -258,6 +262,7 @@ gst_base_camera_src_stop_capture (GstBaseCameraSrc * src) void gst_base_camera_src_finish_capture (GstBaseCameraSrc * self) { + GST_DEBUG_OBJECT (self, "Finishing capture"); g_return_if_fail (self->capturing); self->capturing = FALSE; g_object_notify (G_OBJECT (self), "ready-for-capture"); From a7fe67700e77bc35866d35c758fad5d4948c3c80 Mon Sep 17 00:00:00 2001 From: Teemu Katajisto Date: Fri, 10 Dec 2010 17:45:40 +0200 Subject: [PATCH 181/448] camerabin2: remove abreviations from imagecapturebin --- gst/camerabin2/gstimagecapturebin.c | 1 - 1 file changed, 1 deletion(-) diff --git a/gst/camerabin2/gstimagecapturebin.c b/gst/camerabin2/gstimagecapturebin.c index a1cf3ac131..b20cb46309 100644 --- a/gst/camerabin2/gstimagecapturebin.c +++ b/gst/camerabin2/gstimagecapturebin.c @@ -117,7 +117,6 @@ gst_image_capture_bin_set_property (GObject * object, guint prop_id, case PROP_LOCATION: g_free (imagebin->location); imagebin->location = g_value_dup_string (value); - if (imagebin->sink) { g_object_set (imagebin, "location", imagebin->location, NULL); } From 42092fe9286b1dad53d5c1d01176e6d160966587 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Sun, 19 Dec 2010 19:40:54 -0300 Subject: [PATCH 182/448] basecamerabinsrc: Fix makefile building order basecamerabinsrc must be built after photography interface as it depends on it. --- gst-libs/gst/Makefile.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gst-libs/gst/Makefile.am b/gst-libs/gst/Makefile.am index 561c1f4ea2..56145806b0 100644 --- a/gst-libs/gst/Makefile.am +++ b/gst-libs/gst/Makefile.am @@ -3,7 +3,7 @@ if BUILD_EXPERIMENTAL EXPERIMENTAL_LIBS=basecamerabinsrc endif -SUBDIRS = $(EXPERIMENTAL_LIBS) interfaces signalprocessor video +SUBDIRS = interfaces signalprocessor video $(EXPERIMENTAL_LIBS) noinst_HEADERS = gst-i18n-plugin.h gettext.h -DIST_SUBDIRS = $(EXPERIMENTAL_LIBS) interfaces signalprocessor video +DIST_SUBDIRS = interfaces signalprocessor video $(EXPERIMENTAL_LIBS) From 85bf8f233556a1f73d66ae742d0fb97524a44e88 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Tue, 14 Dec 2010 18:42:51 -0300 Subject: [PATCH 183/448] camerabin2: Adds properties for capture caps Adds properties for selecting caps for video and image captures --- gst/camerabin2/gstcamerabin2.c | 79 ++++++++++++++++++++++++++-------- 1 file changed, 60 insertions(+), 19 deletions(-) diff --git a/gst/camerabin2/gstcamerabin2.c b/gst/camerabin2/gstcamerabin2.c index 602cf3a954..f155cf24b2 100644 --- a/gst/camerabin2/gstcamerabin2.c +++ b/gst/camerabin2/gstcamerabin2.c @@ -64,7 +64,9 @@ enum PROP_LOCATION, PROP_CAMERA_SRC, PROP_IMAGE_CAPTURE_SUPPORTED_CAPS, - PROP_VIDEO_CAPTURE_SUPPORTED_CAPS + PROP_VIDEO_CAPTURE_SUPPORTED_CAPS, + PROP_IMAGE_CAPTURE_CAPS, + PROP_VIDEO_CAPTURE_CAPS }; enum @@ -305,6 +307,20 @@ gst_camera_bin_class_init (GstCameraBinClass * klass) "Formats supported for capturing videos represented as GstCaps", GST_TYPE_CAPS, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (object_class, + PROP_IMAGE_CAPTURE_CAPS, + g_param_spec_boxed ("image-capture-caps", + "Image capture caps", + "Caps for image capture", + GST_TYPE_CAPS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (object_class, + PROP_VIDEO_CAPTURE_CAPS, + g_param_spec_boxed ("video-capture-caps", + "Video capture caps", + "Caps for video capture", + GST_TYPE_CAPS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** * GstCameraBin::capture-start: @@ -332,15 +348,28 @@ gst_camera_bin_class_init (GstCameraBinClass * klass) } static void -gst_camera_bin_init (GstCameraBin * camerabin) +gst_camera_bin_init (GstCameraBin * camera) { - camerabin->mode = DEFAULT_MODE; - camerabin->video_location = g_strdup (DEFAULT_VID_LOCATION); - camerabin->image_location = g_strdup (DEFAULT_IMG_LOCATION); - camerabin->viewfinderbin = gst_element_factory_make ("viewfinderbin", - "vf-bin"); + camera->mode = DEFAULT_MODE; + camera->video_location = g_strdup (DEFAULT_VID_LOCATION); + camera->image_location = g_strdup (DEFAULT_IMG_LOCATION); + camera->viewfinderbin = gst_element_factory_make ("viewfinderbin", "vf-bin"); - gst_bin_add (GST_BIN (camerabin), gst_object_ref (camerabin->viewfinderbin)); + /* capsfilters are created here as we proxy their caps properties and + * this way we avoid having to store the caps while on NULL state to + * set them later */ + camera->videobin_capsfilter = gst_element_factory_make ("capsfilter", + "videobin-capsfilter"); + camera->imagebin_capsfilter = gst_element_factory_make ("capsfilter", + "imagebin-capsfilter"); + camera->viewfinderbin_capsfilter = gst_element_factory_make ("capsfilter", + "viewfinderbin-capsfilter"); + + gst_bin_add_many (GST_BIN (camera), + gst_object_ref (camera->viewfinderbin), + gst_object_ref (camera->videobin_capsfilter), + gst_object_ref (camera->imagebin_capsfilter), + gst_object_ref (camera->viewfinderbin_capsfilter), NULL); } /** @@ -373,21 +402,11 @@ gst_camera_bin_create_elements (GstCameraBin * camera) camera->viewfinderbin_queue = gst_element_factory_make ("queue", "viewfinderbin-queue"); - camera->videobin_capsfilter = gst_element_factory_make ("capsfilter", - "videobin-capsfilter"); - camera->imagebin_capsfilter = gst_element_factory_make ("capsfilter", - "imagebin-capsfilter"); - camera->viewfinderbin_capsfilter = gst_element_factory_make ("capsfilter", - "viewfinderbin-capsfilter"); - gst_bin_add_many (GST_BIN_CAST (camera), gst_object_ref (camera->videobin), gst_object_ref (camera->imagebin), gst_object_ref (camera->videobin_queue), gst_object_ref (camera->imagebin_queue), - gst_object_ref (camera->viewfinderbin_queue), - gst_object_ref (camera->videobin_capsfilter), - gst_object_ref (camera->imagebin_capsfilter), - gst_object_ref (camera->viewfinderbin_capsfilter), NULL); + gst_object_ref (camera->viewfinderbin_queue), NULL); /* Linking can be optimized TODO */ gst_element_link_many (camera->videobin_queue, camera->videobin_capsfilter, @@ -531,6 +550,14 @@ gst_camera_bin_set_property (GObject * object, guint prop_id, case PROP_CAMERA_SRC: gst_camera_bin_set_camera_src (camera, g_value_get_object (value)); break; + case PROP_IMAGE_CAPTURE_CAPS: + g_object_set (camera->imagebin_capsfilter, "caps", + gst_value_get_caps (value), NULL); + break; + case PROP_VIDEO_CAPTURE_CAPS: + g_object_set (camera->videobin_capsfilter, "caps", + gst_value_get_caps (value), NULL); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -592,6 +619,20 @@ gst_camera_bin_get_property (GObject * object, guint prop_id, } } break; + case PROP_IMAGE_CAPTURE_CAPS:{ + GstCaps *caps = NULL; + g_object_get (camera->imagebin_capsfilter, "caps", &caps, NULL); + gst_value_set_caps (value, caps); + gst_caps_unref (caps); + } + break; + case PROP_VIDEO_CAPTURE_CAPS:{ + GstCaps *caps = NULL; + g_object_get (camera->videobin_capsfilter, "caps", &caps, NULL); + gst_value_set_caps (value, caps); + gst_caps_unref (caps); + } + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; From b1a361b566cf0dfc3a188f5a23c13feab9d575a2 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Thu, 16 Dec 2010 22:49:24 -0300 Subject: [PATCH 184/448] wrappercamerabinsrc: Add local mode --- gst/camerabin2/gstwrappercamerabinsrc.c | 12 +++++++++--- gst/camerabin2/gstwrappercamerabinsrc.h | 2 ++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/gst/camerabin2/gstwrappercamerabinsrc.c b/gst/camerabin2/gstwrappercamerabinsrc.c index bcbddc6cfa..747913b62c 100644 --- a/gst/camerabin2/gstwrappercamerabinsrc.c +++ b/gst/camerabin2/gstwrappercamerabinsrc.c @@ -417,6 +417,9 @@ gst_wrapper_camera_bin_src_set_mode (GstBaseCameraSrc * bcamsrc, GstCameraBinMode mode) { GstPhotography *photography = gst_base_camera_src_get_photography (bcamsrc); + GstWrapperCameraBinSrc *self = GST_WRAPPER_CAMERA_BIN_SRC (bcamsrc); + + self->mode = mode; if (photography) { if (g_object_class_find_property (G_OBJECT_GET_CLASS (photography), @@ -691,10 +694,10 @@ gst_wrapper_camera_bin_src_start_capture (GstBaseCameraSrc * camerasrc) GstWrapperCameraBinSrc *src = GST_WRAPPER_CAMERA_BIN_SRC (camerasrc); /* TODO shoud we access this directly? Maybe a macro is better? */ - if (camerasrc->mode == MODE_IMAGE) { + if (src->mode == MODE_IMAGE) { src->image_capture_count = 1; start_image_capture (src); - } else if (camerasrc->mode == MODE_VIDEO) { + } else if (src->mode == MODE_VIDEO) { if (src->video_rec_status == GST_VIDEO_RECORDING_STATUS_DONE) { src->video_rec_status = GST_VIDEO_RECORDING_STATUS_STARTING; } @@ -711,7 +714,7 @@ gst_wrapper_camera_bin_src_stop_capture (GstBaseCameraSrc * camerasrc) GstWrapperCameraBinSrc *src = GST_WRAPPER_CAMERA_BIN_SRC (camerasrc); /* TODO shoud we access this directly? Maybe a macro is better? */ - if (camerasrc->mode == MODE_VIDEO) { + if (src->mode == MODE_VIDEO) { if (src->video_rec_status == GST_VIDEO_RECORDING_STATUS_STARTING) { GST_DEBUG_OBJECT (src, "Aborting, had not started recording"); src->video_rec_status = GST_VIDEO_RECORDING_STATUS_DONE; @@ -794,6 +797,9 @@ gst_wrapper_camera_bin_src_init (GstWrapperCameraBinSrc * self, /* TODO where are variables reset? */ self->image_capture_count = 0; self->video_rec_status = GST_VIDEO_RECORDING_STATUS_DONE; + self->video_renegotiate = FALSE; + self->image_renegotiate = FALSE; + self->mode = GST_BASE_CAMERA_SRC_CAST (self)->mode; } gboolean diff --git a/gst/camerabin2/gstwrappercamerabinsrc.h b/gst/camerabin2/gstwrappercamerabinsrc.h index c06a9bbce7..dc65f33ce6 100644 --- a/gst/camerabin2/gstwrappercamerabinsrc.h +++ b/gst/camerabin2/gstwrappercamerabinsrc.h @@ -57,6 +57,8 @@ struct _GstWrapperCameraBinSrc { GstBaseCameraSrc parent; + GstCameraBinMode mode; + GstPad *vfsrc; GstPad *imgsrc; GstPad *vidsrc; From 1e6be5ec56210924d09b5b6f8689428f7fa4a613 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Wed, 15 Dec 2010 14:05:54 -0300 Subject: [PATCH 185/448] camerabin2: Use custom renegotiate event Adds a custom renegotiate event that is pushed to the camerasrc pad that needs renegotiation due to the user selecting a new capture caps for that pad. This is a way of notifying the source that it should update its caps, even if it doesn't use pad allocs. --- gst/camerabin2/gstcamerabin2.c | 41 ++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/gst/camerabin2/gstcamerabin2.c b/gst/camerabin2/gstcamerabin2.c index f155cf24b2..d4a0db6c26 100644 --- a/gst/camerabin2/gstcamerabin2.c +++ b/gst/camerabin2/gstcamerabin2.c @@ -135,6 +135,13 @@ gst_camera_bin_change_state (GstElement * element, GstStateChange trans); /* Camerabin functions */ +static GstEvent * +gst_camera_bin_new_event_renegotiate (void) +{ + return gst_event_new_custom (GST_EVENT_CUSTOM_BOTH, + gst_structure_new ("renegotiate", NULL)); +} + static void gst_camera_bin_start_capture (GstCameraBin * camerabin) { @@ -550,13 +557,43 @@ gst_camera_bin_set_property (GObject * object, guint prop_id, case PROP_CAMERA_SRC: gst_camera_bin_set_camera_src (camera, g_value_get_object (value)); break; - case PROP_IMAGE_CAPTURE_CAPS: + case PROP_IMAGE_CAPTURE_CAPS:{ + GstPad *pad = NULL; + + if (camera->src) + pad = + gst_element_get_static_pad (camera->src, + GST_BASE_CAMERA_SRC_IMAGE_PAD_NAME); + + /* set the capsfilter caps and notify the src to renegotiate */ g_object_set (camera->imagebin_capsfilter, "caps", gst_value_get_caps (value), NULL); + if (pad) { + GST_DEBUG_OBJECT (camera, "Pushing renegotiate on %s", + GST_PAD_NAME (pad)); + GST_PAD_EVENTFUNC (pad) (pad, gst_camera_bin_new_event_renegotiate ()); + gst_object_unref (pad); + } + } break; - case PROP_VIDEO_CAPTURE_CAPS: + case PROP_VIDEO_CAPTURE_CAPS:{ + GstPad *pad = NULL; + + if (camera->src) + pad = + gst_element_get_static_pad (camera->src, + GST_BASE_CAMERA_SRC_VIDEO_PAD_NAME); + + /* set the capsfilter caps and notify the src to renegotiate */ g_object_set (camera->videobin_capsfilter, "caps", gst_value_get_caps (value), NULL); + if (pad) { + GST_DEBUG_OBJECT (camera, "Pushing renegotiate on %s", + GST_PAD_NAME (pad)); + gst_pad_push_event (pad, gst_camera_bin_new_event_renegotiate ()); + gst_object_unref (pad); + } + } break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); From e94c5b3b9bb8605d2756412a7e31ac9a9bb248e7 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Thu, 16 Dec 2010 00:40:25 -0300 Subject: [PATCH 186/448] wrappercamerabinsrc: Handle camerabin2 custom renegotiate events --- gst/camerabin2/gstwrappercamerabinsrc.c | 100 +++++++++++++++++++++--- gst/camerabin2/gstwrappercamerabinsrc.h | 7 +- 2 files changed, 95 insertions(+), 12 deletions(-) diff --git a/gst/camerabin2/gstwrappercamerabinsrc.c b/gst/camerabin2/gstwrappercamerabinsrc.c index 747913b62c..7fbcc75258 100644 --- a/gst/camerabin2/gstwrappercamerabinsrc.c +++ b/gst/camerabin2/gstwrappercamerabinsrc.c @@ -110,6 +110,20 @@ gst_wrapper_camera_bin_src_get_property (GObject * object, } } +static void +gst_wrapper_camera_bin_reset_video_src_caps (GstWrapperCameraBinSrc * self, + GstCaps * caps) +{ + GST_DEBUG_OBJECT (self, "Resetting src caps to %" GST_PTR_FORMAT, caps); + /* TODO this won't work on NULL */ + if (self->src_vid_src) { + gst_element_set_state (self->src_vid_src, GST_STATE_NULL); + set_capsfilter_caps (self, caps); + GST_DEBUG_OBJECT (self, "Bringing source up"); + gst_element_sync_state_with_parent (self->src_vid_src); + } +} + /** * gst_wrapper_camera_bin_src_imgsrc_probe: * @@ -177,6 +191,34 @@ gst_wrapper_camera_bin_src_vidsrc_probe (GstPad * pad, GstBuffer * buffer, return ret; } +static gboolean +gst_wrapper_camera_bin_src_event (GstPad * pad, GstEvent * event) +{ + GstWrapperCameraBinSrc *src = + GST_WRAPPER_CAMERA_BIN_SRC (GST_PAD_PARENT (pad)); + const GstStructure *structure; + + structure = gst_event_get_structure (event); + if (structure && gst_structure_has_name (structure, "renegotiate")) { + if (pad == src->imgsrc) { + src->image_renegotiate = TRUE; + } else if (pad == src->vidsrc) { + src->video_renegotiate = TRUE; + } + } + + return src->srcpad_event_func (pad, event); +} + +static gboolean +src_event_probe (GstPad * pad, GstEvent * event, gpointer user_data) +{ + if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) { + return FALSE; + } + return TRUE; +} + /** * gst_wrapper_camera_bin_src_construct_pipeline: * @bcamsrc: camerasrc object @@ -207,6 +249,15 @@ gst_wrapper_camera_bin_src_construct_pipeline (GstBaseCameraSrc * bcamsrc) } } + { + GstPad *pad; + pad = gst_element_get_static_pad (self->src_vid_src, "src"); + + self->src_event_probe_id = gst_pad_add_event_probe (pad, + (GCallback) src_event_probe, self); + gst_object_unref (pad); + } + if (!gst_camerabin_create_and_add_element (cbin, "ffmpegcolorspace")) goto done; @@ -236,6 +287,8 @@ gst_wrapper_camera_bin_src_construct_pipeline (GstBaseCameraSrc * bcamsrc) gst_pad_add_buffer_probe (self->tee_video_srcpad, G_CALLBACK (gst_wrapper_camera_bin_src_vidsrc_probe), self); + g_object_set (tee, "alloc-pad", self->tee_vf_srcpad, NULL); + /* hook-up the ghostpads */ gst_ghost_pad_set_target (GST_GHOST_PAD (self->vfsrc), self->tee_vf_srcpad); gst_ghost_pad_set_target (GST_GHOST_PAD (self->imgsrc), @@ -247,7 +300,6 @@ gst_wrapper_camera_bin_src_construct_pipeline (GstBaseCameraSrc * bcamsrc) gst_pad_set_active (self->imgsrc, TRUE); /* XXX ??? */ gst_pad_set_active (self->vidsrc, TRUE); /* XXX ??? */ - ret = TRUE; done: return ret; @@ -388,24 +440,38 @@ start_image_capture (GstWrapperCameraBinSrc * self) GstBaseCameraSrc *bcamsrc = GST_BASE_CAMERA_SRC (self); GstPhotography *photography = gst_base_camera_src_get_photography (bcamsrc); gboolean ret = FALSE; + GstCaps *caps; + + GST_DEBUG_OBJECT (self, "Starting image capture"); + + if (self->image_renegotiate) { + /* clean capsfilter caps so they don't interfere here */ + g_object_set (self->src_filter, "caps", NULL, NULL); + if (self->src_zoom_filter) + g_object_set (self->src_zoom_filter, "caps", NULL, NULL); + + caps = gst_pad_get_allowed_caps (self->imgsrc); + + caps = gst_caps_make_writable (caps); + gst_pad_fixate_caps (self->imgsrc, caps); + + gst_caps_replace (&self->image_capture_caps, caps); + gst_caps_unref (caps); + + self->image_renegotiate = FALSE; + } if (photography) { - - if (!self->image_capture_caps || self->image_capture_caps_update) { - /* Capture resolution not set. Use viewfinder resolution */ - self->image_capture_caps = gst_caps_copy (self->view_finder_caps); - self->image_capture_caps_update = FALSE; - } - - /* Start preparations for image capture */ GST_DEBUG_OBJECT (self, "prepare image capture caps %" GST_PTR_FORMAT, self->image_capture_caps); - ret = gst_photography_prepare_for_capture (photography, (GstPhotoCapturePrepared) img_capture_prepared, self->image_capture_caps, self); - } else { + g_mutex_unlock (bcamsrc->capturing_mutex); + gst_wrapper_camera_bin_reset_video_src_caps (self, + self->image_capture_caps); + g_mutex_lock (bcamsrc->capturing_mutex); ret = TRUE; } @@ -426,7 +492,10 @@ gst_wrapper_camera_bin_src_set_mode (GstBaseCameraSrc * bcamsrc, "capture-mode")) { g_object_set (G_OBJECT (photography), "capture-mode", mode, NULL); } + } else { + gst_wrapper_camera_bin_reset_video_src_caps (self, NULL); } + return TRUE; } @@ -698,6 +767,10 @@ gst_wrapper_camera_bin_src_start_capture (GstBaseCameraSrc * camerasrc) src->image_capture_count = 1; start_image_capture (src); } else if (src->mode == MODE_VIDEO) { + g_mutex_unlock (camerasrc->capturing_mutex); + gst_wrapper_camera_bin_reset_video_src_caps (src, NULL); + g_mutex_lock (camerasrc->capturing_mutex); + if (src->video_rec_status == GST_VIDEO_RECORDING_STATUS_DONE) { src->video_rec_status = GST_VIDEO_RECORDING_STATUS_STARTING; } @@ -793,6 +866,11 @@ gst_wrapper_camera_bin_src_init (GstWrapperCameraBinSrc * self, GST_PAD_SRC); gst_element_add_pad (GST_ELEMENT (self), self->vidsrc); + self->srcpad_event_func = GST_PAD_EVENTFUNC (self->vfsrc); + + gst_pad_set_event_function (self->imgsrc, gst_wrapper_camera_bin_src_event); + gst_pad_set_event_function (self->vidsrc, gst_wrapper_camera_bin_src_event); + gst_pad_set_event_function (self->vfsrc, gst_wrapper_camera_bin_src_event); /* TODO where are variables reset? */ self->image_capture_count = 0; diff --git a/gst/camerabin2/gstwrappercamerabinsrc.h b/gst/camerabin2/gstwrappercamerabinsrc.h index dc65f33ce6..22697b93aa 100644 --- a/gst/camerabin2/gstwrappercamerabinsrc.h +++ b/gst/camerabin2/gstwrappercamerabinsrc.h @@ -76,11 +76,15 @@ struct _GstWrapperCameraBinSrc GstElement *src_zoom_scale; GstElement *src_zoom_filter; + guint src_event_probe_id; + /* srcpads of tee */ GstPad *tee_vf_srcpad; GstPad *tee_image_srcpad; GstPad *tee_video_srcpad; + GstPadEventFunction srcpad_event_func; + /* Application configurable elements */ GstElement *app_vid_src; @@ -99,7 +103,8 @@ struct _GstWrapperCameraBinSrc /* Caps applied to capsfilters when taking still image */ GstCaps *image_capture_caps; - gboolean image_capture_caps_update; // XXX where does this get set.. + gboolean image_renegotiate; + gboolean video_renegotiate; }; From 1904c1891f44214a8f242ece28a6763e3119419a Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Tue, 14 Dec 2010 22:06:33 -0300 Subject: [PATCH 187/448] camerabin2: Adds tests for image capture with different caps Adds a test that tries sucessive captures with different caps --- tests/check/elements/camerabin2.c | 88 ++++++++++++++++++++++++++++--- 1 file changed, 81 insertions(+), 7 deletions(-) diff --git a/tests/check/elements/camerabin2.c b/tests/check/elements/camerabin2.c index 0d079529d8..3057839195 100644 --- a/tests/check/elements/camerabin2.c +++ b/tests/check/elements/camerabin2.c @@ -322,9 +322,15 @@ validity_bus_cb (GstBus * bus, GstMessage * message, gpointer data) /* Validate captured files by playing them with playbin * and checking that no errors occur. */ static gboolean -check_file_validity (const gchar * filename, gint num, GstTagList * taglist) +check_file_validity (const gchar * filename, gint num, GstTagList * taglist, + gint width, gint height) { GstBus *bus; + GstPad *pad; + GstCaps *caps; + gint caps_width, caps_height; + GstState state; + GMainLoop *loop = g_main_loop_new (NULL, FALSE); GstElement *playbin = gst_element_factory_make ("playbin2", NULL); GstElement *fakevideo = gst_element_factory_make ("fakesink", NULL); @@ -339,6 +345,27 @@ check_file_validity (const gchar * filename, gint num, GstTagList * taglist) bus = gst_pipeline_get_bus (GST_PIPELINE (playbin)); gst_bus_add_watch (bus, (GstBusFunc) validity_bus_cb, loop); + gst_element_set_state (playbin, GST_STATE_PAUSED); + + if (width != 0 && height != 0) { + gst_element_get_state (playbin, &state, NULL, GST_SECOND * 3); + + g_signal_emit_by_name (playbin, "get-video-pad", 0, &pad, NULL); + g_assert (pad != NULL); + caps = gst_pad_get_negotiated_caps (pad); + + g_assert (gst_structure_get_int (gst_caps_get_structure (caps, 0), + "width", &caps_width)); + g_assert (gst_structure_get_int (gst_caps_get_structure (caps, 0), + "height", &caps_height)); + + g_assert (width == caps_width); + g_assert (height == caps_height); + + gst_caps_unref (caps); + gst_object_unref (pad); + } + gst_element_set_state (playbin, GST_STATE_PLAYING); g_main_loop_run (loop); gst_element_set_state (playbin, GST_STATE_NULL); @@ -373,12 +400,58 @@ GST_START_TEST (test_single_image_capture) g_usleep (G_USEC_PER_SEC * 3); gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL); - check_file_validity (IMAGE_FILENAME, 0, NULL); + check_file_validity (IMAGE_FILENAME, 0, NULL, 0, 0); } GST_END_TEST; -GST_START_TEST (test_video_recording) + +GST_START_TEST (test_multiple_image_captures) +{ + gint i; + gint widths[] = { 800, 640, 1280 }; + gint heights[] = { 600, 480, 1024 }; + + if (!camera) + return; + + /* set still image mode */ + g_object_set (camera, "mode", 1, + "location", make_test_file_name (IMAGE_FILENAME, -1), NULL); + + if (gst_element_set_state (GST_ELEMENT (camera), GST_STATE_PLAYING) == + GST_STATE_CHANGE_FAILURE) { + GST_WARNING ("setting camerabin to PLAYING failed"); + gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL); + gst_object_unref (camera); + camera = NULL; + } + fail_unless (camera != NULL); + GST_INFO ("starting capture"); + + for (i = 0; i < 3; i++) { + GstCaps *caps; + + caps = gst_caps_new_simple ("video/x-raw-rgb", "width", G_TYPE_INT, + widths[i], "height", G_TYPE_INT, heights[i], NULL); + + g_object_set (camera, "image-capture-caps", caps, NULL); + gst_caps_unref (caps); + + g_signal_emit_by_name (camera, "start-capture", NULL); + g_usleep (G_USEC_PER_SEC * 1); + } + + g_usleep (G_USEC_PER_SEC * 3); + gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL); + for (i = 0; i < 3; i++) { + check_file_validity (IMAGE_FILENAME, i, NULL, widths[i], heights[i]); + } +} + +GST_END_TEST; + +GST_START_TEST (test_single_video_recording) { if (!camera) return; @@ -406,7 +479,7 @@ GST_START_TEST (test_video_recording) gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL); - check_file_validity (VIDEO_FILENAME, 0, NULL); + check_file_validity (VIDEO_FILENAME, 0, NULL, 0, 0); } GST_END_TEST; @@ -454,8 +527,8 @@ GST_START_TEST (test_image_video_cycle) /* validate all the files */ for (i = 0; i < 2; i++) { - check_file_validity (IMAGE_FILENAME, i, NULL); - check_file_validity (VIDEO_FILENAME, i, NULL); + check_file_validity (IMAGE_FILENAME, i, NULL, 0, 0); + check_file_validity (VIDEO_FILENAME, i, NULL, 0, 0); } } @@ -518,8 +591,9 @@ camerabin_suite (void) tcase_set_timeout (tc_basic, 30); tcase_add_checked_fixture (tc_basic, setup, teardown); tcase_add_test (tc_basic, test_single_image_capture); - tcase_add_test (tc_basic, test_video_recording); + tcase_add_test (tc_basic, test_single_video_recording); tcase_add_test (tc_basic, test_image_video_cycle); + tcase_add_test (tc_basic, test_multiple_image_captures); tcase_add_test (tc_basic, test_supported_caps); return s; From f10e44599542027b09e968bc281b214580b6747f Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Fri, 17 Dec 2010 23:06:23 -0300 Subject: [PATCH 188/448] camerabin2: Small tests update Increases timeout value so that tests won't fail with full debug output. Also removes buffer alloc from videotestsrc as this feature isn't ready on camerabin2 --- tests/check/elements/camerabin2.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/check/elements/camerabin2.c b/tests/check/elements/camerabin2.c index 3057839195..fe36d098e2 100644 --- a/tests/check/elements/camerabin2.c +++ b/tests/check/elements/camerabin2.c @@ -257,11 +257,11 @@ setup (void) main_loop = g_main_loop_new (NULL, TRUE); camera = gst_check_setup_element ("camerabin2"); - fakevideosink = gst_check_setup_element ("fakesink"); - src = gst_check_setup_element ("wrappercamerabinsrc"); - testsrc = gst_check_setup_element ("videotestsrc"); + fakevideosink = gst_element_factory_make ("fakesink", NULL); + src = gst_element_factory_make ("wrappercamerabinsrc", NULL); + testsrc = gst_element_factory_make ("videotestsrc", NULL); - g_object_set (G_OBJECT (testsrc), "is-live", TRUE, NULL); + g_object_set (G_OBJECT (testsrc), "is-live", TRUE, "peer-alloc", FALSE, NULL); g_object_set (G_OBJECT (src), "video-src", testsrc, NULL); g_object_set (G_OBJECT (camera), "camera-src", src, NULL); gst_object_unref (src); @@ -588,7 +588,7 @@ camerabin_suite (void) /* Test that basic operations run without errors */ suite_add_tcase (s, tc_basic); /* Increase timeout due to video recording */ - tcase_set_timeout (tc_basic, 30); + tcase_set_timeout (tc_basic, 60); tcase_add_checked_fixture (tc_basic, setup, teardown); tcase_add_test (tc_basic, test_single_image_capture); tcase_add_test (tc_basic, test_single_video_recording); From 58d4315965779afc83473eed7d82f75c00184662 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Fri, 17 Dec 2010 23:06:45 -0300 Subject: [PATCH 189/448] camerabin2: more logs --- gst/camerabin2/gstcamerabin2.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/gst/camerabin2/gstcamerabin2.c b/gst/camerabin2/gstcamerabin2.c index d4a0db6c26..442c681631 100644 --- a/gst/camerabin2/gstcamerabin2.c +++ b/gst/camerabin2/gstcamerabin2.c @@ -565,6 +565,10 @@ gst_camera_bin_set_property (GObject * object, guint prop_id, gst_element_get_static_pad (camera->src, GST_BASE_CAMERA_SRC_IMAGE_PAD_NAME); + GST_DEBUG_OBJECT (camera, + "Setting image capture caps to %" GST_PTR_FORMAT, + gst_value_get_caps (value)); + /* set the capsfilter caps and notify the src to renegotiate */ g_object_set (camera->imagebin_capsfilter, "caps", gst_value_get_caps (value), NULL); @@ -584,6 +588,10 @@ gst_camera_bin_set_property (GObject * object, guint prop_id, gst_element_get_static_pad (camera->src, GST_BASE_CAMERA_SRC_VIDEO_PAD_NAME); + GST_DEBUG_OBJECT (camera, + "Setting video capture caps to %" GST_PTR_FORMAT, + gst_value_get_caps (value)); + /* set the capsfilter caps and notify the src to renegotiate */ g_object_set (camera->videobin_capsfilter, "caps", gst_value_get_caps (value), NULL); From 450f54b02091a26c025f7d24bb62ab208f5ffccc Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Mon, 20 Dec 2010 02:58:44 -0300 Subject: [PATCH 190/448] viewfinderbin: Remove leaks Removing various leaks from viewfinderbin --- gst/camerabin2/gstviewfinderbin.c | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/gst/camerabin2/gstviewfinderbin.c b/gst/camerabin2/gstviewfinderbin.c index c820c0458a..e03631e328 100644 --- a/gst/camerabin2/gstviewfinderbin.c +++ b/gst/camerabin2/gstviewfinderbin.c @@ -73,6 +73,24 @@ gst_viewfinder_bin_set_video_sink (GstViewfinderBin * vfbin, GstElement * sink); static GstStateChangeReturn gst_viewfinder_bin_change_state (GstElement * element, GstStateChange trans); +static void +gst_viewfinder_bin_dispose (GObject * object) +{ + GstViewfinderBin *viewfinderbin = GST_VIEWFINDER_BIN_CAST (object); + + if (viewfinderbin->user_video_sink) { + gst_object_unref (viewfinderbin->user_video_sink); + viewfinderbin->user_video_sink = NULL; + } + + if (viewfinderbin->video_sink) { + gst_object_unref (viewfinderbin->video_sink); + viewfinderbin->video_sink = NULL; + } + + G_OBJECT_CLASS (parent_class)->dispose ((GObject *) viewfinderbin); +} + static void gst_viewfinder_bin_base_init (gpointer g_class) { @@ -98,6 +116,7 @@ gst_viewfinder_bin_class_init (GstViewfinderBinClass * klass) element_class->change_state = GST_DEBUG_FUNCPTR (gst_viewfinder_bin_change_state); + gobject_klass->dispose = gst_viewfinder_bin_dispose; gobject_klass->set_property = gst_viewfinder_bin_set_property; gobject_klass->get_property = gst_viewfinder_bin_get_property; @@ -111,8 +130,10 @@ static void gst_viewfinder_bin_init (GstViewfinderBin * viewfinderbin, GstViewfinderBinClass * viewfinderbin_class) { + GstPadTemplate *templ = gst_static_pad_template_get (&sink_template); viewfinderbin->ghostpad = gst_ghost_pad_new_no_target_from_template ("sink", - gst_static_pad_template_get (&sink_template)); + templ); + gst_object_unref (templ); gst_element_add_pad (GST_ELEMENT_CAST (viewfinderbin), viewfinderbin->ghostpad); } @@ -149,6 +170,7 @@ gst_viewfinder_bin_create_elements (GstViewfinderBin * vfbin) pad = gst_element_get_static_pad (csp, "sink"); if (!gst_ghost_pad_set_target (GST_GHOST_PAD (vfbin->ghostpad), pad)) goto error; + gst_object_unref (pad); vfbin->elements_created = TRUE; GST_DEBUG_OBJECT (vfbin, "Elements succesfully created and linked"); From 72ef18d535286ebe0ee826f50f88d7b991de9dae Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Mon, 20 Dec 2010 02:59:14 -0300 Subject: [PATCH 191/448] viewfinderbin: Add basic check test Adds minimum check test. It's not a very useful test, but at least it allows us to run it under valgrind and check for leaks automatically --- tests/check/Makefile.am | 3 +- tests/check/elements/viewfinderbin.c | 103 +++++++++++++++++++++++++++ 2 files changed, 105 insertions(+), 1 deletion(-) create mode 100644 tests/check/elements/viewfinderbin.c diff --git a/tests/check/Makefile.am b/tests/check/Makefile.am index 864ce0888b..dc86ff433a 100644 --- a/tests/check/Makefile.am +++ b/tests/check/Makefile.am @@ -130,7 +130,8 @@ VALGRIND_TESTS_DISABLE = \ if BUILD_EXPERIMENTAL EXPERIMENTAL_CHECKS=elements/camerabin2 \ elements/imagecapturebin \ - elements/videorecordingbin + elements/videorecordingbin \ + elements/viewfinderbin endif # these tests don't even pass diff --git a/tests/check/elements/viewfinderbin.c b/tests/check/elements/viewfinderbin.c new file mode 100644 index 0000000000..c5766052c2 --- /dev/null +++ b/tests/check/elements/viewfinderbin.c @@ -0,0 +1,103 @@ +/* GStreamer unit test for the viewfinderbin element + * Copyright (C) 2010 Thiago Santos + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +typedef struct +{ + GstElement *pipe; + GstElement *src; + GstElement *vfbin; +} GstViewFinderBinTestContext; + +static void +gstviewfinderbin_init_test_context (GstViewFinderBinTestContext * ctx, + gint num_buffers) +{ + GstElement *sink; + fail_unless (ctx != NULL); + + ctx->pipe = gst_pipeline_new ("pipeline"); + fail_unless (ctx->pipe != NULL); + ctx->src = gst_element_factory_make ("videotestsrc", "src"); + fail_unless (ctx->src != NULL, "Failed to create videotestsrc element"); + sink = gst_element_factory_make ("fakesink", NULL); + ctx->vfbin = gst_element_factory_make ("viewfinderbin", "vfbin"); + fail_unless (ctx->vfbin != NULL, "Failed to create viewfinderbin element"); + g_object_set (ctx->vfbin, "video-sink", sink, NULL); + gst_object_unref (sink); + + if (num_buffers > 0) + g_object_set (ctx->src, "num-buffers", num_buffers, NULL); + + fail_unless (gst_bin_add (GST_BIN (ctx->pipe), ctx->src)); + fail_unless (gst_bin_add (GST_BIN (ctx->pipe), ctx->vfbin)); + fail_unless (gst_element_link (ctx->src, ctx->vfbin)); +} + +static void +gstviewfinderbin_unset_test_context (GstViewFinderBinTestContext * ctx) +{ + gst_element_set_state (ctx->pipe, GST_STATE_NULL); + gst_object_unref (ctx->pipe); + memset (ctx, 0, sizeof (GstViewFinderBinTestContext)); +} + +GST_START_TEST (test_simple_run) +{ + GstViewFinderBinTestContext ctx; + GstBus *bus; + GstMessage *msg; + + gstviewfinderbin_init_test_context (&ctx, 10); + bus = gst_element_get_bus (ctx.pipe); + + fail_if (gst_element_set_state (ctx.pipe, GST_STATE_PLAYING) == + GST_STATE_CHANGE_FAILURE); + + msg = gst_bus_timed_pop_filtered (bus, GST_SECOND * 30, + GST_MESSAGE_EOS | GST_MESSAGE_ERROR); + fail_unless (msg != NULL); + fail_unless (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_EOS); + gst_message_unref (msg); + + gstviewfinderbin_unset_test_context (&ctx); + gst_object_unref (bus); +} + +GST_END_TEST; + +static Suite * +viewfinderbin_suite (void) +{ + Suite *s = suite_create ("viewfinderbin"); + TCase *tc_chain = tcase_create ("general"); + + suite_add_tcase (s, tc_chain); + tcase_add_test (tc_chain, test_simple_run); + + return s; +} + +GST_CHECK_MAIN (viewfinderbin); From 7ed49bda4f9d56ecbc48db18a6b0e3a0d52aba69 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Mon, 20 Dec 2010 14:20:35 -0300 Subject: [PATCH 192/448] imagecapturebin: Add another test case Adds a test case to check if a sequence of buffers with different caps can be pushed to imagecapturebin and saved correctly --- tests/check/Makefile.am | 10 ++ tests/check/elements/imagecapturebin.c | 164 +++++++++++++++++++++++-- 2 files changed, 167 insertions(+), 7 deletions(-) diff --git a/tests/check/Makefile.am b/tests/check/Makefile.am index dc86ff433a..947513b2bc 100644 --- a/tests/check/Makefile.am +++ b/tests/check/Makefile.am @@ -210,6 +210,16 @@ elements_camerabin2_LDADD = \ $(GST_LIBS) $(GST_BASE_LIBS) $(GST_PLUGINS_BASE_LIBS) \ $(GST_CHECK_LIBS) elements_camerabin2_SOURCES = elements/camerabin2.c + +elements_imagecapturebin_CFLAGS = \ + -I$(top_builddir)/gst-libs \ + $(GST_CFLAGS) $(GST_BASE_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) \ + $(GST_CHECK_CFLAGS) \ + -DGST_USE_UNSTABLE_API +elements_imagecapturebin_LDADD = \ + $(GST_LIBS) $(GST_BASE_LIBS) $(GST_PLUGINS_BASE_LIBS) \ + $(GST_CHECK_LIBS) -lgstapp-@GST_MAJORMINOR@ +elements_imagecapturebin_SOURCES = elements/imagecapturebin.c endif elements_jifmux_CFLAGS = $(GST_CHECK_CFLAGS) $(GST_OPTION_CFLAGS) $(AM_CFLAGS) $(EXIF_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) diff --git a/tests/check/elements/imagecapturebin.c b/tests/check/elements/imagecapturebin.c index 4afe9ce361..6a1ecee721 100644 --- a/tests/check/elements/imagecapturebin.c +++ b/tests/check/elements/imagecapturebin.c @@ -23,6 +23,8 @@ #include #include +#include +#include #define N_BUFFERS 3 @@ -35,14 +37,14 @@ typedef struct static void gstimagecapturebin_init_test_context (GstImageCaptureBinTestContext * ctx, - gint num_buffers) + const gchar * src, gint num_buffers) { fail_unless (ctx != NULL); ctx->pipe = gst_pipeline_new ("pipeline"); fail_unless (ctx->pipe != NULL); - ctx->src = gst_element_factory_make ("videotestsrc", "src"); - fail_unless (ctx->src != NULL, "Failed to create videotestsrc element"); + ctx->src = gst_element_factory_make (src, "src"); + fail_unless (ctx->src != NULL, "Failed to create src element"); ctx->icbin = gst_element_factory_make ("imagecapturebin", "icbin"); fail_unless (ctx->icbin != NULL, "Failed to create imagecapturebin element"); @@ -51,7 +53,7 @@ gstimagecapturebin_init_test_context (GstImageCaptureBinTestContext * ctx, fail_unless (gst_bin_add (GST_BIN (ctx->pipe), ctx->src)); fail_unless (gst_bin_add (GST_BIN (ctx->pipe), ctx->icbin)); - fail_unless (gst_element_link (ctx->src, ctx->icbin)); + fail_unless (gst_element_link_many (ctx->src, ctx->icbin, NULL)); } static void @@ -69,6 +71,70 @@ make_test_file_name (void) "imagecapturebintest_%%d.cap", g_get_tmp_dir ()); } +static gboolean +get_file_info (const gchar * filename, gint * width, gint * height) +{ + GstElement *playbin = gst_element_factory_make ("playbin2", NULL); + GstElement *fakesink = gst_element_factory_make ("fakesink", NULL); + GstState state = GST_STATE_NULL; + GstPad *pad; + GstCaps *caps; + gchar *uri = g_strdup_printf ("file://%s", filename); + + g_object_set (playbin, "video-sink", fakesink, NULL); + g_object_set (playbin, "uri", uri, NULL); + g_free (uri); + + gst_element_set_state (playbin, GST_STATE_PAUSED); + + gst_element_get_state (playbin, &state, NULL, GST_SECOND * 5); + + fail_unless (state == GST_STATE_PAUSED); + + g_signal_emit_by_name (playbin, "get-video-pad", 0, &pad, NULL); + caps = gst_pad_get_negotiated_caps (pad); + fail_unless (gst_structure_get_int (gst_caps_get_structure (caps, 0), "width", + width)); + fail_unless (gst_structure_get_int (gst_caps_get_structure (caps, 0), + "height", height)); + + gst_object_unref (pad); + gst_element_set_state (playbin, GST_STATE_NULL); + gst_object_unref (playbin); + return TRUE; +} + +static GstBuffer * +create_video_buffer (GstCaps * caps) +{ + GstElement *pipeline; + GstElement *cf; + GstElement *sink; + GstBuffer *buffer; + + pipeline = + gst_parse_launch + ("videotestsrc num-buffers=1 ! capsfilter name=cf ! appsink name=sink", + NULL); + g_assert (pipeline != NULL); + + cf = gst_bin_get_by_name (GST_BIN (pipeline), "cf"); + sink = gst_bin_get_by_name (GST_BIN (pipeline), "sink"); + + g_object_set (G_OBJECT (cf), "caps", caps, NULL); + + gst_element_set_state (pipeline, GST_STATE_PLAYING); + + buffer = gst_app_sink_pull_buffer (GST_APP_SINK (sink)); + + gst_element_set_state (pipeline, GST_STATE_NULL); + gst_object_unref (pipeline); + gst_object_unref (sink); + gst_object_unref (cf); + return buffer; +} + + GST_START_TEST (test_simple_capture) { GstImageCaptureBinTestContext ctx; @@ -77,7 +143,7 @@ GST_START_TEST (test_simple_capture) gchar *test_file_name; gint i; - gstimagecapturebin_init_test_context (&ctx, N_BUFFERS); + gstimagecapturebin_init_test_context (&ctx, "videotestsrc", N_BUFFERS); bus = gst_element_get_bus (ctx.pipe); test_file_name = make_test_file_name (); @@ -119,6 +185,89 @@ GST_START_TEST (test_simple_capture) GST_END_TEST; + +GST_START_TEST (test_multiple_captures_different_caps) +{ + GstImageCaptureBinTestContext ctx; + GstBus *bus; + GstMessage *msg; + gchar *test_file_name; + gint i; + gint widths[] = { 100, 300, 200 }; + gint heights[] = { 300, 200, 100 }; + GstPad *pad; + + gstimagecapturebin_init_test_context (&ctx, "appsrc", N_BUFFERS); + bus = gst_element_get_bus (ctx.pipe); + + test_file_name = make_test_file_name (); + g_object_set (ctx.icbin, "location", test_file_name, NULL); + fail_if (gst_element_set_state (ctx.pipe, GST_STATE_PLAYING) == + GST_STATE_CHANGE_FAILURE); + + /* push data directly because set_caps and buffer pushes on appsrc + * are not serialized into the flow, so we can't guarantee the buffers + * have the caps we want on them when pushed */ + pad = gst_element_get_static_pad (ctx.src, "src"); + + /* push the buffers */ + for (i = 0; i < N_BUFFERS; i++) { + GstCaps *caps; + GstBuffer *buf; + + caps = gst_caps_new_simple ("video/x-raw-yuv", "width", G_TYPE_INT, + widths[i], "height", G_TYPE_INT, heights[i], "framerate", + GST_TYPE_FRACTION, 1, 1, "format", GST_TYPE_FOURCC, + GST_MAKE_FOURCC ('I', '4', '2', '0'), NULL); + + buf = create_video_buffer (caps); + fail_if (buf == NULL); + + fail_unless (gst_pad_push (pad, buf) == GST_FLOW_OK); + gst_caps_unref (caps); + } + gst_app_src_end_of_stream (GST_APP_SRC (ctx.src)); + gst_object_unref (pad); + + msg = gst_bus_timed_pop_filtered (bus, GST_SECOND * 10, + GST_MESSAGE_EOS | GST_MESSAGE_ERROR); + fail_unless (msg != NULL); + fail_unless (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_EOS); + gst_message_unref (msg); + + /* check there are N_BUFFERS files */ + for (i = 0; i < N_BUFFERS; i++) { + gchar *filename; + FILE *f; + gint width = 0, height = 0; + + filename = g_strdup_printf (test_file_name, i); + + fail_unless (g_file_test (filename, G_FILE_TEST_EXISTS)); + fail_unless (g_file_test (filename, G_FILE_TEST_IS_REGULAR)); + fail_if (g_file_test (filename, G_FILE_TEST_IS_SYMLINK)); + + /* check the file isn't empty */ + f = fopen (filename, "r"); + fseek (f, 0, SEEK_END); + fail_unless (ftell (f) > 0); + fclose (f); + + /* get the file info */ + fail_unless (get_file_info (filename, &width, &height)); + fail_unless (width == widths[i]); + fail_unless (height == heights[i]); + + g_free (filename); + } + + gstimagecapturebin_unset_test_context (&ctx); + gst_object_unref (bus); + g_free (test_file_name); +} + +GST_END_TEST; + GST_START_TEST (test_setting_encoder) { GstImageCaptureBinTestContext ctx; @@ -128,7 +277,7 @@ GST_START_TEST (test_setting_encoder) gchar *test_file_name; gint i; - gstimagecapturebin_init_test_context (&ctx, N_BUFFERS); + gstimagecapturebin_init_test_context (&ctx, "videotestsrc", N_BUFFERS); bus = gst_element_get_bus (ctx.pipe); test_file_name = make_test_file_name (); @@ -181,7 +330,7 @@ GST_START_TEST (test_setting_muxer) gchar *test_file_name; gint i; - gstimagecapturebin_init_test_context (&ctx, N_BUFFERS); + gstimagecapturebin_init_test_context (&ctx, "videotestsrc", N_BUFFERS); bus = gst_element_get_bus (ctx.pipe); test_file_name = make_test_file_name (); @@ -236,6 +385,7 @@ imagecapturebin_suite (void) suite_add_tcase (s, tc_chain); tcase_add_test (tc_chain, test_simple_capture); + tcase_add_test (tc_chain, test_multiple_captures_different_caps); tcase_add_test (tc_chain, test_setting_encoder); tcase_add_test (tc_chain, test_setting_muxer); From 2513e9f01b8a141484d789ec04ac3423641aa2fe Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Mon, 20 Dec 2010 18:09:26 -0300 Subject: [PATCH 193/448] wrappercamerabinsrc: Add converters for viewfinder branch Viewfinder branch should have converters as it has to work always anyway. --- gst/camerabin2/gstwrappercamerabinsrc.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/gst/camerabin2/gstwrappercamerabinsrc.c b/gst/camerabin2/gstwrappercamerabinsrc.c index 7fbcc75258..19567ab625 100644 --- a/gst/camerabin2/gstwrappercamerabinsrc.c +++ b/gst/camerabin2/gstwrappercamerabinsrc.c @@ -235,6 +235,7 @@ gst_wrapper_camera_bin_src_construct_pipeline (GstBaseCameraSrc * bcamsrc) GstBin *cbin = GST_BIN (bcamsrc); GstElement *tee; gboolean ret = FALSE; + GstElement *videoscale; GST_DEBUG_OBJECT (self, "constructing pipeline"); @@ -279,6 +280,17 @@ gst_wrapper_camera_bin_src_construct_pipeline (GstBaseCameraSrc * bcamsrc) goto done; self->tee_vf_srcpad = gst_element_get_request_pad (tee, "src%d"); + g_object_set (tee, "alloc-pad", self->tee_vf_srcpad, NULL); + + /* the viewfinder should always work, so we add some converters to it */ + if (!gst_camerabin_create_and_add_element (cbin, "ffmpegcolorspace")) + goto done; + if (!(videoscale = gst_camerabin_create_and_add_element (cbin, "videoscale"))) + goto done; + + gst_object_unref (self->tee_vf_srcpad); + self->tee_vf_srcpad = gst_element_get_static_pad (videoscale, "src"); + self->tee_image_srcpad = gst_element_get_request_pad (tee, "src%d"); self->tee_video_srcpad = gst_element_get_request_pad (tee, "src%d"); @@ -287,7 +299,6 @@ gst_wrapper_camera_bin_src_construct_pipeline (GstBaseCameraSrc * bcamsrc) gst_pad_add_buffer_probe (self->tee_video_srcpad, G_CALLBACK (gst_wrapper_camera_bin_src_vidsrc_probe), self); - g_object_set (tee, "alloc-pad", self->tee_vf_srcpad, NULL); /* hook-up the ghostpads */ gst_ghost_pad_set_target (GST_GHOST_PAD (self->vfsrc), self->tee_vf_srcpad); From 65c5b65d6d55b6c5fdffe66c44e572400688c456 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Mon, 20 Dec 2010 18:30:32 -0300 Subject: [PATCH 194/448] tests: gitignore camerabin2 tests Adds more camerabin2 elements tests to gitignore --- tests/check/elements/.gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/check/elements/.gitignore b/tests/check/elements/.gitignore index 95eaceba02..d9250b84b0 100644 --- a/tests/check/elements/.gitignore +++ b/tests/check/elements/.gitignore @@ -7,6 +7,7 @@ assrender autoconvert autovideoconvert camerabin +camerabin2 deinterleave dataurisrc faac @@ -39,6 +40,7 @@ timidity y4menc valve videorecordingbin +viewfinderbin vp8dec vp8enc zbar From 6e4efe5ad45115aa7785ea47a022f936b6b74038 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Tue, 21 Dec 2010 11:04:00 -0300 Subject: [PATCH 195/448] camerabin2: Refactor tests Refactor tests case so that the same tests can be run for different camera sources. --- tests/check/elements/camerabin2.c | 53 +++++++++++++++++++++++-------- 1 file changed, 39 insertions(+), 14 deletions(-) diff --git a/tests/check/elements/camerabin2.c b/tests/check/elements/camerabin2.c index fe36d098e2..a09bdd844b 100644 --- a/tests/check/elements/camerabin2.c +++ b/tests/check/elements/camerabin2.c @@ -167,6 +167,7 @@ gst_test_camera_src_init (GstTestCameraSrc * self, static GstElement *camera; static GMainLoop *main_loop; +guint32 test_id = 0; /* helper function for filenames */ static const gchar * @@ -178,10 +179,12 @@ make_test_file_name (const gchar * base_name, gint num) * multifilesink like location */ if (num == -1) { g_snprintf (file_name, 999, "%s" G_DIR_SEPARATOR_S - "gstcamerabin2test_%s_%%03d.cap", g_get_tmp_dir (), base_name); + "gstcamerabin2test_%s_%u_%%03d.cap", g_get_tmp_dir (), base_name, + test_id); } else { g_snprintf (file_name, 999, "%s" G_DIR_SEPARATOR_S - "gstcamerabin2test_%s_%03d.cap", g_get_tmp_dir (), base_name, num); + "gstcamerabin2test_%s_%u_%03d.cap", g_get_tmp_dir (), base_name, + test_id, num); } GST_INFO ("capturing to: %s", file_name); @@ -244,7 +247,7 @@ capture_bus_cb (GstBus * bus, GstMessage * message, gpointer data) } static void -setup (void) +setup_wrappercamerabinsrc_videotestsrc (void) { GstBus *bus; GstElement *vfbin; @@ -254,6 +257,8 @@ setup (void) GST_INFO ("init"); + test_id = g_random_int (); + main_loop = g_main_loop_new (NULL, TRUE); camera = gst_check_setup_element ("camerabin2"); @@ -579,22 +584,42 @@ GST_START_TEST (test_supported_caps) GST_END_TEST; + +typedef struct _TestCaseDef +{ + const gchar *name; + gpointer setup_func; +} TestCaseDef; + +TestCaseDef tests[] = { + {"wrappercamerabinsrc", setup_wrappercamerabinsrc_videotestsrc} +}; + static Suite * camerabin_suite (void) { Suite *s = suite_create ("camerabin2"); - TCase *tc_basic = tcase_create ("general"); + gint i; + TCase *tc_generic = tcase_create ("generic"); - /* Test that basic operations run without errors */ - suite_add_tcase (s, tc_basic); - /* Increase timeout due to video recording */ - tcase_set_timeout (tc_basic, 60); - tcase_add_checked_fixture (tc_basic, setup, teardown); - tcase_add_test (tc_basic, test_single_image_capture); - tcase_add_test (tc_basic, test_single_video_recording); - tcase_add_test (tc_basic, test_image_video_cycle); - tcase_add_test (tc_basic, test_multiple_image_captures); - tcase_add_test (tc_basic, test_supported_caps); + suite_add_tcase (s, tc_generic); + tcase_add_checked_fixture (tc_generic, setup_wrappercamerabinsrc_videotestsrc, + teardown); + tcase_add_test (tc_generic, test_supported_caps); + + for (i = 0; i < G_N_ELEMENTS (tests); i++) { + TCase *tc_basic = tcase_create (tests[i].name); + suite_add_tcase (s, tc_basic); + + /* Increase timeout due to video recording */ + tcase_set_timeout (tc_basic, 60); + tcase_add_checked_fixture (tc_basic, tests[i].setup_func, teardown); + + tcase_add_test (tc_basic, test_single_image_capture); + tcase_add_test (tc_basic, test_single_video_recording); + tcase_add_test (tc_basic, test_image_video_cycle); + tcase_add_test (tc_basic, test_multiple_image_captures); + } return s; } From 1ff89c5f83599e509e21f646a0ae1e563e19f2ac Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Tue, 21 Dec 2010 19:22:36 -0300 Subject: [PATCH 196/448] videorecordingbin: Fix leaks --- gst/camerabin2/gstvideorecordingbin.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/gst/camerabin2/gstvideorecordingbin.c b/gst/camerabin2/gstvideorecordingbin.c index 7426375ac6..30973d72ff 100644 --- a/gst/camerabin2/gstvideorecordingbin.c +++ b/gst/camerabin2/gstvideorecordingbin.c @@ -210,9 +210,12 @@ static void gst_video_recording_bin_init (GstVideoRecordingBin * videobin, GstVideoRecordingBinClass * videobin_class) { + GstPadTemplate *templ; + + templ = gst_static_pad_template_get (&sink_template); videobin->ghostpad = - gst_ghost_pad_new_no_target_from_template ("sink", - gst_static_pad_template_get (&sink_template)); + gst_ghost_pad_new_no_target_from_template ("sink", templ); + gst_object_unref (templ); gst_element_add_pad (GST_ELEMENT_CAST (videobin), videobin->ghostpad); videobin->location = g_strdup (DEFAULT_LOCATION); @@ -307,6 +310,8 @@ gst_video_recording_bin_create_elements (GstVideoRecordingBin * videobin) pad = gst_element_get_static_pad (colorspace, "sink"); if (!gst_ghost_pad_set_target (GST_GHOST_PAD (videobin->ghostpad), pad)) goto error; + gst_object_unref (pad); + pad = NULL; videobin->elements_created = TRUE; return TRUE; From 614c4d8f6ebaf6d1c401c41dfca5fcfd6fabf154 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Wed, 22 Dec 2010 11:44:55 -0300 Subject: [PATCH 197/448] basecamerasrc: Notify earlier Notify about ready-for-capture changes earlier to allow camerabin2 to do the videobin state switching before the capture starts. --- gst-libs/gst/basecamerabinsrc/gstbasecamerasrc.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gst-libs/gst/basecamerabinsrc/gstbasecamerasrc.c b/gst-libs/gst/basecamerabinsrc/gstbasecamerasrc.c index 7469f50fb7..57582cba76 100644 --- a/gst-libs/gst/basecamerabinsrc/gstbasecamerasrc.c +++ b/gst-libs/gst/basecamerabinsrc/gstbasecamerasrc.c @@ -232,11 +232,12 @@ gst_base_camera_src_start_capture (GstBaseCameraSrc * src) } src->capturing = TRUE; + g_object_notify (G_OBJECT (src), "ready-for-capture"); if (klass->start_capture (src)) { GST_DEBUG_OBJECT (src, "Capture started"); - g_object_notify (G_OBJECT (src), "ready-for-capture"); } else { src->capturing = FALSE; + g_object_notify (G_OBJECT (src), "ready-for-capture"); GST_WARNING_OBJECT (src, "Failed to start capture"); } g_mutex_unlock (src->capturing_mutex); From e6d0435a8ed722ba1d61b1c2d56a26c1b6fc5ff8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Thu, 23 Dec 2010 22:01:00 +0000 Subject: [PATCH 198/448] mpeg4videoparse: try harder to make buffer metadata writable before modifying Also, check buffer for NULL-ness before dereferencing it. https://bugzilla.gnome.org/show_bug.cgi?id=637824 --- gst/mpeg4videoparse/mpeg4videoparse.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/gst/mpeg4videoparse/mpeg4videoparse.c b/gst/mpeg4videoparse/mpeg4videoparse.c index d23f2cc1fd..254db9fb7d 100644 --- a/gst/mpeg4videoparse/mpeg4videoparse.c +++ b/gst/mpeg4videoparse/mpeg4videoparse.c @@ -502,10 +502,11 @@ gst_mpeg4vparse_push (GstMpeg4VParse * parse, gsize size) GstBuffer *out_buf; out_buf = gst_adapter_take_buffer (parse->adapter, parse->offset); - out_buf = gst_buffer_make_metadata_writable (out_buf); - GST_BUFFER_TIMESTAMP (out_buf) = parse->timestamp; if (G_LIKELY (out_buf)) { + out_buf = gst_buffer_make_metadata_writable (out_buf); + GST_BUFFER_TIMESTAMP (out_buf) = parse->timestamp; + /* Set GST_BUFFER_FLAG_DELTA_UNIT if it's not an intra frame */ if (!parse->intra_frame) { GST_BUFFER_FLAG_SET (out_buf, GST_BUFFER_FLAG_DELTA_UNIT); @@ -540,10 +541,10 @@ gst_mpeg4vparse_push (GstMpeg4VParse * parse, gsize size) /* insert header */ superbuf = gst_buffer_merge (parse->config, out_buf); - - GST_BUFFER_TIMESTAMP (superbuf) = timestamp; gst_buffer_unref (out_buf); - out_buf = superbuf; + + out_buf = gst_buffer_make_metadata_writable (superbuf); + GST_BUFFER_TIMESTAMP (out_buf) = timestamp; if (G_UNLIKELY (timestamp != -1)) { parse->last_report = timestamp; From 29c6a954172c5ffc66b820058c9a64cd76c1a360 Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Fri, 24 Dec 2010 09:50:00 +0000 Subject: [PATCH 199/448] mpegdemux: do not use the pad buffer allocation functions in demuxers https://bugzilla.gnome.org/show_bug.cgi?id=637931 --- gst/mpegdemux/gstmpegtsdemux.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/gst/mpegdemux/gstmpegtsdemux.c b/gst/mpegdemux/gstmpegtsdemux.c index 863547078a..166a246c61 100644 --- a/gst/mpegdemux/gstmpegtsdemux.c +++ b/gst/mpegdemux/gstmpegtsdemux.c @@ -1616,11 +1616,9 @@ gst_mpegts_stream_parse_private_section (GstMpegTSStream * stream, goto wrong_crc; /* just dump this down the pad */ - if (gst_pad_alloc_buffer (stream->pad, 0, datalen, NULL, &buffer) == - GST_FLOW_OK) { - memcpy (buffer->data, data, datalen); - gst_pad_push (stream->pad, buffer); - } + buffer = gst_buffer_new_and_alloc (datalen); + memcpy (buffer->data, data, datalen); + gst_pad_push (stream->pad, buffer); GST_DEBUG_OBJECT (demux, "parsing private section"); return TRUE; From 4422cca1d3f98fcc68895e9a051f38dc22d4f7d7 Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Fri, 24 Dec 2010 10:15:46 +0000 Subject: [PATCH 200/448] mve: do not use the pad buffer allocation functions in demuxers https://bugzilla.gnome.org/show_bug.cgi?id=637929 --- gst/mve/gstmvedemux.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/gst/mve/gstmvedemux.c b/gst/mve/gstmvedemux.c index e60d880205..a101a9059d 100644 --- a/gst/mve/gstmvedemux.c +++ b/gst/mve/gstmvedemux.c @@ -288,14 +288,11 @@ static GstFlowReturn gst_mve_buffer_alloc_for_pad (GstMveDemuxStream * stream, guint32 size, GstBuffer ** buffer) { - GstFlowReturn ret = - gst_pad_alloc_buffer_and_set_caps (stream->pad, stream->offset, - size, stream->caps, buffer); - - if (ret == GST_FLOW_OK) - GST_BUFFER_TIMESTAMP (*buffer) = stream->last_ts; - - return ret; + *buffer = gst_buffer_new_and_alloc (size); + gst_buffer_set_caps (*buffer, stream->caps); + GST_BUFFER_TIMESTAMP (*buffer) = stream->last_ts; + GST_BUFFER_OFFSET (*buffer) = stream->offset; + return GST_FLOW_OK; } static GstFlowReturn From 8574e8f991f68506af3a0c369c933020688bd4c3 Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Mon, 25 Jan 2010 18:58:38 +0000 Subject: [PATCH 201/448] kate: add segment tracking, and various other improvements https://bugzilla.gnome.org/show_bug.cgi?id=600929 --- ext/kate/Makefile.am | 2 +- ext/kate/gstkate.c | 3 + ext/kate/gstkatedec.c | 105 ++++++++++++- ext/kate/gstkatedec.h | 4 +- ext/kate/gstkateparse.c | 5 - ext/kate/gstkatespu.c | 8 - ext/kate/gstkatetiger.c | 325 ++++++++++++++++++++++++++++++++-------- ext/kate/gstkatetiger.h | 8 +- ext/kate/gstkateutil.c | 206 +++++++++++++++++++++++-- ext/kate/gstkateutil.h | 30 +++- 10 files changed, 602 insertions(+), 94 deletions(-) diff --git a/ext/kate/Makefile.am b/ext/kate/Makefile.am index 6a2152d13d..fd7d6ced4d 100644 --- a/ext/kate/Makefile.am +++ b/ext/kate/Makefile.am @@ -10,7 +10,7 @@ endif # flags used to compile this plugin libgstkate_la_CFLAGS = $(GST_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) $(TIGER_CFLAGS) $(KATE_CFLAGS) -libgstkate_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) -lgsttag-$(GST_MAJORMINOR) $(GST_LIBS) $(TIGER_LIBS) $(KATE_LIBS) +libgstkate_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) -lgstvideo-$(GST_MAJORMINOR) -lgsttag-$(GST_MAJORMINOR) $(GST_LIBS) $(TIGER_LIBS) $(KATE_LIBS) libgstkate_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) libgstkate_la_LIBTOOLFLAGS = --tag=disable-static diff --git a/ext/kate/gstkate.c b/ext/kate/gstkate.c index 08adfea8d5..91d0579a6c 100644 --- a/ext/kate/gstkate.c +++ b/ext/kate/gstkate.c @@ -64,6 +64,7 @@ GST_DEBUG_CATEGORY (gst_katedec_debug); GST_DEBUG_CATEGORY (gst_kateenc_debug); GST_DEBUG_CATEGORY (gst_kateparse_debug); GST_DEBUG_CATEGORY (gst_katetag_debug); +GST_DEBUG_CATEGORY (gst_kateutil_debug); #ifdef HAVE_TIGER GST_DEBUG_CATEGORY (gst_katetiger_debug); #endif @@ -75,6 +76,8 @@ plugin_init (GstPlugin * plugin) GST_DEBUG_CATEGORY_INIT (gst_kateenc_debug, "kateenc", 0, "Kate encoder"); GST_DEBUG_CATEGORY_INIT (gst_kateparse_debug, "kateparse", 0, "Kate parser"); GST_DEBUG_CATEGORY_INIT (gst_katetag_debug, "katetag", 0, "Kate tagger"); + GST_DEBUG_CATEGORY_INIT (gst_kateutil_debug, "kateutil", 0, + "Kate utility functions"); #ifdef HAVE_TIGER GST_DEBUG_CATEGORY_INIT (gst_katetiger_debug, "tiger", 0, "Kate Tiger renderer"); diff --git a/ext/kate/gstkatedec.c b/ext/kate/gstkatedec.c index 322363d819..4dbe6d8182 100644 --- a/ext/kate/gstkatedec.c +++ b/ext/kate/gstkatedec.c @@ -128,6 +128,9 @@ static GstFlowReturn gst_kate_dec_chain (GstPad * pad, GstBuffer * buf); static GstStateChangeReturn gst_kate_dec_change_state (GstElement * element, GstStateChange transition); static gboolean gst_kate_dec_sink_query (GstPad * pad, GstQuery * query); +static gboolean gst_kate_dec_sink_event (GstPad * pad, GstEvent * event); +static gboolean gst_kate_dec_sink_handle_event (GstPad * pad, GstEvent * event); +static GstCaps *gst_kate_dec_src_get_caps (GstPad * pad); static void gst_kate_dec_base_init (gpointer gclass) @@ -184,16 +187,21 @@ gst_kate_dec_init (GstKateDec * dec, GstKateDecClass * gclass) GST_DEBUG_FUNCPTR (gst_kate_dec_chain)); gst_pad_set_query_function (dec->sinkpad, GST_DEBUG_FUNCPTR (gst_kate_dec_sink_query)); + gst_pad_set_event_function (dec->sinkpad, + GST_DEBUG_FUNCPTR (gst_kate_dec_sink_event)); gst_pad_use_fixed_caps (dec->sinkpad); gst_pad_set_caps (dec->sinkpad, gst_static_pad_template_get_caps (&sink_factory)); gst_element_add_pad (GST_ELEMENT (dec), dec->sinkpad); dec->srcpad = gst_pad_new_from_static_template (&src_factory, "src"); + gst_pad_set_getcaps_function (dec->srcpad, + GST_DEBUG_FUNCPTR (gst_kate_dec_src_get_caps)); gst_element_add_pad (GST_ELEMENT (dec), dec->srcpad); - gst_kate_util_decode_base_init (&dec->decoder); + gst_kate_util_decode_base_init (&dec->decoder, TRUE); + dec->src_caps = NULL; dec->remove_markup = FALSE; } @@ -240,9 +248,16 @@ gst_kate_dec_chain (GstPad * pad, GstBuffer * buf) const kate_event *ev = NULL; GstFlowReturn rflow = GST_FLOW_OK; + if (!gst_kate_util_decoder_base_update_segment (&kd->decoder, + GST_ELEMENT_CAST (kd), buf)) { + GST_WARNING_OBJECT (kd, "Out of segment!"); + goto not_in_seg; + } + rflow = gst_kate_util_decoder_base_chain_kate_packet (&kd->decoder, - GST_ELEMENT_CAST (kd), pad, buf, kd->srcpad, &ev); + GST_ELEMENT_CAST (kd), pad, buf, kd->srcpad, kd->srcpad, &kd->src_caps, + &ev); if (G_UNLIKELY (rflow != GST_FLOW_OK)) { gst_object_unref (kd); gst_buffer_unref (buf); @@ -336,6 +351,7 @@ gst_kate_dec_chain (GstPad * pad, GstBuffer * buf) } } +not_in_seg: gst_object_unref (kd); gst_buffer_unref (buf); return rflow; @@ -345,6 +361,7 @@ static GstStateChangeReturn gst_kate_dec_change_state (GstElement * element, GstStateChange transition) { GstKateDec *kd = GST_KATE_DEC (element); + return gst_kate_decoder_base_change_state (&kd->decoder, element, parent_class, transition); } @@ -359,3 +376,87 @@ gst_kate_dec_sink_query (GstPad * pad, GstQuery * query) gst_object_unref (kd); return res; } + +static gboolean +gst_kate_dec_sink_event (GstPad * pad, GstEvent * event) +{ + GstKateDec *kd = (GstKateDec *) (gst_object_get_parent (GST_OBJECT (pad))); + gboolean res = TRUE; + + g_return_val_if_fail (kd != NULL, FALSE); + + GST_LOG_OBJECT (kd, "Event on sink pad: %s", GST_EVENT_TYPE_NAME (event)); + + // Delay events till we've set caps + if (gst_kate_util_decoder_base_queue_event (&kd->decoder, event, + &gst_kate_dec_sink_handle_event, pad)) { + gst_object_unref (kd); + return TRUE; + } + + res = gst_kate_dec_sink_handle_event (pad, event); + + gst_object_unref (kd); + + return res; +} + +static gboolean +gst_kate_dec_sink_handle_event (GstPad * pad, GstEvent * event) +{ + GstKateDec *kd = (GstKateDec *) (gst_object_get_parent (GST_OBJECT (pad))); + gboolean res = TRUE; + + g_return_val_if_fail (kd != NULL, FALSE); + + GST_LOG_OBJECT (kd, "Handling event on sink pad: %s", + GST_EVENT_TYPE_NAME (event)); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_NEWSEGMENT: + gst_kate_util_decoder_base_new_segment_event (&kd->decoder, event); + res = gst_pad_event_default (pad, event); + break; + + case GST_EVENT_FLUSH_START: + gst_kate_util_decoder_base_set_flushing (&kd->decoder, TRUE); + res = gst_pad_event_default (pad, event); + break; + + case GST_EVENT_FLUSH_STOP: + gst_kate_util_decoder_base_set_flushing (&kd->decoder, FALSE); + res = gst_pad_event_default (pad, event); + break; + + default: + res = gst_pad_event_default (pad, event); + break; + } + + gst_object_unref (kd); + + return res; +} + +static GstCaps * +gst_kate_dec_src_get_caps (GstPad * pad) +{ + GstKateDec *kd = (GstKateDec *) (gst_object_get_parent (GST_OBJECT (pad))); + GstCaps *caps; + + g_return_val_if_fail (kd != NULL, FALSE); + + if (kd->src_caps) { + GST_DEBUG_OBJECT (kd, "We have src caps (%s)", + gst_caps_to_string (kd->src_caps)); + caps = kd->src_caps; + } else { + GST_DEBUG_OBJECT (kd, "We have no src caps, using template caps"); + caps = gst_static_pad_template_get_caps (&src_factory); + } + + caps = gst_caps_copy (caps); + + gst_object_unref (kd); + return caps; +} diff --git a/ext/kate/gstkatedec.h b/ext/kate/gstkatedec.h index a7011ecbcd..b4d99059a4 100644 --- a/ext/kate/gstkatedec.h +++ b/ext/kate/gstkatedec.h @@ -67,12 +67,12 @@ typedef struct _GstKateDecClass GstKateDecClass; struct _GstKateDec { - GstElement element; + GstKateDecoderBase decoder; GstPad *sinkpad; GstPad *srcpad; - GstKateDecoderBase decoder; + GstCaps *src_caps; gboolean remove_markup; }; diff --git a/ext/kate/gstkateparse.c b/ext/kate/gstkateparse.c index c410666451..6a72edec99 100644 --- a/ext/kate/gstkateparse.c +++ b/ext/kate/gstkateparse.c @@ -255,11 +255,6 @@ gst_kate_parse_push_buffer (GstKateParse * parse, GstBuffer * buf, GST_BUFFER_OFFSET_END (buf) = granulepos; GST_BUFFER_TIMESTAMP (buf) = GST_BUFFER_OFFSET (buf); - /* Hack to flush each packet on its own page - taken off the CMML encoder element */ - /* TODO: this is shite and needs to go once I find a way to tell Ogg to flush - as it messes up Matroska's track duration */ - GST_BUFFER_DURATION (buf) = G_MAXINT64; - gst_buffer_set_caps (buf, GST_PAD_CAPS (parse->srcpad)); return gst_pad_push (parse->srcpad, buf); diff --git a/ext/kate/gstkatespu.c b/ext/kate/gstkatespu.c index 778288ecfc..13f561941a 100644 --- a/ext/kate/gstkatespu.c +++ b/ext/kate/gstkatespu.c @@ -804,14 +804,6 @@ gst_kate_spu_encode_spu (GstKateDec * kd, const kate_event * ev) bytes[nbytes++] = ((kp->colors[palette[1]].a / 17) << 4) | (kp->colors[palette[0]].a / 17); -#if 0 - // move to top left - avoids a crash in dvdspu when overlaying on a small video :/ - right -= left; - bottom -= top; - left = 0; - top = 0; -#endif - CHKBUFSPC (7 * 2); bytes[nbytes++] = SPU_CMD_SET_DAREA; bytes[nbytes++] = left >> 4; diff --git a/ext/kate/gstkatetiger.c b/ext/kate/gstkatetiger.c index 93d98e73ad..286929796b 100644 --- a/ext/kate/gstkatetiger.c +++ b/ext/kate/gstkatetiger.c @@ -88,6 +88,19 @@ GST_DEBUG_CATEGORY_EXTERN (gst_katetiger_debug); #define GST_CAT_DEFAULT gst_katetiger_debug +#define GST_KATE_TIGER_MUTEX_LOCK(element) \ + do { \ + /*GST_LOG_OBJECT ((element), "locking from %s:%d\n",__FILE__,__LINE__);*/ \ + g_mutex_lock ((element)->mutex); \ + /*GST_LOG_OBJECT ((element), "ready from %s:%d\n",__FILE__,__LINE__);*/ \ + } while(0) + +#define GST_KATE_TIGER_MUTEX_UNLOCK(element) \ + do { \ + /*GST_LOG_OBJECT ((element), "unlocking from %s:%d\n",__FILE__,__LINE__);*/ \ + g_mutex_unlock ((element)->mutex); \ + } while(0) + /* Filter signals and args */ enum { @@ -119,16 +132,28 @@ static GstStaticPadTemplate kate_sink_factory = ); static GstStaticPadTemplate video_sink_factory = -GST_STATIC_PAD_TEMPLATE ("video_sink", + GST_STATIC_PAD_TEMPLATE ("video_sink", GST_PAD_SINK, GST_PAD_ALWAYS, - GST_STATIC_CAPS ("video/x-raw-rgb, bpp=(int)32, depth=(int)24") +#if G_BYTE_ORDER == G_LITTLE_ENDIAN + GST_STATIC_CAPS (GST_VIDEO_CAPS_xRGB ", endianness = (int) 1234" ";" + GST_VIDEO_CAPS_BGRx ", endianness = (int)4321") +#else + GST_STATIC_CAPS (GST_VIDEO_CAPS_xRGB ", endianness = (int) 4321" ";" + GST_VIDEO_CAPS_BGRx ", endianness = (int)1234") +#endif ); static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, - GST_STATIC_CAPS ("video/x-raw-rgb, bpp=(int)32, depth=(int)24") +#if G_BYTE_ORDER == G_LITTLE_ENDIAN + GST_STATIC_CAPS (GST_VIDEO_CAPS_xRGB ", endianness = (int) 1234" ";" + GST_VIDEO_CAPS_BGRx ", endianness = (int)4321") +#else + GST_STATIC_CAPS (GST_VIDEO_CAPS_xRGB ", endianness = (int) 4321" ";" + GST_VIDEO_CAPS_BGRx ", endianness = (int)1234") +#endif ); GST_BOILERPLATE (GstKateTiger, gst_kate_tiger, GstElement, GST_TYPE_ELEMENT); @@ -163,6 +188,7 @@ static GstStateChangeReturn gst_kate_tiger_change_state (GstElement * element, GstStateChange transition); static gboolean gst_kate_tiger_kate_sink_query (GstPad * pad, GstQuery * query); static gboolean gst_kate_tiger_kate_event (GstPad * pad, GstEvent * event); +static gboolean gst_kate_tiger_video_event (GstPad * pad, GstEvent * event); static gboolean gst_kate_tiger_video_set_caps (GstPad * pad, GstCaps * caps); static gboolean gst_kate_tiger_source_event (GstPad * pad, GstEvent * event); @@ -302,19 +328,19 @@ gst_kate_tiger_init (GstKateTiger * tiger, GstKateTigerClass * gclass) gst_pad_new_from_static_template (&video_sink_factory, "video_sink"); gst_pad_set_chain_function (tiger->videosinkpad, GST_DEBUG_FUNCPTR (gst_kate_tiger_video_chain)); - //gst_pad_set_query_function (tiger->videosinkpad, GST_DEBUG_FUNCPTR (gst_kate_tiger_video_sink_query)); gst_pad_use_fixed_caps (tiger->videosinkpad); - gst_pad_set_caps (tiger->videosinkpad, - gst_static_pad_template_get_caps (&video_sink_factory)); gst_pad_set_setcaps_function (tiger->videosinkpad, GST_DEBUG_FUNCPTR (gst_kate_tiger_video_set_caps)); + gst_pad_set_event_function (tiger->videosinkpad, + GST_DEBUG_FUNCPTR (gst_kate_tiger_video_event)); gst_element_add_pad (GST_ELEMENT (tiger), tiger->videosinkpad); tiger->srcpad = gst_pad_new_from_static_template (&src_factory, "src"); gst_pad_set_event_function (tiger->srcpad, gst_kate_tiger_source_event); + gst_pad_use_fixed_caps (tiger->srcpad); gst_element_add_pad (GST_ELEMENT (tiger), tiger->srcpad); - gst_kate_util_decode_base_init (&tiger->decoder); + gst_kate_util_decode_base_init (&tiger->decoder, FALSE); tiger->tr = NULL; @@ -400,7 +426,7 @@ gst_kate_tiger_set_property (GObject * object, guint prop_id, GstKateTiger *tiger = GST_KATE_TIGER (object); const char *str; - g_mutex_lock (tiger->mutex); + GST_KATE_TIGER_MUTEX_LOCK (tiger); switch (prop_id) { case ARG_DEFAULT_FONT_DESC: @@ -465,7 +491,7 @@ gst_kate_tiger_set_property (GObject * object, guint prop_id, break; } - g_mutex_unlock (tiger->mutex); + GST_KATE_TIGER_MUTEX_UNLOCK (tiger); } static void @@ -474,7 +500,7 @@ gst_kate_tiger_get_property (GObject * object, guint prop_id, { GstKateTiger *tiger = GST_KATE_TIGER (object); - g_mutex_lock (tiger->mutex); + GST_KATE_TIGER_MUTEX_LOCK (tiger); switch (prop_id) { case ARG_DEFAULT_FONT_DESC: @@ -522,7 +548,7 @@ gst_kate_tiger_get_property (GObject * object, guint prop_id, break; } - g_mutex_unlock (tiger->mutex); + GST_KATE_TIGER_MUTEX_UNLOCK (tiger); } /* GstElement vmethod implementations */ @@ -538,30 +564,36 @@ gst_kate_tiger_kate_chain (GstPad * pad, GstBuffer * buf) const kate_event *ev = NULL; GstFlowReturn rflow = GST_FLOW_OK; - g_mutex_lock (tiger->mutex); + GST_KATE_TIGER_MUTEX_LOCK (tiger); - GST_LOG_OBJECT (tiger, "Got kate buffer"); + GST_LOG_OBJECT (tiger, "Got kate buffer, caps %s", + gst_caps_to_string (GST_BUFFER_CAPS (buf))); - rflow = - gst_kate_util_decoder_base_chain_kate_packet (&tiger->decoder, - GST_ELEMENT_CAST (tiger), pad, buf, tiger->srcpad, &ev); - if (G_LIKELY (rflow == GST_FLOW_OK)) { - if (ev) { - int ret = tiger_renderer_add_event (tiger->tr, ev->ki, ev); - GST_INFO_OBJECT (tiger, "adding event for %p from %f to %f: %p, \"%s\"", - ev->ki, ev->start_time, ev->end_time, ev->bitmap, ev->text); - if (G_UNLIKELY (ret < 0)) { - GST_WARNING_OBJECT (tiger, - "failed to add Kate event to Tiger renderer: %d", ret); + if (gst_kate_util_decoder_base_update_segment (&tiger->decoder, + GST_ELEMENT_CAST (tiger), buf)) { + GstPad *tagpad = gst_pad_get_peer (pad); + rflow = + gst_kate_util_decoder_base_chain_kate_packet (&tiger->decoder, + GST_ELEMENT_CAST (tiger), pad, buf, tiger->srcpad, tagpad, NULL, &ev); + if (G_LIKELY (rflow == GST_FLOW_OK)) { + if (ev) { + int ret = tiger_renderer_add_event (tiger->tr, ev->ki, ev); + GST_INFO_OBJECT (tiger, "adding event for %p from %f to %f: %p, \"%s\"", + ev->ki, ev->start_time, ev->end_time, ev->bitmap, ev->text); + if (G_UNLIKELY (ret < 0)) { + GST_WARNING_OBJECT (tiger, + "failed to add Kate event to Tiger renderer: %d", ret); + } } } + gst_object_unref (tagpad); } + GST_KATE_TIGER_MUTEX_UNLOCK (tiger); + gst_object_unref (tiger); gst_buffer_unref (buf); - g_mutex_unlock (tiger->mutex); - return rflow; } @@ -569,28 +601,36 @@ static gboolean gst_kate_tiger_video_set_caps (GstPad * pad, GstCaps * caps) { GstKateTiger *tiger = GST_KATE_TIGER (gst_pad_get_parent (pad)); - GstStructure *s; + GstVideoFormat format; gint w, h; - gboolean res = FALSE; - g_mutex_lock (tiger->mutex); + GST_KATE_TIGER_MUTEX_LOCK (tiger); - s = gst_caps_get_structure (caps, 0); + /* Cairo expects ARGB in native endianness, and that's what we get + as we've forced it in the caps. We might allow swapped red/blue + at some point, and get tiger to swap, to make some cases faster */ + tiger->swap_rgb = FALSE; - if (G_LIKELY (gst_structure_get_int (s, "width", &w)) - && G_LIKELY (gst_structure_get_int (s, "height", &h))) { - GST_INFO_OBJECT (tiger, "video sink: %d %d", w, h); + if (gst_video_format_parse_caps (caps, &format, &w, &h)) { tiger->video_width = w; tiger->video_height = h; - res = TRUE; } - g_mutex_unlock (tiger->mutex); + GST_KATE_TIGER_MUTEX_UNLOCK (tiger); + + gst_pad_set_caps (tiger->srcpad, caps); gst_object_unref (tiger); return TRUE; } +static gdouble +gst_kate_tiger_get_time (GstKateTiger * tiger) +{ + return gst_segment_to_running_time (&tiger->video_segment, GST_FORMAT_TIME, + tiger->video_segment.last_stop) / (gdouble) GST_SECOND; +} + static GstFlowReturn gst_kate_tiger_video_chain (GstPad * pad, GstBuffer * buf) { @@ -599,10 +639,22 @@ gst_kate_tiger_video_chain (GstPad * pad, GstBuffer * buf) unsigned char *ptr; int ret; - g_mutex_lock (tiger->mutex); + GST_KATE_TIGER_MUTEX_LOCK (tiger); GST_LOG_OBJECT (tiger, "got video frame, %u bytes", GST_BUFFER_SIZE (buf)); + if (G_UNLIKELY (tiger->video_flushing)) { + GST_KATE_TIGER_MUTEX_UNLOCK (tiger); + gst_object_unref (tiger); + gst_buffer_unref (buf); + return GST_FLOW_WRONG_STATE; + } + + if (G_LIKELY (GST_BUFFER_TIMESTAMP_IS_VALID (buf))) { + gst_segment_set_last_stop (&tiger->video_segment, GST_FORMAT_TIME, + GST_BUFFER_TIMESTAMP (buf)); + } + /* draw on it */ buf = gst_buffer_make_writable (buf); if (G_UNLIKELY (!buf)) { @@ -613,12 +665,17 @@ gst_kate_tiger_video_chain (GstPad * pad, GstBuffer * buf) GST_WARNING_OBJECT (tiger, "Failed to get a pointer to video buffer data"); } else { - ret = tiger_renderer_set_buffer (tiger->tr, ptr, tiger->video_width, tiger->video_height, tiger->video_width * 4, 0); // TODO: stride ? + ret = + tiger_renderer_set_buffer (tiger->tr, ptr, tiger->video_width, + tiger->video_height, tiger->video_width * 4, tiger->swap_rgb); if (G_UNLIKELY (ret < 0)) { GST_WARNING_OBJECT (tiger, "Tiger renderer failed to set buffer to video frame: %d", ret); } else { - kate_float t = GST_BUFFER_TIMESTAMP (buf) / (gdouble) GST_SECOND; + kate_float t = gst_kate_tiger_get_time (tiger); + GST_LOG_OBJECT (tiger, "Video segment calc: last stop %ld, time %.3f", + (long) tiger->video_segment.last_stop, t); + ret = tiger_renderer_update (tiger->tr, t, 1); if (G_UNLIKELY (ret < 0)) { GST_WARNING_OBJECT (tiger, "Tiger renderer failed to update: %d", @@ -636,12 +693,13 @@ gst_kate_tiger_video_chain (GstPad * pad, GstBuffer * buf) } } } + + GST_KATE_TIGER_MUTEX_UNLOCK (tiger); + rflow = gst_pad_push (tiger->srcpad, buf); gst_object_unref (tiger); - g_mutex_unlock (tiger->mutex); - return rflow; } @@ -654,12 +712,14 @@ gst_kate_tiger_change_state (GstElement * element, GstStateChange transition) switch (transition) { case GST_STATE_CHANGE_PAUSED_TO_READY: GST_DEBUG_OBJECT (tiger, "PAUSED -> READY, clearing kate state"); - g_mutex_lock (tiger->mutex); + GST_KATE_TIGER_MUTEX_LOCK (tiger); if (tiger->tr) { tiger_renderer_destroy (tiger->tr); tiger->tr = NULL; } - g_mutex_unlock (tiger->mutex); + gst_segment_init (&tiger->video_segment, GST_FORMAT_UNDEFINED); + tiger->video_flushing = TRUE; + GST_KATE_TIGER_MUTEX_UNLOCK (tiger); break; default: break; @@ -672,7 +732,7 @@ gst_kate_tiger_change_state (GstElement * element, GstStateChange transition) switch (transition) { case GST_STATE_CHANGE_READY_TO_PAUSED: GST_DEBUG_OBJECT (tiger, "READY -> PAUSED, initializing kate state"); - g_mutex_lock (tiger->mutex); + GST_KATE_TIGER_MUTEX_LOCK (tiger); if (tiger->decoder.initialized) { int ret = tiger_renderer_create (&tiger->tr); if (ret < 0) { @@ -692,7 +752,9 @@ gst_kate_tiger_change_state (GstElement * element, GstStateChange transition) gst_kate_tiger_update_quality (tiger); } } - g_mutex_unlock (tiger->mutex); + gst_segment_init (&tiger->video_segment, GST_FORMAT_UNDEFINED); + tiger->video_flushing = FALSE; + GST_KATE_TIGER_MUTEX_UNLOCK (tiger); break; default: break; @@ -713,18 +775,42 @@ gst_kate_tiger_seek (GstKateTiger * tiger, GstPad * pad, GstEvent * event) gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur, &stop_type, &stop); + GST_KATE_TIGER_MUTEX_LOCK (tiger); + tiger->video_flushing = TRUE; + gst_kate_util_decoder_base_set_flushing (&tiger->decoder, TRUE); + GST_KATE_TIGER_MUTEX_UNLOCK (tiger); + + if (format == GST_FORMAT_TIME) { + /* if seeking in time, we can update tiger to remove any appropriate events */ + kate_float target; + switch (cur_type) { + case GST_SEEK_TYPE_SET: + target = cur / (float) GST_SECOND; + break; + case GST_SEEK_TYPE_CUR: + target = gst_kate_tiger_get_time (tiger) + cur / (float) GST_SECOND; + break; + case GST_SEEK_TYPE_END: + GST_WARNING_OBJECT (tiger, + "Seeking from the end, cannot work out target so flushing everything"); + target = (kate_float) 0; + break; + default: + GST_WARNING_OBJECT (tiger, "Unexpected seek type"); + target = (kate_float) 0; + break; + } + GST_INFO_OBJECT (tiger, "Seeking in time to %f", target); + GST_KATE_TIGER_MUTEX_LOCK (tiger); + tiger_renderer_seek (tiger->tr, target); + GST_KATE_TIGER_MUTEX_UNLOCK (tiger); + } + /* forward to both sinks */ gst_event_ref (event); if (gst_pad_push_event (tiger->videosinkpad, event)) { - if (gst_pad_push_event (tiger->katesinkpad, event)) { - if (format == GST_FORMAT_TIME) { - /* if seeking in time, we can update tiger to remove any appropriate events */ - kate_float target = cur / (gdouble) GST_SECOND; - GST_INFO_OBJECT (tiger, "Seeking in time to %f", target); - g_mutex_lock (tiger->mutex); - tiger_renderer_seek (tiger->tr, target); - g_mutex_unlock (tiger->mutex); - } + int ret = gst_pad_push_event (tiger->katesinkpad, event); + if (ret) { return TRUE; } else { return FALSE; @@ -744,6 +830,9 @@ gst_kate_tiger_source_event (GstPad * pad, GstEvent * event) g_return_val_if_fail (tiger != NULL, FALSE); + GST_LOG_OBJECT (tiger, "Event on source pad: %s", + GST_EVENT_TYPE_NAME (event)); + switch (GST_EVENT_TYPE (event)) { case GST_EVENT_SEEK: GST_INFO_OBJECT (tiger, "Seek on source pad"); @@ -759,6 +848,49 @@ gst_kate_tiger_source_event (GstPad * pad, GstEvent * event) return res; } +static gboolean +gst_kate_tiger_handle_kate_event (GstPad * pad, GstEvent * event) +{ + GstKateTiger *tiger = + (GstKateTiger *) (gst_object_get_parent (GST_OBJECT (pad))); + gboolean res = TRUE; + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_NEWSEGMENT: + GST_INFO_OBJECT (tiger, "New segment on Kate pad"); + GST_KATE_TIGER_MUTEX_LOCK (tiger); + gst_kate_util_decoder_base_new_segment_event (&tiger->decoder, event); + GST_KATE_TIGER_MUTEX_UNLOCK (tiger); + gst_event_unref (event); + break; + case GST_EVENT_FLUSH_START: + GST_KATE_TIGER_MUTEX_LOCK (tiger); + gst_kate_util_decoder_base_set_flushing (&tiger->decoder, TRUE); + GST_KATE_TIGER_MUTEX_UNLOCK (tiger); + gst_event_unref (event); + break; + case GST_EVENT_FLUSH_STOP: + GST_KATE_TIGER_MUTEX_LOCK (tiger); + gst_kate_util_decoder_base_set_flushing (&tiger->decoder, FALSE); + GST_KATE_TIGER_MUTEX_UNLOCK (tiger); + gst_event_unref (event); + break; + case GST_EVENT_EOS: + /* we ignore this, it just means we don't have anymore Kate packets, but + the Tiger renderer will still draw (if appropriate) on incoming video */ + GST_INFO_OBJECT (tiger, "EOS on Kate pad"); + gst_event_unref (event); + break; + default: + res = gst_pad_event_default (pad, event); + break; + } + + gst_object_unref (tiger); + + return res; +} + static gboolean gst_kate_tiger_kate_event (GstPad * pad, GstEvent * event) { @@ -768,16 +900,69 @@ gst_kate_tiger_kate_event (GstPad * pad, GstEvent * event) g_return_val_if_fail (tiger != NULL, FALSE); + GST_LOG_OBJECT (tiger, "Event on Kate pad: %s", GST_EVENT_TYPE_NAME (event)); + + /* Delay events till we've set caps */ + if (gst_kate_util_decoder_base_queue_event (&tiger->decoder, event, + &gst_kate_tiger_handle_kate_event, pad)) { + gst_object_unref (tiger); + return TRUE; + } + + res = gst_kate_tiger_handle_kate_event (pad, event); + + gst_object_unref (tiger); + + return res; +} + +static gboolean +gst_kate_tiger_handle_video_event (GstPad * pad, GstEvent * event) +{ + GstKateTiger *tiger = + (GstKateTiger *) (gst_object_get_parent (GST_OBJECT (pad))); + gboolean res = TRUE; + switch (GST_EVENT_TYPE (event)) { case GST_EVENT_NEWSEGMENT: - GST_INFO_OBJECT (tiger, "New segment on Kate pad"); - gst_event_unref (event); + { + gboolean update; + gdouble rate, arate; + GstFormat format; + gint64 start, stop, time; + + gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format, + &start, &stop, &time); + + if (format == GST_FORMAT_TIME) { + GST_DEBUG_OBJECT (tiger, "video pad segment:" + " Update %d, rate %g arate %g format %d start %" GST_TIME_FORMAT + " %" GST_TIME_FORMAT " position %" GST_TIME_FORMAT, + update, rate, arate, format, GST_TIME_ARGS (start), + GST_TIME_ARGS (stop), GST_TIME_ARGS (time)); + + GST_KATE_TIGER_MUTEX_LOCK (tiger); + gst_segment_set_newsegment_full (&tiger->video_segment, update, rate, + arate, format, start, stop, time); + GST_KATE_TIGER_MUTEX_UNLOCK (tiger); + } + + res = gst_pad_event_default (pad, event); break; - case GST_EVENT_EOS: - /* we ignore this, it just means we don't have anymore Kate packets, but - the Tiger renderer will still draw (if appropriate) on incoming video */ - GST_INFO_OBJECT (tiger, "EOS on Kate pad"); - gst_event_unref (event); + } + case GST_EVENT_FLUSH_START: + GST_KATE_TIGER_MUTEX_LOCK (tiger); + gst_segment_init (&tiger->video_segment, GST_FORMAT_UNDEFINED); + tiger->video_flushing = TRUE; + GST_KATE_TIGER_MUTEX_UNLOCK (tiger); + res = gst_pad_event_default (pad, event); + break; + case GST_EVENT_FLUSH_STOP: + GST_KATE_TIGER_MUTEX_LOCK (tiger); + gst_segment_init (&tiger->video_segment, GST_FORMAT_UNDEFINED); + tiger->video_flushing = FALSE; + GST_KATE_TIGER_MUTEX_UNLOCK (tiger); + res = gst_pad_event_default (pad, event); break; default: res = gst_pad_event_default (pad, event); @@ -789,12 +974,32 @@ gst_kate_tiger_kate_event (GstPad * pad, GstEvent * event) return res; } +static gboolean +gst_kate_tiger_video_event (GstPad * pad, GstEvent * event) +{ + GstKateTiger *tiger = + (GstKateTiger *) (gst_object_get_parent (GST_OBJECT (pad))); + gboolean res = TRUE; + + g_return_val_if_fail (tiger != NULL, FALSE); + + GST_INFO_OBJECT (tiger, "Event on video pad: %s", + GST_EVENT_TYPE_NAME (event)); + + res = gst_kate_tiger_handle_video_event (pad, event); + + gst_object_unref (tiger); + + return res; +} + gboolean gst_kate_tiger_kate_sink_query (GstPad * pad, GstQuery * query) { GstKateTiger *tiger = GST_KATE_TIGER (gst_pad_get_parent (pad)); gboolean res = gst_kate_decoder_base_sink_query (&tiger->decoder, GST_ELEMENT_CAST (tiger), pad, query); + GST_INFO_OBJECT (tiger, "Query on Kate pad"); gst_object_unref (tiger); return res; } diff --git a/ext/kate/gstkatetiger.h b/ext/kate/gstkatetiger.h index 0ab7dc136a..353f9f79ec 100644 --- a/ext/kate/gstkatetiger.h +++ b/ext/kate/gstkatetiger.h @@ -68,14 +68,12 @@ typedef struct _GstKateTigerClass GstKateTigerClass; struct _GstKateTiger { - GstElement element; + GstKateDecoderBase decoder; GstPad *katesinkpad; GstPad *videosinkpad; GstPad *srcpad; - GstKateDecoderBase decoder; - tiger_renderer *tr; gdouble quality; @@ -93,8 +91,12 @@ struct _GstKateTiger gint video_width; gint video_height; + gboolean swap_rgb; GMutex *mutex; + + GstSegment video_segment; + gboolean video_flushing; }; struct _GstKateTigerClass diff --git a/ext/kate/gstkateutil.c b/ext/kate/gstkateutil.c index 5b71b94a31..0bccc4b6fa 100644 --- a/ext/kate/gstkateutil.c +++ b/ext/kate/gstkateutil.c @@ -23,10 +23,17 @@ # include "config.h" #endif +#include #include #include "gstkate.h" #include "gstkateutil.h" +GST_DEBUG_CATEGORY_EXTERN (gst_kateutil_debug); +#define GST_CAT_DEFAULT gst_kateutil_debug + +static void gst_kate_util_decoder_base_free_event_queue (GstKateDecoderBase * + decoder); + GstCaps * gst_kate_util_set_header_on_caps (GstElement * element, GstCaps * caps, GList * headers) @@ -95,7 +102,8 @@ gst_kate_util_install_decoder_base_properties (GObjectClass * gobject_class) } void -gst_kate_util_decode_base_init (GstKateDecoderBase * decoder) +gst_kate_util_decode_base_init (GstKateDecoderBase * decoder, + gboolean delay_events) { if (G_UNLIKELY (!decoder)) return; @@ -106,6 +114,8 @@ gst_kate_util_decode_base_init (GstKateDecoderBase * decoder) decoder->original_canvas_height = 0; decoder->tags = NULL; decoder->initialized = FALSE; + decoder->delay_events = delay_events; + decoder->event_queue = NULL; } static void @@ -121,9 +131,76 @@ gst_kate_util_decode_base_reset (GstKateDecoderBase * decoder) } decoder->original_canvas_width = 0; decoder->original_canvas_height = 0; + if (decoder->event_queue) { + gst_kate_util_decoder_base_free_event_queue (decoder); + } decoder->initialized = FALSE; } +gboolean +gst_kate_util_decoder_base_queue_event (GstKateDecoderBase * decoder, + GstEvent * event, gboolean (*handler) (GstPad *, GstEvent *), GstPad * pad) +{ + gboolean can_be_queued; + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_FLUSH_START: + case GST_EVENT_FLUSH_STOP: + case GST_EVENT_EOS: + can_be_queued = FALSE; + break; + default: + can_be_queued = TRUE; + break; + } + + if (decoder->delay_events && can_be_queued) { + GstKateDecoderBaseQueuedEvent *item; + GST_DEBUG_OBJECT (decoder, "We have to delay the event"); + item = g_slice_new (GstKateDecoderBaseQueuedEvent); + if (item) { + item->event = event; + item->pad = pad; + item->handler = handler; + g_queue_push_tail (decoder->event_queue, item); + return TRUE; + } else { + return FALSE; + } + } else { + return FALSE; + } +} + +static void +gst_kate_util_decoder_base_free_event_queue (GstKateDecoderBase * decoder) +{ + while (decoder->event_queue->length) { + GstKateDecoderBaseQueuedEvent *item = (GstKateDecoderBaseQueuedEvent *) + g_queue_pop_head (decoder->event_queue); + g_slice_free (GstKateDecoderBaseQueuedEvent, item); + } + g_queue_free (decoder->event_queue); + decoder->event_queue = NULL; +} + +static void +gst_kate_util_decoder_base_drain_event_queue (GstKateDecoderBase * decoder) +{ + decoder->delay_events = FALSE; + + if (decoder->event_queue->length == 0) + return; + + GST_DEBUG_OBJECT (decoder, "We can now drain all events!"); + while (decoder->event_queue->length) { + GstKateDecoderBaseQueuedEvent *item = (GstKateDecoderBaseQueuedEvent *) + g_queue_pop_head (decoder->event_queue); + (*item->handler) (item->pad, item->event); + g_slice_free (GstKateDecoderBaseQueuedEvent, item); + } +} + gboolean gst_kate_util_decoder_base_get_property (GstKateDecoderBase * decoder, GObject * object, guint prop_id, GValue * value, GParamSpec * pspec) @@ -152,38 +229,67 @@ gst_kate_util_decoder_base_get_property (GstKateDecoderBase * decoder, GstFlowReturn gst_kate_util_decoder_base_chain_kate_packet (GstKateDecoderBase * decoder, GstElement * element, GstPad * pad, GstBuffer * buf, GstPad * srcpad, - const kate_event ** ev) + GstPad * tagpad, GstCaps ** src_caps, const kate_event ** ev) { kate_packet kp; int ret; GstFlowReturn rflow = GST_FLOW_OK; + gboolean is_header; GST_DEBUG_OBJECT (element, "got kate packet, %u bytes, type %02x", GST_BUFFER_SIZE (buf), GST_BUFFER_SIZE (buf) == 0 ? -1 : GST_BUFFER_DATA (buf)[0]); + + is_header = GST_BUFFER_SIZE (buf) > 0 && (GST_BUFFER_DATA (buf)[0] & 0x80); + + if (!is_header && decoder->tags) { + /* after we've processed headers, send any tags before processing the data packet */ + GST_DEBUG_OBJECT (element, "Not a header, sending tags for pad %s:%s", + GST_DEBUG_PAD_NAME (tagpad)); + gst_element_found_tags_for_pad (element, tagpad, decoder->tags); + decoder->tags = NULL; + } + kate_packet_wrap (&kp, GST_BUFFER_SIZE (buf), GST_BUFFER_DATA (buf)); ret = kate_high_decode_packetin (&decoder->k, &kp, ev); if (G_UNLIKELY (ret < 0)) { GST_ELEMENT_ERROR (element, STREAM, DECODE, (NULL), ("Failed to decode Kate packet: %d", ret)); return GST_FLOW_ERROR; - } else if (G_UNLIKELY (ret > 0)) { + } + + if (G_UNLIKELY (ret > 0)) { GST_DEBUG_OBJECT (element, "kate_high_decode_packetin has received EOS packet"); - return GST_FLOW_OK; } /* headers may be interesting to retrieve information from */ - if (G_LIKELY (GST_BUFFER_SIZE (buf) > 0)) + if (G_UNLIKELY (is_header)) { switch (GST_BUFFER_DATA (buf)[0]) { - GstCaps *caps; - case 0x80: /* ID header */ GST_INFO_OBJECT (element, "Parsed ID header: language %s, category %s", decoder->k.ki->language, decoder->k.ki->category); - caps = gst_caps_new_simple ("text/x-pango-markup", NULL); - gst_pad_set_caps (srcpad, caps); - gst_caps_unref (caps); + if (src_caps) { + if (*src_caps) { + gst_caps_unref (*src_caps); + *src_caps = NULL; + } + if (strcmp (decoder->k.ki->category, "K-SPU") == 0 || + strcmp (decoder->k.ki->category, "spu-subtitles") == 0) { + *src_caps = gst_caps_new_simple ("video/x-dvd-subpicture", NULL); + } else if (decoder->k.ki->text_markup_type == kate_markup_none) { + *src_caps = gst_caps_new_simple ("text/plain", NULL); + } else { + *src_caps = gst_caps_new_simple ("text/x-pango-markup", NULL); + } + GST_INFO_OBJECT (element, "Setting src caps to %s", + gst_caps_to_string (*src_caps)); + if (!gst_pad_set_caps (srcpad, *src_caps)) { + GST_ERROR_OBJECT (element, + "Failed to renegotiate caps for pad %s:%s", + GST_DEBUG_PAD_NAME (srcpad)); + } + } if (decoder->k.ki->language && *decoder->k.ki->language) { GstTagList *old = decoder->tags, *tags = gst_tag_list_new (); if (tags) { @@ -214,6 +320,9 @@ gst_kate_util_decoder_base_chain_kate_packet (GstKateDecoderBase * decoder, decoder->original_canvas_width = decoder->k.ki->original_canvas_width; decoder->original_canvas_height = decoder->k.ki->original_canvas_height; + /* we can now send away any event we've delayed, as the src pad now has caps */ + gst_kate_util_decoder_base_drain_event_queue (decoder); + break; case 0x81: /* Vorbis comments header */ @@ -247,8 +356,9 @@ gst_kate_util_decoder_base_chain_kate_packet (GstKateDecoderBase * decoder, if (old) gst_tag_list_free (old); +#if 0 if (decoder->initialized) { - gst_element_found_tags_for_pad (element, srcpad, decoder->tags); + gst_element_found_tags_for_pad (element, tagpad, decoder->tags); decoder->tags = NULL; } else { /* Only push them as messages for the time being. * @@ -257,12 +367,14 @@ gst_kate_util_decoder_base_chain_kate_packet (GstKateDecoderBase * decoder, gst_message_new_tag (GST_OBJECT (element), gst_tag_list_copy (decoder->tags))); } +#endif } break; default: break; } + } return rflow; } @@ -285,7 +397,10 @@ gst_kate_decoder_base_change_state (GstKateDecoderBase * decoder, GST_WARNING_OBJECT (element, "failed to initialize kate state: %d", ret); } + gst_segment_init (&decoder->kate_segment, GST_FORMAT_UNDEFINED); + decoder->kate_flushing = FALSE; decoder->initialized = TRUE; + decoder->event_queue = g_queue_new (); break; case GST_STATE_CHANGE_PAUSED_TO_PLAYING: break; @@ -304,6 +419,8 @@ gst_kate_decoder_base_change_state (GstKateDecoderBase * decoder, kate_high_decode_clear (&decoder->k); decoder->initialized = FALSE; } + gst_segment_init (&decoder->kate_segment, GST_FORMAT_UNDEFINED); + decoder->kate_flushing = TRUE; gst_kate_util_decode_base_reset (decoder); break; case GST_STATE_CHANGE_READY_TO_NULL: @@ -316,6 +433,73 @@ gst_kate_decoder_base_change_state (GstKateDecoderBase * decoder, return res; } +void +gst_kate_util_decoder_base_set_flushing (GstKateDecoderBase * decoder, + gboolean flushing) +{ + decoder->kate_flushing = flushing; + gst_segment_init (&decoder->kate_segment, GST_FORMAT_UNDEFINED); +} + +void +gst_kate_util_decoder_base_new_segment_event (GstKateDecoderBase * decoder, + GstEvent * event) +{ + gboolean update; + gdouble rate; + GstFormat format; + gint64 start, stop, time; + gdouble arate; + + gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format, + &start, &stop, &time); + GST_DEBUG_OBJECT (decoder, "kate pad segment:" + " Update %d, rate %g arate %g format %d start %" GST_TIME_FORMAT + " %" GST_TIME_FORMAT " position %" GST_TIME_FORMAT, + update, rate, arate, format, GST_TIME_ARGS (start), + GST_TIME_ARGS (stop), GST_TIME_ARGS (time)); + gst_segment_set_newsegment_full (&decoder->kate_segment, update, rate, + arate, format, start, stop, time); +} + +gboolean +gst_kate_util_decoder_base_update_segment (GstKateDecoderBase * decoder, + GstElement * element, GstBuffer * buf) +{ + gint64 clip_start = 0, clip_stop = 0; + gboolean in_seg; + + if (decoder->kate_flushing) { + GST_LOG_OBJECT (element, "Kate pad flushing, buffer ignored"); + return FALSE; + } + + if (G_LIKELY (GST_BUFFER_TIMESTAMP_IS_VALID (buf))) { + GstClockTime stop; + + if (G_LIKELY (GST_BUFFER_DURATION_IS_VALID (buf))) + stop = GST_BUFFER_TIMESTAMP (buf) + GST_BUFFER_DURATION (buf); + else + stop = GST_CLOCK_TIME_NONE; + + in_seg = gst_segment_clip (&decoder->kate_segment, GST_FORMAT_TIME, + GST_BUFFER_TIMESTAMP (buf), stop, &clip_start, &clip_stop); + } else { + in_seg = TRUE; + } + + if (in_seg) { + if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) { + gst_segment_set_last_stop (&decoder->kate_segment, GST_FORMAT_TIME, + clip_start); + } + } else { + GST_INFO_OBJECT (element, "Kate buffer not in segment, ignored"); + } + + return in_seg; +} + static GstClockTime gst_kate_util_granule_time (kate_state * k, gint64 granulepos) { diff --git a/ext/kate/gstkateutil.h b/ext/kate/gstkateutil.h index 6e8ea2e013..27b6f70f31 100644 --- a/ext/kate/gstkateutil.h +++ b/ext/kate/gstkateutil.h @@ -37,6 +37,15 @@ G_BEGIN_DECLS enum typedef struct { + GstEvent * event; + gboolean (*handler)(GstPad *, GstEvent *); + GstPad *pad; +} GstKateDecoderBaseQueuedEvent; + +typedef struct +{ + GstElement element; + kate_state k; gboolean initialized; @@ -49,11 +58,17 @@ typedef struct gint original_canvas_width; gint original_canvas_height; + GstSegment kate_segment; + gboolean kate_flushing; + + gboolean delay_events; + GQueue *event_queue; } GstKateDecoderBase; extern GstCaps *gst_kate_util_set_header_on_caps (GstElement * element, GstCaps * caps, GList * headers); -extern void gst_kate_util_decode_base_init (GstKateDecoderBase * decoder); +extern void gst_kate_util_decode_base_init (GstKateDecoderBase * decoder, + gboolean delay_events); extern void gst_kate_util_install_decoder_base_properties (GObjectClass * gobject_class); extern gboolean gst_kate_util_decoder_base_get_property (GstKateDecoderBase * @@ -62,7 +77,16 @@ extern gboolean gst_kate_util_decoder_base_get_property (GstKateDecoderBase * extern GstFlowReturn gst_kate_util_decoder_base_chain_kate_packet (GstKateDecoderBase * decoder, GstElement * element, GstPad * pad, GstBuffer * buffer, GstPad * srcpad, - const kate_event ** ev); + GstPad * tagpad, GstCaps **src_caps, const kate_event ** ev); +extern void +gst_kate_util_decoder_base_set_flushing (GstKateDecoderBase * decoder, + gboolean flushing); +extern void +gst_kate_util_decoder_base_new_segment_event (GstKateDecoderBase * decoder, + GstEvent * event); +extern gboolean +gst_kate_util_decoder_base_update_segment (GstKateDecoderBase * decoder, + GstElement * element, GstBuffer * buf); extern GstStateChangeReturn gst_kate_decoder_base_change_state (GstKateDecoderBase * decoder, GstElement * element, GstElementClass * parent_class, @@ -72,6 +96,8 @@ extern gboolean gst_kate_decoder_base_convert (GstKateDecoderBase * decoder, GstFormat * dest_fmt, gint64 * dest_val); extern gboolean gst_kate_decoder_base_sink_query (GstKateDecoderBase * decoder, GstElement * element, GstPad * pad, GstQuery * query); +extern gboolean +gst_kate_util_decoder_base_queue_event (GstKateDecoderBase * decoder, GstEvent * event, gboolean (*handler)(GstPad *, GstEvent *), GstPad * pad); G_END_DECLS #endif /* __GST_KATE_UTIL_H__ */ From 2a2c76cdbd89ee0c587b1dab2d196e6d446a9e37 Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Mon, 25 Jan 2010 18:26:25 +0000 Subject: [PATCH 202/448] tiger: Give tiger primary rank --- ext/kate/gstkate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/kate/gstkate.c b/ext/kate/gstkate.c index 91d0579a6c..c7858e4951 100644 --- a/ext/kate/gstkate.c +++ b/ext/kate/gstkate.c @@ -100,7 +100,7 @@ plugin_init (GstPlugin * plugin) return FALSE; #ifdef HAVE_TIGER - if (!gst_element_register (plugin, "tiger", GST_RANK_NONE, + if (!gst_element_register (plugin, "tiger", GST_RANK_PRIMARY, GST_TYPE_KATE_TIGER)) return FALSE; #endif From f8dc80a8b7c118fa0159629c43412babb4836bf0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Fri, 24 Dec 2010 14:24:12 +0000 Subject: [PATCH 203/448] dvbsuboverlay: clean-up: dvb sub parser helper doesn't need to be a GObject --- gst/dvbsuboverlay/dvb-sub.c | 105 ++++++++++++--------------- gst/dvbsuboverlay/dvb-sub.h | 34 +-------- gst/dvbsuboverlay/gstdvbsuboverlay.c | 14 +--- 3 files changed, 54 insertions(+), 99 deletions(-) diff --git a/gst/dvbsuboverlay/dvb-sub.c b/gst/dvbsuboverlay/dvb-sub.c index 803729dc58..b84ac3cc13 100644 --- a/gst/dvbsuboverlay/dvb-sub.c +++ b/gst/dvbsuboverlay/dvb-sub.c @@ -30,20 +30,17 @@ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ -#include "dvb-sub.h" #include /* memset */ #include /* GST_READ_UINT16_BE */ #include /* GstBitReader */ #include "ffmpeg-colorspace.h" /* YUV_TO_RGB1_CCIR */ /* FIXME: Just give YUV data to gstreamer then? */ +#include "dvb-sub.h" + GST_DEBUG_CATEGORY_STATIC (dvbsub_debug); #define GST_CAT_DEFAULT dvbsub_debug -void -dvb_sub_init_debug (void) -{ - GST_DEBUG_CATEGORY_INIT (dvbsub_debug, "dvbsub", 0, "dvbsuboverlay parser"); -} +static void dvb_sub_init (void); /* FIXME: Are we waiting for an acquisition point before trying to do things? */ /* FIXME: In the end convert some of the guint8/16 (especially stack variables) back to gint for access efficiency */ @@ -154,10 +151,12 @@ struct _DvbSubPrivate GString *pes_buffer; DVBSubtitleWindow display_def; }; +struct _DvbSub +{ + DvbSubPrivate priv; // FIXME (tpm) -#define DVB_SUB_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), DVB_TYPE_SUB, DvbSubPrivate)) - -G_DEFINE_TYPE (DvbSub, dvb_sub, G_TYPE_OBJECT); + DvbSubPrivate *private_data; +}; typedef enum { @@ -280,40 +279,6 @@ delete_state (DvbSub * dvb_sub) g_warning ("Memory deallocation error!"); } -static void -dvb_sub_init (DvbSub * self) -{ - DvbSubPrivate *priv; - - self->private_data = priv = DVB_SUB_GET_PRIVATE (self); - - /* TODO: Add initialization code here */ - /* FIXME: Do we have a reason to initiate the members to zero, or are we guaranteed that anyway? */ - priv->region_list = NULL; - priv->object_list = NULL; - priv->page_time_out = 0; /* FIXME: Maybe 255 instead? */ - priv->pes_buffer = g_string_new (NULL); - - /* display/window information */ - priv->display_def.version = -1; - priv->display_def.window_flag = 0; - priv->display_def.display_width = 720; - priv->display_def.display_height = 576; -} - -static void -dvb_sub_finalize (GObject * object) -{ - DvbSub *self = DVB_SUB (object); - DvbSubPrivate *priv = (DvbSubPrivate *) self->private_data; - /* TODO: Add deinitalization code here */ - /* FIXME: Clear up region_list contents */ - delete_state (self); /* close_pid should have called this, but lets be sure */ - g_string_free (priv->pes_buffer, TRUE); - - G_OBJECT_CLASS (dvb_sub_parent_class)->finalize (object); -} - /* init static data necessary for ffmpeg-colorspace conversion */ static void dsputil_static_init (void) @@ -329,14 +294,11 @@ dsputil_static_init (void) } static void -dvb_sub_class_init (DvbSubClass * klass) +dvb_sub_init (void) { int i, r, g, b, a = 0; - GObjectClass *object_class = (GObjectClass *) klass; - object_class->finalize = dvb_sub_finalize; - - g_type_class_add_private (klass, sizeof (DvbSubPrivate)); + GST_DEBUG_CATEGORY_INIT (dvbsub_debug, "dvbsub", 0, "dvbsuboverlay parser"); dsputil_static_init (); /* Initializes ff_cropTbl table, used in YUV_TO_RGB conversion */ @@ -1377,19 +1339,47 @@ dvb_subtitles_free (DVBSubtitles * sub) g_slice_free (DVBSubtitles, sub); } -/** - * dvb_sub_new: - * - * Creates a new #DvbSub. - * - * Return value: a newly created #DvbSub - */ DvbSub * dvb_sub_new (void) { - DvbSub *dvbsub = g_object_new (DVB_TYPE_SUB, NULL); + static gsize inited = 0; + DvbSubPrivate *sub; + DvbSub *dvb_sub; - return dvbsub; + if (g_once_init_enter (&inited)) { + dvb_sub_init (); + g_once_init_leave (&inited, TRUE); + } + + dvb_sub = g_slice_new0 (DvbSub); + dvb_sub->private_data = &dvb_sub->priv; + + sub = dvb_sub->private_data; + + /* TODO: Add initialization code here */ + /* FIXME: Do we have a reason to initiate the members to zero, or are we guaranteed that anyway? */ + sub->region_list = NULL; + sub->object_list = NULL; + sub->page_time_out = 0; /* FIXME: Maybe 255 instead? */ + sub->pes_buffer = g_string_new (NULL); + + /* display/window information */ + sub->display_def.version = -1; + sub->display_def.window_flag = 0; + sub->display_def.display_width = 720; + sub->display_def.display_height = 576; + + return dvb_sub; +} + +void +dvb_sub_free (DvbSub * sub) +{ + /* TODO: Add deinitalization code here */ + /* FIXME: Clear up region_list contents */ + delete_state (sub); + g_string_free (sub->private_data->pes_buffer, TRUE); + g_slice_free (DvbSub, sub); } #define DVB_SUB_SEGMENT_PAGE_COMPOSITION 0x10 @@ -1528,7 +1518,6 @@ dvb_sub_set_callbacks (DvbSub * dvb_sub, DvbSubCallbacks * callbacks, DvbSubPrivate *priv; g_return_if_fail (dvb_sub != NULL); - g_return_if_fail (DVB_IS_SUB (dvb_sub)); g_return_if_fail (callbacks != NULL); priv = (DvbSubPrivate *) dvb_sub->private_data; diff --git a/gst/dvbsuboverlay/dvb-sub.h b/gst/dvbsuboverlay/dvb-sub.h index ae7297747c..180047afc8 100644 --- a/gst/dvbsuboverlay/dvb-sub.h +++ b/gst/dvbsuboverlay/dvb-sub.h @@ -21,39 +21,12 @@ #ifndef _DVB_SUB_H_ #define _DVB_SUB_H_ -#include +#include G_BEGIN_DECLS -#define DVB_TYPE_SUB (dvb_sub_get_type ()) -#define DVB_SUB(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), DVB_TYPE_SUB, DvbSub)) -#define DVB_SUB_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), DVB_TYPE_SUB, DvbSubClass)) -#define DVB_IS_SUB(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), DVB_TYPE_SUB)) -#define DVB_IS_SUB_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), DVB_TYPE_SUB)) -#define DVB_SUB_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), DVB_TYPE_SUB, DvbSubClass)) - -typedef struct _DvbSubClass DvbSubClass; typedef struct _DvbSub DvbSub; -struct _DvbSubClass -{ - GObjectClass parent_class; -}; - -/** - * DvbSub: - * - * The #DvbSub struct contains only private fields and should not be - * directly accessed. - */ -struct _DvbSub -{ - GObject parent_instance; - - /*< private >*/ - gpointer private_data; -}; - /** * DVBSubtitlePicture: * @data: the data in the form of palette indices, each byte represents one pixel @@ -153,10 +126,9 @@ typedef struct { gpointer _dvb_sub_reserved[3]; } DvbSubCallbacks; -void dvb_sub_init_debug (void); - -GType dvb_sub_get_type (void) G_GNUC_CONST; DvbSub *dvb_sub_new (void); +void dvb_sub_free (DvbSub * sub); + gint dvb_sub_feed_with_pts (DvbSub *dvb_sub, guint64 pts, guint8 *data, gint len); void dvb_sub_set_callbacks (DvbSub *dvb_sub, DvbSubCallbacks *callbacks, gpointer user_data); void dvb_subtitles_free (DVBSubtitles *sub); diff --git a/gst/dvbsuboverlay/gstdvbsuboverlay.c b/gst/dvbsuboverlay/gstdvbsuboverlay.c index 80ea604620..f2b9734bd7 100644 --- a/gst/dvbsuboverlay/gstdvbsuboverlay.c +++ b/gst/dvbsuboverlay/gstdvbsuboverlay.c @@ -168,12 +168,9 @@ gst_dvbsub_overlay_flush_subtitles (GstDVBSubOverlay * render) } if (render->dvb_sub) - g_object_unref (render->dvb_sub); + dvb_sub_free (render->dvb_sub); + render->dvb_sub = dvb_sub_new (); - if (!render->dvb_sub) { - GST_WARNING_OBJECT (render, "cannot create dvbsub instance"); - g_assert_not_reached (); - } { DvbSubCallbacks dvbsub_callbacks = { &new_dvb_subtitles_cb, }; @@ -254,9 +251,8 @@ gst_dvbsub_overlay_finalize (GObject * object) } g_queue_free (overlay->pending_subtitles); - if (overlay->dvb_sub) { - g_object_unref (overlay->dvb_sub); - } + if (overlay->dvb_sub) + dvb_sub_free (overlay->dvb_sub); if (overlay->dvbsub_mutex) g_mutex_free (overlay->dvbsub_mutex); @@ -1157,8 +1153,6 @@ plugin_init (GstPlugin * plugin) GST_DEBUG_CATEGORY_INIT (gst_dvbsub_overlay_debug, "dvbsuboverlay", 0, "DVB subtitle overlay"); - dvb_sub_init_debug (); - return gst_element_register (plugin, "dvbsuboverlay", GST_RANK_PRIMARY, GST_TYPE_DVBSUB_OVERLAY); } From e35a3ddbf9382534729e8526d827bfca391500ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Fri, 24 Dec 2010 14:44:23 +0000 Subject: [PATCH 204/448] dvbsuboverlay: clean-up: merge private data struct into main struct --- gst/dvbsuboverlay/dvb-sub.c | 132 ++++++++++++++---------------------- 1 file changed, 50 insertions(+), 82 deletions(-) diff --git a/gst/dvbsuboverlay/dvb-sub.c b/gst/dvbsuboverlay/dvb-sub.c index b84ac3cc13..c562319151 100644 --- a/gst/dvbsuboverlay/dvb-sub.c +++ b/gst/dvbsuboverlay/dvb-sub.c @@ -134,10 +134,8 @@ typedef struct DVBSubRegion struct DVBSubRegion *next; } DVBSubRegion; -typedef struct _DvbSubPrivate DvbSubPrivate; -struct _DvbSubPrivate +struct _DvbSub { - int fd; DvbSubCallbacks callbacks; gpointer user_data; @@ -151,12 +149,6 @@ struct _DvbSubPrivate GString *pes_buffer; DVBSubtitleWindow display_def; }; -struct _DvbSub -{ - DvbSubPrivate priv; // FIXME (tpm) - - DvbSubPrivate *private_data; -}; typedef enum { @@ -164,12 +156,10 @@ typedef enum BOTTOM_FIELD = 1 } DvbSubPixelDataSubBlockFieldType; -/* FIXME: It might make sense to pass DvbSubPrivate for all the get_* functions, instead of public DvbSub */ static DVBSubObject * get_object (DvbSub * dvb_sub, guint16 object_id) { - const DvbSubPrivate *priv = (DvbSubPrivate *) dvb_sub->private_data; - DVBSubObject *ptr = priv->object_list; + DVBSubObject *ptr = dvb_sub->object_list; while (ptr && ptr->id != object_id) { ptr = ptr->next; @@ -181,8 +171,7 @@ get_object (DvbSub * dvb_sub, guint16 object_id) static DVBSubCLUT * get_clut (DvbSub * dvb_sub, gint clut_id) { - const DvbSubPrivate *priv = (DvbSubPrivate *) dvb_sub->private_data; - DVBSubCLUT *ptr = priv->clut_list; + DVBSubCLUT *ptr = dvb_sub->clut_list; while (ptr && ptr->id != clut_id) { ptr = ptr->next; @@ -191,12 +180,10 @@ get_clut (DvbSub * dvb_sub, gint clut_id) return ptr; } -// FIXME: Just pass private_data pointer directly here and in other get_* helper functions? static DVBSubRegion * get_region (DvbSub * dvb_sub, guint8 region_id) { - const DvbSubPrivate *priv = (DvbSubPrivate *) dvb_sub->private_data; - DVBSubRegion *ptr = priv->region_list; + DVBSubRegion *ptr = dvb_sub->region_list; while (ptr && ptr->id != region_id) { ptr = ptr->next; @@ -208,7 +195,6 @@ get_region (DvbSub * dvb_sub, guint8 region_id) static void delete_region_display_list (DvbSub * dvb_sub, DVBSubRegion * region) { - const DvbSubPrivate *priv = (DvbSubPrivate *) dvb_sub->private_data; DVBSubObject *object, *obj2; DVBSubObject **obj2_ptr; DVBSubObjectDisplay *display, *obj_disp, **obj_disp_ptr; @@ -231,7 +217,7 @@ delete_region_display_list (DvbSub * dvb_sub, DVBSubRegion * region) *obj_disp_ptr = obj_disp->object_list_next; if (!object->display_list) { - obj2_ptr = (DVBSubObject **) & priv->object_list; /* FIXME: Evil casting */ + obj2_ptr = (DVBSubObject **) & dvb_sub->object_list; /* FIXME: Evil casting */ obj2 = *obj2_ptr; while (obj2 != object) { @@ -256,13 +242,12 @@ delete_region_display_list (DvbSub * dvb_sub, DVBSubRegion * region) static void delete_state (DvbSub * dvb_sub) { - DvbSubPrivate *priv = (DvbSubPrivate *) dvb_sub->private_data; DVBSubRegion *region; - while (priv->region_list) { - region = priv->region_list; + while (dvb_sub->region_list) { + region = dvb_sub->region_list; - priv->region_list = region->next; + dvb_sub->region_list = region->next; delete_region_display_list (dvb_sub, region); if (region->pbuf) @@ -271,12 +256,11 @@ delete_state (DvbSub * dvb_sub) g_slice_free (DVBSubRegion, region); } - g_slice_free_chain (DVBSubCLUT, priv->clut_list, next); - priv->clut_list = NULL; + g_slice_free_chain (DVBSubCLUT, dvb_sub->clut_list, next); + dvb_sub->clut_list = NULL; - /* Should already be null */ - if (priv->object_list) - g_warning ("Memory deallocation error!"); + /* Should already be NULL */ + g_warn_if_fail (dvb_sub->object_list == NULL); } /* init static data necessary for ffmpeg-colorspace conversion */ @@ -369,7 +353,6 @@ static void _dvb_sub_parse_page_segment (DvbSub * dvb_sub, guint16 page_id, guint8 * buf, gint buf_size) { /* FIXME: Use guint for buf_size here and in many other places? */ - DvbSubPrivate *priv = (DvbSubPrivate *) dvb_sub->private_data; DVBSubRegionDisplay *display; DVBSubRegionDisplay *tmp_display_list, **tmp_ptr; @@ -384,7 +367,7 @@ _dvb_sub_parse_page_segment (DvbSub * dvb_sub, guint16 page_id, guint8 * buf, if (buf_size < 1) return; - priv->page_time_out = *buf++; + dvb_sub->page_time_out = *buf++; page_state = ((*buf++) >> 2) & 3; #ifndef GST_DISABLE_GST_DEBUG @@ -395,7 +378,7 @@ _dvb_sub_parse_page_segment (DvbSub * dvb_sub, guint16 page_id, guint8 * buf, ++counter; GST_DEBUG ("PAGE: %d: page_id = %u, length = %d, page_time_out = %u secs, " - "page_state = %s", counter, page_id, buf_size, priv->page_time_out, + "page_state = %s", counter, page_id, buf_size, dvb_sub->page_time_out, page_state_str[page_state]); } #endif @@ -404,9 +387,9 @@ _dvb_sub_parse_page_segment (DvbSub * dvb_sub, guint16 page_id, guint8 * buf, delete_state (dvb_sub); } - tmp_display_list = priv->display_list; - priv->display_list = NULL; - priv->display_list_size = 0; + tmp_display_list = dvb_sub->display_list; + dvb_sub->display_list = NULL; + dvb_sub->display_list_size = 0; while (buf + 5 < buf_end) { region_id = *buf++; @@ -432,9 +415,9 @@ _dvb_sub_parse_page_segment (DvbSub * dvb_sub, guint16 page_id, guint8 * buf, *tmp_ptr = display->next; - display->next = priv->display_list; - priv->display_list = display; - priv->display_list_size++; + display->next = dvb_sub->display_list; + dvb_sub->display_list = display; + dvb_sub->display_list_size++; GST_LOG ("PAGE %d: REGION information: ID = %u, address = %ux%u", counter, region_id, display->x_pos, display->y_pos); @@ -453,8 +436,6 @@ static void _dvb_sub_parse_region_segment (DvbSub * dvb_sub, guint16 page_id, guint8 * buf, gint buf_size) { - DvbSubPrivate *priv = (DvbSubPrivate *) dvb_sub->private_data; - const guint8 *buf_end = buf + buf_size; guint8 region_id; guint16 object_id; @@ -473,8 +454,8 @@ _dvb_sub_parse_region_segment (DvbSub * dvb_sub, guint16 page_id, guint8 * buf, if (!region) { /* Create a new region */ region = g_slice_new0 (DVBSubRegion); region->id = region_id; - region->next = priv->region_list; - priv->region_list = region; + region->next = dvb_sub->region_list; + dvb_sub->region_list = region; } fill = ((*buf++) >> 3) & 1; @@ -536,8 +517,8 @@ _dvb_sub_parse_region_segment (DvbSub * dvb_sub, guint16 page_id, guint8 * buf, object->id = object_id; - object->next = priv->object_list; - priv->object_list = object; + object->next = dvb_sub->object_list; + dvb_sub->object_list = object; } object->type = (*buf) >> 6; @@ -578,8 +559,6 @@ static void _dvb_sub_parse_clut_segment (DvbSub * dvb_sub, guint16 page_id, guint8 * buf, gint buf_size) { - DvbSubPrivate *priv = (DvbSubPrivate *) dvb_sub->private_data; - const guint8 *buf_end = buf + buf_size; guint8 clut_id; DVBSubCLUT *clut; @@ -601,8 +580,8 @@ _dvb_sub_parse_clut_segment (DvbSub * dvb_sub, guint16 page_id, guint8 * buf, clut->id = clut_id; - clut->next = priv->clut_list; - priv->clut_list = clut; + clut->next = dvb_sub->clut_list; + dvb_sub->clut_list = clut; } while (buf + 4 < buf_end) { @@ -1168,7 +1147,6 @@ _dvb_sub_parse_display_definition_segment (DvbSub * dvb_sub, guint8 * buf, gint buf_size) { int dds_version, info_byte; - DvbSubPrivate *ctx = dvb_sub->private_data; if (buf_size < 5) return -1; @@ -1176,27 +1154,27 @@ _dvb_sub_parse_display_definition_segment (DvbSub * dvb_sub, guint8 * buf, info_byte = *buf++; dds_version = info_byte >> 4; - if (ctx->display_def.version == dds_version) + if (dvb_sub->display_def.version == dds_version) return 0; /* already have this display definition version */ - ctx->display_def.version = dds_version; - ctx->display_def.display_width = GST_READ_UINT16_BE (buf) + 1; + dvb_sub->display_def.version = dds_version; + dvb_sub->display_def.display_width = GST_READ_UINT16_BE (buf) + 1; buf += 2; - ctx->display_def.display_height = GST_READ_UINT16_BE (buf) + 1; + dvb_sub->display_def.display_height = GST_READ_UINT16_BE (buf) + 1; buf += 2; - ctx->display_def.window_flag = info_byte & 1 << 3; + dvb_sub->display_def.window_flag = info_byte & 1 << 3; - if (buf_size >= 13 && ctx->display_def.window_flag) { - ctx->display_def.window_x = GST_READ_UINT16_BE (buf); + if (buf_size >= 13 && dvb_sub->display_def.window_flag) { + dvb_sub->display_def.window_x = GST_READ_UINT16_BE (buf); buf += 2; - ctx->display_def.window_y = GST_READ_UINT16_BE (buf); + dvb_sub->display_def.window_y = GST_READ_UINT16_BE (buf); buf += 2; - ctx->display_def.window_width = - GST_READ_UINT16_BE (buf) - ctx->display_def.window_x + 1; + dvb_sub->display_def.window_width = + GST_READ_UINT16_BE (buf) - dvb_sub->display_def.window_x + 1; buf += 2; - ctx->display_def.window_height = - GST_READ_UINT16_BE (buf) - ctx->display_def.window_y + 1; + dvb_sub->display_def.window_height = + GST_READ_UINT16_BE (buf) - dvb_sub->display_def.window_y + 1; buf += 2; } @@ -1207,8 +1185,6 @@ static gint _dvb_sub_parse_end_of_display_set (DvbSub * dvb_sub, guint16 page_id, guint8 * buf, gint buf_size, guint64 pts) { - DvbSubPrivate *priv = (DvbSubPrivate *) dvb_sub->private_data; - DVBSubtitles *sub = g_slice_new0 (DVBSubtitles); DVBSubRegion *region; @@ -1229,7 +1205,7 @@ _dvb_sub_parse_end_of_display_set (DvbSub * dvb_sub, guint16 page_id, sub->format = 0; /* 0 = graphics */ #endif - sub->num_rects = priv->display_list_size; + sub->num_rects = dvb_sub->display_list_size; if (sub->num_rects > 0) { // FIXME-MEMORY-LEAK: This structure is not freed up yet @@ -1241,9 +1217,9 @@ _dvb_sub_parse_end_of_display_set (DvbSub * dvb_sub, guint16 page_id, i = 0; /* copy subtitle display and window information */ - sub->display_def = priv->display_def; + sub->display_def = dvb_sub->display_def; - for (display = priv->display_list; display; display = display->next) { + for (display = dvb_sub->display_list; display; display = display->next) { region = get_region (dvb_sub, display->region_id); rect = sub->rects[i]; @@ -1304,11 +1280,11 @@ _dvb_sub_parse_end_of_display_set (DvbSub * dvb_sub, guint16 page_id, } sub->pts = pts; - sub->page_time_out = priv->page_time_out; + sub->page_time_out = dvb_sub->page_time_out; sub->num_rects = i; - if (priv->callbacks.new_data) { - priv->callbacks.new_data (dvb_sub, sub, priv->user_data); + if (dvb_sub->callbacks.new_data) { + dvb_sub->callbacks.new_data (dvb_sub, sub, dvb_sub->user_data); } else { /* No-one responsible to clean up memory, so do it ourselves */ /* FIXME: Just don't bother with all this palette image creation in the first place then... */ @@ -1343,18 +1319,14 @@ DvbSub * dvb_sub_new (void) { static gsize inited = 0; - DvbSubPrivate *sub; - DvbSub *dvb_sub; + DvbSub *sub; if (g_once_init_enter (&inited)) { dvb_sub_init (); g_once_init_leave (&inited, TRUE); } - dvb_sub = g_slice_new0 (DvbSub); - dvb_sub->private_data = &dvb_sub->priv; - - sub = dvb_sub->private_data; + sub = g_slice_new0 (DvbSub); /* TODO: Add initialization code here */ /* FIXME: Do we have a reason to initiate the members to zero, or are we guaranteed that anyway? */ @@ -1369,7 +1341,7 @@ dvb_sub_new (void) sub->display_def.display_width = 720; sub->display_def.display_height = 576; - return dvb_sub; + return sub; } void @@ -1378,7 +1350,7 @@ dvb_sub_free (DvbSub * sub) /* TODO: Add deinitalization code here */ /* FIXME: Clear up region_list contents */ delete_state (sub); - g_string_free (sub->private_data->pes_buffer, TRUE); + g_string_free (sub->pes_buffer, TRUE); g_slice_free (DvbSub, sub); } @@ -1515,13 +1487,9 @@ void dvb_sub_set_callbacks (DvbSub * dvb_sub, DvbSubCallbacks * callbacks, gpointer user_data) { - DvbSubPrivate *priv; - g_return_if_fail (dvb_sub != NULL); g_return_if_fail (callbacks != NULL); - priv = (DvbSubPrivate *) dvb_sub->private_data; - - priv->callbacks = *callbacks; - priv->user_data = user_data; + dvb_sub->callbacks = *callbacks; + dvb_sub->user_data = user_data; } From 5dac64b20adf8d41b060d6aa0b32ea7709efd3a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Sat, 25 Dec 2010 16:44:03 +0000 Subject: [PATCH 205/448] tiger: move #if #else bits outside of macro Some compilers/preprocessors don't like if/else/endif preprocessor directives in the middle of macros. --- ext/kate/gstkatetiger.c | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/ext/kate/gstkatetiger.c b/ext/kate/gstkatetiger.c index 286929796b..c6f1988c81 100644 --- a/ext/kate/gstkatetiger.c +++ b/ext/kate/gstkatetiger.c @@ -131,30 +131,26 @@ static GstStaticPadTemplate kate_sink_factory = GST_STATIC_CAPS ("subtitle/x-kate; application/x-kate") ); +#if G_BYTE_ORDER == G_LITTLE_ENDIAN +#define TIGER_VIDEO_CAPS \ + GST_VIDEO_CAPS_xRGB ", endianness = (int)1234; " \ + GST_VIDEO_CAPS_BGRx ", endianness = (int)4321" +#else +#define TIGER_VIDEO_CAPS \ + GST_VIDEO_CAPS_BGRx ", endianness = (int)4321; " \ + GST_VIDEO_CAPS_xRGB ", endianness = (int)1234" +#endif + static GstStaticPadTemplate video_sink_factory = - GST_STATIC_PAD_TEMPLATE ("video_sink", +GST_STATIC_PAD_TEMPLATE ("video_sink", GST_PAD_SINK, GST_PAD_ALWAYS, -#if G_BYTE_ORDER == G_LITTLE_ENDIAN - GST_STATIC_CAPS (GST_VIDEO_CAPS_xRGB ", endianness = (int) 1234" ";" - GST_VIDEO_CAPS_BGRx ", endianness = (int)4321") -#else - GST_STATIC_CAPS (GST_VIDEO_CAPS_xRGB ", endianness = (int) 4321" ";" - GST_VIDEO_CAPS_BGRx ", endianness = (int)1234") -#endif - ); + GST_STATIC_CAPS (TIGER_VIDEO_CAPS)); static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, GST_PAD_ALWAYS, -#if G_BYTE_ORDER == G_LITTLE_ENDIAN - GST_STATIC_CAPS (GST_VIDEO_CAPS_xRGB ", endianness = (int) 1234" ";" - GST_VIDEO_CAPS_BGRx ", endianness = (int)4321") -#else - GST_STATIC_CAPS (GST_VIDEO_CAPS_xRGB ", endianness = (int) 4321" ";" - GST_VIDEO_CAPS_BGRx ", endianness = (int)1234") -#endif - ); + GST_STATIC_CAPS (TIGER_VIDEO_CAPS)); GST_BOILERPLATE (GstKateTiger, gst_kate_tiger, GstElement, GST_TYPE_ELEMENT); From 74d82c4c1ea4525b6df7a6f6a2126f791e378101 Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Sat, 25 Dec 2010 17:01:11 +0000 Subject: [PATCH 206/448] kate: if seeking with GST_SEEK_TYPE_CUR, flush everything We don't know how to calculate the target, so be safe. https://bugzilla.gnome.org/show_bug.cgi?id=600929 --- ext/kate/gstkatetiger.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/ext/kate/gstkatetiger.c b/ext/kate/gstkatetiger.c index c6f1988c81..d5a2faf3a0 100644 --- a/ext/kate/gstkatetiger.c +++ b/ext/kate/gstkatetiger.c @@ -784,7 +784,9 @@ gst_kate_tiger_seek (GstKateTiger * tiger, GstPad * pad, GstEvent * event) target = cur / (float) GST_SECOND; break; case GST_SEEK_TYPE_CUR: - target = gst_kate_tiger_get_time (tiger) + cur / (float) GST_SECOND; + GST_WARNING_OBJECT (tiger, + "Seeking from the current segment, cannot work out target so flushing everything"); + target = (kate_float) 0; break; case GST_SEEK_TYPE_END: GST_WARNING_OBJECT (tiger, From f90b8bdfa04cd2d9661b702f83305c5920130576 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Sun, 26 Dec 2010 17:07:38 +0000 Subject: [PATCH 207/448] examples: fix gtk3 code path in camerabin example app Just add rows via the combobox's model, which should work with both gtk2 and gtk3, instead of using the gtk_combo_box_append_text() convenience API (which was renamed to gtk_combo_box_text_append_text()). Fixes compilation against gtk3 (there was a typo in the list store variable name, spotted by Markus Vartiainen). --- tests/examples/camerabin/gst-camera.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/tests/examples/camerabin/gst-camera.c b/tests/examples/camerabin/gst-camera.c index e439bb88b6..eded8bb881 100644 --- a/tests/examples/camerabin/gst-camera.c +++ b/tests/examples/camerabin/gst-camera.c @@ -1105,6 +1105,7 @@ format_value_callback (GtkScale * scale, gdouble value, gpointer user_data) static gint create_menu_items_from_structure (GstStructure * structure) { + GtkListStore *store; const GValue *framerate_list = NULL; const gchar *structure_name; GString *item_str = NULL; @@ -1159,12 +1160,10 @@ create_menu_items_from_structure (GstStructure * structure) goto range_found; } + store = GTK_LIST_STORE (gtk_combo_box_get_model (ui_cbbox_resolution)); for (j = 0; j < num_framerates; j++) { GstCaps *video_caps; -#if GTK_CHECK_VERSION (2, 91, 6) - GtkListStore *sotre; GtkTreeIter iter; -#endif if (framerate_list) { const GValue *item = gst_value_list_get_value (framerate_list, j); @@ -1175,13 +1174,8 @@ create_menu_items_from_structure (GstStructure * structure) g_string_append_printf (item_str, " (%" GST_FOURCC_FORMAT ")", GST_FOURCC_ARGS (fourcc)); g_string_append_printf (item_str, ", %dx%d at %d/%d", w, h, n, d); -#if GTK_CHECK_VERSION (2, 91, 6) - store = GTK_LIST_STORE (gtk_combo_box_get_model (ui_cbbox_resolution)); gtk_list_store_append (store, &iter); gtk_list_store_set (store, &iter, 0, item_str->str, -1); -#else - gtk_combo_box_append_text (ui_cbbox_resolution, item_str->str); -#endif video_caps = gst_caps_new_simple (structure_name, "format", GST_TYPE_FOURCC, From 18e69fb72e27a81012041fe70c6b2bf2f028510c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Sun, 26 Dec 2010 17:19:00 +0000 Subject: [PATCH 208/448] photography: fix typo in property description --- gst-libs/gst/interfaces/photography.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst-libs/gst/interfaces/photography.c b/gst-libs/gst/interfaces/photography.c index eeaa5d1ea2..95e0f307a7 100644 --- a/gst-libs/gst/interfaces/photography.c +++ b/gst-libs/gst/interfaces/photography.c @@ -618,7 +618,7 @@ gst_photography_iface_class_init (gpointer g_class) g_object_interface_install_property (g_class, g_param_spec_flags (GST_PHOTOGRAPHY_PROP_NOISE_REDUCTION, "Noise Reduction settings", - "Which noise reduction modes are enalbed in Camera (0 = disabled)", + "Which noise reduction modes are enabled (0 = disabled)", GST_TYPE_PHOTOGRAPHY_NOISE_REDUCTION, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); } From 857e3dda46bc7c6e3ca6dd4b2f1413f517219f7c Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Thu, 23 Dec 2010 18:18:50 +0000 Subject: [PATCH 209/448] tiger: fallback on headers in caps to initialize if headers are absent When Totem switches streams, tiger will be reset, and start receiving buffers from the middle of the stream, without being sent headers. If this happens, try to get headers from the caps. https://bugzilla.gnome.org/show_bug.cgi?id=638004 --- ext/kate/gstkatetiger.c | 47 +++++++++++++++++++++++++++++++++++++++++ ext/kate/gstkatetiger.h | 1 + 2 files changed, 48 insertions(+) diff --git a/ext/kate/gstkatetiger.c b/ext/kate/gstkatetiger.c index d5a2faf3a0..67d046aaa8 100644 --- a/ext/kate/gstkatetiger.c +++ b/ext/kate/gstkatetiger.c @@ -355,6 +355,8 @@ gst_kate_tiger_init (GstKateTiger * tiger, GstKateTigerClass * gclass) tiger->video_width = 0; tiger->video_height = 0; + + tiger->seen_header = FALSE; } static void @@ -565,6 +567,50 @@ gst_kate_tiger_kate_chain (GstPad * pad, GstBuffer * buf) GST_LOG_OBJECT (tiger, "Got kate buffer, caps %s", gst_caps_to_string (GST_BUFFER_CAPS (buf))); + /* Unfortunately, it can happen that the start of the stream is not sent, + for instance if there's a stream selector upstream, which is switched + from another Kate stream. If this happens, then we can fallback on the + headers stored in the caps (if any). */ + if (!tiger->seen_header) { + if (GST_BUFFER_SIZE (buf) == 0 || (GST_BUFFER_DATA (buf)[0] & 0x80) == 0) { + /* Not a header, try to fall back on caps */ + GstStructure *s; + const GValue *streamheader; + + GST_INFO_OBJECT (tiger, "Headers not seen, start of stream is cut off"); + s = gst_caps_get_structure (GST_BUFFER_CAPS (buf), 0); + streamheader = gst_structure_get_value (s, "streamheader"); + if (streamheader && G_VALUE_TYPE (streamheader) == GST_TYPE_ARRAY) { + GstPad *tagpad = gst_pad_get_peer (pad); + GArray *array; + gint i; + + GST_INFO_OBJECT (tiger, "Falling back on caps to initialize decoder"); + array = g_value_peek_pointer (streamheader); + for (i = 0; i < array->len; i++) { + GValue *value = &g_array_index (array, GValue, i); + if (G_VALUE_TYPE (value) == GST_TYPE_BUFFER) { + GstBuffer *hbuf = g_value_peek_pointer (value); + gst_buffer_ref (hbuf); + rflow = + gst_kate_util_decoder_base_chain_kate_packet (&tiger->decoder, + GST_ELEMENT_CAST (tiger), pad, hbuf, tiger->srcpad, tagpad, + NULL, NULL); + } else { + GST_WARNING_OBJECT (tiger, + "Streamheader index %d does not hold a buffer", i); + } + } + gst_object_unref (tagpad); + tiger->seen_header = TRUE; + } else { + GST_WARNING_OBJECT (tiger, "No headers seen, and no headers on caps"); + } + } else { + tiger->seen_header = TRUE; + } + } + if (gst_kate_util_decoder_base_update_segment (&tiger->decoder, GST_ELEMENT_CAST (tiger), buf)) { GstPad *tagpad = gst_pad_get_peer (pad); @@ -750,6 +796,7 @@ gst_kate_tiger_change_state (GstElement * element, GstStateChange transition) } gst_segment_init (&tiger->video_segment, GST_FORMAT_UNDEFINED); tiger->video_flushing = FALSE; + tiger->seen_header = FALSE; GST_KATE_TIGER_MUTEX_UNLOCK (tiger); break; default: diff --git a/ext/kate/gstkatetiger.h b/ext/kate/gstkatetiger.h index 353f9f79ec..48884b1c22 100644 --- a/ext/kate/gstkatetiger.h +++ b/ext/kate/gstkatetiger.h @@ -97,6 +97,7 @@ struct _GstKateTiger GstSegment video_segment; gboolean video_flushing; + gboolean seen_header; }; struct _GstKateTigerClass From 7a21a194991d80d93096f2f5c2bdf7dc06cc6886 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Mon, 27 Dec 2010 11:10:53 +0000 Subject: [PATCH 210/448] dvbsuboverlay: clean-up: allocate flat array of rectangles instead of an array of pointers to individually-allocated rectangles. --- gst/dvbsuboverlay/dvb-sub.c | 30 ++++++++++------------------ gst/dvbsuboverlay/dvb-sub.h | 4 ++-- gst/dvbsuboverlay/gstdvbsuboverlay.c | 2 +- 3 files changed, 14 insertions(+), 22 deletions(-) diff --git a/gst/dvbsuboverlay/dvb-sub.c b/gst/dvbsuboverlay/dvb-sub.c index c562319151..259362278a 100644 --- a/gst/dvbsuboverlay/dvb-sub.c +++ b/gst/dvbsuboverlay/dvb-sub.c @@ -1185,11 +1185,8 @@ static gint _dvb_sub_parse_end_of_display_set (DvbSub * dvb_sub, guint16 page_id, guint8 * buf, gint buf_size, guint64 pts) { - DVBSubtitles *sub = g_slice_new0 (DVBSubtitles); - - DVBSubRegion *region; DVBSubRegionDisplay *display; - DVBSubtitleRect *rect; + DVBSubtitles *sub; DVBSubCLUT *clut; guint32 *clut_table; int i; @@ -1198,21 +1195,17 @@ _dvb_sub_parse_end_of_display_set (DvbSub * dvb_sub, guint16 page_id, GST_DEBUG ("DISPLAY SET END: page_id = %u, length = %d", page_id, buf_size); - sub->rects = NULL; + sub = g_slice_new0 (DVBSubtitles); + #if 0 /* FIXME: PTS stuff not figured out yet */ sub->start_display_time = 0; sub->end_display_time = priv->page_time_out * 1000; sub->format = 0; /* 0 = graphics */ #endif + /* N.B. g_new0() will return NULL if num_rects is 0 */ sub->num_rects = dvb_sub->display_list_size; - - if (sub->num_rects > 0) { - // FIXME-MEMORY-LEAK: This structure is not freed up yet - sub->rects = g_malloc0 (sizeof (*sub->rects) * sub->num_rects); /* GSlice? */ - for (i = 0; i < sub->num_rects; i++) - sub->rects[i] = g_malloc0 (sizeof (*sub->rects[i])); /* GSlice? */ - } + sub->rects = g_new0 (DVBSubtitleRect, sub->num_rects); i = 0; @@ -1220,12 +1213,15 @@ _dvb_sub_parse_end_of_display_set (DvbSub * dvb_sub, guint16 page_id, sub->display_def = dvb_sub->display_def; for (display = dvb_sub->display_list; display; display = display->next) { + DVBSubtitleRect *rect; + DVBSubRegion *region; + region = get_region (dvb_sub, display->region_id); - rect = sub->rects[i]; if (!region) continue; + rect = &sub->rects[i]; rect->x = display->x_pos; rect->y = display->y_pos; rect->w = region->width; @@ -1298,18 +1294,14 @@ void dvb_subtitles_free (DVBSubtitles * sub) { int i; - DVBSubtitleRect *rect; if (sub == NULL) return; /* Now free up all the temporary memory we allocated */ for (i = 0; i < sub->num_rects; ++i) { - rect = sub->rects[i]; - - g_free (rect->pict.palette); - g_free (rect->pict.data); - g_free (rect); + g_free (sub->rects[i].pict.palette); + g_free (sub->rects[i].pict.data); } g_free (sub->rects); g_slice_free (DVBSubtitles, sub); diff --git a/gst/dvbsuboverlay/dvb-sub.h b/gst/dvbsuboverlay/dvb-sub.h index 180047afc8..7faa31f456 100644 --- a/gst/dvbsuboverlay/dvb-sub.h +++ b/gst/dvbsuboverlay/dvb-sub.h @@ -103,8 +103,8 @@ typedef struct DVBSubtitleWindow { typedef struct DVBSubtitles { guint64 pts; guint8 page_time_out; - unsigned int num_rects; - DVBSubtitleRect **rects; + guint num_rects; + DVBSubtitleRect *rects; DVBSubtitleWindow display_def; } DVBSubtitles; diff --git a/gst/dvbsuboverlay/gstdvbsuboverlay.c b/gst/dvbsuboverlay/gstdvbsuboverlay.c index f2b9734bd7..a2b7b1e27e 100644 --- a/gst/dvbsuboverlay/gstdvbsuboverlay.c +++ b/gst/dvbsuboverlay/gstdvbsuboverlay.c @@ -527,7 +527,7 @@ blit_i420 (GstDVBSubOverlay * overlay, DVBSubtitles * subs, GstBuffer * buffer) gint32 sx = 0, sy; /* 16.16 fixed point */ gint32 xstep, ystep; /* 16.16 fixed point */ - sub_region = subs->rects[counter]; + sub_region = &subs->rects[counter]; if (sub_region->y > height || sub_region->x > width) continue; From 143efa727e28e82d677cbe37969c0307cba91b9c Mon Sep 17 00:00:00 2001 From: Alessandro Decina Date: Mon, 27 Dec 2010 13:20:28 +0100 Subject: [PATCH 211/448] dvbsuboverlay: fix compiler warnings --- gst/dvbsuboverlay/gstdvbsuboverlay.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst/dvbsuboverlay/gstdvbsuboverlay.c b/gst/dvbsuboverlay/gstdvbsuboverlay.c index a2b7b1e27e..64cfe9c317 100644 --- a/gst/dvbsuboverlay/gstdvbsuboverlay.c +++ b/gst/dvbsuboverlay/gstdvbsuboverlay.c @@ -480,7 +480,7 @@ blit_i420 (GstDVBSubOverlay * overlay, DVBSubtitles * subs, GstBuffer * buffer) gint u_offset, u_height, u_width, u_stride; gint v_offset, v_height, v_width, v_stride; gint scale = 0; - gint scale_x, scale_y; /* 16.16 fixed point */ + gint scale_x = 0, scale_y = 0; /* 16.16 fixed point */ y_offset = gst_video_format_get_component_offset (GST_VIDEO_FORMAT_I420, 0, width, From a2f54e26f2021bf3c179c2056d316b1ed3109cc9 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Mon, 27 Dec 2010 16:58:26 -0300 Subject: [PATCH 212/448] asfmux: Fix plugin package name/origin --- gst/asfmux/gstasf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst/asfmux/gstasf.c b/gst/asfmux/gstasf.c index fb93517211..0cf3b32e53 100644 --- a/gst/asfmux/gstasf.c +++ b/gst/asfmux/gstasf.c @@ -48,4 +48,4 @@ GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, GST_VERSION_MINOR, "asfmux", "ASF Muxer Plugin", - plugin_init, VERSION, "LGPL", "gsoc2009 package", "embedded.ufcg.edu.br") + plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) From 895c07ef046d4edd994c0b497434457ed53dfa5f Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Tue, 28 Dec 2010 16:55:11 -0300 Subject: [PATCH 213/448] camerabin: Remove unused variable --- gst/camerabin/gstcamerabin.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/gst/camerabin/gstcamerabin.c b/gst/camerabin/gstcamerabin.c index 0f43020c7b..f759923169 100644 --- a/gst/camerabin/gstcamerabin.c +++ b/gst/camerabin/gstcamerabin.c @@ -1312,7 +1312,6 @@ static void gst_camerabin_rewrite_tags_to_bin (GstBin * bin, const GstTagList * list) { GstElement *setter; - GstElementFactory *setter_factory; GstIterator *iter; GstIteratorResult res = GST_ITERATOR_OK; gpointer data; @@ -1333,7 +1332,6 @@ gst_camerabin_rewrite_tags_to_bin (GstBin * bin, const GstTagList * list) case GST_ITERATOR_OK: setter = GST_ELEMENT (data); GST_LOG ("iterating tag setters: %" GST_PTR_FORMAT, setter); - setter_factory = gst_element_get_factory (setter); GST_DEBUG ("replacement tags %" GST_PTR_FORMAT, list); gst_tag_setter_merge_tags (GST_TAG_SETTER (setter), list, GST_TAG_MERGE_REPLACE_ALL); From 07279bac7b2271439d0ef201264400a3ff4c0ff9 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Tue, 28 Dec 2010 17:16:05 -0300 Subject: [PATCH 214/448] camerabin: mode can be only image or video No need to check if camerabin is on video mode if it isn't on image mode as those are the only 2 modes available. Additionally, if mode gets corrupted somehow and would be neither image or video it would cause a null pointer dereferencing some lines of code below, so this is safer. --- gst/camerabin/gstcamerabin.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gst/camerabin/gstcamerabin.c b/gst/camerabin/gstcamerabin.c index f759923169..e7f13dae8f 100644 --- a/gst/camerabin/gstcamerabin.c +++ b/gst/camerabin/gstcamerabin.c @@ -3520,7 +3520,7 @@ gst_camerabin_set_property (GObject * object, guint prop_id, prev_pipe = &camera->preview_pipeline; preview_source_filter = &camera->app_preview_source_filter; prev_caps = &camera->preview_caps; - } else if (camera->mode == MODE_VIDEO) { + } else { /* MODE VIDEO */ prev_pipe = &camera->video_preview_pipeline; preview_source_filter = &camera->app_video_preview_source_filter; prev_caps = &camera->video_preview_caps; @@ -3562,7 +3562,7 @@ gst_camerabin_set_property (GObject * object, guint prop_id, preview_pipe = &camera->preview_pipeline; preview_source_filter = &camera->app_preview_source_filter; preview_caps = camera->preview_caps; - } else if (camera->mode == MODE_VIDEO) { + } else { /* MODE VIDEO */ preview_pipe = &camera->video_preview_pipeline; preview_source_filter = &camera->app_video_preview_source_filter; preview_caps = camera->video_preview_caps; From 17ab963b104327d0a01071d9028d502dcb45819a Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Wed, 22 Dec 2010 14:42:27 +0000 Subject: [PATCH 215/448] configure: use -pthread for xvid configure check https://bugzilla.gnome.org/show_bug.cgi?id=637823 https://bugzilla.gnome.org/show_bug.cgi?id=637308 --- configure.ac | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 89cc9cb7e2..25edb91767 100644 --- a/configure.ac +++ b/configure.ac @@ -1437,7 +1437,7 @@ AG_GST_CHECK_FEATURE(XVID, [xvid plugins], xvid, [ HAVE_XVID=no AC_CHECK_HEADER(xvid.h, [ OLD_LIBS="$LIBS" - LIBS="-lm" + LIBS="-lpthread -lm" AC_CHECK_LIB(xvidcore, xvid_encore, [ AC_CHECK_LIB(xvidcore, xvid_decore, [ AC_CHECK_LIB(xvidcore, xvid_global, [ From 1c761196f709d4f06616750ad6403a459fac5dc0 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Fri, 24 Dec 2010 09:10:48 -0300 Subject: [PATCH 216/448] wrappercamerabinsrc: Refactor internal pipeline Instead of linking 3 src pads from tee to the ghostpads, use 2 srcpads and add an output-selector to completely split caps negotiation of video/image modes. I don't think there is an use case that would require image and video pads to be used at the same time. --- gst/camerabin2/gstwrappercamerabinsrc.c | 90 ++++++++++++++++++++----- gst/camerabin2/gstwrappercamerabinsrc.h | 10 +-- 2 files changed, 80 insertions(+), 20 deletions(-) diff --git a/gst/camerabin2/gstwrappercamerabinsrc.c b/gst/camerabin2/gstwrappercamerabinsrc.c index 19567ab625..353e733ca8 100644 --- a/gst/camerabin2/gstwrappercamerabinsrc.c +++ b/gst/camerabin2/gstwrappercamerabinsrc.c @@ -1,6 +1,7 @@ /* * GStreamer * Copyright (C) 2010 Texas Instruments, Inc + * Copyright (C) 2010 Thiago Santos * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -137,6 +138,10 @@ gst_wrapper_camera_bin_src_imgsrc_probe (GstPad * pad, GstBuffer * buffer, GstBaseCameraSrc *camerasrc = GST_BASE_CAMERA_SRC (data); gboolean ret = FALSE; + GST_LOG_OBJECT (self, "Image probe, mode %d, capture count %d, caps %" + GST_PTR_FORMAT, camerasrc->mode, self->image_capture_count, + GST_BUFFER_CAPS (buffer)); + g_mutex_lock (camerasrc->capturing_mutex); if (self->image_capture_count > 0) { ret = TRUE; @@ -162,6 +167,9 @@ gst_wrapper_camera_bin_src_vidsrc_probe (GstPad * pad, GstBuffer * buffer, GstBaseCameraSrc *camerasrc = GST_BASE_CAMERA_SRC_CAST (self); gboolean ret = FALSE; + GST_LOG_OBJECT (self, "Video probe, mode %d, capture status %d", + camerasrc->mode, self->video_rec_status); + /* TODO do we want to lock for every buffer? */ /* * Note that we can use gst_pad_push_event here because we are a buffer @@ -200,6 +208,9 @@ gst_wrapper_camera_bin_src_event (GstPad * pad, GstEvent * event) structure = gst_event_get_structure (event); if (structure && gst_structure_has_name (structure, "renegotiate")) { + GST_DEBUG_OBJECT (src, "Received renegotiate on pad %s", + GST_PAD_NAME (pad)); + if (pad == src->imgsrc) { src->image_renegotiate = TRUE; } else if (pad == src->vidsrc) { @@ -224,7 +235,11 @@ src_event_probe (GstPad * pad, GstEvent * event, gpointer user_data) * @bcamsrc: camerasrc object * * This function creates and links the elements of the camerasrc bin - * videosrc ! cspconv ! capsfilter ! crop ! scale ! capsfilter ! tee ! .. + * videosrc ! cspconv ! capsfilter ! crop ! scale ! capsfilter ! tee name=t ! + * t. ! ... (viewfinder pad) + * t. ! output-selector name=outsel + * outsel. ! (image pad) + * outsel. ! (video pad) * * Returns: TRUE, if elements were successfully created, FALSE otherwise */ @@ -236,6 +251,11 @@ gst_wrapper_camera_bin_src_construct_pipeline (GstBaseCameraSrc * bcamsrc) GstElement *tee; gboolean ret = FALSE; GstElement *videoscale; + GstPad *vf_pad; + GstPad *tee_capture_pad; + + if (self->elements_created) + return TRUE; GST_DEBUG_OBJECT (self, "constructing pipeline"); @@ -250,6 +270,7 @@ gst_wrapper_camera_bin_src_construct_pipeline (GstBaseCameraSrc * bcamsrc) } } + /* add a buffer probe to the src elemento to drop EOS from READY->NULL */ { GstPad *pad; pad = gst_element_get_static_pad (self->src_vid_src, "src"); @@ -279,8 +300,9 @@ gst_wrapper_camera_bin_src_construct_pipeline (GstBaseCameraSrc * bcamsrc) if (!(tee = gst_camerabin_create_and_add_element (cbin, "tee"))) goto done; - self->tee_vf_srcpad = gst_element_get_request_pad (tee, "src%d"); - g_object_set (tee, "alloc-pad", self->tee_vf_srcpad, NULL); + /* viewfinder pad */ + vf_pad = gst_element_get_request_pad (tee, "src%d"); + g_object_set (tee, "alloc-pad", vf_pad, NULL); /* the viewfinder should always work, so we add some converters to it */ if (!gst_camerabin_create_and_add_element (cbin, "ffmpegcolorspace")) @@ -288,30 +310,56 @@ gst_wrapper_camera_bin_src_construct_pipeline (GstBaseCameraSrc * bcamsrc) if (!(videoscale = gst_camerabin_create_and_add_element (cbin, "videoscale"))) goto done; - gst_object_unref (self->tee_vf_srcpad); - self->tee_vf_srcpad = gst_element_get_static_pad (videoscale, "src"); + gst_object_unref (vf_pad); + vf_pad = gst_element_get_static_pad (videoscale, "src"); - self->tee_image_srcpad = gst_element_get_request_pad (tee, "src%d"); - self->tee_video_srcpad = gst_element_get_request_pad (tee, "src%d"); + /* image/video pad from tee */ + tee_capture_pad = gst_element_get_request_pad (tee, "src%d"); - gst_pad_add_buffer_probe (self->tee_image_srcpad, + self->output_selector = + gst_element_factory_make ("output-selector", "outsel"); + gst_bin_add (GST_BIN (self), self->output_selector); + { + GstPad *pad = gst_element_get_static_pad (self->output_selector, "sink"); + + /* check return TODO */ + gst_pad_link (tee_capture_pad, pad); + gst_object_unref (pad); + } + + /* Create the 2 output pads for video and image */ + self->outsel_vidpad = + gst_element_get_request_pad (self->output_selector, "src%d"); + self->outsel_imgpad = + gst_element_get_request_pad (self->output_selector, "src%d"); + + g_assert (self->outsel_vidpad != NULL); + g_assert (self->outsel_imgpad != NULL); + + gst_pad_add_buffer_probe (self->outsel_imgpad, G_CALLBACK (gst_wrapper_camera_bin_src_imgsrc_probe), self); - gst_pad_add_buffer_probe (self->tee_video_srcpad, + gst_pad_add_buffer_probe (self->outsel_vidpad, G_CALLBACK (gst_wrapper_camera_bin_src_vidsrc_probe), self); + gst_ghost_pad_set_target (GST_GHOST_PAD (self->imgsrc), self->outsel_imgpad); + gst_ghost_pad_set_target (GST_GHOST_PAD (self->vidsrc), self->outsel_vidpad); + if (bcamsrc->mode == MODE_IMAGE) { + g_object_set (self->output_selector, "active-pad", self->outsel_imgpad, + NULL); + } else { + g_object_set (self->output_selector, "active-pad", self->outsel_vidpad, + NULL); + } - /* hook-up the ghostpads */ - gst_ghost_pad_set_target (GST_GHOST_PAD (self->vfsrc), self->tee_vf_srcpad); - gst_ghost_pad_set_target (GST_GHOST_PAD (self->imgsrc), - self->tee_image_srcpad); - gst_ghost_pad_set_target (GST_GHOST_PAD (self->vidsrc), - self->tee_video_srcpad); + /* hook-up the vf ghostpads */ + gst_ghost_pad_set_target (GST_GHOST_PAD (self->vfsrc), vf_pad); gst_pad_set_active (self->vfsrc, TRUE); gst_pad_set_active (self->imgsrc, TRUE); /* XXX ??? */ gst_pad_set_active (self->vidsrc, TRUE); /* XXX ??? */ ret = TRUE; + self->elements_created = TRUE; done: return ret; } @@ -498,6 +546,16 @@ gst_wrapper_camera_bin_src_set_mode (GstBaseCameraSrc * bcamsrc, self->mode = mode; + if (self->output_selector) { + if (mode == MODE_IMAGE) { + g_object_set (self->output_selector, "active-pad", self->outsel_imgpad, + NULL); + } else { + g_object_set (self->output_selector, "active-pad", self->outsel_vidpad, + NULL); + } + } + if (photography) { if (g_object_class_find_property (G_OBJECT_GET_CLASS (photography), "capture-mode")) { @@ -775,8 +833,8 @@ gst_wrapper_camera_bin_src_start_capture (GstBaseCameraSrc * camerasrc) /* TODO shoud we access this directly? Maybe a macro is better? */ if (src->mode == MODE_IMAGE) { - src->image_capture_count = 1; start_image_capture (src); + src->image_capture_count = 1; } else if (src->mode == MODE_VIDEO) { g_mutex_unlock (camerasrc->capturing_mutex); gst_wrapper_camera_bin_reset_video_src_caps (src, NULL); diff --git a/gst/camerabin2/gstwrappercamerabinsrc.h b/gst/camerabin2/gstwrappercamerabinsrc.h index 22697b93aa..2813e8b4b2 100644 --- a/gst/camerabin2/gstwrappercamerabinsrc.h +++ b/gst/camerabin2/gstwrappercamerabinsrc.h @@ -1,6 +1,7 @@ /* * GStreamer * Copyright (C) 2010 Texas Instruments, Inc + * Copyright (C) 2010 Thiago Santos * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -75,13 +76,14 @@ struct _GstWrapperCameraBinSrc GstElement *src_zoom_crop; GstElement *src_zoom_scale; GstElement *src_zoom_filter; + GstElement *output_selector; + + gboolean elements_created; guint src_event_probe_id; - /* srcpads of tee */ - GstPad *tee_vf_srcpad; - GstPad *tee_image_srcpad; - GstPad *tee_video_srcpad; + GstPad *outsel_imgpad; + GstPad *outsel_vidpad; GstPadEventFunction srcpad_event_func; From 203508079a8f8879cdc56ead5f8f71a539fdcb95 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Sun, 26 Dec 2010 20:35:47 -0300 Subject: [PATCH 217/448] camerabin2: Fix renegotiate event pushing Use a hack to make the event upstream to reach the camera source instead of going downstream and being useless. This was already fixed this way for image srcpad renegotiate and video srcpad was left unfixed. --- gst/camerabin2/gstcamerabin2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst/camerabin2/gstcamerabin2.c b/gst/camerabin2/gstcamerabin2.c index 442c681631..73a7fdf1c8 100644 --- a/gst/camerabin2/gstcamerabin2.c +++ b/gst/camerabin2/gstcamerabin2.c @@ -598,7 +598,7 @@ gst_camera_bin_set_property (GObject * object, guint prop_id, if (pad) { GST_DEBUG_OBJECT (camera, "Pushing renegotiate on %s", GST_PAD_NAME (pad)); - gst_pad_push_event (pad, gst_camera_bin_new_event_renegotiate ()); + GST_PAD_EVENTFUNC (pad) (pad, gst_camera_bin_new_event_renegotiate ()); gst_object_unref (pad); } } From bfe1e7f8bc967d7d88557f0d3ab625fa0667ffb6 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Sun, 26 Dec 2010 20:47:40 -0300 Subject: [PATCH 218/448] camerabin2: Add tests for video capture Add a test for capturing multiple videos with different resolutions in a sequence. --- tests/check/elements/camerabin2.c | 50 +++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) diff --git a/tests/check/elements/camerabin2.c b/tests/check/elements/camerabin2.c index a09bdd844b..6f3e295cb0 100644 --- a/tests/check/elements/camerabin2.c +++ b/tests/check/elements/camerabin2.c @@ -489,6 +489,55 @@ GST_START_TEST (test_single_video_recording) GST_END_TEST; +GST_START_TEST (test_multiple_video_recordings) +{ + gint i; + gint widths[] = { 800, 640, 1280 }; + gint heights[] = { 600, 480, 1024 }; + gint fr[] = { 20, 30, 5 }; + + if (!camera) + return; + + /* Set video recording mode */ + g_object_set (camera, "mode", 2, NULL); + + if (gst_element_set_state (GST_ELEMENT (camera), GST_STATE_PLAYING) == + GST_STATE_CHANGE_FAILURE) { + GST_WARNING ("setting camerabin to PLAYING failed"); + gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL); + gst_object_unref (camera); + camera = NULL; + } + + GST_INFO ("starting capture"); + fail_unless (camera != NULL); + for (i = 0; i < 3; i++) { + GstCaps *caps; + + caps = gst_caps_new_simple ("video/x-raw-rgb", "width", G_TYPE_INT, + widths[i], "height", G_TYPE_INT, heights[i], "framerate", + GST_TYPE_FRACTION, fr[i], 1, NULL); + + g_object_set (camera, "video-capture-caps", caps, + "location", make_test_file_name (VIDEO_FILENAME, i), NULL); + + gst_caps_unref (caps); + + g_signal_emit_by_name (camera, "start-capture", NULL); + g_usleep (VIDEO_DURATION * G_USEC_PER_SEC); + g_signal_emit_by_name (camera, "stop-capture", NULL); + g_usleep (1 * G_USEC_PER_SEC); + } + gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL); + + for (i = 0; i < 3; i++) { + check_file_validity (VIDEO_FILENAME, i, NULL, widths[i], heights[i]); + } +} + +GST_END_TEST; + GST_START_TEST (test_image_video_cycle) { gint i; @@ -619,6 +668,7 @@ camerabin_suite (void) tcase_add_test (tc_basic, test_single_video_recording); tcase_add_test (tc_basic, test_image_video_cycle); tcase_add_test (tc_basic, test_multiple_image_captures); + tcase_add_test (tc_basic, test_multiple_video_recordings); } return s; From 890c4ab4fdcb2791999ab35d849d6640ae72e101 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Sun, 26 Dec 2010 20:52:25 -0300 Subject: [PATCH 219/448] wrappercamerabinsrc: Implement video capture renegotiate Handle caps renegotiation from camerabin2's renegotiate event to allow video capture to be done with the user's requested resolution. --- gst/camerabin2/gstwrappercamerabinsrc.c | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/gst/camerabin2/gstwrappercamerabinsrc.c b/gst/camerabin2/gstwrappercamerabinsrc.c index 353e733ca8..74d27fe794 100644 --- a/gst/camerabin2/gstwrappercamerabinsrc.c +++ b/gst/camerabin2/gstwrappercamerabinsrc.c @@ -138,9 +138,8 @@ gst_wrapper_camera_bin_src_imgsrc_probe (GstPad * pad, GstBuffer * buffer, GstBaseCameraSrc *camerasrc = GST_BASE_CAMERA_SRC (data); gboolean ret = FALSE; - GST_LOG_OBJECT (self, "Image probe, mode %d, capture count %d, caps %" - GST_PTR_FORMAT, camerasrc->mode, self->image_capture_count, - GST_BUFFER_CAPS (buffer)); + GST_LOG_OBJECT (self, "Image probe, mode %d, capture count %d", + camerasrc->mode, self->image_capture_count); g_mutex_lock (camerasrc->capturing_mutex); if (self->image_capture_count > 0) { @@ -836,10 +835,29 @@ gst_wrapper_camera_bin_src_start_capture (GstBaseCameraSrc * camerasrc) start_image_capture (src); src->image_capture_count = 1; } else if (src->mode == MODE_VIDEO) { + GstCaps *caps = NULL; + g_mutex_unlock (camerasrc->capturing_mutex); gst_wrapper_camera_bin_reset_video_src_caps (src, NULL); g_mutex_lock (camerasrc->capturing_mutex); + if (src->video_renegotiate) { + /* clean capsfilter caps so they don't interfere here */ + g_object_set (src->src_filter, "caps", NULL, NULL); + if (src->src_zoom_filter) + g_object_set (src->src_zoom_filter, "caps", NULL, NULL); + + caps = gst_pad_get_allowed_caps (src->vidsrc); + caps = gst_caps_make_writable (caps); + gst_pad_fixate_caps (src->vidsrc, caps); + GST_DEBUG_OBJECT (src, "Vidsrc caps fixated to %" GST_PTR_FORMAT, caps); + + src->video_renegotiate = FALSE; + g_mutex_unlock (camerasrc->capturing_mutex); + gst_wrapper_camera_bin_reset_video_src_caps (src, caps); + g_mutex_lock (camerasrc->capturing_mutex); + gst_caps_unref (caps); + } if (src->video_rec_status == GST_VIDEO_RECORDING_STATUS_DONE) { src->video_rec_status = GST_VIDEO_RECORDING_STATUS_STARTING; } From 87c5c7a08bdb2ff479ffa307bc90a43d45191f08 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Mon, 27 Dec 2010 17:18:29 -0300 Subject: [PATCH 220/448] camerabin2: example: gitignore captured files --- tests/examples/camerabin2/.gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/examples/camerabin2/.gitignore b/tests/examples/camerabin2/.gitignore index cf225216fa..4a17e8d5c2 100644 --- a/tests/examples/camerabin2/.gitignore +++ b/tests/examples/camerabin2/.gitignore @@ -1,2 +1,4 @@ gst-camera2 test_*.jpg +vid_* +img_* From 95597d8f0e4c6813732d3d067236f35d3debf552 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Wed, 29 Dec 2010 13:18:37 -0300 Subject: [PATCH 221/448] camerabin2: Various leak fixes Various leak fixes and some code reorganization --- gst/camerabin2/gstwrappercamerabinsrc.c | 27 +++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) diff --git a/gst/camerabin2/gstwrappercamerabinsrc.c b/gst/camerabin2/gstwrappercamerabinsrc.c index 74d27fe794..ebf2d8e87b 100644 --- a/gst/camerabin2/gstwrappercamerabinsrc.c +++ b/gst/camerabin2/gstwrappercamerabinsrc.c @@ -57,6 +57,13 @@ static void set_capsfilter_caps (GstWrapperCameraBinSrc * self, static void gst_wrapper_camera_bin_src_dispose (GObject * object) { + GstWrapperCameraBinSrc *self = GST_WRAPPER_CAMERA_BIN_SRC (object); + + if (self->app_vid_src) { + gst_object_unref (self->app_vid_src); + self->app_vid_src = NULL; + } + G_OBJECT_CLASS (parent_class)->dispose (object); } @@ -116,7 +123,6 @@ gst_wrapper_camera_bin_reset_video_src_caps (GstWrapperCameraBinSrc * self, GstCaps * caps) { GST_DEBUG_OBJECT (self, "Resetting src caps to %" GST_PTR_FORMAT, caps); - /* TODO this won't work on NULL */ if (self->src_vid_src) { gst_element_set_state (self->src_vid_src, GST_STATE_NULL); set_capsfilter_caps (self, caps); @@ -268,6 +274,8 @@ gst_wrapper_camera_bin_src_construct_pipeline (GstBaseCameraSrc * bcamsrc) goto done; } } + /* we lost the reference */ + self->app_vid_src = NULL; /* add a buffer probe to the src elemento to drop EOS from READY->NULL */ { @@ -302,6 +310,7 @@ gst_wrapper_camera_bin_src_construct_pipeline (GstBaseCameraSrc * bcamsrc) /* viewfinder pad */ vf_pad = gst_element_get_request_pad (tee, "src%d"); g_object_set (tee, "alloc-pad", vf_pad, NULL); + gst_object_unref (vf_pad); /* the viewfinder should always work, so we add some converters to it */ if (!gst_camerabin_create_and_add_element (cbin, "ffmpegcolorspace")) @@ -309,9 +318,6 @@ gst_wrapper_camera_bin_src_construct_pipeline (GstBaseCameraSrc * bcamsrc) if (!(videoscale = gst_camerabin_create_and_add_element (cbin, "videoscale"))) goto done; - gst_object_unref (vf_pad); - vf_pad = gst_element_get_static_pad (videoscale, "src"); - /* image/video pad from tee */ tee_capture_pad = gst_element_get_request_pad (tee, "src%d"); @@ -325,6 +331,7 @@ gst_wrapper_camera_bin_src_construct_pipeline (GstBaseCameraSrc * bcamsrc) gst_pad_link (tee_capture_pad, pad); gst_object_unref (pad); } + gst_object_unref (tee_capture_pad); /* Create the 2 output pads for video and image */ self->outsel_vidpad = @@ -350,8 +357,10 @@ gst_wrapper_camera_bin_src_construct_pipeline (GstBaseCameraSrc * bcamsrc) NULL); } - /* hook-up the vf ghostpads */ + /* hook-up the vf ghostpad */ + vf_pad = gst_element_get_static_pad (videoscale, "src"); gst_ghost_pad_set_target (GST_GHOST_PAD (self->vfsrc), vf_pad); + gst_object_unref (vf_pad); gst_pad_set_active (self->vfsrc, TRUE); gst_pad_set_active (self->imgsrc, TRUE); /* XXX ??? */ @@ -446,8 +455,10 @@ adapt_image_capture (GstWrapperCameraBinSrc * self, GstCaps * in_caps) } /* Update capsfilters */ - gst_caps_replace (&self->image_capture_caps, - gst_caps_new_full (new_st, NULL)); + if (self->image_capture_caps) { + gst_caps_unref (self->image_capture_caps); + } + self->image_capture_caps = gst_caps_new_full (new_st, NULL); set_capsfilter_caps (self, self->image_capture_caps); /* Adjust the capsfilter before crop and videoscale elements if necessary */ @@ -830,7 +841,7 @@ gst_wrapper_camera_bin_src_start_capture (GstBaseCameraSrc * camerasrc) { GstWrapperCameraBinSrc *src = GST_WRAPPER_CAMERA_BIN_SRC (camerasrc); - /* TODO shoud we access this directly? Maybe a macro is better? */ + /* TODO should we access this directly? Maybe a macro is better? */ if (src->mode == MODE_IMAGE) { start_image_capture (src); src->image_capture_count = 1; From 222be5f0e9d13d031ff9b4a7efdaec70bd6c4735 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Thu, 30 Dec 2010 01:14:29 +0000 Subject: [PATCH 222/448] valve: move valve element/plugin to core https://bugzilla.gnome.org/show_bug.cgi?id=630808 --- Makefile.am | 5 +- configure.ac | 8 +- docs/plugins/Makefile.am | 1 - .../plugins/gst-plugins-bad-plugins-docs.sgml | 2 - .../gst-plugins-bad-plugins-sections.txt | 15 - docs/plugins/gst-plugins-bad-plugins.args | 738 ++++++++++++++++-- .../plugins/gst-plugins-bad-plugins.hierarchy | 322 +++++++- .../gst-plugins-bad-plugins.interfaces | 35 +- .../gst-plugins-bad-plugins.prerequisites | 6 +- docs/plugins/inspect/plugin-valve.xml | 34 - gst-plugins-bad.spec.in | 1 - gst/valve/Makefile.am | 9 - gst/valve/gstvalve.c | 284 ------- gst/valve/gstvalve.h | 82 -- tests/check/Makefile.am | 4 - tests/check/elements/.gitignore | 1 - tests/check/elements/valve.c | 135 ---- 17 files changed, 1044 insertions(+), 638 deletions(-) delete mode 100644 docs/plugins/inspect/plugin-valve.xml delete mode 100644 gst/valve/Makefile.am delete mode 100644 gst/valve/gstvalve.c delete mode 100644 gst/valve/gstvalve.h delete mode 100644 tests/check/elements/valve.c diff --git a/Makefile.am b/Makefile.am index 93388d7927..dad96866f2 100644 --- a/Makefile.am +++ b/Makefile.am @@ -49,12 +49,14 @@ CRUFT_FILES = \ $(top_builddir)/gst/aacparse/.libs/*.{so,dll,DLL,dylib} \ $(top_builddir)/gst/amrparse/.libs/*.{so,dll,DLL,dylib} \ $(top_builddir)/gst/flacparse/.libs/*.{so,dll,DLL,dylib} \ - $(top_builddir)/gst/shapewipe/.libs/*.{so,dll,DLL,dylib} \ $(top_builddir)/gst/imagefreeze/.libs/*.{so,dll,DLL,dylib} \ + $(top_builddir)/gst/shapewipe/.libs/*.{so,dll,DLL,dylib} \ + $(top_builddir)/gst/valve/.libs/*.{so,dll,DLL,dylib} \ $(top_builddir)/sys/oss4/.libs/*.{so,dll,DLL,dylib} \ $(top_builddir)/tests/check/elements/autocolorspace \ $(top_builddir)/tests/check/elements/capssetter \ $(top_builddir)/tests/check/elements/imagefreeze \ + $(top_builddir)/tests/check/elements/valve \ $(top_builddir)/tests/check/pipelines/metadata \ $(top_builddir)/tests/icles/test-oss4 @@ -64,6 +66,7 @@ CRUFT_DIRS = \ $(top_srcdir)/gst/flacparse \ $(top_srcdir)/gst/imagefreeze \ $(top_srcdir)/gst/shapewipe \ + $(top_srcdir)/gst/valve \ $(top_srcdir)/tests/examples/shapewipe \ $(top_srcdir)/ext/alsaspdif \ $(top_srcdir)/ext/ivorbis \ diff --git a/configure.ac b/configure.ac index 25edb91767..cde1da983f 100644 --- a/configure.ac +++ b/configure.ac @@ -50,8 +50,8 @@ AC_LIBTOOL_WIN32_DLL AM_PROG_LIBTOOL dnl *** required versions of GStreamer stuff *** -GST_REQ=0.10.31 -GSTPB_REQ=0.10.31 +GST_REQ=0.10.31.1 +GSTPB_REQ=0.10.31.1 dnl *** autotools stuff **** @@ -178,7 +178,7 @@ AC_CHECK_FUNC(socket,,[AC_CHECK_LIB(socket,socket)]) AC_CHECK_FUNC(gethostbyname,,[AC_CHECK_LIB(nsl,gethostbyname)]) dnl GLib is required -AG_GST_GLIB_CHECK([2.20]) +AG_GST_GLIB_CHECK([2.22]) dnl checks for gstreamer dnl uninstalled is selected preferentially -- see pkg-config(1) @@ -343,7 +343,6 @@ AG_GST_CHECK_PLUGIN(speed) AG_GST_CHECK_PLUGIN(subenc) AG_GST_CHECK_PLUGIN(stereo) AG_GST_CHECK_PLUGIN(tta) -AG_GST_CHECK_PLUGIN(valve) AG_GST_CHECK_PLUGIN(videomaxrate) AG_GST_CHECK_PLUGIN(videomeasure) AG_GST_CHECK_PLUGIN(videosignal) @@ -1773,7 +1772,6 @@ gst/speed/Makefile gst/subenc/Makefile gst/stereo/Makefile gst/tta/Makefile -gst/valve/Makefile gst/videomaxrate/Makefile gst/videomeasure/Makefile gst/videosignal/Makefile diff --git a/docs/plugins/Makefile.am b/docs/plugins/Makefile.am index ff940df719..478b90eb90 100644 --- a/docs/plugins/Makefile.am +++ b/docs/plugins/Makefile.am @@ -203,7 +203,6 @@ EXTRA_HFILES = \ $(top_srcdir)/gst/videosignal/gstvideoanalyse.h \ $(top_srcdir)/gst/videosignal/gstvideodetect.h \ $(top_srcdir)/gst/videosignal/gstvideomark.h \ - $(top_srcdir)/gst/valve/gstvalve.h \ $(top_srcdir)/sys/directdraw/gstdirectdrawsink.h \ $(top_srcdir)/sys/dvb/gstdvbsrc.h \ $(top_srcdir)/sys/shm/gstshmsink.h \ diff --git a/docs/plugins/gst-plugins-bad-plugins-docs.sgml b/docs/plugins/gst-plugins-bad-plugins-docs.sgml index 575afc1b1a..cb2ff1a69b 100644 --- a/docs/plugins/gst-plugins-bad-plugins-docs.sgml +++ b/docs/plugins/gst-plugins-bad-plugins-docs.sgml @@ -122,7 +122,6 @@ - @@ -215,7 +214,6 @@ - diff --git a/docs/plugins/gst-plugins-bad-plugins-sections.txt b/docs/plugins/gst-plugins-bad-plugins-sections.txt index fdfb78136c..8f26b09b8d 100644 --- a/docs/plugins/gst-plugins-bad-plugins-sections.txt +++ b/docs/plugins/gst-plugins-bad-plugins-sections.txt @@ -1602,21 +1602,6 @@ gst_twirl_get_type gst_twirl_plugin_init -
-element-valve -valve -GstValve - -GstValveClass -GstValvePrivate -gst_valve_get_type -GST_IS_VALVE -GST_IS_VALVE_CLASS -GST_TYPE_VALVE -GST_VALVE -GST_VALVE_CLASS -
-
element-videoanalyse videoanalyse diff --git a/docs/plugins/gst-plugins-bad-plugins.args b/docs/plugins/gst-plugins-bad-plugins.args index 4717bb9aa1..73c886cbbb 100644 --- a/docs/plugins/gst-plugins-bad-plugins.args +++ b/docs/plugins/gst-plugins-bad-plugins.args @@ -41,7 +41,7 @@ GstXvidEnc::averaging-period gint -[-1,100] +[G_MAXULONG,100] rw Averaging Period [CBR] Number of frames for which XviD averages bitrate. @@ -91,7 +91,7 @@ GstXvidEnc::buffer gint ->= -1 +>= G_MAXULONG rw Buffer Size [CBR] Size of the video buffers. @@ -121,7 +121,7 @@ GstXvidEnc::container-frame-overhead gint -[-1,100] +[G_MAXULONG,100] rw Container Frame Overhead [PASS2] Average container overhead per frame. @@ -151,7 +151,7 @@ GstXvidEnc::flow-control-strength gint -[-1,100] +[G_MAXULONG,100] rw Flow Control Strength [PASS2] Overflow control strength per frame. @@ -211,7 +211,7 @@ GstXvidEnc::keyframe-reduction gint -[-1,100] +[G_MAXULONG,100] rw Keyframe Reduction [PASS2] Keyframe size reduction in % of those within threshold. @@ -221,7 +221,7 @@ GstXvidEnc::keyframe-threshold gint -[-1,100] +[G_MAXULONG,100] rw Keyframe Threshold [PASS2] Distance between keyframes not to be subject to reduction. @@ -281,7 +281,7 @@ GstXvidEnc::max-overflow-degradation gint -[-1,100] +[G_MAXULONG,100] rw Max Overflow Degradation [PASS2] Amount in % that flow control can decrease frame size compared to ideal curve. @@ -291,7 +291,7 @@ GstXvidEnc::max-overflow-improvement gint -[-1,100] +[G_MAXULONG,100] rw Max Overflow Improvement [PASS2] Amount in % that flow control can increase frame size compared to ideal curve. @@ -421,7 +421,7 @@ GstXvidEnc::reaction-delay-factor gint -[-1,100] +[G_MAXULONG,100] rw Reaction Delay Factor [CBR] Reaction delay factor. @@ -1731,7 +1731,7 @@ GstDvbSrc::diseqc-source gint -[-1,7] +[G_MAXULONG,7] rw diseqc source DISEqC selected source (-1 disabled) (DVB-S). @@ -17175,7 +17175,7 @@ rw Path where to search for RealPlayer codecs Path where to search for RealPlayer codecs. -"/usr/lib/win32:/usr/lib/codecs:/usr/local/RealPlayer/codecs:/usr/local/lib/win32:/usr/local/lib/codecs" +"/usr/lib64/win32:/usr/lib64/codecs:/usr/local/lib64/win32:/usr/local/lib64/codecs" @@ -17215,7 +17215,7 @@ rw Path where to search for RealPlayer codecs Path where to search for RealPlayer codecs. -"/usr/lib/win32:/usr/lib/codecs:/usr/local/RealPlayer/codecs:/usr/local/lib/win32:/usr/local/lib/codecs" +"/usr/lib64/win32:/usr/lib64/codecs:/usr/local/lib64/win32:/usr/local/lib64/codecs" @@ -17871,7 +17871,7 @@ DvbBaseBin::diseqc-source gint -[-1,7] +[G_MAXULONG,7] rw diseqc source DISEqC selected source (-1 disabled) (DVB-S). @@ -18018,6 +18018,16 @@ 10000000 + +GstSDPDemux::redirect +gboolean + +rwx +Redirect +Sends a redirection message instead of using a custom session element. +TRUE + + GstSpeexResample::quality gint @@ -18098,6 +18108,16 @@ 16 + +GstAudioParse::channel-positions +GValueArray* + +rw +Channel positions +Channel positions used on the output. + + + GstVideoParse::alpha-mask gint @@ -21916,11 +21936,11 @@ GstCeltEnc::bitrate gint -[10,320] +[10000,320000] rw Encoding Bit-rate -Specify an encoding bit-rate (in Kbps). -64 +Specify an encoding bit-rate (in bps). +64000 @@ -21956,11 +21976,11 @@ GstCeltEnc::max-bitrate gint -[10,320] +[10000,320000] rw Maximum Encoding Bit-rate -Specify a maximum encoding bit rate (in Kbps) for variable bit rate encoding. -64 +Specify a maximum encoding bit rate (in bps) for variable bit rate encoding. +64000 @@ -22066,7 +22086,7 @@ GstDCCPClientSrc::sockfd gint ->= -1 +>= G_MAXULONG rw Socket fd The socket file descriptor. @@ -22106,7 +22126,7 @@ GstDCCPServerSink::sockfd gint ->= -1 +>= G_MAXULONG rw Socket fd The client socket file descriptor. @@ -22166,7 +22186,7 @@ GstDCCPClientSink::sockfd gint ->= -1 +>= G_MAXULONG rw Socket fd The socket file descriptor. @@ -22226,7 +22246,7 @@ GstDCCPServerSrc::sockfd gint ->= -1 +>= G_MAXULONG rw Socket fd The client socket file descriptor. @@ -22286,7 +22306,7 @@ GstMpegTSDemux::program-number gint ->= -1 +>= G_MAXULONG rw Program Number Program number to demux for (-1 to ignore). @@ -22346,7 +22366,7 @@ GstPcapParse::dst-port gint -[-1,65535] +[G_MAXULONG,65535] rw Destination port Destination port to restrict to. @@ -22366,13 +22386,23 @@ GstPcapParse::src-port gint -[-1,65535] +[G_MAXULONG,65535] rw Source port Source port to restrict to. -1 + +GstPcapParse::caps +GstCaps* + +rw +Caps +The caps of the source pad. + + + MpegTsMux::m2ts-mode gboolean @@ -22523,6 +22553,36 @@ NULL + +GstMJ2Mux::fragment-duration +guint + +rwx +Fragment duration +Fragment durations in ms (produce a fragmented file if > 0). +0 + + + +GstMJ2Mux::streamable +gboolean + +rwx +Streamable +If set to true, the output should be as if it is to be streamed and hence no indexes written or duration written. +FALSE + + + +GstMJ2Mux::trak-timescale +guint + +rwx +Track timescale +Timescale to use for the tracks (units per second, 0 is automatic). +0 + + GstGPPMux::faststart gboolean @@ -22583,6 +22643,36 @@ NULL + +GstGPPMux::fragment-duration +guint + +rwx +Fragment duration +Fragment durations in ms (produce a fragmented file if > 0). +0 + + + +GstGPPMux::streamable +gboolean + +rwx +Streamable +If set to true, the output should be as if it is to be streamed and hence no indexes written or duration written. +FALSE + + + +GstGPPMux::trak-timescale +guint + +rwx +Track timescale +Timescale to use for the tracks (units per second, 0 is automatic). +0 + + GstMP4Mux::faststart gboolean @@ -22643,6 +22733,36 @@ NULL + +GstMP4Mux::fragment-duration +guint + +rwx +Fragment duration +Fragment durations in ms (produce a fragmented file if > 0). +0 + + + +GstMP4Mux::streamable +gboolean + +rwx +Streamable +If set to true, the output should be as if it is to be streamed and hence no indexes written or duration written. +FALSE + + + +GstMP4Mux::trak-timescale +guint + +rwx +Track timescale +Timescale to use for the tracks (units per second, 0 is automatic). +0 + + GstQTMux::faststart gboolean @@ -22703,6 +22823,36 @@ NULL + +GstQTMux::fragment-duration +guint + +rwx +Fragment duration +Fragment durations in ms (produce a fragmented file if > 0). +0 + + + +GstQTMux::streamable +gboolean + +rwx +Streamable +If set to true, the output should be as if it is to be streamed and hence no indexes written or duration written. +FALSE + + + +GstQTMux::trak-timescale +guint + +rwx +Track timescale +Timescale to use for the tracks (units per second, 0 is automatic). +0 + + GstAudioresample::filter-length gint @@ -22895,12 +23045,12 @@ GstCameraBin::zoom -gint -[100,1000] +gfloat +[1,10] rw Zoom -The zoom. 100 for 1x, 200 for 2x and so on. -100 +The zoom. 1.0 for 1x, 2.0 for 2x and so on. +1 @@ -23103,6 +23253,36 @@ + +GstCameraBin::idle +gboolean + +r +Indicates if data is being processed (recording/capturing/saving) +Indicates if data is being processed (recording/capturing/saving). +TRUE + + + +GstCameraBin::preview-source-filter +GstElement* + +rw +preview source filter element +Optional preview source filter GStreamer element. + + + + +GstCameraBin::ready-for-capture +gboolean + +r +Indicates if preparing a new capture is possible +Indicates if preparing a new capture is possible. +TRUE + + GstDTMFSrc::interval guint @@ -23166,7 +23346,7 @@ GstRTPDTMFSrc::seqnum-offset gint ->= -1 +>= G_MAXULONG rw Sequence number Offset Offset to add to all outgoing seqnum (-1 = random). @@ -23196,7 +23376,7 @@ GstRTPDTMFSrc::timestamp-offset gint ->= -1 +>= G_MAXULONG rw Timestamp Offset Offset to add to all outgoing timestamps (-1 = random). @@ -23246,7 +23426,7 @@ GstRTPMux::seqnum-offset gint ->= -1 +>= G_MAXULONG rw Sequence number Offset Offset to add to all outgoing seqnum (-1 = random). @@ -23266,7 +23446,7 @@ GstRTPMux::timestamp-offset gint ->= -1 +>= G_MAXULONG rw Timestamp Offset Offset to add to all outgoing timestamps (-1 = random). @@ -26410,7 +26590,7 @@ rw physics water density: from 1 to 4. -8.20075e-304 +0 @@ -26450,7 +26630,7 @@ rw splash make a big splash in the center. -0 +7.7486e-304 @@ -26460,7 +26640,7 @@ rw splash make a big splash in the center. -4.77773e-299 +0 @@ -26490,7 +26670,7 @@ rw ratiox x-ratio. -8.0843e+44 +8.55111e-317 @@ -26500,7 +26680,7 @@ rw ratioy y-ratio. -9.3207e+68 +2.28459e-26 @@ -26510,7 +26690,7 @@ rw DelayTime the delay time. -1.18576e-322 +0 @@ -26560,7 +26740,7 @@ rw Color-R the color of the image. -0 +2.49965e-38 @@ -26890,7 +27070,7 @@ rw lredscale multiplier for downscaling non-edge brightness. -0 +3.40216e-111 @@ -26910,7 +27090,7 @@ rw lupscale multiplier for upscaling edge brightness. -1.34037e-317 +7.54985e-96 @@ -27080,7 +27260,7 @@ rw blend blend factor. -7.75038e-304 +-5.83169e+303 @@ -27090,7 +27270,7 @@ rw fader the fader position. -5.12056e+199 +1.20296e-314 @@ -27270,7 +27450,7 @@ rw HSync the hsync offset. -2.07558e-316 +2.98023e-08 @@ -43118,11 +43298,21 @@ gboolean rw -mesage +message Post a barcode message for each detected code. TRUE + +GstZBar::cache +gboolean + +rw +cache +Enable or disable the inter-image result cache. +FALSE + + GstQTMoovRecover::broken-input gchar* @@ -45753,6 +45943,36 @@ GST_PHOTOGRAPHY_WB_MODE_AUTO + +GstPhotography::image-preview-supported-caps +GstCaps* + +r +Image preview supported caps +Caps describing supported image preview formats. + + + + +GstPhotography::noise-reduction +GstPhotographyNoiseReduction + +rw +Noise Reduction settings +Which noise reduction modes are enabled (0 = disabled). + + + + +GstPhotography::zoom +gfloat +[1,10] +rw +Zoom property +How much the resulted image will be zoomed. +1 + + GstWaterRipple::amplitude gdouble @@ -46113,6 +46333,36 @@ FALSE + +GstSolarize::end +guint +<= 256 +rw +End +End parameter. +185 + + + +GstSolarize::start +guint +<= 256 +rw +Start +Start parameter. +50 + + + +GstSolarize::threshold +guint +<= 256 +rw +Threshold +Threshold parameter. +127 + + GstExclusion::silent gboolean @@ -46123,6 +46373,16 @@ FALSE + +GstExclusion::factor +guint +<= 175 +rw +Factor +Exclusion factor parameter. +175 + + GstDodge::silent gboolean @@ -46143,6 +46403,16 @@ FALSE + +GstDilate::erode +gboolean + +rw +Erode +Erode parameter. +FALSE + + GstChromium::silent gboolean @@ -46153,6 +46423,26 @@ FALSE + +GstChromium::edge-a +guint +<= 256 +rw +Edge A +First edge parameter. +200 + + + +GstChromium::edge-b +guint +<= 256 +rw +Edge B +Second edge parameter. +1 + + GstBurn::silent gboolean @@ -46163,6 +46453,16 @@ FALSE + +GstBurn::adjustment +guint +<= 256 +rw +Adjustment +Adjustment parameter. +175 + + GaussBlur::sigma gdouble @@ -46303,6 +46603,36 @@ FALSE + +GstInterlace::allow-rff +gboolean + +rw +Allow Repeat-First-Field flags +Allow generation of buffers with RFF flag set, i.e., duration of 3 fields. +FALSE + + + +GstInterlace::field-pattern +GstInterlacePattern + +rw +Field pattern +The output field pattern. +2:3 + + + +GstInterlace::pattern-offset +guint +<= 12 +rw +Pattern offset +The initial field pattern offset. Counts from 0. +0 + + Gsttextwrite::colorB gint @@ -46483,6 +46813,56 @@ "/usr/share/opencv/haarcascades/haarcascade_frontalface_default.xml" + +Gstfacedetect::flags +GstOpencvFaceDetectFlags + +rw +Flags +Flags to cvHaarDetectObjects. + + + + +Gstfacedetect::min-neighbors +gint +>= 0 +rw +Mininum neighbors +Minimum number (minus 1) of neighbor rectangles that makes up an object. +3 + + + +Gstfacedetect::min-size-height +gint +>= 0 +rw +Minimum size height +Minimum window height size. +0 + + + +Gstfacedetect::min-size-width +gint +>= 0 +rw +Minimum size width +Minimum window width size. +0 + + + +Gstfacedetect::scale-factor +gdouble +[1.1,10] +rw +Scale factor +Factor by which the windows is scaled after each scan. +1.1 + + Gstfaceblur::profile gchar* @@ -46546,7 +46926,7 @@ GstCvSobel::x-order gint ->= -1 +>= G_MAXULONG rw x order Order of the derivative x. @@ -46556,7 +46936,7 @@ GstCvSobel::y-order gint ->= -1 +>= G_MAXULONG rw y order Order of the derivative y. @@ -46623,3 +47003,263 @@ 3 + +GstRotate::angle +gdouble + +rw +angle +Angle at which the arc starts in radians. +0 + + + +GstJP2kDecimator::max-decomposition-levels +gint +[G_MAXULONG,32] +rw +Maximum Number of Decomposition Levels +Maximum number of decomposition levels to keep (-1 == all). +-1 + + + +GstJP2kDecimator::max-layers +gint +[0,65535] +rw +Maximum Number of Layers +Maximum number of layers to keep (0 == all). +0 + + + +GstISMLMux::faststart +gboolean + +rw +Format file to faststart +If the file should be formated for faststart (headers first). . +FALSE + + + +GstISMLMux::faststart-file +gchar* + +rwx +File to use for storing buffers +File that will be used temporarily to store data from the stream when creating a faststart file. If null a filepath will be created automatically. +NULL + + + +GstISMLMux::fragment-duration +guint + +rwx +Fragment duration +Fragment durations in ms (produce a fragmented file if > 0). +2000 + + + +GstISMLMux::large-file +gboolean + +rw +Support for large files +Uses 64bits to some fields instead of 32bits, providing support for large files. +FALSE + + + +GstISMLMux::moov-recovery-file +gchar* + +rwx +File to store data for posterior moov atom recovery +File to be used to store data for moov atom making movie file recovery possible in case of a crash during muxing. Null for disabled. (Experimental). +NULL + + + +GstISMLMux::movie-timescale +guint +>= 1 +rwx +Movie timescale +Timescale to use in the movie (units per second). +1000 + + + +GstISMLMux::presentation-time +gboolean + +rwx +Include presentation-time info +Calculate and include presentation/composition time (in addition to decoding time) (use with caution). +FALSE + + + +GstISMLMux::streamable +gboolean + +rwx +Streamable +If set to true, the output should be as if it is to be streamed and hence no indexes written or duration written. +FALSE + + + +GstISMLMux::trak-timescale +guint + +rwx +Track timescale +Timescale to use for the tracks (units per second, 0 is automatic). +0 + + + +GstChopMyData::max-size +gint +>= 1 +rw +max-size +Maximum size of outgoing buffers. +4096 + + + +GstChopMyData::min-size +gint +>= 1 +rw +max-size +Minimum size of outgoing buffers. +1 + + + +GstChopMyData::step-size +gint +>= 1 +rw +step-size +Step increment for random buffer sizes. +4096 + + + +GstChromaHold::target-b +guint +<= 255 +rw +Target Blue +The Blue target. +0 + + + +GstChromaHold::target-g +guint +<= 255 +rw +Target Green +The Green target. +0 + + + +GstChromaHold::target-r +guint +<= 255 +rw +Target Red +The Red target. +255 + + + +GstChromaHold::tolerance +guint +<= 180 +rw +Tolerance +Tolerance for the target color. +30 + + + +GstDVBSubOverlay::enable +gboolean + +rw +Enable +Enable rendering of subtitles. +TRUE + + + +GstDVBSubOverlay::max-page-timeout +gint +>= 0 +rw +max-page-timeout +Limit maximum display time of a subtitle page (0 - disabled, value in seconds). +0 + + + +GstRsvgOverlay::data +gchar* + +w +data +SVG data. +"" + + + +GstRsvgOverlay::fit-to-frame +gboolean + +rw +fit to frame +Fit the SVG to fill the whole frame. +TRUE + + + +GstRsvgOverlay::location +gchar* + +w +location +SVG file location. +"" + + + +GstRsvgOverlay::x +gint +>= 0 +rw +x offset +Specify an x offset. +0 + + + +GstRsvgOverlay::y +gint +>= 0 +rw +y offset +Specify a y offset. +0 + + diff --git a/docs/plugins/gst-plugins-bad-plugins.hierarchy b/docs/plugins/gst-plugins-bad-plugins.hierarchy index c8888c2908..d377a64fa5 100644 --- a/docs/plugins/gst-plugins-bad-plugins.hierarchy +++ b/docs/plugins/gst-plugins-bad-plugins.hierarchy @@ -3,11 +3,14 @@ GObject GstObject GstBus GstClock + GstSystemClock + GstAudioClock GstElement ADPCMDec ADPCMEnc GstAiffMux GstAiffParse + GstAmrWbEnc GstAsfMux GstAsfParse GstAssRender @@ -15,37 +18,58 @@ GObject GstAacParse GstAc3Parse GstAmrParse + GstDcaParse GstFlacParse - GstBaseMetadata - GstMetadataDemux - GstMetadataMux + GstMpegAudioParse GstBaseRTPDepayload GstRtpDTMFDepay GstBaseRTPPayload GstRtpAsfPay GstBaseSink - AlsaSPDIFSink + GstBaseAudioSink + GstAudioSink + GstApExSink + GstNasSink + GstSDLAudioSink + GstJackAudioSink GstChecksumSink GstDCCPClientSink GstDCCPServerSink GstFBDEVSink + GstSFSink GstShmSink GstVideoSink GstDfbVideoSink + GstSDLVideoSink + VdpSink GstBaseSrc GstDTMFSrc GstDataURISrc GstPushSrc + GstBaseAudioSrc + GstJackAudioSrc GstDCCPClientSrc GstDCCPServerSrc + GstDc1394 GstDvbSrc GstMMS + GstMythtvSrc + GstNeonhttpSrc GstRfbSrc GstShmSrc GstVCDSrc + frei0r-src-ising0r + frei0r-src-lissajous0r + frei0r-src-nois0r + frei0r-src-onecol0r + frei0r-src-partik0l + frei0r-src-plasma GstRTPDTMFSrc + GstSFSrc GstBaseTransform GstAudioFilter + GstBPMDetect + GstOFA GstStereo GstBayer2RGB GstCogScale @@ -62,8 +86,10 @@ GObject GstVideoFilter GaussBlur GstBurn + GstChromaHold GstChromium GstColorEffects + GstCsp GstDilate GstDodge GstExclusion @@ -82,6 +108,7 @@ GObject GstFisheye GstMarble GstMirror + GstRotate GstSquare GstOpencvVideoFilter GstCvDilateErode @@ -92,20 +119,97 @@ GObject GstCvSmooth GstCvSobel Gstfacedetect + GstRsvgOverlay GstSolarize GstVideoAnalyse GstVideoDetect GstVideoMark + GstZBar + frei0r-filter-3-point-color-balance + frei0r-filter-3dflippo + frei0r-filter-b + frei0r-filter-baltan + frei0r-filter-bluescreen0r + frei0r-filter-brightness + frei0r-filter-bw0r + frei0r-filter-cartoon + frei0r-filter-color-distance + frei0r-filter-contrast0r + frei0r-filter-curves + frei0r-filter-dealygrab + frei0r-filter-delay0r + frei0r-filter-distort0r + frei0r-filter-edgeglow + frei0r-filter-equaliz0r + frei0r-filter-flippo + frei0r-filter-g + frei0r-filter-gamma + frei0r-filter-glow + frei0r-filter-hueshift0r + frei0r-filter-invert0r + frei0r-filter-k-means-clustering + frei0r-filter-lens-correction + frei0r-filter-letterb0xed + frei0r-filter-levels + frei0r-filter-luminance + frei0r-filter-mask0mate + frei0r-filter-nervous + frei0r-filter-nosync0r + frei0r-filter-perspective + frei0r-filter-pixeliz0r + frei0r-filter-primaries + frei0r-filter-r + frei0r-filter-rgb-parade + frei0r-filter-saturat0r + frei0r-filter-scale0tilt + frei0r-filter-scanline0r + frei0r-filter-sobel + frei0r-filter-squareblur + frei0r-filter-tehroxx0r + frei0r-filter-threelay0r + frei0r-filter-threshold0r + frei0r-filter-tint0r + frei0r-filter-transparency + frei0r-filter-twolay0r + frei0r-filter-vectorscope + frei0r-filter-vertigo + frei0r-filter-water + frei0r-filter-white-balance GstVideoMaxRate + GstBaseVideoCodec + GstBaseVideoDecoder + GstSchroDec + GstVP8Dec + GstBaseVideoEncoder + GstDiracEnc + GstSchroEnc + GstVP8Enc + GstBaseVideoParse + GstSchroParse GstBin DvbBaseBin GstAutoConvert + GstAutoVideoConvert GstFPSDisplaySink + GstGSettingsSwitchSink + GstGSettingsAudioSink + GstGSettingsVideoSink + GstGSettingsSwitchSrc + GstGSettingsAudioSrc + GstGSettingsVideoSrc GstPipeline GstCameraBin GstQTMoovRecover GstSDPDemux + RsnDvdBin + GstBz2dec + GstBz2enc + GstCDAudio GstCDXAParse + GstCeltDec + GstCeltEnc + GstChopMyData + GstDVBSubOverlay GstDVDSpu GstDtsDec GstFaac @@ -113,34 +217,46 @@ GObject GstFestival GstFreeze GstGPPMux + GstGSMDec + GstGSMEnc GstH264Parse + GstISMLMux GstId3BaseMux GstId3Mux GstInputSelector GstInterlace GstInvtelecine GstIvfParse + GstJP2kDecimator GstJifMux GstJpegParse GstKateDec GstKateEnc GstKateParse GstKateTag + GstKateTiger GstLiveAdder GstMJ2Mux GstMP4Mux GstMSE GstMXFDemux GstMXFMux + GstMimDec + GstMimEnc + GstModPlug + GstMpeg2enc GstMpeg4VParse GstMpegPSDemux GstMpegTSDemux + GstMplex + GstMusepackDec GstMveDemux GstMveMux GstNsfDec GstNuvDemux GstOutputSelector GstPcapParse + GstPitch GstPnmdec GstPnmenc GstQTMux @@ -156,18 +272,170 @@ GObject GstSegmentClip GstAudioSegmentClip GstVideoSegmentClip + GstSignalProcessor + ladspa-Chorus1 + ladspa-Chorus2 + ladspa-G2reverb + ladspa-Mvchpf-1 + ladspa-Mvclpf-1 + ladspa-Mvclpf-2 + ladspa-Mvclpf-3 + ladspa-Mvclpf-4 + ladspa-Phaser1 + ladspa-Phaser1+LFO + ladspa-TripleChorus + ladspa-alias + ladspa-allpass-c + ladspa-allpass-l + ladspa-allpass-n + ladspa-amPitchshift + ladspa-amp + ladspa-amp-mono + ladspa-amp-stereo + ladspa-analogueOsc + ladspa-artificialLatency + ladspa-autoPhaser + ladspa-bandpass-a-iir + ladspa-bandpass-iir + ladspa-bodeShifter + ladspa-bodeShifterCV + ladspa-butthigh-iir + ladspa-buttlow-iir + ladspa-bwxover-iir + ladspa-chebstortion + ladspa-comb + ladspa-comb-c + ladspa-comb-l + ladspa-comb-n + ladspa-combSplitter + ladspa-const + ladspa-crossoverDist + ladspa-dcRemove + ladspa-decay + ladspa-decimator + ladspa-declip + ladspa-delay-5s + ladspa-delay-c + ladspa-delay-l + ladspa-delay-n + ladspa-delayorama + ladspa-diode + ladspa-divider + ladspa-dj-eq + ladspa-dj-eq-mono + ladspa-djFlanger + ladspa-dysonCompress + ladspa-fadDelay + ladspa-fastLookaheadLimiter + ladspa-flanger + ladspa-fmOsc + ladspa-foldover + ladspa-fourByFourPole + ladspa-foverdrive + ladspa-freqTracker + ladspa-gate + ladspa-giantFlange + ladspa-gong + ladspa-gongBeater + ladspa-gsm + ladspa-gverb + ladspa-hardLimiter + ladspa-harmonicGen + ladspa-hermesFilter + ladspa-highpass-iir + ladspa-hilbert + ladspa-hpf + ladspa-imp + ladspa-impulse-fc + ladspa-inv + ladspa-karaoke + ladspa-lcrDelay + ladspa-lfoPhaser + ladspa-lowpass-iir + ladspa-lpf + ladspa-lsFilter + ladspa-matrixMSSt + ladspa-matrixSpatialiser + ladspa-matrixStMS + ladspa-mbeq + ladspa-modDelay + ladspa-multivoiceChorus + ladspa-noise-white + ladspa-notch-iir + ladspa-pitchScale + ladspa-pitchScaleHQ + ladspa-plate + ladspa-pointerCastDistortion + ladspa-rateShifter + ladspa-retroFlange + ladspa-revdelay + ladspa-ringmod-1i1o1l + ladspa-ringmod-2i1o + ladspa-satanMaximiser + ladspa-sc1 + ladspa-sc2 + ladspa-sc3 + ladspa-sc4 + ladspa-sc4m + ladspa-se4 + ladspa-shaper + ladspa-sifter + ladspa-sinCos + ladspa-sine-faaa + ladspa-sine-faac + ladspa-sine-fcaa + ladspa-sine-fcac + ladspa-singlePara + ladspa-sinusWavewrapper + ladspa-smoothDecimate + ladspa-split + ladspa-stepMuxer + ladspa-surroundEncoder + ladspa-svf + ladspa-tap-autopan + ladspa-tap-chorusflanger + ladspa-tap-deesser + ladspa-tap-doubler + ladspa-tap-dynamics-m + ladspa-tap-dynamics-st + ladspa-tap-equalizer + ladspa-tap-equalizer-bw + ladspa-tap-limiter + ladspa-tap-pinknoise + ladspa-tap-pitch + ladspa-tap-reflector + ladspa-tap-reverb + ladspa-tap-rotspeak + ladspa-tap-sigmoid + ladspa-tap-stereo-echo + ladspa-tap-tremolo + ladspa-tap-tubewarmth + ladspa-tap-vibrato + ladspa-tapeDelay + ladspa-transient + ladspa-triplePara + ladspa-valve + ladspa-valveRect + ladspa-vynil + ladspa-waveTerrain + ladspa-xfade + ladspa-xfade4 + ladspa-zm1 GstSirenDec GstSirenEnc GstSpeed GstSrtEnc + GstTRM GstTemplateMatch GstTtaDec GstTtaParse GstVMncDec - GstValve GstVcdParse + GstVdpVideoPostProcess + GstWildmidi GstXvidDec GstXvidEnc + GstY4mDec Gstedgedetect Gstfaceblur Gstpyramidsegment @@ -176,8 +444,46 @@ GObject MpegTSParse MpegTsMux MpegVideoParse + SatBaseVideoDecoder + GstVdpDecoder + GstVdpH264Dec + GstVdpMpeg4Dec + GstVdpMpegDec + frei0r-mixer-addition + frei0r-mixer-alpha-injection + frei0r-mixer-alphaatop + frei0r-mixer-alphain + frei0r-mixer-alphaout + frei0r-mixer-alphaover + frei0r-mixer-alphaxor + frei0r-mixer-blend + frei0r-mixer-burn + frei0r-mixer-color-only + frei0r-mixer-composition + frei0r-mixer-darken + frei0r-mixer-difference + frei0r-mixer-divide + frei0r-mixer-dodge + frei0r-mixer-grain-extract + frei0r-mixer-grain-merge + frei0r-mixer-hardlight + frei0r-mixer-hue + frei0r-mixer-lighten + frei0r-mixer-multiply + frei0r-mixer-overlay + frei0r-mixer-rgb + frei0r-mixer-saturation + frei0r-mixer-screen + frei0r-mixer-softlight + frei0r-mixer-subtract + frei0r-mixer-uv-map + frei0r-mixer-value + frei0r-mixer-xfade0r GstPad + GstVdpOutputSrcPad + GstVdpVideoSrcPad GstPadTemplate + GstSignalProcessorPadTemplate GstPlugin GstPluginFeature GstElementFactory @@ -185,9 +491,13 @@ GObject GstTypeFindFactory GstRegistry GstRingBuffer + GstAudioSinkRingBuffer + GstJackAudioSinkRingBuffer + GstJackAudioSrcRingBuffer GstTask GstTaskPool GstSignalObject + GstVdpDevice MpegTsPatInfo MpegTsPmtInfo GInterface @@ -195,9 +505,11 @@ GInterface GstChildProxy GstColorBalance GstImplementsInterface + GstMixer GstNavigation GstPhotography GstPreset GstTagSetter GstURIHandler + GstXOverlay MXFDescriptiveMetadataFrameworkInterface diff --git a/docs/plugins/gst-plugins-bad-plugins.interfaces b/docs/plugins/gst-plugins-bad-plugins.interfaces index a135859ace..bfa93f0553 100644 --- a/docs/plugins/gst-plugins-bad-plugins.interfaces +++ b/docs/plugins/gst-plugins-bad-plugins.interfaces @@ -1,25 +1,44 @@ GstBin GstChildProxy GstPipeline GstChildProxy +GstCameraBin GstChildProxy GstImplementsInterface GstColorBalance GstTagSetter GstQTMoovRecover GstChildProxy -GstCameraBin GstChildProxy GstImplementsInterface GstColorBalance GstTagSetter GstPhotography +GstGSettingsSwitchSink GstChildProxy +GstGSettingsAudioSink GstChildProxy +GstGSettingsVideoSink GstChildProxy +GstGSettingsSwitchSrc GstChildProxy +GstGSettingsAudioSrc GstChildProxy +GstGSettingsVideoSrc GstChildProxy +RsnDvdBin GstChildProxy GstURIHandler DvbBaseBin GstChildProxy GstURIHandler -GstSDPDemux GstChildProxy GstAutoConvert GstChildProxy +GstAutoVideoConvert GstChildProxy +GstSDPDemux GstChildProxy GstFPSDisplaySink GstChildProxy -GstXvidEnc GstPreset +GstMpeg2enc GstPreset +GstSDLVideoSink GstImplementsInterface GstXOverlay GstNavigation GstDfbVideoSink GstImplementsInterface GstNavigation GstColorBalance -GstKateEnc GstTagSetter -GstKateTag GstTagSetter +VdpSink GstImplementsInterface GstNavigation GstXOverlay +GstApExSink GstImplementsInterface GstMixer +GstCeltEnc GstTagSetter GstPreset +GstCDAudio GstURIHandler +GstMythtvSrc GstURIHandler GstMMS GstURIHandler +GstNeonhttpSrc GstURIHandler GstVCDSrc GstURIHandler GstDataURISrc GstURIHandler -GstMetadataMux GstTagSetter +GstAmrWbEnc GstPreset GstFaac GstPreset -GstAsfMux GstTagSetter +GstXvidEnc GstPreset +GstDiracEnc GstPreset +GstVP8Enc GstTagSetter GstPreset +GstKateEnc GstTagSetter +GstKateTag GstTagSetter +GstJifMux GstTagSetter GstId3BaseMux GstTagSetter GstId3Mux GstTagSetter -GstJifMux GstTagSetter GstQTMux GstTagSetter GstMP4Mux GstTagSetter +GstISMLMux GstTagSetter GstGPPMux GstTagSetter GstMJ2Mux GstTagSetter +GstAsfMux GstTagSetter diff --git a/docs/plugins/gst-plugins-bad-plugins.prerequisites b/docs/plugins/gst-plugins-bad-plugins.prerequisites index e9203c1765..f55006018f 100644 --- a/docs/plugins/gst-plugins-bad-plugins.prerequisites +++ b/docs/plugins/gst-plugins-bad-plugins.prerequisites @@ -1,6 +1,8 @@ GstChildProxy GstObject GstImplementsInterface GstElement -GstColorBalance GstImplementsInterface GstElement +GstXOverlay GstImplementsInterface GstElement GstTagSetter GstElement -GstPhotography GstImplementsInterface GstElement +GstColorBalance GstImplementsInterface GstElement +GstMixer GstImplementsInterface GstElement MXFDescriptiveMetadataFrameworkInterface MXFDescriptiveMetadata +GstPhotography GstImplementsInterface GstElement diff --git a/docs/plugins/inspect/plugin-valve.xml b/docs/plugins/inspect/plugin-valve.xml deleted file mode 100644 index c67f8cc6bb..0000000000 --- a/docs/plugins/inspect/plugin-valve.xml +++ /dev/null @@ -1,34 +0,0 @@ - - valve - Valve - ../../gst/valve/.libs/libgstvalve.so - libgstvalve.so - 0.10.20.1 - LGPL - gst-plugins-bad - GStreamer Bad Plug-ins git - Unknown package origin - - - valve - Valve element - Filter - This element drops all packets when drop is TRUE - Olivier Crete <olivier.crete@collabora.co.uk> - - - sink - sink - always -
ANY
-
- - src - source - always -
ANY
-
-
-
-
-
\ No newline at end of file diff --git a/gst-plugins-bad.spec.in b/gst-plugins-bad.spec.in index 8da39aae5c..02495e1844 100644 --- a/gst-plugins-bad.spec.in +++ b/gst-plugins-bad.spec.in @@ -111,7 +111,6 @@ rm -rf $RPM_BUILD_ROOT %{_libdir}/gstreamer-%{majorminor}/libgstmxf.so %{_libdir}/gstreamer-%{majorminor}/libgstvmnc.so %{_libdir}/gstreamer-%{majorminor}/libgstvideosignal.so -%{_libdir}/gstreamer-%{majorminor}/libgstvalve.so %{_libdir}/gstreamer-%{majorminor}/libgstautoconvert.so %{_libdir}/gstreamer-%{majorminor}/libgstdtmf.so %{_libdir}/gstreamer-%{majorminor}/libgstliveadder.so diff --git a/gst/valve/Makefile.am b/gst/valve/Makefile.am deleted file mode 100644 index 4662a13b5e..0000000000 --- a/gst/valve/Makefile.am +++ /dev/null @@ -1,9 +0,0 @@ -plugin_LTLIBRARIES = libgstvalve.la - -libgstvalve_la_SOURCES = gstvalve.c gstvalve.h - -libgstvalve_la_CFLAGS = $(GST_CFLAGS) -libgstvalve_la_LIBADD = $(GST_LIBS) -libgstvalve_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) -libgstvalve_la_LIBTOOLFLAGS = --tag=disable-static - diff --git a/gst/valve/gstvalve.c b/gst/valve/gstvalve.c deleted file mode 100644 index 977a4afa02..0000000000 --- a/gst/valve/gstvalve.c +++ /dev/null @@ -1,284 +0,0 @@ -/* GStreamer - * Copyright 2007-2009 Collabora Ltd - * @author: Olivier Crete - * Copyright 2007-2009 Nokia Corporation - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -/** - * SECTION:element-valve - * - * The valve is a simple element that drops buffers when the #GstValve::drop - * property is set to %TRUE and lets then through otherwise. - * - * Any downstream error received while the #GstValve::drop property is %FALSE - * is ignored. So downstream element can be set to %GST_STATE_NULL and removed, - * without using pad blocking. - * - * Last reviewed on 2008-02-10 (0.10.11) - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "gstvalve.h" - -#include - -GST_DEBUG_CATEGORY (valve_debug); -#define GST_CAT_DEFAULT (valve_debug) - -static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS_ANY); - -static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", - GST_PAD_SRC, - GST_PAD_ALWAYS, - GST_STATIC_CAPS_ANY); - -/* Valve signals and args */ -enum -{ - /* FILL ME */ - LAST_SIGNAL -}; - -enum -{ - ARG_0, - ARG_DROP, -}; - - - - -static void gst_valve_set_property (GObject * object, - guint prop_id, const GValue * value, GParamSpec * pspec); -static void gst_valve_get_property (GObject * object, - guint prop_id, GValue * value, GParamSpec * pspec); - -static gboolean gst_valve_event (GstPad * pad, GstEvent * event); -static GstFlowReturn gst_valve_buffer_alloc (GstPad * pad, guint64 offset, - guint size, GstCaps * caps, GstBuffer ** buf); -static GstFlowReturn gst_valve_chain (GstPad * pad, GstBuffer * buffer); -static GstCaps *gst_valve_getcaps (GstPad * pad); - -#define _do_init(bla) \ - GST_DEBUG_CATEGORY_INIT (valve_debug, "valve", 0, "Valve"); - -GST_BOILERPLATE_FULL (GstValve, gst_valve, GstElement, - GST_TYPE_ELEMENT, _do_init); - -static void -gst_valve_base_init (gpointer klass) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (klass); - - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&srctemplate)); - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&sinktemplate)); - - gst_element_class_set_details_simple (element_class, "Valve element", - "Filter", - "This element drops all packets when drop is TRUE", - "Olivier Crete "); -} - -static void -gst_valve_class_init (GstValveClass * klass) -{ - GObjectClass *gobject_class; - - gobject_class = (GObjectClass *) klass; - - gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_valve_set_property); - gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_valve_get_property); - - g_object_class_install_property (gobject_class, ARG_DROP, - g_param_spec_boolean ("drop", - "Drops all buffers if TRUE", - "If this property if TRUE, the element will drop all buffers, " - "if its FALSE, it will let them through", - FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); -} - -static void -gst_valve_init (GstValve * valve, GstValveClass * klass) -{ - valve->drop = FALSE; - valve->discont = FALSE; - - valve->srcpad = gst_pad_new_from_static_template (&srctemplate, "src"); - gst_pad_set_getcaps_function (valve->srcpad, - GST_DEBUG_FUNCPTR (gst_valve_getcaps)); - gst_element_add_pad (GST_ELEMENT (valve), valve->srcpad); - - valve->sinkpad = gst_pad_new_from_static_template (&sinktemplate, "sink"); - gst_pad_set_chain_function (valve->sinkpad, - GST_DEBUG_FUNCPTR (gst_valve_chain)); - gst_pad_set_event_function (valve->sinkpad, - GST_DEBUG_FUNCPTR (gst_valve_event)); - gst_pad_set_bufferalloc_function (valve->sinkpad, - GST_DEBUG_FUNCPTR (gst_valve_buffer_alloc)); - gst_pad_set_getcaps_function (valve->sinkpad, - GST_DEBUG_FUNCPTR (gst_valve_getcaps)); - gst_element_add_pad (GST_ELEMENT (valve), valve->sinkpad); -} - - -static void -gst_valve_set_property (GObject * object, - guint prop_id, const GValue * value, GParamSpec * pspec) -{ - GstValve *valve = GST_VALVE (object); - - switch (prop_id) { - case ARG_DROP: - g_atomic_int_set (&valve->drop, g_value_get_boolean (value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_valve_get_property (GObject * object, - guint prop_id, GValue * value, GParamSpec * pspec) -{ - GstValve *valve = GST_VALVE (object); - - switch (prop_id) { - case ARG_DROP: - g_value_set_boolean (value, g_atomic_int_get (&valve->drop)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static GstFlowReturn -gst_valve_chain (GstPad * pad, GstBuffer * buffer) -{ - GstValve *valve = GST_VALVE (GST_OBJECT_PARENT (pad)); - GstFlowReturn ret = GST_FLOW_OK; - - if (g_atomic_int_get (&valve->drop)) { - gst_buffer_unref (buffer); - valve->discont = TRUE; - } else { - if (valve->discont) { - buffer = gst_buffer_make_metadata_writable (buffer); - GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT); - } - - ret = gst_pad_push (valve->srcpad, buffer); - } - - - /* Ignore errors if "drop" was changed while the thread was blocked - * downwards - */ - if (g_atomic_int_get (&valve->drop)) - ret = GST_FLOW_OK; - - return ret; -} - - -static gboolean -gst_valve_event (GstPad * pad, GstEvent * event) -{ - GstValve *valve = GST_VALVE (gst_pad_get_parent_element (pad)); - gboolean ret = TRUE; - - if (g_atomic_int_get (&valve->drop)) - gst_event_unref (event); - else - ret = gst_pad_push_event (valve->srcpad, event); - - /* Ignore errors if "drop" was changed while the thread was blocked - * downwards. - */ - if (g_atomic_int_get (&valve->drop)) - ret = TRUE; - - gst_object_unref (valve); - return ret; -} - -static GstFlowReturn -gst_valve_buffer_alloc (GstPad * pad, guint64 offset, guint size, - GstCaps * caps, GstBuffer ** buf) -{ - GstValve *valve = GST_VALVE (gst_pad_get_parent_element (pad)); - GstFlowReturn ret = GST_FLOW_OK; - - if (g_atomic_int_get (&valve->drop)) - *buf = NULL; - else - ret = gst_pad_alloc_buffer (valve->srcpad, offset, size, caps, buf); - - /* Ignore errors if "drop" was changed while the thread was blocked - * downwards - */ - if (g_atomic_int_get (&valve->drop)) - ret = GST_FLOW_OK; - - gst_object_unref (valve); - - return ret; -} - -static GstCaps * -gst_valve_getcaps (GstPad * pad) -{ - GstValve *valve = GST_VALVE (gst_pad_get_parent (pad)); - GstCaps *caps; - - if (pad == valve->sinkpad) - caps = gst_pad_peer_get_caps (valve->srcpad); - else - caps = gst_pad_peer_get_caps (valve->sinkpad); - - if (caps == NULL) - caps = gst_caps_copy (gst_pad_get_pad_template_caps (pad)); - - gst_object_unref (valve); - - return caps; -} - - -static gboolean -plugin_init (GstPlugin * plugin) -{ - return gst_element_register (plugin, "valve", - GST_RANK_MARGINAL, GST_TYPE_VALVE); -} - -GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, - GST_VERSION_MINOR, - "valve", - "Valve", - plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/gst/valve/gstvalve.h b/gst/valve/gstvalve.h deleted file mode 100644 index 9e15df5712..0000000000 --- a/gst/valve/gstvalve.h +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Farsight Voice+Video library - * - * Copyright 2007 Collabora Ltd, - * Copyright 2007 Nokia Corporation - * @author: Olivier Crete - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - * - */ - -#ifndef __GST_VALVE_H__ -#define __GST_VALVE_H__ - -#include - -G_BEGIN_DECLS -/* #define's don't like whitespacey bits */ -#define GST_TYPE_VALVE \ - (gst_valve_get_type()) -#define GST_VALVE(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj), \ - GST_TYPE_VALVE,GstValve)) -#define GST_VALVE_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass), \ - GST_TYPE_VALVE,GstValveClass)) -#define GST_IS_VALVE(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VALVE)) -#define GST_IS_VALVE_CLASS(obj) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VALVE)) -typedef struct _GstValve GstValve; -typedef struct _GstValveClass GstValveClass; -typedef struct _GstValvePrivate GstValvePrivate; - -/** - * GstValve: - * - * The private valve structure - */ -struct _GstValve -{ - /*< private >*/ - GstElement parent; - - /* atomic boolean */ - volatile gint drop; - - /* Protected by the stream lock */ - gboolean discont; - - GstPad *srcpad; - GstPad *sinkpad; - - /*< private > */ - gpointer _gst_reserved[GST_PADDING]; -}; - -struct _GstValveClass -{ - GstElementClass parent_class; - - /*< private > */ - gpointer _gst_reserved[GST_PADDING]; -}; - -GType gst_valve_get_type (void); - -G_END_DECLS -#endif /* __GST_VALVE_H__ */ diff --git a/tests/check/Makefile.am b/tests/check/Makefile.am index 947513b2bc..45678f384a 100644 --- a/tests/check/Makefile.am +++ b/tests/check/Makefile.am @@ -171,7 +171,6 @@ check_PROGRAMS = \ $(check_mimic) \ elements/rtpmux \ $(check_schro) \ - elements/valve \ $(check_vp8) \ $(check_zbar) \ $(check_orc) \ @@ -235,9 +234,6 @@ elements_kate_LDADD = $(GST_BASE_LIBS) $(LDADD) elements_rtpmux_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(AM_CFLAGS) elements_rtpmux_LDADD = $(GST_BASE_LIBS) $(LDADD) -lgstrtp-0.10 -elements_valve_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(AM_CFLAGS) -elements_valve_LDADD = $(GST_BASE_LIBS) $(LDADD) -lgstrtp-0.10 - elements_assrender_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(AM_CFLAGS) elements_assrender_LDADD = $(GST_BASE_LIBS) $(LDADD) -lgstvideo-0.10 -lgstapp-0.10 diff --git a/tests/check/elements/.gitignore b/tests/check/elements/.gitignore index d9250b84b0..ec35d9b796 100644 --- a/tests/check/elements/.gitignore +++ b/tests/check/elements/.gitignore @@ -38,7 +38,6 @@ selector spectrum timidity y4menc -valve videorecordingbin viewfinderbin vp8dec diff --git a/tests/check/elements/valve.c b/tests/check/elements/valve.c deleted file mode 100644 index d7971bd5a2..0000000000 --- a/tests/check/elements/valve.c +++ /dev/null @@ -1,135 +0,0 @@ -/* GStreamer - * - * unit test for the valve element - * - * Copyright 2009 Collabora Ltd. - * @author: Olivier Crete - * Copyright 2009 Nokia Corp. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include -#include -#include - - -static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS ("audio/x-raw-int")); - -static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", - GST_PAD_SRC, - GST_PAD_ALWAYS, - GST_STATIC_CAPS ("audio/x-raw-int")); - -gboolean event_received = FALSE; -gboolean buffer_allocated = FALSE; - -static gboolean -event_func (GstPad * pad, GstEvent * event) -{ - event_received = TRUE; - gst_event_unref (event); - return TRUE; -} - -static GstFlowReturn -bufferalloc_func (GstPad * pad, guint64 offset, guint size, GstCaps * caps, - GstBuffer ** buf) -{ - buffer_allocated = TRUE; - *buf = gst_buffer_new_and_alloc (size); - GST_BUFFER_OFFSET (*buf) = offset; - gst_buffer_set_caps (*buf, caps); - - return GST_FLOW_OK; -} - -GST_START_TEST (test_valve_basic) -{ - GstElement *valve; - GstPad *sink; - GstPad *src; - GstBuffer *buf; - GstCaps *caps; - - valve = gst_check_setup_element ("valve"); - - sink = gst_check_setup_sink_pad_by_name (valve, &sinktemplate, "src"); - src = gst_check_setup_src_pad_by_name (valve, &srctemplate, "sink"); - gst_pad_set_event_function (sink, event_func); - gst_pad_set_bufferalloc_function (sink, bufferalloc_func); - gst_pad_set_active (src, TRUE); - gst_pad_set_active (sink, TRUE); - gst_element_set_state (valve, GST_STATE_PLAYING); - - g_object_set (valve, "drop", FALSE, NULL); - - fail_unless (gst_pad_push_event (src, gst_event_new_eos ()) == TRUE); - fail_unless (event_received == TRUE); - fail_unless (gst_pad_alloc_buffer (src, 0, 10, NULL, &buf) == GST_FLOW_OK); - fail_unless (buffer_allocated == TRUE); - gst_buffer_unref (buf); - fail_unless (gst_pad_push (src, gst_buffer_new ()) == GST_FLOW_OK); - fail_unless (gst_pad_push (src, gst_buffer_new ()) == GST_FLOW_OK); - fail_unless (g_list_length (buffers) == 2); - caps = gst_pad_get_caps (src); - fail_unless (caps && gst_caps_is_equal (caps, - gst_pad_get_pad_template_caps (src))); - gst_caps_unref (caps); - - gst_check_drop_buffers (); - event_received = buffer_allocated = FALSE; - - g_object_set (valve, "drop", TRUE, NULL); - fail_unless (gst_pad_push_event (src, gst_event_new_eos ()) == TRUE); - fail_unless (event_received == FALSE); - fail_unless (gst_pad_alloc_buffer (src, 0, 10, NULL, &buf) == GST_FLOW_OK); - fail_unless (buffer_allocated == FALSE); - gst_buffer_unref (buf); - fail_unless (gst_pad_push (src, gst_buffer_new ()) == GST_FLOW_OK); - fail_unless (gst_pad_push (src, gst_buffer_new ()) == GST_FLOW_OK); - fail_unless (buffers == NULL); - caps = gst_pad_get_caps (src); - fail_unless (caps && gst_caps_is_equal (caps, - gst_pad_get_pad_template_caps (src))); - gst_caps_unref (caps); - - gst_pad_set_active (src, FALSE); - gst_pad_set_active (sink, FALSE); - gst_check_teardown_src_pad (valve); - gst_check_teardown_sink_pad (valve); - gst_check_teardown_element (valve); -} - -GST_END_TEST; - -static Suite * -valve_suite (void) -{ - Suite *s = suite_create ("valve"); - TCase *tc_chain; - - tc_chain = tcase_create ("valve_basic"); - tcase_add_test (tc_chain, test_valve_basic); - suite_add_tcase (s, tc_chain); - - return s; -} - -GST_CHECK_MAIN (valve) From 44946440a2b67874aed3120a42437d004ffc4064 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Thu, 30 Dec 2010 01:17:28 +0000 Subject: [PATCH 223/448] docs: update plugin docs --- docs/plugins/gst-plugins-bad-plugins.args | 24 +++++----- docs/plugins/inspect/plugin-asfmux.xml | 4 +- .../inspect/plugin-audioparsersbad.xml | 46 +++++++++++++++++- docs/plugins/inspect/plugin-autoconvert.xml | 21 ++++++++ docs/plugins/inspect/plugin-bayer.xml | 2 +- docs/plugins/inspect/plugin-coloreffects.xml | 21 ++++++++ docs/plugins/inspect/plugin-colorspace.xml | 34 +++++++++++++ docs/plugins/inspect/plugin-debugutilsbad.xml | 21 ++++++++ docs/plugins/inspect/plugin-dvbsuboverlay.xml | 40 ++++++++++++++++ .../inspect/plugin-geometrictransform.xml | 21 ++++++++ docs/plugins/inspect/plugin-interlace.xml | 6 +-- docs/plugins/inspect/plugin-jp2kdecimator.xml | 34 +++++++++++++ docs/plugins/inspect/plugin-jpegformat.xml | 8 ++-- docs/plugins/inspect/plugin-kate.xml | 4 +- docs/plugins/inspect/plugin-opencv.xml | 48 +++++++++---------- docs/plugins/inspect/plugin-qtmux.xml | 27 +++++++++++ docs/plugins/inspect/plugin-rsvg.xml | 27 +++++++++++ docs/plugins/inspect/plugin-videomeasure.xml | 2 +- docs/plugins/inspect/plugin-y4mdec.xml | 34 +++++++++++++ docs/plugins/inspect/plugin-zbar.xml | 4 +- 20 files changed, 375 insertions(+), 53 deletions(-) create mode 100644 docs/plugins/inspect/plugin-colorspace.xml create mode 100644 docs/plugins/inspect/plugin-dvbsuboverlay.xml create mode 100644 docs/plugins/inspect/plugin-jp2kdecimator.xml create mode 100644 docs/plugins/inspect/plugin-y4mdec.xml diff --git a/docs/plugins/gst-plugins-bad-plugins.args b/docs/plugins/gst-plugins-bad-plugins.args index 73c886cbbb..d54b586ad2 100644 --- a/docs/plugins/gst-plugins-bad-plugins.args +++ b/docs/plugins/gst-plugins-bad-plugins.args @@ -26590,7 +26590,7 @@ rw physics water density: from 1 to 4. -0 +7.75038e-304
@@ -26630,7 +26630,7 @@ rw splash make a big splash in the center. -7.7486e-304 +0 @@ -26640,7 +26640,7 @@ rw splash make a big splash in the center. -0 +4.77773e-299 @@ -26670,7 +26670,7 @@ rw ratiox x-ratio. -8.55111e-317 +0 @@ -26680,7 +26680,7 @@ rw ratioy y-ratio. -2.28459e-26 +0 @@ -26740,7 +26740,7 @@ rw Color-R the color of the image. -2.49965e-38 +0 @@ -27070,7 +27070,7 @@ rw lredscale multiplier for downscaling non-edge brightness. -3.40216e-111 +0 @@ -27080,7 +27080,7 @@ rw lthresh threshold for edge lightening. -6.9235e+228 +0 @@ -27090,7 +27090,7 @@ rw lupscale multiplier for upscaling edge brightness. -7.54985e-96 +0 @@ -27260,7 +27260,7 @@ rw blend blend factor. --5.83169e+303 +4.74303e-322 @@ -27270,7 +27270,7 @@ rw fader the fader position. -1.20296e-314 +7.7486e-304 @@ -27450,7 +27450,7 @@ rw HSync the hsync offset. -2.98023e-08 +0 diff --git a/docs/plugins/inspect/plugin-asfmux.xml b/docs/plugins/inspect/plugin-asfmux.xml index 6369c80d28..1e68b3fd93 100644 --- a/docs/plugins/inspect/plugin-asfmux.xml +++ b/docs/plugins/inspect/plugin-asfmux.xml @@ -6,8 +6,8 @@ 0.10.20.1 LGPL gst-plugins-bad - gsoc2009 package - embedded.ufcg.edu.br + GStreamer Bad Plug-ins git + Unknown package origin asfmux diff --git a/docs/plugins/inspect/plugin-audioparsersbad.xml b/docs/plugins/inspect/plugin-audioparsersbad.xml index dd9373154d..f308eaf6b9 100644 --- a/docs/plugins/inspect/plugin-audioparsersbad.xml +++ b/docs/plugins/inspect/plugin-audioparsersbad.xml @@ -41,13 +41,13 @@ sink sink always -
audio/x-ac3, framed=(boolean)false; audio/ac3, framed=(boolean)false
+
audio/x-ac3, framed=(boolean)false; audio/x-eac3, framed=(boolean)false; audio/ac3, framed=(boolean)false
src source always -
audio/x-ac3, framed=(boolean)true, channels=(int)[ 1, 6 ], rate=(int)[ 32000, 48000 ]; audio/ac3, framed=(boolean)true, channels=(int)[ 1, 6 ], rate=(int)[ 32000, 48000 ]
+
audio/x-ac3, framed=(boolean)true, channels=(int)[ 1, 6 ], rate=(int)[ 32000, 48000 ]; audio/x-eac3, framed=(boolean)true, channels=(int)[ 1, 6 ], rate=(int)[ 32000, 48000 ]
@@ -72,6 +72,27 @@ + + dcaparse + DTS Coherent Acoustics audio stream parser + Codec/Parser/Audio + DCA parser + Tim-Philipp Müller <tim centricular net> + + + sink + sink + always +
audio/x-dts, framed=(boolean)false
+
+ + src + source + always +
audio/x-dts, framed=(boolean)true, channels=(int)[ 1, 8 ], rate=(int)[ 8000, 192000 ]
+
+
+
flacparse FLAC audio parser @@ -93,5 +114,26 @@ + + mpegaudioparse + MPEG1 Audio Parser + Codec/Parser/Audio + Parses and frames mpeg1 audio streams (levels 1-3), provides seek + Jan Schmidt <thaytan@mad.scientist.com>,Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk> + + + sink + sink + always +
audio/mpeg, mpegversion=(int)1, parsed=(boolean)false
+
+ + src + source + always +
audio/mpeg, mpegversion=(int)1, layer=(int)[ 1, 3 ], rate=(int)[ 8000, 48000 ], channels=(int)[ 1, 2 ], parsed=(boolean)true
+
+
+
\ No newline at end of file diff --git a/docs/plugins/inspect/plugin-autoconvert.xml b/docs/plugins/inspect/plugin-autoconvert.xml index ad4ff9bcbd..a0244845a6 100644 --- a/docs/plugins/inspect/plugin-autoconvert.xml +++ b/docs/plugins/inspect/plugin-autoconvert.xml @@ -30,5 +30,26 @@ + + autovideoconvert + Select color space convertor based on caps + Generic/Bin + Selects the right color space convertor based on the caps + Benjamin Gaignard <benjamin.gaignard@stericsson.com> + + + sink + sink + always +
ANY
+
+ + src + source + always +
ANY
+
+
+
\ No newline at end of file diff --git a/docs/plugins/inspect/plugin-bayer.xml b/docs/plugins/inspect/plugin-bayer.xml index 597f9585db..fb6292bb34 100644 --- a/docs/plugins/inspect/plugin-bayer.xml +++ b/docs/plugins/inspect/plugin-bayer.xml @@ -20,7 +20,7 @@ sink sink always -
video/x-raw-bayer, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ]
+
video/x-raw-bayer, format=(string){ bggr, grbg, gbrg, rggb }, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]
src diff --git a/docs/plugins/inspect/plugin-coloreffects.xml b/docs/plugins/inspect/plugin-coloreffects.xml index 39760d45ab..3f5b92b35e 100644 --- a/docs/plugins/inspect/plugin-coloreffects.xml +++ b/docs/plugins/inspect/plugin-coloreffects.xml @@ -9,6 +9,27 @@ GStreamer Bad Plug-ins git Unknown package origin + + chromahold + Chroma hold filter + Filter/Effect/Video + Removes all color information except for one color + Sebastian Dröge <sebastian.droege@collabora.co.uk> + + + sink + sink + always +
video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, alpha_mask=(int)-16777216, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)65280, green_mask=(int)16711680, blue_mask=(int)-16777216, alpha_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)255, green_mask=(int)65280, blue_mask=(int)16711680, alpha_mask=(int)-16777216, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)-16777216, green_mask=(int)16711680, blue_mask=(int)65280, alpha_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)65280, green_mask=(int)16711680, blue_mask=(int)-16777216, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)255, green_mask=(int)65280, blue_mask=(int)16711680, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)-16777216, green_mask=(int)16711680, blue_mask=(int)65280, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]
+
+ + src + source + always +
video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, alpha_mask=(int)-16777216, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)65280, green_mask=(int)16711680, blue_mask=(int)-16777216, alpha_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)255, green_mask=(int)65280, blue_mask=(int)16711680, alpha_mask=(int)-16777216, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)-16777216, green_mask=(int)16711680, blue_mask=(int)65280, alpha_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)65280, green_mask=(int)16711680, blue_mask=(int)-16777216, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)255, green_mask=(int)65280, blue_mask=(int)16711680, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)-16777216, green_mask=(int)16711680, blue_mask=(int)65280, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]
+
+
+
coloreffects Color Look-up Table filter diff --git a/docs/plugins/inspect/plugin-colorspace.xml b/docs/plugins/inspect/plugin-colorspace.xml new file mode 100644 index 0000000000..b0b3602d97 --- /dev/null +++ b/docs/plugins/inspect/plugin-colorspace.xml @@ -0,0 +1,34 @@ + + colorspace + Colorspace conversion + ../../gst/colorspace/.libs/libgstcolorspace.so + libgstcolorspace.so + 0.10.20.1 + LGPL + gst-plugins-bad + + + + + colorspace + Colorspace converter + Filter/Converter/Video + Converts video from one colorspace to another + GStreamer maintainers <gstreamer-devel@lists.sourceforge.net> + + + sink + sink + always +
video/x-raw-yuv, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ], format=(fourcc){ I420, NV12, NV21, YV12, YUY2, Y42B, Y444, YUV9, YVU9, Y41B, Y800, Y8 , GREY, Y16 , UYVY, YVYU, IYU1, v308, AYUV, v210, A420 }; video/x-raw-rgb, bpp=(int)24, depth=(int)24, endianness=(int)4321, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)24, depth=(int)24, endianness=(int)4321, red_mask=(int)255, green_mask=(int)65280, blue_mask=(int)16711680, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)-16777216, green_mask=(int)16711680, blue_mask=(int)65280, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)65280, green_mask=(int)16711680, blue_mask=(int)-16777216, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)255, green_mask=(int)65280, blue_mask=(int)16711680, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)-16777216, green_mask=(int)16711680, blue_mask=(int)65280, alpha_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, alpha_mask=(int)-16777216, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)65280, green_mask=(int)16711680, blue_mask=(int)-16777216, alpha_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)255, green_mask=(int)65280, blue_mask=(int)16711680, alpha_mask=(int)-16777216, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)16, depth=(int)16, endianness=(int)1234, red_mask=(int)63488, green_mask=(int)2016, blue_mask=(int)31, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)16, depth=(int)16, endianness=(int)1234, red_mask=(int)31, green_mask=(int)2016, blue_mask=(int)63488, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)16, depth=(int)15, endianness=(int)1234, red_mask=(int)31744, green_mask=(int)992, blue_mask=(int)31, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)16, depth=(int)15, endianness=(int)1234, red_mask=(int)31, green_mask=(int)992, blue_mask=(int)31744, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)8, depth=(int)8, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-gray, bpp=(int)8, depth=(int)8, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-gray, bpp=(int)16, depth=(int)16, endianness=(int)4321, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-gray, bpp=(int)16, depth=(int)16, endianness=(int)1234, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]
+
+ + src + source + always +
video/x-raw-yuv, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ], format=(fourcc){ I420, NV12, NV21, YV12, YUY2, Y42B, Y444, YUV9, YVU9, Y41B, Y800, Y8 , GREY, Y16 , UYVY, YVYU, IYU1, v308, AYUV, v210, A420 }; video/x-raw-rgb, bpp=(int)24, depth=(int)24, endianness=(int)4321, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)24, depth=(int)24, endianness=(int)4321, red_mask=(int)255, green_mask=(int)65280, blue_mask=(int)16711680, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)-16777216, green_mask=(int)16711680, blue_mask=(int)65280, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)65280, green_mask=(int)16711680, blue_mask=(int)-16777216, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)255, green_mask=(int)65280, blue_mask=(int)16711680, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)-16777216, green_mask=(int)16711680, blue_mask=(int)65280, alpha_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, alpha_mask=(int)-16777216, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)65280, green_mask=(int)16711680, blue_mask=(int)-16777216, alpha_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)255, green_mask=(int)65280, blue_mask=(int)16711680, alpha_mask=(int)-16777216, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)16, depth=(int)16, endianness=(int)1234, red_mask=(int)63488, green_mask=(int)2016, blue_mask=(int)31, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)16, depth=(int)16, endianness=(int)1234, red_mask=(int)31, green_mask=(int)2016, blue_mask=(int)63488, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)16, depth=(int)15, endianness=(int)1234, red_mask=(int)31744, green_mask=(int)992, blue_mask=(int)31, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)16, depth=(int)15, endianness=(int)1234, red_mask=(int)31, green_mask=(int)992, blue_mask=(int)31744, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)8, depth=(int)8, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-gray, bpp=(int)8, depth=(int)8, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-gray, bpp=(int)16, depth=(int)16, endianness=(int)4321, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-gray, bpp=(int)16, depth=(int)16, endianness=(int)1234, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]
+
+
+
+
+
\ No newline at end of file diff --git a/docs/plugins/inspect/plugin-debugutilsbad.xml b/docs/plugins/inspect/plugin-debugutilsbad.xml index 70f7ffdedb..4ddb78e618 100644 --- a/docs/plugins/inspect/plugin-debugutilsbad.xml +++ b/docs/plugins/inspect/plugin-debugutilsbad.xml @@ -30,6 +30,27 @@
+ + chopmydata + FIXME + Generic + FIXME + David Schleef <ds@schleef.org> + + + sink + sink + always +
ANY
+
+ + src + source + always +
ANY
+
+
+
fpsdisplaysink Measure and show framerate on videosink diff --git a/docs/plugins/inspect/plugin-dvbsuboverlay.xml b/docs/plugins/inspect/plugin-dvbsuboverlay.xml new file mode 100644 index 0000000000..f8f2afd6f4 --- /dev/null +++ b/docs/plugins/inspect/plugin-dvbsuboverlay.xml @@ -0,0 +1,40 @@ + + dvbsuboverlay + DVB subtitle renderer + ../../gst/dvbsuboverlay/.libs/libgstdvbsuboverlay.so + libgstdvbsuboverlay.so + 0.10.20.1 + LGPL + gst-plugins-bad + GStreamer Bad Plug-ins git + Unknown package origin + + + dvbsuboverlay + DVB Subtitles Overlay + Mixer/Video/Overlay/Subtitle + Renders DVB subtitles + Mart Raudsepp <mart.raudsepp@collabora.co.uk> + + + text_sink + sink + always +
subpicture/x-dvb
+
+ + video_sink + sink + always +
video/x-raw-yuv, format=(fourcc)I420, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]
+
+ + src + source + always +
video/x-raw-yuv, format=(fourcc)I420, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]
+
+
+
+
+
\ No newline at end of file diff --git a/docs/plugins/inspect/plugin-geometrictransform.xml b/docs/plugins/inspect/plugin-geometrictransform.xml index 440d2366bb..1e4c78819c 100644 --- a/docs/plugins/inspect/plugin-geometrictransform.xml +++ b/docs/plugins/inspect/plugin-geometrictransform.xml @@ -177,6 +177,27 @@
+ + rotate + rotate + Transform/Effect/Video + Warps the picture into an arc shaped form + Thiago Santos<thiago.sousa.santos@collabora.co.uk> + + + sink + sink + always +
video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)255, green_mask=(int)65280, blue_mask=(int)16711680, alpha_mask=(int)-16777216, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, alpha_mask=(int)-16777216, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)24, depth=(int)24, endianness=(int)4321, red_mask=(int)255, green_mask=(int)65280, blue_mask=(int)16711680, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)65280, green_mask=(int)16711680, blue_mask=(int)-16777216, alpha_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)65280, green_mask=(int)16711680, blue_mask=(int)-16777216, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)24, depth=(int)24, endianness=(int)4321, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)-16777216, green_mask=(int)16711680, blue_mask=(int)65280, alpha_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)-16777216, green_mask=(int)16711680, blue_mask=(int)65280, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)AYUV, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)255, green_mask=(int)65280, blue_mask=(int)16711680, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-gray, bpp=(int)8, depth=(int)8, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-gray, bpp=(int)16, depth=(int)16, endianness=(int)4321, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-gray, bpp=(int)16, depth=(int)16, endianness=(int)1234, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]
+
+ + src + source + always +
video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)255, green_mask=(int)65280, blue_mask=(int)16711680, alpha_mask=(int)-16777216, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, alpha_mask=(int)-16777216, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)24, depth=(int)24, endianness=(int)4321, red_mask=(int)255, green_mask=(int)65280, blue_mask=(int)16711680, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)65280, green_mask=(int)16711680, blue_mask=(int)-16777216, alpha_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)65280, green_mask=(int)16711680, blue_mask=(int)-16777216, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)24, depth=(int)24, endianness=(int)4321, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)-16777216, green_mask=(int)16711680, blue_mask=(int)65280, alpha_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)-16777216, green_mask=(int)16711680, blue_mask=(int)65280, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)AYUV, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)255, green_mask=(int)65280, blue_mask=(int)16711680, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-gray, bpp=(int)8, depth=(int)8, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-gray, bpp=(int)16, depth=(int)16, endianness=(int)4321, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-gray, bpp=(int)16, depth=(int)16, endianness=(int)1234, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]
+
+
+
sphere sphere diff --git a/docs/plugins/inspect/plugin-interlace.xml b/docs/plugins/inspect/plugin-interlace.xml index f0858231e4..1691edda69 100644 --- a/docs/plugins/inspect/plugin-interlace.xml +++ b/docs/plugins/inspect/plugin-interlace.xml @@ -11,10 +11,10 @@ interlace - Inverse Telecine filter + Interlace filter Filter/Video - Detects and reconstructs progressive content from telecine video - Entropy Wave <ds@entropywave.com> + Creates an interlaced video from progressive frames + David Schleef <ds@schleef.org> sink diff --git a/docs/plugins/inspect/plugin-jp2kdecimator.xml b/docs/plugins/inspect/plugin-jp2kdecimator.xml new file mode 100644 index 0000000000..4a44f21113 --- /dev/null +++ b/docs/plugins/inspect/plugin-jp2kdecimator.xml @@ -0,0 +1,34 @@ + + jp2kdecimator + JPEG2000 decimator + ../../gst/jp2kdecimator/.libs/libgstjp2kdecimator.so + libgstjp2kdecimator.so + 0.10.20.1 + LGPL + gst-plugins-bad + GStreamer Bad Plug-ins git + Unknown package origin + + + jp2kdecimator + JPEG2000 decimator + Filter/Image + Removes information from JPEG2000 streams without recompression + Sebastian Dröge <sebastian.droege@collabora.co.uk> + + + sink + sink + always +
image/x-jpc
+
+ + src + source + always +
image/x-jpc
+
+
+
+
+
\ No newline at end of file diff --git a/docs/plugins/inspect/plugin-jpegformat.xml b/docs/plugins/inspect/plugin-jpegformat.xml index 2e770a2bf3..2b5be56125 100644 --- a/docs/plugins/inspect/plugin-jpegformat.xml +++ b/docs/plugins/inspect/plugin-jpegformat.xml @@ -11,9 +11,9 @@ jifmux - JPEG stream parser - Codec/Parser/Video - Parse JPEG images into single-frame buffers + JPEG stream muxer + Video/Muxer + Remuxes JPEG images with markers and tags Arnout Vandecappelle (Essensium/Mind) <arnout@mind.be> @@ -33,7 +33,7 @@ jpegparse JPEG stream parser - Codec/Parser/Video + Video/Parser Parse JPEG images into single-frame buffers Arnout Vandecappelle (Essensium/Mind) <arnout@mind.be> diff --git a/docs/plugins/inspect/plugin-kate.xml b/docs/plugins/inspect/plugin-kate.xml index 0cd8729d3c..cf0d0670f1 100644 --- a/docs/plugins/inspect/plugin-kate.xml +++ b/docs/plugins/inspect/plugin-kate.xml @@ -110,13 +110,13 @@ video_sink sink always -
video/x-raw-rgb, bpp=(int)32, depth=(int)24
+
video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)1234, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)65280, green_mask=(int)16711680, blue_mask=(int)-16777216, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]
src source always -
video/x-raw-rgb, bpp=(int)32, depth=(int)24
+
video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)1234, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)65280, green_mask=(int)16711680, blue_mask=(int)-16777216, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]
diff --git a/docs/plugins/inspect/plugin-opencv.xml b/docs/plugins/inspect/plugin-opencv.xml index cecc91d8b0..1cb9888a57 100644 --- a/docs/plugins/inspect/plugin-opencv.xml +++ b/docs/plugins/inspect/plugin-opencv.xml @@ -6,8 +6,8 @@ 0.10.20.1 LGPL gst-plugins-bad - OpenCv - http://opencv.willowgarage.com + GStreamer Bad Plug-ins git + Unknown package origin cvdilate @@ -20,13 +20,13 @@ sink sink always -
video/x-raw-rgb, depth=(int)24, bpp=(int)24; video/x-raw-gray
+
video/x-raw-gray, bpp=(int)16, depth=(int)16, endianness=(int)1234, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-gray, bpp=(int)16, depth=(int)16, endianness=(int)4321, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)-16777216, green_mask=(int)16711680, blue_mask=(int)65280, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)65280, green_mask=(int)16711680, blue_mask=(int)-16777216, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)255, green_mask=(int)65280, blue_mask=(int)16711680, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)-16777216, green_mask=(int)16711680, blue_mask=(int)65280, alpha_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, alpha_mask=(int)-16777216, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)65280, green_mask=(int)16711680, blue_mask=(int)-16777216, alpha_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)255, green_mask=(int)65280, blue_mask=(int)16711680, alpha_mask=(int)-16777216, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)24, depth=(int)24, endianness=(int)4321, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)24, depth=(int)24, endianness=(int)4321, red_mask=(int)255, green_mask=(int)65280, blue_mask=(int)16711680, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-gray, bpp=(int)8, depth=(int)8, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]
src source always -
video/x-raw-rgb, depth=(int)24, bpp=(int)24; video/x-raw-gray
+
video/x-raw-gray, bpp=(int)16, depth=(int)16, endianness=(int)1234, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-gray, bpp=(int)16, depth=(int)16, endianness=(int)4321, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)-16777216, green_mask=(int)16711680, blue_mask=(int)65280, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)65280, green_mask=(int)16711680, blue_mask=(int)-16777216, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)255, green_mask=(int)65280, blue_mask=(int)16711680, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)-16777216, green_mask=(int)16711680, blue_mask=(int)65280, alpha_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, alpha_mask=(int)-16777216, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)65280, green_mask=(int)16711680, blue_mask=(int)-16777216, alpha_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)255, green_mask=(int)65280, blue_mask=(int)16711680, alpha_mask=(int)-16777216, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)24, depth=(int)24, endianness=(int)4321, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)24, depth=(int)24, endianness=(int)4321, red_mask=(int)255, green_mask=(int)65280, blue_mask=(int)16711680, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-gray, bpp=(int)8, depth=(int)8, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]
@@ -41,13 +41,13 @@ sink sink always -
video/x-raw-gray, depth=(int)8, bpp=(int)8
+
video/x-raw-gray, bpp=(int)8, depth=(int)8, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]
src source always -
video/x-raw-gray, depth=(int)8, bpp=(int)8
+
video/x-raw-gray, bpp=(int)8, depth=(int)8, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]
@@ -62,13 +62,13 @@ sink sink always -
video/x-raw-rgb, depth=(int)24, bpp=(int)24; video/x-raw-gray
+
video/x-raw-gray, bpp=(int)16, depth=(int)16, endianness=(int)1234, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-gray, bpp=(int)16, depth=(int)16, endianness=(int)4321, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)-16777216, green_mask=(int)16711680, blue_mask=(int)65280, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)65280, green_mask=(int)16711680, blue_mask=(int)-16777216, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)255, green_mask=(int)65280, blue_mask=(int)16711680, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)-16777216, green_mask=(int)16711680, blue_mask=(int)65280, alpha_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, alpha_mask=(int)-16777216, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)65280, green_mask=(int)16711680, blue_mask=(int)-16777216, alpha_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)255, green_mask=(int)65280, blue_mask=(int)16711680, alpha_mask=(int)-16777216, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)24, depth=(int)24, endianness=(int)4321, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)24, depth=(int)24, endianness=(int)4321, red_mask=(int)255, green_mask=(int)65280, blue_mask=(int)16711680, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-gray, bpp=(int)8, depth=(int)8, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]
src source always -
video/x-raw-rgb, depth=(int)24, bpp=(int)24; video/x-raw-gray
+
video/x-raw-gray, bpp=(int)16, depth=(int)16, endianness=(int)1234, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-gray, bpp=(int)16, depth=(int)16, endianness=(int)4321, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)-16777216, green_mask=(int)16711680, blue_mask=(int)65280, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)65280, green_mask=(int)16711680, blue_mask=(int)-16777216, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)24, endianness=(int)4321, red_mask=(int)255, green_mask=(int)65280, blue_mask=(int)16711680, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)-16777216, green_mask=(int)16711680, blue_mask=(int)65280, alpha_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, alpha_mask=(int)-16777216, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)65280, green_mask=(int)16711680, blue_mask=(int)-16777216, alpha_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)255, green_mask=(int)65280, blue_mask=(int)16711680, alpha_mask=(int)-16777216, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)24, depth=(int)24, endianness=(int)4321, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)24, depth=(int)24, endianness=(int)4321, red_mask=(int)255, green_mask=(int)65280, blue_mask=(int)16711680, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-gray, bpp=(int)8, depth=(int)8, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]
@@ -83,13 +83,13 @@ sink sink always -
video/x-raw-gray, depth=(int)8, bpp=(int)8
+
video/x-raw-gray, bpp=(int)8, depth=(int)8, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]
src source always -
video/x-raw-gray, depth=(int)16, bpp=(int)16, endianness=(int)4321
+
video/x-raw-gray, bpp=(int)16, depth=(int)16, endianness=(int)1234, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]
@@ -104,13 +104,13 @@ sink sink always -
video/x-raw-rgb, depth=(int)24, bpp=(int)24; video/x-raw-gray, depth=(int)8, bpp=(int)8
+
video/x-raw-rgb, bpp=(int)24, depth=(int)24, endianness=(int)4321, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)24, depth=(int)24, endianness=(int)4321, red_mask=(int)255, green_mask=(int)65280, blue_mask=(int)16711680, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-gray, bpp=(int)8, depth=(int)8, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]
src source always -
video/x-raw-rgb, depth=(int)24, bpp=(int)24; video/x-raw-gray, depth=(int)8, bpp=(int)8
+
video/x-raw-rgb, bpp=(int)24, depth=(int)24, endianness=(int)4321, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-rgb, bpp=(int)24, depth=(int)24, endianness=(int)4321, red_mask=(int)255, green_mask=(int)65280, blue_mask=(int)16711680, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-gray, bpp=(int)8, depth=(int)8, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]
@@ -125,13 +125,13 @@ sink sink always -
video/x-raw-gray, depth=(int)8, bpp=(int)8
+
video/x-raw-gray, bpp=(int)8, depth=(int)8, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]
src source always -
video/x-raw-gray, depth=(int)16, bpp=(int)16, endianness=(int)4321
+
video/x-raw-gray, bpp=(int)16, depth=(int)16, endianness=(int)1234, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]
@@ -146,13 +146,13 @@ sink sink always -
video/x-raw-rgb
+
video/x-raw-rgb, bpp=(int)24, depth=(int)24, endianness=(int)4321, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]
src source always -
video/x-raw-rgb
+
video/x-raw-rgb, bpp=(int)24, depth=(int)24, endianness=(int)4321, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]
@@ -167,13 +167,13 @@ sink sink always -
video/x-raw-rgb
+
video/x-raw-rgb, bpp=(int)24, depth=(int)24, endianness=(int)4321, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]
src source always -
video/x-raw-rgb
+
video/x-raw-rgb, bpp=(int)24, depth=(int)24, endianness=(int)4321, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]
@@ -209,13 +209,13 @@ sink sink always -
video/x-raw-rgb
+
video/x-raw-rgb, bpp=(int)24, depth=(int)24, endianness=(int)4321, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]
src source always -
video/x-raw-rgb
+
video/x-raw-rgb, bpp=(int)24, depth=(int)24, endianness=(int)4321, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]
@@ -230,13 +230,13 @@ sink sink always -
video/x-raw-rgb
+
video/x-raw-rgb, bpp=(int)24, depth=(int)24, endianness=(int)4321, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]
src source always -
video/x-raw-rgb
+
video/x-raw-rgb, bpp=(int)24, depth=(int)24, endianness=(int)4321, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]
@@ -251,13 +251,13 @@ sink sink always -
video/x-raw-rgb
+
video/x-raw-rgb, bpp=(int)24, depth=(int)24, endianness=(int)4321, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]
src source always -
ANY
+
video/x-raw-rgb, bpp=(int)24, depth=(int)24, endianness=(int)4321, red_mask=(int)16711680, green_mask=(int)65280, blue_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]
diff --git a/docs/plugins/inspect/plugin-qtmux.xml b/docs/plugins/inspect/plugin-qtmux.xml index df9d6ed279..286d8e0e0c 100644 --- a/docs/plugins/inspect/plugin-qtmux.xml +++ b/docs/plugins/inspect/plugin-qtmux.xml @@ -36,6 +36,33 @@ + + ismlmux + ISML Muxer + Codec/Muxer + Multiplex audio and video into a ISML file + Thiago Sousa Santos <thiagoss@embedded.ufcg.edu.br> + + + audio_%d + sink + request +
audio/mpeg, mpegversion=(int)1, layer=(int)3, channels=(int)[ 1, 2 ], rate=(int)[ 1, 2147483647 ]; audio/mpeg, mpegversion=(int)4, stream-format=(string)raw, channels=(int)[ 1, 8 ], rate=(int)[ 1, 2147483647 ]
+
+ + video_%d + sink + request +
video/mpeg, mpegversion=(int)4, systemstream=(boolean)false, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-divx, divxversion=(int)5, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-h264, stream-format=(string)avc, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(fraction)[ 0/1, 2147483647/1 ]
+
+ + src + source + always +
video/quicktime, variant=(string)iso
+
+
+
mj2mux MJ2 Muxer diff --git a/docs/plugins/inspect/plugin-rsvg.xml b/docs/plugins/inspect/plugin-rsvg.xml index 3891783179..17ff3078b6 100644 --- a/docs/plugins/inspect/plugin-rsvg.xml +++ b/docs/plugins/inspect/plugin-rsvg.xml @@ -30,5 +30,32 @@ + + rsvgoverlay + RSVG overlay + Filter/Editor/Video + Overlays SVG graphics over a video stream + Olivier Aubert <olivier.aubert@liris.cnrs.fr> + + + data_sink + sink + always +
image/svg+xml; image/svg; text/plain
+
+ + sink + sink + always +
video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)65280, green_mask=(int)16711680, blue_mask=(int)-16777216, alpha_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]
+
+ + src + source + always +
video/x-raw-rgb, bpp=(int)32, depth=(int)32, endianness=(int)4321, red_mask=(int)65280, green_mask=(int)16711680, blue_mask=(int)-16777216, alpha_mask=(int)255, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]
+
+
+
\ No newline at end of file diff --git a/docs/plugins/inspect/plugin-videomeasure.xml b/docs/plugins/inspect/plugin-videomeasure.xml index 5efca8aa70..0d8bacab1d 100644 --- a/docs/plugins/inspect/plugin-videomeasure.xml +++ b/docs/plugins/inspect/plugin-videomeasure.xml @@ -33,7 +33,7 @@ ssim SSim - Filter/Converter/Video + Filter/Analyzer/Video Calculate Y-SSIM for n+2 YUV video streams Руслан Ижбулатов <lrn1986 _at_ gmail _dot_ com> diff --git a/docs/plugins/inspect/plugin-y4mdec.xml b/docs/plugins/inspect/plugin-y4mdec.xml new file mode 100644 index 0000000000..8f3d50fa03 --- /dev/null +++ b/docs/plugins/inspect/plugin-y4mdec.xml @@ -0,0 +1,34 @@ + + y4mdec + FIXME + ../../gst/y4m/.libs/libgsty4mdec.so + libgsty4mdec.so + 0.10.20.1 + LGPL + gst-plugins-bad + GStreamer Bad Plug-ins + Unknown package origin + + + y4mdec + YUV4MPEG demuxer/decoder + Codec/Demuxer + Demuxes/decodes YUV4MPEG streams + David Schleef <ds@schleef.org> + + + sink + sink + always +
application/x-yuv4mpeg, y4mversion=(int)2
+
+ + src + source + always +
video/x-raw-yuv, format=(fourcc){ I420, Y42B, Y444 }, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]
+
+
+
+
+
\ No newline at end of file diff --git a/docs/plugins/inspect/plugin-zbar.xml b/docs/plugins/inspect/plugin-zbar.xml index b330883139..232802a3f7 100644 --- a/docs/plugins/inspect/plugin-zbar.xml +++ b/docs/plugins/inspect/plugin-zbar.xml @@ -20,13 +20,13 @@ sink sink always -
video/x-raw-yuv, format=(fourcc){ Y800 }, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]
+
video/x-raw-yuv, format=(fourcc){ Y800, I420, YV12, NV12, NV21, Y41B, Y42B }, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]
src source always -
video/x-raw-yuv, format=(fourcc){ Y800 }, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]
+
video/x-raw-yuv, format=(fourcc){ Y800, I420, YV12, NV12, NV21, Y41B, Y42B }, width=(int)[ 1, 2147483647 ], height=(int)[ 1, 2147483647 ], framerate=(fraction)[ 0/1, 2147483647/1 ]
From c6c3d9781befc7a7056e7d9befdf8cd5b5254c76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Fri, 31 Dec 2010 01:38:02 +0000 Subject: [PATCH 224/448] selector: move input-selector and output-selector to core https://bugzilla.gnome.org/show_bug.cgi?id=614306 --- Makefile.am | 6 + configure.ac | 3 - docs/plugins/Makefile.am | 2 - .../plugins/gst-plugins-bad-plugins-docs.sgml | 3 - .../gst-plugins-bad-plugins-sections.txt | 34 - docs/plugins/gst-plugins-bad-plugins.args | 200 --- .../plugins/gst-plugins-bad-plugins.hierarchy | 2 - docs/plugins/inspect/plugin-selector.xml | 55 - gst-plugins-bad.spec.in | 1 - gst/selector/.gitignore | 2 - gst/selector/Makefile.am | 24 - gst/selector/gstinputselector.c | 1430 ----------------- gst/selector/gstinputselector.h | 84 - gst/selector/gstoutputselector.c | 519 ------ gst/selector/gstoutputselector.h | 66 - gst/selector/gstselector-marshal.list | 2 - gst/selector/gstselector.c | 44 - gst/selector/selector.vcproj | 148 -- tests/check/Makefile.am | 1 - tests/check/elements/.gitignore | 1 - tests/check/elements/selector.c | 385 ----- tests/examples/Makefile.am | 6 +- tests/examples/switch/.gitignore | 1 - tests/examples/switch/Makefile.am | 7 - tests/examples/switch/switcher.c | 162 -- tests/icles/.gitignore | 1 - tests/icles/Makefile.am | 8 +- tests/icles/output-selector-test.c | 173 -- 28 files changed, 11 insertions(+), 3359 deletions(-) delete mode 100644 docs/plugins/inspect/plugin-selector.xml delete mode 100644 gst/selector/.gitignore delete mode 100644 gst/selector/Makefile.am delete mode 100644 gst/selector/gstinputselector.c delete mode 100644 gst/selector/gstinputselector.h delete mode 100644 gst/selector/gstoutputselector.c delete mode 100644 gst/selector/gstoutputselector.h delete mode 100644 gst/selector/gstselector-marshal.list delete mode 100644 gst/selector/gstselector.c delete mode 100644 gst/selector/selector.vcproj delete mode 100644 tests/check/elements/selector.c delete mode 100644 tests/examples/switch/.gitignore delete mode 100644 tests/examples/switch/Makefile.am delete mode 100644 tests/examples/switch/switcher.c delete mode 100644 tests/icles/output-selector-test.c diff --git a/Makefile.am b/Makefile.am index dad96866f2..402b8b9575 100644 --- a/Makefile.am +++ b/Makefile.am @@ -50,14 +50,18 @@ CRUFT_FILES = \ $(top_builddir)/gst/amrparse/.libs/*.{so,dll,DLL,dylib} \ $(top_builddir)/gst/flacparse/.libs/*.{so,dll,DLL,dylib} \ $(top_builddir)/gst/imagefreeze/.libs/*.{so,dll,DLL,dylib} \ + $(top_builddir)/gst/selector/.libs/*.{so,dll,DLL,dylib} \ $(top_builddir)/gst/shapewipe/.libs/*.{so,dll,DLL,dylib} \ $(top_builddir)/gst/valve/.libs/*.{so,dll,DLL,dylib} \ $(top_builddir)/sys/oss4/.libs/*.{so,dll,DLL,dylib} \ $(top_builddir)/tests/check/elements/autocolorspace \ $(top_builddir)/tests/check/elements/capssetter \ $(top_builddir)/tests/check/elements/imagefreeze \ + $(top_builddir)/tests/check/elements/selector \ $(top_builddir)/tests/check/elements/valve \ $(top_builddir)/tests/check/pipelines/metadata \ + $(top_builddir)/tests/examples/switch/switcher \ + $(top_builddir)/tests/icles/output-selector-test \ $(top_builddir)/tests/icles/test-oss4 CRUFT_DIRS = \ @@ -65,9 +69,11 @@ CRUFT_DIRS = \ $(top_srcdir)/gst/amrparse \ $(top_srcdir)/gst/flacparse \ $(top_srcdir)/gst/imagefreeze \ + $(top_srcdir)/gst/selector \ $(top_srcdir)/gst/shapewipe \ $(top_srcdir)/gst/valve \ $(top_srcdir)/tests/examples/shapewipe \ + $(top_srcdir)/tests/examples/switch \ $(top_srcdir)/ext/alsaspdif \ $(top_srcdir)/ext/ivorbis \ $(top_srcdir)/ext/metadata diff --git a/configure.ac b/configure.ac index cde1da983f..50f03565e7 100644 --- a/configure.ac +++ b/configure.ac @@ -337,7 +337,6 @@ AG_GST_CHECK_PLUGIN(rtpmux) AG_GST_CHECK_PLUGIN(scaletempo) AG_GST_CHECK_PLUGIN(sdp) AG_GST_CHECK_PLUGIN(segmentclip) -AG_GST_CHECK_PLUGIN(selector) AG_GST_CHECK_PLUGIN(siren) AG_GST_CHECK_PLUGIN(speed) AG_GST_CHECK_PLUGIN(subenc) @@ -1766,7 +1765,6 @@ gst/rtpmux/Makefile gst/scaletempo/Makefile gst/sdp/Makefile gst/segmentclip/Makefile -gst/selector/Makefile gst/siren/Makefile gst/speed/Makefile gst/subenc/Makefile @@ -1814,7 +1812,6 @@ tests/examples/camerabin2/Makefile tests/examples/directfb/Makefile tests/examples/mxf/Makefile tests/examples/scaletempo/Makefile -tests/examples/switch/Makefile tests/examples/jack/Makefile tests/icles/Makefile ext/amrwbenc/Makefile diff --git a/docs/plugins/Makefile.am b/docs/plugins/Makefile.am index 478b90eb90..6a151ffea1 100644 --- a/docs/plugins/Makefile.am +++ b/docs/plugins/Makefile.am @@ -195,8 +195,6 @@ EXTRA_HFILES = \ $(top_srcdir)/gst/rtpmux/gstrtpdtmfmux.h \ $(top_srcdir)/gst/scaletempo/gstscaletempo.h \ $(top_srcdir)/gst/sdp/gstsdpdemux.h \ - $(top_srcdir)/gst/selector/gstinputselector.h \ - $(top_srcdir)/gst/selector/gstoutputselector.h \ $(top_srcdir)/gst/speed/gstspeed.h \ $(top_srcdir)/gst/stereo/gststereo.h \ $(top_srcdir)/gst/videomaxrate/videomaxrate.h \ diff --git a/docs/plugins/gst-plugins-bad-plugins-docs.sgml b/docs/plugins/gst-plugins-bad-plugins-docs.sgml index cb2ff1a69b..f4b5455045 100644 --- a/docs/plugins/gst-plugins-bad-plugins-docs.sgml +++ b/docs/plugins/gst-plugins-bad-plugins-docs.sgml @@ -68,7 +68,6 @@ - @@ -93,7 +92,6 @@ - @@ -204,7 +202,6 @@ - diff --git a/docs/plugins/gst-plugins-bad-plugins-sections.txt b/docs/plugins/gst-plugins-bad-plugins-sections.txt index 8f26b09b8d..764f641af2 100644 --- a/docs/plugins/gst-plugins-bad-plugins-sections.txt +++ b/docs/plugins/gst-plugins-bad-plugins-sections.txt @@ -791,26 +791,6 @@ gauss_blur_get_type gst_gauss_blur_plugin_init
-
-element-input-selector -input-selector -GstInputSelector - -GstInputSelectorClass -GST_INPUT_SELECTOR -GST_INPUT_SELECTOR_CLASS -GST_IS_INPUT_SELECTOR -GST_IS_INPUT_SELECTOR_CLASS -GST_TYPE_INPUT_SELECTOR -gst_input_selector_get_type -GST_INPUT_SELECTOR_BROADCAST -GST_INPUT_SELECTOR_GET_COND -GST_INPUT_SELECTOR_GET_LOCK -GST_INPUT_SELECTOR_LOCK -GST_INPUT_SELECTOR_UNLOCK -GST_INPUT_SELECTOR_WAIT -
-
element-ivfparse ivfparse @@ -1179,20 +1159,6 @@ GST_TYPE_NUV_DEMUX gst_nuv_demux_get_type
-
-element-output-selector -output-selector -GstOutputSelector - -GstOutputSelectorClass -GST_OUTPUT_SELECTOR -GST_OUTPUT_SELECTOR_CLASS -GST_IS_OUTPUT_SELECTOR -GST_IS_OUTPUT_SELECTOR_CLASS -GST_TYPE_OUTPUT_SELECTOR -gst_output_selector_get_type -
-
element-pcapparse pcapparse diff --git a/docs/plugins/gst-plugins-bad-plugins.args b/docs/plugins/gst-plugins-bad-plugins.args index d54b586ad2..9d4bdf5ca3 100644 --- a/docs/plugins/gst-plugins-bad-plugins.args +++ b/docs/plugins/gst-plugins-bad-plugins.args @@ -18473,56 +18473,6 @@ 26 - -GstInputSelector::active-pad -GstPad* - -rw -Active pad -The currently active sink pad. - - - - -GstInputSelector::n-pads -guint - -r -Number of Pads -The number of sink pads. -0 - - - -GstInputSelector::select-all -gboolean - -rw -Select all mode -Forwards data from all input pads. -FALSE - - - -GstOutputSelector::active-pad -GstPad* - -rw -Active pad -Currently active src pad. - - - - -GstOutputSelector::resend-latest -gboolean - -rw -Resend latest buffer -Resend latest buffer after a switch to a new pad. -FALSE - - GstGLTestSrc::is-live gboolean @@ -23453,16 +23403,6 @@ -1 - -GstValve::drop -gboolean - -rw -Drops all buffers if TRUE -If this property if TRUE, the element will drop all buffers, if its FALSE, it will let them through. -FALSE - - GstAutoConvert::factories gpointer @@ -28653,146 +28593,6 @@ FALSE - -GstRtpBin::do-lost -gboolean - -rw -Do Lost -Send an event downstream when a packet is lost. -FALSE - - - -GstRtpBin::latency -guint - -rw -Buffer latency in ms -Default amount of ms to buffer in the jitterbuffers. -200 - - - -GstRtpBin::sdes -GstStructure* - -rw -SDES -The SDES items of this session. - - - - -GstRtpJitterBuffer::do-lost -gboolean - -rw -Do Lost -Send an event downstream when a packet is lost. -FALSE - - - -GstRtpJitterBuffer::drop-on-latency -gboolean - -rw -Drop buffers when maximum latency is reached -Tells the jitterbuffer to never exceed the given latency in size. -FALSE - - - -GstRtpJitterBuffer::latency -guint - -rw -Buffer latency in ms -Amount of ms to buffer. -200 - - - -GstRtpJitterBuffer::ts-offset -gint64 - -rw -Timestamp Offset -Adjust buffer timestamps with offset in nanoseconds. -0 - - - -GstRtpSession::bandwidth -gdouble ->= 0 -rw -Bandwidth -The bandwidth of the session. -64000 - - - -GstRtpSession::internal-session -RTPSession* - -r -Internal Session -The internal RTPSession object. - - - - -GstRtpSession::ntp-ns-base -guint64 - -rw -NTP base time -The NTP base time corresponding to running_time 0. -0 - - - -GstRtpSession::num-active-sources -guint - -r -Num Active Sources -The number of active sources in the session. -0 - - - -GstRtpSession::num-sources -guint - -r -Num Sources -The number of sources in the session. -0 - - - -GstRtpSession::rtcp-fraction -gdouble ->= 0 -rw -RTCP Fraction -The fraction of the bandwidth used for RTCP. -3000 - - - -GstRtpSession::sdes -GstStructure* - -rw -SDES -The SDES items of this session. - - - GstSSim::gauss-sigma gfloat diff --git a/docs/plugins/gst-plugins-bad-plugins.hierarchy b/docs/plugins/gst-plugins-bad-plugins.hierarchy index d377a64fa5..511a79e541 100644 --- a/docs/plugins/gst-plugins-bad-plugins.hierarchy +++ b/docs/plugins/gst-plugins-bad-plugins.hierarchy @@ -223,7 +223,6 @@ GObject GstISMLMux GstId3BaseMux GstId3Mux - GstInputSelector GstInterlace GstInvtelecine GstIvfParse @@ -254,7 +253,6 @@ GObject GstMveMux GstNsfDec GstNuvDemux - GstOutputSelector GstPcapParse GstPitch GstPnmdec diff --git a/docs/plugins/inspect/plugin-selector.xml b/docs/plugins/inspect/plugin-selector.xml deleted file mode 100644 index b3b15c91dd..0000000000 --- a/docs/plugins/inspect/plugin-selector.xml +++ /dev/null @@ -1,55 +0,0 @@ - - selector - input/output stream selector elements - ../../gst/selector/.libs/libgstselector.so - libgstselector.so - 0.10.20.1 - LGPL - gst-plugins-bad - GStreamer Bad Plug-ins git - Unknown package origin - - - input-selector - Input selector - Generic - N-to-1 input stream selectoring - Julien Moutte <julien@moutte.net>, Jan Schmidt <thaytan@mad.scientist.com>, Wim Taymans <wim.taymans@gmail.com> - - - sink%d - sink - request -
ANY
-
- - src - source - always -
ANY
-
-
-
- - output-selector - Output selector - Generic - 1-to-N output stream selectoring - Stefan Kost <stefan.kost@nokia.com> - - - sink - sink - always -
ANY
-
- - src%d - source - request -
ANY
-
-
-
-
-
\ No newline at end of file diff --git a/gst-plugins-bad.spec.in b/gst-plugins-bad.spec.in index 02495e1844..6ad7d763cb 100644 --- a/gst-plugins-bad.spec.in +++ b/gst-plugins-bad.spec.in @@ -95,7 +95,6 @@ rm -rf $RPM_BUILD_ROOT %{_libdir}/gstreamer-%{majorminor}/libgstmpeg4videoparse.so %{_libdir}/gstreamer-%{majorminor}/libgstfbdevsink.so %{_libdir}/gstreamer-%{majorminor}/libgstrawparse.so -%{_libdir}/gstreamer-%{majorminor}/libgstselector.so %{_libdir}/gstreamer-%{majorminor}/libgstsubenc.so %{_libdir}/gstreamer-%{majorminor}/libresindvd.so %{_libdir}/gstreamer-%{majorminor}/libgstaiff.so diff --git a/gst/selector/.gitignore b/gst/selector/.gitignore deleted file mode 100644 index 1cf1f1b306..0000000000 --- a/gst/selector/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -gstselector-marshal.c -gstselector-marshal.h diff --git a/gst/selector/Makefile.am b/gst/selector/Makefile.am deleted file mode 100644 index 0e43cce17e..0000000000 --- a/gst/selector/Makefile.am +++ /dev/null @@ -1,24 +0,0 @@ -glib_gen_prefix = gst_selector -glib_gen_basename = gstselector - -include $(top_srcdir)/common/gst-glib-gen.mak - -built_sources = gstselector-marshal.c -built_headers = gstselector-marshal.h - -BUILT_SOURCES = $(built_sources) $(built_headers) - -CLEANFILES = $(BUILT_SOURCES) - -EXTRA_DIST = gstselector-marshal.list - -plugin_LTLIBRARIES = libgstselector.la - -libgstselector_la_SOURCES = gstselector.c gstinputselector.c gstoutputselector.c -nodist_libgstselector_la_SOURCES = $(built_sources) -libgstselector_la_CFLAGS = $(GST_CFLAGS) -libgstselector_la_LIBADD = $(GST_LIBS) $(GST_BASE_LIBS) -libgstselector_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) -libgstselector_la_LIBTOOLFLAGS = --tag=disable-static - -noinst_HEADERS = gstinputselector.h gstoutputselector.h diff --git a/gst/selector/gstinputselector.c b/gst/selector/gstinputselector.c deleted file mode 100644 index ee7643f262..0000000000 --- a/gst/selector/gstinputselector.c +++ /dev/null @@ -1,1430 +0,0 @@ -/* GStreamer - * Copyright (C) 2003 Julien Moutte - * Copyright (C) 2005 Ronald S. Bultje - * Copyright (C) 2005 Jan Schmidt - * Copyright (C) 2007 Wim Taymans - * Copyright (C) 2007 Andy Wingo - * Copyright (C) 2008 Nokia Corporation. (contact ) - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -/** - * SECTION:element-input-selector - * @see_also: #GstOutputSelector - * - * Direct one out of N input streams to the output pad. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include - -#include "gstinputselector.h" -#include "gstselector-marshal.h" - -GST_DEBUG_CATEGORY_STATIC (input_selector_debug); -#define GST_CAT_DEFAULT input_selector_debug - -static GstStaticPadTemplate gst_input_selector_sink_factory = -GST_STATIC_PAD_TEMPLATE ("sink%d", - GST_PAD_SINK, - GST_PAD_REQUEST, - GST_STATIC_CAPS_ANY); - -static GstStaticPadTemplate gst_input_selector_src_factory = -GST_STATIC_PAD_TEMPLATE ("src", - GST_PAD_SRC, - GST_PAD_ALWAYS, - GST_STATIC_CAPS_ANY); - -enum -{ - PROP_0, - PROP_N_PADS, - PROP_ACTIVE_PAD, - PROP_SELECT_ALL, - PROP_LAST -}; - -#define DEFAULT_PAD_ALWAYS_OK TRUE - -enum -{ - PROP_PAD_0, - PROP_PAD_RUNNING_TIME, - PROP_PAD_TAGS, - PROP_PAD_ACTIVE, - PROP_PAD_ALWAYS_OK, - PROP_PAD_LAST -}; - -enum -{ - /* methods */ - SIGNAL_BLOCK, - SIGNAL_SWITCH, - LAST_SIGNAL -}; -static guint gst_input_selector_signals[LAST_SIGNAL] = { 0 }; - -static inline gboolean gst_input_selector_is_active_sinkpad (GstInputSelector * - sel, GstPad * pad); -static GstPad *gst_input_selector_activate_sinkpad (GstInputSelector * sel, - GstPad * pad); -static GstPad *gst_input_selector_get_linked_pad (GstPad * pad, - gboolean strict); -static gboolean gst_input_selector_check_eos (GstElement * selector); - -#define GST_TYPE_SELECTOR_PAD \ - (gst_selector_pad_get_type()) -#define GST_SELECTOR_PAD(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_SELECTOR_PAD, GstSelectorPad)) -#define GST_SELECTOR_PAD_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_SELECTOR_PAD, GstSelectorPadClass)) -#define GST_IS_SELECTOR_PAD(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_SELECTOR_PAD)) -#define GST_IS_SELECTOR_PAD_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_SELECTOR_PAD)) -#define GST_SELECTOR_PAD_CAST(obj) \ - ((GstSelectorPad *)(obj)) - -typedef struct _GstSelectorPad GstSelectorPad; -typedef struct _GstSelectorPadClass GstSelectorPadClass; - -struct _GstSelectorPad -{ - GstPad parent; - - gboolean active; /* when buffer have passed the pad */ - gboolean eos; /* when EOS has been received */ - gboolean discont; /* after switching we create a discont */ - gboolean always_ok; - GstSegment segment; /* the current segment on the pad */ - GstTagList *tags; /* last tags received on the pad */ - - gboolean segment_pending; -}; - -struct _GstSelectorPadClass -{ - GstPadClass parent; -}; - -static void gst_selector_pad_class_init (GstSelectorPadClass * klass); -static void gst_selector_pad_init (GstSelectorPad * pad); -static void gst_selector_pad_finalize (GObject * object); -static void gst_selector_pad_get_property (GObject * object, - guint prop_id, GValue * value, GParamSpec * pspec); -static void gst_selector_pad_set_property (GObject * object, - guint prop_id, const GValue * value, GParamSpec * pspec); - -static GstPadClass *selector_pad_parent_class = NULL; - -static gint64 gst_selector_pad_get_running_time (GstSelectorPad * pad); -static void gst_selector_pad_reset (GstSelectorPad * pad); -static gboolean gst_selector_pad_event (GstPad * pad, GstEvent * event); -static GstCaps *gst_selector_pad_getcaps (GstPad * pad); -static gboolean gst_selector_pad_acceptcaps (GstPad * pad, GstCaps * caps); -static GstIterator *gst_selector_pad_iterate_linked_pads (GstPad * pad); -static GstFlowReturn gst_selector_pad_chain (GstPad * pad, GstBuffer * buf); -static GstFlowReturn gst_selector_pad_bufferalloc (GstPad * pad, - guint64 offset, guint size, GstCaps * caps, GstBuffer ** buf); - -static GType -gst_selector_pad_get_type (void) -{ - static GType selector_pad_type = 0; - - if (!selector_pad_type) { - static const GTypeInfo selector_pad_info = { - sizeof (GstSelectorPadClass), - NULL, - NULL, - (GClassInitFunc) gst_selector_pad_class_init, - NULL, - NULL, - sizeof (GstSelectorPad), - 0, - (GInstanceInitFunc) gst_selector_pad_init, - }; - - selector_pad_type = - g_type_register_static (GST_TYPE_PAD, "GstSelectorPad", - &selector_pad_info, 0); - } - return selector_pad_type; -} - -static void -gst_selector_pad_class_init (GstSelectorPadClass * klass) -{ - GObjectClass *gobject_class; - - gobject_class = (GObjectClass *) klass; - - selector_pad_parent_class = g_type_class_peek_parent (klass); - - gobject_class->finalize = gst_selector_pad_finalize; - - gobject_class->get_property = gst_selector_pad_get_property; - gobject_class->set_property = gst_selector_pad_set_property; - - g_object_class_install_property (gobject_class, PROP_PAD_RUNNING_TIME, - g_param_spec_int64 ("running-time", "Running time", - "Running time of stream on pad", 0, G_MAXINT64, 0, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, PROP_PAD_TAGS, - g_param_spec_boxed ("tags", "Tags", - "The currently active tags on the pad", GST_TYPE_TAG_LIST, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, PROP_PAD_ACTIVE, - g_param_spec_boolean ("active", "Active", - "If the pad is currently active", FALSE, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, PROP_PAD_ALWAYS_OK, - g_param_spec_boolean ("always-ok", "Always OK", - "Make an inactive pad return OK instead of NOT_LINKED", - DEFAULT_PAD_ALWAYS_OK, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); -} - -static void -gst_selector_pad_init (GstSelectorPad * pad) -{ - pad->always_ok = DEFAULT_PAD_ALWAYS_OK; - gst_selector_pad_reset (pad); -} - -static void -gst_selector_pad_finalize (GObject * object) -{ - GstSelectorPad *pad; - - pad = GST_SELECTOR_PAD_CAST (object); - - if (pad->tags) - gst_tag_list_free (pad->tags); - - G_OBJECT_CLASS (selector_pad_parent_class)->finalize (object); -} - -static void -gst_selector_pad_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstSelectorPad *spad = GST_SELECTOR_PAD_CAST (object); - - switch (prop_id) { - case PROP_PAD_ALWAYS_OK: - GST_OBJECT_LOCK (object); - spad->always_ok = g_value_get_boolean (value); - GST_OBJECT_UNLOCK (object); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_selector_pad_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - GstSelectorPad *spad = GST_SELECTOR_PAD_CAST (object); - - switch (prop_id) { - case PROP_PAD_RUNNING_TIME: - g_value_set_int64 (value, gst_selector_pad_get_running_time (spad)); - break; - case PROP_PAD_TAGS: - GST_OBJECT_LOCK (object); - g_value_set_boxed (value, spad->tags); - GST_OBJECT_UNLOCK (object); - break; - case PROP_PAD_ACTIVE: - { - GstInputSelector *sel; - - sel = GST_INPUT_SELECTOR (gst_pad_get_parent (spad)); - g_value_set_boolean (value, gst_input_selector_is_active_sinkpad (sel, - GST_PAD_CAST (spad))); - gst_object_unref (sel); - break; - } - case PROP_PAD_ALWAYS_OK: - GST_OBJECT_LOCK (object); - g_value_set_boolean (value, spad->always_ok); - GST_OBJECT_UNLOCK (object); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static gint64 -gst_selector_pad_get_running_time (GstSelectorPad * pad) -{ - gint64 ret = 0; - - GST_OBJECT_LOCK (pad); - if (pad->active) { - gint64 last_stop = pad->segment.last_stop; - - if (last_stop >= 0) - ret = gst_segment_to_running_time (&pad->segment, GST_FORMAT_TIME, - last_stop); - } - GST_OBJECT_UNLOCK (pad); - - GST_DEBUG_OBJECT (pad, "running time: %" GST_TIME_FORMAT, - GST_TIME_ARGS (ret)); - - return ret; -} - -static void -gst_selector_pad_reset (GstSelectorPad * pad) -{ - GST_OBJECT_LOCK (pad); - pad->active = FALSE; - pad->eos = FALSE; - pad->segment_pending = FALSE; - pad->discont = FALSE; - gst_segment_init (&pad->segment, GST_FORMAT_UNDEFINED); - GST_OBJECT_UNLOCK (pad); -} - -/* strictly get the linked pad from the sinkpad. If the pad is active we return - * the srcpad else we return NULL */ -static GstIterator * -gst_selector_pad_iterate_linked_pads (GstPad * pad) -{ - GstInputSelector *sel = GST_INPUT_SELECTOR (gst_pad_get_parent (pad)); - GstPad *otherpad; - GstIterator *it; - - otherpad = gst_input_selector_get_linked_pad (pad, TRUE); - it = gst_iterator_new_single (GST_TYPE_PAD, otherpad, - (GstCopyFunction) gst_object_ref, (GFreeFunc) gst_object_unref); - - if (otherpad) - gst_object_unref (otherpad); - gst_object_unref (sel); - - return it; -} - -static gboolean -gst_selector_pad_event (GstPad * pad, GstEvent * event) -{ - gboolean res = TRUE; - gboolean forward = TRUE; - GstInputSelector *sel; - GstSelectorPad *selpad; - GstPad *prev_active_sinkpad; - GstPad *active_sinkpad; - - sel = GST_INPUT_SELECTOR (gst_pad_get_parent (pad)); - selpad = GST_SELECTOR_PAD_CAST (pad); - - GST_INPUT_SELECTOR_LOCK (sel); - prev_active_sinkpad = sel->active_sinkpad; - active_sinkpad = gst_input_selector_activate_sinkpad (sel, pad); - - /* only forward if we are dealing with the active sinkpad or if select_all - * is enabled */ - if (pad != active_sinkpad && !sel->select_all) - forward = FALSE; - GST_INPUT_SELECTOR_UNLOCK (sel); - - if (prev_active_sinkpad != active_sinkpad && pad == active_sinkpad) - g_object_notify (G_OBJECT (sel), "active-pad"); - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_FLUSH_START: - /* FIXME, flush out the waiter */ - break; - case GST_EVENT_FLUSH_STOP: - GST_INPUT_SELECTOR_LOCK (sel); - gst_selector_pad_reset (selpad); - sel->pending_close = FALSE; - GST_INPUT_SELECTOR_UNLOCK (sel); - break; - case GST_EVENT_NEWSEGMENT: - { - gboolean update; - GstFormat format; - gdouble rate, arate; - gint64 start, stop, time; - - gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format, - &start, &stop, &time); - - GST_DEBUG_OBJECT (pad, - "configured NEWSEGMENT update %d, rate %lf, applied rate %lf, " - "format %d, " - "%" G_GINT64_FORMAT " -- %" G_GINT64_FORMAT ", time %" - G_GINT64_FORMAT, update, rate, arate, format, start, stop, time); - - GST_INPUT_SELECTOR_LOCK (sel); - GST_OBJECT_LOCK (selpad); - gst_segment_set_newsegment_full (&selpad->segment, update, - rate, arate, format, start, stop, time); - GST_OBJECT_UNLOCK (selpad); - - /* If we aren't forwarding the event (because the pad is not the - * active_sinkpad, and select_all is not set, then set the flag on the - * that says a segment needs sending if/when that pad is activated. - * For all other cases, we send the event immediately, which makes - * sparse streams and other segment updates work correctly downstream. - */ - if (!forward) - selpad->segment_pending = TRUE; - - GST_INPUT_SELECTOR_UNLOCK (sel); - break; - } - case GST_EVENT_TAG: - { - GstTagList *tags, *oldtags, *newtags; - - gst_event_parse_tag (event, &tags); - - GST_OBJECT_LOCK (selpad); - oldtags = selpad->tags; - - newtags = gst_tag_list_merge (oldtags, tags, GST_TAG_MERGE_REPLACE); - selpad->tags = newtags; - if (oldtags) - gst_tag_list_free (oldtags); - GST_DEBUG_OBJECT (pad, "received tags %" GST_PTR_FORMAT, newtags); - GST_OBJECT_UNLOCK (selpad); - - g_object_notify (G_OBJECT (selpad), "tags"); - break; - } - case GST_EVENT_EOS: - selpad->eos = TRUE; - GST_DEBUG_OBJECT (pad, "received EOS"); - /* don't forward eos in select_all mode until all sink pads have eos */ - if (sel->select_all && !gst_input_selector_check_eos (GST_ELEMENT (sel))) { - forward = FALSE; - } - break; - default: - break; - } - if (forward) { - GST_DEBUG_OBJECT (pad, "forwarding event"); - res = gst_pad_push_event (sel->srcpad, event); - } else - gst_event_unref (event); - - gst_object_unref (sel); - - return res; -} - -static GstCaps * -gst_selector_pad_getcaps (GstPad * pad) -{ - GstInputSelector *sel; - GstCaps *caps; - - sel = GST_INPUT_SELECTOR (gst_pad_get_parent (pad)); - - GST_DEBUG_OBJECT (sel, "Getting caps of srcpad peer"); - caps = gst_pad_peer_get_caps_reffed (sel->srcpad); - if (caps == NULL) - caps = gst_caps_new_any (); - - gst_object_unref (sel); - - return caps; -} - -static gboolean -gst_selector_pad_acceptcaps (GstPad * pad, GstCaps * caps) -{ - GstInputSelector *sel; - gboolean res; - - sel = GST_INPUT_SELECTOR (gst_pad_get_parent (pad)); - - GST_DEBUG_OBJECT (sel, "Checking acceptcaps of srcpad peer"); - res = gst_pad_peer_accept_caps (sel->srcpad, caps); - gst_object_unref (sel); - - return res; -} - -static GstFlowReturn -gst_selector_pad_bufferalloc (GstPad * pad, guint64 offset, - guint size, GstCaps * caps, GstBuffer ** buf) -{ - GstInputSelector *sel; - GstFlowReturn result; - GstPad *active_sinkpad; - GstPad *prev_active_sinkpad; - GstSelectorPad *selpad; - - sel = GST_INPUT_SELECTOR (gst_pad_get_parent (pad)); - selpad = GST_SELECTOR_PAD_CAST (pad); - - GST_LOG_OBJECT (pad, "received alloc"); - - GST_INPUT_SELECTOR_LOCK (sel); - prev_active_sinkpad = sel->active_sinkpad; - active_sinkpad = gst_input_selector_activate_sinkpad (sel, pad); - - if (pad != active_sinkpad) - goto not_active; - - GST_INPUT_SELECTOR_UNLOCK (sel); - - if (prev_active_sinkpad != active_sinkpad && pad == active_sinkpad) - g_object_notify (G_OBJECT (sel), "active-pad"); - - result = gst_pad_alloc_buffer (sel->srcpad, offset, size, caps, buf); - -done: - gst_object_unref (sel); - - return result; - - /* ERRORS */ -not_active: - { - GST_INPUT_SELECTOR_UNLOCK (sel); - - /* unselected pad, perform fallback alloc or return unlinked when - * asked */ - GST_OBJECT_LOCK (selpad); - if (selpad->always_ok) { - GST_DEBUG_OBJECT (pad, "Not selected, performing fallback allocation"); - *buf = NULL; - result = GST_FLOW_OK; - } else { - GST_DEBUG_OBJECT (pad, "Not selected, return NOT_LINKED"); - result = GST_FLOW_NOT_LINKED; - } - GST_OBJECT_UNLOCK (selpad); - - goto done; - } -} - -/* must be called with the SELECTOR_LOCK, will block while the pad is blocked - * or return TRUE when flushing */ -static gboolean -gst_input_selector_wait (GstInputSelector * self, GstPad * pad) -{ - while (self->blocked && !self->flushing) { - /* we can be unlocked here when we are shutting down (flushing) or when we - * get unblocked */ - GST_INPUT_SELECTOR_WAIT (self); - } - return self->flushing; -} - -static GstFlowReturn -gst_selector_pad_chain (GstPad * pad, GstBuffer * buf) -{ - GstInputSelector *sel; - GstFlowReturn res; - GstPad *active_sinkpad; - GstPad *prev_active_sinkpad; - GstSelectorPad *selpad; - GstClockTime start_time; - GstSegment *seg; - GstEvent *close_event = NULL, *start_event = NULL; - GstCaps *caps; - - sel = GST_INPUT_SELECTOR (gst_pad_get_parent (pad)); - selpad = GST_SELECTOR_PAD_CAST (pad); - seg = &selpad->segment; - - GST_INPUT_SELECTOR_LOCK (sel); - /* wait or check for flushing */ - if (gst_input_selector_wait (sel, pad)) - goto flushing; - - GST_LOG_OBJECT (pad, "getting active pad"); - - prev_active_sinkpad = sel->active_sinkpad; - active_sinkpad = gst_input_selector_activate_sinkpad (sel, pad); - - /* update the segment on the srcpad */ - start_time = GST_BUFFER_TIMESTAMP (buf); - if (GST_CLOCK_TIME_IS_VALID (start_time)) { - GST_LOG_OBJECT (pad, "received start time %" GST_TIME_FORMAT, - GST_TIME_ARGS (start_time)); - if (GST_BUFFER_DURATION_IS_VALID (buf)) - GST_LOG_OBJECT (pad, "received end time %" GST_TIME_FORMAT, - GST_TIME_ARGS (start_time + GST_BUFFER_DURATION (buf))); - - GST_OBJECT_LOCK (pad); - gst_segment_set_last_stop (seg, seg->format, start_time); - GST_OBJECT_UNLOCK (pad); - } - - /* Ignore buffers from pads except the selected one */ - if (pad != active_sinkpad) - goto ignore; - - if (G_UNLIKELY (sel->pending_close)) { - GstSegment *cseg = &sel->segment; - - GST_DEBUG_OBJECT (sel, - "pushing close NEWSEGMENT update %d, rate %lf, applied rate %lf, " - "format %d, " - "%" G_GINT64_FORMAT " -- %" G_GINT64_FORMAT ", time %" - G_GINT64_FORMAT, TRUE, cseg->rate, cseg->applied_rate, cseg->format, - cseg->start, cseg->stop, cseg->time); - - /* create update segment */ - close_event = gst_event_new_new_segment_full (TRUE, cseg->rate, - cseg->applied_rate, cseg->format, cseg->start, cseg->stop, cseg->time); - - sel->pending_close = FALSE; - } - /* if we have a pending segment, push it out now */ - if (G_UNLIKELY (selpad->segment_pending)) { - GST_DEBUG_OBJECT (pad, - "pushing pending NEWSEGMENT update %d, rate %lf, applied rate %lf, " - "format %d, " - "%" G_GINT64_FORMAT " -- %" G_GINT64_FORMAT ", time %" - G_GINT64_FORMAT, FALSE, seg->rate, seg->applied_rate, seg->format, - seg->start, seg->stop, seg->time); - - start_event = gst_event_new_new_segment_full (FALSE, seg->rate, - seg->applied_rate, seg->format, seg->start, seg->stop, seg->time); - - selpad->segment_pending = FALSE; - } - GST_INPUT_SELECTOR_UNLOCK (sel); - - if (prev_active_sinkpad != active_sinkpad && pad == active_sinkpad) - g_object_notify (G_OBJECT (sel), "active-pad"); - - if (close_event) - gst_pad_push_event (sel->srcpad, close_event); - - if (start_event) - gst_pad_push_event (sel->srcpad, start_event); - - if (selpad->discont) { - buf = gst_buffer_make_metadata_writable (buf); - - GST_DEBUG_OBJECT (pad, "Marking discont buffer %p", buf); - GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT); - selpad->discont = FALSE; - } - - /* forward */ - GST_LOG_OBJECT (pad, "Forwarding buffer %p", buf); - - if ((caps = GST_BUFFER_CAPS (buf))) { - if (GST_PAD_CAPS (sel->srcpad) != caps) - gst_pad_set_caps (sel->srcpad, caps); - } - - res = gst_pad_push (sel->srcpad, buf); - -done: - gst_object_unref (sel); - return res; - - /* dropped buffers */ -ignore: - { - GST_DEBUG_OBJECT (pad, "Pad not active, discard buffer %p", buf); - /* when we drop a buffer, we're creating a discont on this pad */ - selpad->discont = TRUE; - GST_INPUT_SELECTOR_UNLOCK (sel); - gst_buffer_unref (buf); - - /* figure out what to return upstream */ - GST_OBJECT_LOCK (selpad); - if (selpad->always_ok) - res = GST_FLOW_OK; - else - res = GST_FLOW_NOT_LINKED; - GST_OBJECT_UNLOCK (selpad); - - goto done; - } -flushing: - { - GST_DEBUG_OBJECT (pad, "We are flushing, discard buffer %p", buf); - GST_INPUT_SELECTOR_UNLOCK (sel); - gst_buffer_unref (buf); - res = GST_FLOW_WRONG_STATE; - goto done; - } -} - -static void gst_input_selector_dispose (GObject * object); - -static void gst_input_selector_set_property (GObject * object, - guint prop_id, const GValue * value, GParamSpec * pspec); -static void gst_input_selector_get_property (GObject * object, - guint prop_id, GValue * value, GParamSpec * pspec); - -static GstPad *gst_input_selector_request_new_pad (GstElement * element, - GstPadTemplate * templ, const gchar * unused); -static void gst_input_selector_release_pad (GstElement * element, GstPad * pad); - -static GstStateChangeReturn gst_input_selector_change_state (GstElement * - element, GstStateChange transition); - -static GstCaps *gst_input_selector_getcaps (GstPad * pad); -static gboolean gst_input_selector_event (GstPad * pad, GstEvent * event); -static gboolean gst_input_selector_query (GstPad * pad, GstQuery * query); -static gint64 gst_input_selector_block (GstInputSelector * self); -static void gst_input_selector_switch (GstInputSelector * self, - GstPad * pad, gint64 stop_time, gint64 start_time); - -#define _do_init(bla) \ - GST_DEBUG_CATEGORY_INIT (input_selector_debug, \ - "input-selector", 0, "An input stream selector element"); - -GST_BOILERPLATE_FULL (GstInputSelector, gst_input_selector, GstElement, - GST_TYPE_ELEMENT, _do_init); - -static void -gst_input_selector_base_init (gpointer g_class) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); - - gst_element_class_set_details_simple (element_class, "Input selector", - "Generic", "N-to-1 input stream selectoring", - "Julien Moutte , " - "Jan Schmidt , " - "Wim Taymans "); - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&gst_input_selector_sink_factory)); - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&gst_input_selector_src_factory)); -} - -static void -gst_input_selector_class_init (GstInputSelectorClass * klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); - - parent_class = g_type_class_peek_parent (klass); - - gobject_class->dispose = gst_input_selector_dispose; - - gobject_class->set_property = gst_input_selector_set_property; - gobject_class->get_property = gst_input_selector_get_property; - - g_object_class_install_property (gobject_class, PROP_N_PADS, - g_param_spec_uint ("n-pads", "Number of Pads", - "The number of sink pads", 0, G_MAXUINT, 0, - G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, PROP_ACTIVE_PAD, - g_param_spec_object ("active-pad", "Active pad", - "The currently active sink pad", GST_TYPE_PAD, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, PROP_SELECT_ALL, - g_param_spec_boolean ("select-all", "Select all mode", - "Forwards data from all input pads", FALSE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - /** - * GstInputSelector::block: - * @inputselector: the #GstInputSelector - * - * Block all sink pads in preparation for a switch. Returns the stop time of - * the current switch segment, as a running time, or 0 if there is no current - * active pad or the current active pad never received data. - */ - gst_input_selector_signals[SIGNAL_BLOCK] = - g_signal_new ("block", G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, - G_STRUCT_OFFSET (GstInputSelectorClass, block), NULL, NULL, - gst_selector_marshal_INT64__VOID, G_TYPE_INT64, 0); - /** - * GstInputSelector::switch: - * @inputselector: the #GstInputSelector - * @pad: the pad to switch to - * @stop_time: running time at which to close the previous segment, or -1 - * to use the running time of the previously active sink pad - * @start_time: running time at which to start the new segment, or -1 to - * use the running time of the newly active sink pad - * - * Switch to a new feed. The segment opened by the previously active pad, if - * any, will be closed, and a new segment opened before data flows again. - * - * This signal must be emitted when the element has been blocked via the block signal. - * - * If you have a stream with only one switch element, such as an audio-only - * stream, a stream switch should be performed by first emitting the block - * signal, and then emitting the switch signal with -1 for the stop and start - * time values. - * - * The intention of the @stop_time and @start_time arguments is to allow - * multiple switch elements to switch and maintain stream synchronization. - * When switching a stream with multiple feeds, you will need as many switch - * elements as you have feeds. For example, a feed with audio and video will - * have one switch element between the audio feeds and one for video. - * - * A switch over multiple switch elements should be performed as follows: - * First, emit the block - * signal, collecting the returned values. The maximum running time returned - * by block should then be used as the time at which to close the previous - * segment. - * - * Then, query the running times of the new audio and video pads that you will - * switch to. Naturally, these pads are on separate switch elements. Take the - * minimum running time for those streams and use it for the time at which to - * open the new segment. - * - * If @pad is the same as the current active pad, the element will cancel any - * previous block without adjusting segments. - * - * - * the signal changed from accepting the pad name to the pad object. - * - * - * Since: 0.10.7 - */ - gst_input_selector_signals[SIGNAL_SWITCH] = - g_signal_new ("switch", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (GstInputSelectorClass, switch_), - NULL, NULL, gst_selector_marshal_VOID__OBJECT_INT64_INT64, - G_TYPE_NONE, 3, GST_TYPE_PAD, G_TYPE_INT64, G_TYPE_INT64); - - gstelement_class->request_new_pad = gst_input_selector_request_new_pad; - gstelement_class->release_pad = gst_input_selector_release_pad; - gstelement_class->change_state = gst_input_selector_change_state; - - klass->block = GST_DEBUG_FUNCPTR (gst_input_selector_block); - /* note the underscore because switch is a keyword otherwise */ - klass->switch_ = GST_DEBUG_FUNCPTR (gst_input_selector_switch); -} - -static void -gst_input_selector_init (GstInputSelector * sel, - GstInputSelectorClass * g_class) -{ - sel->srcpad = gst_pad_new ("src", GST_PAD_SRC); - gst_pad_set_iterate_internal_links_function (sel->srcpad, - GST_DEBUG_FUNCPTR (gst_selector_pad_iterate_linked_pads)); - gst_pad_set_getcaps_function (sel->srcpad, - GST_DEBUG_FUNCPTR (gst_input_selector_getcaps)); - gst_pad_set_query_function (sel->srcpad, - GST_DEBUG_FUNCPTR (gst_input_selector_query)); - gst_pad_set_event_function (sel->srcpad, - GST_DEBUG_FUNCPTR (gst_input_selector_event)); - gst_element_add_pad (GST_ELEMENT (sel), sel->srcpad); - /* sinkpad management */ - sel->active_sinkpad = NULL; - sel->padcount = 0; - gst_segment_init (&sel->segment, GST_FORMAT_UNDEFINED); - - sel->lock = g_mutex_new (); - sel->cond = g_cond_new (); - sel->blocked = FALSE; - - sel->select_all = FALSE; -} - -static void -gst_input_selector_dispose (GObject * object) -{ - GstInputSelector *sel = GST_INPUT_SELECTOR (object); - - if (sel->active_sinkpad) { - gst_object_unref (sel->active_sinkpad); - sel->active_sinkpad = NULL; - } - if (sel->lock) { - g_mutex_free (sel->lock); - sel->lock = NULL; - } - if (sel->cond) { - g_cond_free (sel->cond); - sel->cond = NULL; - } - - G_OBJECT_CLASS (parent_class)->dispose (object); -} - -/* Solve the following equation for B.timestamp, and set that as the segment - * stop: - * B.running_time = (B.timestamp - NS.start) / NS.abs_rate + NS.accum - */ -static gint64 -gst_segment_get_timestamp (GstSegment * segment, gint64 running_time) -{ - if (running_time <= segment->accum) - return segment->start; - else - return (running_time - segment->accum) * segment->abs_rate + segment->start; -} - -static void -gst_segment_set_stop (GstSegment * segment, gint64 running_time) -{ - segment->stop = gst_segment_get_timestamp (segment, running_time); - segment->last_stop = -1; -} - -static void -gst_segment_set_start (GstSegment * segment, gint64 running_time) -{ - gint64 new_start, duration; - - new_start = gst_segment_get_timestamp (segment, running_time); - - /* this is the duration we skipped */ - duration = new_start - segment->start; - /* add the duration to the accumulated segment time */ - segment->accum += duration; - /* move position in the segment */ - segment->time += duration; - segment->start += duration; -} - -/* this function must be called with the SELECTOR_LOCK. It returns TRUE when the - * active pad changed. */ -static gboolean -gst_input_selector_set_active_pad (GstInputSelector * self, - GstPad * pad, gint64 stop_time, gint64 start_time) -{ - GstSelectorPad *old, *new; - GstPad **active_pad_p; - - if (pad == self->active_sinkpad) - return FALSE; - - old = GST_SELECTOR_PAD_CAST (self->active_sinkpad); - new = GST_SELECTOR_PAD_CAST (pad); - - GST_DEBUG_OBJECT (self, "setting active pad to %s:%s", - GST_DEBUG_PAD_NAME (new)); - - if (!GST_CLOCK_TIME_IS_VALID (stop_time) && old) { - /* no stop time given, get the latest running_time on the active pad to - * close and open the new segment */ - stop_time = start_time = gst_selector_pad_get_running_time (old); - GST_DEBUG_OBJECT (self, "using start/stop of %" GST_TIME_FORMAT, - GST_TIME_ARGS (start_time)); - } - - if (old && old->active && !self->pending_close && stop_time >= 0) { - /* schedule a last_stop update if one isn't already scheduled, and a - segment has been pushed before. */ - memcpy (&self->segment, &old->segment, sizeof (self->segment)); - - GST_DEBUG_OBJECT (self, "setting stop_time to %" GST_TIME_FORMAT, - GST_TIME_ARGS (stop_time)); - gst_segment_set_stop (&self->segment, stop_time); - self->pending_close = TRUE; - } - - if (new && new->active && start_time >= 0) { - GST_DEBUG_OBJECT (self, "setting start_time to %" GST_TIME_FORMAT, - GST_TIME_ARGS (start_time)); - /* schedule a new segment push */ - gst_segment_set_start (&new->segment, start_time); - new->segment_pending = TRUE; - } - - active_pad_p = &self->active_sinkpad; - gst_object_replace ((GstObject **) active_pad_p, GST_OBJECT_CAST (pad)); - GST_DEBUG_OBJECT (self, "New active pad is %" GST_PTR_FORMAT, - self->active_sinkpad); - - return TRUE; -} - -static void -gst_input_selector_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstInputSelector *sel = GST_INPUT_SELECTOR (object); - - switch (prop_id) { - case PROP_ACTIVE_PAD: - { - GstPad *pad; - - pad = g_value_get_object (value); - - GST_INPUT_SELECTOR_LOCK (sel); - gst_input_selector_set_active_pad (sel, pad, - GST_CLOCK_TIME_NONE, GST_CLOCK_TIME_NONE); - GST_INPUT_SELECTOR_UNLOCK (sel); - break; - } - case PROP_SELECT_ALL: - GST_INPUT_SELECTOR_LOCK (object); - sel->select_all = g_value_get_boolean (value); - GST_INPUT_SELECTOR_UNLOCK (object); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_input_selector_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - GstInputSelector *sel = GST_INPUT_SELECTOR (object); - - switch (prop_id) { - case PROP_N_PADS: - GST_INPUT_SELECTOR_LOCK (object); - g_value_set_uint (value, sel->n_pads); - GST_INPUT_SELECTOR_UNLOCK (object); - break; - case PROP_ACTIVE_PAD: - GST_INPUT_SELECTOR_LOCK (object); - g_value_set_object (value, sel->active_sinkpad); - GST_INPUT_SELECTOR_UNLOCK (object); - break; - case PROP_SELECT_ALL: - GST_INPUT_SELECTOR_LOCK (object); - g_value_set_boolean (value, sel->select_all); - GST_INPUT_SELECTOR_UNLOCK (object); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static GstPad * -gst_input_selector_get_linked_pad (GstPad * pad, gboolean strict) -{ - GstInputSelector *sel; - GstPad *otherpad = NULL; - - sel = GST_INPUT_SELECTOR (gst_pad_get_parent (pad)); - - GST_INPUT_SELECTOR_LOCK (sel); - if (pad == sel->srcpad) - otherpad = sel->active_sinkpad; - else if (pad == sel->active_sinkpad || !strict) - otherpad = sel->srcpad; - if (otherpad) - gst_object_ref (otherpad); - GST_INPUT_SELECTOR_UNLOCK (sel); - - gst_object_unref (sel); - - return otherpad; -} - -static gboolean -gst_input_selector_event (GstPad * pad, GstEvent * event) -{ - gboolean res = FALSE; - GstPad *otherpad; - - otherpad = gst_input_selector_get_linked_pad (pad, TRUE); - - if (otherpad) { - res = gst_pad_push_event (otherpad, event); - - gst_object_unref (otherpad); - } else - gst_event_unref (event); - return res; -} - -/* query on the srcpad. We override this function because by default it will - * only forward the query to one random sinkpad */ -static gboolean -gst_input_selector_query (GstPad * pad, GstQuery * query) -{ - gboolean res = TRUE; - GstInputSelector *sel; - GstPad *otherpad; - - sel = GST_INPUT_SELECTOR (gst_pad_get_parent (pad)); - - otherpad = gst_input_selector_get_linked_pad (pad, TRUE); - - switch (GST_QUERY_TYPE (query)) { - case GST_QUERY_LATENCY: - { - GList *walk; - GstClockTime resmin, resmax; - gboolean reslive; - - resmin = 0; - resmax = -1; - reslive = FALSE; - - /* assume FALSE, we become TRUE if one query succeeds */ - res = FALSE; - - /* perform the query on all sinkpads and combine the results. We take the - * max of min and the min of max for the result latency. */ - GST_INPUT_SELECTOR_LOCK (sel); - for (walk = GST_ELEMENT_CAST (sel)->sinkpads; walk; - walk = g_list_next (walk)) { - GstPad *sinkpad = GST_PAD_CAST (walk->data); - - if (gst_pad_peer_query (sinkpad, query)) { - GstClockTime min, max; - gboolean live; - - /* one query succeeded, we succeed too */ - res = TRUE; - - gst_query_parse_latency (query, &live, &min, &max); - - GST_DEBUG_OBJECT (sinkpad, - "peer latency min %" GST_TIME_FORMAT ", max %" GST_TIME_FORMAT - ", live %d", GST_TIME_ARGS (min), GST_TIME_ARGS (max), live); - - if (live) { - if (min > resmin) - resmin = min; - if (resmax == -1) - resmax = max; - else if (max < resmax) - resmax = max; - if (reslive == FALSE) - reslive = live; - } - } - } - GST_INPUT_SELECTOR_UNLOCK (sel); - if (res) { - gst_query_set_latency (query, reslive, resmin, resmax); - - GST_DEBUG_OBJECT (sel, - "total latency min %" GST_TIME_FORMAT ", max %" GST_TIME_FORMAT - ", live %d", GST_TIME_ARGS (resmin), GST_TIME_ARGS (resmax), - reslive); - } - - break; - } - default: - if (otherpad) - res = gst_pad_peer_query (otherpad, query); - break; - } - if (otherpad) - gst_object_unref (otherpad); - gst_object_unref (sel); - - return res; -} - -static GstCaps * -gst_input_selector_getcaps (GstPad * pad) -{ - GstPad *otherpad; - GstObject *parent; - GstCaps *caps; - - parent = gst_object_get_parent (GST_OBJECT (pad)); - - otherpad = gst_input_selector_get_linked_pad (pad, FALSE); - - if (!otherpad) { - if (GST_INPUT_SELECTOR (parent)->select_all) { - GST_DEBUG_OBJECT (parent, - "Pad %s:%s not linked, returning merge of caps", - GST_DEBUG_PAD_NAME (pad)); - caps = gst_pad_proxy_getcaps (pad); - } else { - GST_DEBUG_OBJECT (parent, - "Pad %s:%s not linked, returning ANY", GST_DEBUG_PAD_NAME (pad)); - caps = gst_caps_new_any (); - } - } else { - GST_DEBUG_OBJECT (parent, - "Pad %s:%s is linked (to %s:%s), returning peer caps", - GST_DEBUG_PAD_NAME (pad), GST_DEBUG_PAD_NAME (otherpad)); - /* if the peer has caps, use those. If the pad is not linked, this function - * returns NULL and we return ANY */ - if (!(caps = gst_pad_peer_get_caps_reffed (otherpad))) - caps = gst_caps_new_any (); - gst_object_unref (otherpad); - } - - gst_object_unref (parent); - return caps; -} - -/* check if the pad is the active sinkpad */ -static inline gboolean -gst_input_selector_is_active_sinkpad (GstInputSelector * sel, GstPad * pad) -{ - gboolean res; - - GST_INPUT_SELECTOR_LOCK (sel); - res = (pad == sel->active_sinkpad); - GST_INPUT_SELECTOR_UNLOCK (sel); - - return res; -} - -/* Get or create the active sinkpad, must be called with SELECTOR_LOCK */ -static GstPad * -gst_input_selector_activate_sinkpad (GstInputSelector * sel, GstPad * pad) -{ - GstPad *active_sinkpad; - GstSelectorPad *selpad; - - selpad = GST_SELECTOR_PAD_CAST (pad); - - selpad->active = TRUE; - active_sinkpad = sel->active_sinkpad; - if (active_sinkpad == NULL || sel->select_all) { - /* first pad we get activity on becomes the activated pad by default, if we - * select all, we also remember the last used pad. */ - if (sel->active_sinkpad) - gst_object_unref (sel->active_sinkpad); - active_sinkpad = sel->active_sinkpad = gst_object_ref (pad); - GST_DEBUG_OBJECT (sel, "Activating pad %s:%s", GST_DEBUG_PAD_NAME (pad)); - } - - return active_sinkpad; -} - -static GstPad * -gst_input_selector_request_new_pad (GstElement * element, - GstPadTemplate * templ, const gchar * unused) -{ - GstInputSelector *sel; - gchar *name = NULL; - GstPad *sinkpad = NULL; - - g_return_val_if_fail (templ->direction == GST_PAD_SINK, NULL); - - sel = GST_INPUT_SELECTOR (element); - - GST_INPUT_SELECTOR_LOCK (sel); - - GST_LOG_OBJECT (sel, "Creating new pad %d", sel->padcount); - name = g_strdup_printf ("sink%d", sel->padcount++); - sinkpad = g_object_new (GST_TYPE_SELECTOR_PAD, - "name", name, "direction", templ->direction, "template", templ, NULL); - g_free (name); - - sel->n_pads++; - - gst_pad_set_event_function (sinkpad, - GST_DEBUG_FUNCPTR (gst_selector_pad_event)); - gst_pad_set_getcaps_function (sinkpad, - GST_DEBUG_FUNCPTR (gst_selector_pad_getcaps)); - gst_pad_set_acceptcaps_function (sinkpad, - GST_DEBUG_FUNCPTR (gst_selector_pad_acceptcaps)); - gst_pad_set_chain_function (sinkpad, - GST_DEBUG_FUNCPTR (gst_selector_pad_chain)); - gst_pad_set_iterate_internal_links_function (sinkpad, - GST_DEBUG_FUNCPTR (gst_selector_pad_iterate_linked_pads)); - gst_pad_set_bufferalloc_function (sinkpad, - GST_DEBUG_FUNCPTR (gst_selector_pad_bufferalloc)); - - gst_pad_set_active (sinkpad, TRUE); - gst_element_add_pad (GST_ELEMENT (sel), sinkpad); - GST_INPUT_SELECTOR_UNLOCK (sel); - - return sinkpad; -} - -static void -gst_input_selector_release_pad (GstElement * element, GstPad * pad) -{ - GstInputSelector *sel; - - sel = GST_INPUT_SELECTOR (element); - GST_LOG_OBJECT (sel, "Releasing pad %s:%s", GST_DEBUG_PAD_NAME (pad)); - - GST_INPUT_SELECTOR_LOCK (sel); - /* if the pad was the active pad, makes us select a new one */ - if (sel->active_sinkpad == pad) { - GST_DEBUG_OBJECT (sel, "Deactivating pad %s:%s", GST_DEBUG_PAD_NAME (pad)); - gst_object_unref (sel->active_sinkpad); - sel->active_sinkpad = NULL; - } - sel->n_pads--; - - gst_pad_set_active (pad, FALSE); - gst_element_remove_pad (GST_ELEMENT (sel), pad); - GST_INPUT_SELECTOR_UNLOCK (sel); -} - -static void -gst_input_selector_reset (GstInputSelector * sel) -{ - GList *walk; - - GST_INPUT_SELECTOR_LOCK (sel); - /* clear active pad */ - if (sel->active_sinkpad) { - gst_object_unref (sel->active_sinkpad); - sel->active_sinkpad = NULL; - } - /* reset segment */ - gst_segment_init (&sel->segment, GST_FORMAT_UNDEFINED); - sel->pending_close = FALSE; - /* reset each of our sinkpads state */ - for (walk = GST_ELEMENT_CAST (sel)->sinkpads; walk; walk = g_list_next (walk)) { - GstSelectorPad *selpad = GST_SELECTOR_PAD_CAST (walk->data); - - gst_selector_pad_reset (selpad); - - if (selpad->tags) { - gst_tag_list_free (selpad->tags); - selpad->tags = NULL; - } - } - GST_INPUT_SELECTOR_UNLOCK (sel); -} - -static GstStateChangeReturn -gst_input_selector_change_state (GstElement * element, - GstStateChange transition) -{ - GstInputSelector *self = GST_INPUT_SELECTOR (element); - GstStateChangeReturn result; - - switch (transition) { - case GST_STATE_CHANGE_READY_TO_PAUSED: - GST_INPUT_SELECTOR_LOCK (self); - self->blocked = FALSE; - self->flushing = FALSE; - GST_INPUT_SELECTOR_UNLOCK (self); - break; - case GST_STATE_CHANGE_PAUSED_TO_READY: - /* first unlock before we call the parent state change function, which - * tries to acquire the stream lock when going to ready. */ - GST_INPUT_SELECTOR_LOCK (self); - self->blocked = FALSE; - self->flushing = TRUE; - GST_INPUT_SELECTOR_BROADCAST (self); - GST_INPUT_SELECTOR_UNLOCK (self); - break; - default: - break; - } - - result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); - - switch (transition) { - case GST_STATE_CHANGE_PAUSED_TO_READY: - gst_input_selector_reset (self); - break; - default: - break; - } - - return result; -} - -static gint64 -gst_input_selector_block (GstInputSelector * self) -{ - gint64 ret = 0; - GstSelectorPad *spad; - - GST_INPUT_SELECTOR_LOCK (self); - - if (self->blocked) - GST_WARNING_OBJECT (self, "switch already blocked"); - - self->blocked = TRUE; - spad = GST_SELECTOR_PAD_CAST (self->active_sinkpad); - - if (spad) - ret = gst_selector_pad_get_running_time (spad); - else - GST_DEBUG_OBJECT (self, "no active pad while blocking"); - - GST_INPUT_SELECTOR_UNLOCK (self); - - return ret; -} - -/* stop_time and start_time are running times */ -static void -gst_input_selector_switch (GstInputSelector * self, GstPad * pad, - gint64 stop_time, gint64 start_time) -{ - gboolean changed; - - g_return_if_fail (self->blocked == TRUE); - - GST_INPUT_SELECTOR_LOCK (self); - changed = - gst_input_selector_set_active_pad (self, pad, stop_time, start_time); - - self->blocked = FALSE; - GST_INPUT_SELECTOR_BROADCAST (self); - GST_INPUT_SELECTOR_UNLOCK (self); - - if (changed) - g_object_notify (G_OBJECT (self), "active-pad"); -} - -static gboolean -gst_input_selector_check_eos (GstElement * selector) -{ - GstIterator *it = gst_element_iterate_sink_pads (selector); - GstIteratorResult ires; - gpointer item; - gboolean done = FALSE, is_eos = FALSE; - GstSelectorPad *pad; - - while (!done) { - ires = gst_iterator_next (it, &item); - switch (ires) { - case GST_ITERATOR_DONE: - GST_INFO_OBJECT (selector, "all sink pads have eos"); - done = TRUE; - is_eos = TRUE; - break; - case GST_ITERATOR_OK: - pad = GST_SELECTOR_PAD_CAST (item); - if (!pad->eos) { - done = TRUE; - } - gst_object_unref (pad); - break; - case GST_ITERATOR_RESYNC: - gst_iterator_resync (it); - break; - default: - done = TRUE; - break; - } - } - gst_iterator_free (it); - - return is_eos; -} diff --git a/gst/selector/gstinputselector.h b/gst/selector/gstinputselector.h deleted file mode 100644 index 58a671d50c..0000000000 --- a/gst/selector/gstinputselector.h +++ /dev/null @@ -1,84 +0,0 @@ -/* GStreamer - * Copyright (C) 2003 Julien Moutte - * Copyright (C) 2005 Ronald S. Bultje - * Copyright (C) 2008 Nokia Corporation. (contact ) - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef __GST_INPUT_SELECTOR_H__ -#define __GST_INPUT_SELECTOR_H__ - -#include - -G_BEGIN_DECLS - -#define GST_TYPE_INPUT_SELECTOR \ - (gst_input_selector_get_type()) -#define GST_INPUT_SELECTOR(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_INPUT_SELECTOR, GstInputSelector)) -#define GST_INPUT_SELECTOR_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_INPUT_SELECTOR, GstInputSelectorClass)) -#define GST_IS_INPUT_SELECTOR(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_INPUT_SELECTOR)) -#define GST_IS_INPUT_SELECTOR_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_INPUT_SELECTOR)) - -typedef struct _GstInputSelector GstInputSelector; -typedef struct _GstInputSelectorClass GstInputSelectorClass; - -#define GST_INPUT_SELECTOR_GET_LOCK(sel) (((GstInputSelector*)(sel))->lock) -#define GST_INPUT_SELECTOR_GET_COND(sel) (((GstInputSelector*)(sel))->cond) -#define GST_INPUT_SELECTOR_LOCK(sel) (g_mutex_lock (GST_INPUT_SELECTOR_GET_LOCK(sel))) -#define GST_INPUT_SELECTOR_UNLOCK(sel) (g_mutex_unlock (GST_INPUT_SELECTOR_GET_LOCK(sel))) -#define GST_INPUT_SELECTOR_WAIT(sel) (g_cond_wait (GST_INPUT_SELECTOR_GET_COND(sel), \ - GST_INPUT_SELECTOR_GET_LOCK(sel))) -#define GST_INPUT_SELECTOR_BROADCAST(sel) (g_cond_broadcast (GST_INPUT_SELECTOR_GET_COND(sel))) - -struct _GstInputSelector { - GstElement element; - - GstPad *srcpad; - - GstPad *active_sinkpad; - guint n_pads; - guint padcount; - - GstSegment segment; /* the output segment */ - gboolean pending_close; /* if we should push a close first */ - - GMutex *lock; - GCond *cond; - gboolean blocked; - gboolean flushing; - - /* select all mode, send data from all input pads forward */ - gboolean select_all; -}; - -struct _GstInputSelectorClass { - GstElementClass parent_class; - - gint64 (*block) (GstInputSelector *self); - void (*switch_) (GstInputSelector *self, GstPad *pad, - gint64 stop_time, gint64 start_time); -}; - -GType gst_input_selector_get_type (void); - -G_END_DECLS - -#endif /* __GST_INPUT_SELECTOR_H__ */ diff --git a/gst/selector/gstoutputselector.c b/gst/selector/gstoutputselector.c deleted file mode 100644 index 9b75da2c24..0000000000 --- a/gst/selector/gstoutputselector.c +++ /dev/null @@ -1,519 +0,0 @@ -/* GStreamer - * Copyright (C) 2008 Nokia Corporation. (contact ) - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -/** - * SECTION:element-output-selector - * @see_also: #GstOutputSelector, #GstInputSelector - * - * Direct input stream to one out of N output pads. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include - -#include "gstoutputselector.h" - -GST_DEBUG_CATEGORY_STATIC (output_selector_debug); -#define GST_CAT_DEFAULT output_selector_debug - -static GstStaticPadTemplate gst_output_selector_sink_factory = -GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS_ANY); - -static GstStaticPadTemplate gst_output_selector_src_factory = -GST_STATIC_PAD_TEMPLATE ("src%d", - GST_PAD_SRC, - GST_PAD_REQUEST, - GST_STATIC_CAPS_ANY); - -enum -{ - PROP_0, - PROP_ACTIVE_PAD, - PROP_RESEND_LATEST, - PROP_LAST -}; - -#define _do_init(bla) \ -GST_DEBUG_CATEGORY_INIT (output_selector_debug, \ - "output-selector", 0, "An output stream selector element"); - -GST_BOILERPLATE_FULL (GstOutputSelector, gst_output_selector, GstElement, - GST_TYPE_ELEMENT, _do_init); - -static void gst_output_selector_dispose (GObject * object); -static void gst_output_selector_set_property (GObject * object, - guint prop_id, const GValue * value, GParamSpec * pspec); -static void gst_output_selector_get_property (GObject * object, - guint prop_id, GValue * value, GParamSpec * pspec); -static GstPad *gst_output_selector_request_new_pad (GstElement * element, - GstPadTemplate * templ, const gchar * unused); -static void gst_output_selector_release_pad (GstElement * element, - GstPad * pad); -static GstFlowReturn gst_output_selector_chain (GstPad * pad, GstBuffer * buf); -static GstFlowReturn gst_output_selector_buffer_alloc (GstPad * pad, - guint64 offset, guint size, GstCaps * caps, GstBuffer ** buf); -static GstStateChangeReturn gst_output_selector_change_state (GstElement * - element, GstStateChange transition); -static gboolean gst_output_selector_handle_sink_event (GstPad * pad, - GstEvent * event); - -static void -gst_output_selector_base_init (gpointer g_class) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); - - gst_element_class_set_details_simple (element_class, "Output selector", - "Generic", - "1-to-N output stream selectoring", - "Stefan Kost "); - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&gst_output_selector_sink_factory)); - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&gst_output_selector_src_factory)); -} - -static void -gst_output_selector_class_init (GstOutputSelectorClass * klass) -{ - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); - - parent_class = g_type_class_peek_parent (klass); - - gobject_class->dispose = gst_output_selector_dispose; - - gobject_class->set_property = - GST_DEBUG_FUNCPTR (gst_output_selector_set_property); - gobject_class->get_property = - GST_DEBUG_FUNCPTR (gst_output_selector_get_property); - - g_object_class_install_property (gobject_class, PROP_ACTIVE_PAD, - g_param_spec_object ("active-pad", "Active pad", - "Currently active src pad", GST_TYPE_PAD, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - g_object_class_install_property (gobject_class, PROP_RESEND_LATEST, - g_param_spec_boolean ("resend-latest", "Resend latest buffer", - "Resend latest buffer after a switch to a new pad", FALSE, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - gstelement_class->request_new_pad = - GST_DEBUG_FUNCPTR (gst_output_selector_request_new_pad); - gstelement_class->release_pad = - GST_DEBUG_FUNCPTR (gst_output_selector_release_pad); - - gstelement_class->change_state = gst_output_selector_change_state; -} - -static void -gst_output_selector_init (GstOutputSelector * sel, - GstOutputSelectorClass * g_class) -{ - sel->sinkpad = - gst_pad_new_from_static_template (&gst_output_selector_sink_factory, - "sink"); - gst_pad_set_chain_function (sel->sinkpad, - GST_DEBUG_FUNCPTR (gst_output_selector_chain)); - gst_pad_set_event_function (sel->sinkpad, - GST_DEBUG_FUNCPTR (gst_output_selector_handle_sink_event)); - gst_pad_set_bufferalloc_function (sel->sinkpad, - GST_DEBUG_FUNCPTR (gst_output_selector_buffer_alloc)); - /* - gst_pad_set_setcaps_function (sel->sinkpad, - GST_DEBUG_FUNCPTR (gst_pad_proxy_setcaps)); - gst_pad_set_getcaps_function (sel->sinkpad, - GST_DEBUG_FUNCPTR (gst_pad_proxy_getcaps)); - */ - - gst_element_add_pad (GST_ELEMENT (sel), sel->sinkpad); - - /* srcpad management */ - sel->active_srcpad = NULL; - sel->nb_srcpads = 0; - gst_segment_init (&sel->segment, GST_FORMAT_TIME); - sel->pending_srcpad = NULL; - - sel->resend_latest = FALSE; - sel->latest_buffer = NULL; -} - -static void -gst_output_selector_reset (GstOutputSelector * osel) -{ - if (osel->pending_srcpad != NULL) { - gst_object_unref (osel->pending_srcpad); - osel->pending_srcpad = NULL; - } - if (osel->latest_buffer != NULL) { - gst_buffer_unref (osel->latest_buffer); - osel->latest_buffer = NULL; - } - gst_segment_init (&osel->segment, GST_FORMAT_UNDEFINED); -} - -static void -gst_output_selector_dispose (GObject * object) -{ - GstOutputSelector *osel = GST_OUTPUT_SELECTOR (object); - - gst_output_selector_reset (osel); - - G_OBJECT_CLASS (parent_class)->dispose (object); -} - -static void -gst_output_selector_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstOutputSelector *sel = GST_OUTPUT_SELECTOR (object); - - switch (prop_id) { - case PROP_ACTIVE_PAD: - { - GstPad *next_pad; - - next_pad = g_value_get_object (value); - - GST_INFO_OBJECT (sel, "Activating pad %s:%s", - GST_DEBUG_PAD_NAME (next_pad)); - - GST_OBJECT_LOCK (object); - if (next_pad != sel->active_srcpad) { - /* switch to new srcpad in next chain run */ - if (sel->pending_srcpad != NULL) { - GST_INFO ("replacing pending switch"); - gst_object_unref (sel->pending_srcpad); - } - if (next_pad) - gst_object_ref (next_pad); - sel->pending_srcpad = next_pad; - } else { - GST_INFO ("pad already active"); - if (sel->pending_srcpad != NULL) { - gst_object_unref (sel->pending_srcpad); - sel->pending_srcpad = NULL; - } - } - GST_OBJECT_UNLOCK (object); - break; - } - case PROP_RESEND_LATEST:{ - sel->resend_latest = g_value_get_boolean (value); - break; - } - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_output_selector_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - GstOutputSelector *sel = GST_OUTPUT_SELECTOR (object); - - switch (prop_id) { - case PROP_ACTIVE_PAD: - GST_OBJECT_LOCK (object); - g_value_set_object (value, - sel->pending_srcpad ? sel->pending_srcpad : sel->active_srcpad); - GST_OBJECT_UNLOCK (object); - break; - case PROP_RESEND_LATEST:{ - GST_OBJECT_LOCK (object); - g_value_set_boolean (value, sel->resend_latest); - GST_OBJECT_UNLOCK (object); - break; - } - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static GstFlowReturn -gst_output_selector_buffer_alloc (GstPad * pad, guint64 offset, guint size, - GstCaps * caps, GstBuffer ** buf) -{ - GstOutputSelector *sel; - GstFlowReturn res; - GstPad *allocpad; - - sel = GST_OUTPUT_SELECTOR (GST_PAD_PARENT (pad)); - res = GST_FLOW_NOT_LINKED; - - GST_OBJECT_LOCK (sel); - allocpad = sel->pending_srcpad ? sel->pending_srcpad : sel->active_srcpad; - if (allocpad) { - /* if we had a previous pad we used for allocating a buffer, continue using - * it. */ - GST_DEBUG_OBJECT (sel, "using pad %s:%s for alloc", - GST_DEBUG_PAD_NAME (allocpad)); - gst_object_ref (allocpad); - GST_OBJECT_UNLOCK (sel); - - res = gst_pad_alloc_buffer (allocpad, offset, size, caps, buf); - gst_object_unref (allocpad); - - GST_OBJECT_LOCK (sel); - } else { - /* fallback case, allocate a buffer of our own, add pad caps. */ - GST_DEBUG_OBJECT (pad, "fallback buffer alloc"); - *buf = NULL; - res = GST_FLOW_OK; - } - GST_OBJECT_UNLOCK (sel); - - GST_DEBUG_OBJECT (sel, "buffer alloc finished: %s", gst_flow_get_name (res)); - - return res; -} - -static GstPad * -gst_output_selector_request_new_pad (GstElement * element, - GstPadTemplate * templ, const gchar * name) -{ - gchar *padname; - GstPad *srcpad; - GstOutputSelector *osel; - - osel = GST_OUTPUT_SELECTOR (element); - - GST_DEBUG_OBJECT (osel, "requesting pad"); - - GST_OBJECT_LOCK (osel); - padname = g_strdup_printf ("src%d", osel->nb_srcpads++); - srcpad = gst_pad_new_from_template (templ, padname); - GST_OBJECT_UNLOCK (osel); - - gst_pad_set_active (srcpad, TRUE); - gst_element_add_pad (GST_ELEMENT (osel), srcpad); - - /* Set the first requested src pad as active by default */ - if (osel->active_srcpad == NULL) { - osel->active_srcpad = srcpad; - } - g_free (padname); - - return srcpad; -} - -static void -gst_output_selector_release_pad (GstElement * element, GstPad * pad) -{ - GstOutputSelector *osel; - - osel = GST_OUTPUT_SELECTOR (element); - - GST_DEBUG_OBJECT (osel, "releasing pad"); - - gst_pad_set_active (pad, FALSE); - - gst_element_remove_pad (GST_ELEMENT_CAST (osel), pad); -} - -static gboolean -gst_output_selector_switch (GstOutputSelector * osel) -{ - gboolean res = FALSE; - GstEvent *ev = NULL; - GstSegment *seg = NULL; - gint64 start = 0, position = 0; - - /* Switch */ - GST_OBJECT_LOCK (GST_OBJECT (osel)); - GST_INFO ("switching to pad %" GST_PTR_FORMAT, osel->pending_srcpad); - if (gst_pad_is_linked (osel->pending_srcpad)) { - osel->active_srcpad = osel->pending_srcpad; - res = TRUE; - } - gst_object_unref (osel->pending_srcpad); - osel->pending_srcpad = NULL; - GST_OBJECT_UNLOCK (GST_OBJECT (osel)); - - /* Send NEWSEGMENT event and latest buffer if switching succeeded */ - if (res) { - /* Send NEWSEGMENT to the pad we are going to switch to */ - seg = &osel->segment; - /* If resending then mark newsegment start and position accordingly */ - if (osel->resend_latest && osel->latest_buffer && - GST_BUFFER_TIMESTAMP_IS_VALID (osel->latest_buffer)) { - start = position = GST_BUFFER_TIMESTAMP (osel->latest_buffer); - } else { - start = position = seg->last_stop; - } - ev = gst_event_new_new_segment (TRUE, seg->rate, - seg->format, start, seg->stop, position); - if (!gst_pad_push_event (osel->active_srcpad, ev)) { - GST_WARNING_OBJECT (osel, - "newsegment handling failed in %" GST_PTR_FORMAT, - osel->active_srcpad); - } - - /* Resend latest buffer to newly switched pad */ - if (osel->resend_latest && osel->latest_buffer) { - GST_INFO ("resending latest buffer"); - gst_pad_push (osel->active_srcpad, gst_buffer_ref (osel->latest_buffer)); - } - } else { - GST_WARNING_OBJECT (osel, "switch failed, pad not linked"); - } - - return res; -} - -static GstFlowReturn -gst_output_selector_chain (GstPad * pad, GstBuffer * buf) -{ - GstFlowReturn res; - GstOutputSelector *osel; - GstClockTime last_stop, duration; - - osel = GST_OUTPUT_SELECTOR (gst_pad_get_parent (pad)); - - /* - * The _switch function might push a buffer if 'resend-latest' is true. - * - * Elements/Applications (e.g. camerabin) might use pad probes to - * switch output-selector's active pad. If we simply switch and don't - * recheck any pending pad switch the following codepath could end - * up pushing a buffer on a non-active pad. This is bad. - * - * So we always should check the pending_srcpad before going further down - * the chain and pushing the new buffer - */ - while (osel->pending_srcpad) { - /* Do the switch */ - gst_output_selector_switch (osel); - } - - if (osel->latest_buffer) { - gst_buffer_unref (osel->latest_buffer); - osel->latest_buffer = NULL; - } - - if (osel->resend_latest) { - /* Keep reference to latest buffer to resend it after switch */ - osel->latest_buffer = gst_buffer_ref (buf); - } - - /* Keep track of last stop and use it in NEWSEGMENT start after - switching to a new src pad */ - last_stop = GST_BUFFER_TIMESTAMP (buf); - if (GST_CLOCK_TIME_IS_VALID (last_stop)) { - duration = GST_BUFFER_DURATION (buf); - if (GST_CLOCK_TIME_IS_VALID (duration)) { - last_stop += duration; - } - GST_LOG_OBJECT (osel, "setting last stop %" GST_TIME_FORMAT, - GST_TIME_ARGS (last_stop)); - gst_segment_set_last_stop (&osel->segment, osel->segment.format, last_stop); - } - - GST_LOG_OBJECT (osel, "pushing buffer to %" GST_PTR_FORMAT, - osel->active_srcpad); - res = gst_pad_push (osel->active_srcpad, buf); - gst_object_unref (osel); - - return res; -} - -static GstStateChangeReturn -gst_output_selector_change_state (GstElement * element, - GstStateChange transition) -{ - GstOutputSelector *sel; - GstStateChangeReturn result; - - sel = GST_OUTPUT_SELECTOR (element); - - switch (transition) { - case GST_STATE_CHANGE_READY_TO_PAUSED: - break; - default: - break; - } - - result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); - - switch (transition) { - case GST_STATE_CHANGE_PAUSED_TO_READY: - gst_output_selector_reset (sel); - break; - default: - break; - } - - return result; -} - -static gboolean -gst_output_selector_handle_sink_event (GstPad * pad, GstEvent * event) -{ - gboolean res = TRUE; - GstOutputSelector *sel; - GstPad *output_pad = NULL; - - sel = GST_OUTPUT_SELECTOR (gst_pad_get_parent (pad)); - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_NEWSEGMENT: - { - gboolean update; - GstFormat format; - gdouble rate, arate; - gint64 start, stop, time; - - gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format, - &start, &stop, &time); - - GST_DEBUG_OBJECT (sel, - "configured NEWSEGMENT update %d, rate %lf, applied rate %lf, " - "format %d, " "%" G_GINT64_FORMAT " -- %" G_GINT64_FORMAT ", time %" - G_GINT64_FORMAT, update, rate, arate, format, start, stop, time); - - gst_segment_set_newsegment_full (&sel->segment, update, - rate, arate, format, start, stop, time); - - /* Send newsegment to all src pads */ - gst_pad_event_default (pad, event); - break; - } - case GST_EVENT_EOS: - /* Send eos to all src pads */ - gst_pad_event_default (pad, event); - break; - default: - /* Send other events to pending or active src pad */ - output_pad = - sel->pending_srcpad ? sel->pending_srcpad : sel->active_srcpad; - res = gst_pad_push_event (output_pad, event); - break; - } - - gst_object_unref (sel); - - return res; -} diff --git a/gst/selector/gstoutputselector.h b/gst/selector/gstoutputselector.h deleted file mode 100644 index 5389d47354..0000000000 --- a/gst/selector/gstoutputselector.h +++ /dev/null @@ -1,66 +0,0 @@ -/* GStreamer - * Copyright (C) 2008 Nokia Corporation. (contact ) - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef __GST_OUTPUT_SELECTOR_H__ -#define __GST_OUTPUT_SELECTOR_H__ - -#include - -G_BEGIN_DECLS - -#define GST_TYPE_OUTPUT_SELECTOR \ - (gst_output_selector_get_type()) -#define GST_OUTPUT_SELECTOR(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_OUTPUT_SELECTOR, GstOutputSelector)) -#define GST_OUTPUT_SELECTOR_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_OUTPUT_SELECTOR, GstOutputSelectorClass)) -#define GST_IS_OUTPUT_SELECTOR(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_OUTPUT_SELECTOR)) -#define GST_IS_OUTPUT_SELECTOR_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_OUTPUT_SELECTOR)) - -typedef struct _GstOutputSelector GstOutputSelector; -typedef struct _GstOutputSelectorClass GstOutputSelectorClass; - -struct _GstOutputSelector { - GstElement element; - - GstPad *sinkpad; - - GstPad *active_srcpad; - GstPad *pending_srcpad; - guint nb_srcpads; - - GstSegment segment; - - /* resend latest buffer after switch */ - gboolean resend_latest; - GstBuffer *latest_buffer; - -}; - -struct _GstOutputSelectorClass { - GstElementClass parent_class; -}; - -GType gst_output_selector_get_type (void); - -G_END_DECLS - -#endif /* __GST_OUTPUT_SELECTOR_H__ */ diff --git a/gst/selector/gstselector-marshal.list b/gst/selector/gstselector-marshal.list deleted file mode 100644 index 1102f04cb7..0000000000 --- a/gst/selector/gstselector-marshal.list +++ /dev/null @@ -1,2 +0,0 @@ -INT64:VOID -VOID:OBJECT,INT64,INT64 diff --git a/gst/selector/gstselector.c b/gst/selector/gstselector.c deleted file mode 100644 index 008e457562..0000000000 --- a/gst/selector/gstselector.c +++ /dev/null @@ -1,44 +0,0 @@ -/* GStreamer - * Copyright (C) 2008 Nokia Corporation. (contact ) - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include - -#include "gstinputselector.h" -#include "gstoutputselector.h" - - -static gboolean -plugin_init (GstPlugin * plugin) -{ - - return gst_element_register (plugin, "input-selector", - GST_RANK_NONE, GST_TYPE_INPUT_SELECTOR) && - gst_element_register (plugin, "output-selector", - GST_RANK_NONE, GST_TYPE_OUTPUT_SELECTOR); -} - -GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, - GST_VERSION_MINOR, - "selector", - "input/output stream selector elements", - plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/gst/selector/selector.vcproj b/gst/selector/selector.vcproj deleted file mode 100644 index f28880d730..0000000000 --- a/gst/selector/selector.vcproj +++ /dev/null @@ -1,148 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/tests/check/Makefile.am b/tests/check/Makefile.am index 45678f384a..fc2e25f96e 100644 --- a/tests/check/Makefile.am +++ b/tests/check/Makefile.am @@ -162,7 +162,6 @@ check_PROGRAMS = \ $(check_jifmux) \ elements/jpegparse \ elements/qtmux \ - elements/selector \ elements/mxfdemux \ elements/mxfmux \ elements/id3mux \ diff --git a/tests/check/elements/.gitignore b/tests/check/elements/.gitignore index ec35d9b796..60d4386473 100644 --- a/tests/check/elements/.gitignore +++ b/tests/check/elements/.gitignore @@ -34,7 +34,6 @@ rganalysis rglimiter rgvolume rtpmux -selector spectrum timidity y4menc diff --git a/tests/check/elements/selector.c b/tests/check/elements/selector.c deleted file mode 100644 index 56d2840ec1..0000000000 --- a/tests/check/elements/selector.c +++ /dev/null @@ -1,385 +0,0 @@ -/* GStreamer - * - * Unit test for selector plugin - * Copyright (C) 2008 Nokia Corporation. (contact ) - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include - -#define NUM_SELECTOR_PADS 4 -#define NUM_INPUT_BUFFERS 4 // buffers to send per each selector pad - -static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS_ANY); -static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", - GST_PAD_SRC, - GST_PAD_ALWAYS, - GST_STATIC_CAPS_ANY); - -/* Data probe cb to drop everything but count buffers and events */ -static gboolean -probe_cb (GstPad * pad, GstMiniObject * obj, gpointer user_data) -{ - gint count = 0; - const gchar *count_type = NULL; - - GST_LOG_OBJECT (pad, "got data"); - - if (GST_IS_BUFFER (obj)) { - count_type = "buffer_count"; - } else if (GST_IS_EVENT (obj)) { - count_type = "event_count"; - } else { - g_assert_not_reached (); - } - - /* increment and store count */ - count = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (pad), count_type)); - count++; - g_object_set_data (G_OBJECT (pad), count_type, GINT_TO_POINTER (count)); - - /* drop everything */ - return FALSE; -} - -/* Create and link output pad: selector:src%d ! output_pad */ -static GstPad * -setup_output_pad (GstElement * element) -{ - GstPad *srcpad = NULL, *output_pad = NULL; - gulong probe_id = 0; - - /* create output_pad */ - output_pad = gst_pad_new_from_static_template (&sinktemplate, "sink"); - fail_if (output_pad == NULL, "Could not create a output_pad"); - - /* add probe */ - probe_id = gst_pad_add_data_probe (output_pad, G_CALLBACK (probe_cb), NULL); - g_object_set_data (G_OBJECT (output_pad), "probe_id", - GINT_TO_POINTER (probe_id)); - - /* request src pad */ - srcpad = gst_element_get_request_pad (element, "src%d"); - fail_if (srcpad == NULL, "Could not get source pad from %s", - GST_ELEMENT_NAME (element)); - - /* link pads and activate */ - fail_unless (gst_pad_link (srcpad, output_pad) == GST_PAD_LINK_OK, - "Could not link %s source and output pad", GST_ELEMENT_NAME (element)); - - gst_pad_set_active (output_pad, TRUE); - - GST_DEBUG_OBJECT (output_pad, "set up %" GST_PTR_FORMAT " ! %" GST_PTR_FORMAT, - srcpad, output_pad); - - gst_object_unref (srcpad); - ASSERT_OBJECT_REFCOUNT (srcpad, "srcpad", 1); - - return output_pad; -} - -/* Clean up output/input pad and respective selector request pad */ -static void -cleanup_pad (GstPad * pad, GstElement * element) -{ - GstPad *selpad = NULL; - guint probe_id = 0; - - fail_if (pad == NULL, "pad doesn't exist"); - - /* remove probe if necessary */ - probe_id = GPOINTER_TO_INT (g_object_get_data (G_OBJECT (pad), "probe_id")); - if (probe_id) - gst_pad_remove_data_probe (pad, probe_id); - - /* unlink */ - selpad = gst_pad_get_peer (pad); - if (GST_PAD_DIRECTION (selpad) == GST_PAD_SRC) { - gst_pad_unlink (selpad, pad); - } else { - gst_pad_unlink (pad, selpad); - } - - /* caps could have been set, make sure they get unset */ - gst_pad_set_caps (pad, NULL); - - GST_DEBUG_OBJECT (pad, "clean up %" GST_PTR_FORMAT " and %" GST_PTR_FORMAT, - selpad, pad); - - /* cleanup the pad */ - gst_pad_set_active (pad, FALSE); - ASSERT_OBJECT_REFCOUNT (pad, "pad", 1); - gst_object_unref (pad); - - /* cleanup selector pad, reffed by this function (_get_peer) and creator */ - gst_element_release_request_pad (element, selpad); - gst_object_unref (selpad); -} - -/* Duplicate and push given buffer many times to all input_pads */ -static void -push_input_buffers (GList * input_pads, GstBuffer * buf, gint num_buffers) -{ - GstBuffer *buf_in = NULL; - GList *l = input_pads; - GstPad *input_pad; - gint i = 0; - - while (l != NULL) { - input_pad = l->data; - GST_DEBUG_OBJECT (input_pad, "pushing %d buffers to %" GST_PTR_FORMAT, - num_buffers, input_pad); - for (i = 0; i < num_buffers; i++) { - buf_in = gst_buffer_copy (buf); - fail_unless (gst_pad_push (input_pad, buf_in) == GST_FLOW_OK, - "pushing buffer failed"); - } - l = g_list_next (l); - } -} - -/* Check that received buffers count match to expected buffers */ -static void -count_output_buffers (GList * output_pads, gint expected_buffers) -{ - gint count = 0; - GList *l = output_pads; - GstPad *output_pad = NULL; - - while (l != NULL) { - output_pad = l->data; - count = - GPOINTER_TO_INT (g_object_get_data (G_OBJECT (output_pad), - "buffer_count")); - GST_DEBUG_OBJECT (output_pad, "received %d buffers", count); - fail_unless (count == expected_buffers, - "received/expected buffer count doesn't match %d/%d", count, - expected_buffers); - count = - GPOINTER_TO_INT (g_object_get_data (G_OBJECT (output_pad), - "event_count")); - GST_DEBUG_OBJECT (output_pad, "received %d events", count); - l = g_list_next (l); - } -} - -/* Set selector active pad */ -static void -selector_set_active_pad (GstElement * elem, GstPad * selpad) -{ - gchar *padname = NULL; - - if (selpad) { - padname = gst_pad_get_name (selpad); - } - - g_object_set (G_OBJECT (elem), "active-pad", selpad, NULL); - GST_DEBUG_OBJECT (elem, "activated selector pad: %s", GST_STR_NULL (padname)); - g_free (padname); -} - -/* Push buffers and switch for each selector pad */ -static void -push_switched_buffers (GList * input_pads, - GstElement * elem, GList * peer_pads, gint num_buffers) -{ - GstBuffer *buf = NULL; - GstCaps *caps = NULL; - GList *l = peer_pads; - GstPad *selpad = NULL; - - /* setup dummy buffer */ - caps = gst_caps_from_string ("application/x-unknown"); - buf = gst_buffer_new_and_alloc (1); - gst_buffer_set_caps (buf, caps); - gst_caps_unref (caps); - - while (l != NULL) { - /* set selector pad */ - selpad = gst_pad_get_peer (GST_PAD (l->data)); - selector_set_active_pad (elem, selpad); - if (selpad) { - gst_object_unref (selpad); - } - /* push buffers */ - push_input_buffers (input_pads, buf, num_buffers); - /* switch to next selector pad */ - l = g_list_next (l); - } - - /* cleanup buffer */ - gst_buffer_unref (buf); -} - -/* Create output-selector with given number of src pads and switch - given number of input buffers to each src pad. - */ -static void -run_output_selector_buffer_count (gint num_output_pads, - gint num_buffers_per_output) -{ - /* setup input_pad ! selector ! output_pads */ - gint i = 0; - GList *output_pads = NULL, *input_pads = NULL; - GstElement *sel = gst_check_setup_element ("output-selector"); - GstPad *input_pad = gst_check_setup_src_pad (sel, &srctemplate, NULL); - - input_pads = g_list_append (input_pads, input_pad); - gst_pad_set_active (input_pad, TRUE); - for (i = 0; i < num_output_pads; i++) { - output_pads = g_list_append (output_pads, setup_output_pad (sel)); - } - - /* run the test */ - fail_unless (gst_element_set_state (sel, - GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, - "could not set to playing"); - push_switched_buffers (input_pads, sel, output_pads, num_buffers_per_output); - count_output_buffers (output_pads, num_buffers_per_output); - fail_unless (gst_element_set_state (sel, - GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null"); - - /* cleanup input_pad, selector and output_pads */ - gst_pad_set_active (input_pad, FALSE); - gst_check_teardown_src_pad (sel); - g_list_foreach (output_pads, (GFunc) cleanup_pad, sel); - g_list_free (output_pads); - g_list_free (input_pads); - gst_check_teardown_element (sel); -} - -/* Create and link input pad: input_pad ! selector:sink%d */ -static GstPad * -setup_input_pad (GstElement * element) -{ - GstPad *sinkpad = NULL, *input_pad = NULL; - - /* create input_pad */ - input_pad = gst_pad_new_from_static_template (&srctemplate, "src"); - fail_if (input_pad == NULL, "Could not create a input_pad"); - - /* request sink pad */ - sinkpad = gst_element_get_request_pad (element, "sink%d"); - fail_if (sinkpad == NULL, "Could not get sink pad from %s", - GST_ELEMENT_NAME (element)); - - /* link pads and activate */ - fail_unless (gst_pad_link (input_pad, sinkpad) == GST_PAD_LINK_OK, - "Could not link input_pad and %s sink", GST_ELEMENT_NAME (element)); - - gst_pad_set_active (input_pad, TRUE); - - GST_DEBUG_OBJECT (input_pad, "set up %" GST_PTR_FORMAT " ! %" GST_PTR_FORMAT, - input_pad, sinkpad); - - gst_object_unref (sinkpad); - ASSERT_OBJECT_REFCOUNT (sinkpad, "sinkpad", 1); - - return input_pad; -} - -/* Create input-selector with given number of sink pads and switch - given number of input buffers to each sink pad. - */ -static void -run_input_selector_buffer_count (gint num_input_pads, - gint num_buffers_per_input) -{ - /* set up input_pads ! selector ! output_pad */ - gint i = 0, probe_id = 0; - GList *input_pads = NULL, *output_pads = NULL; - GstElement *sel = gst_check_setup_element ("input-selector"); - GstPad *output_pad = gst_check_setup_sink_pad (sel, &sinktemplate, NULL); - - output_pads = g_list_append (output_pads, output_pad); - gst_pad_set_active (output_pad, TRUE); - for (i = 0; i < num_input_pads; i++) { - input_pads = g_list_append (input_pads, setup_input_pad (sel)); - } - /* add probe */ - probe_id = gst_pad_add_data_probe (output_pad, G_CALLBACK (probe_cb), NULL); - g_object_set_data (G_OBJECT (output_pad), "probe_id", - GINT_TO_POINTER (probe_id)); - - /* run the test */ - fail_unless (gst_element_set_state (sel, - GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS, - "could not set to playing"); - push_switched_buffers (input_pads, sel, input_pads, num_buffers_per_input); - count_output_buffers (output_pads, (num_input_pads * num_buffers_per_input)); - fail_unless (gst_element_set_state (sel, - GST_STATE_NULL) == GST_STATE_CHANGE_SUCCESS, "could not set to null"); - - /* clean up */ - gst_pad_remove_data_probe (output_pad, probe_id); - gst_pad_set_active (output_pad, FALSE); - gst_check_teardown_sink_pad (sel); - GST_DEBUG ("setting selector pad to NULL"); - selector_set_active_pad (sel, NULL); // unref input-selector active pad - g_list_foreach (input_pads, (GFunc) cleanup_pad, sel); - g_list_free (input_pads); - g_list_free (output_pads); - gst_check_teardown_element (sel); -} - -/* Push buffers to input pad and check the - amount of buffers arrived to output pads */ -GST_START_TEST (test_output_selector_buffer_count); -{ - gint i, j; - - for (i = 0; i < NUM_SELECTOR_PADS; i++) { - for (j = 0; j < NUM_INPUT_BUFFERS; j++) { - run_output_selector_buffer_count (i, j); - } - } -} - -GST_END_TEST; - -/* Push buffers to input pads and check the - amount of buffers arrived to output pad */ -GST_START_TEST (test_input_selector_buffer_count); -{ - gint i, j; - - for (i = 0; i < NUM_SELECTOR_PADS; i++) { - for (j = 0; j < NUM_INPUT_BUFFERS; j++) { - run_input_selector_buffer_count (i, j); - } - } -} - -GST_END_TEST; - -static Suite * -selector_suite (void) -{ - Suite *s = suite_create ("selector"); - TCase *tc_chain = tcase_create ("general"); - - suite_add_tcase (s, tc_chain); - tcase_add_test (tc_chain, test_output_selector_buffer_count); - tcase_add_test (tc_chain, test_input_selector_buffer_count); - - return s; -} - -GST_CHECK_MAIN (selector); diff --git a/tests/examples/Makefile.am b/tests/examples/Makefile.am index dbd11934c9..4a158d951a 100644 --- a/tests/examples/Makefile.am +++ b/tests/examples/Makefile.am @@ -21,5 +21,7 @@ else CAMERABIN2= endif -SUBDIRS= $(DIRECTFB_DIR) $(GTK_EXAMPLES) $(JACK_EXAMPLES) switch -DIST_SUBDIRS= camerabin $(CAMERABIN2) directfb jack mxf scaletempo switch +SUBDIRS= $(DIRECTFB_DIR) $(GTK_EXAMPLES) $(JACK_EXAMPLES) +DIST_SUBDIRS= camerabin $(CAMERABIN2) directfb jack mxf scaletempo + +include $(top_srcdir)/common/parallel-subdirs.mak diff --git a/tests/examples/switch/.gitignore b/tests/examples/switch/.gitignore deleted file mode 100644 index 7893c4354d..0000000000 --- a/tests/examples/switch/.gitignore +++ /dev/null @@ -1 +0,0 @@ -switcher diff --git a/tests/examples/switch/Makefile.am b/tests/examples/switch/Makefile.am deleted file mode 100644 index 9a70604857..0000000000 --- a/tests/examples/switch/Makefile.am +++ /dev/null @@ -1,7 +0,0 @@ - -noinst_PROGRAMS = switcher - -switcher_SOURCES = switcher.c -switcher_CFLAGS = $(GST_CFLAGS) -switcher_LDFLAGS = $(GST_LIBS) - diff --git a/tests/examples/switch/switcher.c b/tests/examples/switch/switcher.c deleted file mode 100644 index 4742c03376..0000000000 --- a/tests/examples/switch/switcher.c +++ /dev/null @@ -1,162 +0,0 @@ -/* GStreamer - * Copyright (C) 2003 Julien Moutte - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -#include -#include - - -#include - -static GMainLoop *loop = NULL; - -static gboolean -my_bus_callback (GstBus * bus, GstMessage * message, gpointer data) -{ - g_print ("Got %s message\n", GST_MESSAGE_TYPE_NAME (message)); - - switch (GST_MESSAGE_TYPE (message)) { - case GST_MESSAGE_ERROR:{ - GError *err; - gchar *debug; - - gst_message_parse_error (message, &err, &debug); - g_print ("Error: %s\n", err->message); - g_error_free (err); - g_free (debug); - - g_main_loop_quit (loop); - break; - } - case GST_MESSAGE_EOS: - /* end-of-stream */ - g_main_loop_quit (loop); - break; - default: - /* unhandled message */ - break; - } - - /* we want to be notified again the next time there is a message - * on the bus, so returning TRUE (FALSE means we want to stop watching - * for messages on the bus and our callback should not be called again) - */ - return TRUE; -} - - - -static gboolean -switch_timer (GstElement * video_switch) -{ - gint nb_sources; - GstPad *active_pad, *new_pad; - gchar *active_name; - - g_message ("switching"); - g_object_get (G_OBJECT (video_switch), "n-pads", &nb_sources, NULL); - g_object_get (G_OBJECT (video_switch), "active-pad", &active_pad, NULL); - - active_name = gst_pad_get_name (active_pad); - if (strcmp (active_name, "sink0") == 0) { - new_pad = gst_element_get_static_pad (video_switch, "sink1"); - } else { - new_pad = gst_element_get_static_pad (video_switch, "sink0"); - } - g_object_set (G_OBJECT (video_switch), "active-pad", new_pad, NULL); - g_free (active_name); - gst_object_unref (new_pad); - - g_message ("current number of sources : %d, active source %s", - nb_sources, gst_pad_get_name (active_pad)); - - return (GST_STATE (GST_ELEMENT (video_switch)) == GST_STATE_PLAYING); -} - -static void -last_message_received (GObject * segment) -{ - gchar *last_message; - - g_object_get (segment, "last_message", &last_message, NULL); - g_print ("last-message: %s\n", last_message); - g_free (last_message); -} - -int -main (int argc, char *argv[]) -{ - GstElement *pipeline, *src1, *src2, *video_switch, *video_sink, *segment; - GstElement *sink1_sync, *sink2_sync, *capsfilter; - GstBus *bus; - - /* Initing GStreamer library */ - gst_init (&argc, &argv); - - loop = g_main_loop_new (NULL, FALSE); - - pipeline = gst_pipeline_new ("pipeline"); - src1 = gst_element_factory_make ("videotestsrc", "src1"); - g_object_set (G_OBJECT (src1), "pattern", 0, NULL); - src2 = gst_element_factory_make ("videotestsrc", "src2"); - g_object_set (G_OBJECT (src2), "pattern", 1, NULL); - capsfilter = gst_element_factory_make ("capsfilter", "caps0"); - g_object_set (G_OBJECT (capsfilter), "caps", - gst_caps_from_string ("video/x-raw-rgb,width=640,height=480"), NULL); - video_switch = gst_element_factory_make ("input-selector", "video_switch"); - segment = gst_element_factory_make ("identity", "identity-segment"); - g_object_set (G_OBJECT (segment), "silent", TRUE, NULL); - g_signal_connect (G_OBJECT (segment), "notify::last-message", - G_CALLBACK (last_message_received), segment); - g_object_set (G_OBJECT (segment), "single-segment", TRUE, NULL); - video_sink = gst_element_factory_make ("ximagesink", "video_sink"); - g_object_set (G_OBJECT (video_sink), "sync", FALSE, NULL); - sink1_sync = gst_element_factory_make ("identity", "sink0_sync"); - g_object_set (G_OBJECT (sink1_sync), "sync", TRUE, NULL); - sink2_sync = gst_element_factory_make ("identity", "sink1_sync"); - g_object_set (G_OBJECT (sink2_sync), "sync", TRUE, NULL); - gst_bin_add_many (GST_BIN (pipeline), src1, src2, segment, video_switch, - video_sink, sink1_sync, sink2_sync, capsfilter, NULL); - gst_element_link (src1, sink1_sync); - gst_element_link (sink1_sync, video_switch); - gst_element_link (src2, capsfilter); - gst_element_link (capsfilter, sink2_sync); - gst_element_link (sink2_sync, video_switch); - gst_element_link (video_switch, segment); - gst_element_link (segment, /*scaler); - gst_element_link (scaler, */ video_sink); - - bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); - gst_bus_add_watch (bus, my_bus_callback, NULL); - gst_object_unref (bus); - gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_PLAYING); - - g_timeout_add (200, (GSourceFunc) switch_timer, video_switch); - - g_main_loop_run (loop); - - gst_element_set_state (GST_ELEMENT (pipeline), GST_STATE_READY); - - /* unref */ - gst_object_unref (GST_OBJECT (pipeline)); - - exit (0); -} diff --git a/tests/icles/.gitignore b/tests/icles/.gitignore index 94f42ab6f6..dc69c10760 100644 --- a/tests/icles/.gitignore +++ b/tests/icles/.gitignore @@ -1,6 +1,5 @@ equalizer-test metadata_editor -output-selector-test pitch-test cog-test cog-test.c diff --git a/tests/icles/Makefile.am b/tests/icles/Makefile.am index 6ac25fd296..c175aec7f2 100644 --- a/tests/icles/Makefile.am +++ b/tests/icles/Makefile.am @@ -30,12 +30,6 @@ equalizer_test_CFLAGS = $(GST_CFLAGS) equalizer_test_LDADD = $(GST_LIBS) equalizer_test_LDFLAGS = $(GST_PLUGIN_LDFLAGS) -output_selector_test_SOURCES = output-selector-test.c -output_selector_test_CFLAGS = $(GST_CFLAGS) -output_selector_test_LDADD = $(GST_LIBS) -output_selector_test_LDFLAGS = $(GST_PLUGIN_LDFLAGS) - - noinst_PROGRAMS = $(GST_SOUNDTOUCH_TESTS) $(GST_METADATA_TESTS) \ - equalizer-test output-selector-test + equalizer-test diff --git a/tests/icles/output-selector-test.c b/tests/icles/output-selector-test.c deleted file mode 100644 index 24ad2835dc..0000000000 --- a/tests/icles/output-selector-test.c +++ /dev/null @@ -1,173 +0,0 @@ -#include - -#define SWITCH_TIMEOUT 1000 -#define NUM_VIDEO_BUFFERS 500 - -static GMainLoop *loop; - -/* Output selector src pads */ -static GstPad *osel_src1 = NULL; -static GstPad *osel_src2 = NULL; - -static gboolean -my_bus_callback (GstBus * bus, GstMessage * message, gpointer data) -{ - g_print ("Got %s message\n", GST_MESSAGE_TYPE_NAME (message)); - - switch (GST_MESSAGE_TYPE (message)) { - case GST_MESSAGE_ERROR:{ - GError *err; - gchar *debug; - - gst_message_parse_error (message, &err, &debug); - g_print ("Error: %s\n", err->message); - g_error_free (err); - g_free (debug); - - g_main_loop_quit (loop); - break; - } - case GST_MESSAGE_EOS: - /* end-of-stream */ - g_main_loop_quit (loop); - break; - default: - /* unhandled message */ - break; - } - /* we want to be notified again the next time there is a message - * on the bus, so returning TRUE (FALSE means we want to stop watching - * for messages on the bus and our callback should not be called again) - */ - return TRUE; -} - -static gboolean -switch_cb (gpointer user_data) -{ - GstElement *sel = GST_ELEMENT (user_data); - GstPad *old_pad, *new_pad = NULL; - - g_object_get (G_OBJECT (sel), "active-pad", &old_pad, NULL); - - if (old_pad == osel_src1) - new_pad = osel_src2; - else - new_pad = osel_src1; - - g_object_set (G_OBJECT (sel), "active-pad", new_pad, NULL); - - g_print ("switched from %s:%s to %s:%s\n", GST_DEBUG_PAD_NAME (old_pad), - GST_DEBUG_PAD_NAME (new_pad)); - - gst_object_unref (old_pad); - - return TRUE; - -} - -static void -on_bin_element_added (GstBin * bin, GstElement * element, gpointer user_data) -{ - g_object_set (G_OBJECT (element), "sync", FALSE, "async", FALSE, NULL); -} - -gint -main (gint argc, gchar * argv[]) -{ - GstElement *pipeline, *src, *toverlay, *osel, *sink1, *sink2, *c1, *c2, *c0; - GstPad *sinkpad; - GstBus *bus; - - /* init GStreamer */ - gst_init (&argc, &argv); - loop = g_main_loop_new (NULL, FALSE); - - /* create elements */ - pipeline = gst_element_factory_make ("pipeline", "pipeline"); - src = gst_element_factory_make ("videotestsrc", "src"); - c0 = gst_element_factory_make ("ffmpegcolorspace", NULL); - toverlay = gst_element_factory_make ("timeoverlay", "timeoverlay"); - osel = gst_element_factory_make ("output-selector", "osel"); - c1 = gst_element_factory_make ("ffmpegcolorspace", NULL); - c2 = gst_element_factory_make ("ffmpegcolorspace", NULL); - sink1 = gst_element_factory_make ("autovideosink", "sink1"); - sink2 = gst_element_factory_make ("autovideosink", "sink2"); - - if (!pipeline || !src || !c0 || !toverlay || !osel || !c1 || !c2 || !sink1 || - !sink2) { - g_print ("missing element\n"); - return -1; - } - - /* add them to bin */ - gst_bin_add_many (GST_BIN (pipeline), src, c0, toverlay, osel, c1, sink1, c2, - sink2, NULL); - - /* set properties */ - g_object_set (G_OBJECT (src), "is-live", TRUE, NULL); - g_object_set (G_OBJECT (src), "do-timestamp", TRUE, NULL); - g_object_set (G_OBJECT (src), "num-buffers", NUM_VIDEO_BUFFERS, NULL); - g_object_set (G_OBJECT (osel), "resend-latest", TRUE, NULL); - - /* handle deferred properties */ - g_signal_connect (G_OBJECT (sink1), "element-added", - G_CALLBACK (on_bin_element_added), NULL); - g_signal_connect (G_OBJECT (sink2), "element-added", - G_CALLBACK (on_bin_element_added), NULL); - - /* link src ! timeoverlay ! osel */ - if (!gst_element_link_many (src, c0, toverlay, osel, NULL)) { - g_print ("linking failed\n"); - return -1; - } - - /* link output 1 */ - sinkpad = gst_element_get_static_pad (c1, "sink"); - osel_src1 = gst_element_get_request_pad (osel, "src%d"); - if (gst_pad_link (osel_src1, sinkpad) != GST_PAD_LINK_OK) { - g_print ("linking output 1 converter failed\n"); - return -1; - } - gst_object_unref (sinkpad); - - if (!gst_element_link (c1, sink1)) { - g_print ("linking output 1 failed\n"); - return -1; - } - - /* link output 2 */ - sinkpad = gst_element_get_static_pad (c2, "sink"); - osel_src2 = gst_element_get_request_pad (osel, "src%d"); - if (gst_pad_link (osel_src2, sinkpad) != GST_PAD_LINK_OK) { - g_print ("linking output 2 converter failed\n"); - return -1; - } - gst_object_unref (sinkpad); - - if (!gst_element_link (c2, sink2)) { - g_print ("linking output 2 failed\n"); - return -1; - } - - /* add switch callback */ - g_timeout_add (SWITCH_TIMEOUT, switch_cb, osel); - - /* change to playing */ - bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); - gst_bus_add_watch (bus, my_bus_callback, loop); - gst_object_unref (bus); - - gst_element_set_state (pipeline, GST_STATE_PLAYING); - - /* now run */ - g_main_loop_run (loop); - - /* also clean up */ - gst_element_set_state (pipeline, GST_STATE_NULL); - gst_element_release_request_pad (osel, osel_src1); - gst_element_release_request_pad (osel, osel_src2); - gst_object_unref (GST_OBJECT (pipeline)); - - return 0; -} From 0073550300ba3f146f52ca59472c497cd1fc22e0 Mon Sep 17 00:00:00 2001 From: David Schleef Date: Thu, 30 Dec 2010 18:02:06 -0800 Subject: [PATCH 225/448] dataurisrc: use g_ascii_strcasecmp() --- gst/dataurisrc/gstdataurisrc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gst/dataurisrc/gstdataurisrc.c b/gst/dataurisrc/gstdataurisrc.c index 17ebf4b104..446ca84078 100644 --- a/gst/dataurisrc/gstdataurisrc.c +++ b/gst/dataurisrc/gstdataurisrc.c @@ -415,8 +415,8 @@ gst_data_uri_src_set_uri (GstURIHandler * handler, const gchar * uri) /* Convert to UTF8 */ if (strcmp ("text/plain", mimetype) == 0 && - charset && strcasecmp ("US-ASCII", charset) != 0 - && strcasecmp ("UTF-8", charset) != 0) { + charset && g_ascii_strcasecmp ("US-ASCII", charset) != 0 + && g_ascii_strcasecmp ("UTF-8", charset) != 0) { gsize read; gsize written; gchar *old_data = (gchar *) GST_BUFFER_DATA (src->buffer); From 5fed7a264c4c796c8e8e7ecc4e2ae893ecae111d Mon Sep 17 00:00:00 2001 From: David Schleef Date: Thu, 30 Dec 2010 18:19:47 -0800 Subject: [PATCH 226/448] dtmf: reindent --- gst/dtmf/tone_detect.c | 749 ++++++++++++++++++++--------------------- 1 file changed, 366 insertions(+), 383 deletions(-) diff --git a/gst/dtmf/tone_detect.c b/gst/dtmf/tone_detect.c index c3b92ba7d4..d8f1df16e1 100644 --- a/gst/dtmf/tone_detect.c +++ b/gst/dtmf/tone_detect.c @@ -60,12 +60,12 @@ #define DTMF_THRESHOLD 8.0e7 #define FAX_THRESHOLD 8.0e7 #define FAX_2ND_HARMONIC 2.0 /* 4dB */ -#define DTMF_NORMAL_TWIST 6.3 /* 8dB */ +#define DTMF_NORMAL_TWIST 6.3 /* 8dB */ #define DTMF_REVERSE_TWIST ((isradio) ? 4.0 : 2.5) /* 4dB normal */ -#define DTMF_RELATIVE_PEAK_ROW 6.3 /* 8dB */ -#define DTMF_RELATIVE_PEAK_COL 6.3 /* 8dB */ +#define DTMF_RELATIVE_PEAK_ROW 6.3 /* 8dB */ +#define DTMF_RELATIVE_PEAK_COL 6.3 /* 8dB */ #define DTMF_2ND_HARMONIC_ROW ((isradio) ? 1.7 : 2.5) /* 4dB normal */ -#define DTMF_2ND_HARMONIC_COL 63.1 /* 18dB */ +#define DTMF_2ND_HARMONIC_COL 63.1 /* 18dB */ static tone_detection_descriptor_t dtmf_detect_row[4]; static tone_detection_descriptor_t dtmf_detect_col[4]; @@ -74,443 +74,426 @@ static tone_detection_descriptor_t dtmf_detect_col_2nd[4]; static tone_detection_descriptor_t fax_detect; static tone_detection_descriptor_t fax_detect_2nd; -static float dtmf_row[] = -{ - 697.0, 770.0, 852.0, 941.0 +static float dtmf_row[] = { + 697.0, 770.0, 852.0, 941.0 }; -static float dtmf_col[] = -{ - 1209.0, 1336.0, 1477.0, 1633.0 + +static float dtmf_col[] = { + 1209.0, 1336.0, 1477.0, 1633.0 }; static float fax_freq = 1100.0; static char dtmf_positions[] = "123A" "456B" "789C" "*0#D"; -static void goertzel_init(goertzel_state_t *s, - tone_detection_descriptor_t *t) +static void +goertzel_init (goertzel_state_t * s, tone_detection_descriptor_t * t) { - s->v2 = - s->v3 = 0.0; - s->fac = t->fac; + s->v2 = s->v3 = 0.0; + s->fac = t->fac; } + /*- End of function --------------------------------------------------------*/ #if defined(USE_3DNOW) -static inline void _dtmf_goertzel_update(goertzel_state_t *s, - float x[], - int samples) +static inline void +_dtmf_goertzel_update (goertzel_state_t * s, float x[], int samples) { - int n; - float v; - int i; - float vv[16]; + int n; + float v; + int i; + float vv[16]; - vv[4] = s[0].v2; - vv[5] = s[1].v2; - vv[6] = s[2].v2; - vv[7] = s[3].v2; - vv[8] = s[0].v3; - vv[9] = s[1].v3; - vv[10] = s[2].v3; - vv[11] = s[3].v3; - vv[12] = s[0].fac; - vv[13] = s[1].fac; - vv[14] = s[2].fac; - vv[15] = s[3].fac; + vv[4] = s[0].v2; + vv[5] = s[1].v2; + vv[6] = s[2].v2; + vv[7] = s[3].v2; + vv[8] = s[0].v3; + vv[9] = s[1].v3; + vv[10] = s[2].v3; + vv[11] = s[3].v3; + vv[12] = s[0].fac; + vv[13] = s[1].fac; + vv[14] = s[2].fac; + vv[15] = s[3].fac; - //v1 = s->v2; - //s->v2 = s->v3; - //s->v3 = s->fac*s->v2 - v1 + x[0]; + //v1 = s->v2; + //s->v2 = s->v3; + //s->v3 = s->fac*s->v2 - v1 + x[0]; - __asm__ __volatile__ ( - " femms;\n" + __asm__ __volatile__ (" femms;\n" + " movq 16(%%edx),%%mm2;\n" + " movq 24(%%edx),%%mm3;\n" + " movq 32(%%edx),%%mm4;\n" + " movq 40(%%edx),%%mm5;\n" + " movq 48(%%edx),%%mm6;\n" + " movq 56(%%edx),%%mm7;\n" + " jmp 1f;\n" + " .align 32;\n" + " 1: ;\n" + " prefetch (%%eax);\n" + " movq %%mm3,%%mm1;\n" + " movq %%mm2,%%mm0;\n" + " movq %%mm5,%%mm3;\n" + " movq %%mm4,%%mm2;\n" + " pfmul %%mm7,%%mm5;\n" + " pfmul %%mm6,%%mm4;\n" + " pfsub %%mm1,%%mm5;\n" + " pfsub %%mm0,%%mm4;\n" + " movq (%%eax),%%mm0;\n" + " movq %%mm0,%%mm1;\n" + " punpckldq %%mm0,%%mm1;\n" + " add $4,%%eax;\n" + " pfadd %%mm1,%%mm5;\n" + " pfadd %%mm1,%%mm4;\n" + " dec %%ecx;\n" + " jnz 1b;\n" + " movq %%mm2,16(%%edx);\n" + " movq %%mm3,24(%%edx);\n" + " movq %%mm4,32(%%edx);\n" + " movq %%mm5,40(%%edx);\n" + " femms;\n"::"c" (samples), "a" (x), "d" (vv) + :"memory", "eax", "ecx"); - " movq 16(%%edx),%%mm2;\n" - " movq 24(%%edx),%%mm3;\n" - " movq 32(%%edx),%%mm4;\n" - " movq 40(%%edx),%%mm5;\n" - " movq 48(%%edx),%%mm6;\n" - " movq 56(%%edx),%%mm7;\n" - - " jmp 1f;\n" - " .align 32;\n" - - " 1: ;\n" - " prefetch (%%eax);\n" - " movq %%mm3,%%mm1;\n" - " movq %%mm2,%%mm0;\n" - " movq %%mm5,%%mm3;\n" - " movq %%mm4,%%mm2;\n" - - " pfmul %%mm7,%%mm5;\n" - " pfmul %%mm6,%%mm4;\n" - " pfsub %%mm1,%%mm5;\n" - " pfsub %%mm0,%%mm4;\n" - - " movq (%%eax),%%mm0;\n" - " movq %%mm0,%%mm1;\n" - " punpckldq %%mm0,%%mm1;\n" - " add $4,%%eax;\n" - " pfadd %%mm1,%%mm5;\n" - " pfadd %%mm1,%%mm4;\n" - - " dec %%ecx;\n" - - " jnz 1b;\n" - - " movq %%mm2,16(%%edx);\n" - " movq %%mm3,24(%%edx);\n" - " movq %%mm4,32(%%edx);\n" - " movq %%mm5,40(%%edx);\n" - - " femms;\n" - : - : "c" (samples), "a" (x), "d" (vv) - : "memory", "eax", "ecx"); - - s[0].v2 = vv[4]; - s[1].v2 = vv[5]; - s[2].v2 = vv[6]; - s[3].v2 = vv[7]; - s[0].v3 = vv[8]; - s[1].v3 = vv[9]; - s[2].v3 = vv[10]; - s[3].v3 = vv[11]; + s[0].v2 = vv[4]; + s[1].v2 = vv[5]; + s[2].v2 = vv[6]; + s[3].v2 = vv[7]; + s[0].v3 = vv[8]; + s[1].v3 = vv[9]; + s[2].v3 = vv[10]; + s[3].v3 = vv[11]; } #endif /*- End of function --------------------------------------------------------*/ -void zap_goertzel_update(goertzel_state_t *s, - int16_t x[], - int samples) +void +zap_goertzel_update (goertzel_state_t * s, int16_t x[], int samples) { - int i; - float v1; - - for (i = 0; i < samples; i++) - { - v1 = s->v2; - s->v2 = s->v3; - s->v3 = s->fac*s->v2 - v1 + x[i]; - } + int i; + float v1; + + for (i = 0; i < samples; i++) { + v1 = s->v2; + s->v2 = s->v3; + s->v3 = s->fac * s->v2 - v1 + x[i]; + } } + /*- End of function --------------------------------------------------------*/ -float zap_goertzel_result (goertzel_state_t *s) +float +zap_goertzel_result (goertzel_state_t * s) { - return s->v3*s->v3 + s->v2*s->v2 - s->v2*s->v3*s->fac; + return s->v3 * s->v3 + s->v2 * s->v2 - s->v2 * s->v3 * s->fac; } + /*- End of function --------------------------------------------------------*/ -void zap_dtmf_detect_init (dtmf_detect_state_t *s) +void +zap_dtmf_detect_init (dtmf_detect_state_t * s) { - int i; - float theta; + int i; + float theta; - s->hit1 = - s->hit2 = 0; + s->hit1 = s->hit2 = 0; - for (i = 0; i < 4; i++) - { - theta = 2.0*M_PI*(dtmf_row[i]/SAMPLE_RATE); - dtmf_detect_row[i].fac = 2.0*cos(theta); + for (i = 0; i < 4; i++) { + theta = 2.0 * M_PI * (dtmf_row[i] / SAMPLE_RATE); + dtmf_detect_row[i].fac = 2.0 * cos (theta); - theta = 2.0*M_PI*(dtmf_col[i]/SAMPLE_RATE); - dtmf_detect_col[i].fac = 2.0*cos(theta); - - theta = 2.0*M_PI*(dtmf_row[i]*2.0/SAMPLE_RATE); - dtmf_detect_row_2nd[i].fac = 2.0*cos(theta); + theta = 2.0 * M_PI * (dtmf_col[i] / SAMPLE_RATE); + dtmf_detect_col[i].fac = 2.0 * cos (theta); - theta = 2.0*M_PI*(dtmf_col[i]*2.0/SAMPLE_RATE); - dtmf_detect_col_2nd[i].fac = 2.0*cos(theta); - - goertzel_init (&s->row_out[i], &dtmf_detect_row[i]); - goertzel_init (&s->col_out[i], &dtmf_detect_col[i]); - goertzel_init (&s->row_out2nd[i], &dtmf_detect_row_2nd[i]); - goertzel_init (&s->col_out2nd[i], &dtmf_detect_col_2nd[i]); - - s->energy = 0.0; - } + theta = 2.0 * M_PI * (dtmf_row[i] * 2.0 / SAMPLE_RATE); + dtmf_detect_row_2nd[i].fac = 2.0 * cos (theta); - /* Same for the fax dector */ - theta = 2.0*M_PI*(fax_freq/SAMPLE_RATE); - fax_detect.fac = 2.0 * cos(theta); - goertzel_init (&s->fax_tone, &fax_detect); + theta = 2.0 * M_PI * (dtmf_col[i] * 2.0 / SAMPLE_RATE); + dtmf_detect_col_2nd[i].fac = 2.0 * cos (theta); - /* Same for the fax dector 2nd harmonic */ - theta = 2.0*M_PI*(fax_freq * 2.0/SAMPLE_RATE); - fax_detect_2nd.fac = 2.0 * cos(theta); - goertzel_init (&s->fax_tone2nd, &fax_detect_2nd); - - s->current_sample = 0; - s->detected_digits = 0; - s->lost_digits = 0; - s->digits[0] = '\0'; - s->mhit = 0; + goertzel_init (&s->row_out[i], &dtmf_detect_row[i]); + goertzel_init (&s->col_out[i], &dtmf_detect_col[i]); + goertzel_init (&s->row_out2nd[i], &dtmf_detect_row_2nd[i]); + goertzel_init (&s->col_out2nd[i], &dtmf_detect_col_2nd[i]); + + s->energy = 0.0; + } + + /* Same for the fax dector */ + theta = 2.0 * M_PI * (fax_freq / SAMPLE_RATE); + fax_detect.fac = 2.0 * cos (theta); + goertzel_init (&s->fax_tone, &fax_detect); + + /* Same for the fax dector 2nd harmonic */ + theta = 2.0 * M_PI * (fax_freq * 2.0 / SAMPLE_RATE); + fax_detect_2nd.fac = 2.0 * cos (theta); + goertzel_init (&s->fax_tone2nd, &fax_detect_2nd); + + s->current_sample = 0; + s->detected_digits = 0; + s->lost_digits = 0; + s->digits[0] = '\0'; + s->mhit = 0; } + /*- End of function --------------------------------------------------------*/ -int zap_dtmf_detect (dtmf_detect_state_t *s, - int16_t amp[], - int samples, - int isradio) +int +zap_dtmf_detect (dtmf_detect_state_t * s, + int16_t amp[], int samples, int isradio) { - float row_energy[4]; - float col_energy[4]; - float fax_energy; - float fax_energy_2nd; - float famp; - float v1; - int i; - int j; - int sample; - int best_row; - int best_col; - int hit; - int limit; + float row_energy[4]; + float col_energy[4]; + float fax_energy; + float fax_energy_2nd; + float famp; + float v1; + int i; + int j; + int sample; + int best_row; + int best_col; + int hit; + int limit; - hit = 0; - for (sample = 0; sample < samples; sample = limit) - { - /* 102 is optimised to meet the DTMF specs. */ - if ((samples - sample) >= (102 - s->current_sample)) - limit = sample + (102 - s->current_sample); - else - limit = samples; + hit = 0; + for (sample = 0; sample < samples; sample = limit) { + /* 102 is optimised to meet the DTMF specs. */ + if ((samples - sample) >= (102 - s->current_sample)) + limit = sample + (102 - s->current_sample); + else + limit = samples; #if defined(USE_3DNOW) - _dtmf_goertzel_update (s->row_out, amp + sample, limit - sample); - _dtmf_goertzel_update (s->col_out, amp + sample, limit - sample); - _dtmf_goertzel_update (s->row_out2nd, amp + sample, limit2 - sample); - _dtmf_goertzel_update (s->col_out2nd, amp + sample, limit2 - sample); - /* XXX Need to fax detect for 3dnow too XXX */ - #warning "Fax Support Broken" + _dtmf_goertzel_update (s->row_out, amp + sample, limit - sample); + _dtmf_goertzel_update (s->col_out, amp + sample, limit - sample); + _dtmf_goertzel_update (s->row_out2nd, amp + sample, limit2 - sample); + _dtmf_goertzel_update (s->col_out2nd, amp + sample, limit2 - sample); + /* XXX Need to fax detect for 3dnow too XXX */ +#warning "Fax Support Broken" #else - /* The following unrolled loop takes only 35% (rough estimate) of the - time of a rolled loop on the machine on which it was developed */ - for (j = sample; j < limit; j++) - { - famp = amp[j]; - - s->energy += famp*famp; - - /* With GCC 2.95, the following unrolled code seems to take about 35% - (rough estimate) as long as a neat little 0-3 loop */ - v1 = s->row_out[0].v2; - s->row_out[0].v2 = s->row_out[0].v3; - s->row_out[0].v3 = s->row_out[0].fac*s->row_out[0].v2 - v1 + famp; - - v1 = s->col_out[0].v2; - s->col_out[0].v2 = s->col_out[0].v3; - s->col_out[0].v3 = s->col_out[0].fac*s->col_out[0].v2 - v1 + famp; - - v1 = s->row_out[1].v2; - s->row_out[1].v2 = s->row_out[1].v3; - s->row_out[1].v3 = s->row_out[1].fac*s->row_out[1].v2 - v1 + famp; - - v1 = s->col_out[1].v2; - s->col_out[1].v2 = s->col_out[1].v3; - s->col_out[1].v3 = s->col_out[1].fac*s->col_out[1].v2 - v1 + famp; - - v1 = s->row_out[2].v2; - s->row_out[2].v2 = s->row_out[2].v3; - s->row_out[2].v3 = s->row_out[2].fac*s->row_out[2].v2 - v1 + famp; - - v1 = s->col_out[2].v2; - s->col_out[2].v2 = s->col_out[2].v3; - s->col_out[2].v3 = s->col_out[2].fac*s->col_out[2].v2 - v1 + famp; - - v1 = s->row_out[3].v2; - s->row_out[3].v2 = s->row_out[3].v3; - s->row_out[3].v3 = s->row_out[3].fac*s->row_out[3].v2 - v1 + famp; + /* The following unrolled loop takes only 35% (rough estimate) of the + time of a rolled loop on the machine on which it was developed */ + for (j = sample; j < limit; j++) { + famp = amp[j]; - v1 = s->col_out[3].v2; - s->col_out[3].v2 = s->col_out[3].v3; - s->col_out[3].v3 = s->col_out[3].fac*s->col_out[3].v2 - v1 + famp; + s->energy += famp * famp; - v1 = s->col_out2nd[0].v2; - s->col_out2nd[0].v2 = s->col_out2nd[0].v3; - s->col_out2nd[0].v3 = s->col_out2nd[0].fac*s->col_out2nd[0].v2 - v1 + famp; - - v1 = s->row_out2nd[0].v2; - s->row_out2nd[0].v2 = s->row_out2nd[0].v3; - s->row_out2nd[0].v3 = s->row_out2nd[0].fac*s->row_out2nd[0].v2 - v1 + famp; - - v1 = s->col_out2nd[1].v2; - s->col_out2nd[1].v2 = s->col_out2nd[1].v3; - s->col_out2nd[1].v3 = s->col_out2nd[1].fac*s->col_out2nd[1].v2 - v1 + famp; - - v1 = s->row_out2nd[1].v2; - s->row_out2nd[1].v2 = s->row_out2nd[1].v3; - s->row_out2nd[1].v3 = s->row_out2nd[1].fac*s->row_out2nd[1].v2 - v1 + famp; - - v1 = s->col_out2nd[2].v2; - s->col_out2nd[2].v2 = s->col_out2nd[2].v3; - s->col_out2nd[2].v3 = s->col_out2nd[2].fac*s->col_out2nd[2].v2 - v1 + famp; - - v1 = s->row_out2nd[2].v2; - s->row_out2nd[2].v2 = s->row_out2nd[2].v3; - s->row_out2nd[2].v3 = s->row_out2nd[2].fac*s->row_out2nd[2].v2 - v1 + famp; - - v1 = s->col_out2nd[3].v2; - s->col_out2nd[3].v2 = s->col_out2nd[3].v3; - s->col_out2nd[3].v3 = s->col_out2nd[3].fac*s->col_out2nd[3].v2 - v1 + famp; - - v1 = s->row_out2nd[3].v2; - s->row_out2nd[3].v2 = s->row_out2nd[3].v3; - s->row_out2nd[3].v3 = s->row_out2nd[3].fac*s->row_out2nd[3].v2 - v1 + famp; + /* With GCC 2.95, the following unrolled code seems to take about 35% + (rough estimate) as long as a neat little 0-3 loop */ + v1 = s->row_out[0].v2; + s->row_out[0].v2 = s->row_out[0].v3; + s->row_out[0].v3 = s->row_out[0].fac * s->row_out[0].v2 - v1 + famp; - /* Update fax tone */ - v1 = s->fax_tone.v2; - s->fax_tone.v2 = s->fax_tone.v3; - s->fax_tone.v3 = s->fax_tone.fac*s->fax_tone.v2 - v1 + famp; + v1 = s->col_out[0].v2; + s->col_out[0].v2 = s->col_out[0].v3; + s->col_out[0].v3 = s->col_out[0].fac * s->col_out[0].v2 - v1 + famp; - v1 = s->fax_tone.v2; - s->fax_tone2nd.v2 = s->fax_tone2nd.v3; - s->fax_tone2nd.v3 = s->fax_tone2nd.fac*s->fax_tone2nd.v2 - v1 + famp; - } + v1 = s->row_out[1].v2; + s->row_out[1].v2 = s->row_out[1].v3; + s->row_out[1].v3 = s->row_out[1].fac * s->row_out[1].v2 - v1 + famp; + + v1 = s->col_out[1].v2; + s->col_out[1].v2 = s->col_out[1].v3; + s->col_out[1].v3 = s->col_out[1].fac * s->col_out[1].v2 - v1 + famp; + + v1 = s->row_out[2].v2; + s->row_out[2].v2 = s->row_out[2].v3; + s->row_out[2].v3 = s->row_out[2].fac * s->row_out[2].v2 - v1 + famp; + + v1 = s->col_out[2].v2; + s->col_out[2].v2 = s->col_out[2].v3; + s->col_out[2].v3 = s->col_out[2].fac * s->col_out[2].v2 - v1 + famp; + + v1 = s->row_out[3].v2; + s->row_out[3].v2 = s->row_out[3].v3; + s->row_out[3].v3 = s->row_out[3].fac * s->row_out[3].v2 - v1 + famp; + + v1 = s->col_out[3].v2; + s->col_out[3].v2 = s->col_out[3].v3; + s->col_out[3].v3 = s->col_out[3].fac * s->col_out[3].v2 - v1 + famp; + + v1 = s->col_out2nd[0].v2; + s->col_out2nd[0].v2 = s->col_out2nd[0].v3; + s->col_out2nd[0].v3 = + s->col_out2nd[0].fac * s->col_out2nd[0].v2 - v1 + famp; + + v1 = s->row_out2nd[0].v2; + s->row_out2nd[0].v2 = s->row_out2nd[0].v3; + s->row_out2nd[0].v3 = + s->row_out2nd[0].fac * s->row_out2nd[0].v2 - v1 + famp; + + v1 = s->col_out2nd[1].v2; + s->col_out2nd[1].v2 = s->col_out2nd[1].v3; + s->col_out2nd[1].v3 = + s->col_out2nd[1].fac * s->col_out2nd[1].v2 - v1 + famp; + + v1 = s->row_out2nd[1].v2; + s->row_out2nd[1].v2 = s->row_out2nd[1].v3; + s->row_out2nd[1].v3 = + s->row_out2nd[1].fac * s->row_out2nd[1].v2 - v1 + famp; + + v1 = s->col_out2nd[2].v2; + s->col_out2nd[2].v2 = s->col_out2nd[2].v3; + s->col_out2nd[2].v3 = + s->col_out2nd[2].fac * s->col_out2nd[2].v2 - v1 + famp; + + v1 = s->row_out2nd[2].v2; + s->row_out2nd[2].v2 = s->row_out2nd[2].v3; + s->row_out2nd[2].v3 = + s->row_out2nd[2].fac * s->row_out2nd[2].v2 - v1 + famp; + + v1 = s->col_out2nd[3].v2; + s->col_out2nd[3].v2 = s->col_out2nd[3].v3; + s->col_out2nd[3].v3 = + s->col_out2nd[3].fac * s->col_out2nd[3].v2 - v1 + famp; + + v1 = s->row_out2nd[3].v2; + s->row_out2nd[3].v2 = s->row_out2nd[3].v3; + s->row_out2nd[3].v3 = + s->row_out2nd[3].fac * s->row_out2nd[3].v2 - v1 + famp; + + /* Update fax tone */ + v1 = s->fax_tone.v2; + s->fax_tone.v2 = s->fax_tone.v3; + s->fax_tone.v3 = s->fax_tone.fac * s->fax_tone.v2 - v1 + famp; + + v1 = s->fax_tone.v2; + s->fax_tone2nd.v2 = s->fax_tone2nd.v3; + s->fax_tone2nd.v3 = s->fax_tone2nd.fac * s->fax_tone2nd.v2 - v1 + famp; + } #endif - s->current_sample += (limit - sample); - if (s->current_sample < 102) - continue; + s->current_sample += (limit - sample); + if (s->current_sample < 102) + continue; - /* Detect the fax energy, too */ - fax_energy = zap_goertzel_result(&s->fax_tone); - - /* We are at the end of a DTMF detection block */ - /* Find the peak row and the peak column */ - row_energy[0] = zap_goertzel_result (&s->row_out[0]); - col_energy[0] = zap_goertzel_result (&s->col_out[0]); + /* Detect the fax energy, too */ + fax_energy = zap_goertzel_result (&s->fax_tone); - for (best_row = best_col = 0, i = 1; i < 4; i++) - { - row_energy[i] = zap_goertzel_result (&s->row_out[i]); - if (row_energy[i] > row_energy[best_row]) - best_row = i; - col_energy[i] = zap_goertzel_result (&s->col_out[i]); - if (col_energy[i] > col_energy[best_col]) - best_col = i; - } - hit = 0; - /* Basic signal level test and the twist test */ - if (row_energy[best_row] >= DTMF_THRESHOLD - && - col_energy[best_col] >= DTMF_THRESHOLD - && - col_energy[best_col] < row_energy[best_row]*DTMF_REVERSE_TWIST - && - col_energy[best_col]*DTMF_NORMAL_TWIST > row_energy[best_row]) - { - /* Relative peak test */ - for (i = 0; i < 4; i++) - { - if ((i != best_col && col_energy[i]*DTMF_RELATIVE_PEAK_COL > col_energy[best_col]) - || - (i != best_row && row_energy[i]*DTMF_RELATIVE_PEAK_ROW > row_energy[best_row])) - { - break; - } - } - /* ... and second harmonic test */ - if (i >= 4 - && - (row_energy[best_row] + col_energy[best_col]) > 42.0*s->energy - && - zap_goertzel_result (&s->col_out2nd[best_col])*DTMF_2ND_HARMONIC_COL < col_energy[best_col] - && - zap_goertzel_result (&s->row_out2nd[best_row])*DTMF_2ND_HARMONIC_ROW < row_energy[best_row]) - { - hit = dtmf_positions[(best_row << 2) + best_col]; - /* Look for two successive similar results */ - /* The logic in the next test is: - We need two successive identical clean detects, with - something different preceeding it. This can work with - back to back differing digits. More importantly, it - can work with nasty phones that give a very wobbly start - to a digit. */ - if (hit == s->hit3 && s->hit3 != s->hit2) - { - s->mhit = hit; - s->digit_hits[(best_row << 2) + best_col]++; - s->detected_digits++; - if (s->current_digits < MAX_DTMF_DIGITS) - { - s->digits[s->current_digits++] = hit; - s->digits[s->current_digits] = '\0'; - } - else - { - s->lost_digits++; - } - } - } - } - if (!hit && (fax_energy >= FAX_THRESHOLD) && (fax_energy > s->energy * 21.0)) { - fax_energy_2nd = zap_goertzel_result(&s->fax_tone2nd); - if (fax_energy_2nd * FAX_2ND_HARMONIC < fax_energy) { -#if 0 - printf("Fax energy/Second Harmonic: %f/%f\n", fax_energy, fax_energy_2nd); -#endif - /* XXX Probably need better checking than just this the energy XXX */ - hit = 'f'; - s->fax_hits++; - } /* Don't reset fax hits counter */ - } else { - if (s->fax_hits > 5) { - s->mhit = 'f'; - s->detected_digits++; - if (s->current_digits < MAX_DTMF_DIGITS) - { - s->digits[s->current_digits++] = hit; - s->digits[s->current_digits] = '\0'; - } - else - { - s->lost_digits++; - } - } - s->fax_hits = 0; - } - s->hit1 = s->hit2; - s->hit2 = s->hit3; - s->hit3 = hit; - /* Reinitialise the detector for the next block */ - for (i = 0; i < 4; i++) - { - goertzel_init (&s->row_out[i], &dtmf_detect_row[i]); - goertzel_init (&s->col_out[i], &dtmf_detect_col[i]); - goertzel_init (&s->row_out2nd[i], &dtmf_detect_row_2nd[i]); - goertzel_init (&s->col_out2nd[i], &dtmf_detect_col_2nd[i]); + /* We are at the end of a DTMF detection block */ + /* Find the peak row and the peak column */ + row_energy[0] = zap_goertzel_result (&s->row_out[0]); + col_energy[0] = zap_goertzel_result (&s->col_out[0]); + + for (best_row = best_col = 0, i = 1; i < 4; i++) { + row_energy[i] = zap_goertzel_result (&s->row_out[i]); + if (row_energy[i] > row_energy[best_row]) + best_row = i; + col_energy[i] = zap_goertzel_result (&s->col_out[i]); + if (col_energy[i] > col_energy[best_col]) + best_col = i; + } + hit = 0; + /* Basic signal level test and the twist test */ + if (row_energy[best_row] >= DTMF_THRESHOLD + && + col_energy[best_col] >= DTMF_THRESHOLD + && + col_energy[best_col] < row_energy[best_row] * DTMF_REVERSE_TWIST + && col_energy[best_col] * DTMF_NORMAL_TWIST > row_energy[best_row]) { + /* Relative peak test */ + for (i = 0; i < 4; i++) { + if ((i != best_col + && col_energy[i] * DTMF_RELATIVE_PEAK_COL > + col_energy[best_col]) + || (i != best_row + && row_energy[i] * DTMF_RELATIVE_PEAK_ROW > + row_energy[best_row])) { + break; } - goertzel_init (&s->fax_tone, &fax_detect); - goertzel_init (&s->fax_tone2nd, &fax_detect_2nd); - s->energy = 0.0; - s->current_sample = 0; + } + /* ... and second harmonic test */ + if (i >= 4 + && + (row_energy[best_row] + col_energy[best_col]) > 42.0 * s->energy + && + zap_goertzel_result (&s->col_out2nd[best_col]) * + DTMF_2ND_HARMONIC_COL < col_energy[best_col] + && zap_goertzel_result (&s->row_out2nd[best_row]) * + DTMF_2ND_HARMONIC_ROW < row_energy[best_row]) { + hit = dtmf_positions[(best_row << 2) + best_col]; + /* Look for two successive similar results */ + /* The logic in the next test is: + We need two successive identical clean detects, with + something different preceeding it. This can work with + back to back differing digits. More importantly, it + can work with nasty phones that give a very wobbly start + to a digit. */ + if (hit == s->hit3 && s->hit3 != s->hit2) { + s->mhit = hit; + s->digit_hits[(best_row << 2) + best_col]++; + s->detected_digits++; + if (s->current_digits < MAX_DTMF_DIGITS) { + s->digits[s->current_digits++] = hit; + s->digits[s->current_digits] = '\0'; + } else { + s->lost_digits++; + } + } + } } - if ((!s->mhit) || (s->mhit != hit)) - { - s->mhit = 0; - return(0); + if (!hit && (fax_energy >= FAX_THRESHOLD) + && (fax_energy > s->energy * 21.0)) { + fax_energy_2nd = zap_goertzel_result (&s->fax_tone2nd); + if (fax_energy_2nd * FAX_2ND_HARMONIC < fax_energy) { +#if 0 + printf ("Fax energy/Second Harmonic: %f/%f\n", fax_energy, + fax_energy_2nd); +#endif + /* XXX Probably need better checking than just this the energy XXX */ + hit = 'f'; + s->fax_hits++; + } /* Don't reset fax hits counter */ + } else { + if (s->fax_hits > 5) { + s->mhit = 'f'; + s->detected_digits++; + if (s->current_digits < MAX_DTMF_DIGITS) { + s->digits[s->current_digits++] = hit; + s->digits[s->current_digits] = '\0'; + } else { + s->lost_digits++; + } + } + s->fax_hits = 0; } - return (hit); + s->hit1 = s->hit2; + s->hit2 = s->hit3; + s->hit3 = hit; + /* Reinitialise the detector for the next block */ + for (i = 0; i < 4; i++) { + goertzel_init (&s->row_out[i], &dtmf_detect_row[i]); + goertzel_init (&s->col_out[i], &dtmf_detect_col[i]); + goertzel_init (&s->row_out2nd[i], &dtmf_detect_row_2nd[i]); + goertzel_init (&s->col_out2nd[i], &dtmf_detect_col_2nd[i]); + } + goertzel_init (&s->fax_tone, &fax_detect); + goertzel_init (&s->fax_tone2nd, &fax_detect_2nd); + s->energy = 0.0; + s->current_sample = 0; + } + if ((!s->mhit) || (s->mhit != hit)) { + s->mhit = 0; + return (0); + } + return (hit); } + /*- End of function --------------------------------------------------------*/ -int zap_dtmf_get (dtmf_detect_state_t *s, - char *buf, - int max) +int +zap_dtmf_get (dtmf_detect_state_t * s, char *buf, int max) { - if (max > s->current_digits) - max = s->current_digits; - if (max > 0) - { - memcpy (buf, s->digits, max); - memmove (s->digits, s->digits + max, s->current_digits - max); - s->current_digits -= max; - } - buf[max] = '\0'; - return max; + if (max > s->current_digits) + max = s->current_digits; + if (max > 0) { + memcpy (buf, s->digits, max); + memmove (s->digits, s->digits + max, s->current_digits - max); + s->current_digits -= max; + } + buf[max] = '\0'; + return max; } + /*- End of function --------------------------------------------------------*/ /*- End of file ------------------------------------------------------------*/ From 57095d302d0daaf344aa6da261f638746cf62c1f Mon Sep 17 00:00:00 2001 From: David Schleef Date: Thu, 30 Dec 2010 18:20:47 -0800 Subject: [PATCH 227/448] dtmf: build fixes for MSVC Use gint16 and G_PI. --- gst/dtmf/gstdtmfdetect.c | 2 +- gst/dtmf/tone_detect.c | 12 ++++++------ gst/dtmf/tone_detect.h | 6 ++++-- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/gst/dtmf/gstdtmfdetect.c b/gst/dtmf/gstdtmfdetect.c index 6fa17b5e49..0bb9242647 100644 --- a/gst/dtmf/gstdtmfdetect.c +++ b/gst/dtmf/gstdtmfdetect.c @@ -175,7 +175,7 @@ gst_dtmf_detect_transform_ip (GstBaseTransform * trans, GstBuffer * buf) if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_GAP)) return GST_FLOW_OK; - zap_dtmf_detect (&self->dtmf_state, (int16_t *) GST_BUFFER_DATA (buf), + zap_dtmf_detect (&self->dtmf_state, (gint16 *) GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf) / 2, FALSE); dtmf_count = zap_dtmf_get (&self->dtmf_state, dtmfbuf, MAX_DTMF_DIGITS); diff --git a/gst/dtmf/tone_detect.c b/gst/dtmf/tone_detect.c index d8f1df16e1..8c1b5ad956 100644 --- a/gst/dtmf/tone_detect.c +++ b/gst/dtmf/tone_detect.c @@ -199,16 +199,16 @@ zap_dtmf_detect_init (dtmf_detect_state_t * s) s->hit1 = s->hit2 = 0; for (i = 0; i < 4; i++) { - theta = 2.0 * M_PI * (dtmf_row[i] / SAMPLE_RATE); + theta = 2.0 * G_PI * (dtmf_row[i] / SAMPLE_RATE); dtmf_detect_row[i].fac = 2.0 * cos (theta); - theta = 2.0 * M_PI * (dtmf_col[i] / SAMPLE_RATE); + theta = 2.0 * G_PI * (dtmf_col[i] / SAMPLE_RATE); dtmf_detect_col[i].fac = 2.0 * cos (theta); - theta = 2.0 * M_PI * (dtmf_row[i] * 2.0 / SAMPLE_RATE); + theta = 2.0 * G_PI * (dtmf_row[i] * 2.0 / SAMPLE_RATE); dtmf_detect_row_2nd[i].fac = 2.0 * cos (theta); - theta = 2.0 * M_PI * (dtmf_col[i] * 2.0 / SAMPLE_RATE); + theta = 2.0 * G_PI * (dtmf_col[i] * 2.0 / SAMPLE_RATE); dtmf_detect_col_2nd[i].fac = 2.0 * cos (theta); goertzel_init (&s->row_out[i], &dtmf_detect_row[i]); @@ -220,12 +220,12 @@ zap_dtmf_detect_init (dtmf_detect_state_t * s) } /* Same for the fax dector */ - theta = 2.0 * M_PI * (fax_freq / SAMPLE_RATE); + theta = 2.0 * G_PI * (fax_freq / SAMPLE_RATE); fax_detect.fac = 2.0 * cos (theta); goertzel_init (&s->fax_tone, &fax_detect); /* Same for the fax dector 2nd harmonic */ - theta = 2.0 * M_PI * (fax_freq * 2.0 / SAMPLE_RATE); + theta = 2.0 * G_PI * (fax_freq * 2.0 / SAMPLE_RATE); fax_detect_2nd.fac = 2.0 * cos (theta); goertzel_init (&s->fax_tone2nd, &fax_detect_2nd); diff --git a/gst/dtmf/tone_detect.h b/gst/dtmf/tone_detect.h index 909c5ef601..ce6dddd2cb 100644 --- a/gst/dtmf/tone_detect.h +++ b/gst/dtmf/tone_detect.h @@ -35,6 +35,8 @@ #include "_stdint.h" +#include + typedef struct { float v2; @@ -75,13 +77,13 @@ typedef struct } tone_detection_descriptor_t; void zap_goertzel_update(goertzel_state_t *s, - int16_t x[], + gint16 x[], int samples); float zap_goertzel_result (goertzel_state_t *s); void zap_dtmf_detect_init (dtmf_detect_state_t *s); int zap_dtmf_detect (dtmf_detect_state_t *s, - int16_t amp[], + gint16 amp[], int samples, int isradio); int zap_dtmf_get (dtmf_detect_state_t *s, From 512c66d8ba25c782e0c68782361722cb3d4974bd Mon Sep 17 00:00:00 2001 From: David Schleef Date: Thu, 30 Dec 2010 19:03:14 -0800 Subject: [PATCH 228/448] frei0r: convert uint32_t to guint32 --- gst/frei0r/frei0r.h | 12 ++++++------ gst/frei0r/gstfrei0r.h | 10 +++++----- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/gst/frei0r/frei0r.h b/gst/frei0r/frei0r.h index 48c942dd47..9aed4453b0 100644 --- a/gst/frei0r/frei0r.h +++ b/gst/frei0r/frei0r.h @@ -200,7 +200,7 @@ #ifndef INCLUDED_FREI0R_H #define INCLUDED_FREI0R_H -#include +#include /** * The frei0r API major version @@ -554,7 +554,7 @@ void f0r_get_param_value(f0r_instance_t instance, * \see f0r_update2 */ void f0r_update(f0r_instance_t instance, - double time, const uint32_t* inframe, uint32_t* outframe); + double time, const guint32* inframe, guint32* outframe); //--------------------------------------------------------------------------- @@ -581,10 +581,10 @@ void f0r_update(f0r_instance_t instance, */ void f0r_update2(f0r_instance_t instance, double time, - const uint32_t* inframe1, - const uint32_t* inframe2, - const uint32_t* inframe3, - uint32_t* outframe); + const guint32* inframe1, + const guint32* inframe2, + const guint32* inframe3, + guint32* outframe); //--------------------------------------------------------------------------- #endif diff --git a/gst/frei0r/gstfrei0r.h b/gst/frei0r/gstfrei0r.h index af2126542d..490d6aae9c 100644 --- a/gst/frei0r/gstfrei0r.h +++ b/gst/frei0r/gstfrei0r.h @@ -66,13 +66,13 @@ struct _GstFrei0rFuncTable { f0r_param_t param, int param_index); void (*update) (f0r_instance_t instance, - double time, const uint32_t* inframe, uint32_t* outframe); + double time, const guint32* inframe, guint32* outframe); void (*update2) (f0r_instance_t instance, double time, - const uint32_t* inframe1, - const uint32_t* inframe2, - const uint32_t* inframe3, - uint32_t* outframe); + const guint32* inframe1, + const guint32* inframe2, + const guint32* inframe3, + guint32* outframe); }; typedef enum { From 2f5c92f1c8540fb4d573436609b34a6b393211ba Mon Sep 17 00:00:00 2001 From: David Schleef Date: Thu, 30 Dec 2010 19:03:54 -0800 Subject: [PATCH 229/448] change M_PI to G_PI --- gst/gaudieffects/gstgaussblur.c | 4 ++-- gst/geometrictransform/gstrotate.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gst/gaudieffects/gstgaussblur.c b/gst/gaudieffects/gstgaussblur.c index 6691c4c368..6b1223e1d3 100644 --- a/gst/gaudieffects/gstgaussblur.c +++ b/gst/gaudieffects/gstgaussblur.c @@ -307,7 +307,7 @@ make_gaussian_kernel (GaussBlur * gb, float sigma) int i, center, left, right; float sum, sum2; const float fe = -0.5 / (sigma * sigma); - const float dx = 1.0 / (sigma * sqrt (2 * M_PI)); + const float dx = 1.0 / (sigma * sqrt (2 * G_PI)); center = ceil (2.5 * fabs (sigma)); gb->windowsize = (int) (1 + 2 * center); @@ -330,7 +330,7 @@ make_gaussian_kernel (GaussBlur * gb, float sigma) left = center - 1; right = center + 1; for (i = 1; i <= center; i++, left--, right++) { - float fx = dx * pow (M_E, fe * i * i); + float fx = dx * pow (G_E, fe * i * i); gb->kernel[right] = gb->kernel[left] = fx; sum += 2 * fx; } diff --git a/gst/geometrictransform/gstrotate.c b/gst/geometrictransform/gstrotate.c index a7433cce09..6c5ba62cbc 100644 --- a/gst/geometrictransform/gstrotate.c +++ b/gst/geometrictransform/gstrotate.c @@ -154,7 +154,7 @@ rotate_map (GstGeometricTransform * gt, gint x, gint y, gdouble * in_x, h = gt->height; /* our parameters */ - ar = rotate->angle * M_PI / 180.0; /* angle of rotation, degrees to radians */ + ar = rotate->angle * G_PI / 180.0; /* angle of rotation, degrees to radians */ /* get in and out centers */ cox = 0.5 * w; From 04c44d18c9b480ad8cffff2dbe1f78ad3d478b96 Mon Sep 17 00:00:00 2001 From: David Schleef Date: Thu, 30 Dec 2010 19:12:23 -0800 Subject: [PATCH 230/448] legacyresample: Use math-compat header --- gst/legacyresample/resample_functable.c | 2 ++ gst/legacyresample/resample_ref.c | 1 + 2 files changed, 3 insertions(+) diff --git a/gst/legacyresample/resample_functable.c b/gst/legacyresample/resample_functable.c index 6d6e26c0c3..fc3e38a8b4 100644 --- a/gst/legacyresample/resample_functable.c +++ b/gst/legacyresample/resample_functable.c @@ -28,6 +28,8 @@ #include #include +#include + #include "_stdint.h" #include "resample.h" diff --git a/gst/legacyresample/resample_ref.c b/gst/legacyresample/resample_ref.c index 383e069e99..546e7cc9c2 100644 --- a/gst/legacyresample/resample_ref.c +++ b/gst/legacyresample/resample_ref.c @@ -28,6 +28,7 @@ #include #include +#include #include "_stdint.h" #include "resample.h" From edd1f791ca4e4526e10c6458d4d19a1fc3173a89 Mon Sep 17 00:00:00 2001 From: David Schleef Date: Thu, 30 Dec 2010 19:21:21 -0800 Subject: [PATCH 231/448] mpegdemux: Fix c99-ism --- gst/mpegdemux/gstmpegtsdemux.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gst/mpegdemux/gstmpegtsdemux.c b/gst/mpegdemux/gstmpegtsdemux.c index 166a246c61..4f116e4d5c 100644 --- a/gst/mpegdemux/gstmpegtsdemux.c +++ b/gst/mpegdemux/gstmpegtsdemux.c @@ -946,11 +946,12 @@ gst_mpegts_demux_send_tags_for_stream (GstMpegTSDemux * demux, GstMpegTSStream * stream) { GstTagList *list = NULL; + gint i; if (stream->ES_info) { static const guint8 lang_descs[] = { DESC_ISO_639_LANGUAGE, DESC_DVB_SUBTITLING }; - for (gint i = 0; i < G_N_ELEMENTS (lang_descs); i++) { + for (i = 0; i < G_N_ELEMENTS (lang_descs); i++) { guint8 *iso639_languages = gst_mpeg_descriptor_find (stream->ES_info, lang_descs[i]); if (iso639_languages) { From 272086b121297cdbcaeef02fa133ef5f20f11163 Mon Sep 17 00:00:00 2001 From: David Schleef Date: Thu, 30 Dec 2010 19:21:47 -0800 Subject: [PATCH 232/448] cog: Use math-compat.h --- ext/cog/generate_tables.c | 1 + ext/cog/gstcms.c | 1 + ext/cog/gstcolorconvert.c | 2 +- 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/ext/cog/generate_tables.c b/ext/cog/generate_tables.c index d775bcc216..033f23c39f 100644 --- a/ext/cog/generate_tables.c +++ b/ext/cog/generate_tables.c @@ -2,6 +2,7 @@ #include "config.h" #include +#include #include #include "gstcms.h" diff --git a/ext/cog/gstcms.c b/ext/cog/gstcms.c index 8fd28c6bab..27648cbf8e 100644 --- a/ext/cog/gstcms.c +++ b/ext/cog/gstcms.c @@ -22,6 +22,7 @@ #endif #include +#include #include "gstcms.h" #include "cogutils.h" diff --git a/ext/cog/gstcolorconvert.c b/ext/cog/gstcolorconvert.c index 6f5d9c85f1..560ca68c90 100644 --- a/ext/cog/gstcolorconvert.c +++ b/ext/cog/gstcolorconvert.c @@ -27,7 +27,7 @@ #include #include #include -#include +#include #include "gstcogutils.h" From 68493aadab267a096391587cd6b596cb20318038 Mon Sep 17 00:00:00 2001 From: David Schleef Date: Fri, 31 Dec 2010 00:12:53 -0800 Subject: [PATCH 233/448] dtmf: Fix build failure caused by previous commit --- gst/dtmf/tone_detect.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/gst/dtmf/tone_detect.c b/gst/dtmf/tone_detect.c index 8c1b5ad956..73a73ee98b 100644 --- a/gst/dtmf/tone_detect.c +++ b/gst/dtmf/tone_detect.c @@ -38,8 +38,12 @@ #include #include "tone_detect.h" +#ifndef FALSE #define FALSE 0 +#endif +#ifndef TRUE #define TRUE (!FALSE) +#endif //#define USE_3DNOW From 76b087b8b6a9f3dd34aa90fa0c307afef89bb6e7 Mon Sep 17 00:00:00 2001 From: David Schleef Date: Fri, 31 Dec 2010 00:07:28 -0800 Subject: [PATCH 234/448] Add gst-app-maker --- tools/Makefile.am | 1 + tools/gst-app-maker | 545 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 546 insertions(+) create mode 100755 tools/gst-app-maker diff --git a/tools/Makefile.am b/tools/Makefile.am index ceb8be87f2..6412930528 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -24,5 +24,6 @@ templatefiles=\ EXTRA_DIST = \ gst-element-maker \ + gst-app-maker \ $(templatefiles) diff --git a/tools/gst-app-maker b/tools/gst-app-maker new file mode 100755 index 0000000000..f90944213b --- /dev/null +++ b/tools/gst-app-maker @@ -0,0 +1,545 @@ +#!/bin/sh + + +prefix=gst +templatedir=element-templates + +while [ "$1" ] ; do + case $1 in + --help) + cat <<-EOF +Usage: element-maker [OPTIONS] _NAME BASE_CLASS +Create a GStreamer application from a template. +Options: + --help Print this information + --prefix PREFIX Use PREFIX instead of "gst" +Example: 'gst-app-maker my_app' will create the file gstmyapp.c. +EOF + exit 0 + ;; + --prefix) + shift + prefix=$1 + ;; + -*) + echo Unknown option: $1 + exit 1 + ;; + *) + if [ "$name" = "" ]; then + name=$1 + else + echo Ignored: $1 + fi + esac + shift +done + +if [ "$name" = "" ] ; then + echo "Usage: element-maker [OPTIONS] ELEMENT_NAME BASE_CLASS" + exit 1 +fi + + +PREFIX=$(echo $prefix | sed -e 's/\(.*\)/\U\1/') +NAME=$(echo $name | sed -e 's/\(.*\)/\U\1/') +Prefix=$(echo $prefix | sed -e 's/_\(.\)/\U\1/g' -e 's/^\(.\)/\U\1/') +Name=$(echo $name | sed -e 's/_\(.\)/\U\1/g' -e 's/^\(.\)/\U\1/') + +GST_IS_REPLACE=${PREFIX}_IS_${NAME} +GST_REPLACE=${PREFIX}_${NAME} +GST_TYPE_REPLACE=${PREFIX}_TYPE_${NAME} +GstReplace=${Prefix}${Name} +gst_replace=${prefix}_${name} +gstreplace=${prefix}$(echo $name | sed -e 's/_//g') +replace=$(echo $name | sed -e 's/_//g') + +if [ "$REAL_NAME" = "" ] ; then + REAL_NAME=FIXME +fi +if [ "$EMAIL_ADDRESS" = "" ] ; then + EMAIL_ADDRESS=fixme@example.com +fi + + + +generate () +{ + +cat <<-EOF +/* GstReplace + * Copyright (C) $(date +%Y) $REAL_NAME <$EMAIL_ADDRESS> + * Copyright (C) 2010 Entropy Wave Inc + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR + * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING + * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#define GETTEXT_PACKAGE "replace" + + +typedef struct _GstReplace GstReplace; +struct _GstReplace { + GstElement *pipeline; + GstBus *bus; + GMainLoop *main_loop; + + GstElement *source_element; + GstElement *sink_element; + + gboolean paused_for_buffering; + guint timer_id; +}; + +GstReplace * gst_replace_new (void); +void gst_replace_free (GstReplace *replace); +void gst_replace_create_pipeline (GstReplace *replace); +void gst_replace_create_pipeline_playbin (GstReplace *replace, const char *uri); +void gst_replace_start (GstReplace *replace); +void gst_replace_stop (GstReplace *replace); + +static gboolean gst_replace_handle_message (GstBus *bus, GstMessage *message, + gpointer data); +static gboolean onesecond_timer (gpointer priv); + + +gboolean verbose; + +static GOptionEntry entries[] = +{ + { "verbose", 'v', 0, G_OPTION_ARG_NONE, &verbose, "Be verbose", NULL }, + + { NULL } + +}; + +int +main (int argc, char *argv[]) +{ + GError *error = NULL; + GOptionContext *context; + GstReplace *replace; + GMainLoop *main_loop; + + if (!g_thread_supported ()) g_thread_init(NULL); + + context = g_option_context_new ("- FIXME"); + g_option_context_add_main_entries (context, entries, GETTEXT_PACKAGE); + g_option_context_add_group (context, gst_init_get_option_group ()); + if (!g_option_context_parse (context, &argc, &argv, &error)) { + g_print ("option parsing failed: %s\n", error->message); + exit (1); + } + g_option_context_free (context); + + replace = gst_replace_new (); + + if (argc > 1) { + gchar *uri; + if (gst_uri_is_valid (argv[1])) { + uri = g_strdup (argv[1]); + } else { + uri = g_filename_to_uri (argv[1], NULL, NULL); + } + gst_replace_create_pipeline_playbin (replace, uri); + g_free (uri); + } else { + gst_replace_create_pipeline (replace); + } + + gst_replace_start (replace); + + main_loop = g_main_loop_new (NULL, TRUE); + replace->main_loop = main_loop; + + g_main_loop_run (main_loop); + + exit (0); +} + + +GstReplace * +gst_replace_new (void) +{ + GstReplace *replace; + + replace = g_new0 (GstReplace, 1); + + return replace; +} + +void +gst_replace_free (GstReplace *replace) +{ + if (replace->source_element) { + gst_object_unref (replace->source_element); + replace->source_element = NULL; + } + if (replace->sink_element) { + gst_object_unref (replace->sink_element); + replace->sink_element = NULL; + } + + if (replace->pipeline) { + gst_element_set_state (replace->pipeline, GST_STATE_NULL); + gst_object_unref (replace->pipeline); + replace->pipeline = NULL; + } + g_free (replace); +} + +void +gst_replace_create_pipeline_playbin (GstReplace *replace, const char *uri) +{ + GstElement *pipeline; + GError *error = NULL; + + pipeline = gst_pipeline_new (NULL); + gst_bin_add (GST_BIN(pipeline), + gst_element_factory_make ("playbin2", "source")); + + if (error) { + g_print("pipeline parsing error: %s\n", error->message); + gst_object_unref (pipeline); + return; + } + + replace->pipeline = pipeline; + + gst_pipeline_set_auto_flush_bus (GST_PIPELINE(pipeline), FALSE); + replace->bus = gst_pipeline_get_bus (GST_PIPELINE(pipeline)); + gst_bus_add_watch (replace->bus, gst_replace_handle_message, replace); + + replace->source_element = gst_bin_get_by_name (GST_BIN(pipeline), "source"); + g_print("source_element is %p\n", replace->source_element); + + g_print("setting uri to %s\n", uri); + g_object_set (replace->source_element, "uri", uri, NULL); +} + +void +gst_replace_create_pipeline (GstReplace *replace) +{ + GString *pipe_desc; + GstElement *pipeline; + GError *error = NULL; + + pipe_desc = g_string_new (""); + + g_string_append (pipe_desc, "videotestsrc name=source num-buffers=100 ! "); + g_string_append (pipe_desc, "timeoverlay ! "); + g_string_append (pipe_desc, "xvimagesink name=sink "); + g_string_append (pipe_desc, "audiotestsrc samplesperbuffer=1600 num-buffers=100 ! "); + g_string_append (pipe_desc, "alsasink "); + + if (verbose) g_print ("pipeline: %s\n", pipe_desc->str); + + pipeline = (GstElement *) gst_parse_launch (pipe_desc->str, &error); + g_string_free (pipe_desc, FALSE); + + if (error) { + g_print("pipeline parsing error: %s\n", error->message); + gst_object_unref (pipeline); + return; + } + + replace->pipeline = pipeline; + + gst_pipeline_set_auto_flush_bus (GST_PIPELINE(pipeline), FALSE); + replace->bus = gst_pipeline_get_bus (GST_PIPELINE(pipeline)); + gst_bus_add_watch (replace->bus, gst_replace_handle_message, replace); + + replace->source_element = gst_bin_get_by_name (GST_BIN(pipeline), "source"); + replace->sink_element = gst_bin_get_by_name (GST_BIN(pipeline), "sink"); +} + +void +gst_replace_start (GstReplace *replace) +{ + gst_element_set_state (replace->pipeline, GST_STATE_READY); + + replace->timer_id = g_timeout_add (1000, onesecond_timer, replace); +} + +void +gst_replace_stop (GstReplace *replace) +{ + gst_element_set_state (replace->pipeline, GST_STATE_NULL); + + g_source_remove (replace->timer_id); +} + +static void +gst_replace_handle_eos (GstReplace *replace) +{ + gst_replace_stop (replace); +} + +static void +gst_replace_handle_error (GstReplace *replace, GError *error, + const char *debug) +{ + g_print ("error: %s\n", error->message); + gst_replace_stop (replace); +} + +static void +gst_replace_handle_warning (GstReplace *replace, GError *error, + const char *debug) +{ + g_print ("warning: %s\n", error->message); +} + +static void +gst_replace_handle_info (GstReplace *replace, GError *error, + const char *debug) +{ + g_print ("info: %s\n", error->message); +} + +static void +gst_replace_handle_null_to_ready (GstReplace *replace) +{ + gst_element_set_state (replace->pipeline, GST_STATE_PAUSED); + +} + +static void +gst_replace_handle_ready_to_paused (GstReplace *replace) +{ + if (!replace->paused_for_buffering) { + gst_element_set_state (replace->pipeline, GST_STATE_PLAYING); + } +} + +static void +gst_replace_handle_paused_to_playing (GstReplace *replace) +{ + +} + +static void +gst_replace_handle_playing_to_paused (GstReplace *replace) +{ + +} + +static void +gst_replace_handle_paused_to_ready (GstReplace *replace) +{ + +} + +static void +gst_replace_handle_ready_to_null (GstReplace *replace) +{ + g_main_loop_quit (replace->main_loop); + +} + + +static gboolean +gst_replace_handle_message (GstBus *bus, GstMessage *message, + gpointer data) +{ + GstReplace *replace = (GstReplace *) data; + + switch (GST_MESSAGE_TYPE(message)) { + case GST_MESSAGE_EOS: + gst_replace_handle_eos (replace); + break; + case GST_MESSAGE_ERROR: + { + GError *error = NULL; + gchar *debug; + + gst_message_parse_error (message, &error, &debug); + gst_replace_handle_error (replace, error, debug); + } + break; + case GST_MESSAGE_WARNING: + { + GError *error = NULL; + gchar *debug; + + gst_message_parse_warning (message, &error, &debug); + gst_replace_handle_warning (replace, error, debug); + } + break; + case GST_MESSAGE_INFO: + { + GError *error = NULL; + gchar *debug; + + gst_message_parse_info (message, &error, &debug); + gst_replace_handle_info (replace, error, debug); + } + break; + case GST_MESSAGE_TAG: + { + GstTagList *tag_list; + + gst_message_parse_tag (message, &tag_list); + if (verbose) g_print("tag\n"); + } + break; + case GST_MESSAGE_STATE_CHANGED: + { + GstState oldstate, newstate, pending; + + gst_message_parse_state_changed (message, &oldstate, &newstate, + &pending); + if (GST_ELEMENT(message->src) == replace->pipeline) { + if (verbose) g_print("state change from %s to %s\n", + gst_element_state_get_name (oldstate), + gst_element_state_get_name (newstate)); + switch (GST_STATE_TRANSITION(oldstate, newstate)) { + case GST_STATE_CHANGE_NULL_TO_READY: + gst_replace_handle_null_to_ready (replace); + break; + case GST_STATE_CHANGE_READY_TO_PAUSED: + gst_replace_handle_ready_to_paused (replace); + break; + case GST_STATE_CHANGE_PAUSED_TO_PLAYING: + gst_replace_handle_paused_to_playing (replace); + break; + case GST_STATE_CHANGE_PLAYING_TO_PAUSED: + gst_replace_handle_playing_to_paused (replace); + break; + case GST_STATE_CHANGE_PAUSED_TO_READY: + gst_replace_handle_paused_to_ready (replace); + break; + case GST_STATE_CHANGE_READY_TO_NULL: + gst_replace_handle_ready_to_null (replace); + break; + default: + if (verbose) g_print("unknown state change from %s to %s\n", + gst_element_state_get_name (oldstate), + gst_element_state_get_name (newstate)); + } + } + } + break; + case GST_MESSAGE_BUFFERING: + { + int percent; + gst_message_parse_buffering (message, &percent); + //g_print("buffering %d\n", percent); + if (!replace->paused_for_buffering && percent < 100) { + g_print ("pausing for buffing\n"); + replace->paused_for_buffering = TRUE; + gst_element_set_state (replace->pipeline, GST_STATE_PAUSED); + } else if (replace->paused_for_buffering && percent == 100) { + g_print ("unpausing for buffing\n"); + replace->paused_for_buffering = FALSE; + gst_element_set_state (replace->pipeline, GST_STATE_PLAYING); + } + } + break; + case GST_MESSAGE_STATE_DIRTY: + case GST_MESSAGE_CLOCK_PROVIDE: + case GST_MESSAGE_CLOCK_LOST: + case GST_MESSAGE_NEW_CLOCK: + case GST_MESSAGE_STRUCTURE_CHANGE: + case GST_MESSAGE_STREAM_STATUS: + break; + case GST_MESSAGE_STEP_DONE: + case GST_MESSAGE_APPLICATION: + case GST_MESSAGE_ELEMENT: + case GST_MESSAGE_SEGMENT_START: + case GST_MESSAGE_SEGMENT_DONE: + case GST_MESSAGE_DURATION: + case GST_MESSAGE_LATENCY: + case GST_MESSAGE_ASYNC_START: + case GST_MESSAGE_ASYNC_DONE: + case GST_MESSAGE_REQUEST_STATE: + case GST_MESSAGE_STEP_START: + case GST_MESSAGE_QOS: + default: + if (verbose) { + g_print ("message: %s\n", GST_MESSAGE_TYPE_NAME (message)); + } + break; + } + + return TRUE; +} + + + +static gboolean +onesecond_timer (gpointer priv) +{ + //GstReplace *replace = (GstReplace *)priv; + + g_print(".\n"); + + return TRUE; +} + + + +/* helper functions */ + +#if 0 +gboolean +have_element (const gchar *element_name) +{ + GstPluginFeature *feature; + + feature = gst_default_registry_find_feature (element_name, + GST_TYPE_ELEMENT_FACTORY); + if (feature) { + g_object_unref (feature); + return TRUE; + } + return FALSE; +} +#endif + +EOF + +} + +generate | sed \ + -e "s/GST_BASE_REPLACE/$GST_BASE_REPLACE/g" \ + -e "s/GST_TYPE_BASE_REPLACE/$GST_TYPE_BASE_REPLACE/g" \ + -e "s/GstBaseReplace/$GstBaseReplace/g" \ + -e "s/GST_IS_REPLACE/$GST_IS_REPLACE/g" \ + -e "s/GST_REPLACE/$GST_REPLACE/g" \ + -e "s/GST_TYPE_REPLACE/$GST_TYPE_REPLACE/g" \ + -e "s/GstReplace/$GstReplace/g" \ + -e "s/gst_replace/$gst_replace/g" \ + -e "s/gstreplace/$gstreplace/g" \ + -e "s/replace/$replace/g" >$gstreplace.c + +gst-indent $gstreplace.c + +gcc -Wall $(pkg-config --cflags gstreamer-0.10) -c -o $gstreplace.o $gstreplace.c +gcc -o $gstreplace $gstreplace.o $(pkg-config --libs gstreamer-0.10) + + From a12dce10956e5368a9254a1c2aa54024dafaa2bd Mon Sep 17 00:00:00 2001 From: David Schleef Date: Fri, 31 Dec 2010 00:09:09 -0800 Subject: [PATCH 235/448] element-maker: Update FSF address --- tools/gst-element-maker | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/gst-element-maker b/tools/gst-element-maker index 816385d965..fa56baf9e3 100755 --- a/tools/gst-element-maker +++ b/tools/gst-element-maker @@ -95,8 +95,8 @@ cat <<-EOF * * You should have received a copy of the GNU Library General Public * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * Free Software Foundation, Inc., 51 Franklin Street, Suite 500, + * Boston, MA 02110-1335, USA. */ EOF From 21fb0dc586357d9496165d4cb3fc5ba90931a55c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Sun, 2 Jan 2011 13:29:06 +0000 Subject: [PATCH 236/448] gaudieffects: dist python examples --- gst/gaudieffects/Makefile.am | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gst/gaudieffects/Makefile.am b/gst/gaudieffects/Makefile.am index 92b8ce5f9a..e34e71c503 100644 --- a/gst/gaudieffects/Makefile.am +++ b/gst/gaudieffects/Makefile.am @@ -11,3 +11,5 @@ libgstgaudieffects_la_LIBTOOLFLAGS = --tag=disable-static noinst_HEADERS = \ gstburn.h gstchromium.h gstdilate.h gstdodge.h \ gstexclusion.h gstgaussblur.h gstplugin.h gstsolarize.h + +EXTRA_DIST = blur-example.py burn-example.py From 4b56970d58246dc6a961ee36937eaae180b3aaea Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Fri, 31 Dec 2010 16:17:50 +0000 Subject: [PATCH 237/448] kate: reenable the sending of a message for tags https://bugzilla.gnome.org/show_bug.cgi?id=638412 --- ext/kate/gstkateutil.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/ext/kate/gstkateutil.c b/ext/kate/gstkateutil.c index 0bccc4b6fa..14f4258083 100644 --- a/ext/kate/gstkateutil.c +++ b/ext/kate/gstkateutil.c @@ -356,7 +356,6 @@ gst_kate_util_decoder_base_chain_kate_packet (GstKateDecoderBase * decoder, if (old) gst_tag_list_free (old); -#if 0 if (decoder->initialized) { gst_element_found_tags_for_pad (element, tagpad, decoder->tags); decoder->tags = NULL; @@ -367,7 +366,6 @@ gst_kate_util_decoder_base_chain_kate_packet (GstKateDecoderBase * decoder, gst_message_new_tag (GST_OBJECT (element), gst_tag_list_copy (decoder->tags))); } -#endif } break; From 992c05f840381dd251d76eda4f3cc05fb5312c68 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Sun, 2 Jan 2011 13:52:36 +0000 Subject: [PATCH 238/448] kate: fix caps and string leaks and some minor clean-ups Don't leak source caps. Use GST_PTR_FORMAT to log caps, so we don't need to leak strings from gst_caps_to_string(). No need to use GST_DEBUG_FUNCPTR for vfuncs where the base class will never look them up (like property getters/setters). Don't use g_return_*_if_fail() for things that aren't directly programming errors (by the application developer). Fixes kate unit test under valgrind. --- ext/kate/gstkatedec.c | 28 ++++++++++++++-------------- ext/kate/gstkatetiger.c | 4 ++-- ext/kate/gstkateutil.c | 8 +++----- 3 files changed, 19 insertions(+), 21 deletions(-) diff --git a/ext/kate/gstkatedec.c b/ext/kate/gstkatedec.c index 4dbe6d8182..df3607024f 100644 --- a/ext/kate/gstkatedec.c +++ b/ext/kate/gstkatedec.c @@ -158,8 +158,8 @@ gst_kate_dec_class_init (GstKateDecClass * klass) gobject_class = (GObjectClass *) klass; gstelement_class = (GstElementClass *) klass; - gobject_class->set_property = GST_DEBUG_FUNCPTR (gst_kate_dec_set_property); - gobject_class->get_property = GST_DEBUG_FUNCPTR (gst_kate_dec_get_property); + gobject_class->set_property = gst_kate_dec_set_property; + gobject_class->get_property = gst_kate_dec_get_property; gst_kate_util_install_decoder_base_properties (gobject_class); @@ -360,10 +360,17 @@ not_in_seg: static GstStateChangeReturn gst_kate_dec_change_state (GstElement * element, GstStateChange transition) { + GstStateChangeReturn ret; GstKateDec *kd = GST_KATE_DEC (element); - return gst_kate_decoder_base_change_state (&kd->decoder, element, + ret = gst_kate_decoder_base_change_state (&kd->decoder, element, parent_class, transition); + + if (transition == GST_STATE_CHANGE_PAUSED_TO_READY) { + gst_caps_replace (&kd->src_caps, NULL); + } + + return ret; } gboolean @@ -383,11 +390,9 @@ gst_kate_dec_sink_event (GstPad * pad, GstEvent * event) GstKateDec *kd = (GstKateDec *) (gst_object_get_parent (GST_OBJECT (pad))); gboolean res = TRUE; - g_return_val_if_fail (kd != NULL, FALSE); + GST_LOG_OBJECT (pad, "Event on sink pad: %s", GST_EVENT_TYPE_NAME (event)); - GST_LOG_OBJECT (kd, "Event on sink pad: %s", GST_EVENT_TYPE_NAME (event)); - - // Delay events till we've set caps + /* Delay events till we've set caps */ if (gst_kate_util_decoder_base_queue_event (&kd->decoder, event, &gst_kate_dec_sink_handle_event, pad)) { gst_object_unref (kd); @@ -407,9 +412,7 @@ gst_kate_dec_sink_handle_event (GstPad * pad, GstEvent * event) GstKateDec *kd = (GstKateDec *) (gst_object_get_parent (GST_OBJECT (pad))); gboolean res = TRUE; - g_return_val_if_fail (kd != NULL, FALSE); - - GST_LOG_OBJECT (kd, "Handling event on sink pad: %s", + GST_LOG_OBJECT (pad, "Handling event on sink pad: %s", GST_EVENT_TYPE_NAME (event)); switch (GST_EVENT_TYPE (event)) { @@ -444,11 +447,8 @@ gst_kate_dec_src_get_caps (GstPad * pad) GstKateDec *kd = (GstKateDec *) (gst_object_get_parent (GST_OBJECT (pad))); GstCaps *caps; - g_return_val_if_fail (kd != NULL, FALSE); - if (kd->src_caps) { - GST_DEBUG_OBJECT (kd, "We have src caps (%s)", - gst_caps_to_string (kd->src_caps)); + GST_DEBUG_OBJECT (kd, "We have src caps %" GST_PTR_FORMAT, kd->src_caps); caps = kd->src_caps; } else { GST_DEBUG_OBJECT (kd, "We have no src caps, using template caps"); diff --git a/ext/kate/gstkatetiger.c b/ext/kate/gstkatetiger.c index 67d046aaa8..533aef4c8b 100644 --- a/ext/kate/gstkatetiger.c +++ b/ext/kate/gstkatetiger.c @@ -564,8 +564,8 @@ gst_kate_tiger_kate_chain (GstPad * pad, GstBuffer * buf) GST_KATE_TIGER_MUTEX_LOCK (tiger); - GST_LOG_OBJECT (tiger, "Got kate buffer, caps %s", - gst_caps_to_string (GST_BUFFER_CAPS (buf))); + GST_LOG_OBJECT (tiger, "Got kate buffer, caps %" GST_PTR_FORMAT, + GST_BUFFER_CAPS (buf)); /* Unfortunately, it can happen that the start of the stream is not sent, for instance if there's a stream selector upstream, which is switched diff --git a/ext/kate/gstkateutil.c b/ext/kate/gstkateutil.c index 14f4258083..b873d0aca1 100644 --- a/ext/kate/gstkateutil.c +++ b/ext/kate/gstkateutil.c @@ -282,12 +282,10 @@ gst_kate_util_decoder_base_chain_kate_packet (GstKateDecoderBase * decoder, } else { *src_caps = gst_caps_new_simple ("text/x-pango-markup", NULL); } - GST_INFO_OBJECT (element, "Setting src caps to %s", - gst_caps_to_string (*src_caps)); + GST_INFO_OBJECT (srcpad, "Setting caps: %" GST_PTR_FORMAT, *src_caps); if (!gst_pad_set_caps (srcpad, *src_caps)) { - GST_ERROR_OBJECT (element, - "Failed to renegotiate caps for pad %s:%s", - GST_DEBUG_PAD_NAME (srcpad)); + GST_ERROR_OBJECT (srcpad, "Failed to set caps %" GST_PTR_FORMAT, + *src_caps); } } if (decoder->k.ki->language && *decoder->k.ki->language) { From a197901b82c22db9d8441eadba8063151c994b22 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Sun, 2 Jan 2011 15:11:52 +0000 Subject: [PATCH 239/448] jack: move plugin to gst-plugins-good https://bugzilla.gnome.org/show_bug.cgi?id=621929 --- LICENSE_readme | 2 - Makefile.am | 4 + configure.ac | 11 - docs/plugins/Makefile.am | 2 - .../plugins/gst-plugins-bad-plugins-docs.sgml | 3 - .../gst-plugins-bad-plugins-sections.txt | 30 - docs/plugins/gst-plugins-bad-plugins.args | 86 +- .../plugins/gst-plugins-bad-plugins.hierarchy | 5 - docs/plugins/inspect/plugin-jack.xml | 43 - ext/Makefile.am | 8 - ext/jack/.gitignore | 1 - ext/jack/Makefile.am | 12 - ext/jack/README | 4 - ext/jack/gstjack.c | 95 -- ext/jack/gstjack.h | 55 -- ext/jack/gstjackaudioclient.c | 525 ----------- ext/jack/gstjackaudioclient.h | 59 -- ext/jack/gstjackaudiosink.c | 852 ----------------- ext/jack/gstjackaudiosink.h | 78 -- ext/jack/gstjackaudiosrc.c | 874 ------------------ ext/jack/gstjackaudiosrc.h | 97 -- ext/jack/gstjackringbuffer.h | 88 -- ext/jack/gstjackutil.c | 114 --- ext/jack/gstjackutil.h | 30 - gst-plugins-bad.spec.in | 1 - tests/examples/Makefile.am | 9 +- tests/examples/jack/Makefile.am | 6 - tests/examples/jack/jack_client.c | 79 -- 28 files changed, 19 insertions(+), 3154 deletions(-) delete mode 100644 docs/plugins/inspect/plugin-jack.xml delete mode 100644 ext/jack/.gitignore delete mode 100644 ext/jack/Makefile.am delete mode 100644 ext/jack/README delete mode 100644 ext/jack/gstjack.c delete mode 100644 ext/jack/gstjack.h delete mode 100644 ext/jack/gstjackaudioclient.c delete mode 100644 ext/jack/gstjackaudioclient.h delete mode 100644 ext/jack/gstjackaudiosink.c delete mode 100644 ext/jack/gstjackaudiosink.h delete mode 100644 ext/jack/gstjackaudiosrc.c delete mode 100644 ext/jack/gstjackaudiosrc.h delete mode 100644 ext/jack/gstjackringbuffer.h delete mode 100644 ext/jack/gstjackutil.c delete mode 100644 ext/jack/gstjackutil.h delete mode 100644 tests/examples/jack/Makefile.am delete mode 100644 tests/examples/jack/jack_client.c diff --git a/LICENSE_readme b/LICENSE_readme index 718d6d23bd..3afe96ebc0 100644 --- a/LICENSE_readme +++ b/LICENSE_readme @@ -37,8 +37,6 @@ xvid libxvidcore (http://www.xvid.org/) Plugins derived from GPL code are as follows: dvdreadsrc libdvdread (http://www.dtek.chalmers.se/groups/dvd/) -jack libjack (http://jackit.sourceforge.net/) - Note libjack is LGPL, but plugin is GPL. monoscope None (Algorithm by Ralph Loader, Joerg Walter, Richard Boulton, and Andy Lo A Foe) rtjpeg None (Erik Walthinsen's algorithm) diff --git a/Makefile.am b/Makefile.am index 402b8b9575..a8ac17d49b 100644 --- a/Makefile.am +++ b/Makefile.am @@ -46,6 +46,7 @@ CRUFT_FILES = \ $(top_builddir)/common/shave-libtool \ $(top_builddir)/ext/alsaspdif/.libs/*.{so,dll,DLL,dylib} \ $(top_builddir)/ext/ivorbis/.libs/*.{so,dll,DLL,dylib} \ + $(top_builddir)/ext/jack/.libs/*.{so,dll,DLL,dylib} \ $(top_builddir)/gst/aacparse/.libs/*.{so,dll,DLL,dylib} \ $(top_builddir)/gst/amrparse/.libs/*.{so,dll,DLL,dylib} \ $(top_builddir)/gst/flacparse/.libs/*.{so,dll,DLL,dylib} \ @@ -60,6 +61,7 @@ CRUFT_FILES = \ $(top_builddir)/tests/check/elements/selector \ $(top_builddir)/tests/check/elements/valve \ $(top_builddir)/tests/check/pipelines/metadata \ + $(top_builddir)/tests/examples/jack/jack_client \ $(top_builddir)/tests/examples/switch/switcher \ $(top_builddir)/tests/icles/output-selector-test \ $(top_builddir)/tests/icles/test-oss4 @@ -74,8 +76,10 @@ CRUFT_DIRS = \ $(top_srcdir)/gst/valve \ $(top_srcdir)/tests/examples/shapewipe \ $(top_srcdir)/tests/examples/switch \ + $(top_srcdir)/tests/examples/jack \ $(top_srcdir)/ext/alsaspdif \ $(top_srcdir)/ext/ivorbis \ + $(top_srcdir)/ext/jack \ $(top_srcdir)/ext/metadata include $(top_srcdir)/common/cruft.mak diff --git a/configure.ac b/configure.ac index 50f03565e7..31b09ed66a 100644 --- a/configure.ac +++ b/configure.ac @@ -888,14 +888,6 @@ AG_GST_CHECK_FEATURE(GSM, [GSM library], gsmenc gsmdec, [ AC_SUBST(GSM_LIBS) ]) -dnl *** Jack *** -translit(dnm, m, l) AM_CONDITIONAL(USE_JACK, true) -AG_GST_CHECK_FEATURE(JACK, Jack, jack, [ - PKG_CHECK_MODULES(JACK, jack >= 0.99.10, HAVE_JACK="yes", HAVE_JACK="no") - AC_SUBST(JACK_CFLAGS) - AC_SUBST(JACK_LIBS) -]) - dnl *** jp2k *** translit(dnm, m, l) AM_CONDITIONAL(USE_JP2K, true) AG_GST_CHECK_FEATURE(JP2K, [jp2k], jp2kdec jp2kenc, [ @@ -1607,7 +1599,6 @@ AM_CONDITIONAL(USE_FAAD, false) AM_CONDITIONAL(USE_FBDEV, false) AM_CONDITIONAL(USE_FLITE, false) AM_CONDITIONAL(USE_GSM, false) -AM_CONDITIONAL(USE_JACK, false) AM_CONDITIONAL(USE_JP2K, false) AM_CONDITIONAL(USE_KATE, false) AM_CONDITIONAL(USE_TIGER, false) @@ -1812,7 +1803,6 @@ tests/examples/camerabin2/Makefile tests/examples/directfb/Makefile tests/examples/mxf/Makefile tests/examples/scaletempo/Makefile -tests/examples/jack/Makefile tests/icles/Makefile ext/amrwbenc/Makefile ext/assrender/Makefile @@ -1830,7 +1820,6 @@ ext/faac/Makefile ext/faad/Makefile ext/flite/Makefile ext/gsm/Makefile -ext/jack/Makefile ext/jp2k/Makefile ext/kate/Makefile ext/ladspa/Makefile diff --git a/docs/plugins/Makefile.am b/docs/plugins/Makefile.am index 6a151ffea1..63719918fa 100644 --- a/docs/plugins/Makefile.am +++ b/docs/plugins/Makefile.am @@ -99,8 +99,6 @@ EXTRA_HFILES = \ $(top_srcdir)/ext/dts/gstdtsdec.h \ $(top_srcdir)/ext/faac/gstfaac.h \ $(top_srcdir)/ext/faad/gstfaad.h \ - $(top_srcdir)/ext/jack/gstjackaudiosrc.h \ - $(top_srcdir)/ext/jack/gstjackaudiosink.h \ $(top_srcdir)/ext/kate/gstkateenc.h \ $(top_srcdir)/ext/kate/gstkatedec.h \ $(top_srcdir)/ext/kate/gstkateparse.h \ diff --git a/docs/plugins/gst-plugins-bad-plugins-docs.sgml b/docs/plugins/gst-plugins-bad-plugins-docs.sgml index f4b5455045..d102a0691d 100644 --- a/docs/plugins/gst-plugins-bad-plugins-docs.sgml +++ b/docs/plugins/gst-plugins-bad-plugins-docs.sgml @@ -69,8 +69,6 @@ - - @@ -169,7 +167,6 @@ - diff --git a/docs/plugins/gst-plugins-bad-plugins-sections.txt b/docs/plugins/gst-plugins-bad-plugins-sections.txt index 764f641af2..fe5104ad51 100644 --- a/docs/plugins/gst-plugins-bad-plugins-sections.txt +++ b/docs/plugins/gst-plugins-bad-plugins-sections.txt @@ -806,36 +806,6 @@ GST_TYPE_IVF_PARSE gst_ivf_parse_get_type
-
-element-jackaudiosrc -jackaudiosrc -GstJackAudioSrc - -GstJackAudioSrcClass -GST_JACK_AUDIO_SRC -GST_JACK_AUDIO_SRC_CLASS -GST_JACK_AUDIO_SRC_GET_CLASS -GST_IS_JACK_AUDIO_SRC -GST_IS_JACK_AUDIO_SRC_CLASS -GST_TYPE_JACK_AUDIO_SRC -gst_jack_audio_src_get_type -
- -
-element-jackaudiosink -jackaudiosink -GstJackAudioSink - -GstJackAudioSinkClass -GST_JACK_AUDIO_SINK -GST_JACK_AUDIO_SINK_CLASS -GST_JACK_AUDIO_SINK_GET_CLASS -GST_IS_JACK_AUDIO_SINK -GST_IS_JACK_AUDIO_SINK_CLASS -GST_TYPE_JACK_AUDIO_SINK -gst_jack_audio_sink_get_type -
-
element-jpegparse jpegparse diff --git a/docs/plugins/gst-plugins-bad-plugins.args b/docs/plugins/gst-plugins-bad-plugins.args index 9d4bdf5ca3..8ca527f247 100644 --- a/docs/plugins/gst-plugins-bad-plugins.args +++ b/docs/plugins/gst-plugins-bad-plugins.args @@ -1538,36 +1538,6 @@ 1 - -GstJackAudioSink::connect -GstJackConnect - -rw -Connect -Specify how the output ports will be connected. -Automatically connect ports to physical ports - - - -GstJackAudioSink::server -gchar* - -rw -Server -The Jack server to connect to (NULL = default). -NULL - - - -GstJackAudioSink::client -JackClient* - -rw -JackClient -Handle for jack client. - - - GstDvbSrc::bandwidth GstDvbSrcBandwidth @@ -21953,36 +21923,6 @@ 0 - -GstJackAudioSrc::connect -GstJackConnect - -rw -Connect -Specify how the input ports will be connected. -Automatically connect ports to physical ports - - - -GstJackAudioSrc::server -gchar* - -rw -Server -The Jack server to connect to (NULL = default). -NULL - - - -GstJackAudioSrc::client -JackClient* - -rw -JackClient -Handle for jack client. - - - GstDCCPClientSrc::caps GstCaps* @@ -26530,7 +26470,7 @@ rw physics water density: from 1 to 4. -7.75038e-304 +8.09774e-321 @@ -26570,7 +26510,7 @@ rw splash make a big splash in the center. -0 +2.34994e-310 @@ -26580,7 +26520,7 @@ rw splash make a big splash in the center. -4.77773e-299 +1.82574e-315 @@ -26610,7 +26550,7 @@ rw ratiox x-ratio. -0 +1.47273e-316 @@ -26620,7 +26560,7 @@ rw ratioy y-ratio. -0 +1.85891e-316 @@ -26630,7 +26570,7 @@ rw DelayTime the delay time. -0 +2.18476e-316 @@ -26660,7 +26600,7 @@ rw Color the color of the image. -0 +1.39669e-37 @@ -26680,7 +26620,7 @@ rw Color-R the color of the image. -0 +7.30424e-38 @@ -27010,7 +26950,7 @@ rw lredscale multiplier for downscaling non-edge brightness. -0 +3.40216e-111 @@ -27020,7 +26960,7 @@ rw lthresh threshold for edge lightening. -0 +6.9235e+228 @@ -27030,7 +26970,7 @@ rw lupscale multiplier for upscaling edge brightness. -0 +7.54985e-96 @@ -27200,7 +27140,7 @@ rw blend blend factor. -4.74303e-322 +4.77773e-299 @@ -27390,7 +27330,7 @@ rw HSync the hsync offset. -0 +1.86264e-09 diff --git a/docs/plugins/gst-plugins-bad-plugins.hierarchy b/docs/plugins/gst-plugins-bad-plugins.hierarchy index 511a79e541..84322e7d5a 100644 --- a/docs/plugins/gst-plugins-bad-plugins.hierarchy +++ b/docs/plugins/gst-plugins-bad-plugins.hierarchy @@ -31,7 +31,6 @@ GObject GstApExSink GstNasSink GstSDLAudioSink - GstJackAudioSink GstChecksumSink GstDCCPClientSink GstDCCPServerSink @@ -46,8 +45,6 @@ GObject GstDTMFSrc GstDataURISrc GstPushSrc - GstBaseAudioSrc - GstJackAudioSrc GstDCCPClientSrc GstDCCPServerSrc GstDc1394 @@ -490,8 +487,6 @@ GObject GstRegistry GstRingBuffer GstAudioSinkRingBuffer - GstJackAudioSinkRingBuffer - GstJackAudioSrcRingBuffer GstTask GstTaskPool GstSignalObject diff --git a/docs/plugins/inspect/plugin-jack.xml b/docs/plugins/inspect/plugin-jack.xml deleted file mode 100644 index baa370192a..0000000000 --- a/docs/plugins/inspect/plugin-jack.xml +++ /dev/null @@ -1,43 +0,0 @@ - - jack - Jack elements - ../../ext/jack/.libs/libgstjack.so - libgstjack.so - 0.10.20.1 - LGPL - gst-plugins-bad - GStreamer Bad Plug-ins git - Unknown package origin - - - jackaudiosink - Audio Sink (Jack) - Sink/Audio - Output to Jack - Wim Taymans <wim@fluendo.com> - - - sink - sink - always -
audio/x-raw-float, endianness=(int){ 1234 }, width=(int)32, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ]
-
-
-
- - jackaudiosrc - Audio Source (Jack) - Source/Audio - Input from Jack - Tristan Matthews <tristan@sat.qc.ca> - - - src - source - always -
audio/x-raw-float, endianness=(int){ 1234 }, width=(int)32, rate=(int)[ 1, 2147483647 ], channels=(int)[ 1, 2147483647 ]
-
-
-
-
-
\ No newline at end of file diff --git a/ext/Makefile.am b/ext/Makefile.am index a9a7c8b5f4..9b670d4dbb 100644 --- a/ext/Makefile.am +++ b/ext/Makefile.am @@ -136,12 +136,6 @@ endif HERMES_DIR= # endif -if USE_JACK -JACK_DIR=jack -else -JACK_DIR= -endif - if USE_JP2K JP2K_DIR = jp2k else @@ -398,7 +392,6 @@ SUBDIRS=\ $(GSM_DIR) \ $(G729_DIR) \ $(HERMES_DIR) \ - $(JACK_DIR) \ $(JP2K_DIR) \ $(KATE_DIR) \ $(LADSPA_DIR) \ @@ -453,7 +446,6 @@ DIST_SUBDIRS = \ gsettings \ gsm \ ladspa \ - jack \ jp2k \ kate \ libmms \ diff --git a/ext/jack/.gitignore b/ext/jack/.gitignore deleted file mode 100644 index 916f265c7a..0000000000 --- a/ext/jack/.gitignore +++ /dev/null @@ -1 +0,0 @@ -*.loT diff --git a/ext/jack/Makefile.am b/ext/jack/Makefile.am deleted file mode 100644 index ede70594bd..0000000000 --- a/ext/jack/Makefile.am +++ /dev/null @@ -1,12 +0,0 @@ - -plugin_LTLIBRARIES = libgstjack.la - -libgstjack_la_SOURCES = gstjackutil.c gstjack.c gstjackaudiosrc.c gstjackaudiosink.c gstjackaudioclient.c -libgstjack_la_CFLAGS = $(GST_PLUGINS_BAD_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) $(JACK_CFLAGS) -libgstjack_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) -lgstaudio-$(GST_MAJORMINOR) $(JACK_LIBS) -libgstjack_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) -libgstjack_la_LIBTOOLFLAGS = --tag=disable-static - -noinst_HEADERS = gstjackutil.h gstjackaudiosrc.h gstjackaudiosink.h gstjackaudioclient.h gstjack.h gstjackringbuffer.h - -EXTRA_DIST = README diff --git a/ext/jack/README b/ext/jack/README deleted file mode 100644 index 2bb97bebad..0000000000 --- a/ext/jack/README +++ /dev/null @@ -1,4 +0,0 @@ -to be written, la dee da - -jackit.sf.net - diff --git a/ext/jack/gstjack.c b/ext/jack/gstjack.c deleted file mode 100644 index 371a9e934f..0000000000 --- a/ext/jack/gstjack.c +++ /dev/null @@ -1,95 +0,0 @@ -/* GStreamer Jack plugins - * Copyright (C) 2006 Wim Taymans - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "gstjackaudiosrc.h" -#include "gstjackaudiosink.h" - -GType -gst_jack_connect_get_type (void) -{ - static GType jack_connect_type = 0; - static const GEnumValue jack_connect[] = { - {GST_JACK_CONNECT_NONE, - "Don't automatically connect ports to physical ports", "none"}, - {GST_JACK_CONNECT_AUTO, - "Automatically connect ports to physical ports", "auto"}, - {GST_JACK_CONNECT_AUTO_FORCED, - "Automatically connect ports to as many physical ports as possible", - "auto-forced"}, - {0, NULL, NULL}, - }; - - if (!jack_connect_type) { - jack_connect_type = g_enum_register_static ("GstJackConnect", jack_connect); - } - return jack_connect_type; -} - - -static gpointer -gst_jack_client_copy (gpointer jclient) -{ - return jclient; -} - - -static void -gst_jack_client_free (gpointer jclient) -{ - return; -} - - -GType -gst_jack_client_get_type (void) -{ - static GType type; /* 0 */ - - if (type == 0) { - /* hackish, but makes it show up nicely in gst-inspect */ - type = g_boxed_type_register_static ("JackClient", - (GBoxedCopyFunc) gst_jack_client_copy, - (GBoxedFreeFunc) gst_jack_client_free); - } - - return type; -} - -static gboolean -plugin_init (GstPlugin * plugin) -{ - if (!gst_element_register (plugin, "jackaudiosrc", GST_RANK_PRIMARY, - GST_TYPE_JACK_AUDIO_SRC)) - return FALSE; - if (!gst_element_register (plugin, "jackaudiosink", GST_RANK_PRIMARY, - GST_TYPE_JACK_AUDIO_SINK)) - return FALSE; - - return TRUE; -} - -GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, - GST_VERSION_MINOR, - "jack", - "Jack elements", - plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/ext/jack/gstjack.h b/ext/jack/gstjack.h deleted file mode 100644 index d923866dfa..0000000000 --- a/ext/jack/gstjack.h +++ /dev/null @@ -1,55 +0,0 @@ -/* GStreamer - * Copyright (C) 2006 Wim Taymans - * - * gstjack.h: - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef _GST_JACK_H_ -#define _GST_JACK_H_ - - -/** - * GstJackConnect: - * @GST_JACK_CONNECT_NONE: Don't automatically connect to physical ports. - * In this mode, the element will accept any number of input channels and will - * create (but not connect) an output port for each channel. - * @GST_JACK_CONNECT_AUTO: In this mode, the element will try to connect each - * output port to a random physical jack input pin. The sink will - * expose the number of physical channels on its pad caps. - * @GST_JACK_CONNECT_AUTO_FORCED: In this mode, the element will try to connect each - * output port to a random physical jack input pin. The element will accept any number - * of input channels. - * - * Specify how the output ports will be connected. - */ - -typedef enum { - GST_JACK_CONNECT_NONE, - GST_JACK_CONNECT_AUTO, - GST_JACK_CONNECT_AUTO_FORCED -} GstJackConnect; - -typedef jack_default_audio_sample_t sample_t; - -#define GST_TYPE_JACK_CONNECT (gst_jack_connect_get_type()) -#define GST_TYPE_JACK_CLIENT (gst_jack_client_get_type ()) - -GType gst_jack_client_get_type(void); -GType gst_jack_connect_get_type(void); - -#endif // _GST_JACK_H_ diff --git a/ext/jack/gstjackaudioclient.c b/ext/jack/gstjackaudioclient.c deleted file mode 100644 index 1789edb60d..0000000000 --- a/ext/jack/gstjackaudioclient.c +++ /dev/null @@ -1,525 +0,0 @@ -/* GStreamer - * Copyright (C) 2006 Wim Taymans - * - * gstjackaudioclient.c: jack audio client implementation - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include - -#include "gstjackaudioclient.h" - -GST_DEBUG_CATEGORY_STATIC (gst_jack_audio_client_debug); -#define GST_CAT_DEFAULT gst_jack_audio_client_debug - -void -gst_jack_audio_client_init (void) -{ - GST_DEBUG_CATEGORY_INIT (gst_jack_audio_client_debug, "jackclient", 0, - "jackclient helpers"); -} - -/* a list of global connections indexed by id and server. */ -G_LOCK_DEFINE_STATIC (connections_lock); -static GList *connections; - -/* the connection to a server */ -typedef struct -{ - gint refcount; - GMutex *lock; - GCond *flush_cond; - - /* id/server pair and the connection */ - gchar *id; - gchar *server; - jack_client_t *client; - - /* lists of GstJackAudioClients */ - gint n_clients; - GList *src_clients; - GList *sink_clients; -} GstJackAudioConnection; - -/* an object sharing a jack_client_t connection. */ -struct _GstJackAudioClient -{ - GstJackAudioConnection *conn; - - GstJackClientType type; - gboolean active; - gboolean deactivate; - - void (*shutdown) (void *arg); - JackProcessCallback process; - JackBufferSizeCallback buffer_size; - JackSampleRateCallback sample_rate; - gpointer user_data; -}; - -typedef jack_default_audio_sample_t sample_t; - -typedef struct -{ - jack_nframes_t nframes; - gpointer user_data; -} JackCB; - -static int -jack_process_cb (jack_nframes_t nframes, void *arg) -{ - GstJackAudioConnection *conn = (GstJackAudioConnection *) arg; - GList *walk; - int res = 0; - - g_mutex_lock (conn->lock); - /* call sources first, then sinks. Sources will either push data into the - * ringbuffer of the sinks, which will then pull the data out of it, or - * sinks will pull the data from the sources. */ - for (walk = conn->src_clients; walk; walk = g_list_next (walk)) { - GstJackAudioClient *client = (GstJackAudioClient *) walk->data; - - /* only call active clients */ - if ((client->active || client->deactivate) && client->process) { - res = client->process (nframes, client->user_data); - if (client->deactivate) { - client->deactivate = FALSE; - g_cond_signal (conn->flush_cond); - } - } - } - for (walk = conn->sink_clients; walk; walk = g_list_next (walk)) { - GstJackAudioClient *client = (GstJackAudioClient *) walk->data; - - /* only call active clients */ - if ((client->active || client->deactivate) && client->process) { - res = client->process (nframes, client->user_data); - if (client->deactivate) { - client->deactivate = FALSE; - g_cond_signal (conn->flush_cond); - } - } - } - g_mutex_unlock (conn->lock); - - return res; -} - -/* we error out */ -static int -jack_sample_rate_cb (jack_nframes_t nframes, void *arg) -{ - return 0; -} - -/* we error out */ -static int -jack_buffer_size_cb (jack_nframes_t nframes, void *arg) -{ - return 0; -} - -static void -jack_shutdown_cb (void *arg) -{ - GstJackAudioConnection *conn = (GstJackAudioConnection *) arg; - GList *walk; - - GST_DEBUG ("disconnect client %s from server %s", conn->id, - GST_STR_NULL (conn->server)); - - g_mutex_lock (conn->lock); - for (walk = conn->src_clients; walk; walk = g_list_next (walk)) { - GstJackAudioClient *client = (GstJackAudioClient *) walk->data; - - if (client->shutdown) - client->shutdown (client->user_data); - } - for (walk = conn->sink_clients; walk; walk = g_list_next (walk)) { - GstJackAudioClient *client = (GstJackAudioClient *) walk->data; - - if (client->shutdown) - client->shutdown (client->user_data); - } - g_mutex_unlock (conn->lock); -} - -typedef struct -{ - const gchar *id; - const gchar *server; -} FindData; - -static gint -connection_find (GstJackAudioConnection * conn, FindData * data) -{ - /* id's must match */ - if (strcmp (conn->id, data->id)) - return 1; - - /* both the same or NULL */ - if (conn->server == data->server) - return 0; - - /* we cannot compare NULL */ - if (conn->server == NULL || data->server == NULL) - return 1; - - if (strcmp (conn->server, data->server)) - return 1; - - return 0; -} - -/* make a connection with @id and @server. Returns NULL on failure with the - * status set. */ -static GstJackAudioConnection * -gst_jack_audio_make_connection (const gchar * id, const gchar * server, - jack_client_t * jclient, jack_status_t * status) -{ - GstJackAudioConnection *conn; - jack_options_t options; - gint res; - - *status = 0; - - GST_DEBUG ("new client %s, connecting to server %s", id, - GST_STR_NULL (server)); - - /* never start a server */ - options = JackNoStartServer; - /* if we have a servername, use it */ - if (server != NULL) - options |= JackServerName; - /* open the client */ - if (jclient == NULL) - jclient = jack_client_open (id, options, status, server); - if (jclient == NULL) - goto could_not_open; - - /* now create object */ - conn = g_new (GstJackAudioConnection, 1); - conn->refcount = 1; - conn->lock = g_mutex_new (); - conn->flush_cond = g_cond_new (); - conn->id = g_strdup (id); - conn->server = g_strdup (server); - conn->client = jclient; - conn->n_clients = 0; - conn->src_clients = NULL; - conn->sink_clients = NULL; - - /* set our callbacks */ - jack_set_process_callback (jclient, jack_process_cb, conn); - /* these callbacks cause us to error */ - jack_set_buffer_size_callback (jclient, jack_buffer_size_cb, conn); - jack_set_sample_rate_callback (jclient, jack_sample_rate_cb, conn); - jack_on_shutdown (jclient, jack_shutdown_cb, conn); - - /* all callbacks are set, activate the client */ - if ((res = jack_activate (jclient))) - goto could_not_activate; - - GST_DEBUG ("opened connection %p", conn); - - return conn; - - /* ERRORS */ -could_not_open: - { - GST_DEBUG ("failed to open jack client, %d", *status); - return NULL; - } -could_not_activate: - { - GST_ERROR ("Could not activate client (%d)", res); - *status = JackFailure; - g_mutex_free (conn->lock); - g_free (conn->id); - g_free (conn->server); - g_free (conn); - return NULL; - } -} - -static GstJackAudioConnection * -gst_jack_audio_get_connection (const gchar * id, const gchar * server, - jack_client_t * jclient, jack_status_t * status) -{ - GstJackAudioConnection *conn; - GList *found; - FindData data; - - GST_DEBUG ("getting connection for id %s, server %s", id, - GST_STR_NULL (server)); - - data.id = id; - data.server = server; - - G_LOCK (connections_lock); - found = - g_list_find_custom (connections, &data, (GCompareFunc) connection_find); - if (found != NULL && jclient != NULL) { - /* we found it, increase refcount and return it */ - conn = (GstJackAudioConnection *) found->data; - conn->refcount++; - - GST_DEBUG ("found connection %p", conn); - } else { - /* make new connection */ - conn = gst_jack_audio_make_connection (id, server, jclient, status); - if (conn != NULL) { - GST_DEBUG ("created connection %p", conn); - /* add to list on success */ - connections = g_list_prepend (connections, conn); - } else { - GST_WARNING ("could not create connection"); - } - } - G_UNLOCK (connections_lock); - - return conn; -} - -static void -gst_jack_audio_unref_connection (GstJackAudioConnection * conn) -{ - gint res; - gboolean zero; - - GST_DEBUG ("unref connection %p refcnt %d", conn, conn->refcount); - - G_LOCK (connections_lock); - conn->refcount--; - if ((zero = (conn->refcount == 0))) { - GST_DEBUG ("closing connection %p", conn); - /* remove from list, we can release the mutex after removing the connection - * from the list because after that, nobody can access the connection anymore. */ - connections = g_list_remove (connections, conn); - } - G_UNLOCK (connections_lock); - - /* if we are zero, close and cleanup the connection */ - if (zero) { - /* don't use conn->lock here. two reasons: - * - * 1) its not necessary: jack_deactivate() will not return until the JACK thread - * associated with this connection is cleaned up by a thread join, hence - * no more callbacks can occur or be in progress. - * - * 2) it would deadlock anyway, because jack_deactivate() will sleep - * waiting for the JACK thread, and can thus cause deadlock in - * jack_process_cb() - */ - if ((res = jack_deactivate (conn->client))) { - /* we only warn, this means the server is probably shut down and the client - * is gone anyway. */ - GST_WARNING ("Could not deactivate Jack client (%d)", res); - } - /* close connection */ - if ((res = jack_client_close (conn->client))) { - /* we assume the client is gone. */ - GST_WARNING ("close failed (%d)", res); - } - - /* free resources */ - g_mutex_free (conn->lock); - g_cond_free (conn->flush_cond); - g_free (conn->id); - g_free (conn->server); - g_free (conn); - } -} - -static void -gst_jack_audio_connection_add_client (GstJackAudioConnection * conn, - GstJackAudioClient * client) -{ - g_mutex_lock (conn->lock); - switch (client->type) { - case GST_JACK_CLIENT_SOURCE: - conn->src_clients = g_list_append (conn->src_clients, client); - conn->n_clients++; - break; - case GST_JACK_CLIENT_SINK: - conn->sink_clients = g_list_append (conn->sink_clients, client); - conn->n_clients++; - break; - default: - g_warning ("trying to add unknown client type"); - break; - } - g_mutex_unlock (conn->lock); -} - -static void -gst_jack_audio_connection_remove_client (GstJackAudioConnection * conn, - GstJackAudioClient * client) -{ - g_mutex_lock (conn->lock); - switch (client->type) { - case GST_JACK_CLIENT_SOURCE: - conn->src_clients = g_list_remove (conn->src_clients, client); - conn->n_clients--; - break; - case GST_JACK_CLIENT_SINK: - conn->sink_clients = g_list_remove (conn->sink_clients, client); - conn->n_clients--; - break; - default: - g_warning ("trying to remove unknown client type"); - break; - } - g_mutex_unlock (conn->lock); -} - -/** - * gst_jack_audio_client_get: - * @id: the client id - * @server: the server to connect to or NULL for the default server - * @type: the client type - * @shutdown: a callback when the jack server shuts down - * @process: a callback when samples are available - * @buffer_size: a callback when the buffer_size changes - * @sample_rate: a callback when the sample_rate changes - * @user_data: user data passed to the callbacks - * @status: pointer to hold the jack status code in case of errors - * - * Get the jack client connection for @id and @server. Connections to the same - * @id and @server will receive the same physical Jack client connection and - * will therefore be scheduled in the same process callback. - * - * Returns: a #GstJackAudioClient. - */ -GstJackAudioClient * -gst_jack_audio_client_new (const gchar * id, const gchar * server, - jack_client_t * jclient, GstJackClientType type, - void (*shutdown) (void *arg), JackProcessCallback process, - JackBufferSizeCallback buffer_size, JackSampleRateCallback sample_rate, - gpointer user_data, jack_status_t * status) -{ - GstJackAudioClient *client; - GstJackAudioConnection *conn; - - g_return_val_if_fail (id != NULL, NULL); - g_return_val_if_fail (status != NULL, NULL); - - /* first get a connection for the id/server pair */ - conn = gst_jack_audio_get_connection (id, server, jclient, status); - if (conn == NULL) - goto no_connection; - - GST_INFO ("new client %s", id); - - /* make new client using the connection */ - client = g_new (GstJackAudioClient, 1); - client->active = client->deactivate = FALSE; - client->conn = conn; - client->type = type; - client->shutdown = shutdown; - client->process = process; - client->buffer_size = buffer_size; - client->sample_rate = sample_rate; - client->user_data = user_data; - - /* add the client to the connection */ - gst_jack_audio_connection_add_client (conn, client); - - return client; - - /* ERRORS */ -no_connection: - { - GST_DEBUG ("Could not get server connection (%d)", *status); - return NULL; - } -} - -/** - * gst_jack_audio_client_free: - * @client: a #GstJackAudioClient - * - * Free the resources used by @client. - */ -void -gst_jack_audio_client_free (GstJackAudioClient * client) -{ - GstJackAudioConnection *conn; - - g_return_if_fail (client != NULL); - - GST_INFO ("free client"); - - conn = client->conn; - - /* remove from connection first so that it's not scheduled anymore after this - * call */ - gst_jack_audio_connection_remove_client (conn, client); - gst_jack_audio_unref_connection (conn); - - g_free (client); -} - -/** - * gst_jack_audio_client_get_client: - * @client: a #GstJackAudioClient - * - * Get the jack audio client for @client. This function is used to perform - * operations on the jack server from this client. - * - * Returns: The jack audio client. - */ -jack_client_t * -gst_jack_audio_client_get_client (GstJackAudioClient * client) -{ - g_return_val_if_fail (client != NULL, NULL); - - /* no lock needed, the connection and the client does not change - * once the client is created. */ - return client->conn->client; -} - -/** - * gst_jack_audio_client_set_active: - * @client: a #GstJackAudioClient - * @active: new mode for the client - * - * Activate or deactive @client. When a client is activated it will receive - * callbacks when data should be processed. - * - * Returns: 0 if all ok. - */ -gint -gst_jack_audio_client_set_active (GstJackAudioClient * client, gboolean active) -{ - g_return_val_if_fail (client != NULL, -1); - - /* make sure that we are not dispatching the client */ - g_mutex_lock (client->conn->lock); - if (client->active && !active) { - /* we need to process once more to flush the port */ - client->deactivate = TRUE; - - /* need to wait for process_cb run once more */ - while (client->deactivate) - g_cond_wait (client->conn->flush_cond, client->conn->lock); - } - client->active = active; - g_mutex_unlock (client->conn->lock); - - return 0; -} diff --git a/ext/jack/gstjackaudioclient.h b/ext/jack/gstjackaudioclient.h deleted file mode 100644 index 5fb7e35444..0000000000 --- a/ext/jack/gstjackaudioclient.h +++ /dev/null @@ -1,59 +0,0 @@ -/* GStreamer - * Copyright (C) 2006 Wim Taymans - * - * gstjackaudioclient.h: - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef __GST_JACK_AUDIO_CLIENT_H__ -#define __GST_JACK_AUDIO_CLIENT_H__ - -#include - -#include - -G_BEGIN_DECLS - -typedef enum -{ - GST_JACK_CLIENT_SOURCE, - GST_JACK_CLIENT_SINK -} GstJackClientType; - -typedef struct _GstJackAudioClient GstJackAudioClient; - -void gst_jack_audio_client_init (void); - - -GstJackAudioClient * gst_jack_audio_client_new (const gchar *id, const gchar *server, - jack_client_t *jclient, - GstJackClientType type, - void (*shutdown) (void *arg), - JackProcessCallback process, - JackBufferSizeCallback buffer_size, - JackSampleRateCallback sample_rate, - gpointer user_data, - jack_status_t *status); -void gst_jack_audio_client_free (GstJackAudioClient *client); - -jack_client_t * gst_jack_audio_client_get_client (GstJackAudioClient *client); - -gboolean gst_jack_audio_client_set_active (GstJackAudioClient *client, gboolean active); - -G_END_DECLS - -#endif /* __GST_JACK_AUDIO_CLIENT_H__ */ diff --git a/ext/jack/gstjackaudiosink.c b/ext/jack/gstjackaudiosink.c deleted file mode 100644 index 32bf1af3e4..0000000000 --- a/ext/jack/gstjackaudiosink.c +++ /dev/null @@ -1,852 +0,0 @@ -/* GStreamer - * Copyright (C) 2006 Wim Taymans - * - * gstjackaudiosink.c: jack audio sink implementation - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -/** - * SECTION:element-jackaudiosink - * @see_also: #GstBaseAudioSink, #GstRingBuffer - * - * A Sink that outputs data to Jack ports. - * - * It will create N Jack ports named out_<name>_<num> where - * <name> is the element name and <num> is starting from 1. - * Each port corresponds to a gstreamer channel. - * - * The samplerate as exposed on the caps is always the same as the samplerate of - * the jack server. - * - * When the #GstJackAudioSink:connect property is set to auto, this element - * will try to connect each output port to a random physical jack input pin. In - * this mode, the sink will expose the number of physical channels on its pad - * caps. - * - * When the #GstJackAudioSink:connect property is set to none, the element will - * accept any number of input channels and will create (but not connect) an - * output port for each channel. - * - * The element will generate an error when the Jack server is shut down when it - * was PAUSED or PLAYING. This element does not support dynamic rate and buffer - * size changes at runtime. - * - * - * Example launch line - * |[ - * gst-launch audiotestsrc ! jackaudiosink - * ]| Play a sine wave to using jack. - * - * - * Last reviewed on 2006-11-30 (0.10.4) - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include - -#include "gstjackaudiosink.h" -#include "gstjackringbuffer.h" - -GST_DEBUG_CATEGORY_STATIC (gst_jack_audio_sink_debug); -#define GST_CAT_DEFAULT gst_jack_audio_sink_debug - -static gboolean -gst_jack_audio_sink_allocate_channels (GstJackAudioSink * sink, gint channels) -{ - jack_client_t *client; - - client = gst_jack_audio_client_get_client (sink->client); - - /* remove ports we don't need */ - while (sink->port_count > channels) { - jack_port_unregister (client, sink->ports[--sink->port_count]); - } - - /* alloc enough output ports */ - sink->ports = g_realloc (sink->ports, sizeof (jack_port_t *) * channels); - - /* create an output port for each channel */ - while (sink->port_count < channels) { - gchar *name; - - /* port names start from 1 and are local to the element */ - name = - g_strdup_printf ("out_%s_%d", GST_ELEMENT_NAME (sink), - sink->port_count + 1); - sink->ports[sink->port_count] = - jack_port_register (client, name, JACK_DEFAULT_AUDIO_TYPE, - JackPortIsOutput, 0); - if (sink->ports[sink->port_count] == NULL) - return FALSE; - - sink->port_count++; - - g_free (name); - } - return TRUE; -} - -static void -gst_jack_audio_sink_free_channels (GstJackAudioSink * sink) -{ - gint res, i = 0; - jack_client_t *client; - - client = gst_jack_audio_client_get_client (sink->client); - - /* get rid of all ports */ - while (sink->port_count) { - GST_LOG_OBJECT (sink, "unregister port %d", i); - if ((res = jack_port_unregister (client, sink->ports[i++]))) { - GST_DEBUG_OBJECT (sink, "unregister of port failed (%d)", res); - } - sink->port_count--; - } - g_free (sink->ports); - sink->ports = NULL; -} - -/* ringbuffer abstract base class */ -static GType -gst_jack_ring_buffer_get_type (void) -{ - static GType ringbuffer_type = 0; - - if (!ringbuffer_type) { - static const GTypeInfo ringbuffer_info = { - sizeof (GstJackRingBufferClass), - NULL, - NULL, - (GClassInitFunc) gst_jack_ring_buffer_class_init, - NULL, - NULL, - sizeof (GstJackRingBuffer), - 0, - (GInstanceInitFunc) gst_jack_ring_buffer_init, - NULL - }; - - ringbuffer_type = - g_type_register_static (GST_TYPE_RING_BUFFER, - "GstJackAudioSinkRingBuffer", &ringbuffer_info, 0); - } - return ringbuffer_type; -} - -static void -gst_jack_ring_buffer_class_init (GstJackRingBufferClass * klass) -{ - GObjectClass *gobject_class; - GstObjectClass *gstobject_class; - GstRingBufferClass *gstringbuffer_class; - - gobject_class = (GObjectClass *) klass; - gstobject_class = (GstObjectClass *) klass; - gstringbuffer_class = (GstRingBufferClass *) klass; - - ring_parent_class = g_type_class_peek_parent (klass); - - gstringbuffer_class->open_device = - GST_DEBUG_FUNCPTR (gst_jack_ring_buffer_open_device); - gstringbuffer_class->close_device = - GST_DEBUG_FUNCPTR (gst_jack_ring_buffer_close_device); - gstringbuffer_class->acquire = - GST_DEBUG_FUNCPTR (gst_jack_ring_buffer_acquire); - gstringbuffer_class->release = - GST_DEBUG_FUNCPTR (gst_jack_ring_buffer_release); - gstringbuffer_class->start = GST_DEBUG_FUNCPTR (gst_jack_ring_buffer_start); - gstringbuffer_class->pause = GST_DEBUG_FUNCPTR (gst_jack_ring_buffer_pause); - gstringbuffer_class->resume = GST_DEBUG_FUNCPTR (gst_jack_ring_buffer_start); - gstringbuffer_class->stop = GST_DEBUG_FUNCPTR (gst_jack_ring_buffer_stop); - - gstringbuffer_class->delay = GST_DEBUG_FUNCPTR (gst_jack_ring_buffer_delay); -} - -/* this is the callback of jack. This should RT-safe. - */ -static int -jack_process_cb (jack_nframes_t nframes, void *arg) -{ - GstJackAudioSink *sink; - GstRingBuffer *buf; - GstJackRingBuffer *abuf; - gint readseg, len; - guint8 *readptr; - gint i, j, flen, channels; - sample_t **buffers, *data; - - buf = GST_RING_BUFFER_CAST (arg); - abuf = GST_JACK_RING_BUFFER_CAST (arg); - sink = GST_JACK_AUDIO_SINK (GST_OBJECT_PARENT (buf)); - - channels = buf->spec.channels; - - /* alloc pointers to samples */ - buffers = g_alloca (sizeof (sample_t *) * channels); - - /* get target buffers */ - for (i = 0; i < channels; i++) { - buffers[i] = (sample_t *) jack_port_get_buffer (sink->ports[i], nframes); - } - - if (gst_ring_buffer_prepare_read (buf, &readseg, &readptr, &len)) { - flen = len / channels; - - /* the number of samples must be exactly the segment size */ - if (nframes * sizeof (sample_t) != flen) - goto wrong_size; - - GST_DEBUG_OBJECT (sink, "copy %d frames: %p, %d bytes, %d channels", - nframes, readptr, flen, channels); - data = (sample_t *) readptr; - - /* the samples in the ringbuffer have the channels interleaved, we need to - * deinterleave into the jack target buffers */ - for (i = 0; i < nframes; i++) { - for (j = 0; j < channels; j++) { - buffers[j][i] = *data++; - } - } - - /* clear written samples in the ringbuffer */ - gst_ring_buffer_clear (buf, readseg); - - /* we wrote one segment */ - gst_ring_buffer_advance (buf, 1); - } else { - GST_DEBUG_OBJECT (sink, "write %d frames silence", nframes); - /* We are not allowed to read from the ringbuffer, write silence to all - * jack output buffers */ - for (i = 0; i < channels; i++) { - memset (buffers[i], 0, nframes * sizeof (sample_t)); - } - } - return 0; - - /* ERRORS */ -wrong_size: - { - GST_ERROR_OBJECT (sink, "nbytes (%d) != flen (%d)", - (gint) (nframes * sizeof (sample_t)), flen); - return 1; - } -} - -/* we error out */ -static int -jack_sample_rate_cb (jack_nframes_t nframes, void *arg) -{ - GstJackAudioSink *sink; - GstJackRingBuffer *abuf; - - abuf = GST_JACK_RING_BUFFER_CAST (arg); - sink = GST_JACK_AUDIO_SINK (GST_OBJECT_PARENT (arg)); - - if (abuf->sample_rate != -1 && abuf->sample_rate != nframes) - goto not_supported; - - return 0; - - /* ERRORS */ -not_supported: - { - GST_ELEMENT_ERROR (sink, RESOURCE, SETTINGS, - (NULL), ("Jack changed the sample rate, which is not supported")); - return 1; - } -} - -/* we error out */ -static int -jack_buffer_size_cb (jack_nframes_t nframes, void *arg) -{ - GstJackAudioSink *sink; - GstJackRingBuffer *abuf; - - abuf = GST_JACK_RING_BUFFER_CAST (arg); - sink = GST_JACK_AUDIO_SINK (GST_OBJECT_PARENT (arg)); - - if (abuf->buffer_size != -1 && abuf->buffer_size != nframes) - goto not_supported; - - return 0; - - /* ERRORS */ -not_supported: - { - GST_ELEMENT_ERROR (sink, RESOURCE, SETTINGS, - (NULL), ("Jack changed the buffer size, which is not supported")); - return 1; - } -} - -static void -jack_shutdown_cb (void *arg) -{ - GstJackAudioSink *sink; - - sink = GST_JACK_AUDIO_SINK (GST_OBJECT_PARENT (arg)); - - GST_DEBUG_OBJECT (sink, "shutdown"); - - GST_ELEMENT_ERROR (sink, RESOURCE, NOT_FOUND, - (NULL), ("Jack server shutdown")); -} - -static void -gst_jack_ring_buffer_init (GstJackRingBuffer * buf, - GstJackRingBufferClass * g_class) -{ - buf->channels = -1; - buf->buffer_size = -1; - buf->sample_rate = -1; -} - -/* the _open_device method should make a connection with the server - */ -static gboolean -gst_jack_ring_buffer_open_device (GstRingBuffer * buf) -{ - GstJackAudioSink *sink; - jack_status_t status = 0; - const gchar *name; - - sink = GST_JACK_AUDIO_SINK (GST_OBJECT_PARENT (buf)); - - GST_DEBUG_OBJECT (sink, "open"); - - name = g_get_application_name (); - if (!name) - name = "GStreamer"; - - sink->client = gst_jack_audio_client_new (name, sink->server, - sink->jclient, - GST_JACK_CLIENT_SINK, - jack_shutdown_cb, - jack_process_cb, jack_buffer_size_cb, jack_sample_rate_cb, buf, &status); - if (sink->client == NULL) - goto could_not_open; - - GST_DEBUG_OBJECT (sink, "opened"); - - return TRUE; - - /* ERRORS */ -could_not_open: - { - if (status & JackServerFailed) { - GST_ELEMENT_ERROR (sink, RESOURCE, NOT_FOUND, - (_("Jack server not found")), - ("Cannot connect to the Jack server (status %d)", status)); - } else { - GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_WRITE, - (NULL), ("Jack client open error (status %d)", status)); - } - return FALSE; - } -} - -/* close the connection with the server - */ -static gboolean -gst_jack_ring_buffer_close_device (GstRingBuffer * buf) -{ - GstJackAudioSink *sink; - - sink = GST_JACK_AUDIO_SINK (GST_OBJECT_PARENT (buf)); - - GST_DEBUG_OBJECT (sink, "close"); - - gst_jack_audio_sink_free_channels (sink); - gst_jack_audio_client_free (sink->client); - sink->client = NULL; - - return TRUE; -} - -/* allocate a buffer and setup resources to process the audio samples of - * the format as specified in @spec. - * - * We allocate N jack ports, one for each channel. If we are asked to - * automatically make a connection with physical ports, we connect as many - * ports as there are physical ports, leaving leftover ports unconnected. - * - * It is assumed that samplerate and number of channels are acceptable since our - * getcaps method will always provide correct values. If unacceptable caps are - * received for some reason, we fail here. - */ -static gboolean -gst_jack_ring_buffer_acquire (GstRingBuffer * buf, GstRingBufferSpec * spec) -{ - GstJackAudioSink *sink; - GstJackRingBuffer *abuf; - const char **ports; - gint sample_rate, buffer_size; - gint i, channels, res; - jack_client_t *client; - - sink = GST_JACK_AUDIO_SINK (GST_OBJECT_PARENT (buf)); - abuf = GST_JACK_RING_BUFFER_CAST (buf); - - GST_DEBUG_OBJECT (sink, "acquire"); - - client = gst_jack_audio_client_get_client (sink->client); - - /* sample rate must be that of the server */ - sample_rate = jack_get_sample_rate (client); - if (sample_rate != spec->rate) - goto wrong_samplerate; - - channels = spec->channels; - - if (!gst_jack_audio_sink_allocate_channels (sink, channels)) - goto out_of_ports; - - buffer_size = jack_get_buffer_size (client); - - /* the segment size in bytes, this is large enough to hold a buffer of 32bit floats - * for all channels */ - spec->segsize = buffer_size * sizeof (gfloat) * channels; - spec->latency_time = gst_util_uint64_scale (spec->segsize, - (GST_SECOND / GST_USECOND), spec->rate * spec->bytes_per_sample); - /* segtotal based on buffer-time latency */ - spec->segtotal = spec->buffer_time / spec->latency_time; - if (spec->segtotal < 2) { - spec->segtotal = 2; - spec->buffer_time = spec->latency_time * spec->segtotal; - } - - GST_DEBUG_OBJECT (sink, "buffer time: %" G_GINT64_FORMAT " usec", - spec->buffer_time); - GST_DEBUG_OBJECT (sink, "latency time: %" G_GINT64_FORMAT " usec", - spec->latency_time); - GST_DEBUG_OBJECT (sink, "buffer_size %d, segsize %d, segtotal %d", - buffer_size, spec->segsize, spec->segtotal); - - /* allocate the ringbuffer memory now */ - buf->data = gst_buffer_new_and_alloc (spec->segtotal * spec->segsize); - memset (GST_BUFFER_DATA (buf->data), 0, GST_BUFFER_SIZE (buf->data)); - - if ((res = gst_jack_audio_client_set_active (sink->client, TRUE))) - goto could_not_activate; - - /* if we need to automatically connect the ports, do so now. We must do this - * after activating the client. */ - if (sink->connect == GST_JACK_CONNECT_AUTO - || sink->connect == GST_JACK_CONNECT_AUTO_FORCED) { - /* find all the physical input ports. A physical input port is a port - * associated with a hardware device. Someone needs connect to a physical - * port in order to hear something. */ - ports = jack_get_ports (client, NULL, NULL, - JackPortIsPhysical | JackPortIsInput); - if (ports == NULL) { - /* no ports? fine then we don't do anything except for posting a warning - * message. */ - GST_ELEMENT_WARNING (sink, RESOURCE, NOT_FOUND, (NULL), - ("No physical input ports found, leaving ports unconnected")); - goto done; - } - - for (i = 0; i < channels; i++) { - /* stop when all input ports are exhausted */ - if (ports[i] == NULL) { - /* post a warning that we could not connect all ports */ - GST_ELEMENT_WARNING (sink, RESOURCE, NOT_FOUND, (NULL), - ("No more physical ports, leaving some ports unconnected")); - break; - } - GST_DEBUG_OBJECT (sink, "try connecting to %s", - jack_port_name (sink->ports[i])); - /* connect the port to a physical port */ - res = jack_connect (client, jack_port_name (sink->ports[i]), ports[i]); - if (res != 0 && res != EEXIST) - goto cannot_connect; - } - free (ports); - } -done: - - abuf->sample_rate = sample_rate; - abuf->buffer_size = buffer_size; - abuf->channels = spec->channels; - - return TRUE; - - /* ERRORS */ -wrong_samplerate: - { - GST_ELEMENT_ERROR (sink, RESOURCE, SETTINGS, (NULL), - ("Wrong samplerate, server is running at %d and we received %d", - sample_rate, spec->rate)); - return FALSE; - } -out_of_ports: - { - GST_ELEMENT_ERROR (sink, RESOURCE, SETTINGS, (NULL), - ("Cannot allocate more Jack ports")); - return FALSE; - } -could_not_activate: - { - GST_ELEMENT_ERROR (sink, RESOURCE, SETTINGS, (NULL), - ("Could not activate client (%d:%s)", res, g_strerror (res))); - return FALSE; - } -cannot_connect: - { - GST_ELEMENT_ERROR (sink, RESOURCE, SETTINGS, (NULL), - ("Could not connect output ports to physical ports (%d:%s)", - res, g_strerror (res))); - free (ports); - return FALSE; - } -} - -/* function is called with LOCK */ -static gboolean -gst_jack_ring_buffer_release (GstRingBuffer * buf) -{ - GstJackAudioSink *sink; - GstJackRingBuffer *abuf; - gint res; - - abuf = GST_JACK_RING_BUFFER_CAST (buf); - sink = GST_JACK_AUDIO_SINK (GST_OBJECT_PARENT (buf)); - - GST_DEBUG_OBJECT (sink, "release"); - - if ((res = gst_jack_audio_client_set_active (sink->client, FALSE))) { - /* we only warn, this means the server is probably shut down and the client - * is gone anyway. */ - GST_ELEMENT_WARNING (sink, RESOURCE, CLOSE, (NULL), - ("Could not deactivate Jack client (%d)", res)); - } - - abuf->channels = -1; - abuf->buffer_size = -1; - abuf->sample_rate = -1; - - /* free the buffer */ - gst_buffer_unref (buf->data); - buf->data = NULL; - - return TRUE; -} - -static gboolean -gst_jack_ring_buffer_start (GstRingBuffer * buf) -{ - GstJackAudioSink *sink; - - sink = GST_JACK_AUDIO_SINK (GST_OBJECT_PARENT (buf)); - - GST_DEBUG_OBJECT (sink, "start"); - - return TRUE; -} - -static gboolean -gst_jack_ring_buffer_pause (GstRingBuffer * buf) -{ - GstJackAudioSink *sink; - - sink = GST_JACK_AUDIO_SINK (GST_OBJECT_PARENT (buf)); - - GST_DEBUG_OBJECT (sink, "pause"); - - return TRUE; -} - -static gboolean -gst_jack_ring_buffer_stop (GstRingBuffer * buf) -{ - GstJackAudioSink *sink; - - sink = GST_JACK_AUDIO_SINK (GST_OBJECT_PARENT (buf)); - - GST_DEBUG_OBJECT (sink, "stop"); - - return TRUE; -} - -static guint -gst_jack_ring_buffer_delay (GstRingBuffer * buf) -{ - GstJackAudioSink *sink; - guint i, res = 0, latency; - jack_client_t *client; - - sink = GST_JACK_AUDIO_SINK (GST_OBJECT_PARENT (buf)); - client = gst_jack_audio_client_get_client (sink->client); - - for (i = 0; i < sink->port_count; i++) { - latency = jack_port_get_total_latency (client, sink->ports[i]); - if (latency > res) - res = latency; - } - - GST_LOG_OBJECT (sink, "delay %u", res); - - return res; -} - -static GstStaticPadTemplate jackaudiosink_sink_factory = -GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS ("audio/x-raw-float, " - "endianness = (int) { " G_STRINGIFY (G_BYTE_ORDER) " }, " - "width = (int) 32, " - "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]") - ); - -/* AudioSink signals and args */ -enum -{ - /* FILL ME */ - SIGNAL_LAST -}; - -#define DEFAULT_PROP_CONNECT GST_JACK_CONNECT_AUTO -#define DEFAULT_PROP_SERVER NULL - -enum -{ - PROP_0, - PROP_CONNECT, - PROP_SERVER, - PROP_CLIENT, - PROP_LAST -}; - -#define _do_init(bla) \ - GST_DEBUG_CATEGORY_INIT (gst_jack_audio_sink_debug, "jacksink", 0, "jacksink element"); - -GST_BOILERPLATE_FULL (GstJackAudioSink, gst_jack_audio_sink, GstBaseAudioSink, - GST_TYPE_BASE_AUDIO_SINK, _do_init); - -static void gst_jack_audio_sink_dispose (GObject * object); -static void gst_jack_audio_sink_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec); -static void gst_jack_audio_sink_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec); - -static GstCaps *gst_jack_audio_sink_getcaps (GstBaseSink * bsink); -static GstRingBuffer *gst_jack_audio_sink_create_ringbuffer (GstBaseAudioSink * - sink); - -static void -gst_jack_audio_sink_base_init (gpointer g_class) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); - - gst_element_class_set_details_simple (element_class, "Audio Sink (Jack)", - "Sink/Audio", "Output to Jack", "Wim Taymans "); - - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&jackaudiosink_sink_factory)); -} - -static void -gst_jack_audio_sink_class_init (GstJackAudioSinkClass * klass) -{ - GObjectClass *gobject_class; - GstElementClass *gstelement_class; - GstBaseSinkClass *gstbasesink_class; - GstBaseAudioSinkClass *gstbaseaudiosink_class; - - gobject_class = (GObjectClass *) klass; - gstelement_class = (GstElementClass *) klass; - gstbasesink_class = (GstBaseSinkClass *) klass; - gstbaseaudiosink_class = (GstBaseAudioSinkClass *) klass; - - gobject_class->dispose = gst_jack_audio_sink_dispose; - gobject_class->get_property = gst_jack_audio_sink_get_property; - gobject_class->set_property = gst_jack_audio_sink_set_property; - - g_object_class_install_property (gobject_class, PROP_CONNECT, - g_param_spec_enum ("connect", "Connect", - "Specify how the output ports will be connected", - GST_TYPE_JACK_CONNECT, DEFAULT_PROP_CONNECT, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, PROP_SERVER, - g_param_spec_string ("server", "Server", - "The Jack server to connect to (NULL = default)", - DEFAULT_PROP_SERVER, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, PROP_CLIENT, - g_param_spec_boxed ("client", "JackClient", "Handle for jack client", - GST_TYPE_JACK_CLIENT, - GST_PARAM_MUTABLE_READY | G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); - - gstbasesink_class->get_caps = GST_DEBUG_FUNCPTR (gst_jack_audio_sink_getcaps); - - gstbaseaudiosink_class->create_ringbuffer = - GST_DEBUG_FUNCPTR (gst_jack_audio_sink_create_ringbuffer); - - /* ref class from a thread-safe context to work around missing bit of - * thread-safety in GObject */ - g_type_class_ref (GST_TYPE_JACK_RING_BUFFER); - - gst_jack_audio_client_init (); -} - -static void -gst_jack_audio_sink_init (GstJackAudioSink * sink, - GstJackAudioSinkClass * g_class) -{ - sink->connect = DEFAULT_PROP_CONNECT; - sink->server = g_strdup (DEFAULT_PROP_SERVER); - sink->jclient = NULL; - sink->ports = NULL; - sink->port_count = 0; -} - -static void -gst_jack_audio_sink_dispose (GObject * object) -{ - GstJackAudioSink *sink = GST_JACK_AUDIO_SINK (object); - - gst_caps_replace (&sink->caps, NULL); - G_OBJECT_CLASS (parent_class)->dispose (object); -} - -static void -gst_jack_audio_sink_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstJackAudioSink *sink; - - sink = GST_JACK_AUDIO_SINK (object); - - switch (prop_id) { - case PROP_CONNECT: - sink->connect = g_value_get_enum (value); - break; - case PROP_SERVER: - g_free (sink->server); - sink->server = g_value_dup_string (value); - break; - case PROP_CLIENT: - if (GST_STATE (sink) == GST_STATE_NULL || - GST_STATE (sink) == GST_STATE_READY) { - sink->jclient = g_value_get_boxed (value); - } - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_jack_audio_sink_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - GstJackAudioSink *sink; - - sink = GST_JACK_AUDIO_SINK (object); - - switch (prop_id) { - case PROP_CONNECT: - g_value_set_enum (value, sink->connect); - break; - case PROP_SERVER: - g_value_set_string (value, sink->server); - break; - case PROP_CLIENT: - g_value_set_boxed (value, sink->jclient); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static GstCaps * -gst_jack_audio_sink_getcaps (GstBaseSink * bsink) -{ - GstJackAudioSink *sink = GST_JACK_AUDIO_SINK (bsink); - const char **ports; - gint min, max; - gint rate; - jack_client_t *client; - - if (sink->client == NULL) - goto no_client; - - client = gst_jack_audio_client_get_client (sink->client); - - if (sink->connect == GST_JACK_CONNECT_AUTO) { - /* get a port count, this is the number of channels we can automatically - * connect. */ - ports = jack_get_ports (client, NULL, NULL, - JackPortIsPhysical | JackPortIsInput); - max = 0; - if (ports != NULL) { - for (; ports[max]; max++); - free (ports); - } else - max = 0; - } else { - /* we allow any number of pads, something else is going to connect the - * pads. */ - max = G_MAXINT; - } - min = MIN (1, max); - - rate = jack_get_sample_rate (client); - - GST_DEBUG_OBJECT (sink, "got %d-%d ports, samplerate: %d", min, max, rate); - - if (!sink->caps) { - sink->caps = gst_caps_new_simple ("audio/x-raw-float", - "endianness", G_TYPE_INT, G_BYTE_ORDER, - "width", G_TYPE_INT, 32, - "rate", G_TYPE_INT, rate, - "channels", GST_TYPE_INT_RANGE, min, max, NULL); - } - GST_INFO_OBJECT (sink, "returning caps %" GST_PTR_FORMAT, sink->caps); - - return gst_caps_ref (sink->caps); - - /* ERRORS */ -no_client: - { - GST_DEBUG_OBJECT (sink, "device not open, using template caps"); - /* base class will get template caps for us when we return NULL */ - return NULL; - } -} - -static GstRingBuffer * -gst_jack_audio_sink_create_ringbuffer (GstBaseAudioSink * sink) -{ - GstRingBuffer *buffer; - - buffer = g_object_new (GST_TYPE_JACK_RING_BUFFER, NULL); - GST_DEBUG_OBJECT (sink, "created ringbuffer @%p", buffer); - - return buffer; -} diff --git a/ext/jack/gstjackaudiosink.h b/ext/jack/gstjackaudiosink.h deleted file mode 100644 index def423329d..0000000000 --- a/ext/jack/gstjackaudiosink.h +++ /dev/null @@ -1,78 +0,0 @@ -/* GStreamer - * Copyright (C) 2006 Wim Taymans - * - * gstjacksink.h: - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef __GST_JACK_AUDIO_SINK_H__ -#define __GST_JACK_AUDIO_SINK_H__ - -#include - -#include -#include - -#include "gstjack.h" -#include "gstjackaudioclient.h" - -G_BEGIN_DECLS - -#define GST_TYPE_JACK_AUDIO_SINK (gst_jack_audio_sink_get_type()) -#define GST_JACK_AUDIO_SINK(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_JACK_AUDIO_SINK,GstJackAudioSink)) -#define GST_JACK_AUDIO_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_JACK_AUDIO_SINK,GstJackAudioSinkClass)) -#define GST_JACK_AUDIO_SINK_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),GST_TYPE_JACK_AUDIO_SINK,GstJackAudioSinkClass)) -#define GST_IS_JACK_AUDIO_SINK(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_JACK_AUDIO_SINK)) -#define GST_IS_JACK_AUDIO_SINK_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_JACK_AUDIO_SINK)) - -typedef struct _GstJackAudioSink GstJackAudioSink; -typedef struct _GstJackAudioSinkClass GstJackAudioSinkClass; - -/** - * GstJackAudioSink: - * - * Opaque #GstJackAudioSink. - */ -struct _GstJackAudioSink { - GstBaseAudioSink element; - - /*< private >*/ - /* cached caps */ - GstCaps *caps; - - /* properties */ - GstJackConnect connect; - gchar *server; - jack_client_t *jclient; - - /* our client */ - GstJackAudioClient *client; - - /* our ports */ - jack_port_t **ports; - int port_count; -}; - -struct _GstJackAudioSinkClass { - GstBaseAudioSinkClass parent_class; -}; - -GType gst_jack_audio_sink_get_type (void); - -G_END_DECLS - -#endif /* __GST_JACK_AUDIO_SINK_H__ */ diff --git a/ext/jack/gstjackaudiosrc.c b/ext/jack/gstjackaudiosrc.c deleted file mode 100644 index 0ffdb23985..0000000000 --- a/ext/jack/gstjackaudiosrc.c +++ /dev/null @@ -1,874 +0,0 @@ -/* GStreamer - * Copyright (C) 2008 Tristan Matthews - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Alternatively, the contents of this file may be used under the - * GNU Lesser General Public License Version 2.1 (the "LGPL"), in - * which case the following provisions apply instead of the ones - * mentioned above: - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -/** - * SECTION:element-jackaudiosrc - * @see_also: #GstBaseAudioSrc, #GstRingBuffer - * - * A Src that inputs data from Jack ports. - * - * It will create N Jack ports named in_<name>_<num> where - * <name> is the element name and <num> is starting from 1. - * Each port corresponds to a gstreamer channel. - * - * The samplerate as exposed on the caps is always the same as the samplerate of - * the jack server. - * - * When the #GstJackAudioSrc:connect property is set to auto, this element - * will try to connect each input port to a random physical jack output pin. - * - * When the #GstJackAudioSrc:connect property is set to none, the element will - * accept any number of output channels and will create (but not connect) an - * input port for each channel. - * - * The element will generate an error when the Jack server is shut down when it - * was PAUSED or PLAYING. This element does not support dynamic rate and buffer - * size changes at runtime. - * - * - * Example launch line - * |[ - * gst-launch jackaudiosrc connect=0 ! jackaudiosink connect=0 - * ]| Get audio input into gstreamer from jack. - * - * - * Last reviewed on 2008-07-22 (0.10.4) - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include - -#include "gstjackaudiosrc.h" -#include "gstjackringbuffer.h" -#include "gstjackutil.h" - -GST_DEBUG_CATEGORY_STATIC (gst_jack_audio_src_debug); -#define GST_CAT_DEFAULT gst_jack_audio_src_debug - -static gboolean -gst_jack_audio_src_allocate_channels (GstJackAudioSrc * src, gint channels) -{ - jack_client_t *client; - - client = gst_jack_audio_client_get_client (src->client); - - /* remove ports we don't need */ - while (src->port_count > channels) - jack_port_unregister (client, src->ports[--src->port_count]); - - /* alloc enough input ports */ - src->ports = g_realloc (src->ports, sizeof (jack_port_t *) * channels); - src->buffers = g_realloc (src->buffers, sizeof (sample_t *) * channels); - - /* create an input port for each channel */ - while (src->port_count < channels) { - gchar *name; - - /* port names start from 1 and are local to the element */ - name = - g_strdup_printf ("in_%s_%d", GST_ELEMENT_NAME (src), - src->port_count + 1); - src->ports[src->port_count] = - jack_port_register (client, name, JACK_DEFAULT_AUDIO_TYPE, - JackPortIsInput, 0); - if (src->ports[src->port_count] == NULL) - return FALSE; - - src->port_count++; - - g_free (name); - } - return TRUE; -} - -static void -gst_jack_audio_src_free_channels (GstJackAudioSrc * src) -{ - gint res, i = 0; - jack_client_t *client; - - client = gst_jack_audio_client_get_client (src->client); - - /* get rid of all ports */ - while (src->port_count) { - GST_LOG_OBJECT (src, "unregister port %d", i); - if ((res = jack_port_unregister (client, src->ports[i++]))) - GST_DEBUG_OBJECT (src, "unregister of port failed (%d)", res); - - src->port_count--; - } - g_free (src->ports); - src->ports = NULL; - g_free (src->buffers); - src->buffers = NULL; -} - -/* ringbuffer abstract base class */ -static GType -gst_jack_ring_buffer_get_type (void) -{ - static GType ringbuffer_type = 0; - - if (!ringbuffer_type) { - static const GTypeInfo ringbuffer_info = { sizeof (GstJackRingBufferClass), - NULL, - NULL, - (GClassInitFunc) gst_jack_ring_buffer_class_init, - NULL, - NULL, - sizeof (GstJackRingBuffer), - 0, - (GInstanceInitFunc) gst_jack_ring_buffer_init, - NULL - }; - - ringbuffer_type = - g_type_register_static (GST_TYPE_RING_BUFFER, - "GstJackAudioSrcRingBuffer", &ringbuffer_info, 0); - } - return ringbuffer_type; -} - -static void -gst_jack_ring_buffer_class_init (GstJackRingBufferClass * klass) -{ - GObjectClass *gobject_class; - GstObjectClass *gstobject_class; - GstRingBufferClass *gstringbuffer_class; - - gobject_class = (GObjectClass *) klass; - gstobject_class = (GstObjectClass *) klass; - gstringbuffer_class = (GstRingBufferClass *) klass; - - ring_parent_class = g_type_class_peek_parent (klass); - - gstringbuffer_class->open_device = - GST_DEBUG_FUNCPTR (gst_jack_ring_buffer_open_device); - gstringbuffer_class->close_device = - GST_DEBUG_FUNCPTR (gst_jack_ring_buffer_close_device); - gstringbuffer_class->acquire = - GST_DEBUG_FUNCPTR (gst_jack_ring_buffer_acquire); - gstringbuffer_class->release = - GST_DEBUG_FUNCPTR (gst_jack_ring_buffer_release); - gstringbuffer_class->start = GST_DEBUG_FUNCPTR (gst_jack_ring_buffer_start); - gstringbuffer_class->pause = GST_DEBUG_FUNCPTR (gst_jack_ring_buffer_pause); - gstringbuffer_class->resume = GST_DEBUG_FUNCPTR (gst_jack_ring_buffer_start); - gstringbuffer_class->stop = GST_DEBUG_FUNCPTR (gst_jack_ring_buffer_stop); - - gstringbuffer_class->delay = GST_DEBUG_FUNCPTR (gst_jack_ring_buffer_delay); -} - -/* this is the callback of jack. This should be RT-safe. - * Writes samples from the jack input port's buffer to the gst ring buffer. - */ -static int -jack_process_cb (jack_nframes_t nframes, void *arg) -{ - GstJackAudioSrc *src; - GstRingBuffer *buf; - gint len; - guint8 *writeptr; - gint writeseg; - gint channels, i, j, flen; - sample_t *data; - - buf = GST_RING_BUFFER_CAST (arg); - src = GST_JACK_AUDIO_SRC (GST_OBJECT_PARENT (buf)); - - channels = buf->spec.channels; - - /* get input buffers */ - for (i = 0; i < channels; i++) - src->buffers[i] = - (sample_t *) jack_port_get_buffer (src->ports[i], nframes); - - if (gst_ring_buffer_prepare_read (buf, &writeseg, &writeptr, &len)) { - flen = len / channels; - - /* the number of samples must be exactly the segment size */ - if (nframes * sizeof (sample_t) != flen) - goto wrong_size; - - /* the samples in the jack input buffers have to be interleaved into the - * ringbuffer */ - data = (sample_t *) writeptr; - for (i = 0; i < nframes; ++i) - for (j = 0; j < channels; ++j) - *data++ = src->buffers[j][i]; - - GST_DEBUG ("copy %d frames: %p, %d bytes, %d channels", nframes, writeptr, - len / channels, channels); - - /* we wrote one segment */ - gst_ring_buffer_advance (buf, 1); - } - return 0; - - /* ERRORS */ -wrong_size: - { - GST_ERROR_OBJECT (src, "nbytes (%d) != flen (%d)", - (gint) (nframes * sizeof (sample_t)), flen); - return 1; - } -} - -/* we error out */ -static int -jack_sample_rate_cb (jack_nframes_t nframes, void *arg) -{ - GstJackAudioSrc *src; - GstJackRingBuffer *abuf; - - abuf = GST_JACK_RING_BUFFER_CAST (arg); - src = GST_JACK_AUDIO_SRC (GST_OBJECT_PARENT (arg)); - - if (abuf->sample_rate != -1 && abuf->sample_rate != nframes) - goto not_supported; - - return 0; - - /* ERRORS */ -not_supported: - { - GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, - (NULL), ("Jack changed the sample rate, which is not supported")); - return 1; - } -} - -/* we error out */ -static int -jack_buffer_size_cb (jack_nframes_t nframes, void *arg) -{ - GstJackAudioSrc *src; - GstJackRingBuffer *abuf; - - abuf = GST_JACK_RING_BUFFER_CAST (arg); - src = GST_JACK_AUDIO_SRC (GST_OBJECT_PARENT (arg)); - - if (abuf->buffer_size != -1 && abuf->buffer_size != nframes) - goto not_supported; - - return 0; - - /* ERRORS */ -not_supported: - { - GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, - (NULL), ("Jack changed the buffer size, which is not supported")); - return 1; - } -} - -static void -jack_shutdown_cb (void *arg) -{ - GstJackAudioSrc *src; - - src = GST_JACK_AUDIO_SRC (GST_OBJECT_PARENT (arg)); - - GST_DEBUG_OBJECT (src, "shutdown"); - - GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND, - (NULL), ("Jack server shutdown")); -} - -static void -gst_jack_ring_buffer_init (GstJackRingBuffer * buf, - GstJackRingBufferClass * g_class) -{ - buf->channels = -1; - buf->buffer_size = -1; - buf->sample_rate = -1; -} - -/* the _open_device method should make a connection with the server -*/ -static gboolean -gst_jack_ring_buffer_open_device (GstRingBuffer * buf) -{ - GstJackAudioSrc *src; - jack_status_t status = 0; - const gchar *name; - - src = GST_JACK_AUDIO_SRC (GST_OBJECT_PARENT (buf)); - - GST_DEBUG_OBJECT (src, "open"); - - name = g_get_application_name (); - if (!name) - name = "GStreamer"; - - src->client = gst_jack_audio_client_new (name, src->server, - src->jclient, - GST_JACK_CLIENT_SOURCE, - jack_shutdown_cb, - jack_process_cb, jack_buffer_size_cb, jack_sample_rate_cb, buf, &status); - if (src->client == NULL) - goto could_not_open; - - GST_DEBUG_OBJECT (src, "opened"); - - return TRUE; - - /* ERRORS */ -could_not_open: - { - if (status & JackServerFailed) { - GST_ELEMENT_ERROR (src, RESOURCE, NOT_FOUND, - (_("Jack server not found")), - ("Cannot connect to the Jack server (status %d)", status)); - } else { - GST_ELEMENT_ERROR (src, RESOURCE, OPEN_WRITE, - (NULL), ("Jack client open error (status %d)", status)); - } - return FALSE; - } -} - -/* close the connection with the server -*/ -static gboolean -gst_jack_ring_buffer_close_device (GstRingBuffer * buf) -{ - GstJackAudioSrc *src; - - src = GST_JACK_AUDIO_SRC (GST_OBJECT_PARENT (buf)); - - GST_DEBUG_OBJECT (src, "close"); - - gst_jack_audio_src_free_channels (src); - gst_jack_audio_client_free (src->client); - src->client = NULL; - - return TRUE; -} - - -/* allocate a buffer and setup resources to process the audio samples of - * the format as specified in @spec. - * - * We allocate N jack ports, one for each channel. If we are asked to - * automatically make a connection with physical ports, we connect as many - * ports as there are physical ports, leaving leftover ports unconnected. - * - * It is assumed that samplerate and number of channels are acceptable since our - * getcaps method will always provide correct values. If unacceptable caps are - * received for some reason, we fail here. - */ -static gboolean -gst_jack_ring_buffer_acquire (GstRingBuffer * buf, GstRingBufferSpec * spec) -{ - GstJackAudioSrc *src; - GstJackRingBuffer *abuf; - const char **ports; - gint sample_rate, buffer_size; - gint i, channels, res; - jack_client_t *client; - - src = GST_JACK_AUDIO_SRC (GST_OBJECT_PARENT (buf)); - abuf = GST_JACK_RING_BUFFER_CAST (buf); - - GST_DEBUG_OBJECT (src, "acquire"); - - client = gst_jack_audio_client_get_client (src->client); - - /* sample rate must be that of the server */ - sample_rate = jack_get_sample_rate (client); - if (sample_rate != spec->rate) - goto wrong_samplerate; - - channels = spec->channels; - - if (!gst_jack_audio_src_allocate_channels (src, channels)) - goto out_of_ports; - - gst_jack_set_layout_on_caps (&spec->caps, channels); - - buffer_size = jack_get_buffer_size (client); - - /* the segment size in bytes, this is large enough to hold a buffer of 32bit floats - * for all channels */ - spec->segsize = buffer_size * sizeof (gfloat) * channels; - spec->latency_time = gst_util_uint64_scale (spec->segsize, - (GST_SECOND / GST_USECOND), spec->rate * spec->bytes_per_sample); - /* segtotal based on buffer-time latency */ - spec->segtotal = spec->buffer_time / spec->latency_time; - if (spec->segtotal < 2) { - spec->segtotal = 2; - spec->buffer_time = spec->latency_time * spec->segtotal; - } - - GST_DEBUG_OBJECT (src, "buffer time: %" G_GINT64_FORMAT " usec", - spec->buffer_time); - GST_DEBUG_OBJECT (src, "latency time: %" G_GINT64_FORMAT " usec", - spec->latency_time); - GST_DEBUG_OBJECT (src, "buffer_size %d, segsize %d, segtotal %d", - buffer_size, spec->segsize, spec->segtotal); - - /* allocate the ringbuffer memory now */ - buf->data = gst_buffer_new_and_alloc (spec->segtotal * spec->segsize); - memset (GST_BUFFER_DATA (buf->data), 0, GST_BUFFER_SIZE (buf->data)); - - if ((res = gst_jack_audio_client_set_active (src->client, TRUE))) - goto could_not_activate; - - /* if we need to automatically connect the ports, do so now. We must do this - * after activating the client. */ - if (src->connect == GST_JACK_CONNECT_AUTO - || src->connect == GST_JACK_CONNECT_AUTO_FORCED) { - /* find all the physical output ports. A physical output port is a port - * associated with a hardware device. Someone needs connect to a physical - * port in order to capture something. */ - ports = - jack_get_ports (client, NULL, NULL, - JackPortIsPhysical | JackPortIsOutput); - if (ports == NULL) { - /* no ports? fine then we don't do anything except for posting a warning - * message. */ - GST_ELEMENT_WARNING (src, RESOURCE, NOT_FOUND, (NULL), - ("No physical output ports found, leaving ports unconnected")); - goto done; - } - - for (i = 0; i < channels; i++) { - /* stop when all output ports are exhausted */ - if (ports[i] == NULL) { - /* post a warning that we could not connect all ports */ - GST_ELEMENT_WARNING (src, RESOURCE, NOT_FOUND, (NULL), - ("No more physical ports, leaving some ports unconnected")); - break; - } - GST_DEBUG_OBJECT (src, "try connecting to %s", - jack_port_name (src->ports[i])); - - /* connect the physical port to a port */ - res = jack_connect (client, ports[i], jack_port_name (src->ports[i])); - if (res != 0 && res != EEXIST) - goto cannot_connect; - } - free (ports); - } -done: - - abuf->sample_rate = sample_rate; - abuf->buffer_size = buffer_size; - abuf->channels = spec->channels; - - return TRUE; - - /* ERRORS */ -wrong_samplerate: - { - GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, (NULL), - ("Wrong samplerate, server is running at %d and we received %d", - sample_rate, spec->rate)); - return FALSE; - } -out_of_ports: - { - GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, (NULL), - ("Cannot allocate more Jack ports")); - return FALSE; - } -could_not_activate: - { - GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, (NULL), - ("Could not activate client (%d:%s)", res, g_strerror (res))); - return FALSE; - } -cannot_connect: - { - GST_ELEMENT_ERROR (src, RESOURCE, SETTINGS, (NULL), - ("Could not connect input ports to physical ports (%d:%s)", - res, g_strerror (res))); - free (ports); - return FALSE; - } -} - -/* function is called with LOCK */ -static gboolean -gst_jack_ring_buffer_release (GstRingBuffer * buf) -{ - GstJackAudioSrc *src; - GstJackRingBuffer *abuf; - gint res; - - abuf = GST_JACK_RING_BUFFER_CAST (buf); - src = GST_JACK_AUDIO_SRC (GST_OBJECT_PARENT (buf)); - - GST_DEBUG_OBJECT (src, "release"); - - if ((res = gst_jack_audio_client_set_active (src->client, FALSE))) { - /* we only warn, this means the server is probably shut down and the client - * is gone anyway. */ - GST_ELEMENT_WARNING (src, RESOURCE, CLOSE, (NULL), - ("Could not deactivate Jack client (%d)", res)); - } - - abuf->channels = -1; - abuf->buffer_size = -1; - abuf->sample_rate = -1; - - /* free the buffer */ - gst_buffer_unref (buf->data); - buf->data = NULL; - - return TRUE; -} - -static gboolean -gst_jack_ring_buffer_start (GstRingBuffer * buf) -{ - GstJackAudioSrc *src; - - src = GST_JACK_AUDIO_SRC (GST_OBJECT_PARENT (buf)); - - GST_DEBUG_OBJECT (src, "start"); - - return TRUE; -} - -static gboolean -gst_jack_ring_buffer_pause (GstRingBuffer * buf) -{ - GstJackAudioSrc *src; - - src = GST_JACK_AUDIO_SRC (GST_OBJECT_PARENT (buf)); - - GST_DEBUG_OBJECT (src, "pause"); - - return TRUE; -} - -static gboolean -gst_jack_ring_buffer_stop (GstRingBuffer * buf) -{ - GstJackAudioSrc *src; - - src = GST_JACK_AUDIO_SRC (GST_OBJECT_PARENT (buf)); - - GST_DEBUG_OBJECT (src, "stop"); - - return TRUE; -} - -static guint -gst_jack_ring_buffer_delay (GstRingBuffer * buf) -{ - GstJackAudioSrc *src; - guint i, res = 0, latency; - jack_client_t *client; - - src = GST_JACK_AUDIO_SRC (GST_OBJECT_PARENT (buf)); - client = gst_jack_audio_client_get_client (src->client); - - for (i = 0; i < src->port_count; i++) { - latency = jack_port_get_total_latency (client, src->ports[i]); - if (latency > res) - res = latency; - } - - GST_DEBUG_OBJECT (src, "delay %u", res); - - return res; -} - -/* Audiosrc signals and args */ -enum -{ - /* FILL ME */ - LAST_SIGNAL -}; - -#define DEFAULT_PROP_CONNECT GST_JACK_CONNECT_AUTO -#define DEFAULT_PROP_SERVER NULL - -enum -{ - PROP_0, - PROP_CONNECT, - PROP_SERVER, - PROP_CLIENT, - PROP_LAST -}; - - -/* the capabilities of the inputs and outputs. - * - * describe the real formats here. - */ - -static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src", - GST_PAD_SRC, - GST_PAD_ALWAYS, - GST_STATIC_CAPS ("audio/x-raw-float, " - "endianness = (int) { " G_STRINGIFY (G_BYTE_ORDER) " }, " - "width = (int) 32, " - "rate = (int) [ 1, MAX ], " "channels = (int) [ 1, MAX ]") - ); - -#define _do_init(bla) \ - GST_DEBUG_CATEGORY_INIT(gst_jack_audio_src_debug, "jacksrc", 0, "jacksrc element"); - -GST_BOILERPLATE_FULL (GstJackAudioSrc, gst_jack_audio_src, GstBaseAudioSrc, - GST_TYPE_BASE_AUDIO_SRC, _do_init); - -static void gst_jack_audio_src_dispose (GObject * object); -static void gst_jack_audio_src_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec); -static void gst_jack_audio_src_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec); - -static GstCaps *gst_jack_audio_src_getcaps (GstBaseSrc * bsrc); -static GstRingBuffer *gst_jack_audio_src_create_ringbuffer (GstBaseAudioSrc * - src); - -/* GObject vmethod implementations */ - -static void -gst_jack_audio_src_base_init (gpointer gclass) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (gclass); - - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&src_factory)); - gst_element_class_set_details_simple (element_class, "Audio Source (Jack)", - "Source/Audio", - "Input from Jack", "Tristan Matthews "); -} - -/* initialize the jack_audio_src's class */ -static void -gst_jack_audio_src_class_init (GstJackAudioSrcClass * klass) -{ - GObjectClass *gobject_class; - GstElementClass *gstelement_class; - GstBaseSrcClass *gstbasesrc_class; - GstBaseAudioSrcClass *gstbaseaudiosrc_class; - - gobject_class = (GObjectClass *) klass; - gstelement_class = (GstElementClass *) klass; - - gstbasesrc_class = (GstBaseSrcClass *) klass; - gstbaseaudiosrc_class = (GstBaseAudioSrcClass *) klass; - - gobject_class->dispose = gst_jack_audio_src_dispose; - gobject_class->set_property = gst_jack_audio_src_set_property; - gobject_class->get_property = gst_jack_audio_src_get_property; - - g_object_class_install_property (gobject_class, PROP_CONNECT, - g_param_spec_enum ("connect", "Connect", - "Specify how the input ports will be connected", - GST_TYPE_JACK_CONNECT, DEFAULT_PROP_CONNECT, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, PROP_SERVER, - g_param_spec_string ("server", "Server", - "The Jack server to connect to (NULL = default)", - DEFAULT_PROP_SERVER, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, PROP_CLIENT, - g_param_spec_boxed ("client", "JackClient", "Handle for jack client", - GST_TYPE_JACK_CLIENT, - GST_PARAM_MUTABLE_READY | G_PARAM_READWRITE | - G_PARAM_STATIC_STRINGS)); - - gstbasesrc_class->get_caps = GST_DEBUG_FUNCPTR (gst_jack_audio_src_getcaps); - gstbaseaudiosrc_class->create_ringbuffer = - GST_DEBUG_FUNCPTR (gst_jack_audio_src_create_ringbuffer); - - /* ref class from a thread-safe context to work around missing bit of - * thread-safety in GObject */ - g_type_class_ref (GST_TYPE_JACK_RING_BUFFER); - - gst_jack_audio_client_init (); -} - -/* initialize the new element - * instantiate pads and add them to element - * set pad calback functions - * initialize instance structure - */ -static void -gst_jack_audio_src_init (GstJackAudioSrc * src, GstJackAudioSrcClass * gclass) -{ - //gst_base_src_set_live(GST_BASE_SRC (src), TRUE); - src->connect = DEFAULT_PROP_CONNECT; - src->server = g_strdup (DEFAULT_PROP_SERVER); - src->jclient = NULL; - src->ports = NULL; - src->port_count = 0; - src->buffers = NULL; -} - -static void -gst_jack_audio_src_dispose (GObject * object) -{ - GstJackAudioSrc *src = GST_JACK_AUDIO_SRC (object); - - gst_caps_replace (&src->caps, NULL); - G_OBJECT_CLASS (parent_class)->dispose (object); -} - -static void -gst_jack_audio_src_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstJackAudioSrc *src = GST_JACK_AUDIO_SRC (object); - - switch (prop_id) { - case PROP_CONNECT: - src->connect = g_value_get_enum (value); - break; - case PROP_SERVER: - g_free (src->server); - src->server = g_value_dup_string (value); - break; - case PROP_CLIENT: - if (GST_STATE (src) == GST_STATE_NULL || - GST_STATE (src) == GST_STATE_READY) { - src->jclient = g_value_get_boxed (value); - } - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_jack_audio_src_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - GstJackAudioSrc *src = GST_JACK_AUDIO_SRC (object); - - switch (prop_id) { - case PROP_CONNECT: - g_value_set_enum (value, src->connect); - break; - case PROP_SERVER: - g_value_set_string (value, src->server); - break; - case PROP_CLIENT: - g_value_set_boxed (value, src->jclient); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static GstCaps * -gst_jack_audio_src_getcaps (GstBaseSrc * bsrc) -{ - GstJackAudioSrc *src = GST_JACK_AUDIO_SRC (bsrc); - const char **ports; - gint min, max; - gint rate; - jack_client_t *client; - - if (src->client == NULL) - goto no_client; - - client = gst_jack_audio_client_get_client (src->client); - - if (src->connect == GST_JACK_CONNECT_AUTO) { - /* get a port count, this is the number of channels we can automatically - * connect. */ - ports = jack_get_ports (client, NULL, NULL, - JackPortIsPhysical | JackPortIsOutput); - max = 0; - if (ports != NULL) { - for (; ports[max]; max++); - - free (ports); - } else - max = 0; - } else { - /* we allow any number of pads, something else is going to connect the - * pads. */ - max = G_MAXINT; - } - min = MIN (1, max); - - rate = jack_get_sample_rate (client); - - GST_DEBUG_OBJECT (src, "got %d-%d ports, samplerate: %d", min, max, rate); - - if (!src->caps) { - src->caps = gst_caps_new_simple ("audio/x-raw-float", - "endianness", G_TYPE_INT, G_BYTE_ORDER, - "width", G_TYPE_INT, 32, - "rate", G_TYPE_INT, rate, - "channels", GST_TYPE_INT_RANGE, min, max, NULL); - } - GST_INFO_OBJECT (src, "returning caps %" GST_PTR_FORMAT, src->caps); - - return gst_caps_ref (src->caps); - - /* ERRORS */ -no_client: - { - GST_DEBUG_OBJECT (src, "device not open, using template caps"); - /* base class will get template caps for us when we return NULL */ - return NULL; - } -} - -static GstRingBuffer * -gst_jack_audio_src_create_ringbuffer (GstBaseAudioSrc * src) -{ - GstRingBuffer *buffer; - - buffer = g_object_new (GST_TYPE_JACK_RING_BUFFER, NULL); - GST_DEBUG_OBJECT (src, "created ringbuffer @%p", buffer); - - return buffer; -} diff --git a/ext/jack/gstjackaudiosrc.h b/ext/jack/gstjackaudiosrc.h deleted file mode 100644 index 7e99b69df9..0000000000 --- a/ext/jack/gstjackaudiosrc.h +++ /dev/null @@ -1,97 +0,0 @@ -/* GStreamer - * Copyright (C) 2008 Tristan Matthews - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Alternatively, the contents of this file may be used under the - * GNU Lesser General Public License Version 2.1 (the "LGPL"), in - * which case the following provisions apply instead of the ones - * mentioned above: - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef __GST_JACK_AUDIO_SRC_H__ -#define __GST_JACK_AUDIO_SRC_H__ - -#include - -#include -#include - -#include "gstjackaudioclient.h" -#include "gstjack.h" - -G_BEGIN_DECLS - -#define GST_TYPE_JACK_AUDIO_SRC (gst_jack_audio_src_get_type()) -#define GST_JACK_AUDIO_SRC(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_JACK_AUDIO_SRC,GstJackAudioSrc)) -#define GST_JACK_AUDIO_SRC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_JACK_AUDIO_SRC,GstJackAudioSrcClass)) -#define GST_JACK_AUDIO_SRC_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj),GST_TYPE_JACK_AUDIO_SRC,GstJackAudioSrcClass)) -#define GST_IS_JACK_AUDIO_SRC(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_JACK_AUDIO_SRC)) -#define GST_IS_JACK_AUDIO_SRC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_JACK_AUDIO_SRC)) - -typedef struct _GstJackAudioSrc GstJackAudioSrc; -typedef struct _GstJackAudioSrcClass GstJackAudioSrcClass; - -struct _GstJackAudioSrc -{ - GstBaseAudioSrc src; - - /*< private >*/ - /* cached caps */ - GstCaps *caps; - - /* properties */ - GstJackConnect connect; - gchar *server; - jack_client_t *jclient; - - /* our client */ - GstJackAudioClient *client; - - /* our ports */ - jack_port_t **ports; - int port_count; - sample_t **buffers; -}; - -struct _GstJackAudioSrcClass -{ - GstBaseAudioSrcClass parent_class; -}; - -GType gst_jack_audio_src_get_type (void); - -G_END_DECLS - -#endif /* __GST_JACK_AUDIO_SRC_H__ */ diff --git a/ext/jack/gstjackringbuffer.h b/ext/jack/gstjackringbuffer.h deleted file mode 100644 index 266fdfa31d..0000000000 --- a/ext/jack/gstjackringbuffer.h +++ /dev/null @@ -1,88 +0,0 @@ -/* - * GStreamer - * Copyright (C) 2006 Wim Taymans - * Copyright (C) 2008 Tristan Matthews - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - * - * Alternatively, the contents of this file may be used under the - * GNU Lesser General Public License Version 2.1 (the "LGPL"), in - * which case the following provisions apply instead of the ones - * mentioned above: - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef __GST_JACK_RING_BUFFER_H__ -#define __GST_JACK_RING_BUFFER_H__ - -#define GST_TYPE_JACK_RING_BUFFER (gst_jack_ring_buffer_get_type()) -#define GST_JACK_RING_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_JACK_RING_BUFFER,GstJackRingBuffer)) -#define GST_JACK_RING_BUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_JACK_RING_BUFFER,GstJackRingBufferClass)) -#define GST_JACK_RING_BUFFER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_JACK_RING_BUFFER,GstJackRingBufferClass)) -#define GST_JACK_RING_BUFFER_CAST(obj) ((GstJackRingBuffer *)obj) -#define GST_IS_JACK_RING_BUFFER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_JACK_RING_BUFFER)) -#define GST_IS_JACK_RING_BUFFER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_JACK_RING_BUFFER)) - -typedef struct _GstJackRingBuffer GstJackRingBuffer; -typedef struct _GstJackRingBufferClass GstJackRingBufferClass; - -struct _GstJackRingBuffer -{ - GstRingBuffer object; - - gint sample_rate; - gint buffer_size; - gint channels; -}; - -struct _GstJackRingBufferClass -{ - GstRingBufferClass parent_class; -}; - -static void gst_jack_ring_buffer_class_init(GstJackRingBufferClass * klass); -static void gst_jack_ring_buffer_init(GstJackRingBuffer * ringbuffer, - GstJackRingBufferClass * klass); - -static GstRingBufferClass *ring_parent_class = NULL; - -static gboolean gst_jack_ring_buffer_open_device(GstRingBuffer * buf); -static gboolean gst_jack_ring_buffer_close_device(GstRingBuffer * buf); -static gboolean gst_jack_ring_buffer_acquire(GstRingBuffer * buf,GstRingBufferSpec * spec); -static gboolean gst_jack_ring_buffer_release(GstRingBuffer * buf); -static gboolean gst_jack_ring_buffer_start(GstRingBuffer * buf); -static gboolean gst_jack_ring_buffer_pause(GstRingBuffer * buf); -static gboolean gst_jack_ring_buffer_stop(GstRingBuffer * buf); -static guint gst_jack_ring_buffer_delay(GstRingBuffer * buf); - -#endif diff --git a/ext/jack/gstjackutil.c b/ext/jack/gstjackutil.c deleted file mode 100644 index cde84d8e85..0000000000 --- a/ext/jack/gstjackutil.c +++ /dev/null @@ -1,114 +0,0 @@ -/* GStreamer Jack utility functions - * Copyright (C) 2010 Tristan Matthews - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#include "gstjackutil.h" -#include - -static const GstAudioChannelPosition default_positions[8][8] = { - /* 1 channel */ - { - GST_AUDIO_CHANNEL_POSITION_FRONT_MONO, - }, - /* 2 channels */ - { - GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, - GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, - }, - /* 3 channels (2.1) */ - { - GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, - GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, - GST_AUDIO_CHANNEL_POSITION_LFE, /* or FRONT_CENTER for 3.0? */ - }, - /* 4 channels (4.0 or 3.1?) */ - { - GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, - GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, - GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, - GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, - }, - /* 5 channels */ - { - GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, - GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, - GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, - GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, - GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, - }, - /* 6 channels */ - { - GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, - GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, - GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, - GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, - GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, - GST_AUDIO_CHANNEL_POSITION_LFE, - }, - /* 7 channels */ - { - GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, - GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, - GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, - GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, - GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, - GST_AUDIO_CHANNEL_POSITION_LFE, - GST_AUDIO_CHANNEL_POSITION_REAR_CENTER, - }, - /* 8 channels */ - { - GST_AUDIO_CHANNEL_POSITION_FRONT_LEFT, - GST_AUDIO_CHANNEL_POSITION_FRONT_RIGHT, - GST_AUDIO_CHANNEL_POSITION_REAR_LEFT, - GST_AUDIO_CHANNEL_POSITION_REAR_RIGHT, - GST_AUDIO_CHANNEL_POSITION_FRONT_CENTER, - GST_AUDIO_CHANNEL_POSITION_LFE, - GST_AUDIO_CHANNEL_POSITION_SIDE_LEFT, - GST_AUDIO_CHANNEL_POSITION_SIDE_RIGHT, - } -}; - - -/* if channels are less than or equal to 8, we set a default layout, - * otherwise set layout to an array of GST_AUDIO_CHANNEL_POSITION_NONE */ -void -gst_jack_set_layout_on_caps (GstCaps ** caps, gint channels) -{ - int c; - GValue pos = { 0 }; - GValue chanpos = { 0 }; - gst_caps_unref (*caps); - - if (channels <= 8) { - g_assert (channels >= 1); - gst_audio_set_channel_positions (gst_caps_get_structure (*caps, 0), - default_positions[channels - 1]); - } else { - g_value_init (&chanpos, GST_TYPE_ARRAY); - g_value_init (&pos, GST_TYPE_AUDIO_CHANNEL_POSITION); - for (c = 0; c < channels; c++) { - g_value_set_enum (&pos, GST_AUDIO_CHANNEL_POSITION_NONE); - gst_value_array_append_value (&chanpos, &pos); - } - g_value_unset (&pos); - gst_structure_set_value (gst_caps_get_structure (*caps, 0), - "channel-positions", &chanpos); - g_value_unset (&chanpos); - } - gst_caps_ref (*caps); -} diff --git a/ext/jack/gstjackutil.h b/ext/jack/gstjackutil.h deleted file mode 100644 index e330afd5e5..0000000000 --- a/ext/jack/gstjackutil.h +++ /dev/null @@ -1,30 +0,0 @@ -/* GStreamer - * Copyright (C) 2010 Tristan Matthews - * - * gstjackutil.h: - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef _GST_JACK_UTIL_H_ -#define _GST_JACK_UTIL_H_ - -#include - -void -gst_jack_set_layout_on_caps (GstCaps **caps, gint channels); - -#endif // _GST_JACK_UTIL_H_ diff --git a/gst-plugins-bad.spec.in b/gst-plugins-bad.spec.in index 6ad7d763cb..33c8bd887d 100644 --- a/gst-plugins-bad.spec.in +++ b/gst-plugins-bad.spec.in @@ -165,7 +165,6 @@ rm -rf $RPM_BUILD_ROOT @USE_DC1394_TRUE@%{_libdir}/gstreamer-%{majorminor}/libgstdc1394.so @USE_TIMIDITY_TRUE@%{_libdir}/gstreamer-%{majorminor}/libgsttimidity.so @USE_WILDMIDI_TRUE@%{_libdir}/gstreamer-%{majorminor}/libgstwildmidi.so -@USE_JACK_TRUE@%{_libdir}/gstreamer-%{majorminor}/libgstjack.so @USE_SNDFILE_TRUE@%{_libdir}/gstreamer-%{majorminor}/libgstsndfile.so @USE_CELT_TRUE@%{_libdir}/gstreamer-%{majorminor}/libgstcelt.so @USE_MPEG2ENC_TRUE@%{_libdir}/gstreamer-%{majorminor}/libgstmpeg2enc.so diff --git a/tests/examples/Makefile.am b/tests/examples/Makefile.am index 4a158d951a..f085c8b423 100644 --- a/tests/examples/Makefile.am +++ b/tests/examples/Makefile.am @@ -1,9 +1,4 @@ if HAVE_GTK -if USE_JACK -JACK_EXAMPLES=jack -else -JACK_EXAMPLES= -endif GTK_EXAMPLES=camerabin mxf scaletempo camerabin2 else GTK_EXAMPLES= @@ -21,7 +16,7 @@ else CAMERABIN2= endif -SUBDIRS= $(DIRECTFB_DIR) $(GTK_EXAMPLES) $(JACK_EXAMPLES) -DIST_SUBDIRS= camerabin $(CAMERABIN2) directfb jack mxf scaletempo +SUBDIRS= $(DIRECTFB_DIR) $(GTK_EXAMPLES) +DIST_SUBDIRS= camerabin $(CAMERABIN2) directfb mxf scaletempo include $(top_srcdir)/common/parallel-subdirs.mak diff --git a/tests/examples/jack/Makefile.am b/tests/examples/jack/Makefile.am deleted file mode 100644 index 4adfd13142..0000000000 --- a/tests/examples/jack/Makefile.am +++ /dev/null @@ -1,6 +0,0 @@ -noinst_PROGRAMS = jack_client - -jack_client_SOURCES = jack_client.c -jack_client_CFLAGS = $(GST_CFLAGS) $(GTK_CFLAGS) $(JACK_CFLAGS) -jack_client_LDFLAGS = $(GST_LIBS) $(GTK_LIBS) $(JACK_LIBS) - diff --git a/tests/examples/jack/jack_client.c b/tests/examples/jack/jack_client.c deleted file mode 100644 index 99599ab5cb..0000000000 --- a/tests/examples/jack/jack_client.c +++ /dev/null @@ -1,79 +0,0 @@ -/* This app demonstrates the creation and use of a jack client in conjunction - * with the jack plugins. This way, an application can control the jack client - * directly. - */ - -#include -#include -#include - -static gboolean -quit_cb (gpointer data) -{ - gtk_main_quit (); - return FALSE; -} - -int -main (int argc, char **argv) -{ - jack_client_t *src_client, *sink_client; - jack_status_t status; - GstElement *pipeline, *src, *sink; - GstStateChangeReturn ret; - - gst_init (&argc, &argv); - - /* create jack clients */ - src_client = jack_client_open ("src_client", JackNoStartServer, &status); - if (src_client == NULL) { - if (status & JackServerFailed) - g_print ("JACK server not running\n"); - else - g_print ("jack_client_open() failed, status = 0x%2.0x\n", status); - return 1; - } - - sink_client = jack_client_open ("sink_client", JackNoStartServer, &status); - if (sink_client == NULL) { - if (status & JackServerFailed) - g_print ("JACK server not running\n"); - else - g_print ("jack_client_open() failed, status = 0x%2.0x\n", status); - return 1; - } - - /* create gst elements */ - pipeline = gst_pipeline_new ("my_pipeline"); - - src = gst_element_factory_make ("jackaudiosrc", NULL); - sink = gst_element_factory_make ("jackaudiosink", NULL); - - g_object_set (src, "client", src_client, NULL); - g_object_set (sink, "client", sink_client, NULL); - - gst_bin_add_many (GST_BIN (pipeline), src, sink, NULL); - - /* link everything together */ - if (!gst_element_link (src, sink)) { - g_print ("Failed to link elements!\n"); - return 1; - } - - /* run */ - ret = gst_element_set_state (pipeline, GST_STATE_PLAYING); - if (ret == GST_STATE_CHANGE_FAILURE) { - g_print ("Failed to start up pipeline!\n"); - return 1; - } - - /* quit after 5 seconds */ - g_timeout_add (5000, (GSourceFunc) quit_cb, NULL); - gtk_main (); - - /* clean up */ - gst_element_set_state (pipeline, GST_STATE_NULL); - gst_object_unref (pipeline); - - return 0; -} From 73923c4a6e79a8585f8874bbb7140a410d7f64ca Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Fri, 31 Dec 2010 16:20:22 +0000 Subject: [PATCH 240/448] tiger: outline text by default, to make it easier to read https://bugzilla.gnome.org/show_bug.cgi?id=638527 --- ext/kate/gstkatetiger.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/kate/gstkatetiger.c b/ext/kate/gstkatetiger.c index 533aef4c8b..932bb42592 100644 --- a/ext/kate/gstkatetiger.c +++ b/ext/kate/gstkatetiger.c @@ -236,7 +236,7 @@ gst_kate_tiger_class_init (GstKateTigerClass * klass) g_param_spec_enum ("default-font-effect", "Default font effect", "Whether to apply an effect to text by default, for increased readability", gst_kate_tiger_font_effect_get_type (), - tiger_font_plain, + tiger_font_outline, G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (gobject_class, @@ -342,7 +342,7 @@ gst_kate_tiger_init (GstKateTiger * tiger, GstKateTigerClass * gclass) tiger->default_font_desc = NULL; tiger->quality = -1.0; - tiger->default_font_effect = tiger_font_plain; + tiger->default_font_effect = tiger_font_outline; tiger->default_font_effect_strength = 0.5; tiger->default_font_r = 255; tiger->default_font_g = 255; From ea113a79aa6a0fc471a0f79677b354423173350f Mon Sep 17 00:00:00 2001 From: David Schleef Date: Wed, 17 Nov 2010 17:49:17 -0800 Subject: [PATCH 241/448] mpegtsmux: Set random_access_indicator for keyframes --- gst/mpegtsmux/mpegtsmux.c | 2 +- gst/mpegtsmux/tsmux/tsmuxstream.c | 13 ++++++++++++- gst/mpegtsmux/tsmux/tsmuxstream.h | 3 ++- 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/gst/mpegtsmux/mpegtsmux.c b/gst/mpegtsmux/mpegtsmux.c index c185039b10..55f51f6eab 100644 --- a/gst/mpegtsmux/mpegtsmux.c +++ b/gst/mpegtsmux/mpegtsmux.c @@ -712,7 +712,7 @@ mpegtsmux_collected (GstCollectPads * pads, MpegTsMux * mux) } tsmux_stream_add_data (best->stream, GST_BUFFER_DATA (buf), - GST_BUFFER_SIZE (buf), buf, pts, -1); + GST_BUFFER_SIZE (buf), buf, pts, -1, !delta); best->queued_buf = NULL; mux->is_delta = delta; diff --git a/gst/mpegtsmux/tsmux/tsmuxstream.c b/gst/mpegtsmux/tsmux/tsmuxstream.c index 62c244fb2c..88d533a09f 100644 --- a/gst/mpegtsmux/tsmux/tsmuxstream.c +++ b/gst/mpegtsmux/tsmux/tsmuxstream.c @@ -100,6 +100,8 @@ struct TsMuxStreamBuffer gint64 pts; gint64 dts; + gboolean random_access; + void *user_data; }; @@ -372,6 +374,13 @@ tsmux_stream_initialize_pes_packet (TsMuxStream * stream) stream->pi.flags |= TSMUX_PACKET_FLAG_PES_WRITE_PTS; } + if (stream->buffers) { + TsMuxStreamBuffer *buf = (TsMuxStreamBuffer *) (stream->buffers->data); + if (buf->random_access) { + stream->pi.flags |= TSMUX_PACKET_FLAG_RANDOM_ACCESS; + } + } + return TRUE; } @@ -589,6 +598,7 @@ tsmux_stream_write_pes_header (TsMuxStream * stream, guint8 * data) * @user_data: user data to pass to release func * @pts: PTS of access unit in @data * @dts: DTS of access unit in @data + * @random_access: TRUE if random access point (keyframe) * * Submit @len bytes of @data into @stream. @pts and @dts can be set to the * timestamp (against a 90Hz clock) of the first access unit in @data. A @@ -599,7 +609,7 @@ tsmux_stream_write_pes_header (TsMuxStream * stream, guint8 * data) */ void tsmux_stream_add_data (TsMuxStream * stream, guint8 * data, guint len, - void *user_data, gint64 pts, gint64 dts) + void *user_data, gint64 pts, gint64 dts, gboolean random_access) { TsMuxStreamBuffer *packet; @@ -609,6 +619,7 @@ tsmux_stream_add_data (TsMuxStream * stream, guint8 * data, guint len, packet->data = data; packet->size = len; packet->user_data = user_data; + packet->random_access = random_access; packet->pts = pts; packet->dts = dts; diff --git a/gst/mpegtsmux/tsmux/tsmuxstream.h b/gst/mpegtsmux/tsmux/tsmuxstream.h index b384d39a20..47ad842e91 100644 --- a/gst/mpegtsmux/tsmux/tsmuxstream.h +++ b/gst/mpegtsmux/tsmux/tsmuxstream.h @@ -201,7 +201,8 @@ void tsmux_stream_set_buffer_release_func (TsMuxStream *stream, /* Add a new buffer to the pool of available bytes. If pts or dts are not -1, they * indicate the PTS or DTS of the first access unit within this packet */ void tsmux_stream_add_data (TsMuxStream *stream, guint8 *data, guint len, - void *user_data, gint64 pts, gint64 dts); + void *user_data, gint64 pts, gint64 dts, + gboolean random_access); void tsmux_stream_pcr_ref (TsMuxStream *stream); void tsmux_stream_pcr_unref (TsMuxStream *stream); From 94f6f34ace352713d2c7dc39fe1eccf51a4eecee Mon Sep 17 00:00:00 2001 From: David Schleef Date: Sun, 5 Dec 2010 03:29:42 -0800 Subject: [PATCH 242/448] mpegtsmux: Set adaptation flag when appropriate Specifically, when there's stuff to go into the adaptation header. --- gst/mpegtsmux/tsmux/tsmuxstream.c | 1 + 1 file changed, 1 insertion(+) diff --git a/gst/mpegtsmux/tsmux/tsmuxstream.c b/gst/mpegtsmux/tsmux/tsmuxstream.c index 88d533a09f..f147bfcdba 100644 --- a/gst/mpegtsmux/tsmux/tsmuxstream.c +++ b/gst/mpegtsmux/tsmux/tsmuxstream.c @@ -378,6 +378,7 @@ tsmux_stream_initialize_pes_packet (TsMuxStream * stream) TsMuxStreamBuffer *buf = (TsMuxStreamBuffer *) (stream->buffers->data); if (buf->random_access) { stream->pi.flags |= TSMUX_PACKET_FLAG_RANDOM_ACCESS; + stream->pi.flags |= TSMUX_PACKET_FLAG_ADAPTATION; } } From 73d85fa438b92316856071902a26f81f9c0ca733 Mon Sep 17 00:00:00 2001 From: David Schleef Date: Sun, 2 Jan 2011 16:13:56 -0800 Subject: [PATCH 243/448] colorspace: Disable matrixing on big-endian It's broken until someone writes better Orc code. Fixes #631232. --- gst/colorspace/colorspace.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/gst/colorspace/colorspace.c b/gst/colorspace/colorspace.c index 334362ec63..e69ab80a4b 100644 --- a/gst/colorspace/colorspace.c +++ b/gst/colorspace/colorspace.c @@ -1708,6 +1708,7 @@ convert_Y444_AYUV (ColorspaceConvert * convert, guint8 * dest, convert->src_stride[2], convert->width, convert->height); } +#if G_BYTE_ORDER == G_LITTLE_ENDIAN static void convert_AYUV_ARGB (ColorspaceConvert * convert, guint8 * dest, const guint8 * src) @@ -1776,6 +1777,7 @@ convert_I420_BGRA (ColorspaceConvert * convert, guint8 * dest, } } } +#endif @@ -1857,6 +1859,7 @@ static const ColorspaceTransform transforms[] = { {GST_VIDEO_FORMAT_Y444, COLOR_SPEC_NONE, GST_VIDEO_FORMAT_Y42B, COLOR_SPEC_NONE, TRUE, convert_Y444_Y42B}, +#if G_BYTE_ORDER == G_LITTLE_ENDIAN {GST_VIDEO_FORMAT_AYUV, COLOR_SPEC_YUV_BT470_6, GST_VIDEO_FORMAT_ARGB, COLOR_SPEC_RGB, FALSE, convert_AYUV_ARGB}, {GST_VIDEO_FORMAT_AYUV, COLOR_SPEC_YUV_BT470_6, GST_VIDEO_FORMAT_BGRA, @@ -1872,6 +1875,7 @@ static const ColorspaceTransform transforms[] = { {GST_VIDEO_FORMAT_I420, COLOR_SPEC_YUV_BT470_6, GST_VIDEO_FORMAT_BGRA, COLOR_SPEC_RGB, FALSE, convert_I420_BGRA}, +#endif }; static void From 36a3688015ed093e29ab2d6e67827bd475712ea0 Mon Sep 17 00:00:00 2001 From: David Schleef Date: Sun, 2 Jan 2011 19:38:01 -0800 Subject: [PATCH 244/448] element-maker: Add debug category --- tools/gst-element-maker | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/tools/gst-element-maker b/tools/gst-element-maker index fa56baf9e3..aa899b652f 100755 --- a/tools/gst-element-maker +++ b/tools/gst-element-maker @@ -133,6 +133,9 @@ grep -A 10000 '^% includes' $templatedir/$class | tail -n +2|grep -m 1 -B 10000 cat < Date: Mon, 3 Jan 2011 18:13:37 +0200 Subject: [PATCH 245/448] README: fix the example pipeline Fix the obvious outdated parts. Still this README looks outdated and should be updated or removed. --- sys/dvb/README | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sys/dvb/README b/sys/dvb/README index 39bc052f6e..1329da99b9 100644 --- a/sys/dvb/README +++ b/sys/dvb/README @@ -5,10 +5,10 @@ GstDvbSrc makes it possible to view Digital TV with gstreamer. Try: - gst-launch dvbsrc freq=11954 pol=h srate=27500 pids=210:220 - ! flutsdemux es-pids=210:220 name=demux ! queue ! mpeg2dec ! - xvimagesink } - demux. ! queue ! mad ! osssink + gst-launch dvbsrc frequency=11954 polarity=h symbol-rate=27500 pids=210:220 + ! mpegtsdemux es-pids=210:220 name=demux ! queue ! mpeg2dec + ! xvimagesink demux. ! queue ! mad ! audioconvert ! autoaudiosink + From 1ff6806cd430694285a9d71a84cef88a55cf4098 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Fri, 3 Dec 2010 15:23:00 +0100 Subject: [PATCH 246/448] qtmux: remove large-file property Rather, auto-determine if 64-bits fields are needed for a valid result, and stick to plain 32-bits if not needed. API: GstQTMux:large-file (removed) --- gst/qtmux/atoms.c | 39 +++------------------------------------ gst/qtmux/atoms.h | 1 - gst/qtmux/gstqtmux.c | 18 +----------------- gst/qtmux/gstqtmux.h | 1 - 4 files changed, 4 insertions(+), 55 deletions(-) diff --git a/gst/qtmux/atoms.c b/gst/qtmux/atoms.c index 2fcb45f2bf..ebbd7c09ba 100644 --- a/gst/qtmux/atoms.c +++ b/gst/qtmux/atoms.c @@ -613,7 +613,7 @@ atom_co64_init (AtomSTCO64 * co64) { guint8 flags[3] = { 0, 0, 0 }; - atom_full_init (&co64->header, FOURCC_co64, 0, 0, 0, flags); + atom_full_init (&co64->header, FOURCC_stco, 0, 0, 0, flags); atom_array_init (&co64->entries, 256); } @@ -2520,6 +2520,8 @@ static void atom_stco64_add_entry (AtomSTCO64 * stco64, guint64 entry) { atom_array_append (&stco64->entries, entry, 256); + if (entry > G_MAXUINT32) + stco64->header.header.type = FOURCC_co64; } static void @@ -2708,41 +2710,6 @@ atom_moov_update_duration (AtomMOOV * moov) moov->mvex.mehd.fragment_duration = duration; } -static void -atom_set_type (Atom * atom, guint32 fourcc) -{ - atom->type = fourcc; -} - -static void -atom_stbl_set_64bits (AtomSTBL * stbl, gboolean use) -{ - if (use) { - atom_set_type (&stbl->stco64.header.header, FOURCC_co64); - } else { - atom_set_type (&stbl->stco64.header.header, FOURCC_stco); - } -} - -static void -atom_trak_set_64bits (AtomTRAK * trak, gboolean use) -{ - atom_stbl_set_64bits (&trak->mdia.minf.stbl, use); -} - -void -atom_moov_set_64bits (AtomMOOV * moov, gboolean large_file) -{ - GList *traks = moov->traks; - - while (traks) { - AtomTRAK *trak = (AtomTRAK *) traks->data; - - atom_trak_set_64bits (trak, large_file); - traks = g_list_next (traks); - } -} - void atom_moov_set_fragmented (AtomMOOV * moov, gboolean fragmented) { diff --git a/gst/qtmux/atoms.h b/gst/qtmux/atoms.h index d074df429f..b65be8256a 100644 --- a/gst/qtmux/atoms.h +++ b/gst/qtmux/atoms.h @@ -821,7 +821,6 @@ void atom_moov_free (AtomMOOV *moov); guint64 atom_moov_copy_data (AtomMOOV *atom, guint8 **buffer, guint64 *size, guint64* offset); void atom_moov_update_timescale (AtomMOOV *moov, guint32 timescale); void atom_moov_update_duration (AtomMOOV *moov); -void atom_moov_set_64bits (AtomMOOV *moov, gboolean large_file); void atom_moov_set_fragmented (AtomMOOV *moov, gboolean fragmented); void atom_moov_chunks_add_offset (AtomMOOV *moov, guint32 offset); void atom_moov_add_trak (AtomMOOV *moov, AtomTRAK *trak); diff --git a/gst/qtmux/gstqtmux.c b/gst/qtmux/gstqtmux.c index ba5b9aca88..95f52a4a60 100644 --- a/gst/qtmux/gstqtmux.c +++ b/gst/qtmux/gstqtmux.c @@ -118,7 +118,6 @@ enum enum { PROP_0, - PROP_LARGE_FILE, PROP_MOVIE_TIMESCALE, PROP_TRAK_TIMESCALE, PROP_DO_CTTS, @@ -133,7 +132,6 @@ enum #define MDAT_LARGE_FILE_LIMIT ((guint64) 1024 * 1024 * 1024 * 2) #define MAX_TOLERATED_LATENESS (GST_SECOND / 10) -#define DEFAULT_LARGE_FILE FALSE #define DEFAULT_MOVIE_TIMESCALE 1000 #define DEFAULT_TRAK_TIMESCALE 0 #define DEFAULT_DO_CTTS FALSE @@ -229,11 +227,6 @@ gst_qt_mux_class_init (GstQTMuxClass * klass) gobject_class->get_property = gst_qt_mux_get_property; gobject_class->set_property = gst_qt_mux_set_property; - g_object_class_install_property (gobject_class, PROP_LARGE_FILE, - g_param_spec_boolean ("large-file", "Support for large files", - "Uses 64bits to some fields instead of 32bits, " - "providing support for large files", - DEFAULT_LARGE_FILE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (gobject_class, PROP_MOVIE_TIMESCALE, g_param_spec_uint ("movie-timescale", "Movie timescale", "Timescale to use in the movie (units per second)", @@ -1405,23 +1398,20 @@ gst_qt_mux_set_header_on_caps (GstQTMux * mux, GstBuffer * buf) static void gst_qt_mux_configure_moov (GstQTMux * qtmux, guint32 * _timescale) { - gboolean large_file, fragmented; + gboolean fragmented; guint32 timescale; GST_OBJECT_LOCK (qtmux); timescale = qtmux->timescale; - large_file = qtmux->large_file; fragmented = qtmux->fragment_sequence > 0; GST_OBJECT_UNLOCK (qtmux); /* inform lower layers of our property wishes, and determine duration. * Let moov take care of this using its list of traks; * so that released pads are also included */ - GST_DEBUG_OBJECT (qtmux, "Large file support: %d", large_file); GST_DEBUG_OBJECT (qtmux, "Updating timescale to %" G_GUINT32_FORMAT, timescale); atom_moov_update_timescale (qtmux->moov, timescale); - atom_moov_set_64bits (qtmux->moov, large_file); atom_moov_set_fragmented (qtmux->moov, fragmented); atom_moov_update_duration (qtmux->moov); @@ -3075,9 +3065,6 @@ gst_qt_mux_get_property (GObject * object, GST_OBJECT_LOCK (qtmux); switch (prop_id) { - case PROP_LARGE_FILE: - g_value_set_boolean (value, qtmux->large_file); - break; case PROP_MOVIE_TIMESCALE: g_value_set_uint (value, qtmux->timescale); break; @@ -3130,9 +3117,6 @@ gst_qt_mux_set_property (GObject * object, GST_OBJECT_LOCK (qtmux); switch (prop_id) { - case PROP_LARGE_FILE: - qtmux->large_file = g_value_get_boolean (value); - break; case PROP_MOVIE_TIMESCALE: qtmux->timescale = g_value_get_uint (value); break; diff --git a/gst/qtmux/gstqtmux.h b/gst/qtmux/gstqtmux.h index 227eb2abdf..4df0c3e2b9 100644 --- a/gst/qtmux/gstqtmux.h +++ b/gst/qtmux/gstqtmux.h @@ -173,7 +173,6 @@ struct _GstQTMux guint32 trak_timescale; AtomsTreeFlavor flavor; gboolean fast_start; - gboolean large_file; gboolean guess_pts; gchar *fast_start_file_path; gchar *moov_recov_file_path; From 8f174304ee5158a5f407f9ba987d4371099bc4d0 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Mon, 3 Jan 2011 10:43:15 +0100 Subject: [PATCH 247/448] qtmux: add some more documentation --- gst/qtmux/gstqtmux.c | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/gst/qtmux/gstqtmux.c b/gst/qtmux/gstqtmux.c index 95f52a4a60..9ef8caf14a 100644 --- a/gst/qtmux/gstqtmux.c +++ b/gst/qtmux/gstqtmux.c @@ -1,7 +1,9 @@ /* Quicktime muxer plugin for GStreamer * Copyright (C) 2008-2010 Thiago Santos * Copyright (C) 2008 Mark Nauwelaerts - * + * Copyright (C) 2010 Nokia Corporation. All rights reserved. + * Contact: Stefan Kost + * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either @@ -62,6 +64,24 @@ * The fragmented file features defined (only) in ISO Base Media are used by * ISMV files making up (a.o.) Smooth Streaming (ismlmux). * + * A few properties (movie-timescale, + * trak-timescale) allow adjusting + * some technical parameters, which might be useful in (rare) cases to resolve + * compatibility issues in some situations. + * + * Some other properties influence the result more fundamentally. + * A typical mov/mp4 file's metadata (aka moov) is located at the end of the file, + * somewhat contrary to this usually being called "the header". + * However, a faststart file will + * (with some effort) arrange this to be located near start of the file, + * which then allows it e.g. to be played while downloading. + * Alternatively, rather than having one chunk of metadata at start (or end), + * there can be some metadata at start and most of the other data can be spread + * out into fragments of fragment-duration. + * If such fragmented layout is intended for streaming purposes, then + * streamable allows foregoing to add + * index metadata (at the end of file). + * * * Example pipelines * |[ From cd690c2bc3193686535161fe36e920a13c733bb1 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Mon, 3 Jan 2011 16:56:57 +0100 Subject: [PATCH 248/448] qtmux: simplify and fix pts_offset storing In particular, only write a ctts atom if and only if ever a non-zero offset. --- gst/qtmux/atoms.c | 29 ++++++++++++++--------------- gst/qtmux/atoms.h | 8 ++++---- gst/qtmux/atomsrecovery.c | 2 +- gst/qtmux/gstqtmux.c | 15 +++++++-------- 4 files changed, 26 insertions(+), 28 deletions(-) diff --git a/gst/qtmux/atoms.c b/gst/qtmux/atoms.c index ebbd7c09ba..bdba5bc5ad 100644 --- a/gst/qtmux/atoms.c +++ b/gst/qtmux/atoms.c @@ -538,6 +538,7 @@ atom_ctts_init (AtomCTTS * ctts) atom_full_init (&ctts->header, FOURCC_ctts, 0, 0, 0, flags); atom_array_init (&ctts->entries, 128); + ctts->do_pts = FALSE; } static AtomCTTS * @@ -2019,7 +2020,7 @@ atom_stbl_copy_data (AtomSTBL * stbl, guint8 ** buffer, guint64 * size, if (!atom_stsz_copy_data (&stbl->stsz, buffer, size, offset)) { return 0; } - if (stbl->ctts) { + if (stbl->ctts && stbl->ctts->do_pts) { if (!atom_ctts_copy_data (stbl->ctts, buffer, size, offset)) { return 0; } @@ -2553,6 +2554,8 @@ atom_ctts_add_entry (AtomCTTS * ctts, guint32 nsamples, guint32 offset) nentry.samplecount = nsamples; nentry.sampleoffset = offset; atom_array_append (&ctts->entries, nentry, 256); + if (offset != 0) + ctts->do_pts = TRUE; } else { entry->samplecount += nsamples; } @@ -2569,8 +2572,7 @@ atom_stbl_add_ctts_entry (AtomSTBL * stbl, guint32 nsamples, guint32 offset) void atom_stbl_add_samples (AtomSTBL * stbl, guint32 nsamples, guint32 delta, - guint32 size, guint64 chunk_offset, gboolean sync, - gboolean do_pts, gint64 pts_offset) + guint32 size, guint64 chunk_offset, gboolean sync, gint64 pts_offset) { atom_stts_add_entry (&stbl->stts, nsamples, delta); atom_stsz_add_entry (&stbl->stsz, nsamples, size); @@ -2579,18 +2581,17 @@ atom_stbl_add_samples (AtomSTBL * stbl, guint32 nsamples, guint32 delta, atom_stco64_get_entry_count (&stbl->stco64), nsamples); if (sync) atom_stbl_add_stss_entry (stbl); - if (do_pts) - atom_stbl_add_ctts_entry (stbl, nsamples, pts_offset); + /* always store to arrange for consistent content */ + atom_stbl_add_ctts_entry (stbl, nsamples, pts_offset); } void atom_trak_add_samples (AtomTRAK * trak, guint32 nsamples, guint32 delta, - guint32 size, guint64 chunk_offset, gboolean sync, - gboolean do_pts, gint64 pts_offset) + guint32 size, guint64 chunk_offset, gboolean sync, gint64 pts_offset) { AtomSTBL *stbl = &trak->mdia.minf.stbl; atom_stbl_add_samples (stbl, nsamples, delta, size, chunk_offset, sync, - do_pts, pts_offset); + pts_offset); } /* trak and moov molding */ @@ -3593,18 +3594,17 @@ atom_sdtp_add_samples (AtomSDTP * sdtp, guint8 val) static void atom_trun_add_samples (AtomTRUN * trun, guint32 delta, guint32 size, - guint32 flags, gboolean do_pts, gint64 pts_offset) + guint32 flags, gint64 pts_offset) { TRUNSampleEntry nentry; - if (do_pts) { + if (pts_offset != 0) trun->header.flags[1] |= TR_COMPOSITION_TIME_OFFSETS; - } nentry.sample_duration = delta; nentry.sample_size = size; nentry.sample_flags = flags; - nentry.sample_composition_time_offset = do_pts ? pts_offset : 0; + nentry.sample_composition_time_offset = pts_offset; atom_array_append (&trun->entries, nentry, 256); trun->sample_count++; } @@ -3637,7 +3637,7 @@ atom_traf_add_trun (AtomTRAF * traf, AtomTRUN * trun) void atom_traf_add_samples (AtomTRAF * traf, guint32 delta, guint32 size, - gboolean sync, gboolean do_pts, gint64 pts_offset, gboolean sdtp_sync) + gboolean sync, gint64 pts_offset, gboolean sdtp_sync) { AtomTRUN *trun; guint32 flags; @@ -3683,8 +3683,7 @@ atom_traf_add_samples (AtomTRAF * traf, guint32 delta, guint32 size, } } - atom_trun_add_samples (traf->truns->data, delta, size, flags, do_pts, - pts_offset); + atom_trun_add_samples (traf->truns->data, delta, size, flags, pts_offset); if (traf->sdtps) atom_sdtp_add_samples (traf->sdtps->data, 0x10 | ((flags & 0xff) >> 4)); diff --git a/gst/qtmux/atoms.h b/gst/qtmux/atoms.h index b65be8256a..d1241184d7 100644 --- a/gst/qtmux/atoms.h +++ b/gst/qtmux/atoms.h @@ -479,6 +479,7 @@ typedef struct _AtomCTTS /* also entry count here */ ATOM_ARRAY (CTTSEntry) entries; + gboolean do_pts; } AtomCTTS; typedef struct _AtomSTBL @@ -806,7 +807,7 @@ void atom_ftyp_free (AtomFTYP *ftyp); AtomTRAK* atom_trak_new (AtomsContext *context); void atom_trak_add_samples (AtomTRAK * trak, guint32 nsamples, guint32 delta, guint32 size, guint64 chunk_offset, gboolean sync, - gboolean do_pts, gint64 pts_offset); + gint64 pts_offset); void atom_trak_add_elst_entry (AtomTRAK * trak, guint32 duration, guint32 media_time, guint32 rate); guint32 atom_trak_get_timescale (AtomTRAK *trak); @@ -814,7 +815,7 @@ guint32 atom_trak_get_id (AtomTRAK * trak); void atom_stbl_add_samples (AtomSTBL * stbl, guint32 nsamples, guint32 delta, guint32 size, guint64 chunk_offset, gboolean sync, - gboolean do_pts, gint64 pts_offset); + gint64 pts_offset); AtomMOOV* atom_moov_new (AtomsContext *context); void atom_moov_free (AtomMOOV *moov); @@ -850,8 +851,7 @@ guint64 atom_moof_copy_data (AtomMOOF *moof, guint8 **buffer, guint64 AtomTRAF * atom_traf_new (AtomsContext * context, guint32 track_ID); void atom_traf_free (AtomTRAF * traf); void atom_traf_add_samples (AtomTRAF * traf, guint32 delta, - guint32 size, gboolean sync, - gboolean do_pts, gint64 pts_offset, + guint32 size, gboolean sync, gint64 pts_offset, gboolean sdtp_sync); guint32 atom_traf_get_sample_num (AtomTRAF * traf); void atom_moof_add_traf (AtomMOOF *moof, AtomTRAF *traf); diff --git a/gst/qtmux/atomsrecovery.c b/gst/qtmux/atomsrecovery.c index c9684b1f34..1f5a287d1d 100644 --- a/gst/qtmux/atomsrecovery.c +++ b/gst/qtmux/atomsrecovery.c @@ -761,7 +761,7 @@ trak_recov_data_add_sample (TrakRecovData * trak, TrakBufferEntryInfo * b) { trak->duration += b->nsamples * b->delta; atom_stbl_add_samples (&trak->stbl, b->nsamples, b->delta, b->size, - b->chunk_offset, b->sync, b->do_pts, b->pts_offset); + b->chunk_offset, b->sync, b->pts_offset); } /** diff --git a/gst/qtmux/gstqtmux.c b/gst/qtmux/gstqtmux.c index 9ef8caf14a..de067b7439 100644 --- a/gst/qtmux/gstqtmux.c +++ b/gst/qtmux/gstqtmux.c @@ -1838,8 +1838,7 @@ ftyp_error: static GstFlowReturn gst_qt_mux_pad_fragment_add_buffer (GstQTMux * qtmux, GstQTPad * pad, GstBuffer * buf, gboolean force, guint32 nsamples, gint64 dts, - guint32 delta, guint32 size, gboolean sync, gboolean do_pts, - gint64 pts_offset) + guint32 delta, guint32 size, gboolean sync, gint64 pts_offset) { GstFlowReturn ret = GST_FLOW_OK; @@ -1913,7 +1912,7 @@ init: } /* add buffer and metadata */ - atom_traf_add_samples (pad->traf, delta, size, sync, do_pts, pts_offset, + atom_traf_add_samples (pad->traf, delta, size, sync, pts_offset, pad->sync && sync); atom_array_append (&pad->fragment_buffers, buf, 256); pad->fragment_duration -= delta; @@ -2159,8 +2158,8 @@ gst_qt_mux_add_buffer (GstQTMux * qtmux, GstQTPad * pad, GstBuffer * buf) /* note that a new chunk is started each time (not fancy but works) */ if (qtmux->moov_recov_file) { if (!atoms_recov_write_trak_samples (qtmux->moov_recov_file, pad->trak, - nsamples, scaled_duration, sample_size, chunk_offset, sync, do_pts, - pts_offset)) { + nsamples, (gint32) scaled_duration, sample_size, chunk_offset, sync, + do_pts, pts_offset)) { GST_WARNING_OBJECT (qtmux, "Failed to write sample information to " "recovery file, disabling recovery"); fclose (qtmux->moov_recov_file); @@ -2175,10 +2174,10 @@ gst_qt_mux_add_buffer (GstQTMux * qtmux, GstQTPad * pad, GstBuffer * buf) /* ensure that always sync samples are marked as such */ return gst_qt_mux_pad_fragment_add_buffer (qtmux, pad, last_buf, buf == NULL, nsamples, last_dts, scaled_duration, sample_size, - !pad->sync || sync, do_pts, pts_offset); + !pad->sync || sync, pts_offset); } else { - atom_trak_add_samples (pad->trak, nsamples, scaled_duration, sample_size, - chunk_offset, sync, do_pts, pts_offset); + atom_trak_add_samples (pad->trak, nsamples, scaled_duration, + sample_size, chunk_offset, sync, pts_offset); return gst_qt_mux_send_buffer (qtmux, last_buf, &qtmux->mdat_size, TRUE); } From 460785352c0739529b17aa4ebc6558c8eb086ca1 Mon Sep 17 00:00:00 2001 From: Felipe Contreras Date: Thu, 30 Dec 2010 21:48:41 +0200 Subject: [PATCH 249/448] qtmux: get rid of timestamp overprotectiveness Signed-off-by: Felipe Contreras --- gst/qtmux/gstqtmux.c | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/gst/qtmux/gstqtmux.c b/gst/qtmux/gstqtmux.c index de067b7439..29edc2a23d 100644 --- a/gst/qtmux/gstqtmux.c +++ b/gst/qtmux/gstqtmux.c @@ -1993,13 +1993,7 @@ gst_qt_mux_add_buffer (GstQTMux * qtmux, GstQTPad * pad, GstBuffer * buf) if (G_LIKELY (buf) && !pad->is_out_of_order) { if (G_LIKELY (GST_BUFFER_TIMESTAMP_IS_VALID (last_buf) && GST_BUFFER_TIMESTAMP_IS_VALID (buf))) { - if ((GST_BUFFER_TIMESTAMP (buf) < GST_BUFFER_TIMESTAMP (last_buf)) || - (!GST_CLOCK_TIME_IS_VALID (pad->first_ts) && - GST_BUFFER_DURATION_IS_VALID (last_buf) && - gst_qtmux_check_difference (qtmux, - GST_BUFFER_TIMESTAMP (last_buf) + - GST_BUFFER_DURATION (last_buf), GST_BUFFER_TIMESTAMP (buf), - GST_BUFFER_DURATION (last_buf)))) { + if ((GST_BUFFER_TIMESTAMP (buf) < GST_BUFFER_TIMESTAMP (last_buf))) { GST_DEBUG_OBJECT (qtmux, "detected out-of-order input"); pad->is_out_of_order = TRUE; } From 38c93429784d10ddd4da0dbe390616b7e9196729 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Mon, 3 Jan 2011 17:24:23 +0100 Subject: [PATCH 250/448] qtmux: adjust nasty case timestamp tracking That is, all sorts of problems arise with re-ordered input timestamps that tend to defy automagic handling for every case, so allow for a few variations that can be tried depending on circumstances. Also try to document accordingly. Also fixes #638288. --- gst/qtmux/gstqtmux.c | 235 ++++++++++++++++++++++++++++++++++++++----- gst/qtmux/gstqtmux.h | 8 ++ 2 files changed, 217 insertions(+), 26 deletions(-) diff --git a/gst/qtmux/gstqtmux.c b/gst/qtmux/gstqtmux.c index 29edc2a23d..0ac1e91141 100644 --- a/gst/qtmux/gstqtmux.c +++ b/gst/qtmux/gstqtmux.c @@ -82,6 +82,18 @@ * streamable allows foregoing to add * index metadata (at the end of file). * + * dts-method allows selecting a + * method for managing input timestamps (stay tuned for 0.11 to have this + * automagically settled). The default delta/duration method should handle nice + * (aka perfect streams) just fine, but may experience problems otherwise + * (e.g. input stream with re-ordered B-frames and/or with frame dropping). + * The re-ordering approach re-assigns incoming timestamps in ascending order + * to incoming buffers and offers an alternative in such cases. In cases where + * that might fail, the remaining method can be tried, which is exact and + * according to specs, but might experience playback on not so spec-wise players. + * Note that this latter approach also requires one to enable + * presentation-timestamp. + * * * Example pipelines * |[ @@ -128,6 +140,36 @@ GST_DEBUG_CATEGORY_STATIC (gst_qt_mux_debug); #define GST_CAT_DEFAULT gst_qt_mux_debug +enum +{ + DTS_METHOD_DD, + DTS_METHOD_REORDER, + DTS_METHOD_ASC +}; + +static GType +gst_qt_mux_dts_method_get_type (void) +{ + static GType gst_qt_mux_dts_method = 0; + + if (!gst_qt_mux_dts_method) { + static const GEnumValue dts_methods[] = { + {DTS_METHOD_DD, "delta/duration", "dd"}, + {DTS_METHOD_REORDER, "reorder", "reorder"}, + {DTS_METHOD_ASC, "ascending", "asc"}, + {0, NULL, NULL}, + }; + + gst_qt_mux_dts_method = + g_enum_register_static ("GstQTMuxDtsMethods", dts_methods); + } + + return gst_qt_mux_dts_method; +} + +#define GST_TYPE_QT_MUX_DTS_METHOD \ + (gst_qt_mux_dts_method_get_type ()) + /* QTMux signals and args */ enum { @@ -140,12 +182,13 @@ enum PROP_0, PROP_MOVIE_TIMESCALE, PROP_TRAK_TIMESCALE, - PROP_DO_CTTS, PROP_FAST_START, PROP_FAST_START_TEMP_FILE, PROP_MOOV_RECOV_FILE, PROP_FRAGMENT_DURATION, - PROP_STREAMABLE + PROP_STREAMABLE, + PROP_DTS_METHOD, + PROP_DO_CTTS, }; /* some spare for header size as well */ @@ -160,6 +203,7 @@ enum #define DEFAULT_MOOV_RECOV_FILE NULL #define DEFAULT_FRAGMENT_DURATION 0 #define DEFAULT_STREAMABLE FALSE +#define DEFAULT_DTS_METHOD DTS_METHOD_DD static void gst_qt_mux_finalize (GObject * object); @@ -264,6 +308,11 @@ gst_qt_mux_class_init (GstQTMuxClass * klass) "(in addition to decoding time) (use with caution)", DEFAULT_DO_CTTS, G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_DTS_METHOD, + g_param_spec_enum ("dts-method", "dts-method", + "Method to determine DTS time", + GST_TYPE_QT_MUX_DTS_METHOD, DEFAULT_DTS_METHOD, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (gobject_class, PROP_FAST_START, g_param_spec_boolean ("faststart", "Format file to faststart", "If the file should be formated for faststart (headers first). ", @@ -304,6 +353,8 @@ gst_qt_mux_class_init (GstQTMuxClass * klass) static void gst_qt_mux_pad_reset (GstQTPad * qtpad) { + gint i; + qtpad->fourcc = 0; qtpad->is_out_of_order = FALSE; qtpad->have_dts = FALSE; @@ -314,6 +365,16 @@ gst_qt_mux_pad_reset (GstQTPad * qtpad) qtpad->prepare_buf_func = NULL; qtpad->avg_bitrate = 0; qtpad->max_bitrate = 0; + qtpad->ts_n_entries = 0; + + qtpad->buf_head = 0; + qtpad->buf_tail = 0; + for (i = 0; i < G_N_ELEMENTS (qtpad->buf_entries); i++) { + if (qtpad->buf_entries[i]) { + gst_buffer_unref (qtpad->buf_entries[i]); + qtpad->buf_entries[i] = NULL; + } + } if (qtpad->last_buf) gst_buffer_replace (&qtpad->last_buf, NULL); @@ -1930,12 +1991,50 @@ init: return ret; } -/* check whether @a differs from @b by order of @magn */ -static gboolean inline -gst_qtmux_check_difference (GstQTMux * qtmux, GstClockTime a, - GstClockTime b, GstClockTime magn) +/* sigh, tiny list helpers to re-order stuff */ +static void +gst_qt_mux_push_ts (GstQTMux * qtmux, GstQTPad * pad, GstClockTime ts) { - return ((a >= b) ? (a - b >= (magn >> 1)) : (b - a >= (magn >> 1))); + gint i; + + for (i = 0; (i < QTMUX_NO_OF_TS) && (i < pad->ts_n_entries); i++) { + if (ts > pad->ts_entries[i]) + break; + } + memmove (&pad->ts_entries[i + 1], &pad->ts_entries[i], + sizeof (GstClockTime) * (pad->ts_n_entries - i)); + pad->ts_entries[i] = ts; + pad->ts_n_entries++; +} + +/* takes ownership of @buf */ +static GstBuffer * +gst_qt_mux_get_asc_buffer_ts (GstQTMux * qtmux, GstQTPad * pad, GstBuffer * buf) +{ + const gint wrap = G_N_ELEMENTS (pad->buf_entries); + GstClockTime ts; + + /* store buffer and ts, latter ordered */ + if (buf) { + pad->buf_entries[pad->buf_tail++] = buf; + pad->buf_tail %= wrap; + gst_qt_mux_push_ts (qtmux, pad, GST_BUFFER_TIMESTAMP (buf)); + } + + if (pad->ts_n_entries && (!buf || pad->ts_n_entries >= QTMUX_NO_OF_TS)) { + ts = pad->ts_entries[--pad->ts_n_entries]; + buf = pad->buf_entries[pad->buf_head]; + pad->buf_entries[pad->buf_head++] = NULL; + pad->buf_head %= wrap; + buf = gst_buffer_make_metadata_writable (buf); + GST_BUFFER_TIMESTAMP (buf) = ts; + GST_DEBUG_OBJECT (qtmux, "next buffer uses reordered ts %" GST_TIME_FORMAT, + GST_TIME_ARGS (ts)); + } else { + buf = NULL; + } + + return buf; } /* @@ -1947,10 +2046,12 @@ gst_qt_mux_add_buffer (GstQTMux * qtmux, GstQTPad * pad, GstBuffer * buf) GstBuffer *last_buf = NULL; GstClockTime duration; guint nsamples, sample_size; - guint64 scaled_duration, chunk_offset; - gint64 last_dts; + guint64 chunk_offset; + gint64 last_dts, scaled_duration; gint64 pts_offset = 0; gboolean sync = FALSE, do_pts = FALSE; + gboolean drain = (buf == NULL); + GstFlowReturn ret; if (!pad->fourcc) goto not_negotiated; @@ -1960,6 +2061,15 @@ gst_qt_mux_add_buffer (GstQTMux * qtmux, GstQTPad * pad, GstBuffer * buf) buf = pad->prepare_buf_func (pad, buf, qtmux); } +again: + if (G_UNLIKELY (qtmux->dts_method == DTS_METHOD_REORDER)) { + buf = gst_qt_mux_get_asc_buffer_ts (qtmux, pad, buf); + if (!buf) { + GST_DEBUG_OBJECT (qtmux, "no reordered buffer yet"); + return GST_FLOW_OK; + } + } + last_buf = pad->last_buf; if (last_buf == NULL) { #ifndef GST_DISABLE_GST_DEBUG @@ -1979,16 +2089,29 @@ gst_qt_mux_add_buffer (GstQTMux * qtmux, GstQTPad * pad, GstBuffer * buf) gst_buffer_ref (last_buf); /* nasty heuristic mess to guestimate dealing with DTS/PTS, - * while also trying to stay close to input ts to preserve sync, so: + * while also trying to stay close to input ts to preserve sync, + * so in DTS_METHOD_DD: * - prefer using input ts where possible - * - if those detected out-of-order (*), and input duration available, - * mark as out-of-order and fallback to duration - * - if in out-of-order, need to preserve sync between streams, and adding - * durations might drift, so try to resync when we expect - * input ts == (sum of durations), which is at some keyframe input frame. + * - if those detected out-of-order (*), mark as out-of-order + * - if in out-of-order, then + * - if duration available, use that as delta + * Also mind to preserve sync between streams, and adding + * durations might drift, so try to resync when we expect + * input ts == (sum of durations), which is at some keyframe input frame. + * - if no duration available, we are actually in serious trouble and need + * to hack around that, so we fail. + * To remedy failure, alternatively, in DTS_METHOD_REORDER: + * - collect some buffers and re-order timestamp, + * then process the oldest buffer with smallest timestamps. + * This should typically compensate for some codec's handywork with ts. + * ... but in case this makes ts end up where not expected: + * - keep each ts with its buffer and still keep a list of most recent X ts, + * use the (ascending) minimum of those as DTS (and the difference as ts delta), + * and use this DTS as a basis to obtain a (positive) CTS offset. + * This should yield exact PTS == buffer ts, but it seems not all players + * out there are aware of ctts pts ... * - * (*) if input ts out-of-order, or if ts differs from (sum of durations) - * by an (approx) order-of-duration magnitude + * 0.11 Phew, can we (pretty) please please sort out DTS/PTS on buffers ... */ if (G_LIKELY (buf) && !pad->is_out_of_order) { if (G_LIKELY (GST_BUFFER_TIMESTAMP_IS_VALID (last_buf) && @@ -2005,9 +2128,16 @@ gst_qt_mux_add_buffer (GstQTMux * qtmux, GstQTPad * pad, GstBuffer * buf) } } + /* would have to be some unusual input, but not impossible */ + if (G_UNLIKELY (qtmux->dts_method == DTS_METHOD_REORDER && + pad->is_out_of_order)) { + goto no_order; + } + /* fall back to duration if last buffer or * out-of-order (determined previously), otherwise use input ts */ - if (buf == NULL || pad->is_out_of_order) { + if (buf == NULL || + (pad->is_out_of_order && qtmux->dts_method == DTS_METHOD_DD)) { if (!GST_BUFFER_DURATION_IS_VALID (last_buf)) { /* be forgiving for some possibly last upstream flushed buffer */ if (buf) @@ -2020,9 +2150,7 @@ gst_qt_mux_add_buffer (GstQTMux * qtmux, GstQTPad * pad, GstBuffer * buf) /* avoid drift in sum timestamps, * so use input timestamp for suitable keyframe */ if (buf && !GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT) && - GST_BUFFER_TIMESTAMP (buf) >= pad->last_dts && - !gst_qtmux_check_difference (qtmux, pad->last_dts + duration, - GST_BUFFER_TIMESTAMP (buf), duration)) { + GST_BUFFER_TIMESTAMP (buf) >= pad->last_dts) { GST_DEBUG_OBJECT (qtmux, "resyncing out-of-order input to ts; " "replacing %" GST_TIME_FORMAT " by %" GST_TIME_FORMAT, GST_TIME_ARGS (pad->last_dts + duration), @@ -2030,8 +2158,37 @@ gst_qt_mux_add_buffer (GstQTMux * qtmux, GstQTPad * pad, GstBuffer * buf) duration = GST_BUFFER_TIMESTAMP (buf) - pad->last_dts; } } - } else { + } else if (qtmux->dts_method != DTS_METHOD_ASC) { duration = GST_BUFFER_TIMESTAMP (buf) - GST_BUFFER_TIMESTAMP (last_buf); + } else { + GstClockTime ts; + + g_assert (qtmux->dts_method == DTS_METHOD_ASC); + if (!qtmux->guess_pts) + goto need_pts; + + /* add timestamp to queue; keeps in descending order */ + gst_qt_mux_push_ts (qtmux, pad, GST_BUFFER_TIMESTAMP (last_buf)); + /* chuck out smallest/last one if we have enough */ + if (G_LIKELY (pad->ts_n_entries > QTMUX_NO_OF_TS)) + pad->ts_n_entries--; + /* peek the now smallest timestamp */ + ts = pad->ts_entries[pad->ts_n_entries - 1]; + /* these tails are expected to be (strictly) ascending with + * large enough history */ + GST_DEBUG_OBJECT (qtmux, "ASC method; base timestamp %" GST_TIME_FORMAT, + GST_TIME_ARGS (ts)); + if (ts >= pad->last_dts) { + duration = ts - pad->last_dts; + } else { + /* fallback to previous value, negative ct offset might handle */ + GST_WARNING_OBJECT (qtmux, "unexpected decrease in timestamp"); + duration = 0; + } + /* arrange for small non-zero duration/delta << expected frame time */ + ts = gst_util_uint64_scale (10, GST_SECOND, + atom_trak_get_timescale (pad->trak)); + duration = MAX (duration, ts); } gst_buffer_replace (&pad->last_buf, buf); @@ -2166,15 +2323,23 @@ gst_qt_mux_add_buffer (GstQTMux * qtmux, GstQTPad * pad, GstBuffer * buf) if (qtmux->fragment_sequence) { /* ensure that always sync samples are marked as such */ - return gst_qt_mux_pad_fragment_add_buffer (qtmux, pad, last_buf, - buf == NULL, nsamples, last_dts, scaled_duration, sample_size, + ret = gst_qt_mux_pad_fragment_add_buffer (qtmux, pad, last_buf, + buf == NULL, nsamples, last_dts, (gint32) scaled_duration, sample_size, !pad->sync || sync, pts_offset); } else { - atom_trak_add_samples (pad->trak, nsamples, scaled_duration, + atom_trak_add_samples (pad->trak, nsamples, (gint32) scaled_duration, sample_size, chunk_offset, sync, pts_offset); - return gst_qt_mux_send_buffer (qtmux, last_buf, &qtmux->mdat_size, TRUE); + ret = gst_qt_mux_send_buffer (qtmux, last_buf, &qtmux->mdat_size, TRUE); } + if (G_UNLIKELY (drain && qtmux->dts_method == DTS_METHOD_REORDER && + ret == GST_FLOW_OK)) { + buf = NULL; + goto again; + } + + return ret; + /* ERRORS */ bail: { @@ -2189,6 +2354,18 @@ no_time: ("Received buffer without timestamp/duration.")); goto bail; } +no_order: + { + GST_ELEMENT_ERROR (qtmux, STREAM, MUX, (NULL), + ("DTS method failed to re-order timestamps.")); + goto bail; + } +need_pts: + { + GST_ELEMENT_ERROR (qtmux, STREAM, MUX, (NULL), + ("Selected DTS method also needs PTS enabled.")); + goto bail; + } fragmented_sample: { GST_ELEMENT_ERROR (qtmux, STREAM, MUX, (NULL), @@ -3087,6 +3264,9 @@ gst_qt_mux_get_property (GObject * object, case PROP_DO_CTTS: g_value_set_boolean (value, qtmux->guess_pts); break; + case PROP_DTS_METHOD: + g_value_set_enum (value, qtmux->dts_method); + break; case PROP_FAST_START: g_value_set_boolean (value, qtmux->fast_start); break; @@ -3139,6 +3319,9 @@ gst_qt_mux_set_property (GObject * object, case PROP_DO_CTTS: qtmux->guess_pts = g_value_get_boolean (value); break; + case PROP_DTS_METHOD: + qtmux->dts_method = g_value_get_enum (value); + break; case PROP_FAST_START: qtmux->fast_start = g_value_get_boolean (value); break; diff --git a/gst/qtmux/gstqtmux.h b/gst/qtmux/gstqtmux.h index 4df0c3e2b9..3a2cb492fe 100644 --- a/gst/qtmux/gstqtmux.h +++ b/gst/qtmux/gstqtmux.h @@ -78,6 +78,8 @@ typedef struct _GstQTPad GstQTPad; typedef GstBuffer * (*GstQTPadPrepareBufferFunc) (GstQTPad * pad, GstBuffer * buf, GstQTMux * qtmux); +#define QTMUX_NO_OF_TS 10 + struct _GstQTPad { GstCollectData collect; /* we extend the CollectData */ @@ -102,6 +104,11 @@ struct _GstQTPad /* store the first timestamp for comparing with other streams and * know if there are late streams */ GstClockTime first_ts; + GstClockTime ts_entries[QTMUX_NO_OF_TS + 2]; + guint ts_n_entries; + GstBuffer *buf_entries[QTMUX_NO_OF_TS + 2]; + guint buf_head; + guint buf_tail; /* all the atom and chunk book-keeping is delegated here * unowned/uncounted reference, parent MOOV owns */ @@ -174,6 +181,7 @@ struct _GstQTMux AtomsTreeFlavor flavor; gboolean fast_start; gboolean guess_pts; + gint dts_method; gchar *fast_start_file_path; gchar *moov_recov_file_path; guint32 fragment_duration; From f63a67ebfbb0c7c12397c63102c22960a83cce83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Mon, 3 Jan 2011 20:21:57 +0000 Subject: [PATCH 251/448] m4: remove some cruft --- m4/Makefile.am | 9 +- m4/esd.m4 | 202 ---------------------------------- m4/glib.m4 | 196 --------------------------------- m4/gst-matroska.m4 | 262 --------------------------------------------- m4/gst-shout2.m4 | 102 ------------------ m4/gtk.m4 | 194 --------------------------------- m4/ogg.m4 | 102 ------------------ m4/vorbis.m4 | 128 ---------------------- 8 files changed, 1 insertion(+), 1194 deletions(-) delete mode 100644 m4/esd.m4 delete mode 100644 m4/glib.m4 delete mode 100644 m4/gst-matroska.m4 delete mode 100644 m4/gst-shout2.m4 delete mode 100644 m4/gtk.m4 delete mode 100644 m4/ogg.m4 delete mode 100644 m4/vorbis.m4 diff --git a/m4/Makefile.am b/m4/Makefile.am index e03a94a611..8357591cf3 100644 --- a/m4/Makefile.am +++ b/m4/Makefile.am @@ -7,19 +7,14 @@ EXTRA_DIST = \ as-slurp-ffmpeg.m4 \ check-libheader.m4 \ codeset.m4 \ - esd.m4 \ freetype2.m4 \ gconf-2.m4 \ gettext.m4 \ glibc21.m4 \ - glib.m4 \ gst-artsc.m4 \ gst-fionread.m4 \ - gst-matroska.m4 \ gst-sdl.m4 \ - gst-shout2.m4 \ gst-sid.m4 \ - gtk.m4 \ iconv.m4 \ intdiv0.m4 \ inttypes_h.m4 \ @@ -32,8 +27,6 @@ EXTRA_DIST = \ lib-prefix.m4 \ lrintf.m4 \ lrint.m4 \ - ogg.m4 \ progtest.m4 \ stdint_h.m4 \ - uintmax_t.m4 \ - vorbis.m4 + uintmax_t.m4 diff --git a/m4/esd.m4 b/m4/esd.m4 deleted file mode 100644 index 1812fd0276..0000000000 --- a/m4/esd.m4 +++ /dev/null @@ -1,202 +0,0 @@ -# Configure paths for ESD -# Manish Singh 98-9-30 -# stolen back from Frank Belew -# stolen from Manish Singh -# Shamelessly stolen from Owen Taylor - -dnl AM_PATH_ESD([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]]) -dnl Test for ESD, and define ESD_CFLAGS and ESD_LIBS -dnl -AC_DEFUN([AM_PATH_ESD], -[dnl -dnl Get the cflags and libraries from the esd-config script -dnl -AC_ARG_WITH(esd-prefix, - AC_HELP_STRING([--with-esd-prefix=PFX], - [prefix where ESD is installed (optional)]), - esd_prefix="$withval", esd_prefix="") - -AC_ARG_WITH(esd-exec-prefix, - AC_HELP_STRING([--with-esd-exec-prefix=PFX], - [exec prefix where ESD is installed (optional)]), - esd_exec_prefix="$withval", esd_exec_prefix="") - -AC_ARG_ENABLE(esdtest, - AC_HELP_STRING([--disable-esdtest], - [do not try to compile and run a test ESD program]), - , enable_esdtest=yes) - - if test x$esd_exec_prefix != x ; then - esd_args="$esd_args --exec-prefix=$esd_exec_prefix" - if test x${ESD_CONFIG+set} != xset ; then - ESD_CONFIG=$esd_exec_prefix/bin/esd-config - fi - fi - if test x$esd_prefix != x ; then - esd_args="$esd_args --prefix=$esd_prefix" - if test x${ESD_CONFIG+set} != xset ; then - ESD_CONFIG=$esd_prefix/bin/esd-config - fi - fi - - AC_PATH_PROG(ESD_CONFIG, esd-config, no) - min_esd_version=ifelse([$1], ,0.2.7,$1) - AC_MSG_CHECKING(for ESD - version >= $min_esd_version) - no_esd="" - if test "$ESD_CONFIG" = "no" ; then - no_esd=yes - else - AC_LANG_SAVE - AC_LANG_C - ESD_CFLAGS=`$ESD_CONFIG $esdconf_args --cflags` - ESD_LIBS=`$ESD_CONFIG $esdconf_args --libs` - - esd_major_version=`$ESD_CONFIG $esd_args --version | \ - sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` - esd_minor_version=`$ESD_CONFIG $esd_args --version | \ - sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` - esd_micro_version=`$ESD_CONFIG $esd_config_args --version | \ - sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` - if test "x$enable_esdtest" = "xyes" ; then - ac_save_CFLAGS="$CFLAGS" - ac_save_LIBS="$LIBS" - CFLAGS="$CFLAGS $ESD_CFLAGS" - LIBS="$LIBS $ESD_LIBS" -dnl -dnl Now check if the installed ESD is sufficiently new. (Also sanity -dnl checks the results of esd-config to some extent -dnl - rm -f conf.esdtest - AC_TRY_RUN([ -#include -#include -#include -#include - -char* -my_strdup (char *str) -{ - char *new_str; - - if (str) - { - new_str = malloc ((strlen (str) + 1) * sizeof(char)); - strcpy (new_str, str); - } - else - new_str = NULL; - - return new_str; -} - -int main () -{ - int major, minor, micro; - char *tmp_version; - - system ("touch conf.esdtest"); - - /* HP/UX 9 (%@#!) writes to sscanf strings */ - tmp_version = my_strdup("$min_esd_version"); - if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, µ) != 3) { - printf("%s, bad version string\n", "$min_esd_version"); - exit(1); - } - - if (($esd_major_version > major) || - (($esd_major_version == major) && ($esd_minor_version > minor)) || - (($esd_major_version == major) && ($esd_minor_version == minor) && ($esd_micro_version >= micro))) - { - return 0; - } - else - { - printf("\n*** 'esd-config --version' returned %d.%d.%d, but the minimum version\n", $esd_major_version, $esd_minor_version, $esd_micro_version); - printf("*** of ESD required is %d.%d.%d. If esd-config is correct, then it is\n", major, minor, micro); - printf("*** best to upgrade to the required version.\n"); - printf("*** If esd-config was wrong, set the environment variable ESD_CONFIG\n"); - printf("*** to point to the correct copy of esd-config, and remove the file\n"); - printf("*** config.cache before re-running configure\n"); - return 1; - } -} - -],, no_esd=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) - CFLAGS="$ac_save_CFLAGS" - LIBS="$ac_save_LIBS" - AC_LANG_RESTORE - fi - fi - if test "x$no_esd" = x ; then - AC_MSG_RESULT(yes) - ifelse([$2], , :, [$2]) - else - AC_MSG_RESULT(no) - if test "$ESD_CONFIG" = "no" ; then - echo "*** The esd-config script installed by ESD could not be found" - echo "*** If ESD was installed in PREFIX, make sure PREFIX/bin is in" - echo "*** your path, or set the ESD_CONFIG environment variable to the" - echo "*** full path to esd-config." - else - if test -f conf.esdtest ; then - : - else - echo "*** Could not run ESD test program, checking why..." - CFLAGS="$CFLAGS $ESD_CFLAGS" - LIBS="$LIBS $ESD_LIBS" - AC_LANG_SAVE - AC_LANG_C - AC_TRY_LINK([ -#include -#include -], [ return 0; ], - [ echo "*** The test program compiled, but did not run. This usually means" - echo "*** that the run-time linker is not finding ESD or finding the wrong" - echo "*** version of ESD. If it is not finding ESD, you'll need to set your" - echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" - echo "*** to the installed location Also, make sure you have run ldconfig if that" - echo "*** is required on your system" - echo "***" - echo "*** If you have an old version installed, it is best to remove it, although" - echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"], - [ echo "*** The test program failed to compile or link. See the file config.log for the" - echo "*** exact error that occured. This usually means ESD was incorrectly installed" - echo "*** or that you have moved ESD since it was installed. In the latter case, you" - echo "*** may want to edit the esd-config script: $ESD_CONFIG" ]) - CFLAGS="$ac_save_CFLAGS" - LIBS="$ac_save_LIBS" - AC_LANG_RESTORE - fi - fi - ESD_CFLAGS="" - ESD_LIBS="" - ifelse([$3], , :, [$3]) - fi - AC_SUBST(ESD_CFLAGS) - AC_SUBST(ESD_LIBS) - rm -f conf.esdtest -]) - -dnl AM_ESD_SUPPORTS_MULTIPLE_RECORD([ACTION-IF-SUPPORTS [, ACTION-IF-NOT-SUPPORTS]]) -dnl Test, whether esd supports multiple recording clients (version >=0.2.21) -dnl -AC_DEFUN([AM_ESD_SUPPORTS_MULTIPLE_RECORD], -[dnl - AC_MSG_NOTICE([whether installed esd version supports multiple recording clients]) - ac_save_ESD_CFLAGS="$ESD_CFLAGS" - ac_save_ESD_LIBS="$ESD_LIBS" - AM_PATH_ESD(0.2.21, - ifelse([$1], , [ - AM_CONDITIONAL(ESD_SUPPORTS_MULTIPLE_RECORD, true) - AC_DEFINE(ESD_SUPPORTS_MULTIPLE_RECORD, 1, - [Define if you have esound with support of multiple recording clients.])], - [$1]), - ifelse([$2], , [AM_CONDITIONAL(ESD_SUPPORTS_MULTIPLE_RECORD, false)], [$2]) - if test "x$ac_save_ESD_CFLAGS" != x ; then - ESD_CFLAGS="$ac_save_ESD_CFLAGS" - fi - if test "x$ac_save_ESD_LIBS" != x ; then - ESD_LIBS="$ac_save_ESD_LIBS" - fi - ) -]) diff --git a/m4/glib.m4 b/m4/glib.m4 deleted file mode 100644 index b3c632b0e1..0000000000 --- a/m4/glib.m4 +++ /dev/null @@ -1,196 +0,0 @@ -# Configure paths for GLIB -# Owen Taylor 97-11-3 - -dnl AM_PATH_GLIB([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND [, MODULES]]]]) -dnl Test for GLIB, and define GLIB_CFLAGS and GLIB_LIBS, if "gmodule" or -dnl gthread is specified in MODULES, pass to glib-config -dnl -AC_DEFUN([AM_PATH_GLIB], -[dnl -dnl Get the cflags and libraries from the glib-config script -dnl -AC_ARG_WITH(glib-prefix,[ --with-glib-prefix=PFX Prefix where GLIB is installed (optional)], - glib_config_prefix="$withval", glib_config_prefix="") -AC_ARG_WITH(glib-exec-prefix,[ --with-glib-exec-prefix=PFX Exec prefix where GLIB is installed (optional)], - glib_config_exec_prefix="$withval", glib_config_exec_prefix="") -AC_ARG_ENABLE(glibtest, [ --disable-glibtest Do not try to compile and run a test GLIB program], - , enable_glibtest=yes) - - if test x$glib_config_exec_prefix != x ; then - glib_config_args="$glib_config_args --exec-prefix=$glib_config_exec_prefix" - if test x${GLIB_CONFIG+set} != xset ; then - GLIB_CONFIG=$glib_config_exec_prefix/bin/glib-config - fi - fi - if test x$glib_config_prefix != x ; then - glib_config_args="$glib_config_args --prefix=$glib_config_prefix" - if test x${GLIB_CONFIG+set} != xset ; then - GLIB_CONFIG=$glib_config_prefix/bin/glib-config - fi - fi - - for module in . $4 - do - case "$module" in - gmodule) - glib_config_args="$glib_config_args gmodule" - ;; - gthread) - glib_config_args="$glib_config_args gthread" - ;; - esac - done - - AC_PATH_PROG(GLIB_CONFIG, glib-config, no) - min_glib_version=ifelse([$1], ,0.99.7,$1) - AC_MSG_CHECKING(for GLIB - version >= $min_glib_version) - no_glib="" - if test "$GLIB_CONFIG" = "no" ; then - no_glib=yes - else - GLIB_CFLAGS=`$GLIB_CONFIG $glib_config_args --cflags` - GLIB_LIBS=`$GLIB_CONFIG $glib_config_args --libs` - glib_config_major_version=`$GLIB_CONFIG $glib_config_args --version | \ - sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` - glib_config_minor_version=`$GLIB_CONFIG $glib_config_args --version | \ - sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` - glib_config_micro_version=`$GLIB_CONFIG $glib_config_args --version | \ - sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` - if test "x$enable_glibtest" = "xyes" ; then - ac_save_CFLAGS="$CFLAGS" - ac_save_LIBS="$LIBS" - CFLAGS="$CFLAGS $GLIB_CFLAGS" - LIBS="$GLIB_LIBS $LIBS" -dnl -dnl Now check if the installed GLIB is sufficiently new. (Also sanity -dnl checks the results of glib-config to some extent -dnl - rm -f conf.glibtest - AC_TRY_RUN([ -#include -#include -#include - -int -main () -{ - int major, minor, micro; - char *tmp_version; - - system ("touch conf.glibtest"); - - /* HP/UX 9 (%@#!) writes to sscanf strings */ - tmp_version = g_strdup("$min_glib_version"); - if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, µ) != 3) { - printf("%s, bad version string\n", "$min_glib_version"); - exit(1); - } - - if ((glib_major_version != $glib_config_major_version) || - (glib_minor_version != $glib_config_minor_version) || - (glib_micro_version != $glib_config_micro_version)) - { - printf("\n*** 'glib-config --version' returned %d.%d.%d, but GLIB (%d.%d.%d)\n", - $glib_config_major_version, $glib_config_minor_version, $glib_config_micro_version, - glib_major_version, glib_minor_version, glib_micro_version); - printf ("*** was found! If glib-config was correct, then it is best\n"); - printf ("*** to remove the old version of GLIB. You may also be able to fix the error\n"); - printf("*** by modifying your LD_LIBRARY_PATH enviroment variable, or by editing\n"); - printf("*** /etc/ld.so.conf. Make sure you have run ldconfig if that is\n"); - printf("*** required on your system.\n"); - printf("*** If glib-config was wrong, set the environment variable GLIB_CONFIG\n"); - printf("*** to point to the correct copy of glib-config, and remove the file config.cache\n"); - printf("*** before re-running configure\n"); - } - else if ((glib_major_version != GLIB_MAJOR_VERSION) || - (glib_minor_version != GLIB_MINOR_VERSION) || - (glib_micro_version != GLIB_MICRO_VERSION)) - { - printf("*** GLIB header files (version %d.%d.%d) do not match\n", - GLIB_MAJOR_VERSION, GLIB_MINOR_VERSION, GLIB_MICRO_VERSION); - printf("*** library (version %d.%d.%d)\n", - glib_major_version, glib_minor_version, glib_micro_version); - } - else - { - if ((glib_major_version > major) || - ((glib_major_version == major) && (glib_minor_version > minor)) || - ((glib_major_version == major) && (glib_minor_version == minor) && (glib_micro_version >= micro))) - { - return 0; - } - else - { - printf("\n*** An old version of GLIB (%d.%d.%d) was found.\n", - glib_major_version, glib_minor_version, glib_micro_version); - printf("*** You need a version of GLIB newer than %d.%d.%d. The latest version of\n", - major, minor, micro); - printf("*** GLIB is always available from ftp://ftp.gtk.org.\n"); - printf("***\n"); - printf("*** If you have already installed a sufficiently new version, this error\n"); - printf("*** probably means that the wrong copy of the glib-config shell script is\n"); - printf("*** being found. The easiest way to fix this is to remove the old version\n"); - printf("*** of GLIB, but you can also set the GLIB_CONFIG environment to point to the\n"); - printf("*** correct copy of glib-config. (In this case, you will have to\n"); - printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n"); - printf("*** so that the correct libraries are found at run-time))\n"); - } - } - return 1; -} -],, no_glib=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) - CFLAGS="$ac_save_CFLAGS" - LIBS="$ac_save_LIBS" - fi - fi - if test "x$no_glib" = x ; then - AC_MSG_RESULT(yes) - ifelse([$2], , :, [$2]) - else - AC_MSG_RESULT(no) - if test "$GLIB_CONFIG" = "no" ; then - echo "*** The glib-config script installed by GLIB could not be found" - echo "*** If GLIB was installed in PREFIX, make sure PREFIX/bin is in" - echo "*** your path, or set the GLIB_CONFIG environment variable to the" - echo "*** full path to glib-config." - else - if test -f conf.glibtest ; then - : - else - echo "*** Could not run GLIB test program, checking why..." - CFLAGS="$CFLAGS $GLIB_CFLAGS" - LIBS="$LIBS $GLIB_LIBS" - AC_TRY_LINK([ -#include -#include -], [ return ((glib_major_version) || (glib_minor_version) || (glib_micro_version)); ], - [ echo "*** The test program compiled, but did not run. This usually means" - echo "*** that the run-time linker is not finding GLIB or finding the wrong" - echo "*** version of GLIB. If it is not finding GLIB, you'll need to set your" - echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" - echo "*** to the installed location Also, make sure you have run ldconfig if that" - echo "*** is required on your system" - echo "***" - echo "*** If you have an old version installed, it is best to remove it, although" - echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH" - echo "***" - echo "*** If you have a RedHat 5.0 system, you should remove the GTK package that" - echo "*** came with the system with the command" - echo "***" - echo "*** rpm --erase --nodeps gtk gtk-devel" ], - [ echo "*** The test program failed to compile or link. See the file config.log for the" - echo "*** exact error that occured. This usually means GLIB was incorrectly installed" - echo "*** or that you have moved GLIB since it was installed. In the latter case, you" - echo "*** may want to edit the glib-config script: $GLIB_CONFIG" ]) - CFLAGS="$ac_save_CFLAGS" - LIBS="$ac_save_LIBS" - fi - fi - GLIB_CFLAGS="" - GLIB_LIBS="" - ifelse([$3], , :, [$3]) - fi - AC_SUBST(GLIB_CFLAGS) - AC_SUBST(GLIB_LIBS) - rm -f conf.glibtest -]) diff --git a/m4/gst-matroska.m4 b/m4/gst-matroska.m4 deleted file mode 100644 index b50caaa27b..0000000000 --- a/m4/gst-matroska.m4 +++ /dev/null @@ -1,262 +0,0 @@ -# Configure paths for libebml - -dnl PATH_EBML([ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) -dnl Test for libebml, and define EBML_CFLAGS and EBML_LIBS -dnl -AC_DEFUN([PATH_EBML], -[dnl -dnl Get the cflags and libraries -dnl -AC_ARG_WITH(ebml-prefix,[ --with-ebml-prefix=PFX Prefix where libebml is installed (optional)], ebml_prefix="$withval", ebml_prefix="") -AC_ARG_WITH(ebml-include,[ --with-ebml-include=DIR Path to where the libebml include files installed (optional)], ebml_include="$withval", ebml_include="") -AC_ARG_WITH(ebml-lib,[ --with-ebml-lib=DIR Path to where the libebml library installed (optional)], ebml_lib="$withval", ebml_lib="") -AC_ARG_ENABLE(ebmltest, [ --disable-ebmltest Do not try to compile and run a test EBML program],, enable_ebmltest=yes) - - if test "x$ebml_prefix" != "x"; then - ebml_args="$ebml_args --prefix=$ebml_prefix" - if test "x$ebml_include" != "x"; then - EBML_CFLAGS="-I$ebml_include" - else - EBML_CFLAGS="-I$ebml_prefix/include/ebml" - fi - if test "x$ebml_lib" != "x"; then - EBML_LIBS="-L$ebml_lib" - else - EBML_LIBS="-L$ebml_prefix/lib" - fi - elif test "x$prefix" != "xNONE"; then - ebml_args="$ebml_args --prefix=$prefix" - if test "x$ebml_include" != "x"; then - EBML_CFLAGS="-I$ebml_include" - else - EBML_CFLAGS="-I$prefix/include/ebml" - fi - if test "x$ebml_lib" != "x"; then - EBML_LIBS="-L$ebml_lib" - else - EBML_LIBS="-L$prefix/lib" - fi - else - if test "x$ebml_include" != "x"; then - EBML_CFLAGS="-I$ebml_include" - else - EBML_CFLAGS="-I/usr/include/ebml -I/usr/local/include/ebml" - fi - if test "x$ebml_lib" != "x"; then - EBML_LIBS="-L$ebml_lib" - else - EBML_LIBS="-L/usr/local/lib" - fi - fi - - EBML_LIBS="$EBML_LIBS -lebml" - - AC_MSG_CHECKING(for EBML) - no_ebml="" - - - if test "x$enable_ebmltest" = "xyes" ; then - ac_save_CFLAGS="$CFLAGS" - ac_save_LIBS="$LIBS" - CFLAGS="$CFLAGS $EBML_CFLAGS" - LIBS="$LIBS $EBML_LIBS" -dnl -dnl Now check if the installed EBML is sufficiently new. -dnl - rm -f conf.ebmltest - AC_TRY_RUN([ -#include -#include -#include -#include - -int main () -{ - system("touch conf.ebmltest"); - return 0; -} - -],, no_ebml=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) - CFLAGS="$ac_save_CFLAGS" - LIBS="$ac_save_LIBS" - fi - - if test "x$no_ebml" = "x" ; then - AC_MSG_RESULT(yes) - ifelse([$1], , :, [$1]) - else - AC_MSG_RESULT(no) - if test -f conf.ebmltest ; then - : - else - echo "*** Could not run Ebml test program, checking why..." - CFLAGS="$CFLAGS $EBML_CFLAGS" - LIBS="$LIBS $EBML_LIBS" - AC_TRY_LINK([ -#include -#include -], [ return 0; ], - [ echo "*** The test program compiled, but did not run. This usually means" - echo "*** that the run-time linker is not finding EBML or finding the wrong" - echo "*** version of EBML. If it is not finding EBML, you'll need to set your" - echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" - echo "*** to the installed location Also, make sure you have run ldconfig if that" - echo "*** is required on your system" - echo "***" - echo "*** If you have an old version installed, it is best to remove it, although" - echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"], - [ echo "*** The test program failed to compile or link. See the file config.log for the" - echo "*** exact error that occured. This usually means EBML was incorrectly installed" - echo "*** or that you have moved EBML since it was installed." ]) - CFLAGS="$ac_save_CFLAGS" - LIBS="$ac_save_LIBS" - fi - EBML_CFLAGS="" - EBML_LIBS="" - ifelse([$2], , :, [$2]) - fi - AC_SUBST(EBML_CFLAGS) - AC_SUBST(EBML_LIBS) - rm -f conf.ebmltest -]) - -# Configure paths for libmatroska - -dnl PATH_MATROSKA(MIN_VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) -dnl Test for libmatroska, and define MATROSKA_CFLAGS and MATROSKA_LIBS -dnl -AC_DEFUN([PATH_MATROSKA], -[dnl -dnl Get the cflags and libraries -dnl -AC_ARG_WITH(matroska-prefix,[ --with-matroska-prefix=PFX Prefix where libmatroska is installed (optional)], matroska_prefix="$withval", matroska_prefix="") -AC_ARG_WITH(matroska-include,[ --with-matroska-include=DIR Path to where the libmatroska include files installed (optional)], matroska_include="$withval", matroska_include="") -AC_ARG_WITH(matroska-lib,[ --with-matroska-lib=DIR Path to where the libmatroska library installed (optional)], matroska_lib="$withval", matroska_lib="") -AC_ARG_ENABLE(matroskatest, [ --disable-matroskatest Do not try to compile and run a test Matroska program],, enable_matroskatest=yes) - - if test "x$matroska_prefix" != "x"; then - matroska_args="$matroska_args --prefix=$matroska_prefix" - if test "x$matroska_include" != "x"; then - MATROSKA_CFLAGS="-I$matroska_include" - else - MATROSKA_CFLAGS="-I$matroska_prefix/include/matroska" - fi - if test "x$matroska_lib" != "x"; then - MATROSKA_LIBS="-L$matroska_lib" - else - MATROSKA_LIBS="-L$matroska_prefix/lib" - fi - elif test "x$prefix" != "xNONE"; then - matroska_args="$matroska_args --prefix=$prefix" - if test "x$matroska_include" != "x"; then - MATROSKA_CFLAGS="-I$matroska_include" - else - MATROSKA_CFLAGS="-I$prefix/include/matroska" - fi - if test "x$matroska_lib" != "x"; then - MATROSKA_LIBS="-L$matroska_lib" - else - MATROSKA_LIBS="-L$prefix/lib" - fi - else - if test "x$matroska_include" != "x"; then - MATROSKA_CFLAGS="-I$matroska_include" - else - MATROSKA_CFLAGS="-I/usr/include/matroska -I/usr/local/include/matroska" - fi - if test "x$matroska_lib" != "x"; then - MATROSKA_LIBS="-L$matroska_lib" - else - MATROSKA_LIBS="-L/usr/local/lib" - fi - fi - - MATROSKA_LIBS="$MATROSKA_LIBS -lmatroska" - - AC_MSG_CHECKING(for Matroska) - no_matroska="" - - - if test "x$enable_matroskatest" = "xyes" ; then - ac_save_CXXFLAGS="$CXXFLAGS" - ac_save_LIBS="$LIBS" - CXXFLAGS="$CXXFLAGS $MATROSKA_CFLAGS $EBML_CFLAGS" - LIBS="$LIBS $MATROSKA_LIBS $EBML_LIBS" -dnl -dnl Now check if the installed Matroska is sufficiently new. -dnl - rm -f conf.matroskatest - AC_LANG_CPLUSPLUS - AC_TRY_RUN([ -#include -#include -#include -#include -#include - -using namespace LIBMATROSKA_NAMESPACE; - -int main () -{ - FILE *f; - f = fopen("conf.matroskatest", "wb"); - if (f == NULL) - return 1; - fprintf(f, "%s\n", KaxCodeVersion.c_str()); - fclose(f); - return 0; -} - -],, no_matroska=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) - AC_LANG_C - CXXFLAGS="$ac_save_CXXFLAGS" - LIBS="$ac_save_LIBS" - fi - - if test "x$no_matroska" = "x" -a -f conf.matroskatest ; then - AC_MSG_RESULT(yes) - - AC_MSG_CHECKING(Matroska version) - - matroska_version=`cat conf.matroskatest` - mk_MAJVER=`echo $1 | cut -d"." -f1` - mk_MINVER=`echo $1 | cut -d"." -f2` - mk_RELVER=`echo $1 | cut -d"." -f3` - mver_ok=`sed 's;\.;\ ;g' < conf.matroskatest | (read -a mver - if test ${mver[[0]]} -gt $mk_MAJVER ; then - mver_ok=1 - elif test ${mver[[0]]} -lt $mk_MAJVER ; then - mver_ok=0 - else - if test ${mver[[1]]} -gt $mk_MINVER ; then - mver_ok=1 - elif test ${mver[[1]]} -lt $mk_MINVER ; then - mver_ok=0 - else - if test ${mver[[2]]} -ge $mk_RELVER ; then - mver_ok=1 - else - mver_ok=0 - fi - fi - fi - echo $mver_ok )` - if test "$mver_ok" = "1" ; then - AC_MSG_RESULT($matroska_version ok) - ifelse([$2], , :, [$2]) - else - AC_MSG_RESULT($matroska_version too old) - echo '*** Your Matroska version is too old. Upgrade to at least version' - echo '*** $1 and re-run configure.' - ifelse([$3], , :, [$3]) - fi - - else - AC_MSG_RESULT(no) - ifelse([$3], , :, [$3]) - fi - - AC_SUBST(MATROSKA_CFLAGS) - AC_SUBST(MATROSKA_LIBS) - rm -f conf.matroskatest -]) diff --git a/m4/gst-shout2.m4 b/m4/gst-shout2.m4 deleted file mode 100644 index e85a76711d..0000000000 --- a/m4/gst-shout2.m4 +++ /dev/null @@ -1,102 +0,0 @@ -# Configure paths for libshout -# Jack Moffitt 08-06-2001 -# Shamelessly stolen from Owen Taylor and Manish Singh - -dnl AM_PATH_SHOUT2([ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) -dnl Test for libshout 2, and define SHOUT2_CFLAGS and SHOUT2_LIBS -dnl -AC_DEFUN([AM_PATH_SHOUT2], -[dnl -dnl Get the cflags and libraries -dnl -AC_ARG_WITH(shout2-prefix,[ --with-shout2-prefix=PFX Prefix where libshout2 is installed (optional)], shout2_prefix="$withval", shout2_prefix="") -AC_ARG_ENABLE(shout2test, [ --disable-shout2test Do not try to compile and run a test shout2 program],, enable_shout2test=yes) - - if test "x$shout2_prefix" != "xNONE" ; then - SHOUT2_CFLAGS="-I$shout2_prefix/include" - SHOUT2_LIBS="-L$shout2_prefix/lib" - elif test "x$prefix" != "x"; then - SHOUT2_CFLAGS="-I$prefix/include" - SHOUT2_LIBS="-L$prefix/lib" - fi - - SHOUT2_LIBS="$SHOUT2_LIBS -lshout -lpthread" - - case $host in - *-*-solaris*) - SHOUT2_LIBS="$SHOUT2_LIBS -lnsl -lsocket -lresolv" - esac - - AC_MSG_CHECKING(for shout2) - no_shout2="" - - if test "x$enable_shout2test" = "xyes" ; then - ac_save_CFLAGS="$CFLAGS" - ac_save_LIBS="$LIBS" - CFLAGS="$CFLAGS $SHOUT2_CFLAGS $OGG_CFLAGS $VORBIS_CFLAGS" - LIBS="$LIBS $SHOUT2_LIBS $OGG_LIBS $VORBIS_LIBS" -dnl -dnl Now check if the installed shout2 is sufficiently new. -dnl - rm -f conf.shout2test - AC_TRY_RUN([ -#include -#include -#include -#include - -int main () -{ - int major, minor, patch; - - system("touch conf.shout2test"); - shout_version(&major, &minor, &patch); - if (major < 2) - return 1; - return 0; -} - -],, no_shout2=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) - CFLAGS="$ac_save_CFLAGS" - LIBS="$ac_save_LIBS" - fi - - if test "x$no_shout2" = "x" ; then - AC_MSG_RESULT(yes) - ifelse([$1], , :, [$1]) - else - AC_MSG_RESULT(no) - if test -f conf.shout2test ; then - : - else - echo "*** Could not run Shout2 test program, checking why..." - CFLAGS="$CFLAGS $SHOUT2_CFLAGS $OGG_CFLAGS $VORBIS_CFLAGS" - LIBS="$LIBS $SHOUT2_LIBS $OGG_LIBS $VORBIS_LIBS" - AC_TRY_LINK([ -#include -#include -], [ return 0; ], - [ echo "*** The test program compiled, but did not run. This usually means" - echo "*** that the run-time linker is not finding Shout2 or finding the wrong" - echo "*** version of Shout2. If it is not finding Shout2, you'll need to set your" - echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" - echo "*** to the installed location Also, make sure you have run ldconfig if that" - echo "*** is required on your system" - echo "***" - echo "*** If you have an old version installed, it is best to remove it, although" - echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"], - [ echo "*** The test program failed to compile or link. See the file config.log for the" - echo "*** exact error that occured. This usually means Shout2 was incorrectly installed" - echo "*** or that you have moved Shout2 since it was installed. In the latter case, you" - echo "*** may want to edit the shout-config script: $SHOUT2_CONFIG" ]) - CFLAGS="$ac_save_CFLAGS" - LIBS="$ac_save_LIBS" - fi - SHOUT2_CFLAGS="" - SHOUT2_LIBS="" - ifelse([$2], , :, [$2]) - fi - AC_SUBST(SHOUT2_CFLAGS) - AC_SUBST(SHOUT2_LIBS) - rm -f conf.shout2test -]) diff --git a/m4/gtk.m4 b/m4/gtk.m4 deleted file mode 100644 index f2dd472197..0000000000 --- a/m4/gtk.m4 +++ /dev/null @@ -1,194 +0,0 @@ -# Configure paths for GTK+ -# Owen Taylor 97-11-3 - -dnl AM_PATH_GTK([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND [, MODULES]]]]) -dnl Test for GTK, and define GTK_CFLAGS and GTK_LIBS -dnl -AC_DEFUN([AM_PATH_GTK], -[dnl -dnl Get the cflags and libraries from the gtk-config script -dnl -AC_ARG_WITH(gtk-prefix,[ --with-gtk-prefix=PFX Prefix where GTK is installed (optional)], - gtk_config_prefix="$withval", gtk_config_prefix="") -AC_ARG_WITH(gtk-exec-prefix,[ --with-gtk-exec-prefix=PFX Exec prefix where GTK is installed (optional)], - gtk_config_exec_prefix="$withval", gtk_config_exec_prefix="") -AC_ARG_ENABLE(gtktest, [ --disable-gtktest Do not try to compile and run a test GTK program], - , enable_gtktest=yes) - - for module in . $4 - do - case "$module" in - gthread) - gtk_config_args="$gtk_config_args gthread" - ;; - esac - done - - if test x$gtk_config_exec_prefix != x ; then - gtk_config_args="$gtk_config_args --exec-prefix=$gtk_config_exec_prefix" - if test x${GTK_CONFIG+set} != xset ; then - GTK_CONFIG=$gtk_config_exec_prefix/bin/gtk-config - fi - fi - if test x$gtk_config_prefix != x ; then - gtk_config_args="$gtk_config_args --prefix=$gtk_config_prefix" - if test x${GTK_CONFIG+set} != xset ; then - GTK_CONFIG=$gtk_config_prefix/bin/gtk-config - fi - fi - - AC_PATH_PROG(GTK_CONFIG, gtk-config, no) - min_gtk_version=ifelse([$1], ,0.99.7,$1) - AC_MSG_CHECKING(for GTK - version >= $min_gtk_version) - no_gtk="" - if test "$GTK_CONFIG" = "no" ; then - no_gtk=yes - else - GTK_CFLAGS=`$GTK_CONFIG $gtk_config_args --cflags` - GTK_LIBS=`$GTK_CONFIG $gtk_config_args --libs` - gtk_config_major_version=`$GTK_CONFIG $gtk_config_args --version | \ - sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'` - gtk_config_minor_version=`$GTK_CONFIG $gtk_config_args --version | \ - sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'` - gtk_config_micro_version=`$GTK_CONFIG $gtk_config_args --version | \ - sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'` - if test "x$enable_gtktest" = "xyes" ; then - ac_save_CFLAGS="$CFLAGS" - ac_save_LIBS="$LIBS" - CFLAGS="$CFLAGS $GTK_CFLAGS" - LIBS="$GTK_LIBS $LIBS" -dnl -dnl Now check if the installed GTK is sufficiently new. (Also sanity -dnl checks the results of gtk-config to some extent -dnl - rm -f conf.gtktest - AC_TRY_RUN([ -#include -#include -#include - -int -main () -{ - int major, minor, micro; - char *tmp_version; - - system ("touch conf.gtktest"); - - /* HP/UX 9 (%@#!) writes to sscanf strings */ - tmp_version = g_strdup("$min_gtk_version"); - if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, µ) != 3) { - printf("%s, bad version string\n", "$min_gtk_version"); - exit(1); - } - - if ((gtk_major_version != $gtk_config_major_version) || - (gtk_minor_version != $gtk_config_minor_version) || - (gtk_micro_version != $gtk_config_micro_version)) - { - printf("\n*** 'gtk-config --version' returned %d.%d.%d, but GTK+ (%d.%d.%d)\n", - $gtk_config_major_version, $gtk_config_minor_version, $gtk_config_micro_version, - gtk_major_version, gtk_minor_version, gtk_micro_version); - printf ("*** was found! If gtk-config was correct, then it is best\n"); - printf ("*** to remove the old version of GTK+. You may also be able to fix the error\n"); - printf("*** by modifying your LD_LIBRARY_PATH enviroment variable, or by editing\n"); - printf("*** /etc/ld.so.conf. Make sure you have run ldconfig if that is\n"); - printf("*** required on your system.\n"); - printf("*** If gtk-config was wrong, set the environment variable GTK_CONFIG\n"); - printf("*** to point to the correct copy of gtk-config, and remove the file config.cache\n"); - printf("*** before re-running configure\n"); - } -#if defined (GTK_MAJOR_VERSION) && defined (GTK_MINOR_VERSION) && defined (GTK_MICRO_VERSION) - else if ((gtk_major_version != GTK_MAJOR_VERSION) || - (gtk_minor_version != GTK_MINOR_VERSION) || - (gtk_micro_version != GTK_MICRO_VERSION)) - { - printf("*** GTK+ header files (version %d.%d.%d) do not match\n", - GTK_MAJOR_VERSION, GTK_MINOR_VERSION, GTK_MICRO_VERSION); - printf("*** library (version %d.%d.%d)\n", - gtk_major_version, gtk_minor_version, gtk_micro_version); - } -#endif /* defined (GTK_MAJOR_VERSION) ... */ - else - { - if ((gtk_major_version > major) || - ((gtk_major_version == major) && (gtk_minor_version > minor)) || - ((gtk_major_version == major) && (gtk_minor_version == minor) && (gtk_micro_version >= micro))) - { - return 0; - } - else - { - printf("\n*** An old version of GTK+ (%d.%d.%d) was found.\n", - gtk_major_version, gtk_minor_version, gtk_micro_version); - printf("*** You need a version of GTK+ newer than %d.%d.%d. The latest version of\n", - major, minor, micro); - printf("*** GTK+ is always available from ftp://ftp.gtk.org.\n"); - printf("***\n"); - printf("*** If you have already installed a sufficiently new version, this error\n"); - printf("*** probably means that the wrong copy of the gtk-config shell script is\n"); - printf("*** being found. The easiest way to fix this is to remove the old version\n"); - printf("*** of GTK+, but you can also set the GTK_CONFIG environment to point to the\n"); - printf("*** correct copy of gtk-config. (In this case, you will have to\n"); - printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n"); - printf("*** so that the correct libraries are found at run-time))\n"); - } - } - return 1; -} -],, no_gtk=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) - CFLAGS="$ac_save_CFLAGS" - LIBS="$ac_save_LIBS" - fi - fi - if test "x$no_gtk" = x ; then - AC_MSG_RESULT(yes) - ifelse([$2], , :, [$2]) - else - AC_MSG_RESULT(no) - if test "$GTK_CONFIG" = "no" ; then - echo "*** The gtk-config script installed by GTK could not be found" - echo "*** If GTK was installed in PREFIX, make sure PREFIX/bin is in" - echo "*** your path, or set the GTK_CONFIG environment variable to the" - echo "*** full path to gtk-config." - else - if test -f conf.gtktest ; then - : - else - echo "*** Could not run GTK test program, checking why..." - CFLAGS="$CFLAGS $GTK_CFLAGS" - LIBS="$LIBS $GTK_LIBS" - AC_TRY_LINK([ -#include -#include -], [ return ((gtk_major_version) || (gtk_minor_version) || (gtk_micro_version)); ], - [ echo "*** The test program compiled, but did not run. This usually means" - echo "*** that the run-time linker is not finding GTK or finding the wrong" - echo "*** version of GTK. If it is not finding GTK, you'll need to set your" - echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" - echo "*** to the installed location Also, make sure you have run ldconfig if that" - echo "*** is required on your system" - echo "***" - echo "*** If you have an old version installed, it is best to remove it, although" - echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH" - echo "***" - echo "*** If you have a RedHat 5.0 system, you should remove the GTK package that" - echo "*** came with the system with the command" - echo "***" - echo "*** rpm --erase --nodeps gtk gtk-devel" ], - [ echo "*** The test program failed to compile or link. See the file config.log for the" - echo "*** exact error that occured. This usually means GTK was incorrectly installed" - echo "*** or that you have moved GTK since it was installed. In the latter case, you" - echo "*** may want to edit the gtk-config script: $GTK_CONFIG" ]) - CFLAGS="$ac_save_CFLAGS" - LIBS="$ac_save_LIBS" - fi - fi - GTK_CFLAGS="" - GTK_LIBS="" - ifelse([$3], , :, [$3]) - fi - AC_SUBST(GTK_CFLAGS) - AC_SUBST(GTK_LIBS) - rm -f conf.gtktest -]) diff --git a/m4/ogg.m4 b/m4/ogg.m4 deleted file mode 100644 index 0e1f1abf59..0000000000 --- a/m4/ogg.m4 +++ /dev/null @@ -1,102 +0,0 @@ -# Configure paths for libogg -# Jack Moffitt 10-21-2000 -# Shamelessly stolen from Owen Taylor and Manish Singh - -dnl XIPH_PATH_OGG([ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) -dnl Test for libogg, and define OGG_CFLAGS and OGG_LIBS -dnl -AC_DEFUN([XIPH_PATH_OGG], -[dnl -dnl Get the cflags and libraries -dnl -AC_ARG_WITH(ogg,[ --with-ogg=PFX Prefix where libogg is installed (optional)], ogg_prefix="$withval", ogg_prefix="") -AC_ARG_WITH(ogg-libraries,[ --with-ogg-libraries=DIR Directory where libogg library is installed (optional)], ogg_libraries="$withval", ogg_libraries="") -AC_ARG_WITH(ogg-includes,[ --with-ogg-includes=DIR Directory where libogg header files are installed (optional)], ogg_includes="$withval", ogg_includes="") -AC_ARG_ENABLE(oggtest, [ --disable-oggtest Do not try to compile and run a test Ogg program],, enable_oggtest=yes) - - if test "x$ogg_libraries" != "x" ; then - OGG_LIBS="-L$ogg_libraries" - elif test "x$ogg_prefix" != "x" ; then - OGG_LIBS="-L$ogg_prefix/lib" - elif test "x$prefix" != "xNONE" ; then - OGG_LIBS="-L$prefix/lib" - fi - - OGG_LIBS="$OGG_LIBS -logg" - - if test "x$ogg_includes" != "x" ; then - OGG_CFLAGS="-I$ogg_includes" - elif test "x$ogg_prefix" != "x" ; then - OGG_CFLAGS="-I$ogg_prefix/include" - elif test "x$prefix" != "xNONE"; then - OGG_CFLAGS="-I$prefix/include" - fi - - AC_MSG_CHECKING(for Ogg) - no_ogg="" - - - if test "x$enable_oggtest" = "xyes" ; then - ac_save_CFLAGS="$CFLAGS" - ac_save_LIBS="$LIBS" - CFLAGS="$CFLAGS $OGG_CFLAGS" - LIBS="$LIBS $OGG_LIBS" -dnl -dnl Now check if the installed Ogg is sufficiently new. -dnl - rm -f conf.oggtest - AC_TRY_RUN([ -#include -#include -#include -#include - -int main () -{ - system("touch conf.oggtest"); - return 0; -} - -],, no_ogg=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) - CFLAGS="$ac_save_CFLAGS" - LIBS="$ac_save_LIBS" - fi - - if test "x$no_ogg" = "x" ; then - AC_MSG_RESULT(yes) - ifelse([$1], , :, [$1]) - else - AC_MSG_RESULT(no) - if test -f conf.oggtest ; then - : - else - echo "*** Could not run Ogg test program, checking why..." - CFLAGS="$CFLAGS $OGG_CFLAGS" - LIBS="$LIBS $OGG_LIBS" - AC_TRY_LINK([ -#include -#include -], [ return 0; ], - [ echo "*** The test program compiled, but did not run. This usually means" - echo "*** that the run-time linker is not finding Ogg or finding the wrong" - echo "*** version of Ogg. If it is not finding Ogg, you'll need to set your" - echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" - echo "*** to the installed location Also, make sure you have run ldconfig if that" - echo "*** is required on your system" - echo "***" - echo "*** If you have an old version installed, it is best to remove it, although" - echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"], - [ echo "*** The test program failed to compile or link. See the file config.log for the" - echo "*** exact error that occured. This usually means Ogg was incorrectly installed" - echo "*** or that you have moved Ogg since it was installed." ]) - CFLAGS="$ac_save_CFLAGS" - LIBS="$ac_save_LIBS" - fi - OGG_CFLAGS="" - OGG_LIBS="" - ifelse([$2], , :, [$2]) - fi - AC_SUBST(OGG_CFLAGS) - AC_SUBST(OGG_LIBS) - rm -f conf.oggtest -]) diff --git a/m4/vorbis.m4 b/m4/vorbis.m4 deleted file mode 100644 index 6a2889318c..0000000000 --- a/m4/vorbis.m4 +++ /dev/null @@ -1,128 +0,0 @@ -# Configure paths for libvorbis -# Jack Moffitt 10-21-2000 -# Shamelessly stolen from Owen Taylor and Manish Singh -# thomasvs added check for vorbis_bitrate_addblock which is new in rc3 -# thomasvs added check for OV_ECTL_RATEMANAGE_SET which is new in 1.0 final - -dnl XIPH_PATH_VORBIS([ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]) -dnl Test for libvorbis, and define VORBIS_CFLAGS and VORBIS_LIBS -dnl -AC_DEFUN([XIPH_PATH_VORBIS], -[dnl -dnl Get the cflags and libraries -dnl -AC_ARG_WITH(vorbis,[ --with-vorbis=PFX Prefix where libvorbis is installed (optional)], vorbis_prefix="$withval", vorbis_prefix="") -AC_ARG_WITH(vorbis-libraries,[ --with-vorbis-libraries=DIR Directory where libvorbis library is installed (optional)], vorbis_libraries="$withval", vorbis_libraries="") -AC_ARG_WITH(vorbis-includes,[ --with-vorbis-includes=DIR Directory where libvorbis header files are installed (optional)], vorbis_includes="$withval", vorbis_includes="") -AC_ARG_ENABLE(vorbistest, [ --disable-vorbistest Do not try to compile and run a test Vorbis program],, enable_vorbistest=yes) - - if test "x$vorbis_libraries" != "x" ; then - VORBIS_LIBS="-L$vorbis_libraries" - elif test "x$vorbis_prefix" != "x" ; then - VORBIS_LIBS="-L$vorbis_prefix/lib" - elif test "x$prefix" != "xNONE"; then - VORBIS_LIBS="-L$prefix/lib" - fi - - VORBIS_LIBS="$VORBIS_LIBS -lvorbis -lm" - VORBISFILE_LIBS="-lvorbisfile" - VORBISENC_LIBS="-lvorbisenc" - - if test "x$vorbis_includes" != "x" ; then - VORBIS_CFLAGS="-I$vorbis_includes" - elif test "x$vorbis_prefix" != "x" ; then - VORBIS_CFLAGS="-I$vorbis_prefix/include" - elif test "x$prefix" != "xNONE"; then - VORBIS_CFLAGS="-I$prefix/include" - fi - - - AC_MSG_CHECKING(for Vorbis) - no_vorbis="" - - - if test "x$enable_vorbistest" = "xyes" ; then - ac_save_CFLAGS="$CFLAGS" - ac_save_LIBS="$LIBS" - CFLAGS="$CFLAGS $VORBIS_CFLAGS $OGG_CFLAGS" - LIBS="$LIBS $VORBIS_LIBS $VORBISENC_LIBS $OGG_LIBS" -dnl -dnl Now check if the installed Vorbis is sufficiently new. -dnl - rm -f conf.vorbistest - AC_TRY_RUN([ -#include -#include -#include -#include -#include - -int main () -{ - vorbis_block vb; - vorbis_dsp_state vd; - vorbis_info vi; - - vorbis_info_init (&vi); - vorbis_encode_init (&vi, 2, 44100, -1, 128000, -1); - vorbis_analysis_init (&vd, &vi); - vorbis_block_init (&vd, &vb); - /* this function was added in 1.0rc3, so this is what we're testing for */ - vorbis_bitrate_addblock (&vb); - - /* this define was added in 1.0 final */ -#ifdef OV_ECTL_RATEMANAGE_SET - system("touch conf.vorbistest"); - return 0; -#else - return -1; -#endif -} - -],, no_vorbis=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"]) - CFLAGS="$ac_save_CFLAGS" - LIBS="$ac_save_LIBS" - fi - - if test "x$no_vorbis" = "x" ; then - AC_MSG_RESULT(yes) - ifelse([$1], , :, [$1]) - else - AC_MSG_RESULT(no) - if test -f conf.vorbistest ; then - : - else - echo "*** Could not run Vorbis test program, checking why..." - CFLAGS="$CFLAGS $VORBIS_CFLAGS" - LIBS="$LIBS $VORBIS_LIBS $OGG_LIBS" - AC_TRY_LINK([ -#include -#include -], [ return 0; ], - [ echo "*** The test program compiled, but did not run. This usually means" - echo "*** that the run-time linker is not finding Vorbis or finding the wrong" - echo "*** version of Vorbis. If it is not finding Vorbis, you'll need to set your" - echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point" - echo "*** to the installed location Also, make sure you have run ldconfig if that" - echo "*** is required on your system" - echo "***" - echo "*** If you have an old version installed, it is best to remove it, although" - echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"], - [ echo "*** The test program failed to compile or link. See the file config.log for the" - echo "*** exact error that occured. This usually means Vorbis was incorrectly installed" - echo "*** or that you have moved Vorbis since it was installed." ]) - CFLAGS="$ac_save_CFLAGS" - LIBS="$ac_save_LIBS" - fi - VORBIS_CFLAGS="" - VORBIS_LIBS="" - VORBISFILE_LIBS="" - VORBISENC_LIBS="" - ifelse([$2], , :, [$2]) - fi - AC_SUBST(VORBIS_CFLAGS) - AC_SUBST(VORBIS_LIBS) - AC_SUBST(VORBISFILE_LIBS) - AC_SUBST(VORBISENC_LIBS) - rm -f conf.vorbistest -]) From 994156c1b8779ea879591eb32def0dc0e6a41b7a Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Mon, 3 Jan 2011 20:05:52 +0100 Subject: [PATCH 252/448] dvbsuboverlay: remove unnecessary RGB -> YUV conversion by using YUV palettes the default CLUTs still use RGB -> YUV conversions since the standard defines them as RGBA values. --- gst/dvbsuboverlay/dvb-sub.c | 86 ++++++++++-------- gst/dvbsuboverlay/gstdvbsuboverlay.c | 126 ++++++--------------------- 2 files changed, 75 insertions(+), 137 deletions(-) diff --git a/gst/dvbsuboverlay/dvb-sub.c b/gst/dvbsuboverlay/dvb-sub.c index 259362278a..eb68106586 100644 --- a/gst/dvbsuboverlay/dvb-sub.c +++ b/gst/dvbsuboverlay/dvb-sub.c @@ -33,7 +33,6 @@ #include /* memset */ #include /* GST_READ_UINT16_BE */ #include /* GstBitReader */ -#include "ffmpeg-colorspace.h" /* YUV_TO_RGB1_CCIR */ /* FIXME: Just give YUV data to gstreamer then? */ #include "dvb-sub.h" @@ -55,13 +54,10 @@ static void dvb_sub_init (void); */ #define MAX_NEG_CROP 1024 -static guint8 ff_cropTbl[256 + 2 * MAX_NEG_CROP] = { 0, }; -#define cm (ff_cropTbl + MAX_NEG_CROP) +#define AYUV(y,u,v,a) (((a) << 24) | ((y) << 16) | ((u) << 8) | (v)) +#define RGBA_TO_AYUV(r,g,b,a) (((a) << 24) | ((rgb_to_y(r,g,b)) << 16) | ((rgb_to_u(r,g,b)) << 8) | (rgb_to_v(r,g,b))) -/* FIXME: This is really ARGB... We might need this configurable for performant - * FIXME: use in GStreamer as well if that likes RGBA more (Qt prefers ARGB) */ -#define RGBA(r,g,b,a) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b)) typedef struct DVBSubCLUT { @@ -156,6 +152,40 @@ typedef enum BOTTOM_FIELD = 1 } DvbSubPixelDataSubBlockFieldType; +static inline gint +rgb_to_y (gint r, gint g, gint b) +{ + gint ret; + + ret = (gint) (((19595 * r) >> 16) + ((38470 * g) >> 16) + ((7471 * b) >> 16)); + ret = CLAMP (ret, 0, 255); + return ret; +} + +static inline gint +rgb_to_u (gint r, gint g, gint b) +{ + gint ret; + + ret = + (gint) (-((11059 * r) >> 16) - ((21709 * g) >> 16) + ((32768 * b) >> 16) + + 128); + ret = CLAMP (ret, 0, 255); + return ret; +} + +static inline gint +rgb_to_v (gint r, gint g, gint b) +{ + gint ret; + + ret = + (gint) (((32768 * r) >> 16) - ((27439 * g) >> 16) - ((5329 * b) >> 16) + + 128); + ret = CLAMP (ret, 0, 255); + return ret; +} + static DVBSubObject * get_object (DvbSub * dvb_sub, guint16 object_id) { @@ -263,20 +293,6 @@ delete_state (DvbSub * dvb_sub) g_warn_if_fail (dvb_sub->object_list == NULL); } -/* init static data necessary for ffmpeg-colorspace conversion */ -static void -dsputil_static_init (void) -{ - int i; - - for (i = 0; i < 256; i++) - ff_cropTbl[i + MAX_NEG_CROP] = i; - for (i = 0; i < MAX_NEG_CROP; i++) { - ff_cropTbl[i] = 0; - ff_cropTbl[i + MAX_NEG_CROP + 256] = 255; - } -} - static void dvb_sub_init (void) { @@ -284,19 +300,17 @@ dvb_sub_init (void) GST_DEBUG_CATEGORY_INIT (dvbsub_debug, "dvbsub", 0, "dvbsuboverlay parser"); - dsputil_static_init (); /* Initializes ff_cropTbl table, used in YUV_TO_RGB conversion */ - /* Initialize the static default_clut structure, from which other clut * structures are initialized from (to start off with default CLUTs * as defined in the specification). */ default_clut.id = -1; - default_clut.clut4[0] = RGBA (0, 0, 0, 0); - default_clut.clut4[1] = RGBA (255, 255, 255, 255); - default_clut.clut4[2] = RGBA (0, 0, 0, 255); - default_clut.clut4[3] = RGBA (127, 127, 127, 255); + default_clut.clut4[0] = RGBA_TO_AYUV (0, 0, 0, 0); + default_clut.clut4[1] = RGBA_TO_AYUV (255, 255, 255, 255); + default_clut.clut4[2] = RGBA_TO_AYUV (0, 0, 0, 255); + default_clut.clut4[3] = RGBA_TO_AYUV (127, 127, 127, 255); - default_clut.clut16[0] = RGBA (0, 0, 0, 0); + default_clut.clut16[0] = RGBA_TO_AYUV (0, 0, 0, 0); for (i = 1; i < 16; i++) { if (i < 8) { r = (i & 1) ? 255 : 0; @@ -307,10 +321,10 @@ dvb_sub_init (void) g = (i & 2) ? 127 : 0; b = (i & 4) ? 127 : 0; } - default_clut.clut16[i] = RGBA (r, g, b, 255); + default_clut.clut16[i] = RGBA_TO_AYUV (r, g, b, 255); } - default_clut.clut256[0] = RGBA (0, 0, 0, 0); + default_clut.clut256[0] = RGBA_TO_AYUV (0, 0, 0, 0); for (i = 1; i < 256; i++) { if (i < 8) { r = (i & 1) ? 255 : 0; @@ -345,7 +359,7 @@ dvb_sub_init (void) break; } } - default_clut.clut256[i] = RGBA (r, g, b, a); + default_clut.clut256[i] = RGBA_TO_AYUV (r, g, b, a); } } @@ -564,7 +578,6 @@ _dvb_sub_parse_clut_segment (DvbSub * dvb_sub, guint16 page_id, guint8 * buf, DVBSubCLUT *clut; int entry_id, depth, full_range; int y, cr, cb, alpha; - int r, g, b, r_add, g_add, b_add; GST_MEMDUMP ("DVB clut packet", buf, buf_size); @@ -613,18 +626,15 @@ _dvb_sub_parse_clut_segment (DvbSub * dvb_sub, guint16 page_id, guint8 * buf, if (y == 0) alpha = 0xff; - YUV_TO_RGB1_CCIR (cb, cr); - YUV_TO_RGB2_CCIR (r, g, b, y); - - GST_DEBUG ("CLUT DEFINITION: clut %d := (%d,%d,%d,%d)", entry_id, r, g, b, + GST_DEBUG ("CLUT DEFINITION: clut %d := (%d,%d,%d,%d)", entry_id, y, cb, cr, alpha); if (depth & 0x80) - clut->clut4[entry_id] = RGBA (r, g, b, 255 - alpha); + clut->clut4[entry_id] = AYUV (y, cb, cr, 255 - alpha); if (depth & 0x40) - clut->clut16[entry_id] = RGBA (r, g, b, 255 - alpha); + clut->clut16[entry_id] = AYUV (y, cb, cr, 255 - alpha); if (depth & 0x20) - clut->clut256[entry_id] = RGBA (r, g, b, 255 - alpha); + clut->clut256[entry_id] = AYUV (y, cb, cr, 255 - alpha); } } diff --git a/gst/dvbsuboverlay/gstdvbsuboverlay.c b/gst/dvbsuboverlay/gstdvbsuboverlay.c index 64cfe9c317..ca6789a87d 100644 --- a/gst/dvbsuboverlay/gstdvbsuboverlay.c +++ b/gst/dvbsuboverlay/gstdvbsuboverlay.c @@ -423,47 +423,11 @@ gst_dvbsub_overlay_getcaps (GstPad * pad) return caps; } -static inline gint -rgb_to_y (gint r, gint g, gint b) -{ - gint ret; - - ret = (gint) (((19595 * r) >> 16) + ((38470 * g) >> 16) + ((7471 * b) >> 16)); - ret = CLAMP (ret, 0, 255); - return ret; -} - -static inline gint -rgb_to_u (gint r, gint g, gint b) -{ - gint ret; - - ret = - (gint) (-((11059 * r) >> 16) - ((21709 * g) >> 16) + ((32768 * b) >> 16) + - 128); - ret = CLAMP (ret, 0, 255); - return ret; -} - -static inline gint -rgb_to_v (gint r, gint g, gint b) -{ - gint ret; - - ret = - (gint) (((32768 * r) >> 16) - ((27439 * g) >> 16) - ((5329 * b) >> 16) + - 128); - ret = CLAMP (ret, 0, 255); - return ret; -} - -/* FIXME: DVB-SUB actually provides us AYUV from CLUT, but libdvbsub used to convert it to ARGB */ static void blit_i420 (GstDVBSubOverlay * overlay, DVBSubtitles * subs, GstBuffer * buffer) { guint counter; DVBSubtitleRect *sub_region; - gint r, g, b; gint a1, a2, a3, a4; gint y1, y2, y3, y4; gint u1, u2, u3, u4; @@ -574,49 +538,33 @@ blit_i420 (GstDVBSubOverlay * overlay, DVBSubtitles * subs, GstBuffer * buffer) color = sub_region->pict.palette[src[(sy >> 16) * src_stride + (sx >> 16)]]; a1 = (color >> 24) & 0xff; - r = (color >> 16) & 0xff; - g = (color >> 8) & 0xff; - b = color & 0xff; - - y1 = rgb_to_y (r, g, b); - u1 = rgb_to_u (r, g, b); - v1 = rgb_to_v (r, g, b); + y1 = (color >> 16) & 0xff; + u1 = (color >> 8) & 0xff; + v1 = color & 0xff; color = sub_region->pict.palette[src[(sy >> 16) * src_stride + ((sx + xstep) >> 16)]]; a2 = (color >> 24) & 0xff; - r = (color >> 16) & 0xff; - g = (color >> 8) & 0xff; - b = color & 0xff; - - y2 = rgb_to_y (r, g, b); - u2 = rgb_to_u (r, g, b); - v2 = rgb_to_v (r, g, b); + y2 = (color >> 16) & 0xff; + u2 = (color >> 8) & 0xff; + v2 = color & 0xff; color = sub_region->pict.palette[src[((sy + ystep) >> 16) * src_stride + (sx >> 16)]]; a3 = (color >> 24) & 0xff; - r = (color >> 16) & 0xff; - g = (color >> 8) & 0xff; - b = color & 0xff; - - y3 = rgb_to_y (r, g, b); - u3 = rgb_to_u (r, g, b); - v3 = rgb_to_v (r, g, b); + y3 = (color >> 16) & 0xff; + u3 = (color >> 8) & 0xff; + v3 = color & 0xff; color = sub_region->pict.palette[src[((sy + ystep) >> 16) * src_stride + ((sx + xstep) >> 16)]]; a4 = (color >> 24) & 0xff; - r = (color >> 16) & 0xff; - g = (color >> 8) & 0xff; - b = color & 0xff; - - y4 = rgb_to_y (r, g, b); - u4 = rgb_to_u (r, g, b); - v4 = rgb_to_v (r, g, b); + y4 = (color >> 16) & 0xff; + u4 = (color >> 8) & 0xff; + v4 = color & 0xff; dst_y[0] = (a1 * y1 + (255 - a1) * dst_y[0]) / 255; dst_y[1] = (a2 * y2 + (255 - a2) * dst_y[1]) / 255; @@ -641,25 +589,17 @@ blit_i420 (GstDVBSubOverlay * overlay, DVBSubtitles * subs, GstBuffer * buffer) color = sub_region->pict.palette[src[(sy >> 16) * src_stride + (sx >> 16)]]; a1 = (color >> 24) & 0xff; - r = (color >> 16) & 0xff; - g = (color >> 8) & 0xff; - b = color & 0xff; - - y1 = rgb_to_y (r, g, b); - u1 = rgb_to_u (r, g, b); - v1 = rgb_to_v (r, g, b); + y1 = (color >> 16) & 0xff; + u1 = (color >> 8) & 0xff; + v1 = color & 0xff; color = sub_region->pict.palette[src[((sy + ystep) >> 16) * src_stride + (sx >> 16)]]; a3 = (color >> 24) & 0xff; - r = (color >> 16) & 0xff; - g = (color >> 8) & 0xff; - b = color & 0xff; - - y3 = rgb_to_y (r, g, b); - u3 = rgb_to_u (r, g, b); - v3 = rgb_to_v (r, g, b); + y3 = (color >> 16) & 0xff; + u3 = (color >> 8) & 0xff; + v3 = color & 0xff; dst_y[0] = (a1 * y1 + (255 - a1) * dst_y[0]) / 255; dst_y2[0] = (a3 * y3 + (255 - a3) * dst_y2[0]) / 255; @@ -690,25 +630,17 @@ blit_i420 (GstDVBSubOverlay * overlay, DVBSubtitles * subs, GstBuffer * buffer) color = sub_region->pict.palette[src[(sy >> 16) * src_stride + (sx >> 16)]]; a1 = (color >> 24) & 0xff; - r = (color >> 16) & 0xff; - g = (color >> 8) & 0xff; - b = color & 0xff; - - y1 = rgb_to_y (r, g, b); - u1 = rgb_to_u (r, g, b); - v1 = rgb_to_v (r, g, b); + y1 = (color >> 16) & 0xff; + u1 = (color >> 8) & 0xff; + v1 = color & 0xff; color = sub_region->pict.palette[src[(sy >> 16) * src_stride + ((sx + xstep) >> 16)]]; a2 = (color >> 24) & 0xff; - r = (color >> 16) & 0xff; - g = (color >> 8) & 0xff; - b = color & 0xff; - - y2 = rgb_to_y (r, g, b); - u2 = rgb_to_u (r, g, b); - v2 = rgb_to_v (r, g, b); + y2 = (color >> 16) & 0xff; + u2 = (color >> 8) & 0xff; + v2 = color & 0xff; dst_y[0] = (a1 * y1 + (255 - a1) * dst_y[0]) / 255; dst_y[1] = (a2 * y2 + (255 - a2) * dst_y[1]) / 255; @@ -728,13 +660,9 @@ blit_i420 (GstDVBSubOverlay * overlay, DVBSubtitles * subs, GstBuffer * buffer) color = sub_region->pict.palette[src[(sy >> 16) * src_stride + (sx >> 16)]]; a1 = (color >> 24) & 0xff; - r = (color >> 16) & 0xff; - g = (color >> 8) & 0xff; - b = color & 0xff; - - y1 = rgb_to_y (r, g, b); - u1 = rgb_to_u (r, g, b); - v1 = rgb_to_v (r, g, b); + y1 = (color >> 16) & 0xff; + u1 = (color >> 8) & 0xff; + v1 = color & 0xff; dst_y[0] = (a1 * y1 + (255 - a1) * dst_y[0]) / 255; From f356c4f7de7f971afe9372d0373c9b883d70fedb Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Mon, 3 Jan 2011 17:10:36 -0600 Subject: [PATCH 253/448] dvb: fix build errors on macosx fixes the following compile errors: cc1: warnings being treated as errors camswclient.c: In function 'cam_sw_client_open': camswclient.c:81: warning: implicit declaration of function 'strncpy' camswclient.c:81: warning: incompatible implicit declaration of built-in function 'strncpy' camswclient.c:89: warning: implicit declaration of function 'strerror' camswclient.c:89: warning: nested extern declaration of 'strerror' camswclient.c:89: warning: format '%s' expects type 'char *', but argument 9 has type 'int' camswclient.c: In function 'send_ca_pmt': camswclient.c:129: warning: implicit declaration of function 'memcpy' camswclient.c:129: warning: incompatible implicit declaration of built-in function 'memcpy' gstdvbsrc.c:48:19: error: error.h: No such file or directory Signed-off-by: Rob Clark --- sys/dvb/camswclient.c | 4 +++- sys/dvb/gstdvbsrc.c | 1 - 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/sys/dvb/camswclient.c b/sys/dvb/camswclient.c index b68b0a7b84..98781f3a96 100644 --- a/sys/dvb/camswclient.c +++ b/sys/dvb/camswclient.c @@ -25,6 +25,8 @@ #include #include #include +#include +#include #include @@ -78,7 +80,7 @@ cam_sw_client_open (CamSwClient * client, const char *sock_path) g_return_val_if_fail (sock_path != NULL, FALSE); addr.sun_family = AF_UNIX; - strncpy (addr.sun_path, sock_path, UNIX_PATH_MAX); + strncpy (addr.sun_path, sock_path, sizeof (addr.sun_path)); GST_INFO ("connecting to softcam socket: %s", sock_path); client->sock = socket (PF_UNIX, SOCK_STREAM, 0); diff --git a/sys/dvb/gstdvbsrc.c b/sys/dvb/gstdvbsrc.c index bce25f69b6..a136027d4e 100644 --- a/sys/dvb/gstdvbsrc.c +++ b/sys/dvb/gstdvbsrc.c @@ -45,7 +45,6 @@ #include #include #include -#include #include #include #include From 124c6d8259b0709a90587ec7a59707a80b5d48c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Mon, 3 Jan 2011 23:46:02 +0000 Subject: [PATCH 254/448] build: fix disting of experimental basecamerabinsrc lib used by camerabin2 https://bugzilla.gnome.org/show_bug.cgi?id=638604 --- gst-libs/gst/Makefile.am | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/gst-libs/gst/Makefile.am b/gst-libs/gst/Makefile.am index 56145806b0..a760e99819 100644 --- a/gst-libs/gst/Makefile.am +++ b/gst-libs/gst/Makefile.am @@ -1,4 +1,3 @@ - if BUILD_EXPERIMENTAL EXPERIMENTAL_LIBS=basecamerabinsrc endif @@ -6,4 +5,4 @@ endif SUBDIRS = interfaces signalprocessor video $(EXPERIMENTAL_LIBS) noinst_HEADERS = gst-i18n-plugin.h gettext.h -DIST_SUBDIRS = interfaces signalprocessor video $(EXPERIMENTAL_LIBS) +DIST_SUBDIRS = interfaces signalprocessor video basecamerabinsrc From c78223fc9cadd3759d100e7d5757fea84bbc212f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Mon, 3 Jan 2011 23:47:33 +0000 Subject: [PATCH 255/448] basecamerabinsrc: fix libs order in Makefile.am --- gst-libs/gst/basecamerabinsrc/Makefile.am | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gst-libs/gst/basecamerabinsrc/Makefile.am b/gst-libs/gst/basecamerabinsrc/Makefile.am index d0b69b5fef..c5d1ac0afe 100644 --- a/gst-libs/gst/basecamerabinsrc/Makefile.am +++ b/gst-libs/gst/basecamerabinsrc/Makefile.am @@ -19,8 +19,8 @@ libgstbasecamerabinsrc_@GST_MAJORMINOR@_la_CFLAGS = \ $(GST_CFLAGS) libgstbasecamerabinsrc_@GST_MAJORMINOR@_la_LIBADD = \ $(top_builddir)/gst-libs/gst/interfaces/libgstphotography-@GST_MAJORMINOR@.la \ - $(GST_PLUGINS_BASE_LIBS) $(GST_BASE_LIBS) $(GST_LIBS) \ - -lgstinterfaces-$(GST_MAJORMINOR) + $(GST_PLUGINS_BASE_LIBS) -lgstinterfaces-$(GST_MAJORMINOR) \ + $(GST_BASE_LIBS) $(GST_LIBS) libgstbasecamerabinsrc_@GST_MAJORMINOR@_la_LDFLAGS = $(GST_LIB_LDFLAGS) $(GST_ALL_LDFLAGS) $(GST_LT_LDFLAGS) From eec67aeee67633dff6a070fa573126fd96f96d46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Mon, 3 Jan 2011 23:49:51 +0000 Subject: [PATCH 256/448] camerabin2: fix cflags and libs order in Makefile.am --- gst/camerabin2/Makefile.am | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/gst/camerabin2/Makefile.am b/gst/camerabin2/Makefile.am index 5f8a53dfae..a4299be10f 100644 --- a/gst/camerabin2/Makefile.am +++ b/gst/camerabin2/Makefile.am @@ -10,14 +10,15 @@ libgstcamerabin2_la_SOURCES = gstviewfinderbin.c \ libgstcamerabin2_la_CFLAGS = \ $(GST_PLUGINS_BAD_CFLAGS) \ - $(GST_CFLAGS) $(GST_BASE_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) \ + $(GST_PLUGINS_BASE_CFLAGS) \ + $(GST_BASE_CFLAGS) $(GST_CFLAGS) \ -DGST_USE_UNSTABLE_API libgstcamerabin2_la_LIBADD = \ $(top_builddir)/gst-libs/gst/interfaces/libgstphotography-$(GST_MAJORMINOR).la \ $(top_builddir)/gst-libs/gst/basecamerabinsrc/libgstbasecamerabinsrc-$(GST_MAJORMINOR).la \ - $(GST_LIBS) $(GST_BASE_LIBS) $(GST_PLUGINS_BASE_LIBS) \ - -lgstinterfaces-$(GST_MAJORMINOR) -lgsttag-$(GST_MAJORMINOR) + $(GST_PLUGINS_BASE_LIBS) -lgstinterfaces-$(GST_MAJORMINOR) -lgsttag-$(GST_MAJORMINOR) \ + $(GST_BASE_LIBS) $(GST_LIBS) libgstcamerabin2_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) libgstcamerabin2_la_LIBTOOLFLAGS = --tag=disable-static From 3bb1d2937f2c4701268373842bd971fffbd93f4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Mon, 3 Jan 2011 23:55:59 +0000 Subject: [PATCH 257/448] examples: dist camerabin2 example as well https://bugzilla.gnome.org/show_bug.cgi?id=638604 --- tests/examples/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/examples/Makefile.am b/tests/examples/Makefile.am index f085c8b423..26833fb619 100644 --- a/tests/examples/Makefile.am +++ b/tests/examples/Makefile.am @@ -17,6 +17,6 @@ CAMERABIN2= endif SUBDIRS= $(DIRECTFB_DIR) $(GTK_EXAMPLES) -DIST_SUBDIRS= camerabin $(CAMERABIN2) directfb mxf scaletempo +DIST_SUBDIRS= camerabin camerabin2 directfb mxf scaletempo include $(top_srcdir)/common/parallel-subdirs.mak From 9f02f693de1dbda6b0aeffe592672f861861b774 Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Tue, 4 Jan 2011 13:51:21 +0000 Subject: [PATCH 258/448] dvbsuboverlay: fix two minor deinitialization memory leaks --- gst/dvbsuboverlay/dvb-sub.c | 5 +++++ gst/dvbsuboverlay/gstdvbsuboverlay.c | 8 ++++++++ 2 files changed, 13 insertions(+) diff --git a/gst/dvbsuboverlay/dvb-sub.c b/gst/dvbsuboverlay/dvb-sub.c index eb68106586..435de92a87 100644 --- a/gst/dvbsuboverlay/dvb-sub.c +++ b/gst/dvbsuboverlay/dvb-sub.c @@ -1352,6 +1352,11 @@ dvb_sub_free (DvbSub * sub) /* TODO: Add deinitalization code here */ /* FIXME: Clear up region_list contents */ delete_state (sub); + while (sub->display_list) { + DVBSubRegionDisplay *tmp = sub->display_list->next; + g_slice_free (DVBSubRegionDisplay, sub->display_list); + sub->display_list = tmp; + } g_string_free (sub->pes_buffer, TRUE); g_slice_free (DvbSub, sub); } diff --git a/gst/dvbsuboverlay/gstdvbsuboverlay.c b/gst/dvbsuboverlay/gstdvbsuboverlay.c index ca6789a87d..dc2b2d4737 100644 --- a/gst/dvbsuboverlay/gstdvbsuboverlay.c +++ b/gst/dvbsuboverlay/gstdvbsuboverlay.c @@ -167,6 +167,10 @@ gst_dvbsub_overlay_flush_subtitles (GstDVBSubOverlay * render) dvb_subtitles_free (subs); } + if (render->current_subtitle) + dvb_subtitles_free (render->current_subtitle); + render->current_subtitle = NULL; + if (render->dvb_sub) dvb_sub_free (render->dvb_sub); @@ -251,6 +255,10 @@ gst_dvbsub_overlay_finalize (GObject * object) } g_queue_free (overlay->pending_subtitles); + if (overlay->current_subtitle) + dvb_subtitles_free (overlay->current_subtitle); + overlay->current_subtitle = NULL; + if (overlay->dvb_sub) dvb_sub_free (overlay->dvb_sub); From 43bfb0009aac7dfd814a11ad6e72ef27ca8d2341 Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Tue, 4 Jan 2011 16:03:01 +0100 Subject: [PATCH 259/448] dvbsuboverlay: fix leak of "clear screen" DVBSubtitles structs --- gst/dvbsuboverlay/gstdvbsuboverlay.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gst/dvbsuboverlay/gstdvbsuboverlay.c b/gst/dvbsuboverlay/gstdvbsuboverlay.c index dc2b2d4737..9962ff0237 100644 --- a/gst/dvbsuboverlay/gstdvbsuboverlay.c +++ b/gst/dvbsuboverlay/gstdvbsuboverlay.c @@ -905,6 +905,8 @@ gst_dvbsub_overlay_chain_video (GstPad * pad, GstBuffer * buffer) dvb_subtitles_free (candidate); candidate = NULL; g_queue_pop_head (overlay->pending_subtitles); + dvb_subtitles_free (tmp); + tmp = NULL; } else if (tmp->pts + tmp->page_time_out * GST_SECOND * overlay->subtitle_segment.abs_rate >= vid_running_time) { if (candidate) From ed8e27b2370e89c411dd785073e16c7c02fd3c80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Wed, 5 Jan 2011 13:44:04 +0000 Subject: [PATCH 260/448] dvbsuboverlay: some more minor clean-ups --- gst/dvbsuboverlay/Makefile.am | 4 +- gst/dvbsuboverlay/dvb-sub.c | 25 ++++-------- gst/dvbsuboverlay/ffmpeg-colorspace.h | 57 --------------------------- 3 files changed, 9 insertions(+), 77 deletions(-) delete mode 100644 gst/dvbsuboverlay/ffmpeg-colorspace.h diff --git a/gst/dvbsuboverlay/Makefile.am b/gst/dvbsuboverlay/Makefile.am index 9cc2f38d4e..531685e04b 100644 --- a/gst/dvbsuboverlay/Makefile.am +++ b/gst/dvbsuboverlay/Makefile.am @@ -3,8 +3,8 @@ plugin_LTLIBRARIES = libgstdvbsuboverlay.la libgstdvbsuboverlay_la_SOURCES = dvb-sub.c gstdvbsuboverlay.c libgstdvbsuboverlay_la_CFLAGS = $(GST_PLUGINS_BAD_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) -libgstdvbsuboverlay_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) $(GST_LIBS) -lgstvideo-@GST_MAJORMINOR@ +libgstdvbsuboverlay_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) -lgstvideo-@GST_MAJORMINOR@ $(GST_LIBS) libgstdvbsuboverlay_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) libgstdvbsuboverlay_la_LIBTOOLFLAGS = --tag=disable-static -noinst_HEADERS = gstdvbsuboverlay.h dvb-sub.h ffmpeg-colorspace.h +noinst_HEADERS = gstdvbsuboverlay.h dvb-sub.h diff --git a/gst/dvbsuboverlay/dvb-sub.c b/gst/dvbsuboverlay/dvb-sub.c index 435de92a87..a0ef3e1519 100644 --- a/gst/dvbsuboverlay/dvb-sub.c +++ b/gst/dvbsuboverlay/dvb-sub.c @@ -53,8 +53,6 @@ static void dvb_sub_init (void); * and signalling the API user for new bitmaps to show on screen. */ -#define MAX_NEG_CROP 1024 - #define AYUV(y,u,v,a) (((a) << 24) | ((y) << 16) | ((u) << 8) | (v)) #define RGBA_TO_AYUV(r,g,b,a) (((a) << 24) | ((rgb_to_y(r,g,b)) << 16) | ((rgb_to_u(r,g,b)) << 8) | (rgb_to_v(r,g,b))) @@ -374,10 +372,6 @@ _dvb_sub_parse_page_segment (DvbSub * dvb_sub, guint16 page_id, guint8 * buf, guint8 region_id; guint8 page_state; -#ifndef GST_DISABLE_GST_DEBUG - static int counter = 0; /* FIXME: static counter? I think not.. */ -#endif - if (buf_size < 1) return; @@ -390,9 +384,8 @@ _dvb_sub_parse_page_segment (DvbSub * dvb_sub, guint16 page_id, guint8 * buf, "Normal case", "ACQUISITION POINT", "Mode Change", "RESERVED" }; - ++counter; - GST_DEBUG ("PAGE: %d: page_id = %u, length = %d, page_time_out = %u secs, " - "page_state = %s", counter, page_id, buf_size, dvb_sub->page_time_out, + GST_DEBUG ("PAGE: page_id = %u, length = %d, page_time_out = %u secs, " + "page_state = %s", page_id, buf_size, dvb_sub->page_time_out, page_state_str[page_state]); } #endif @@ -433,8 +426,8 @@ _dvb_sub_parse_page_segment (DvbSub * dvb_sub, guint16 page_id, guint8 * buf, dvb_sub->display_list = display; dvb_sub->display_list_size++; - GST_LOG ("PAGE %d: REGION information: ID = %u, address = %ux%u", - counter, region_id, display->x_pos, display->y_pos); + GST_LOG ("PAGE: REGION information: ID = %u, address = %ux%u", region_id, + display->x_pos, display->y_pos); } while (tmp_display_list) { @@ -587,7 +580,7 @@ _dvb_sub_parse_clut_segment (DvbSub * dvb_sub, guint16 page_id, guint8 * buf, clut = get_clut (dvb_sub, clut_id); if (!clut) { - clut = g_slice_new (DVBSubCLUT); /* FIXME-MEMORY-LEAK: This seems to leak per valgrind */ + clut = g_slice_new (DVBSubCLUT); memcpy (clut, &default_clut, sizeof (DVBSubCLUT)); @@ -1201,8 +1194,6 @@ _dvb_sub_parse_end_of_display_set (DvbSub * dvb_sub, guint16 page_id, guint32 *clut_table; int i; - static unsigned counter = 0; /* DEBUG use only *//* FIXME: get rid */ - GST_DEBUG ("DISPLAY SET END: page_id = %u, length = %d", page_id, buf_size); sub = g_slice_new0 (DVBSubtitles); @@ -1275,10 +1266,8 @@ _dvb_sub_parse_end_of_display_set (DvbSub * dvb_sub, guint16 page_id, rect->pict.data = g_malloc (region->buf_size); /* FIXME: Can we use GSlice here? */ memcpy (rect->pict.data, region->pbuf, region->buf_size); - ++counter; - GST_DEBUG ("DISPLAY: an object rect created: number %u, iteration %u, " - "pos: %d:%d, size: %dx%d", counter, i, rect->x, rect->y, rect->w, - rect->h); + GST_DEBUG ("DISPLAY: an object rect created: iteration %u, " + "pos: %d:%d, size: %dx%d", i, rect->x, rect->y, rect->w, rect->h); GST_MEMDUMP ("rect->pict.data content", rect->pict.data, region->buf_size); diff --git a/gst/dvbsuboverlay/ffmpeg-colorspace.h b/gst/dvbsuboverlay/ffmpeg-colorspace.h deleted file mode 100644 index baebe80b70..0000000000 --- a/gst/dvbsuboverlay/ffmpeg-colorspace.h +++ /dev/null @@ -1,57 +0,0 @@ -/* - * This file is copied from ffmpeg's libavcodec/colorspace.h - * for the YUV_TO_RGB{1,2}_CCIR macros. - * Original copyright header and contents follows: - */ -/* - * Colorspace conversion defines - * Copyright (c) 2001, 2002, 2003 Fabrice Bellard - * - * This file is part of FFmpeg. - * - * FFmpeg 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; either - * version 2.1 of the License, or (at your option) any later version. - * - * FFmpeg 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 FFmpeg; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - */ - -/** - * @file libavcodec/colorspace.h - * Various defines for YUV<->RGB conversion - */ - -#ifndef AVCODEC_COLORSPACE_H -#define AVCODEC_COLORSPACE_H - -#define SCALEBITS 10 -#define ONE_HALF (1 << (SCALEBITS - 1)) -#define FIX(x) ((int) ((x) * (1<> SCALEBITS];\ - g = cm[(y + g_add) >> SCALEBITS];\ - b = cm[(y + b_add) >> SCALEBITS];\ -} - -#endif /* AVCODEC_COLORSPACE_H */ From c627cd40e76f8927cdf046d039d5955916b11645 Mon Sep 17 00:00:00 2001 From: Edward Hervey Date: Wed, 5 Jan 2011 16:43:45 +0100 Subject: [PATCH 261/448] y4m: Fix unitialized variables on macosx --- gst/y4m/gsty4mdec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst/y4m/gsty4mdec.c b/gst/y4m/gsty4mdec.c index 958512fb32..7011bacf5b 100644 --- a/gst/y4m/gsty4mdec.c +++ b/gst/y4m/gsty4mdec.c @@ -281,7 +281,7 @@ gst_y4m_dec_parse_header (GstY4mDec * y4mdec, char *header) { char *end; int format = -1; - int interlaced_char; + int interlaced_char = 0; if (memcmp (header, "YUV4MPEG2 ", 10) != 0) { return FALSE; From a09078db4a44d3726ecb19b3d2b3765ac68d5d6c Mon Sep 17 00:00:00 2001 From: David Schleef Date: Fri, 17 Dec 2010 14:50:50 -0800 Subject: [PATCH 262/448] element-maker: improve pushsrc --- tools/element-templates/pushsrc | 213 +++++++++++++++++++++++++++++++- tools/gst-element-maker | 33 +++-- 2 files changed, 236 insertions(+), 10 deletions(-) diff --git a/tools/element-templates/pushsrc b/tools/element-templates/pushsrc index 4dfb678494..56cc7a6bf3 100644 --- a/tools/element-templates/pushsrc +++ b/tools/element-templates/pushsrc @@ -10,13 +10,221 @@ gstreamer-base-0.10 % includes #include % prototypes +static GstCaps *gst_replace_get_caps (GstBaseSrc * src); +static gboolean gst_replace_set_caps (GstBaseSrc * src, GstCaps * caps); +static gboolean gst_replace_negotiate (GstBaseSrc * src); +static gboolean gst_replace_newsegment (GstBaseSrc * src); +static gboolean gst_replace_start (GstBaseSrc * src); +static gboolean gst_replace_stop (GstBaseSrc * src); +static void +gst_replace_get_times (GstBaseSrc * src, GstBuffer * buffer, + GstClockTime * start, GstClockTime * end); +static gboolean gst_replace_get_size (GstBaseSrc * src, guint64 * size); +static gboolean gst_replace_is_seekable (GstBaseSrc * src); +static gboolean gst_replace_unlock (GstBaseSrc * src); +static gboolean gst_replace_event (GstBaseSrc * src, GstEvent * event); +static gboolean gst_replace_do_seek (GstBaseSrc * src, GstSegment * segment); +static gboolean gst_replace_query (GstBaseSrc * src, GstQuery * query); +static gboolean gst_replace_check_get_range (GstBaseSrc * src); +static void gst_replace_fixate (GstBaseSrc * src, GstCaps * caps); +static gboolean gst_replace_unlock_stop (GstBaseSrc * src); +static gboolean +gst_replace_prepare_seek_segment (GstBaseSrc * src, GstEvent * seek, + GstSegment * segment); static GstFlowReturn gst_replace_create (GstPushSrc * src, GstBuffer ** buf); % declare-class - GstPushSrcClass *pushsrc_class = GST_PUSH_SRC_CLASS (klass); + GstBaseSrcClass *base_src_class = GST_BASE_SRC_CLASS (klass); + GstPushSrcClass *push_src_class = GST_PUSH_SRC_CLASS (klass); % set-methods - pushsrc_class->create = GST_DEBUG_FUNCPTR (gst_replace_create); + base_src_class->get_caps = GST_DEBUG_FUNCPTR (gst_replace_get_caps); + base_src_class->set_caps = GST_DEBUG_FUNCPTR (gst_replace_set_caps); + base_src_class->negotiate = GST_DEBUG_FUNCPTR (gst_replace_negotiate); + base_src_class->newsegment = GST_DEBUG_FUNCPTR (gst_replace_newsegment); + base_src_class->start = GST_DEBUG_FUNCPTR (gst_replace_start); + base_src_class->stop = GST_DEBUG_FUNCPTR (gst_replace_stop); + base_src_class->get_times = GST_DEBUG_FUNCPTR (gst_replace_get_times); + base_src_class->get_size = GST_DEBUG_FUNCPTR (gst_replace_get_size); + base_src_class->is_seekable = GST_DEBUG_FUNCPTR (gst_replace_is_seekable); + base_src_class->unlock = GST_DEBUG_FUNCPTR (gst_replace_unlock); + base_src_class->event = GST_DEBUG_FUNCPTR (gst_replace_event); + base_src_class->do_seek = GST_DEBUG_FUNCPTR (gst_replace_do_seek); + base_src_class->query = GST_DEBUG_FUNCPTR (gst_replace_query); + base_src_class->check_get_range = GST_DEBUG_FUNCPTR (gst_replace_check_get_range); + base_src_class->fixate = GST_DEBUG_FUNCPTR (gst_replace_fixate); + base_src_class->unlock_stop = GST_DEBUG_FUNCPTR (gst_replace_unlock_stop); + base_src_class->prepare_seek_segment = GST_DEBUG_FUNCPTR (gst_replace_prepare_seek_segment); + + push_src_class->create = GST_DEBUG_FUNCPTR (gst_replace_create); % methods +static GstCaps * +gst_replace_get_caps (GstBaseSrc * src) +{ + GstReplace *replace = GST_REPLACE (src); + + GST_DEBUG_OBJECT (replace, "get_caps"); + + return NULL; +} + +static gboolean +gst_replace_set_caps (GstBaseSrc * src, GstCaps * caps) +{ + GstReplace *replace = GST_REPLACE (src); + + GST_DEBUG_OBJECT (replace, "set_caps"); + + return TRUE; +} + +static gboolean +gst_replace_negotiate (GstBaseSrc * src) +{ + GstReplace *replace = GST_REPLACE (src); + + GST_DEBUG_OBJECT (replace, "negotiate"); + + return TRUE; +} + +static gboolean +gst_replace_newsegment (GstBaseSrc * src) +{ + GstReplace *replace = GST_REPLACE (src); + + GST_DEBUG_OBJECT (replace, "newsegment"); + + return TRUE; +} + +static gboolean +gst_replace_start (GstBaseSrc * src) +{ + GstReplace *replace = GST_REPLACE (src); + + GST_DEBUG_OBJECT (replace, "start"); + + return TRUE; +} + +static gboolean +gst_replace_stop (GstBaseSrc * src) +{ + GstReplace *replace = GST_REPLACE (src); + + GST_DEBUG_OBJECT (replace, "stop"); + + return TRUE; +} + +static void +gst_replace_get_times (GstBaseSrc * src, GstBuffer * buffer, + GstClockTime * start, GstClockTime * end) +{ + GstReplace *replace = GST_REPLACE (src); + + GST_DEBUG_OBJECT (replace, "get_times"); +} + +static gboolean +gst_replace_get_size (GstBaseSrc * src, guint64 * size) +{ + GstReplace *replace = GST_REPLACE (src); + + GST_DEBUG_OBJECT (replace, "get_size"); + + return TRUE; +} + +static gboolean +gst_replace_is_seekable (GstBaseSrc * src) +{ + GstReplace *replace = GST_REPLACE (src); + + GST_DEBUG_OBJECT (replace, "is_seekable"); + + return FALSE; +} + +static gboolean +gst_replace_unlock (GstBaseSrc * src) +{ + GstReplace *replace = GST_REPLACE (src); + + GST_DEBUG_OBJECT (replace, "unlock"); + + return TRUE; +} + +static gboolean +gst_replace_event (GstBaseSrc * src, GstEvent * event) +{ + GstReplace *replace = GST_REPLACE (src); + + GST_DEBUG_OBJECT (replace, "event"); + + return TRUE; +} + +static gboolean +gst_replace_do_seek (GstBaseSrc * src, GstSegment * segment) +{ + GstReplace *replace = GST_REPLACE (src); + + GST_DEBUG_OBJECT (replace, "do_seek"); + + return FALSE; +} + +static gboolean +gst_replace_query (GstBaseSrc * src, GstQuery * query) +{ + GstReplace *replace = GST_REPLACE (src); + + GST_DEBUG_OBJECT (replace, "query"); + + return TRUE; +} + +static gboolean +gst_replace_check_get_range (GstBaseSrc * src) +{ + GstReplace *replace = GST_REPLACE (src); + + GST_DEBUG_OBJECT (replace, "get_range"); + + return FALSE; +} + +static void +gst_replace_fixate (GstBaseSrc * src, GstCaps * caps) +{ + GstReplace *replace = GST_REPLACE (src); + + GST_DEBUG_OBJECT (replace, "fixate"); +} + +static gboolean +gst_replace_unlock_stop (GstBaseSrc * src) +{ + GstReplace *replace = GST_REPLACE (src); + + GST_DEBUG_OBJECT (replace, "stop"); + + return TRUE; +} + +static gboolean +gst_replace_prepare_seek_segment (GstBaseSrc * src, GstEvent * seek, + GstSegment * segment) +{ + GstReplace *replace = GST_REPLACE (src); + + GST_DEBUG_OBJECT (replace, "seek_segment"); + + return FALSE; +} + static GstFlowReturn gst_replace_create (GstPushSrc * src, GstBuffer ** buf) { @@ -24,3 +232,4 @@ gst_replace_create (GstPushSrc * src, GstBuffer ** buf) return GST_FLOW_OK; } % end + diff --git a/tools/gst-element-maker b/tools/gst-element-maker index aa899b652f..67525ef7fc 100755 --- a/tools/gst-element-maker +++ b/tools/gst-element-maker @@ -116,7 +116,6 @@ cat <<-EOF */ EOF -#grep -A 10000 '^% copyright' $templatedir/base | tail -n +2|grep -m 1 -B 10000 '^%'|head -n -1 cat < EOF -grep -A 10000 '^% includes' $templatedir/base | tail -n +2|grep -m 1 -B 10000 '^%'|head -n -1 grep -A 10000 '^% includes' $templatedir/gobject | tail -n +2|grep -m 1 -B 10000 '^%'|head -n -1 grep -A 10000 '^% includes' $templatedir/$class | tail -n +2|grep -m 1 -B 10000 '^%'|head -n -1 @@ -140,7 +139,6 @@ GST_DEBUG_CATEGORY_STATIC (gst_replace_debug); EOF -grep -A 10000 '^% prototypes' $templatedir/base | tail -n +2|grep -m 1 -B 10000 '^%'|head -n -1 grep -A 10000 '^% prototypes' $templatedir/gobject | tail -n +2|grep -m 1 -B 10000 '^%'|head -n -1 grep -A 10000 '^% prototypes' $templatedir/$class | tail -n +2|grep -m 1 -B 10000 '^%'|head -n -1 for each in $pads @@ -180,6 +178,9 @@ gst_replace_base_init (gpointer g_class) { GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + GST_DEBUG_CATEGORY_INIT (gst_replace_debug_category, "replace", 0, + "replace element"); + EOF for each in $pads @@ -197,13 +198,11 @@ static void gst_replace_class_init (GstReplaceClass * klass) { EOF -grep -A 10000 '^% declare-class' $templatedir/base | tail -n +2|grep -m 1 -B 10000 '^%'|head -n -1 grep -A 10000 '^% declare-class' $templatedir/gobject | tail -n +2|grep -m 1 -B 10000 '^%'|head -n -1 grep -A 10000 '^% declare-class' $templatedir/$class | tail -n +2|grep -m 1 -B 10000 '^%'|head -n -1 echo -grep -A 10000 '^% set-methods' $templatedir/base | tail -n +2|grep -m 1 -B 10000 '^%'|head -n -1 grep -A 10000 '^% set-methods' $templatedir/gobject | tail -n +2|grep -m 1 -B 10000 '^%'|head -n -1 grep -A 10000 '^% set-methods' $templatedir/$class | tail -n +2|grep -m 1 -B 10000 '^%'|head -n -1 @@ -227,7 +226,6 @@ cat < + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +EOF cat < Date: Wed, 15 Dec 2010 15:58:48 -0800 Subject: [PATCH 263/448] y4mdec: Fix copyright --- gst/y4m/gsty4mdec.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst/y4m/gsty4mdec.h b/gst/y4m/gsty4mdec.h index 590a2d6427..6ea6ca1187 100644 --- a/gst/y4m/gsty4mdec.h +++ b/gst/y4m/gsty4mdec.h @@ -1,5 +1,5 @@ /* GStreamer - * Copyright (C) 2010 REAL_NAME + * Copyright (C) 2010 David Schleef * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public From 063be2f97208ab5ac3fe6be04d2368b2aa4bb4a8 Mon Sep 17 00:00:00 2001 From: Edward Hervey Date: Thu, 6 Jan 2011 12:49:43 +0100 Subject: [PATCH 264/448] flacparse: Fix unitialized variable on macosx --- gst/audioparsers/gstflacparse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst/audioparsers/gstflacparse.c b/gst/audioparsers/gstflacparse.c index 0d21c4c0ef..9243a0bdd7 100644 --- a/gst/audioparsers/gstflacparse.c +++ b/gst/audioparsers/gstflacparse.c @@ -898,7 +898,7 @@ static void gst_flac_parse_process_seektable (GstFlacParse * flacparse, gint64 boffset) { GstByteReader br; - gint64 offset, samples; + gint64 offset = 0, samples = 0; GST_DEBUG_OBJECT (flacparse, "parsing seektable; base offset %" G_GINT64_FORMAT, boffset); From 0a55306c40b67021cbcc7439dd8944ce47e38c78 Mon Sep 17 00:00:00 2001 From: Edward Hervey Date: Thu, 6 Jan 2011 12:50:14 +0100 Subject: [PATCH 265/448] jp2kdecimator: Fix unitialized variables on macosx --- gst/jp2kdecimator/jp2kcodestream.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/gst/jp2kdecimator/jp2kcodestream.c b/gst/jp2kdecimator/jp2kcodestream.c index e5c67e0d83..6fb28788e7 100644 --- a/gst/jp2kdecimator/jp2kcodestream.c +++ b/gst/jp2kdecimator/jp2kcodestream.c @@ -839,8 +839,8 @@ parse_packet (GstJP2kDecimator * self, GstByteReader * reader, const MainHeader * header, Tile * tile, const PacketIterator * it) { GstFlowReturn ret = GST_FLOW_OK; - guint16 marker, length; - guint16 seqno; + guint16 marker = 0, length; + guint16 seqno = 0; guint packet_start_pos; const guint8 *packet_start_data; gboolean sop, eph; @@ -1031,7 +1031,7 @@ parse_tile (GstJP2kDecimator * self, GstByteReader * reader, const MainHeader * header, Tile * tile) { GstFlowReturn ret = GST_FLOW_OK; - guint16 marker, length; + guint16 marker = 0, length; if (!gst_byte_reader_peek_uint16_be (reader, &marker)) { GST_ERROR_OBJECT (self, "Could not read marker"); @@ -1425,7 +1425,7 @@ parse_main_header (GstJP2kDecimator * self, GstByteReader * reader, MainHeader * header) { GstFlowReturn ret = GST_FLOW_OK; - guint16 marker, length; + guint16 marker = 0, length = 0; /* First SOC */ if (!gst_byte_reader_get_uint16_be (reader, &marker) From 6b9e2628b70796d68164905ab3ffe9410be540a1 Mon Sep 17 00:00:00 2001 From: Edward Hervey Date: Thu, 6 Jan 2011 12:51:27 +0100 Subject: [PATCH 266/448] jpegparse: Fix unitialized variable on macosx --- gst/jpegformat/gstjpegparse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst/jpegformat/gstjpegparse.c b/gst/jpegformat/gstjpegparse.c index 5c54776a02..ca9ac1f2fa 100644 --- a/gst/jpegformat/gstjpegparse.c +++ b/gst/jpegformat/gstjpegparse.c @@ -515,7 +515,7 @@ static inline gboolean gst_jpeg_parse_skip_marker (GstJpegParse * parse, GstByteReader * reader, guint8 marker) { - guint16 size; + guint16 size = 0; if (!gst_byte_reader_get_uint16_be (reader, &size)) return FALSE; From 89fed534e8ee3791d7d961a5a86341bec941bf8c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Fri, 7 Jan 2011 02:10:33 +0000 Subject: [PATCH 267/448] mpegtsdemux: fix PAT and PMT info-related object leaks --- gst/mpegdemux/flutspmtinfo.c | 1 + gst/mpegdemux/gstmpegtsdemux.c | 1 + 2 files changed, 2 insertions(+) diff --git a/gst/mpegdemux/flutspmtinfo.c b/gst/mpegdemux/flutspmtinfo.c index 4c6412eaa5..65402e738d 100644 --- a/gst/mpegdemux/flutspmtinfo.c +++ b/gst/mpegdemux/flutspmtinfo.c @@ -219,4 +219,5 @@ mpegts_pmt_info_add_stream (MpegTsPmtInfo * pmt_info, g_value_init (&v, G_TYPE_OBJECT); g_value_take_object (&v, stream); g_value_array_append (pmt_info->streams, &v); + g_value_unset (&v); } diff --git a/gst/mpegdemux/gstmpegtsdemux.c b/gst/mpegdemux/gstmpegtsdemux.c index 4f116e4d5c..cb0d89c912 100644 --- a/gst/mpegdemux/gstmpegtsdemux.c +++ b/gst/mpegdemux/gstmpegtsdemux.c @@ -3137,6 +3137,7 @@ mpegts_demux_build_pat_info (GstMpegTSDemux * demux) g_value_init (&v, G_TYPE_OBJECT); g_value_take_object (&v, info_obj); g_value_array_append (vals, &v); + g_value_unset (&v); } return vals; } From 60f748575b3ce929fc1a686e5fd8b994e184b296 Mon Sep 17 00:00:00 2001 From: Stefan Kost Date: Fri, 7 Jan 2011 15:22:07 +0200 Subject: [PATCH 268/448] signalprocessor: don't leak the caps --- gst-libs/gst/signalprocessor/gstsignalprocessor.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gst-libs/gst/signalprocessor/gstsignalprocessor.c b/gst-libs/gst/signalprocessor/gstsignalprocessor.c index 45a4dd21a3..2cd33a42ec 100644 --- a/gst-libs/gst/signalprocessor/gstsignalprocessor.c +++ b/gst-libs/gst/signalprocessor/gstsignalprocessor.c @@ -115,6 +115,8 @@ gst_signal_processor_class_add_pad_template (GstSignalProcessorClass * klass, "name", name, "name-template", name, "direction", direction, "presence", GST_PAD_ALWAYS, "caps", caps, NULL); + gst_caps_unref (caps); + GST_SIGNAL_PROCESSOR_PAD_TEMPLATE (new)->index = index; GST_SIGNAL_PROCESSOR_PAD_TEMPLATE (new)->channels = channels; From d03c175f6a9d9ee61a99478e724ba02b88b79b28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Fri, 7 Jan 2011 14:51:46 +0000 Subject: [PATCH 269/448] configure: use $LIBM instead of hard-coding -lm --- configure.ac | 42 +++++++++++++++++++++--------------------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/configure.ac b/configure.ac index 31b09ed66a..0e513552aa 100644 --- a/configure.ac +++ b/configure.ac @@ -689,11 +689,11 @@ dnl *** DTS *** translit(dnm, m, l) AM_CONDITIONAL(USE_DTS, true) AG_GST_CHECK_FEATURE(DTS, [dts library], dtsdec, [ HAVE_DTS="yes" - AG_GST_CHECK_LIBHEADER(DTS, dca, dca_init, -lm, dca.h, - DTS_LIBS="-ldca -lm", HAVE_DTS="no") + AG_GST_CHECK_LIBHEADER(DTS, dca, dca_init, $LIBM, dca.h, + DTS_LIBS="-ldca $LIBM", HAVE_DTS="no") if test $HAVE_DTS = "no"; then - AG_GST_CHECK_LIBHEADER(DTS, dts_pic, dts_init, -lm, dts.h, - [ DTS_LIBS="-ldts_pic -lm" + AG_GST_CHECK_LIBHEADER(DTS, dts_pic, dts_init, $LIBM, dts.h, + [ DTS_LIBS="-ldts_pic $LIBM" AC_DEFINE(DTS_OLD, 1, [Define if an old libdts is used]) ]) fi @@ -750,7 +750,7 @@ return 0; AC_MSG_WARN([Wrong version of divx4linux installed]) ]) fi - LIBS="-lm" + LIBS="$LIBM" if test x$HAVE_DIVX = xyes; then AC_CHECK_LIB(divxencore, encore, , [ AC_MSG_WARN([Divx4linux encore libs not found]) @@ -764,8 +764,8 @@ return 0; ]) fi if test x$HAVE_DIVX = xyes; then - DIVXENC_LIBS="-ldivxencore -lm" - DIVXDEC_LIBS="-ldivxdecore -lm" + DIVXENC_LIBS="-ldivxencore $LIBM" + DIVXDEC_LIBS="-ldivxdecore $LIBM" AC_SUBST(DIVXENC_LIBS) AC_SUBST(DIVXDEC_LIBS) fi @@ -792,8 +792,8 @@ AG_GST_CHECK_FEATURE(EXIF, [exif], exif, [ dnl **** Free AAC Encoder (FAAC) **** translit(dnm, m, l) AM_CONDITIONAL(USE_FAAC, true) AG_GST_CHECK_FEATURE(FAAC, [AAC encoder plug-in], faac, [ - AG_GST_CHECK_LIBHEADER(FAAC, faac, faacEncOpen, -lm, faac.h, - FAAC_LIBS="-lfaac -lm") + AG_GST_CHECK_LIBHEADER(FAAC, faac, faacEncOpen, $LIBM, faac.h, + FAAC_LIBS="-lfaac $LIBM") AS_SCRUB_INCLUDE(FAAC_CFLAGS) AC_SUBST(FAAC_LIBS) ]) @@ -803,11 +803,11 @@ translit(dnm, m, l) AM_CONDITIONAL(USE_FAAD, true) AG_GST_CHECK_FEATURE(FAAD, [AAC decoder plug-in], faad, [ HAVE_FAAD="yes" faad_hdr="" - AG_GST_CHECK_LIBHEADER(FAAD, faad, faacDecOpen, -lm, faad.h, - FAAD_LIBS="-lfaad -lm", HAVE_FAAD="no") + AG_GST_CHECK_LIBHEADER(FAAD, faad, faacDecOpen, $LIBM, faad.h, + FAAD_LIBS="-lfaad $LIBM", HAVE_FAAD="no") if test $HAVE_FAAD = "no"; then - AG_GST_CHECK_LIBHEADER(FAAD, faad, NeAACDecOpen, -lm, neaacdec.h, - [ FAAD_LIBS="-lfaad -lm" + AG_GST_CHECK_LIBHEADER(FAAD, faad, NeAACDecOpen, $LIBM, neaacdec.h, + [ FAAD_LIBS="-lfaad $LIBM" AC_DEFINE(FAAD_IS_NEAAC, 1, [Define if AAC is using new api prefix]) faad_hdr="neaacdec.h" ], [ @@ -868,8 +868,8 @@ AG_GST_CHECK_FEATURE(FBDEV, [linux framebuffer], fbdevsink, [ dnl *** flite *** translit(dnm, m, l) AM_CONDITIONAL(USE_FLITE, true) AG_GST_CHECK_FEATURE(FLITE, [Flite plugin], flite, [ - AG_GST_CHECK_LIBHEADER(FLITE, flite, flite_init, -lm, flite/flite.h, - FLITE_LIBS="-lflite -lflite_cmu_us_kal -lflite_usenglish -lflite_cmulex -lm") + AG_GST_CHECK_LIBHEADER(FLITE, flite, flite_init, $LIBM, flite/flite.h, + FLITE_LIBS="-lflite -lflite_cmu_us_kal -lflite_usenglish -lflite_cmulex $LIBM") AC_SUBST(FLITE_CFLAGS) AC_SUBST(FLITE_LIBS) @@ -991,7 +991,7 @@ PKG_CHECK_EXISTS(mjpegtools >= 1.6.1.93 mjpegtools < 1.8.0, [ OLD_CFLAGS="$CFLAGS" OLD_LIBS="$LIBS" CFLAGS="$MJPEG_CFLAGS" - LIBS="$LIBS $MJPEG_LIBS -lmjpegutils -lm -lpthread" + LIBS="$LIBS $MJPEG_LIBS -lmjpegutils $LIBM -lpthread" AC_CHECK_FUNC(mjpeg_loglev_t, [ mjpegtools_api=10903 ], [ @@ -1028,7 +1028,7 @@ AG_GST_CHECK_FEATURE(MPEG2ENC, [mpeg2enc], mpeg2enc, [ dnl check headers mpeg2enc_headers_ok=no AC_CHECK_HEADER([mpeg2encoder.hh], [ - MPEG2ENC_LIBS="$MPEG2ENC_LIBS -lmpeg2encpp -lm -lpthread" + MPEG2ENC_LIBS="$MPEG2ENC_LIBS -lmpeg2encpp $LIBM -lpthread" OLD_LIBS="$LIBS" LIBS="$LIBS $MPEG2ENC_LIBS" AC_MSG_CHECKING([for valid mpeg2enc objects]) @@ -1096,7 +1096,7 @@ AG_GST_CHECK_FEATURE(MPLEX, [mplex], mplex, [ OLD_CPPFLAGS="$CPPFLAGS" CPPFLAGS="$CPPFLAGS $MPLEX_CFLAGS" AC_CHECK_HEADER(interact.hpp, [ - MPLEX_LIBS="$MPLEX_LIBS -lmplex2 -lm" + MPLEX_LIBS="$MPLEX_LIBS -lmplex2 $LIBM" OLD_LIBS="$LIBS" LIBS="$LIBS $MPLEX_LIBS" OLD_LDFLAGS="$LDFLAGS" @@ -1427,7 +1427,7 @@ AG_GST_CHECK_FEATURE(XVID, [xvid plugins], xvid, [ HAVE_XVID=no AC_CHECK_HEADER(xvid.h, [ OLD_LIBS="$LIBS" - LIBS="-lpthread -lm" + LIBS="-lpthread $LIBM" AC_CHECK_LIB(xvidcore, xvid_encore, [ AC_CHECK_LIB(xvidcore, xvid_decore, [ AC_CHECK_LIB(xvidcore, xvid_global, [ @@ -1437,7 +1437,7 @@ AG_GST_CHECK_FEATURE(XVID, [xvid plugins], xvid, [ #error "Incompatible XviD API version" #endif ],[ AC_MSG_RESULT(yes) - XVID_LIBS="-lxvidcore -lm" + XVID_LIBS="-lxvidcore $LIBM" AC_SUBST(XVID_LIBS) HAVE_XVID=yes ], AC_MSG_RESULT(no) ) @@ -1544,7 +1544,7 @@ AG_GST_CHECK_FEATURE(VP8, [VP8 decoder], vp8, [ HAVE_VP8_DECODER=no OLD_LIBS="$LIBS" - LIBS="$LIBS -lm -lpthread" + LIBS="$LIBS $LIBM -lpthread" AC_CHECK_LIB(vpx, vpx_codec_vp8_cx_algo, [ HAVE_VP8=yes AC_DEFINE(HAVE_VP8_ENCODER, 1, [Defined if the VP8 encoder is available]) From 2aa584c9158ec3d4268ab96e6e182b2b2395f4b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Fri, 7 Jan 2011 15:47:39 +0000 Subject: [PATCH 270/448] configure: fix --disable-external --- configure.ac | 1 + 1 file changed, 1 insertion(+) diff --git a/configure.ac b/configure.ac index 0e513552aa..3006212005 100644 --- a/configure.ac +++ b/configure.ac @@ -1615,6 +1615,7 @@ AM_CONDITIONAL(USE_MYTHTV, false) AM_CONDITIONAL(USE_NAS, false) AM_CONDITIONAL(USE_NEON, false) AM_CONDITIONAL(USE_OFA, false) +AM_CONDITIONAL(USE_OPENCV, false) AM_CONDITIONAL(USE_RSVG, false) AM_CONDITIONAL(USE_TIMIDITY, false) AM_CONDITIONAL(USE_WILDMIDI, false) From e5f1cdd0e9362c14784c4e1e8c762623537af4c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Fri, 7 Jan 2011 18:49:02 +0000 Subject: [PATCH 271/448] Revert "mpegvideoparse: fix timestamp generation" This reverts commit 2271608c4314d6d0a685c18c5c47d55495586159. This patch needs more work so it doesn't cause grave playback regressions (multi-second freezes) with some files that have slightly broken timestamps but play fine everywhere else. https://bugzilla.gnome.org/show_bug.cgi?id=636279 https://bugzilla.gnome.org/show_bug.cgi?id=632222 --- gst/mpegvideoparse/mpegpacketiser.c | 2 - gst/mpegvideoparse/mpegpacketiser.h | 1 - gst/mpegvideoparse/mpegvideoparse.c | 78 +++-------------------------- gst/mpegvideoparse/mpegvideoparse.h | 5 -- 4 files changed, 7 insertions(+), 79 deletions(-) diff --git a/gst/mpegvideoparse/mpegpacketiser.c b/gst/mpegvideoparse/mpegpacketiser.c index b3be15acd9..694c4761d1 100644 --- a/gst/mpegvideoparse/mpegpacketiser.c +++ b/gst/mpegvideoparse/mpegpacketiser.c @@ -636,9 +636,7 @@ mpeg_util_parse_picture_hdr (MPEGPictureHdr * hdr, guint8 * data, guint8 * end) /* Skip the start code */ data += 4; - hdr->temp_ref = (data[0] << 2) | (data[1] >> 6); hdr->pic_type = (data[1] >> 3) & 0x07; - if (hdr->pic_type == 0 || hdr->pic_type > 4) return FALSE; /* Corrupted picture packet */ diff --git a/gst/mpegvideoparse/mpegpacketiser.h b/gst/mpegvideoparse/mpegpacketiser.h index d82018e08a..88b1ca58a9 100644 --- a/gst/mpegvideoparse/mpegpacketiser.h +++ b/gst/mpegvideoparse/mpegpacketiser.h @@ -86,7 +86,6 @@ struct MPEGSeqHdr struct MPEGPictureHdr { - guint16 temp_ref; guint8 pic_type; }; diff --git a/gst/mpegvideoparse/mpegvideoparse.c b/gst/mpegvideoparse/mpegvideoparse.c index 6bff3733bc..70fdc89af3 100644 --- a/gst/mpegvideoparse/mpegvideoparse.c +++ b/gst/mpegvideoparse/mpegvideoparse.c @@ -92,10 +92,6 @@ gst_mpegvideoparse_change_state (GstElement * element, static void mpv_send_pending_segs (MpegVideoParse * mpegvideoparse); static void mpv_clear_pending_segs (MpegVideoParse * mpegvideoparse); -static GstClockTime mpegvideoparse_get_timestamp_from_reference (MPEGSeqHdr * - seq_hdr, GstClockTime ref_ts, gint32 ref); -static GstClockTime mpegvideoparse_get_time_code (guint8 * cur, - MPEGSeqHdr * seq_hdr); static GstElementClass *parent_class = NULL; @@ -167,9 +163,6 @@ mpv_parse_reset (MpegVideoParse * mpegvideoparse) mpegvideoparse->seq_hdr.fps_n = mpegvideoparse->seq_hdr.par_w = 0; mpegvideoparse->seq_hdr.fps_d = mpegvideoparse->seq_hdr.par_h = 1; - mpegvideoparse->ref_ts = GST_CLOCK_TIME_NONE; - mpegvideoparse->base_time_code = GST_CLOCK_TIME_NONE; - mpv_clear_pending_segs (mpegvideoparse); } @@ -411,30 +404,6 @@ picture_type_name (guint8 pct) } #endif /* GST_DISABLE_GST_DEBUG */ -static GstClockTime -mpegvideoparse_get_timestamp_from_reference (MPEGSeqHdr * seq_hdr, - GstClockTime ref_ts, gint32 ref) -{ - - if (ref < 0) { - GstClockTime duration; - - duration = gst_util_uint64_scale_int (ref * GST_SECOND * -1, - seq_hdr->fps_d, seq_hdr->fps_n); - - if (duration > ref_ts) - return ref_ts; - else - return ref_ts - duration; - } - - if (ref == 0) - return ref_ts; - - return ref_ts + gst_util_uint64_scale_int (ref * GST_SECOND, - seq_hdr->fps_d, seq_hdr->fps_n); -} - static gboolean mpegvideoparse_handle_picture (MpegVideoParse * mpegvideoparse, GstBuffer * buf) { @@ -463,43 +432,8 @@ mpegvideoparse_handle_picture (MpegVideoParse * mpegvideoparse, GstBuffer * buf) GST_LOG_OBJECT (mpegvideoparse, "Picture type is %s", picture_type_name (hdr.pic_type)); - - if (GST_BUFFER_TIMESTAMP (buf) == GST_CLOCK_TIME_NONE) { - if (mpegvideoparse->ref_ts != GST_CLOCK_TIME_NONE) { - GST_BUFFER_TIMESTAMP (buf) = - mpegvideoparse_get_timestamp_from_reference - (&mpegvideoparse->seq_hdr, mpegvideoparse->ref_ts, - hdr.temp_ref - mpegvideoparse->temp_ref); - } - } else { - /* we got a timestamp from upstream, use this timestamp as our reference now */ - mpegvideoparse->ref_ts = GST_BUFFER_TIMESTAMP (buf); - mpegvideoparse->temp_ref = hdr.temp_ref; - } - - GST_DEBUG_OBJECT (mpegvideoparse, - "Picture timestamp %" GST_TIME_FORMAT, - GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf))); - } else if (cur[0] == MPEG_PACKET_GOP) { - if (GST_BUFFER_TIMESTAMP (buf) != GST_CLOCK_TIME_NONE) { - mpegvideoparse->base_time_code = - mpegvideoparse_get_time_code (cur, - &mpegvideoparse->seq_hdr) - GST_BUFFER_TIMESTAMP (buf); - mpegvideoparse->ref_ts = GST_BUFFER_TIMESTAMP (buf); - mpegvideoparse->temp_ref = 0; - } else { - if (mpegvideoparse->base_time_code == GST_CLOCK_TIME_NONE) { - mpegvideoparse->base_time_code = - mpegvideoparse_get_time_code (cur, &mpegvideoparse->seq_hdr); - mpegvideoparse->ref_ts = 0; - mpegvideoparse->temp_ref = 0; - } else { - mpegvideoparse->ref_ts = - mpegvideoparse_get_time_code (cur, - &mpegvideoparse->seq_hdr) - mpegvideoparse->base_time_code; - mpegvideoparse->temp_ref = 0; - } - } + /* FIXME: Can use the picture type and number of fields to track a + * timestamp */ } cur = mpeg_util_find_start_code (&sync_word, cur, end); } @@ -507,10 +441,11 @@ mpegvideoparse_handle_picture (MpegVideoParse * mpegvideoparse, GstBuffer * buf) return TRUE; } -static GstClockTime -mpegvideoparse_get_time_code (guint8 * cur, MPEGSeqHdr * seq_hdr) +#if 0 +static guint64 +gst_mpegvideoparse_time_code (guchar * gop, MPEGSeqHdr * seq_hdr) { - guint32 data = GST_READ_UINT32_BE (cur + 1); + guint32 data = GST_READ_UINT32_BE (gop); guint64 seconds; guint8 frames; @@ -523,6 +458,7 @@ mpegvideoparse_get_time_code (guint8 * cur, MPEGSeqHdr * seq_hdr) return seconds * GST_SECOND + gst_util_uint64_scale_int (frames * GST_SECOND, seq_hdr->fps_d, seq_hdr->fps_n); } +#endif static void gst_mpegvideoparse_flush (MpegVideoParse * mpegvideoparse) diff --git a/gst/mpegvideoparse/mpegvideoparse.h b/gst/mpegvideoparse/mpegvideoparse.h index fa5cfd46ab..b514863ff6 100644 --- a/gst/mpegvideoparse/mpegvideoparse.h +++ b/gst/mpegvideoparse/mpegvideoparse.h @@ -49,11 +49,6 @@ struct _MpegVideoParse { gint64 next_offset; gboolean need_discont; - /* Timestamp calculation */ - GstClockTime ref_ts; - guint16 temp_ref; - GstClockTime base_time_code; - /* Info from the Sequence Header */ MPEGSeqHdr seq_hdr; GstBuffer *seq_hdr_buf; From 1498cbcc2d7f85740d33e45dcea9e3adb4b1c120 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Fri, 7 Jan 2011 23:57:21 +0000 Subject: [PATCH 272/448] xvidenc: don't put code with side effects into g_return_val_if_fail() And don't use g_return*_if_fail() for error handling in elements. --- ext/xvid/gstxvidenc.c | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/ext/xvid/gstxvidenc.c b/ext/xvid/gstxvidenc.c index 1194ecbbce..6d16e87bda 100644 --- a/ext/xvid/gstxvidenc.c +++ b/ext/xvid/gstxvidenc.c @@ -714,11 +714,17 @@ gst_xvidenc_setcaps (GstPad * pad, GstCaps * vscaps) structure = gst_caps_get_structure (vscaps, 0); - g_return_val_if_fail (gst_structure_get_int (structure, "width", &w), FALSE); - g_return_val_if_fail (gst_structure_get_int (structure, "height", &h), FALSE); + if (!gst_structure_get_int (structure, "width", &w) || + !gst_structure_get_int (structure, "height", &h)) { + return FALSE; + } + fps = gst_structure_get_value (structure, "framerate"); - g_return_val_if_fail (w > 0 && h > 0 - && fps != NULL && GST_VALUE_HOLDS_FRACTION (fps), FALSE); + if (fps == NULL || !GST_VALUE_HOLDS_FRACTION (fps)) { + GST_WARNING_OBJECT (pad, "no framerate specified, or not a GstFraction"); + return FALSE; + } + /* optional par info */ par = gst_structure_get_value (structure, "pixel-aspect-ratio"); @@ -1039,7 +1045,6 @@ gst_xvidenc_set_property (GObject * object, GstXvidEnc *xvidenc; guint offset; - g_return_if_fail (GST_IS_XVIDENC (object)); xvidenc = GST_XVIDENC (object); if (prop_id > xvidenc_prop_count) { @@ -1050,7 +1055,9 @@ gst_xvidenc_set_property (GObject * object, /* our param specs should have such qdata */ offset = GPOINTER_TO_UINT (g_param_spec_get_qdata (pspec, xvidenc_pspec_quark)); - g_return_if_fail (offset != 0); + + if (offset == 0) + return; switch (G_PARAM_SPEC_VALUE_TYPE (pspec)) { case G_TYPE_BOOLEAN: @@ -1080,7 +1087,6 @@ gst_xvidenc_get_property (GObject * object, GstXvidEnc *xvidenc; guint offset; - g_return_if_fail (GST_IS_XVIDENC (object)); xvidenc = GST_XVIDENC (object); if (prop_id > xvidenc_prop_count) { @@ -1091,7 +1097,9 @@ gst_xvidenc_get_property (GObject * object, /* our param specs should have such qdata */ offset = GPOINTER_TO_UINT (g_param_spec_get_qdata (pspec, xvidenc_pspec_quark)); - g_return_if_fail (offset != 0); + + if (offset == 0) + return; switch (G_PARAM_SPEC_VALUE_TYPE (pspec)) { case G_TYPE_BOOLEAN: From 3145eac5771e62084000d9585b6ccddf258b2186 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Sat, 8 Jan 2011 00:01:01 +0000 Subject: [PATCH 273/448] directfb: don't put code with side-effects into g_assert() It will all be turned into a NOOP if -DG_DISABLE_ASSERT is used (as it is for pre-releases and releases). --- ext/directfb/dfb-example.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ext/directfb/dfb-example.c b/ext/directfb/dfb-example.c index 17dbce3b10..59bbd4a6ff 100644 --- a/ext/directfb/dfb-example.c +++ b/ext/directfb/dfb-example.c @@ -57,7 +57,8 @@ main (int argc, char *argv[]) /* Adding elements to the pipeline */ gst_bin_add_many (GST_BIN (pipeline), src, sink, NULL); - g_assert (gst_element_link (src, sink)); + if (!gst_element_link (src, sink)) + g_error ("Couldn't link videotestsrc and dfbvideosink"); /* Let's play ! */ gst_element_set_state (pipeline, GST_STATE_PLAYING); From a0449837456f12359267de4e653d9764e521db9e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Sat, 8 Jan 2011 00:08:11 +0000 Subject: [PATCH 274/448] tests: never disable g_assert() and cast checks for the unit tests The unit tests are riddled with g_assert() and friends, make sure we don't disable assert and cast checks for the unit tests even if this has been specified for the rest of the code base, e.g. via --disable-glib-asserts. --- tests/check/Makefile.am | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/tests/check/Makefile.am b/tests/check/Makefile.am index fc2e25f96e..31d41b4aa8 100644 --- a/tests/check/Makefile.am +++ b/tests/check/Makefile.am @@ -181,13 +181,14 @@ noinst_HEADERS = elements/mxfdemux.h TESTS = $(check_PROGRAMS) AM_CFLAGS = $(GST_CHECK_CFLAGS) $(GST_OPTION_CFLAGS) \ - -DGST_TEST_FILES_PATH="\"$(TEST_FILES_DIRECTORY)\"" + -DGST_TEST_FILES_PATH="\"$(TEST_FILES_DIRECTORY)\"" \ + -UG_DISABLE_ASSERT -UG_DISABLE_CAST_CHECKS LDADD = $(GST_CHECK_LIBS) elements_camerabin_CFLAGS = \ -I$(top_builddir)/gst-libs \ $(GST_CFLAGS) $(GST_BASE_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) \ - $(GST_PLUGINS_BAD_CFLAGS) $(GST_CHECK_CFLAGS) \ + $(GST_PLUGINS_BAD_CFLAGS) $(GST_CHECK_CFLAGS) $(AM_CFLAGS) \ -DGST_USE_UNSTABLE_API elements_camerabin_LDADD = \ $(top_builddir)/gst-libs/gst/interfaces/libgstphotography-@GST_MAJORMINOR@.la \ @@ -200,7 +201,7 @@ if BUILD_EXPERIMENTAL elements_camerabin2_CFLAGS = \ -I$(top_builddir)/gst-libs \ $(GST_CFLAGS) $(GST_BASE_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) \ - $(GST_PLUGINS_BAD_CFLAGS) $(GST_CHECK_CFLAGS) \ + $(GST_PLUGINS_BAD_CFLAGS) $(GST_CHECK_CFLAGS) $(AM_CFLAGS) \ -DGST_USE_UNSTABLE_API elements_camerabin2_LDADD = \ $(top_builddir)/gst-libs/gst/interfaces/libgstphotography-@GST_MAJORMINOR@.la \ @@ -212,7 +213,7 @@ elements_camerabin2_SOURCES = elements/camerabin2.c elements_imagecapturebin_CFLAGS = \ -I$(top_builddir)/gst-libs \ $(GST_CFLAGS) $(GST_BASE_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) \ - $(GST_CHECK_CFLAGS) \ + $(GST_CHECK_CFLAGS) $(AM_CFLAGS) \ -DGST_USE_UNSTABLE_API elements_imagecapturebin_LDADD = \ $(GST_LIBS) $(GST_BASE_LIBS) $(GST_PLUGINS_BASE_LIBS) \ From 0f48601a35d43344e0dc8fbc5d2e8746cd36eaa9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Sat, 8 Jan 2011 00:17:26 +0000 Subject: [PATCH 275/448] tests: fix CFLAGS and LIBADD order in Makefile.am --- tests/check/Makefile.am | 44 +++++++++++++++++++---------------------- 1 file changed, 20 insertions(+), 24 deletions(-) diff --git a/tests/check/Makefile.am b/tests/check/Makefile.am index 31d41b4aa8..8bfd88c335 100644 --- a/tests/check/Makefile.am +++ b/tests/check/Makefile.am @@ -186,43 +186,39 @@ AM_CFLAGS = $(GST_CHECK_CFLAGS) $(GST_OPTION_CFLAGS) \ LDADD = $(GST_CHECK_LIBS) elements_camerabin_CFLAGS = \ - -I$(top_builddir)/gst-libs \ - $(GST_CFLAGS) $(GST_BASE_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) \ - $(GST_PLUGINS_BAD_CFLAGS) $(GST_CHECK_CFLAGS) $(AM_CFLAGS) \ - -DGST_USE_UNSTABLE_API + $(GST_PLUGINS_BAD_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) \ + $(GST_BASE_CFLAGS) $(GST_CHECK_CFLAGS) $(GST_CFLAGS) \ + $(AM_CFLAGS) -DGST_USE_UNSTABLE_API elements_camerabin_LDADD = \ - $(top_builddir)/gst-libs/gst/interfaces/libgstphotography-@GST_MAJORMINOR@.la \ - $(GST_LIBS) $(GST_BASE_LIBS) $(GST_PLUGINS_BASE_LIBS) \ - $(GST_CHECK_LIBS) \ - -lgstinterfaces-@GST_MAJORMINOR@ + $(top_builddir)/gst-libs/gst/interfaces/libgstphotography-@GST_MAJORMINOR@.la \ + $(GST_PLUGINS_BASE_LIBS) -lgstinterfaces-@GST_MAJORMINOR@ \ + $(GST_BASE_LIBS) $(GST_CHECK_LIBS) $(GST_LIBS) + elements_camerabin_SOURCES = elements/camerabin.c if BUILD_EXPERIMENTAL elements_camerabin2_CFLAGS = \ - -I$(top_builddir)/gst-libs \ - $(GST_CFLAGS) $(GST_BASE_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) \ - $(GST_PLUGINS_BAD_CFLAGS) $(GST_CHECK_CFLAGS) $(AM_CFLAGS) \ - -DGST_USE_UNSTABLE_API + $(GST_PLUGINS_BAD_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) \ + $(GST_BASE_CFLAGS) $(GST_CHECK_CFLAGS) $(GST_CFLAGS) \ + $(AM_CFLAGS) -DGST_USE_UNSTABLE_API elements_camerabin2_LDADD = \ $(top_builddir)/gst-libs/gst/interfaces/libgstphotography-@GST_MAJORMINOR@.la \ $(top_builddir)/gst-libs/gst/basecamerabinsrc/libgstbasecamerabinsrc-@GST_MAJORMINOR@.la \ - $(GST_LIBS) $(GST_BASE_LIBS) $(GST_PLUGINS_BASE_LIBS) \ - $(GST_CHECK_LIBS) + $(GST_PLUGINS_BASE_LIBS) $(GST_BASE_LIBS) $(GST_CHECK_LIBS) $(GST_LIBS) elements_camerabin2_SOURCES = elements/camerabin2.c elements_imagecapturebin_CFLAGS = \ - -I$(top_builddir)/gst-libs \ - $(GST_CFLAGS) $(GST_BASE_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) \ - $(GST_CHECK_CFLAGS) $(AM_CFLAGS) \ - -DGST_USE_UNSTABLE_API + $(GST_PLUGINS_BAD_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) \ + $(GST_BASE_CFLAGS) $(GST_CHECK_CFLAGS) $(GST_CFLAGS) \ + $(AM_CFLAGS) -DGST_USE_UNSTABLE_API elements_imagecapturebin_LDADD = \ - $(GST_LIBS) $(GST_BASE_LIBS) $(GST_PLUGINS_BASE_LIBS) \ - $(GST_CHECK_LIBS) -lgstapp-@GST_MAJORMINOR@ + $(GST_PLUGINS_BASE_LIBS) -lgstapp-@GST_MAJORMINOR@ \ + $(GST_BASE_LIBS) $(GST_CHECK_LIBS) $(GST_LIBS) elements_imagecapturebin_SOURCES = elements/imagecapturebin.c endif -elements_jifmux_CFLAGS = $(GST_CHECK_CFLAGS) $(GST_OPTION_CFLAGS) $(AM_CFLAGS) $(EXIF_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) -elements_jifmux_LDADD = $(GST_CHECK_LIBS) $(EXIF_LIBS) $(LDADD) $(GST_PLUGINS_BASE_LIBS) -lgsttag-$(GST_MAJORMINOR) +elements_jifmux_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CHECK_CFLAGS) $(GST_OPTION_CFLAGS) $(AM_CFLAGS) $(EXIF_CFLAGS) +elements_jifmux_LDADD = $(GST_PLUGINS_BASE_LIBS) -lgsttag-$(GST_MAJORMINOR) $(GST_CHECK_LIBS) $(EXIF_LIBS) $(LDADD) elements_jifmux_SOURCES = elements/jifmux.c elements_timidity_CFLAGS = $(GST_BASE_CFLAGS) $(AM_CFLAGS) @@ -232,10 +228,10 @@ elements_kate_CFLAGS = $(GST_BASE_CFLAGS) $(AM_CFLAGS) elements_kate_LDADD = $(GST_BASE_LIBS) $(LDADD) elements_rtpmux_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(AM_CFLAGS) -elements_rtpmux_LDADD = $(GST_BASE_LIBS) $(LDADD) -lgstrtp-0.10 +elements_rtpmux_LDADD = $(GST_PLUGINS_BASE_LIBS) -lgstrtp-0.10 $(GST_BASE_LIBS) $(LDADD) elements_assrender_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(AM_CFLAGS) -elements_assrender_LDADD = $(GST_BASE_LIBS) $(LDADD) -lgstvideo-0.10 -lgstapp-0.10 +elements_assrender_LDADD = $(GST_PLUGINS_BASE_LIBS) -lgstvideo-0.10 -lgstapp-0.10 $(GST_BASE_LIBS) $(LDADD) # parser unit test convenience lib noinst_LTLIBRARIES = libparser.la From 2ba964df4945ae37904ccbc60ee453cbadb2278e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Sat, 8 Jan 2011 00:18:17 +0000 Subject: [PATCH 276/448] tests: make git ignore new schroenc test binary --- tests/check/elements/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/check/elements/.gitignore b/tests/check/elements/.gitignore index 60d4386473..8a748233c3 100644 --- a/tests/check/elements/.gitignore +++ b/tests/check/elements/.gitignore @@ -34,6 +34,7 @@ rganalysis rglimiter rgvolume rtpmux +schroenc spectrum timidity y4menc From f6591e59380bd0346cb96b93c963a4f54a8e997a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Sat, 8 Jan 2011 00:19:06 +0000 Subject: [PATCH 277/448] smoothwave: remove old 0.8 example containing code with sideeffects in g_return_if_fail() May just as well remove it rather than fix it, so it doesn't show up in greps for this any longer. --- gst/smoothwave/demo-osssrc.c | 52 ------------------------------------ 1 file changed, 52 deletions(-) delete mode 100644 gst/smoothwave/demo-osssrc.c diff --git a/gst/smoothwave/demo-osssrc.c b/gst/smoothwave/demo-osssrc.c deleted file mode 100644 index 9c55a3b358..0000000000 --- a/gst/smoothwave/demo-osssrc.c +++ /dev/null @@ -1,52 +0,0 @@ -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif -#include -#include - -extern gboolean _gst_plugin_spew; - -gboolean idle_func (gpointer data); - -GtkWidget *drawingarea; - -int -main (int argc, char *argv[]) -{ - GstElement *bin; - GstElement *src; - GstElement *wave; - GstElement *ximage; - - gst_init (&argc, &argv); - gst_plugin_load ("libsmoothwave.so"); - gtk_init (&argc, &argv); - - bin = gst_pipeline_new ("bin"); - - src = gst_element_factory_make ("sinesrc", "src"); - wave = gst_element_factory_make ("smoothwave", "wave"); - ximage = gst_element_factory_make (DEFAULT_VIDEOSINK, "sink"); - g_return_val_if_fail (src != NULL, -1); - g_return_val_if_fail (wave != NULL, -1); - g_return_val_if_fail (ximage != NULL, -1); - - - gst_bin_add_many (GST_BIN (bin), src, wave, ximage, NULL); - g_return_val_if_fail (gst_element_link_many (src, wave, ximage, - NULL) != FALSE, -1); - - gst_element_set_state (GST_ELEMENT (bin), GST_STATE_PLAYING); - g_idle_add (idle_func, bin); - - gtk_main (); - - return 0; -} - -gboolean -idle_func (gpointer data) -{ - gst_bin_iterate (GST_BIN (data)); - return TRUE; -} From ce83c366fe8ca0dd49803efb3b0084dddb4df113 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Sat, 8 Jan 2011 00:32:21 +0000 Subject: [PATCH 278/448] tests: Makefile.am clean-up Avoid duplicates GST_CHECK_CFLAGS and GST_OPTIONS_CFLAGS are already in AM_CFLAGS. Add LDADD instead of GST_CHECK_LIBS for consistency. --- tests/check/Makefile.am | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/tests/check/Makefile.am b/tests/check/Makefile.am index 8bfd88c335..90c9a7ed52 100644 --- a/tests/check/Makefile.am +++ b/tests/check/Makefile.am @@ -187,37 +187,34 @@ LDADD = $(GST_CHECK_LIBS) elements_camerabin_CFLAGS = \ $(GST_PLUGINS_BAD_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) \ - $(GST_BASE_CFLAGS) $(GST_CHECK_CFLAGS) $(GST_CFLAGS) \ - $(AM_CFLAGS) -DGST_USE_UNSTABLE_API + $(GST_BASE_CFLAGS) $(GST_CFLAGS) $(AM_CFLAGS) -DGST_USE_UNSTABLE_API elements_camerabin_LDADD = \ $(top_builddir)/gst-libs/gst/interfaces/libgstphotography-@GST_MAJORMINOR@.la \ $(GST_PLUGINS_BASE_LIBS) -lgstinterfaces-@GST_MAJORMINOR@ \ - $(GST_BASE_LIBS) $(GST_CHECK_LIBS) $(GST_LIBS) + $(GST_BASE_LIBS) $(GST_LIBS) $(LDADD) elements_camerabin_SOURCES = elements/camerabin.c if BUILD_EXPERIMENTAL elements_camerabin2_CFLAGS = \ $(GST_PLUGINS_BAD_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) \ - $(GST_BASE_CFLAGS) $(GST_CHECK_CFLAGS) $(GST_CFLAGS) \ - $(AM_CFLAGS) -DGST_USE_UNSTABLE_API + $(GST_BASE_CFLAGS) $(GST_CFLAGS) $(AM_CFLAGS) -DGST_USE_UNSTABLE_API elements_camerabin2_LDADD = \ $(top_builddir)/gst-libs/gst/interfaces/libgstphotography-@GST_MAJORMINOR@.la \ $(top_builddir)/gst-libs/gst/basecamerabinsrc/libgstbasecamerabinsrc-@GST_MAJORMINOR@.la \ - $(GST_PLUGINS_BASE_LIBS) $(GST_BASE_LIBS) $(GST_CHECK_LIBS) $(GST_LIBS) + $(GST_PLUGINS_BASE_LIBS) $(GST_BASE_LIBS) $(GST_LIBS) $(LDADD) elements_camerabin2_SOURCES = elements/camerabin2.c elements_imagecapturebin_CFLAGS = \ $(GST_PLUGINS_BAD_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) \ - $(GST_BASE_CFLAGS) $(GST_CHECK_CFLAGS) $(GST_CFLAGS) \ - $(AM_CFLAGS) -DGST_USE_UNSTABLE_API + $(GST_BASE_CFLAGS) $(GST_CFLAGS) $(AM_CFLAGS) -DGST_USE_UNSTABLE_API elements_imagecapturebin_LDADD = \ $(GST_PLUGINS_BASE_LIBS) -lgstapp-@GST_MAJORMINOR@ \ - $(GST_BASE_LIBS) $(GST_CHECK_LIBS) $(GST_LIBS) + $(GST_BASE_LIBS) $(GST_LIBS) $(LDADD) elements_imagecapturebin_SOURCES = elements/imagecapturebin.c endif -elements_jifmux_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CHECK_CFLAGS) $(GST_OPTION_CFLAGS) $(AM_CFLAGS) $(EXIF_CFLAGS) +elements_jifmux_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(EXIF_CFLAGS) $(AM_CFLAGS) elements_jifmux_LDADD = $(GST_PLUGINS_BASE_LIBS) -lgsttag-$(GST_MAJORMINOR) $(GST_CHECK_LIBS) $(EXIF_LIBS) $(LDADD) elements_jifmux_SOURCES = elements/jifmux.c From b700377e22210015cf42cf464651dd163977a9a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Sat, 8 Jan 2011 02:43:41 +0000 Subject: [PATCH 279/448] camerabin: use private input-selector that still has "select-all" property The "select-all" property was removed when input-selector was moved to core, but camerabin uses this, so make camerabin use a private copy until a better fix is found. --- gst/camerabin/Makefile.am | 2 + gst/camerabin/camerabingeneral.c | 13 +- gst/camerabin/gstcamerabin-marshal.list | 2 + gst/camerabin/gstinputselector.c | 1459 +++++++++++++++++++++++ gst/camerabin/gstinputselector.h | 84 ++ 5 files changed, 1558 insertions(+), 2 deletions(-) create mode 100644 gst/camerabin/gstinputselector.c create mode 100644 gst/camerabin/gstinputselector.h diff --git a/gst/camerabin/Makefile.am b/gst/camerabin/Makefile.am index d77dae464a..7d7e55576e 100644 --- a/gst/camerabin/Makefile.am +++ b/gst/camerabin/Makefile.am @@ -16,6 +16,7 @@ plugin_LTLIBRARIES = libgstcamerabin.la libgstcamerabin_la_SOURCES = gstcamerabin.c \ gstcamerabincolorbalance.c \ + gstinputselector.c \ camerabinimage.c \ camerabinvideo.c \ camerabingeneral.c \ @@ -37,6 +38,7 @@ libgstcamerabin_la_LIBTOOLFLAGS = --tag=disable-static noinst_HEADERS = gstcamerabin.h \ gstcamerabincolorbalance.h \ + gstinputselector.h \ camerabinimage.h \ camerabinvideo.h \ camerabindebug.h \ diff --git a/gst/camerabin/camerabingeneral.c b/gst/camerabin/camerabingeneral.c index f1cf35da02..b82b22cfc9 100644 --- a/gst/camerabin/camerabingeneral.c +++ b/gst/camerabin/camerabingeneral.c @@ -27,9 +27,10 @@ * */ #include +#include #include "camerabingeneral.h" -#include +#include "gstinputselector.h" GST_DEBUG_CATEGORY (gst_camerabin_debug); @@ -128,7 +129,15 @@ gst_camerabin_create_and_add_element (GstBin * bin, const gchar * elem_name) g_return_val_if_fail (bin, FALSE); g_return_val_if_fail (elem_name, FALSE); - new_elem = gst_element_factory_make (elem_name, NULL); + if (strcmp (elem_name, "input-selector") == 0) { + /* we ship our own copy of input-selector because we still use the + * "select-all" property which was removed when input-selector was + * moved to core */ + new_elem = g_object_new (GST_TYPE_INPUT_SELECTOR, NULL); + } else { + new_elem = gst_element_factory_make (elem_name, NULL); + } + if (!new_elem) { GST_ELEMENT_ERROR (bin, CORE, MISSING_PLUGIN, (NULL), ("could not create \"%s\" element.", elem_name)); diff --git a/gst/camerabin/gstcamerabin-marshal.list b/gst/camerabin/gstcamerabin-marshal.list index 40829e5452..6bc959adbd 100644 --- a/gst/camerabin/gstcamerabin-marshal.list +++ b/gst/camerabin/gstcamerabin-marshal.list @@ -4,3 +4,5 @@ VOID:INT,INT,INT,INT VOID:INT,INT BOOLEAN:STRING +INT64:VOID +VOID:OBJECT,INT64,INT64 diff --git a/gst/camerabin/gstinputselector.c b/gst/camerabin/gstinputselector.c new file mode 100644 index 0000000000..75ecab1d21 --- /dev/null +++ b/gst/camerabin/gstinputselector.c @@ -0,0 +1,1459 @@ +/* GStreamer + * Copyright (C) 2003 Julien Moutte + * Copyright (C) 2005 Ronald S. Bultje + * Copyright (C) 2005 Jan Schmidt + * Copyright (C) 2007 Wim Taymans + * Copyright (C) 2007 Andy Wingo + * Copyright (C) 2008 Nokia Corporation. (contact ) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/** + * SECTION:element-input-selector + * @see_also: #GstOutputSelector + * + * Direct one out of N input streams to the output pad. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "gstinputselector.h" +#include "gstcamerabin-marshal.h" + +GST_DEBUG_CATEGORY_STATIC (input_selector_debug); +#define GST_CAT_DEFAULT input_selector_debug + +static GstStaticPadTemplate gst_input_selector_sink_factory = +GST_STATIC_PAD_TEMPLATE ("sink%d", + GST_PAD_SINK, + GST_PAD_REQUEST, + GST_STATIC_CAPS_ANY); + +static GstStaticPadTemplate gst_input_selector_src_factory = +GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS_ANY); + +enum +{ + PROP_0, + PROP_N_PADS, + PROP_ACTIVE_PAD, + PROP_SELECT_ALL, + PROP_LAST +}; + +#define DEFAULT_PAD_ALWAYS_OK TRUE + +enum +{ + PROP_PAD_0, + PROP_PAD_RUNNING_TIME, + PROP_PAD_TAGS, + PROP_PAD_ACTIVE, + PROP_PAD_ALWAYS_OK, + PROP_PAD_LAST +}; + +enum +{ + /* methods */ + SIGNAL_BLOCK, + SIGNAL_SWITCH, + LAST_SIGNAL +}; +static guint gst_input_selector_signals[LAST_SIGNAL] = { 0 }; + +static inline gboolean gst_input_selector_is_active_sinkpad (GstInputSelector * + sel, GstPad * pad); +static GstPad *gst_input_selector_activate_sinkpad (GstInputSelector * sel, + GstPad * pad); +static GstPad *gst_input_selector_get_linked_pad (GstPad * pad, + gboolean strict); +static gboolean gst_input_selector_check_eos (GstElement * selector); + +#define GST_TYPE_SELECTOR_PAD \ + (gst_selector_pad_get_type()) +#define GST_SELECTOR_PAD(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_SELECTOR_PAD, GstSelectorPad)) +#define GST_SELECTOR_PAD_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_SELECTOR_PAD, GstSelectorPadClass)) +#define GST_IS_SELECTOR_PAD(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_SELECTOR_PAD)) +#define GST_IS_SELECTOR_PAD_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_SELECTOR_PAD)) +#define GST_SELECTOR_PAD_CAST(obj) \ + ((GstSelectorPad *)(obj)) + +typedef struct _GstSelectorPad GstSelectorPad; +typedef struct _GstSelectorPadClass GstSelectorPadClass; + +struct _GstSelectorPad +{ + GstPad parent; + + gboolean active; /* when buffer have passed the pad */ + gboolean eos; /* when EOS has been received */ + gboolean discont; /* after switching we create a discont */ + gboolean always_ok; + GstSegment segment; /* the current segment on the pad */ + GstTagList *tags; /* last tags received on the pad */ + + gboolean segment_pending; +}; + +struct _GstSelectorPadClass +{ + GstPadClass parent; +}; + +static void gst_selector_pad_class_init (GstSelectorPadClass * klass); +static void gst_selector_pad_init (GstSelectorPad * pad); +static void gst_selector_pad_finalize (GObject * object); +static void gst_selector_pad_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec); +static void gst_selector_pad_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec); + +static GstPadClass *selector_pad_parent_class = NULL; + +static gint64 gst_selector_pad_get_running_time (GstSelectorPad * pad); +static void gst_selector_pad_reset (GstSelectorPad * pad); +static gboolean gst_selector_pad_event (GstPad * pad, GstEvent * event); +static GstCaps *gst_selector_pad_getcaps (GstPad * pad); +static gboolean gst_selector_pad_acceptcaps (GstPad * pad, GstCaps * caps); +static GstIterator *gst_selector_pad_iterate_linked_pads (GstPad * pad); +static GstFlowReturn gst_selector_pad_chain (GstPad * pad, GstBuffer * buf); +static GstFlowReturn gst_selector_pad_bufferalloc (GstPad * pad, + guint64 offset, guint size, GstCaps * caps, GstBuffer ** buf); + +static GType +gst_selector_pad_get_type (void) +{ + static GType selector_pad_type = 0; + + if (!selector_pad_type) { + static const GTypeInfo selector_pad_info = { + sizeof (GstSelectorPadClass), + NULL, + NULL, + (GClassInitFunc) gst_selector_pad_class_init, + NULL, + NULL, + sizeof (GstSelectorPad), + 0, + (GInstanceInitFunc) gst_selector_pad_init, + }; + + selector_pad_type = + g_type_register_static (GST_TYPE_PAD, "GstCamerabinSelectorPad", + &selector_pad_info, 0); + } + return selector_pad_type; +} + +static void +gst_selector_pad_class_init (GstSelectorPadClass * klass) +{ + GObjectClass *gobject_class; + + gobject_class = (GObjectClass *) klass; + + selector_pad_parent_class = g_type_class_peek_parent (klass); + + gobject_class->finalize = gst_selector_pad_finalize; + + gobject_class->get_property = gst_selector_pad_get_property; + gobject_class->set_property = gst_selector_pad_set_property; + + g_object_class_install_property (gobject_class, PROP_PAD_RUNNING_TIME, + g_param_spec_int64 ("running-time", "Running time", + "Running time of stream on pad", 0, G_MAXINT64, 0, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_PAD_TAGS, + g_param_spec_boxed ("tags", "Tags", + "The currently active tags on the pad", GST_TYPE_TAG_LIST, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_PAD_ACTIVE, + g_param_spec_boolean ("active", "Active", + "If the pad is currently active", FALSE, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_PAD_ALWAYS_OK, + g_param_spec_boolean ("always-ok", "Always OK", + "Make an inactive pad return OK instead of NOT_LINKED", + DEFAULT_PAD_ALWAYS_OK, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); +} + +static void +gst_selector_pad_init (GstSelectorPad * pad) +{ + pad->always_ok = DEFAULT_PAD_ALWAYS_OK; + gst_selector_pad_reset (pad); +} + +static void +gst_selector_pad_finalize (GObject * object) +{ + GstSelectorPad *pad; + + pad = GST_SELECTOR_PAD_CAST (object); + + if (pad->tags) + gst_tag_list_free (pad->tags); + + G_OBJECT_CLASS (selector_pad_parent_class)->finalize (object); +} + +static void +gst_selector_pad_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstSelectorPad *spad = GST_SELECTOR_PAD_CAST (object); + + switch (prop_id) { + case PROP_PAD_ALWAYS_OK: + GST_OBJECT_LOCK (object); + spad->always_ok = g_value_get_boolean (value); + GST_OBJECT_UNLOCK (object); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_selector_pad_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstSelectorPad *spad = GST_SELECTOR_PAD_CAST (object); + + switch (prop_id) { + case PROP_PAD_RUNNING_TIME: + g_value_set_int64 (value, gst_selector_pad_get_running_time (spad)); + break; + case PROP_PAD_TAGS: + GST_OBJECT_LOCK (object); + g_value_set_boxed (value, spad->tags); + GST_OBJECT_UNLOCK (object); + break; + case PROP_PAD_ACTIVE: + { + GstInputSelector *sel; + + sel = GST_INPUT_SELECTOR (gst_pad_get_parent (spad)); + g_value_set_boolean (value, gst_input_selector_is_active_sinkpad (sel, + GST_PAD_CAST (spad))); + gst_object_unref (sel); + break; + } + case PROP_PAD_ALWAYS_OK: + GST_OBJECT_LOCK (object); + g_value_set_boolean (value, spad->always_ok); + GST_OBJECT_UNLOCK (object); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static gint64 +gst_selector_pad_get_running_time (GstSelectorPad * pad) +{ + gint64 ret = 0; + + GST_OBJECT_LOCK (pad); + if (pad->active) { + gint64 last_stop = pad->segment.last_stop; + + if (last_stop >= 0) + ret = gst_segment_to_running_time (&pad->segment, GST_FORMAT_TIME, + last_stop); + } + GST_OBJECT_UNLOCK (pad); + + GST_DEBUG_OBJECT (pad, "running time: %" GST_TIME_FORMAT, + GST_TIME_ARGS (ret)); + + return ret; +} + +static void +gst_selector_pad_reset (GstSelectorPad * pad) +{ + GST_OBJECT_LOCK (pad); + pad->active = FALSE; + pad->eos = FALSE; + pad->segment_pending = FALSE; + pad->discont = FALSE; + gst_segment_init (&pad->segment, GST_FORMAT_UNDEFINED); + GST_OBJECT_UNLOCK (pad); +} + +/* strictly get the linked pad from the sinkpad. If the pad is active we return + * the srcpad else we return NULL */ +static GstIterator * +gst_selector_pad_iterate_linked_pads (GstPad * pad) +{ + GstInputSelector *sel = GST_INPUT_SELECTOR (gst_pad_get_parent (pad)); + GstPad *otherpad; + GstIterator *it; + + otherpad = gst_input_selector_get_linked_pad (pad, TRUE); + it = gst_iterator_new_single (GST_TYPE_PAD, otherpad, + (GstCopyFunction) gst_object_ref, (GFreeFunc) gst_object_unref); + + if (otherpad) + gst_object_unref (otherpad); + gst_object_unref (sel); + + return it; +} + +static gboolean +gst_selector_pad_event (GstPad * pad, GstEvent * event) +{ + gboolean res = TRUE; + gboolean forward = TRUE; + GstInputSelector *sel; + GstSelectorPad *selpad; + GstPad *prev_active_sinkpad; + GstPad *active_sinkpad; + + sel = GST_INPUT_SELECTOR (gst_pad_get_parent (pad)); + selpad = GST_SELECTOR_PAD_CAST (pad); + + GST_INPUT_SELECTOR_LOCK (sel); + prev_active_sinkpad = sel->active_sinkpad; + active_sinkpad = gst_input_selector_activate_sinkpad (sel, pad); + + /* only forward if we are dealing with the active sinkpad or if select_all + * is enabled */ + if (pad != active_sinkpad && !sel->select_all) + forward = FALSE; + GST_INPUT_SELECTOR_UNLOCK (sel); + + if (prev_active_sinkpad != active_sinkpad && pad == active_sinkpad) + g_object_notify (G_OBJECT (sel), "active-pad"); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_FLUSH_START: + /* FIXME, flush out the waiter */ + break; + case GST_EVENT_FLUSH_STOP: + GST_INPUT_SELECTOR_LOCK (sel); + gst_selector_pad_reset (selpad); + sel->pending_close = FALSE; + GST_INPUT_SELECTOR_UNLOCK (sel); + break; + case GST_EVENT_NEWSEGMENT: + { + gboolean update; + GstFormat format; + gdouble rate, arate; + gint64 start, stop, time; + + gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format, + &start, &stop, &time); + + GST_DEBUG_OBJECT (pad, + "configured NEWSEGMENT update %d, rate %lf, applied rate %lf, " + "format %d, " + "%" G_GINT64_FORMAT " -- %" G_GINT64_FORMAT ", time %" + G_GINT64_FORMAT, update, rate, arate, format, start, stop, time); + + GST_INPUT_SELECTOR_LOCK (sel); + GST_OBJECT_LOCK (selpad); + gst_segment_set_newsegment_full (&selpad->segment, update, + rate, arate, format, start, stop, time); + GST_OBJECT_UNLOCK (selpad); + + /* If we aren't forwarding the event (because the pad is not the + * active_sinkpad, and select_all is not set, then set the flag on the + * that says a segment needs sending if/when that pad is activated. + * For all other cases, we send the event immediately, which makes + * sparse streams and other segment updates work correctly downstream. + */ + if (!forward) + selpad->segment_pending = TRUE; + + GST_INPUT_SELECTOR_UNLOCK (sel); + break; + } + case GST_EVENT_TAG: + { + GstTagList *tags, *oldtags, *newtags; + + gst_event_parse_tag (event, &tags); + + GST_OBJECT_LOCK (selpad); + oldtags = selpad->tags; + + newtags = gst_tag_list_merge (oldtags, tags, GST_TAG_MERGE_REPLACE); + selpad->tags = newtags; + if (oldtags) + gst_tag_list_free (oldtags); + GST_DEBUG_OBJECT (pad, "received tags %" GST_PTR_FORMAT, newtags); + GST_OBJECT_UNLOCK (selpad); + + g_object_notify (G_OBJECT (selpad), "tags"); + break; + } + case GST_EVENT_EOS: + selpad->eos = TRUE; + GST_DEBUG_OBJECT (pad, "received EOS"); + /* don't forward eos in select_all mode until all sink pads have eos */ + if (sel->select_all && !gst_input_selector_check_eos (GST_ELEMENT (sel))) { + forward = FALSE; + } + break; + default: + break; + } + if (forward) { + GST_DEBUG_OBJECT (pad, "forwarding event"); + res = gst_pad_push_event (sel->srcpad, event); + } else + gst_event_unref (event); + + gst_object_unref (sel); + + return res; +} + +static GstCaps * +gst_selector_pad_getcaps (GstPad * pad) +{ + GstInputSelector *sel; + GstCaps *caps; + + sel = GST_INPUT_SELECTOR (gst_pad_get_parent (pad)); + + GST_DEBUG_OBJECT (sel, "Getting caps of srcpad peer"); + caps = gst_pad_peer_get_caps_reffed (sel->srcpad); + if (caps == NULL) + caps = gst_caps_new_any (); + + gst_object_unref (sel); + + return caps; +} + +static gboolean +gst_selector_pad_acceptcaps (GstPad * pad, GstCaps * caps) +{ + GstInputSelector *sel; + gboolean res; + + sel = GST_INPUT_SELECTOR (gst_pad_get_parent (pad)); + + GST_DEBUG_OBJECT (sel, "Checking acceptcaps of srcpad peer"); + res = gst_pad_peer_accept_caps (sel->srcpad, caps); + gst_object_unref (sel); + + return res; +} + +static GstFlowReturn +gst_selector_pad_bufferalloc (GstPad * pad, guint64 offset, + guint size, GstCaps * caps, GstBuffer ** buf) +{ + GstInputSelector *sel; + GstFlowReturn result; + GstPad *active_sinkpad; + GstPad *prev_active_sinkpad; + GstSelectorPad *selpad; + + sel = GST_INPUT_SELECTOR (gst_pad_get_parent (pad)); + selpad = GST_SELECTOR_PAD_CAST (pad); + + GST_LOG_OBJECT (pad, "received alloc"); + + GST_INPUT_SELECTOR_LOCK (sel); + prev_active_sinkpad = sel->active_sinkpad; + active_sinkpad = gst_input_selector_activate_sinkpad (sel, pad); + + if (pad != active_sinkpad) + goto not_active; + + GST_INPUT_SELECTOR_UNLOCK (sel); + + if (prev_active_sinkpad != active_sinkpad && pad == active_sinkpad) + g_object_notify (G_OBJECT (sel), "active-pad"); + + result = gst_pad_alloc_buffer (sel->srcpad, offset, size, caps, buf); + +done: + gst_object_unref (sel); + + return result; + + /* ERRORS */ +not_active: + { + GST_INPUT_SELECTOR_UNLOCK (sel); + + /* unselected pad, perform fallback alloc or return unlinked when + * asked */ + GST_OBJECT_LOCK (selpad); + if (selpad->always_ok) { + GST_DEBUG_OBJECT (pad, "Not selected, performing fallback allocation"); + *buf = NULL; + result = GST_FLOW_OK; + } else { + GST_DEBUG_OBJECT (pad, "Not selected, return NOT_LINKED"); + result = GST_FLOW_NOT_LINKED; + } + GST_OBJECT_UNLOCK (selpad); + + goto done; + } +} + +/* must be called with the SELECTOR_LOCK, will block while the pad is blocked + * or return TRUE when flushing */ +static gboolean +gst_input_selector_wait (GstInputSelector * self, GstPad * pad) +{ + while (self->blocked && !self->flushing) { + /* we can be unlocked here when we are shutting down (flushing) or when we + * get unblocked */ + GST_INPUT_SELECTOR_WAIT (self); + } + return self->flushing; +} + +static GstFlowReturn +gst_selector_pad_chain (GstPad * pad, GstBuffer * buf) +{ + GstInputSelector *sel; + GstFlowReturn res; + GstPad *active_sinkpad; + GstPad *prev_active_sinkpad; + GstSelectorPad *selpad; + GstClockTime start_time; + GstSegment *seg; + GstEvent *close_event = NULL, *start_event = NULL; + GstCaps *caps; + + sel = GST_INPUT_SELECTOR (gst_pad_get_parent (pad)); + selpad = GST_SELECTOR_PAD_CAST (pad); + seg = &selpad->segment; + + GST_INPUT_SELECTOR_LOCK (sel); + /* wait or check for flushing */ + if (gst_input_selector_wait (sel, pad)) + goto flushing; + + GST_LOG_OBJECT (pad, "getting active pad"); + + prev_active_sinkpad = sel->active_sinkpad; + active_sinkpad = gst_input_selector_activate_sinkpad (sel, pad); + + /* update the segment on the srcpad */ + start_time = GST_BUFFER_TIMESTAMP (buf); + if (GST_CLOCK_TIME_IS_VALID (start_time)) { + GST_LOG_OBJECT (pad, "received start time %" GST_TIME_FORMAT, + GST_TIME_ARGS (start_time)); + if (GST_BUFFER_DURATION_IS_VALID (buf)) + GST_LOG_OBJECT (pad, "received end time %" GST_TIME_FORMAT, + GST_TIME_ARGS (start_time + GST_BUFFER_DURATION (buf))); + + GST_OBJECT_LOCK (pad); + gst_segment_set_last_stop (seg, seg->format, start_time); + GST_OBJECT_UNLOCK (pad); + } + + /* Ignore buffers from pads except the selected one */ + if (pad != active_sinkpad) + goto ignore; + + if (G_UNLIKELY (sel->pending_close)) { + GstSegment *cseg = &sel->segment; + + GST_DEBUG_OBJECT (sel, + "pushing close NEWSEGMENT update %d, rate %lf, applied rate %lf, " + "format %d, " + "%" G_GINT64_FORMAT " -- %" G_GINT64_FORMAT ", time %" + G_GINT64_FORMAT, TRUE, cseg->rate, cseg->applied_rate, cseg->format, + cseg->start, cseg->stop, cseg->time); + + /* create update segment */ + close_event = gst_event_new_new_segment_full (TRUE, cseg->rate, + cseg->applied_rate, cseg->format, cseg->start, cseg->stop, cseg->time); + + sel->pending_close = FALSE; + } + /* if we have a pending segment, push it out now */ + if (G_UNLIKELY (selpad->segment_pending)) { + GST_DEBUG_OBJECT (pad, + "pushing pending NEWSEGMENT update %d, rate %lf, applied rate %lf, " + "format %d, " + "%" G_GINT64_FORMAT " -- %" G_GINT64_FORMAT ", time %" + G_GINT64_FORMAT, FALSE, seg->rate, seg->applied_rate, seg->format, + seg->start, seg->stop, seg->time); + + start_event = gst_event_new_new_segment_full (FALSE, seg->rate, + seg->applied_rate, seg->format, seg->start, seg->stop, seg->time); + + selpad->segment_pending = FALSE; + } + GST_INPUT_SELECTOR_UNLOCK (sel); + + if (prev_active_sinkpad != active_sinkpad && pad == active_sinkpad) + g_object_notify (G_OBJECT (sel), "active-pad"); + + if (close_event) + gst_pad_push_event (sel->srcpad, close_event); + + if (start_event) + gst_pad_push_event (sel->srcpad, start_event); + + if (selpad->discont) { + buf = gst_buffer_make_metadata_writable (buf); + + GST_DEBUG_OBJECT (pad, "Marking discont buffer %p", buf); + GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DISCONT); + selpad->discont = FALSE; + } + + /* forward */ + GST_LOG_OBJECT (pad, "Forwarding buffer %p", buf); + + if ((caps = GST_BUFFER_CAPS (buf))) { + if (GST_PAD_CAPS (sel->srcpad) != caps) + gst_pad_set_caps (sel->srcpad, caps); + } + + res = gst_pad_push (sel->srcpad, buf); + +done: + gst_object_unref (sel); + return res; + + /* dropped buffers */ +ignore: + { + GST_DEBUG_OBJECT (pad, "Pad not active, discard buffer %p", buf); + /* when we drop a buffer, we're creating a discont on this pad */ + selpad->discont = TRUE; + GST_INPUT_SELECTOR_UNLOCK (sel); + gst_buffer_unref (buf); + + /* figure out what to return upstream */ + GST_OBJECT_LOCK (selpad); + if (selpad->always_ok) + res = GST_FLOW_OK; + else + res = GST_FLOW_NOT_LINKED; + GST_OBJECT_UNLOCK (selpad); + + goto done; + } +flushing: + { + GST_DEBUG_OBJECT (pad, "We are flushing, discard buffer %p", buf); + GST_INPUT_SELECTOR_UNLOCK (sel); + gst_buffer_unref (buf); + res = GST_FLOW_WRONG_STATE; + goto done; + } +} + +static void gst_input_selector_init (GstInputSelector * sel); +static void gst_input_selector_base_init (GstInputSelectorClass * klass); +static void gst_input_selector_class_init (GstInputSelectorClass * klass); + +static void gst_input_selector_dispose (GObject * object); + +static void gst_input_selector_set_property (GObject * object, + guint prop_id, const GValue * value, GParamSpec * pspec); +static void gst_input_selector_get_property (GObject * object, + guint prop_id, GValue * value, GParamSpec * pspec); + +static GstPad *gst_input_selector_request_new_pad (GstElement * element, + GstPadTemplate * templ, const gchar * unused); +static void gst_input_selector_release_pad (GstElement * element, GstPad * pad); + +static GstStateChangeReturn gst_input_selector_change_state (GstElement * + element, GstStateChange transition); + +static GstCaps *gst_input_selector_getcaps (GstPad * pad); +static gboolean gst_input_selector_event (GstPad * pad, GstEvent * event); +static gboolean gst_input_selector_query (GstPad * pad, GstQuery * query); +static gint64 gst_input_selector_block (GstInputSelector * self); +static void gst_input_selector_switch (GstInputSelector * self, + GstPad * pad, gint64 stop_time, gint64 start_time); + +static GstElementClass *parent_class = NULL; + +GType +gst_input_selector_get_type (void) +{ + static GType input_selector_type = 0; + + if (!input_selector_type) { + static const GTypeInfo input_selector_info = { + sizeof (GstInputSelectorClass), + (GBaseInitFunc) gst_input_selector_base_init, + NULL, + (GClassInitFunc) gst_input_selector_class_init, + NULL, + NULL, + sizeof (GstInputSelector), + 0, + (GInstanceInitFunc) gst_input_selector_init, + }; + input_selector_type = + g_type_register_static (GST_TYPE_ELEMENT, + "GstCamerabinInputSelector", &input_selector_info, 0); + GST_DEBUG_CATEGORY_INIT (input_selector_debug, + "camerabin-input-selector", 0, "Camerabin input selector element"); + } + + return input_selector_type; +} + +static void +gst_input_selector_base_init (GstInputSelectorClass * klass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + + gst_element_class_set_details_simple (element_class, + "Input selector", "Generic", + "N-to-1 input stream selectoring", + "Julien Moutte , " + "Jan Schmidt , " + "Wim Taymans "); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_input_selector_sink_factory)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_input_selector_src_factory)); +} + +static void +gst_input_selector_class_init (GstInputSelectorClass * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass); + + parent_class = g_type_class_peek_parent (klass); + + /* FIXME: remove after confirming it is safe now */ + g_type_class_ref (gst_selector_pad_get_type ()); + + gobject_class->dispose = gst_input_selector_dispose; + + gobject_class->set_property = gst_input_selector_set_property; + gobject_class->get_property = gst_input_selector_get_property; + + g_object_class_install_property (gobject_class, PROP_N_PADS, + g_param_spec_uint ("n-pads", "Number of Pads", + "The number of sink pads", 0, G_MAXUINT, 0, + G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_ACTIVE_PAD, + g_param_spec_object ("active-pad", "Active pad", + "The currently active sink pad", GST_TYPE_PAD, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_SELECT_ALL, + g_param_spec_boolean ("select-all", "Select all mode", + "Forwards data from all input pads", FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** + * GstInputSelector::block: + * @inputselector: the #GstInputSelector + * + * Block all sink pads in preparation for a switch. Returns the stop time of + * the current switch segment, as a running time, or 0 if there is no current + * active pad or the current active pad never received data. + */ + gst_input_selector_signals[SIGNAL_BLOCK] = + g_signal_new ("block", G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION, + G_STRUCT_OFFSET (GstInputSelectorClass, block), NULL, NULL, + __gst_camerabin_marshal_INT64__VOID, G_TYPE_INT64, 0); + /** + * GstInputSelector::switch: + * @inputselector: the #GstInputSelector + * @pad: the pad to switch to + * @stop_time: running time at which to close the previous segment, or -1 + * to use the running time of the previously active sink pad + * @start_time: running time at which to start the new segment, or -1 to + * use the running time of the newly active sink pad + * + * Switch to a new feed. The segment opened by the previously active pad, if + * any, will be closed, and a new segment opened before data flows again. + * + * This signal must be emitted when the element has been blocked via the block signal. + * + * If you have a stream with only one switch element, such as an audio-only + * stream, a stream switch should be performed by first emitting the block + * signal, and then emitting the switch signal with -1 for the stop and start + * time values. + * + * The intention of the @stop_time and @start_time arguments is to allow + * multiple switch elements to switch and maintain stream synchronization. + * When switching a stream with multiple feeds, you will need as many switch + * elements as you have feeds. For example, a feed with audio and video will + * have one switch element between the audio feeds and one for video. + * + * A switch over multiple switch elements should be performed as follows: + * First, emit the block + * signal, collecting the returned values. The maximum running time returned + * by block should then be used as the time at which to close the previous + * segment. + * + * Then, query the running times of the new audio and video pads that you will + * switch to. Naturally, these pads are on separate switch elements. Take the + * minimum running time for those streams and use it for the time at which to + * open the new segment. + * + * If @pad is the same as the current active pad, the element will cancel any + * previous block without adjusting segments. + * + * + * the signal changed from accepting the pad name to the pad object. + * + * + * Since: 0.10.7 + */ + gst_input_selector_signals[SIGNAL_SWITCH] = + g_signal_new ("switch", G_TYPE_FROM_CLASS (klass), G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (GstInputSelectorClass, switch_), + NULL, NULL, __gst_camerabin_marshal_VOID__OBJECT_INT64_INT64, + G_TYPE_NONE, 3, GST_TYPE_PAD, G_TYPE_INT64, G_TYPE_INT64); + + gstelement_class->request_new_pad = gst_input_selector_request_new_pad; + gstelement_class->release_pad = gst_input_selector_release_pad; + gstelement_class->change_state = gst_input_selector_change_state; + + klass->block = GST_DEBUG_FUNCPTR (gst_input_selector_block); + /* note the underscore because switch is a keyword otherwise */ + klass->switch_ = GST_DEBUG_FUNCPTR (gst_input_selector_switch); +} + +static void +gst_input_selector_init (GstInputSelector * sel) +{ + sel->srcpad = gst_pad_new ("src", GST_PAD_SRC); + gst_pad_set_iterate_internal_links_function (sel->srcpad, + GST_DEBUG_FUNCPTR (gst_selector_pad_iterate_linked_pads)); + gst_pad_set_getcaps_function (sel->srcpad, + GST_DEBUG_FUNCPTR (gst_input_selector_getcaps)); + gst_pad_set_query_function (sel->srcpad, + GST_DEBUG_FUNCPTR (gst_input_selector_query)); + gst_pad_set_event_function (sel->srcpad, + GST_DEBUG_FUNCPTR (gst_input_selector_event)); + gst_element_add_pad (GST_ELEMENT (sel), sel->srcpad); + /* sinkpad management */ + sel->active_sinkpad = NULL; + sel->padcount = 0; + gst_segment_init (&sel->segment, GST_FORMAT_UNDEFINED); + + sel->lock = g_mutex_new (); + sel->cond = g_cond_new (); + sel->blocked = FALSE; + + sel->select_all = FALSE; +} + +static void +gst_input_selector_dispose (GObject * object) +{ + GstInputSelector *sel = GST_INPUT_SELECTOR (object); + + if (sel->active_sinkpad) { + gst_object_unref (sel->active_sinkpad); + sel->active_sinkpad = NULL; + } + if (sel->lock) { + g_mutex_free (sel->lock); + sel->lock = NULL; + } + if (sel->cond) { + g_cond_free (sel->cond); + sel->cond = NULL; + } + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +/* Solve the following equation for B.timestamp, and set that as the segment + * stop: + * B.running_time = (B.timestamp - NS.start) / NS.abs_rate + NS.accum + */ +static gint64 +gst_segment_get_timestamp (GstSegment * segment, gint64 running_time) +{ + if (running_time <= segment->accum) + return segment->start; + else + return (running_time - segment->accum) * segment->abs_rate + segment->start; +} + +static void +gst_segment_set_stop (GstSegment * segment, gint64 running_time) +{ + segment->stop = gst_segment_get_timestamp (segment, running_time); + segment->last_stop = -1; +} + +static void +gst_segment_set_start (GstSegment * segment, gint64 running_time) +{ + gint64 new_start, duration; + + new_start = gst_segment_get_timestamp (segment, running_time); + + /* this is the duration we skipped */ + duration = new_start - segment->start; + /* add the duration to the accumulated segment time */ + segment->accum += duration; + /* move position in the segment */ + segment->time += duration; + segment->start += duration; +} + +/* this function must be called with the SELECTOR_LOCK. It returns TRUE when the + * active pad changed. */ +static gboolean +gst_input_selector_set_active_pad (GstInputSelector * self, + GstPad * pad, gint64 stop_time, gint64 start_time) +{ + GstSelectorPad *old, *new; + GstPad **active_pad_p; + + if (pad == self->active_sinkpad) + return FALSE; + + old = GST_SELECTOR_PAD_CAST (self->active_sinkpad); + new = GST_SELECTOR_PAD_CAST (pad); + + GST_DEBUG_OBJECT (self, "setting active pad to %s:%s", + GST_DEBUG_PAD_NAME (new)); + + if (!GST_CLOCK_TIME_IS_VALID (stop_time) && old) { + /* no stop time given, get the latest running_time on the active pad to + * close and open the new segment */ + stop_time = start_time = gst_selector_pad_get_running_time (old); + GST_DEBUG_OBJECT (self, "using start/stop of %" GST_TIME_FORMAT, + GST_TIME_ARGS (start_time)); + } + + if (old && old->active && !self->pending_close && stop_time >= 0) { + /* schedule a last_stop update if one isn't already scheduled, and a + segment has been pushed before. */ + memcpy (&self->segment, &old->segment, sizeof (self->segment)); + + GST_DEBUG_OBJECT (self, "setting stop_time to %" GST_TIME_FORMAT, + GST_TIME_ARGS (stop_time)); + gst_segment_set_stop (&self->segment, stop_time); + self->pending_close = TRUE; + } + + if (new && new->active && start_time >= 0) { + GST_DEBUG_OBJECT (self, "setting start_time to %" GST_TIME_FORMAT, + GST_TIME_ARGS (start_time)); + /* schedule a new segment push */ + gst_segment_set_start (&new->segment, start_time); + new->segment_pending = TRUE; + } + + active_pad_p = &self->active_sinkpad; + gst_object_replace ((GstObject **) active_pad_p, GST_OBJECT_CAST (pad)); + GST_DEBUG_OBJECT (self, "New active pad is %" GST_PTR_FORMAT, + self->active_sinkpad); + + return TRUE; +} + +static void +gst_input_selector_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstInputSelector *sel = GST_INPUT_SELECTOR (object); + + switch (prop_id) { + case PROP_ACTIVE_PAD: + { + GstPad *pad; + + pad = g_value_get_object (value); + + GST_INPUT_SELECTOR_LOCK (sel); + gst_input_selector_set_active_pad (sel, pad, + GST_CLOCK_TIME_NONE, GST_CLOCK_TIME_NONE); + GST_INPUT_SELECTOR_UNLOCK (sel); + break; + } + case PROP_SELECT_ALL: + GST_INPUT_SELECTOR_LOCK (object); + sel->select_all = g_value_get_boolean (value); + GST_INPUT_SELECTOR_UNLOCK (object); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_input_selector_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstInputSelector *sel = GST_INPUT_SELECTOR (object); + + switch (prop_id) { + case PROP_N_PADS: + GST_INPUT_SELECTOR_LOCK (object); + g_value_set_uint (value, sel->n_pads); + GST_INPUT_SELECTOR_UNLOCK (object); + break; + case PROP_ACTIVE_PAD: + GST_INPUT_SELECTOR_LOCK (object); + g_value_set_object (value, sel->active_sinkpad); + GST_INPUT_SELECTOR_UNLOCK (object); + break; + case PROP_SELECT_ALL: + GST_INPUT_SELECTOR_LOCK (object); + g_value_set_boolean (value, sel->select_all); + GST_INPUT_SELECTOR_UNLOCK (object); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static GstPad * +gst_input_selector_get_linked_pad (GstPad * pad, gboolean strict) +{ + GstInputSelector *sel; + GstPad *otherpad = NULL; + + sel = GST_INPUT_SELECTOR (gst_pad_get_parent (pad)); + + GST_INPUT_SELECTOR_LOCK (sel); + if (pad == sel->srcpad) + otherpad = sel->active_sinkpad; + else if (pad == sel->active_sinkpad || !strict) + otherpad = sel->srcpad; + if (otherpad) + gst_object_ref (otherpad); + GST_INPUT_SELECTOR_UNLOCK (sel); + + gst_object_unref (sel); + + return otherpad; +} + +static gboolean +gst_input_selector_event (GstPad * pad, GstEvent * event) +{ + gboolean res = FALSE; + GstPad *otherpad; + + otherpad = gst_input_selector_get_linked_pad (pad, TRUE); + + if (otherpad) { + res = gst_pad_push_event (otherpad, event); + + gst_object_unref (otherpad); + } else + gst_event_unref (event); + return res; +} + +/* query on the srcpad. We override this function because by default it will + * only forward the query to one random sinkpad */ +static gboolean +gst_input_selector_query (GstPad * pad, GstQuery * query) +{ + gboolean res = TRUE; + GstInputSelector *sel; + GstPad *otherpad; + + sel = GST_INPUT_SELECTOR (gst_pad_get_parent (pad)); + + otherpad = gst_input_selector_get_linked_pad (pad, TRUE); + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_LATENCY: + { + GList *walk; + GstClockTime resmin, resmax; + gboolean reslive; + + resmin = 0; + resmax = -1; + reslive = FALSE; + + /* assume FALSE, we become TRUE if one query succeeds */ + res = FALSE; + + /* perform the query on all sinkpads and combine the results. We take the + * max of min and the min of max for the result latency. */ + GST_INPUT_SELECTOR_LOCK (sel); + for (walk = GST_ELEMENT_CAST (sel)->sinkpads; walk; + walk = g_list_next (walk)) { + GstPad *sinkpad = GST_PAD_CAST (walk->data); + + if (gst_pad_peer_query (sinkpad, query)) { + GstClockTime min, max; + gboolean live; + + /* one query succeeded, we succeed too */ + res = TRUE; + + gst_query_parse_latency (query, &live, &min, &max); + + GST_DEBUG_OBJECT (sinkpad, + "peer latency min %" GST_TIME_FORMAT ", max %" GST_TIME_FORMAT + ", live %d", GST_TIME_ARGS (min), GST_TIME_ARGS (max), live); + + if (live) { + if (min > resmin) + resmin = min; + if (resmax == -1) + resmax = max; + else if (max < resmax) + resmax = max; + if (reslive == FALSE) + reslive = live; + } + } + } + GST_INPUT_SELECTOR_UNLOCK (sel); + if (res) { + gst_query_set_latency (query, reslive, resmin, resmax); + + GST_DEBUG_OBJECT (sel, + "total latency min %" GST_TIME_FORMAT ", max %" GST_TIME_FORMAT + ", live %d", GST_TIME_ARGS (resmin), GST_TIME_ARGS (resmax), + reslive); + } + + break; + } + default: + if (otherpad) + res = gst_pad_peer_query (otherpad, query); + break; + } + if (otherpad) + gst_object_unref (otherpad); + gst_object_unref (sel); + + return res; +} + +static GstCaps * +gst_input_selector_getcaps (GstPad * pad) +{ + GstPad *otherpad; + GstObject *parent; + GstCaps *caps; + + parent = gst_object_get_parent (GST_OBJECT (pad)); + + otherpad = gst_input_selector_get_linked_pad (pad, FALSE); + + if (!otherpad) { + if (GST_INPUT_SELECTOR (parent)->select_all) { + GST_DEBUG_OBJECT (parent, + "Pad %s:%s not linked, returning merge of caps", + GST_DEBUG_PAD_NAME (pad)); + caps = gst_pad_proxy_getcaps (pad); + } else { + GST_DEBUG_OBJECT (parent, + "Pad %s:%s not linked, returning ANY", GST_DEBUG_PAD_NAME (pad)); + caps = gst_caps_new_any (); + } + } else { + GST_DEBUG_OBJECT (parent, + "Pad %s:%s is linked (to %s:%s), returning peer caps", + GST_DEBUG_PAD_NAME (pad), GST_DEBUG_PAD_NAME (otherpad)); + /* if the peer has caps, use those. If the pad is not linked, this function + * returns NULL and we return ANY */ + if (!(caps = gst_pad_peer_get_caps_reffed (otherpad))) + caps = gst_caps_new_any (); + gst_object_unref (otherpad); + } + + gst_object_unref (parent); + return caps; +} + +/* check if the pad is the active sinkpad */ +static gboolean +gst_input_selector_is_active_sinkpad (GstInputSelector * sel, GstPad * pad) +{ + gboolean res; + + GST_INPUT_SELECTOR_LOCK (sel); + res = (pad == sel->active_sinkpad); + GST_INPUT_SELECTOR_UNLOCK (sel); + + return res; +} + +/* Get or create the active sinkpad, must be called with SELECTOR_LOCK */ +static GstPad * +gst_input_selector_activate_sinkpad (GstInputSelector * sel, GstPad * pad) +{ + GstPad *active_sinkpad; + GstSelectorPad *selpad; + + selpad = GST_SELECTOR_PAD_CAST (pad); + + selpad->active = TRUE; + active_sinkpad = sel->active_sinkpad; + if (active_sinkpad == NULL || sel->select_all) { + /* first pad we get activity on becomes the activated pad by default, if we + * select all, we also remember the last used pad. */ + if (sel->active_sinkpad) + gst_object_unref (sel->active_sinkpad); + active_sinkpad = sel->active_sinkpad = gst_object_ref (pad); + GST_DEBUG_OBJECT (sel, "Activating pad %s:%s", GST_DEBUG_PAD_NAME (pad)); + } + + return active_sinkpad; +} + +static GstPad * +gst_input_selector_request_new_pad (GstElement * element, + GstPadTemplate * templ, const gchar * unused) +{ + GstInputSelector *sel; + gchar *name = NULL; + GstPad *sinkpad = NULL; + + g_return_val_if_fail (templ->direction == GST_PAD_SINK, NULL); + + sel = GST_INPUT_SELECTOR (element); + + GST_INPUT_SELECTOR_LOCK (sel); + + GST_LOG_OBJECT (sel, "Creating new pad %d", sel->padcount); + name = g_strdup_printf ("sink%d", sel->padcount++); + sinkpad = g_object_new (GST_TYPE_SELECTOR_PAD, + "name", name, "direction", templ->direction, "template", templ, NULL); + g_free (name); + + sel->n_pads++; + + gst_pad_set_event_function (sinkpad, + GST_DEBUG_FUNCPTR (gst_selector_pad_event)); + gst_pad_set_getcaps_function (sinkpad, + GST_DEBUG_FUNCPTR (gst_selector_pad_getcaps)); + gst_pad_set_acceptcaps_function (sinkpad, + GST_DEBUG_FUNCPTR (gst_selector_pad_acceptcaps)); + gst_pad_set_chain_function (sinkpad, + GST_DEBUG_FUNCPTR (gst_selector_pad_chain)); + gst_pad_set_iterate_internal_links_function (sinkpad, + GST_DEBUG_FUNCPTR (gst_selector_pad_iterate_linked_pads)); + gst_pad_set_bufferalloc_function (sinkpad, + GST_DEBUG_FUNCPTR (gst_selector_pad_bufferalloc)); + + gst_pad_set_active (sinkpad, TRUE); + gst_element_add_pad (GST_ELEMENT (sel), sinkpad); + GST_INPUT_SELECTOR_UNLOCK (sel); + + return sinkpad; +} + +static void +gst_input_selector_release_pad (GstElement * element, GstPad * pad) +{ + GstInputSelector *sel; + + sel = GST_INPUT_SELECTOR (element); + GST_LOG_OBJECT (sel, "Releasing pad %s:%s", GST_DEBUG_PAD_NAME (pad)); + + GST_INPUT_SELECTOR_LOCK (sel); + /* if the pad was the active pad, makes us select a new one */ + if (sel->active_sinkpad == pad) { + GST_DEBUG_OBJECT (sel, "Deactivating pad %s:%s", GST_DEBUG_PAD_NAME (pad)); + gst_object_unref (sel->active_sinkpad); + sel->active_sinkpad = NULL; + } + sel->n_pads--; + + gst_pad_set_active (pad, FALSE); + gst_element_remove_pad (GST_ELEMENT (sel), pad); + GST_INPUT_SELECTOR_UNLOCK (sel); +} + +static void +gst_input_selector_reset (GstInputSelector * sel) +{ + GList *walk; + + GST_INPUT_SELECTOR_LOCK (sel); + /* clear active pad */ + if (sel->active_sinkpad) { + gst_object_unref (sel->active_sinkpad); + sel->active_sinkpad = NULL; + } + /* reset segment */ + gst_segment_init (&sel->segment, GST_FORMAT_UNDEFINED); + sel->pending_close = FALSE; + /* reset each of our sinkpads state */ + for (walk = GST_ELEMENT_CAST (sel)->sinkpads; walk; walk = g_list_next (walk)) { + GstSelectorPad *selpad = GST_SELECTOR_PAD_CAST (walk->data); + + gst_selector_pad_reset (selpad); + + if (selpad->tags) { + gst_tag_list_free (selpad->tags); + selpad->tags = NULL; + } + } + GST_INPUT_SELECTOR_UNLOCK (sel); +} + +static GstStateChangeReturn +gst_input_selector_change_state (GstElement * element, + GstStateChange transition) +{ + GstInputSelector *self = GST_INPUT_SELECTOR (element); + GstStateChangeReturn result; + + switch (transition) { + case GST_STATE_CHANGE_READY_TO_PAUSED: + GST_INPUT_SELECTOR_LOCK (self); + self->blocked = FALSE; + self->flushing = FALSE; + GST_INPUT_SELECTOR_UNLOCK (self); + break; + case GST_STATE_CHANGE_PAUSED_TO_READY: + /* first unlock before we call the parent state change function, which + * tries to acquire the stream lock when going to ready. */ + GST_INPUT_SELECTOR_LOCK (self); + self->blocked = FALSE; + self->flushing = TRUE; + GST_INPUT_SELECTOR_BROADCAST (self); + GST_INPUT_SELECTOR_UNLOCK (self); + break; + default: + break; + } + + result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + + switch (transition) { + case GST_STATE_CHANGE_PAUSED_TO_READY: + gst_input_selector_reset (self); + break; + default: + break; + } + + return result; +} + +static gint64 +gst_input_selector_block (GstInputSelector * self) +{ + gint64 ret = 0; + GstSelectorPad *spad; + + GST_INPUT_SELECTOR_LOCK (self); + + if (self->blocked) + GST_WARNING_OBJECT (self, "switch already blocked"); + + self->blocked = TRUE; + spad = GST_SELECTOR_PAD_CAST (self->active_sinkpad); + + if (spad) + ret = gst_selector_pad_get_running_time (spad); + else + GST_DEBUG_OBJECT (self, "no active pad while blocking"); + + GST_INPUT_SELECTOR_UNLOCK (self); + + return ret; +} + +/* stop_time and start_time are running times */ +static void +gst_input_selector_switch (GstInputSelector * self, GstPad * pad, + gint64 stop_time, gint64 start_time) +{ + gboolean changed; + + g_return_if_fail (self->blocked == TRUE); + + GST_INPUT_SELECTOR_LOCK (self); + changed = + gst_input_selector_set_active_pad (self, pad, stop_time, start_time); + + self->blocked = FALSE; + GST_INPUT_SELECTOR_BROADCAST (self); + GST_INPUT_SELECTOR_UNLOCK (self); + + if (changed) + g_object_notify (G_OBJECT (self), "active-pad"); +} + +static gboolean +gst_input_selector_check_eos (GstElement * selector) +{ + GstIterator *it = gst_element_iterate_sink_pads (selector); + GstIteratorResult ires; + gpointer item; + gboolean done = FALSE, is_eos = FALSE; + GstSelectorPad *pad; + + while (!done) { + ires = gst_iterator_next (it, &item); + switch (ires) { + case GST_ITERATOR_DONE: + GST_INFO_OBJECT (selector, "all sink pads have eos"); + done = TRUE; + is_eos = TRUE; + break; + case GST_ITERATOR_OK: + pad = GST_SELECTOR_PAD_CAST (item); + if (!pad->eos) { + done = TRUE; + } + gst_object_unref (pad); + break; + case GST_ITERATOR_RESYNC: + gst_iterator_resync (it); + break; + default: + done = TRUE; + break; + } + } + gst_iterator_free (it); + + return is_eos; +} diff --git a/gst/camerabin/gstinputselector.h b/gst/camerabin/gstinputselector.h new file mode 100644 index 0000000000..58a671d50c --- /dev/null +++ b/gst/camerabin/gstinputselector.h @@ -0,0 +1,84 @@ +/* GStreamer + * Copyright (C) 2003 Julien Moutte + * Copyright (C) 2005 Ronald S. Bultje + * Copyright (C) 2008 Nokia Corporation. (contact ) + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_INPUT_SELECTOR_H__ +#define __GST_INPUT_SELECTOR_H__ + +#include + +G_BEGIN_DECLS + +#define GST_TYPE_INPUT_SELECTOR \ + (gst_input_selector_get_type()) +#define GST_INPUT_SELECTOR(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST ((obj), GST_TYPE_INPUT_SELECTOR, GstInputSelector)) +#define GST_INPUT_SELECTOR_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST ((klass), GST_TYPE_INPUT_SELECTOR, GstInputSelectorClass)) +#define GST_IS_INPUT_SELECTOR(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE ((obj), GST_TYPE_INPUT_SELECTOR)) +#define GST_IS_INPUT_SELECTOR_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_INPUT_SELECTOR)) + +typedef struct _GstInputSelector GstInputSelector; +typedef struct _GstInputSelectorClass GstInputSelectorClass; + +#define GST_INPUT_SELECTOR_GET_LOCK(sel) (((GstInputSelector*)(sel))->lock) +#define GST_INPUT_SELECTOR_GET_COND(sel) (((GstInputSelector*)(sel))->cond) +#define GST_INPUT_SELECTOR_LOCK(sel) (g_mutex_lock (GST_INPUT_SELECTOR_GET_LOCK(sel))) +#define GST_INPUT_SELECTOR_UNLOCK(sel) (g_mutex_unlock (GST_INPUT_SELECTOR_GET_LOCK(sel))) +#define GST_INPUT_SELECTOR_WAIT(sel) (g_cond_wait (GST_INPUT_SELECTOR_GET_COND(sel), \ + GST_INPUT_SELECTOR_GET_LOCK(sel))) +#define GST_INPUT_SELECTOR_BROADCAST(sel) (g_cond_broadcast (GST_INPUT_SELECTOR_GET_COND(sel))) + +struct _GstInputSelector { + GstElement element; + + GstPad *srcpad; + + GstPad *active_sinkpad; + guint n_pads; + guint padcount; + + GstSegment segment; /* the output segment */ + gboolean pending_close; /* if we should push a close first */ + + GMutex *lock; + GCond *cond; + gboolean blocked; + gboolean flushing; + + /* select all mode, send data from all input pads forward */ + gboolean select_all; +}; + +struct _GstInputSelectorClass { + GstElementClass parent_class; + + gint64 (*block) (GstInputSelector *self); + void (*switch_) (GstInputSelector *self, GstPad *pad, + gint64 stop_time, gint64 start_time); +}; + +GType gst_input_selector_get_type (void); + +G_END_DECLS + +#endif /* __GST_INPUT_SELECTOR_H__ */ From 04358a4af9060dd964427ab333caad37ce4419c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Sat, 8 Jan 2011 02:47:12 +0000 Subject: [PATCH 280/448] po: update translations --- po/bg.po | 43 ++++++------- po/ca.po | 190 ++++++------------------------------------------------- po/ja.po | 152 ++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 187 insertions(+), 198 deletions(-) diff --git a/po/bg.po b/po/bg.po index a41931c050..3f3b07b571 100644 --- a/po/bg.po +++ b/po/bg.po @@ -1,31 +1,32 @@ # Bulgarian translation of gst-plugins-bad. -# Copyright (C) 2007, 2008, 2009 Free Software Fondation, Inc. +# Copyright (C) 2007, 2008, 2009, 2010 Free Software Fondation, Inc. # This file is distributed under the same license as the gst-plugins-bad package. -# Alexander Shopov , 2007, 2008, 2009. +# Alexander Shopov , 2007, 2008, 2009, 2010. +# # msgid "" msgstr "" -"Project-Id-Version: gst-plugins-bad 0.10.13.2\n" +"Project-Id-Version: gst-plugins-bad 0.10.18.2\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" -"POT-Creation-Date: 2010-10-19 23:33+0100\n" -"PO-Revision-Date: 2009-09-24 15:33+0300\n" -"Last-Translator: Alexander Shopov \n" +"POT-Creation-Date: 2011-01-07 20:26+0000\n" +"PO-Revision-Date: 2010-11-04 14:25+0200\n" +"Last-Translator: Alexander Shopov \n" "Language-Team: Bulgarian \n" -"Language: bg\n" +"Language: \n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" msgid "Could not read title information for DVD." -msgstr "Информацията за заглавието на DVD-то не може да бъде прочетена." +msgstr "Информацията за заглавните части на DVD-то не може да бъде прочетена." #, c-format msgid "Failed to open DVD device '%s'." -msgstr "Устройството за DVD „%s“ не може да бъде отворено." +msgstr "Не може да се чете от устройството за DVD-та „%s“." msgid "Failed to set PGC based seeking." -msgstr "Неуспех при задаване на търсене чрез PGC." +msgstr "Не може да се търси по веригата на програмите (PGC)" msgid "" "Could not read DVD. This may be because the DVD is encrypted and a DVD " @@ -34,24 +35,24 @@ msgstr "" #, fuzzy msgid "Could not read DVD." -msgstr "Информацията за заглавието на DVD-то не може да бъде прочетена." +msgstr "Информацията за заглавните части на DVD-то не може да бъде прочетена." msgid "No file name specified for writing." -msgstr "Не е указано име на файл, в който да се пише." +msgstr "Не е указано име на файл за запис." #, c-format msgid "Could not open file \"%s\" for writing." -msgstr "Файлът „%s“ не може да бъде отворен за запис." +msgstr "Файлът „%s“ не може да се отвори за запис." msgid "Internal data stream error." -msgstr "Вътрешна грешка в потока от данни." +msgstr "Вътрешна грешка в потока на данни." #, c-format msgid "Could not write to file \"%s\"." -msgstr "Във файла „%s“ не може да се пише." +msgstr "Не може да се записва във файла „%s“." msgid "Internal data flow error." -msgstr "Вътрешна грешка в потока от данни." +msgstr "Вътрешна грешка в потока на данни." #, c-format msgid "Device \"%s\" does not exist." @@ -63,14 +64,8 @@ msgstr "Устройството „%s“ не може да бъде отвор #, c-format msgid "Could not get settings from frontend device \"%s\"." -msgstr "Не могат да бъдат получени настройките от устройството „%s“." +msgstr "Настройките на устройството „%s“ не могат да бъдат получени." #, c-format msgid "Could not open file \"%s\" for reading." -msgstr "Файлът „%s“ не може да бъде отворен за четене." - -#~ msgid "%s %d" -#~ msgstr "%s %d" - -#~ msgid "Internal clock error." -#~ msgstr "Вътрешна грешка в часовника." +msgstr "Файлът „%s“ не може да се отвори за четене." diff --git a/po/ca.po b/po/ca.po index 2e8aa2a23f..f47593fefd 100644 --- a/po/ca.po +++ b/po/ca.po @@ -1,31 +1,31 @@ -# Catalan translation for GStreamer. -# Copyright © 2004 Free Software Foundation, Inc. -# This file is distributed under the same licence as the gst-plugins package. -# Jordi Mallach , 2004. +# Catalan translation for gst-plugins-bad. +# Copyright © 2004, 2005, 2010 Free Software Foundation, Inc. +# This file is distributed under the same licence as the gst-plugins-bad package. +# Jordi Mallach , 2004, 2005, 2010. # msgid "" msgstr "" -"Project-Id-Version: gst-plugins 0.8.3\n" +"Project-Id-Version: gst-plugins-bad 0.10.18.2\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" -"POT-Creation-Date: 2010-10-19 23:33+0100\n" -"PO-Revision-Date: 2004-08-05 15:48+0200\n" +"POT-Creation-Date: 2011-01-07 20:26+0000\n" +"PO-Revision-Date: 2010-11-04 21:02+0100\n" "Last-Translator: Jordi Mallach \n" "Language-Team: Catalan \n" "Language: ca\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n!=1;\n" -#, fuzzy msgid "Could not read title information for DVD." -msgstr "No s'ha pogut escriure al fitxer «%s»." +msgstr "No s'ha pogut llegir la informació del títol del DVD." -#, fuzzy, c-format +#, c-format msgid "Failed to open DVD device '%s'." -msgstr "No s'ha pogut tancar el dispositiu de control «%s»." +msgstr "No s'ha pogut obrir el dispositiu de DVD «%s»." msgid "Failed to set PGC based seeking." -msgstr "" +msgstr "No s'ha pogut establir la cerca basada en PGC." msgid "" "Could not read DVD. This may be because the DVD is encrypted and a DVD " @@ -34,185 +34,37 @@ msgstr "" #, fuzzy msgid "Could not read DVD." -msgstr "No s'ha pogut escriure al fitxer «%s»." +msgstr "No s'ha pogut llegir la informació del títol del DVD." -#, fuzzy msgid "No file name specified for writing." -msgstr "No s'ha especificat cap nom de fitxer." +msgstr "No s'ha especificat cap nom de fitxer per a l'escriptura." #, c-format msgid "Could not open file \"%s\" for writing." -msgstr "No s'ha pogut obrir el fitxer «%s» per a l'escriptura." +msgstr "No s'ha pogut obrir «%s» per a l'escriptura." msgid "Internal data stream error." -msgstr "" +msgstr "S'ha produït un error intern de flux de dades." #, c-format msgid "Could not write to file \"%s\"." msgstr "No s'ha pogut escriure al fitxer «%s»." msgid "Internal data flow error." -msgstr "" +msgstr "S'ha produït un error intern de flux de dades." #, c-format msgid "Device \"%s\" does not exist." msgstr "El dispositiu «%s» no existeix." -#, fuzzy, c-format +#, c-format msgid "Could not open frontend device \"%s\"." -msgstr "No s'ha pogut tancar el dispositiu de control «%s»." +msgstr "No s'ha pogut crear el dispositiu frontal «%s»." -#, fuzzy, c-format +#, c-format msgid "Could not get settings from frontend device \"%s\"." -msgstr "No s'han pogut obtenir búfers suficients del dispositiu «%s»." +msgstr "No s'ha pogut obtenir els paràmetres des del dispositiu frontal «%s»." #, c-format msgid "Could not open file \"%s\" for reading." msgstr "No s'ha pogut obrir el fitxer «%s» per a la lectura." - -#, fuzzy -#~ msgid "PCM 1" -#~ msgstr "PCM" - -#, fuzzy -#~ msgid "PCM 2" -#~ msgstr "PCM-2" - -#, fuzzy -#~ msgid "PCM 3" -#~ msgstr "PCM" - -#, fuzzy -#~ msgid "PCM 4" -#~ msgstr "PCM" - -#~ msgid "Error closing file \"%s\"." -#~ msgstr "S'ha produït un error en tancar el fitxer «%s»." - -#~ msgid "Could not open CD device for reading." -#~ msgstr "No s'ha pogut obrir el dispositiu de CD per a la lectura." - -#~ msgid "Could not open vfs file \"%s\" for reading." -#~ msgstr "No s'ha pogut obrir el fitxer vfs «%s» per a la lectura." - -#~ msgid "Could not open vfs file \"%s\" for writing: %s." -#~ msgstr "No s'ha pogut obrir el fitxer vfs «%s» per a l'escriptura: %s." - -#~ msgid "No filename given" -#~ msgstr "No s'ha donat cap nom de fitxer" - -#~ msgid "Could not close vfs file \"%s\"." -#~ msgstr "No s'ha pogut tancar el fitxer vfs «%s»." - -#~ msgid "No or invalid input audio, AVI stream will be corrupt." -#~ msgstr "" -#~ "L'entrada d'àudio no existeix o és invàlida, el flux AVI serà corrupte." - -#~ msgid "" -#~ "The %s element could not be found. This element is essential for " -#~ "playback. Please install the right plug-in and verify that it works by " -#~ "running 'gst-inspect %s'" -#~ msgstr "" -#~ "No s'ha pogut trobar l'element %s. Aquest element és essencial per a la " -#~ "reproducció. Si us plau, instal·leu el connector adequat i verifiqueu que " -#~ "funciona correctament executant «gst-inspect %s»" - -#~ msgid "" -#~ "No usable colorspace element could be found.\n" -#~ "Please install one and restart." -#~ msgstr "" -#~ "No s'ha trobat cap element d'espai de color utilitzable.\n" -#~ "Si us plau, instal·leu un i reinicieu." - -#~ msgid "Could not open control device \"%s\" for writing." -#~ msgstr "" -#~ "No s'ha pogut obrir el dispositiu de control «%s» per a l'escriptura." - -#~ msgid "Could not configure audio device \"%s\"." -#~ msgstr "No s'ha pogut configurar el dispositiu d'àudio «%s»." - -#~ msgid "Could not set audio device \"%s\" to %d Hz." -#~ msgstr "No s'ha pogut establir el dispositiu d'àudio «%s» a %d Hz." - -#~ msgid "Could not close audio device \"%s\"." -#~ msgstr "No s'ha pogut tancar el dispositiu d'àudio «%s»." - -#~ msgid "Could not open video device \"%s\" for writing." -#~ msgstr "No s'ha pogut obrir el dispositiu de vídeo «%s» per a l'escriptura." - -#~ msgid "Could not close video device \"%s\"." -#~ msgstr "No s'ha pogut tancar el dispositiu de vídeo «%s»." - -#~ msgid "Could not write to device \"%s\"." -#~ msgstr "No s'ha pogut escriure al dispositiu «%s»." - -#~ msgid "OSS device \"%s\" is already in use by another program." -#~ msgstr "El dispositiu OSS «%s» ja està en ús per un altre programa." - -#~ msgid "Could not access device \"%s\", check its permissions." -#~ msgstr "" -#~ "No s'ha pogut accedir al dispositiu «%s», comproveu els seus permisos." - -#~ msgid "Could not open device \"%s\" for writing." -#~ msgstr "No s'ha pogut obrir el dispositiu «%s» per a l'escriptura." - -#~ msgid "Could not open device \"%s\" for reading." -#~ msgstr "No s'ha pogut obrir el dispositiu «%s» per a la lectura." - -#~ msgid "Your OSS device could not be probed correctly" -#~ msgstr "No s'ha pogut detectar el vostre dispositiu d'OSS correctament" - -#~ msgid "Synth" -#~ msgstr "Sintetitzador" - -#~ msgid "CD" -#~ msgstr "CD" - -#~ msgid "Mixer" -#~ msgstr "Mesclador" - -#~ msgid "In-gain" -#~ msgstr "Ganància-entrada" - -#~ msgid "Line-1" -#~ msgstr "Línia-1" - -#~ msgid "Line-2" -#~ msgstr "Línia-2" - -#~ msgid "Line-3" -#~ msgstr "Línia-3" - -#~ msgid "Digital-2" -#~ msgstr "Digital-2" - -#~ msgid "Digital-3" -#~ msgstr "Digital-3" - -#~ msgid "Phone-in" -#~ msgstr "Telèfon-entrada" - -#~ msgid "Phone-out" -#~ msgstr "Telèfon-sortida" - -#~ msgid "Radio" -#~ msgstr "Ràdio" - -#~ msgid "No device specified." -#~ msgstr "No s'ha especificat cap dispositiu." - -#~ msgid "Could not open device \"%s\" for reading and writing." -#~ msgstr "" -#~ "No s'ha pogut obrir el dispositiu «%s» per a l'escriptura i lectura." - -#~ msgid "Device is not open." -#~ msgstr "El dispositiu no està obert." - -#~ msgid "Device is open." -#~ msgstr "El dispositiu està obert." - -#~ msgid "Device \"%s\" is not a capture device." -#~ msgstr "El dispositiu «%s» no és un dispositiu de captura." - -#~ msgid "Could not get buffers from device \"%s\"." -#~ msgstr "No s'han pogut obtenir els búfers del dispositiu «%s»." diff --git a/po/ja.po b/po/ja.po index 6df29da905..878d34b242 100644 --- a/po/ja.po +++ b/po/ja.po @@ -1,13 +1,13 @@ # Japanese traslation for gst-plugins-bad # This file is put in the public domain. # -# Makoto Kato , 2009. +# Makoto Kato , 2009-2010. msgid "" msgstr "" -"Project-Id-Version: gst-plugins-bad 0.10.11.2\n" +"Project-Id-Version: gst-plugins-bad 0.10.18.2\n" "Report-Msgid-Bugs-To: http://bugzilla.gnome.org/\n" -"POT-Creation-Date: 2010-10-19 23:33+0100\n" -"PO-Revision-Date: 2009-06-01 20:27+0900\n" +"POT-Creation-Date: 2011-01-07 20:26+0000\n" +"PO-Revision-Date: 2010-10-26 16:31+0900\n" "Last-Translator: Makoto Kato \n" "Language-Team: Japanese \n" "Language: ja\n" @@ -25,7 +25,7 @@ msgid "Failed to open DVD device '%s'." msgstr "DVD デバイス '%s' のオープンに失敗しました" msgid "Failed to set PGC based seeking." -msgstr "" +msgstr "PGCを利用したシークに失敗しました。" msgid "" "Could not read DVD. This may be because the DVD is encrypted and a DVD " @@ -72,6 +72,61 @@ msgstr "読み込み用にファイル \"%s\" を開くことができません #~ msgid "Internal clock error." #~ msgstr "内部クロックエラー" +#~ msgid "Could not open audio device for mixer control handling." +#~ msgstr "" +#~ "ミキサーがコントロールするオーディオデバイスを開くことができません。" + +#~ msgid "Low" +#~ msgstr "低音" + +#~ msgid "Medium" +#~ msgstr "中音" + +#~ msgid "High" +#~ msgstr "高音" + +#~ msgid "Production" +#~ msgstr "プロダクション" + +#~ msgid "Off" +#~ msgstr "Off" + +#~ msgid "On" +#~ msgstr "On" + +#~ msgid "Stereo" +#~ msgstr "ステレオ" + +#~ msgid "Surround sound" +#~ msgstr "サラウンドサウンド" + +#~ msgid "Input mix" +#~ msgstr "入力ミックス" + +#~ msgid "Front" +#~ msgstr "フロント" + +#~ msgid "Rear" +#~ msgstr "リア" + +#~ msgid "Side" +#~ msgstr "サイド" + +#~ msgid "Center / LFE" +#~ msgstr "センター / LFE" + +#~ msgid "Microphone" +#~ msgstr "マイクロフォン" + +#~ msgid "Front panel microphone" +#~ msgstr "フロントパネルのマイクロフォン" + +#~ msgid "Input" +#~ msgstr "入力" + +#~ msgid "Line-in" +#~ msgstr "ライン入力" + #~ msgid "PCM 1" #~ msgstr "PCM 1" @@ -84,12 +139,99 @@ msgstr "読み込み用にファイル \"%s\" を開くことができません #~ msgid "PCM 4" #~ msgstr "PCM 4" +#~ msgid "Green connector" +#~ msgstr "緑色コネクタ" + +#~ msgid "Green front panel connector" +#~ msgstr "緑色のフロントパネルのコネクタ" + +#~ msgid "Pink connector" +#~ msgstr "ピンク色コネクタ" + +#~ msgid "Pink front panel connector" +#~ msgstr "ピンク色のフロントパネルコネクタ" + +#~ msgid "Blue connector" +#~ msgstr "青色コネクタ" + +#~ msgid "Orange connector" +#~ msgstr "オレンジ色コネクタ" + +#~ msgid "Black connector" +#~ msgstr "黒色コネクタ" + +#~ msgid "Gray connector" +#~ msgstr "グレー色コネクタ" + +#~ msgid "White connector" +#~ msgstr "白色コネクタ" + +#~ msgid "Red connector" +#~ msgstr "赤色コネクタ" + +#~ msgid "Yellow connector" +#~ msgstr "黄色コネクタ" + #~ msgid "Green connector function" #~ msgstr "緑色コネクタ機能" +#~ msgid "Front panel line-in" +#~ msgstr "プロントパネルのライン入力" + +#~ msgid "Headphones" +#~ msgstr "ヘッドフォン" + +#~ msgid "Front panel headphones" +#~ msgstr "フロントパネルのヘッドフォン" + +#~ msgid "PCM" +#~ msgstr "PCM" + +#~ msgid "Virtual mixer input" +#~ msgstr "仮想ミキサー入力" + +#~ msgid "Virtual mixer output" +#~ msgstr "仮想ミキサー出力" + #~ msgid "Virtual mixer channel configuration" #~ msgstr "仮想ミックスチャンネル設定" +#~ msgid "" +#~ "Could not open audio device for playback. Device is being used by another " +#~ "application." +#~ msgstr "" +#~ "プレイバック用にオーディオデバイスを開くことができませんでした。デバイスは" +#~ "他のアプリケーションによって使われています。" + +#~ msgid "" +#~ "Could not open audio device for playback. You don't have permission to " +#~ "open the device." +#~ msgstr "" +#~ "プレイバック用にオーディオデバイスを開くことができませんでした。デバイスを" +#~ "開くための権限を持っていません。" + +#~ msgid "Could not open audio device for playback." +#~ msgstr "プレイバック用にオーディオデバイスを開くことができませんでした。" + +#~ msgid "" +#~ "Could not open audio device for playback. This version of the Open Sound " +#~ "System is not supported by this element." +#~ msgstr "" +#~ "プレイバック用にオーディオデバイスを開くことができませんでした。この Open " +#~ "Sound System のバージョンはこのエレメントによってサポートされません。" + +#~ msgid "Playback is not supported by this audio device." +#~ msgstr "プレイバックはこのオーディオデバイスによってサポートされません。" + +#~ msgid "Audio playback error." +#~ msgstr "オーディオプレイバックエラー" + +#~ msgid "Recording is not supported by this audio device." +#~ msgstr "録音はこのオーディオデバイスによってサポートされません。" + +#~ msgid "Error recording from audio device." +#~ msgstr "オーディオデバイスからの録音時にエラーが発生しました。" + #~ msgid "Failed to configure TwoLAME encoder. Check your encoding parameters." #~ msgstr "" #~ "TwoLAME エンコーダーの構成に失敗しました。エンコーディングパラメータを" From c0a108012ed2317ee82b7b2490ff66c50eed84ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Sat, 8 Jan 2011 02:49:06 +0000 Subject: [PATCH 281/448] docs: update docs --- docs/plugins/gst-plugins-bad-plugins.args | 80 +++++++++++++++---- .../plugins/gst-plugins-bad-plugins.hierarchy | 2 + docs/plugins/inspect/plugin-adpcmdec.xml | 4 +- docs/plugins/inspect/plugin-adpcmenc.xml | 4 +- docs/plugins/inspect/plugin-aiff.xml | 4 +- docs/plugins/inspect/plugin-amrwbenc.xml | 4 +- docs/plugins/inspect/plugin-apexsink.xml | 4 +- docs/plugins/inspect/plugin-asfmux.xml | 4 +- docs/plugins/inspect/plugin-assrender.xml | 4 +- .../inspect/plugin-audioparsersbad.xml | 4 +- docs/plugins/inspect/plugin-autoconvert.xml | 4 +- docs/plugins/inspect/plugin-bayer.xml | 4 +- docs/plugins/inspect/plugin-bz2.xml | 4 +- docs/plugins/inspect/plugin-camerabin.xml | 4 +- docs/plugins/inspect/plugin-cdaudio.xml | 4 +- docs/plugins/inspect/plugin-cdxaparse.xml | 4 +- docs/plugins/inspect/plugin-celt.xml | 4 +- docs/plugins/inspect/plugin-cog.xml | 4 +- docs/plugins/inspect/plugin-coloreffects.xml | 4 +- docs/plugins/inspect/plugin-colorspace.xml | 2 +- docs/plugins/inspect/plugin-dataurisrc.xml | 4 +- docs/plugins/inspect/plugin-dc1394.xml | 4 +- docs/plugins/inspect/plugin-dccp.xml | 2 +- docs/plugins/inspect/plugin-debugutilsbad.xml | 4 +- docs/plugins/inspect/plugin-dfbvideosink.xml | 4 +- docs/plugins/inspect/plugin-dirac.xml | 4 +- docs/plugins/inspect/plugin-dtmf.xml | 4 +- docs/plugins/inspect/plugin-dtsdec.xml | 4 +- docs/plugins/inspect/plugin-dvb.xml | 4 +- docs/plugins/inspect/plugin-dvbsuboverlay.xml | 4 +- docs/plugins/inspect/plugin-dvdspu.xml | 4 +- docs/plugins/inspect/plugin-faac.xml | 4 +- docs/plugins/inspect/plugin-faad.xml | 4 +- docs/plugins/inspect/plugin-fbdevsink.xml | 4 +- docs/plugins/inspect/plugin-festival.xml | 4 +- docs/plugins/inspect/plugin-freeze.xml | 4 +- docs/plugins/inspect/plugin-frei0r.xml | 4 +- docs/plugins/inspect/plugin-gaudieffects.xml | 2 +- .../inspect/plugin-geometrictransform.xml | 4 +- docs/plugins/inspect/plugin-gsettings.xml | 4 +- docs/plugins/inspect/plugin-gsm.xml | 4 +- docs/plugins/inspect/plugin-gstsiren.xml | 4 +- docs/plugins/inspect/plugin-h264parse.xml | 4 +- docs/plugins/inspect/plugin-hdvparse.xml | 2 +- docs/plugins/inspect/plugin-id3tag.xml | 4 +- docs/plugins/inspect/plugin-interlace.xml | 4 +- docs/plugins/inspect/plugin-invtelecine.xml | 4 +- docs/plugins/inspect/plugin-ivfparse.xml | 4 +- docs/plugins/inspect/plugin-jp2kdecimator.xml | 4 +- docs/plugins/inspect/plugin-jpegformat.xml | 4 +- docs/plugins/inspect/plugin-kate.xml | 4 +- docs/plugins/inspect/plugin-ladspa.xml | 4 +- .../plugins/inspect/plugin-legacyresample.xml | 4 +- docs/plugins/inspect/plugin-liveadder.xml | 4 +- docs/plugins/inspect/plugin-mimic.xml | 4 +- docs/plugins/inspect/plugin-mms.xml | 4 +- docs/plugins/inspect/plugin-modplug.xml | 4 +- docs/plugins/inspect/plugin-mpeg2enc.xml | 4 +- .../inspect/plugin-mpeg4videoparse.xml | 4 +- docs/plugins/inspect/plugin-mpegdemux2.xml | 4 +- docs/plugins/inspect/plugin-mpegpsmux.xml | 4 +- docs/plugins/inspect/plugin-mpegtsmux.xml | 4 +- .../plugins/inspect/plugin-mpegvideoparse.xml | 4 +- docs/plugins/inspect/plugin-mplex.xml | 4 +- docs/plugins/inspect/plugin-musepack.xml | 4 +- docs/plugins/inspect/plugin-musicbrainz.xml | 4 +- docs/plugins/inspect/plugin-mve.xml | 4 +- docs/plugins/inspect/plugin-mxf.xml | 4 +- docs/plugins/inspect/plugin-mythtv.xml | 4 +- docs/plugins/inspect/plugin-nas.xml | 4 +- docs/plugins/inspect/plugin-neon.xml | 4 +- docs/plugins/inspect/plugin-nsf.xml | 4 +- docs/plugins/inspect/plugin-nuvdemux.xml | 4 +- docs/plugins/inspect/plugin-ofa.xml | 4 +- docs/plugins/inspect/plugin-opencv.xml | 4 +- docs/plugins/inspect/plugin-pcapparse.xml | 2 +- docs/plugins/inspect/plugin-pnm.xml | 4 +- docs/plugins/inspect/plugin-qtmux.xml | 4 +- docs/plugins/inspect/plugin-rawparse.xml | 4 +- docs/plugins/inspect/plugin-real.xml | 4 +- docs/plugins/inspect/plugin-resindvd.xml | 2 +- docs/plugins/inspect/plugin-rfbsrc.xml | 4 +- docs/plugins/inspect/plugin-rsvg.xml | 4 +- docs/plugins/inspect/plugin-rtpmux.xml | 4 +- docs/plugins/inspect/plugin-scaletempo.xml | 2 +- docs/plugins/inspect/plugin-schro.xml | 4 +- docs/plugins/inspect/plugin-sdl.xml | 4 +- docs/plugins/inspect/plugin-sdp.xml | 4 +- docs/plugins/inspect/plugin-segmentclip.xml | 4 +- docs/plugins/inspect/plugin-shm.xml | 4 +- docs/plugins/inspect/plugin-sndfile.xml | 4 +- docs/plugins/inspect/plugin-soundtouch.xml | 4 +- docs/plugins/inspect/plugin-speed.xml | 4 +- docs/plugins/inspect/plugin-stereo.xml | 4 +- docs/plugins/inspect/plugin-subenc.xml | 4 +- docs/plugins/inspect/plugin-tta.xml | 4 +- docs/plugins/inspect/plugin-vcdsrc.xml | 4 +- docs/plugins/inspect/plugin-vdpau.xml | 2 +- docs/plugins/inspect/plugin-videomaxrate.xml | 4 +- docs/plugins/inspect/plugin-videomeasure.xml | 4 +- docs/plugins/inspect/plugin-videosignal.xml | 4 +- docs/plugins/inspect/plugin-vmnc.xml | 4 +- docs/plugins/inspect/plugin-vp8.xml | 4 +- docs/plugins/inspect/plugin-wildmidi.xml | 4 +- docs/plugins/inspect/plugin-xvid.xml | 4 +- docs/plugins/inspect/plugin-y4mdec.xml | 2 +- docs/plugins/inspect/plugin-zbar.xml | 4 +- 107 files changed, 268 insertions(+), 216 deletions(-) diff --git a/docs/plugins/gst-plugins-bad-plugins.args b/docs/plugins/gst-plugins-bad-plugins.args index 8ca527f247..31494f8daa 100644 --- a/docs/plugins/gst-plugins-bad-plugins.args +++ b/docs/plugins/gst-plugins-bad-plugins.args @@ -22473,6 +22473,16 @@ 0
+ +GstMJ2Mux::dts-method +GstQTMuxDtsMethods + +rwx +dts-method +Method to determine DTS time. +delta/duration + + GstGPPMux::faststart gboolean @@ -22563,6 +22573,16 @@ 0 + +GstGPPMux::dts-method +GstQTMuxDtsMethods + +rwx +dts-method +Method to determine DTS time. +delta/duration + + GstMP4Mux::faststart gboolean @@ -22653,6 +22673,16 @@ 0 + +GstMP4Mux::dts-method +GstQTMuxDtsMethods + +rwx +dts-method +Method to determine DTS time. +delta/duration + + GstQTMux::faststart gboolean @@ -22743,6 +22773,16 @@ 0 + +GstQTMux::dts-method +GstQTMuxDtsMethods + +rwx +dts-method +Method to determine DTS time. +delta/duration + + GstAudioresample::filter-length gint @@ -26470,7 +26510,7 @@ rw physics water density: from 1 to 4. -8.09774e-321 +4.63015e-299 @@ -26510,7 +26550,7 @@ rw splash make a big splash in the center. -2.34994e-310 +4.62958e-299 @@ -26520,7 +26560,7 @@ rw splash make a big splash in the center. -1.82574e-315 +4.63015e-299 @@ -26550,7 +26590,7 @@ rw ratiox x-ratio. -1.47273e-316 +0 @@ -26560,7 +26600,7 @@ rw ratioy y-ratio. -1.85891e-316 +0 @@ -26570,7 +26610,7 @@ rw DelayTime the delay time. -2.18476e-316 +0 @@ -26600,7 +26640,7 @@ rw Color the color of the image. -1.39669e-37 +0 @@ -26620,7 +26660,7 @@ rw Color-R the color of the image. -7.30424e-38 +0 @@ -26950,7 +26990,7 @@ rw lredscale multiplier for downscaling non-edge brightness. -3.40216e-111 +0 @@ -26960,7 +27000,7 @@ rw lthresh threshold for edge lightening. -6.9235e+228 +0 @@ -26970,7 +27010,7 @@ rw lupscale multiplier for upscaling edge brightness. -7.54985e-96 +0 @@ -27140,7 +27180,7 @@ rw blend blend factor. -4.77773e-299 +4.74303e-322 @@ -27330,7 +27370,7 @@ rw HSync the hsync offset. -1.86264e-09 +2.98023e-08 @@ -27680,7 +27720,7 @@ rwx Default font effect Whether to apply an effect to text by default, for increased readability. -none +outline @@ -45906,7 +45946,7 @@ GstVideoMaxRate::average-period guint64 -[1,G_MAXINT64] +[1,G_MAXLONG] rw Period over which to average Period over which to average the framerate (in ns). @@ -46863,6 +46903,16 @@ 0 + +GstISMLMux::dts-method +GstQTMuxDtsMethods + +rwx +dts-method +Method to determine DTS time. +delta/duration + + GstChopMyData::max-size gint diff --git a/docs/plugins/gst-plugins-bad-plugins.hierarchy b/docs/plugins/gst-plugins-bad-plugins.hierarchy index 84322e7d5a..c711d8d42d 100644 --- a/docs/plugins/gst-plugins-bad-plugins.hierarchy +++ b/docs/plugins/gst-plugins-bad-plugins.hierarchy @@ -1,5 +1,7 @@ GObject GstColorBalanceChannel + GstMixerTrack + GstMixerOptions GstObject GstBus GstClock diff --git a/docs/plugins/inspect/plugin-adpcmdec.xml b/docs/plugins/inspect/plugin-adpcmdec.xml index d54ade1e28..586a3da56a 100644 --- a/docs/plugins/inspect/plugin-adpcmdec.xml +++ b/docs/plugins/inspect/plugin-adpcmdec.xml @@ -3,10 +3,10 @@ ADPCM decoder ../../gst/adpcmdec/.libs/libgstadpcmdec.so libgstadpcmdec.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-adpcmenc.xml b/docs/plugins/inspect/plugin-adpcmenc.xml index 0fc939eea6..9aa84e5242 100644 --- a/docs/plugins/inspect/plugin-adpcmenc.xml +++ b/docs/plugins/inspect/plugin-adpcmenc.xml @@ -3,10 +3,10 @@ ADPCM encoder ../../gst/adpcmenc/.libs/libgstadpcmenc.so libgstadpcmenc.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-aiff.xml b/docs/plugins/inspect/plugin-aiff.xml index a8c33c11d9..c63a3de8ca 100644 --- a/docs/plugins/inspect/plugin-aiff.xml +++ b/docs/plugins/inspect/plugin-aiff.xml @@ -3,10 +3,10 @@ Create and parse Audio Interchange File Format (AIFF) files ../../gst/aiff/.libs/libgstaiff.so libgstaiff.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-amrwbenc.xml b/docs/plugins/inspect/plugin-amrwbenc.xml index 27fefc0a7e..bc96b0e1b3 100644 --- a/docs/plugins/inspect/plugin-amrwbenc.xml +++ b/docs/plugins/inspect/plugin-amrwbenc.xml @@ -3,10 +3,10 @@ Adaptive Multi-Rate Wide-Band Encoder ../../ext/amrwbenc/.libs/libgstamrwbenc.so libgstamrwbenc.so - 0.10.20.1 + 0.10.20.2 unknown gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-apexsink.xml b/docs/plugins/inspect/plugin-apexsink.xml index ab3db8a88b..f4fb729a75 100644 --- a/docs/plugins/inspect/plugin-apexsink.xml +++ b/docs/plugins/inspect/plugin-apexsink.xml @@ -3,10 +3,10 @@ Apple AirPort Express Plugin ../../ext/apexsink/.libs/libgstapexsink.so libgstapexsink.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-asfmux.xml b/docs/plugins/inspect/plugin-asfmux.xml index 1e68b3fd93..fdbcbfcef3 100644 --- a/docs/plugins/inspect/plugin-asfmux.xml +++ b/docs/plugins/inspect/plugin-asfmux.xml @@ -3,10 +3,10 @@ ASF Muxer Plugin ../../gst/asfmux/.libs/libgstasfmux.so libgstasfmux.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-assrender.xml b/docs/plugins/inspect/plugin-assrender.xml index 1165483594..4d59f26226 100644 --- a/docs/plugins/inspect/plugin-assrender.xml +++ b/docs/plugins/inspect/plugin-assrender.xml @@ -3,10 +3,10 @@ ASS/SSA subtitle renderer ../../ext/assrender/.libs/libgstassrender.so libgstassrender.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-audioparsersbad.xml b/docs/plugins/inspect/plugin-audioparsersbad.xml index f308eaf6b9..2bbf5c585f 100644 --- a/docs/plugins/inspect/plugin-audioparsersbad.xml +++ b/docs/plugins/inspect/plugin-audioparsersbad.xml @@ -3,10 +3,10 @@ audioparsers ../../gst/audioparsers/.libs/libgstaudioparsersbad.so libgstaudioparsersbad.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-autoconvert.xml b/docs/plugins/inspect/plugin-autoconvert.xml index a0244845a6..fb91f17afd 100644 --- a/docs/plugins/inspect/plugin-autoconvert.xml +++ b/docs/plugins/inspect/plugin-autoconvert.xml @@ -3,10 +3,10 @@ Selects convertor element based on caps ../../gst/autoconvert/.libs/libgstautoconvert.so libgstautoconvert.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-bayer.xml b/docs/plugins/inspect/plugin-bayer.xml index fb6292bb34..799434e135 100644 --- a/docs/plugins/inspect/plugin-bayer.xml +++ b/docs/plugins/inspect/plugin-bayer.xml @@ -3,10 +3,10 @@ Elements to convert Bayer images ../../gst/bayer/.libs/libgstbayer.so libgstbayer.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-bz2.xml b/docs/plugins/inspect/plugin-bz2.xml index b07dc7a38e..afe2d89ca7 100644 --- a/docs/plugins/inspect/plugin-bz2.xml +++ b/docs/plugins/inspect/plugin-bz2.xml @@ -3,10 +3,10 @@ Compress or decompress streams ../../ext/bz2/.libs/libgstbz2.so libgstbz2.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-camerabin.xml b/docs/plugins/inspect/plugin-camerabin.xml index 0609afa404..0b14bf8e3c 100644 --- a/docs/plugins/inspect/plugin-camerabin.xml +++ b/docs/plugins/inspect/plugin-camerabin.xml @@ -3,10 +3,10 @@ High level api for DC (Digital Camera) application ../../gst/camerabin/.libs/libgstcamerabin.so libgstcamerabin.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-cdaudio.xml b/docs/plugins/inspect/plugin-cdaudio.xml index 86ed0c8d89..89c266b2b5 100644 --- a/docs/plugins/inspect/plugin-cdaudio.xml +++ b/docs/plugins/inspect/plugin-cdaudio.xml @@ -3,10 +3,10 @@ Play CD audio through the CD Drive ../../ext/cdaudio/.libs/libgstcdaudio.so libgstcdaudio.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-cdxaparse.xml b/docs/plugins/inspect/plugin-cdxaparse.xml index b8e4da81fe..fbf9810ad5 100644 --- a/docs/plugins/inspect/plugin-cdxaparse.xml +++ b/docs/plugins/inspect/plugin-cdxaparse.xml @@ -3,10 +3,10 @@ Parse a .dat file (VCD) into raw mpeg1 ../../gst/cdxaparse/.libs/libgstcdxaparse.so libgstcdxaparse.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-celt.xml b/docs/plugins/inspect/plugin-celt.xml index 8cee667464..17c19db00a 100644 --- a/docs/plugins/inspect/plugin-celt.xml +++ b/docs/plugins/inspect/plugin-celt.xml @@ -3,10 +3,10 @@ CELT plugin library ../../ext/celt/.libs/libgstcelt.so libgstcelt.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-cog.xml b/docs/plugins/inspect/plugin-cog.xml index 6271670028..d3b0db0fd7 100644 --- a/docs/plugins/inspect/plugin-cog.xml +++ b/docs/plugins/inspect/plugin-cog.xml @@ -3,10 +3,10 @@ Cog plugin ../../ext/cog/.libs/libgstcog.so libgstcog.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-coloreffects.xml b/docs/plugins/inspect/plugin-coloreffects.xml index 3f5b92b35e..105681fc33 100644 --- a/docs/plugins/inspect/plugin-coloreffects.xml +++ b/docs/plugins/inspect/plugin-coloreffects.xml @@ -3,10 +3,10 @@ Color Look-up Table filters ../../gst/coloreffects/.libs/libgstcoloreffects.so libgstcoloreffects.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-colorspace.xml b/docs/plugins/inspect/plugin-colorspace.xml index b0b3602d97..cf27b95a17 100644 --- a/docs/plugins/inspect/plugin-colorspace.xml +++ b/docs/plugins/inspect/plugin-colorspace.xml @@ -3,7 +3,7 @@ Colorspace conversion ../../gst/colorspace/.libs/libgstcolorspace.so libgstcolorspace.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad diff --git a/docs/plugins/inspect/plugin-dataurisrc.xml b/docs/plugins/inspect/plugin-dataurisrc.xml index 1ae558bdf4..cef7e17148 100644 --- a/docs/plugins/inspect/plugin-dataurisrc.xml +++ b/docs/plugins/inspect/plugin-dataurisrc.xml @@ -3,10 +3,10 @@ data: URI source ../../gst/dataurisrc/.libs/libgstdataurisrc.so libgstdataurisrc.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-dc1394.xml b/docs/plugins/inspect/plugin-dc1394.xml index cae9bfd916..3ba7e8dc59 100644 --- a/docs/plugins/inspect/plugin-dc1394.xml +++ b/docs/plugins/inspect/plugin-dc1394.xml @@ -3,10 +3,10 @@ 1394 IIDC Video Source ../../ext/dc1394/.libs/libgstdc1394.so libgstdc1394.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-dccp.xml b/docs/plugins/inspect/plugin-dccp.xml index 4972b5e220..0beb68df81 100644 --- a/docs/plugins/inspect/plugin-dccp.xml +++ b/docs/plugins/inspect/plugin-dccp.xml @@ -3,7 +3,7 @@ transfer data over the network via DCCP. ../../gst/dccp/.libs/libgstdccp.so libgstdccp.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad DCCP diff --git a/docs/plugins/inspect/plugin-debugutilsbad.xml b/docs/plugins/inspect/plugin-debugutilsbad.xml index 4ddb78e618..7400471c8c 100644 --- a/docs/plugins/inspect/plugin-debugutilsbad.xml +++ b/docs/plugins/inspect/plugin-debugutilsbad.xml @@ -3,10 +3,10 @@ Collection of elements that may or may not be useful for debugging ../../gst/debugutils/.libs/libgstdebugutilsbad.so libgstdebugutilsbad.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-dfbvideosink.xml b/docs/plugins/inspect/plugin-dfbvideosink.xml index 5c144291c8..e04d4e8680 100644 --- a/docs/plugins/inspect/plugin-dfbvideosink.xml +++ b/docs/plugins/inspect/plugin-dfbvideosink.xml @@ -3,10 +3,10 @@ DirectFB video output plugin ../../ext/directfb/.libs/libgstdfbvideosink.so libgstdfbvideosink.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-dirac.xml b/docs/plugins/inspect/plugin-dirac.xml index 802141c471..f03944b474 100644 --- a/docs/plugins/inspect/plugin-dirac.xml +++ b/docs/plugins/inspect/plugin-dirac.xml @@ -3,10 +3,10 @@ Dirac plugin ../../ext/dirac/.libs/libgstdirac.so libgstdirac.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-dtmf.xml b/docs/plugins/inspect/plugin-dtmf.xml index 92e5c83a4e..d84ca27992 100644 --- a/docs/plugins/inspect/plugin-dtmf.xml +++ b/docs/plugins/inspect/plugin-dtmf.xml @@ -3,10 +3,10 @@ DTMF plugins ../../gst/dtmf/.libs/libgstdtmf.so libgstdtmf.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-dtsdec.xml b/docs/plugins/inspect/plugin-dtsdec.xml index 82668fe7f6..926a1cb78c 100644 --- a/docs/plugins/inspect/plugin-dtsdec.xml +++ b/docs/plugins/inspect/plugin-dtsdec.xml @@ -3,10 +3,10 @@ Decodes DTS audio streams ../../ext/dts/.libs/libgstdtsdec.so libgstdtsdec.so - 0.10.20.1 + 0.10.20.2 GPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-dvb.xml b/docs/plugins/inspect/plugin-dvb.xml index 5042cff9bc..08474d6354 100644 --- a/docs/plugins/inspect/plugin-dvb.xml +++ b/docs/plugins/inspect/plugin-dvb.xml @@ -3,10 +3,10 @@ DVB elements ../../sys/dvb/.libs/libgstdvb.so libgstdvb.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-dvbsuboverlay.xml b/docs/plugins/inspect/plugin-dvbsuboverlay.xml index f8f2afd6f4..fdec8725eb 100644 --- a/docs/plugins/inspect/plugin-dvbsuboverlay.xml +++ b/docs/plugins/inspect/plugin-dvbsuboverlay.xml @@ -3,10 +3,10 @@ DVB subtitle renderer ../../gst/dvbsuboverlay/.libs/libgstdvbsuboverlay.so libgstdvbsuboverlay.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-dvdspu.xml b/docs/plugins/inspect/plugin-dvdspu.xml index 596f920f58..27168511bb 100644 --- a/docs/plugins/inspect/plugin-dvdspu.xml +++ b/docs/plugins/inspect/plugin-dvdspu.xml @@ -3,10 +3,10 @@ DVD Sub-picture Overlay element ../../gst/dvdspu/.libs/libgstdvdspu.so libgstdvdspu.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-faac.xml b/docs/plugins/inspect/plugin-faac.xml index cadf3d97d8..ffd828e455 100644 --- a/docs/plugins/inspect/plugin-faac.xml +++ b/docs/plugins/inspect/plugin-faac.xml @@ -3,10 +3,10 @@ Free AAC Encoder (FAAC) ../../ext/faac/.libs/libgstfaac.so libgstfaac.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-faad.xml b/docs/plugins/inspect/plugin-faad.xml index 3992320aae..0296d80c87 100644 --- a/docs/plugins/inspect/plugin-faad.xml +++ b/docs/plugins/inspect/plugin-faad.xml @@ -3,10 +3,10 @@ Free AAC Decoder (FAAD) ../../ext/faad/.libs/libgstfaad.so libgstfaad.so - 0.10.20.1 + 0.10.20.2 GPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-fbdevsink.xml b/docs/plugins/inspect/plugin-fbdevsink.xml index cde9fa996a..2d47128fee 100644 --- a/docs/plugins/inspect/plugin-fbdevsink.xml +++ b/docs/plugins/inspect/plugin-fbdevsink.xml @@ -3,10 +3,10 @@ linux framebuffer video sink ../../sys/fbdev/.libs/libgstfbdevsink.so libgstfbdevsink.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-festival.xml b/docs/plugins/inspect/plugin-festival.xml index bad79a660e..7de0f6d015 100644 --- a/docs/plugins/inspect/plugin-festival.xml +++ b/docs/plugins/inspect/plugin-festival.xml @@ -3,10 +3,10 @@ Synthesizes plain text into audio ../../gst/festival/.libs/libgstfestival.so libgstfestival.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-freeze.xml b/docs/plugins/inspect/plugin-freeze.xml index 79609c5e6a..b5b54560ca 100644 --- a/docs/plugins/inspect/plugin-freeze.xml +++ b/docs/plugins/inspect/plugin-freeze.xml @@ -3,10 +3,10 @@ Stream freezer ../../gst/freeze/.libs/libgstfreeze.so libgstfreeze.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-frei0r.xml b/docs/plugins/inspect/plugin-frei0r.xml index a5c89fed56..6b12c78a6f 100644 --- a/docs/plugins/inspect/plugin-frei0r.xml +++ b/docs/plugins/inspect/plugin-frei0r.xml @@ -3,10 +3,10 @@ frei0r plugin library ../../gst/frei0r/.libs/libgstfrei0r.so libgstfrei0r.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-gaudieffects.xml b/docs/plugins/inspect/plugin-gaudieffects.xml index 7a650a9efe..8e20ab4d59 100644 --- a/docs/plugins/inspect/plugin-gaudieffects.xml +++ b/docs/plugins/inspect/plugin-gaudieffects.xml @@ -3,7 +3,7 @@ Gaudi video effects. ../../gst/gaudieffects/.libs/libgstgaudieffects.so libgstgaudieffects.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad GStreamer diff --git a/docs/plugins/inspect/plugin-geometrictransform.xml b/docs/plugins/inspect/plugin-geometrictransform.xml index 1e4c78819c..8595004be1 100644 --- a/docs/plugins/inspect/plugin-geometrictransform.xml +++ b/docs/plugins/inspect/plugin-geometrictransform.xml @@ -3,10 +3,10 @@ Various geometric image transform elements ../../gst/geometrictransform/.libs/libgstgeometrictransform.so libgstgeometrictransform.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-gsettings.xml b/docs/plugins/inspect/plugin-gsettings.xml index 19637c217b..3d8d5561f2 100644 --- a/docs/plugins/inspect/plugin-gsettings.xml +++ b/docs/plugins/inspect/plugin-gsettings.xml @@ -3,10 +3,10 @@ GSettings plugin ../../ext/gsettings/.libs/libgstgsettingselements.so libgstgsettingselements.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-gsm.xml b/docs/plugins/inspect/plugin-gsm.xml index dbc19234e0..390ded1e19 100644 --- a/docs/plugins/inspect/plugin-gsm.xml +++ b/docs/plugins/inspect/plugin-gsm.xml @@ -3,10 +3,10 @@ GSM encoder/decoder ../../ext/gsm/.libs/libgstgsm.so libgstgsm.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-gstsiren.xml b/docs/plugins/inspect/plugin-gstsiren.xml index d8219863c2..1edd584f62 100644 --- a/docs/plugins/inspect/plugin-gstsiren.xml +++ b/docs/plugins/inspect/plugin-gstsiren.xml @@ -3,10 +3,10 @@ Siren encoder/decoder/payloader/depayloader plugins ../../gst/siren/.libs/libgstsiren.so libgstsiren.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-h264parse.xml b/docs/plugins/inspect/plugin-h264parse.xml index 1233f34016..bc58490007 100644 --- a/docs/plugins/inspect/plugin-h264parse.xml +++ b/docs/plugins/inspect/plugin-h264parse.xml @@ -3,10 +3,10 @@ Element parsing raw h264 streams ../../gst/h264parse/.libs/libgsth264parse.so libgsth264parse.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-hdvparse.xml b/docs/plugins/inspect/plugin-hdvparse.xml index 74c445b43e..b18fb3798b 100644 --- a/docs/plugins/inspect/plugin-hdvparse.xml +++ b/docs/plugins/inspect/plugin-hdvparse.xml @@ -3,7 +3,7 @@ HDV private stream parser ../../gst/hdvparse/.libs/libgsthdvparse.so libgsthdvparse.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad GStreamer diff --git a/docs/plugins/inspect/plugin-id3tag.xml b/docs/plugins/inspect/plugin-id3tag.xml index 09dfe550d4..aa3598ef1f 100644 --- a/docs/plugins/inspect/plugin-id3tag.xml +++ b/docs/plugins/inspect/plugin-id3tag.xml @@ -3,10 +3,10 @@ ID3 v1 and v2 muxing plugin ../../gst/id3tag/.libs/libgstid3tag.so libgstid3tag.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-interlace.xml b/docs/plugins/inspect/plugin-interlace.xml index 1691edda69..365d1ff1ed 100644 --- a/docs/plugins/inspect/plugin-interlace.xml +++ b/docs/plugins/inspect/plugin-interlace.xml @@ -3,10 +3,10 @@ Create an interlaced video stream ../../gst/interlace/.libs/libgstinterlace.so libgstinterlace.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-invtelecine.xml b/docs/plugins/inspect/plugin-invtelecine.xml index ea96e0a8c4..d2ab52b4dd 100644 --- a/docs/plugins/inspect/plugin-invtelecine.xml +++ b/docs/plugins/inspect/plugin-invtelecine.xml @@ -3,10 +3,10 @@ Inverse Telecine ../../gst/invtelecine/.libs/libgstinvtelecine.so libgstinvtelecine.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-ivfparse.xml b/docs/plugins/inspect/plugin-ivfparse.xml index a8a93f42e7..dd7da9d28f 100644 --- a/docs/plugins/inspect/plugin-ivfparse.xml +++ b/docs/plugins/inspect/plugin-ivfparse.xml @@ -3,10 +3,10 @@ IVF parser ../../gst/ivfparse/.libs/libgstivfparse.so libgstivfparse.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-jp2kdecimator.xml b/docs/plugins/inspect/plugin-jp2kdecimator.xml index 4a44f21113..2df75c8a34 100644 --- a/docs/plugins/inspect/plugin-jp2kdecimator.xml +++ b/docs/plugins/inspect/plugin-jp2kdecimator.xml @@ -3,10 +3,10 @@ JPEG2000 decimator ../../gst/jp2kdecimator/.libs/libgstjp2kdecimator.so libgstjp2kdecimator.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-jpegformat.xml b/docs/plugins/inspect/plugin-jpegformat.xml index 2b5be56125..03c2b595fa 100644 --- a/docs/plugins/inspect/plugin-jpegformat.xml +++ b/docs/plugins/inspect/plugin-jpegformat.xml @@ -3,10 +3,10 @@ JPEG interchange format plugin ../../gst/jpegformat/.libs/libgstjpegformat.so libgstjpegformat.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-kate.xml b/docs/plugins/inspect/plugin-kate.xml index cf0d0670f1..19fb170502 100644 --- a/docs/plugins/inspect/plugin-kate.xml +++ b/docs/plugins/inspect/plugin-kate.xml @@ -3,10 +3,10 @@ Kate plugin ../../ext/kate/.libs/libgstkate.so libgstkate.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-ladspa.xml b/docs/plugins/inspect/plugin-ladspa.xml index 99861849cf..d46d02a195 100644 --- a/docs/plugins/inspect/plugin-ladspa.xml +++ b/docs/plugins/inspect/plugin-ladspa.xml @@ -3,10 +3,10 @@ All LADSPA plugins ../../ext/ladspa/.libs/libgstladspa.so libgstladspa.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-legacyresample.xml b/docs/plugins/inspect/plugin-legacyresample.xml index 6a78c594e9..ef960ca61e 100644 --- a/docs/plugins/inspect/plugin-legacyresample.xml +++ b/docs/plugins/inspect/plugin-legacyresample.xml @@ -3,10 +3,10 @@ Resamples audio ../../gst/legacyresample/.libs/libgstlegacyresample.so libgstlegacyresample.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-liveadder.xml b/docs/plugins/inspect/plugin-liveadder.xml index bccb1e76d4..0aeacfb891 100644 --- a/docs/plugins/inspect/plugin-liveadder.xml +++ b/docs/plugins/inspect/plugin-liveadder.xml @@ -3,10 +3,10 @@ Adds multiple live discontinuous streams ../../gst/liveadder/.libs/libgstliveadder.so libgstliveadder.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-mimic.xml b/docs/plugins/inspect/plugin-mimic.xml index 67d605f26f..d4c56931cb 100644 --- a/docs/plugins/inspect/plugin-mimic.xml +++ b/docs/plugins/inspect/plugin-mimic.xml @@ -3,10 +3,10 @@ Mimic codec ../../ext/mimic/.libs/libgstmimic.so libgstmimic.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-mms.xml b/docs/plugins/inspect/plugin-mms.xml index dd0f37885c..d0607d0be9 100644 --- a/docs/plugins/inspect/plugin-mms.xml +++ b/docs/plugins/inspect/plugin-mms.xml @@ -3,10 +3,10 @@ Microsoft Multi Media Server streaming protocol support ../../ext/libmms/.libs/libgstmms.so libgstmms.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-modplug.xml b/docs/plugins/inspect/plugin-modplug.xml index 70e11f43bd..a142537d4d 100644 --- a/docs/plugins/inspect/plugin-modplug.xml +++ b/docs/plugins/inspect/plugin-modplug.xml @@ -3,10 +3,10 @@ .MOD audio decoding ../../ext/modplug/.libs/libgstmodplug.so libgstmodplug.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-mpeg2enc.xml b/docs/plugins/inspect/plugin-mpeg2enc.xml index 92dde048db..9eb28e722f 100644 --- a/docs/plugins/inspect/plugin-mpeg2enc.xml +++ b/docs/plugins/inspect/plugin-mpeg2enc.xml @@ -3,10 +3,10 @@ High-quality MPEG-1/2 video encoder ../../ext/mpeg2enc/.libs/libgstmpeg2enc.so libgstmpeg2enc.so - 0.10.20.1 + 0.10.20.2 GPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-mpeg4videoparse.xml b/docs/plugins/inspect/plugin-mpeg4videoparse.xml index c3b91f1a9e..ca4c720cc7 100644 --- a/docs/plugins/inspect/plugin-mpeg4videoparse.xml +++ b/docs/plugins/inspect/plugin-mpeg4videoparse.xml @@ -3,10 +3,10 @@ MPEG-4 video parser ../../gst/mpeg4videoparse/.libs/libgstmpeg4videoparse.so libgstmpeg4videoparse.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-mpegdemux2.xml b/docs/plugins/inspect/plugin-mpegdemux2.xml index 2320d4e97b..c35498916e 100644 --- a/docs/plugins/inspect/plugin-mpegdemux2.xml +++ b/docs/plugins/inspect/plugin-mpegdemux2.xml @@ -3,10 +3,10 @@ MPEG demuxers ../../gst/mpegdemux/.libs/libgstmpegdemux.so libgstmpegdemux.so - 0.10.20.1 + 0.10.20.2 unknown gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-mpegpsmux.xml b/docs/plugins/inspect/plugin-mpegpsmux.xml index 74a7d9805d..c1b27311b6 100644 --- a/docs/plugins/inspect/plugin-mpegpsmux.xml +++ b/docs/plugins/inspect/plugin-mpegpsmux.xml @@ -3,10 +3,10 @@ MPEG-PS muxer ../../gst/mpegpsmux/.libs/libgstmpegpsmux.so libgstmpegpsmux.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-mpegtsmux.xml b/docs/plugins/inspect/plugin-mpegtsmux.xml index a7ca0ac5a2..f1a6d550c6 100644 --- a/docs/plugins/inspect/plugin-mpegtsmux.xml +++ b/docs/plugins/inspect/plugin-mpegtsmux.xml @@ -3,10 +3,10 @@ MPEG-TS muxer ../../gst/mpegtsmux/.libs/libgstmpegtsmux.so libgstmpegtsmux.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-mpegvideoparse.xml b/docs/plugins/inspect/plugin-mpegvideoparse.xml index 539501f837..82c6121fd5 100644 --- a/docs/plugins/inspect/plugin-mpegvideoparse.xml +++ b/docs/plugins/inspect/plugin-mpegvideoparse.xml @@ -3,10 +3,10 @@ MPEG-1 and MPEG-2 video parser ../../gst/mpegvideoparse/.libs/libgstmpegvideoparse.so libgstmpegvideoparse.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-mplex.xml b/docs/plugins/inspect/plugin-mplex.xml index a608ea28a5..6d7669623e 100644 --- a/docs/plugins/inspect/plugin-mplex.xml +++ b/docs/plugins/inspect/plugin-mplex.xml @@ -3,10 +3,10 @@ High-quality MPEG/DVD/SVCD/VCD video/audio multiplexer ../../ext/mplex/.libs/libgstmplex.so libgstmplex.so - 0.10.20.1 + 0.10.20.2 GPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-musepack.xml b/docs/plugins/inspect/plugin-musepack.xml index 2164282de5..9bc633d4f0 100644 --- a/docs/plugins/inspect/plugin-musepack.xml +++ b/docs/plugins/inspect/plugin-musepack.xml @@ -3,10 +3,10 @@ Musepack decoder ../../ext/musepack/.libs/libgstmusepack.so libgstmusepack.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-musicbrainz.xml b/docs/plugins/inspect/plugin-musicbrainz.xml index 0e82b158ad..1ba564cfb4 100644 --- a/docs/plugins/inspect/plugin-musicbrainz.xml +++ b/docs/plugins/inspect/plugin-musicbrainz.xml @@ -3,10 +3,10 @@ A TRM signature producer based on libmusicbrainz ../../ext/musicbrainz/.libs/libgsttrm.so libgsttrm.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-mve.xml b/docs/plugins/inspect/plugin-mve.xml index 037ed80417..34d532790c 100644 --- a/docs/plugins/inspect/plugin-mve.xml +++ b/docs/plugins/inspect/plugin-mve.xml @@ -3,10 +3,10 @@ Interplay MVE movie format manipulation ../../gst/mve/.libs/libgstmve.so libgstmve.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-mxf.xml b/docs/plugins/inspect/plugin-mxf.xml index 2b0fd106ed..b7c500eae0 100644 --- a/docs/plugins/inspect/plugin-mxf.xml +++ b/docs/plugins/inspect/plugin-mxf.xml @@ -3,10 +3,10 @@ MXF plugin library ../../gst/mxf/.libs/libgstmxf.so libgstmxf.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-mythtv.xml b/docs/plugins/inspect/plugin-mythtv.xml index 3ee461b914..21d4b018ed 100644 --- a/docs/plugins/inspect/plugin-mythtv.xml +++ b/docs/plugins/inspect/plugin-mythtv.xml @@ -3,10 +3,10 @@ lib MythTV src ../../ext/mythtv/.libs/libgstmythtvsrc.so libgstmythtvsrc.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-nas.xml b/docs/plugins/inspect/plugin-nas.xml index 4da7985514..c72cef3d1f 100644 --- a/docs/plugins/inspect/plugin-nas.xml +++ b/docs/plugins/inspect/plugin-nas.xml @@ -3,10 +3,10 @@ NAS (Network Audio System) support for GStreamer ../../ext/nas/.libs/libgstnassink.so libgstnassink.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-neon.xml b/docs/plugins/inspect/plugin-neon.xml index a7b7a5a334..59891a7665 100644 --- a/docs/plugins/inspect/plugin-neon.xml +++ b/docs/plugins/inspect/plugin-neon.xml @@ -3,10 +3,10 @@ lib neon http client src ../../ext/neon/.libs/libgstneonhttpsrc.so libgstneonhttpsrc.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-nsf.xml b/docs/plugins/inspect/plugin-nsf.xml index 2ad014331f..7f65aee8db 100644 --- a/docs/plugins/inspect/plugin-nsf.xml +++ b/docs/plugins/inspect/plugin-nsf.xml @@ -3,10 +3,10 @@ Uses nosefart to decode .nsf files ../../gst/nsf/.libs/libgstnsf.so libgstnsf.so - 0.10.20.1 + 0.10.20.2 GPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-nuvdemux.xml b/docs/plugins/inspect/plugin-nuvdemux.xml index ff9519f72d..eb0f3ea2ae 100644 --- a/docs/plugins/inspect/plugin-nuvdemux.xml +++ b/docs/plugins/inspect/plugin-nuvdemux.xml @@ -3,10 +3,10 @@ Demuxes MythTV NuppelVideo files ../../gst/nuvdemux/.libs/libgstnuvdemux.so libgstnuvdemux.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-ofa.xml b/docs/plugins/inspect/plugin-ofa.xml index c806613bc7..3ba130933a 100644 --- a/docs/plugins/inspect/plugin-ofa.xml +++ b/docs/plugins/inspect/plugin-ofa.xml @@ -3,10 +3,10 @@ Calculate MusicIP fingerprint from audio files ../../ext/ofa/.libs/libgstofa.so libgstofa.so - 0.10.20.1 + 0.10.20.2 GPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-opencv.xml b/docs/plugins/inspect/plugin-opencv.xml index 1cb9888a57..eace0307c8 100644 --- a/docs/plugins/inspect/plugin-opencv.xml +++ b/docs/plugins/inspect/plugin-opencv.xml @@ -3,10 +3,10 @@ GStreamer OpenCV Plugins ../../ext/opencv/.libs/libgstopencv.so libgstopencv.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-pcapparse.xml b/docs/plugins/inspect/plugin-pcapparse.xml index dfd303ef27..158ebe70fe 100644 --- a/docs/plugins/inspect/plugin-pcapparse.xml +++ b/docs/plugins/inspect/plugin-pcapparse.xml @@ -3,7 +3,7 @@ Element parsing raw pcap streams ../../gst/pcapparse/.libs/libgstpcapparse.so libgstpcapparse.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad GStreamer diff --git a/docs/plugins/inspect/plugin-pnm.xml b/docs/plugins/inspect/plugin-pnm.xml index 04595bba11..87551d5d3b 100644 --- a/docs/plugins/inspect/plugin-pnm.xml +++ b/docs/plugins/inspect/plugin-pnm.xml @@ -3,10 +3,10 @@ PNM plugin ../../gst/pnm/.libs/libgstpnm.so libgstpnm.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-qtmux.xml b/docs/plugins/inspect/plugin-qtmux.xml index 286d8e0e0c..be0ca02c11 100644 --- a/docs/plugins/inspect/plugin-qtmux.xml +++ b/docs/plugins/inspect/plugin-qtmux.xml @@ -3,10 +3,10 @@ Quicktime Muxer plugin ../../gst/qtmux/.libs/libgstqtmux.so libgstqtmux.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-rawparse.xml b/docs/plugins/inspect/plugin-rawparse.xml index 618542a514..8c33ef5d22 100644 --- a/docs/plugins/inspect/plugin-rawparse.xml +++ b/docs/plugins/inspect/plugin-rawparse.xml @@ -3,10 +3,10 @@ Parses byte streams into raw frames ../../gst/rawparse/.libs/libgstrawparse.so libgstrawparse.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-real.xml b/docs/plugins/inspect/plugin-real.xml index 00f412312d..ce86ab0138 100644 --- a/docs/plugins/inspect/plugin-real.xml +++ b/docs/plugins/inspect/plugin-real.xml @@ -3,10 +3,10 @@ Decode REAL streams ../../gst/real/.libs/libgstreal.so libgstreal.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-resindvd.xml b/docs/plugins/inspect/plugin-resindvd.xml index fb20d4bc90..549a74ee3b 100644 --- a/docs/plugins/inspect/plugin-resindvd.xml +++ b/docs/plugins/inspect/plugin-resindvd.xml @@ -3,7 +3,7 @@ Resin DVD playback elements ../../ext/resindvd/.libs/libresindvd.so libresindvd.so - 0.10.20.1 + 0.10.20.2 GPL gst-plugins-bad GStreamer diff --git a/docs/plugins/inspect/plugin-rfbsrc.xml b/docs/plugins/inspect/plugin-rfbsrc.xml index 6c4436f78c..878ecbf7e2 100644 --- a/docs/plugins/inspect/plugin-rfbsrc.xml +++ b/docs/plugins/inspect/plugin-rfbsrc.xml @@ -3,10 +3,10 @@ Connects to a VNC server and decodes RFB stream ../../gst/librfb/.libs/libgstrfbsrc.so libgstrfbsrc.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-rsvg.xml b/docs/plugins/inspect/plugin-rsvg.xml index 17ff3078b6..fef49353f7 100644 --- a/docs/plugins/inspect/plugin-rsvg.xml +++ b/docs/plugins/inspect/plugin-rsvg.xml @@ -3,10 +3,10 @@ RSVG plugin library ../../ext/rsvg/.libs/libgstrsvg.so libgstrsvg.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-rtpmux.xml b/docs/plugins/inspect/plugin-rtpmux.xml index f88d523d32..352e243c5a 100644 --- a/docs/plugins/inspect/plugin-rtpmux.xml +++ b/docs/plugins/inspect/plugin-rtpmux.xml @@ -3,10 +3,10 @@ RTP Muxer plugins ../../gst/rtpmux/.libs/libgstrtpmux.so libgstrtpmux.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-scaletempo.xml b/docs/plugins/inspect/plugin-scaletempo.xml index 0530697ce6..2918403964 100644 --- a/docs/plugins/inspect/plugin-scaletempo.xml +++ b/docs/plugins/inspect/plugin-scaletempo.xml @@ -3,7 +3,7 @@ Scale audio tempo in sync with playback rate ../../gst/scaletempo/.libs/libgstscaletempoplugin.so libgstscaletempoplugin.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad GStreamer diff --git a/docs/plugins/inspect/plugin-schro.xml b/docs/plugins/inspect/plugin-schro.xml index 43cbbc7eae..dd0ec0557f 100644 --- a/docs/plugins/inspect/plugin-schro.xml +++ b/docs/plugins/inspect/plugin-schro.xml @@ -3,10 +3,10 @@ Schroedinger plugin ../../ext/schroedinger/.libs/libgstschro.so libgstschro.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-sdl.xml b/docs/plugins/inspect/plugin-sdl.xml index ce8912d7a4..91862dfc5c 100644 --- a/docs/plugins/inspect/plugin-sdl.xml +++ b/docs/plugins/inspect/plugin-sdl.xml @@ -3,10 +3,10 @@ SDL (Simple DirectMedia Layer) support for GStreamer ../../ext/sdl/.libs/libgstsdl.so libgstsdl.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-sdp.xml b/docs/plugins/inspect/plugin-sdp.xml index 462fc13afe..b4f18393dc 100644 --- a/docs/plugins/inspect/plugin-sdp.xml +++ b/docs/plugins/inspect/plugin-sdp.xml @@ -3,10 +3,10 @@ configure streaming sessions using SDP ../../gst/sdp/.libs/libgstsdpelem.so libgstsdpelem.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-segmentclip.xml b/docs/plugins/inspect/plugin-segmentclip.xml index e9811458db..1dbfe345d1 100644 --- a/docs/plugins/inspect/plugin-segmentclip.xml +++ b/docs/plugins/inspect/plugin-segmentclip.xml @@ -3,10 +3,10 @@ Segment clip elements ../../gst/segmentclip/.libs/libgstsegmentclip.so libgstsegmentclip.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-shm.xml b/docs/plugins/inspect/plugin-shm.xml index 39025fc202..5a76f7c5e3 100644 --- a/docs/plugins/inspect/plugin-shm.xml +++ b/docs/plugins/inspect/plugin-shm.xml @@ -3,10 +3,10 @@ shared memory sink source ../../sys/shm/.libs/libgstshm.so libgstshm.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-sndfile.xml b/docs/plugins/inspect/plugin-sndfile.xml index 4a46cbeffd..3165a191af 100644 --- a/docs/plugins/inspect/plugin-sndfile.xml +++ b/docs/plugins/inspect/plugin-sndfile.xml @@ -3,10 +3,10 @@ use libsndfile to read and write audio from and to files ../../ext/sndfile/.libs/libgstsndfile.so libgstsndfile.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-soundtouch.xml b/docs/plugins/inspect/plugin-soundtouch.xml index 7ccf6a9c89..b731aa3913 100644 --- a/docs/plugins/inspect/plugin-soundtouch.xml +++ b/docs/plugins/inspect/plugin-soundtouch.xml @@ -3,10 +3,10 @@ Audio Pitch Controller & BPM Detection ../../ext/soundtouch/.libs/libgstsoundtouch.so libgstsoundtouch.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-speed.xml b/docs/plugins/inspect/plugin-speed.xml index 5f2d5be4c9..ca3b469a6c 100644 --- a/docs/plugins/inspect/plugin-speed.xml +++ b/docs/plugins/inspect/plugin-speed.xml @@ -3,10 +3,10 @@ Set speed/pitch on audio/raw streams (resampler) ../../gst/speed/.libs/libgstspeed.so libgstspeed.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-stereo.xml b/docs/plugins/inspect/plugin-stereo.xml index 97d55f70c1..aee6a66139 100644 --- a/docs/plugins/inspect/plugin-stereo.xml +++ b/docs/plugins/inspect/plugin-stereo.xml @@ -3,10 +3,10 @@ Muck with the stereo signal, enhance it's 'stereo-ness' ../../gst/stereo/.libs/libgststereo.so libgststereo.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-subenc.xml b/docs/plugins/inspect/plugin-subenc.xml index 2a9ea5d1ce..6c5279fa3c 100644 --- a/docs/plugins/inspect/plugin-subenc.xml +++ b/docs/plugins/inspect/plugin-subenc.xml @@ -3,10 +3,10 @@ subtitle encoders ../../gst/subenc/.libs/libgstsubenc.so libgstsubenc.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-tta.xml b/docs/plugins/inspect/plugin-tta.xml index 242bbe82b5..7198d82f09 100644 --- a/docs/plugins/inspect/plugin-tta.xml +++ b/docs/plugins/inspect/plugin-tta.xml @@ -3,10 +3,10 @@ TTA lossless audio format handling ../../gst/tta/.libs/libgsttta.so libgsttta.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-vcdsrc.xml b/docs/plugins/inspect/plugin-vcdsrc.xml index 8211a90cb1..82865aad5e 100644 --- a/docs/plugins/inspect/plugin-vcdsrc.xml +++ b/docs/plugins/inspect/plugin-vcdsrc.xml @@ -3,10 +3,10 @@ Asynchronous read from VCD disk ../../sys/vcd/.libs/libgstvcdsrc.so libgstvcdsrc.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-vdpau.xml b/docs/plugins/inspect/plugin-vdpau.xml index ab1141f01e..1d3391e1fe 100644 --- a/docs/plugins/inspect/plugin-vdpau.xml +++ b/docs/plugins/inspect/plugin-vdpau.xml @@ -3,7 +3,7 @@ Various elements utilizing VDPAU ../../sys/vdpau/.libs/libgstvdpau.so libgstvdpau.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad GStreamer diff --git a/docs/plugins/inspect/plugin-videomaxrate.xml b/docs/plugins/inspect/plugin-videomaxrate.xml index 11011b9f5d..de69ceb4e3 100644 --- a/docs/plugins/inspect/plugin-videomaxrate.xml +++ b/docs/plugins/inspect/plugin-videomaxrate.xml @@ -3,10 +3,10 @@ Drop extra frames ../../gst/videomaxrate/.libs/libgstvideomaxrate.so libgstvideomaxrate.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-videomeasure.xml b/docs/plugins/inspect/plugin-videomeasure.xml index 0d8bacab1d..774e3dd0f4 100644 --- a/docs/plugins/inspect/plugin-videomeasure.xml +++ b/docs/plugins/inspect/plugin-videomeasure.xml @@ -3,10 +3,10 @@ Various video measurers ../../gst/videomeasure/.libs/libgstvideomeasure.so libgstvideomeasure.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-videosignal.xml b/docs/plugins/inspect/plugin-videosignal.xml index 2300debb33..45ddbafcc5 100644 --- a/docs/plugins/inspect/plugin-videosignal.xml +++ b/docs/plugins/inspect/plugin-videosignal.xml @@ -3,10 +3,10 @@ Various video signal analysers ../../gst/videosignal/.libs/libgstvideosignal.so libgstvideosignal.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-vmnc.xml b/docs/plugins/inspect/plugin-vmnc.xml index 7a7d4cd118..8fa5902d23 100644 --- a/docs/plugins/inspect/plugin-vmnc.xml +++ b/docs/plugins/inspect/plugin-vmnc.xml @@ -3,10 +3,10 @@ VmWare Video Codec plugins ../../gst/vmnc/.libs/libgstvmnc.so libgstvmnc.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-vp8.xml b/docs/plugins/inspect/plugin-vp8.xml index 55387b38be..5fd55fb1ec 100644 --- a/docs/plugins/inspect/plugin-vp8.xml +++ b/docs/plugins/inspect/plugin-vp8.xml @@ -3,10 +3,10 @@ VP8 plugin ../../ext/vp8/.libs/libgstvp8.so libgstvp8.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-wildmidi.xml b/docs/plugins/inspect/plugin-wildmidi.xml index f68db86d05..3815c491c3 100644 --- a/docs/plugins/inspect/plugin-wildmidi.xml +++ b/docs/plugins/inspect/plugin-wildmidi.xml @@ -3,10 +3,10 @@ Wildmidi Plugin ../../ext/timidity/.libs/libgstwildmidi.so libgstwildmidi.so - 0.10.20.1 + 0.10.20.2 GPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-xvid.xml b/docs/plugins/inspect/plugin-xvid.xml index 8ba36b5e6b..8a365bbb58 100644 --- a/docs/plugins/inspect/plugin-xvid.xml +++ b/docs/plugins/inspect/plugin-xvid.xml @@ -3,10 +3,10 @@ XviD plugin library ../../ext/xvid/.libs/libgstxvid.so libgstxvid.so - 0.10.20.1 + 0.10.20.2 GPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin diff --git a/docs/plugins/inspect/plugin-y4mdec.xml b/docs/plugins/inspect/plugin-y4mdec.xml index 8f3d50fa03..f782b943de 100644 --- a/docs/plugins/inspect/plugin-y4mdec.xml +++ b/docs/plugins/inspect/plugin-y4mdec.xml @@ -3,7 +3,7 @@ FIXME ../../gst/y4m/.libs/libgsty4mdec.so libgsty4mdec.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad GStreamer Bad Plug-ins diff --git a/docs/plugins/inspect/plugin-zbar.xml b/docs/plugins/inspect/plugin-zbar.xml index 232802a3f7..0fdfb655fb 100644 --- a/docs/plugins/inspect/plugin-zbar.xml +++ b/docs/plugins/inspect/plugin-zbar.xml @@ -3,10 +3,10 @@ zbar barcode scanner ../../ext/zbar/.libs/libgstzbar.so libgstzbar.so - 0.10.20.1 + 0.10.20.2 LGPL gst-plugins-bad - GStreamer Bad Plug-ins git + GStreamer Bad Plug-ins prerelease Unknown package origin From 62c289f71dfe68f9ef6068498119345f744b3b19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Sat, 8 Jan 2011 03:10:00 +0000 Subject: [PATCH 282/448] 0.10.20.2 pre-release --- configure.ac | 6 +- ext/cog/gstcogorc-dist.c | 973 +++++++++++---------------------------- ext/cog/gstcogorc-dist.h | 6 +- win32/common/config.h | 4 +- 4 files changed, 290 insertions(+), 699 deletions(-) diff --git a/configure.ac b/configure.ac index 3006212005..757dffd415 100644 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ AC_PREREQ(2.60) dnl initialize autoconf dnl when going to/from release please set the nano (fourth number) right ! dnl releases only do Wall, cvs and prerelease does Werror too -AC_INIT(GStreamer Bad Plug-ins, 0.10.20.1, +AC_INIT(GStreamer Bad Plug-ins, 0.10.20.2, http://bugzilla.gnome.org/enter_bug.cgi?product=GStreamer, gst-plugins-bad) @@ -50,8 +50,8 @@ AC_LIBTOOL_WIN32_DLL AM_PROG_LIBTOOL dnl *** required versions of GStreamer stuff *** -GST_REQ=0.10.31.1 -GSTPB_REQ=0.10.31.1 +GST_REQ=0.10.31.2 +GSTPB_REQ=0.10.31.2 dnl *** autotools stuff **** diff --git a/ext/cog/gstcogorc-dist.c b/ext/cog/gstcogorc-dist.c index 01d791e39d..4cd43b5be3 100644 --- a/ext/cog/gstcogorc-dist.c +++ b/ext/cog/gstcogorc-dist.c @@ -21,6 +21,7 @@ typedef uint8_t orc_uint8; typedef uint16_t orc_uint16; typedef uint32_t orc_uint32; typedef uint64_t orc_uint64; +#define ORC_UINT64_C(x) UINT64_C(x) #elif defined(_MSC_VER) typedef signed __int8 orc_int8; typedef signed __int16 orc_int16; @@ -30,6 +31,7 @@ typedef unsigned __int8 orc_uint8; typedef unsigned __int16 orc_uint16; typedef unsigned __int32 orc_uint32; typedef unsigned __int64 orc_uint64; +#define ORC_UINT64_C(x) (x##Ui64) #else #include typedef signed char orc_int8; @@ -41,9 +43,11 @@ typedef unsigned int orc_uint32; #if INT_MAX == LONG_MAX typedef long long orc_int64; typedef unsigned long long orc_uint64; +#define ORC_UINT64_C(x) (x##ULL) #else typedef long orc_int64; typedef unsigned long orc_uint64; +#define ORC_UINT64_C(x) (x##UL) #endif #endif typedef union @@ -63,6 +67,7 @@ typedef union orc_int64 i; double f; orc_int32 x2[2]; + float x2f[2]; orc_int16 x4[4]; } orc_union64; #endif @@ -252,12 +257,12 @@ void cogorc_convert_I420_BGRA_avg (orc_uint32 * d1, const orc_uint8 * s1, #define ORC_CLAMP_UL(x) ORC_CLAMP(x,ORC_UL_MIN,ORC_UL_MAX) #define ORC_SWAP_W(x) ((((x)&0xff)<<8) | (((x)&0xff00)>>8)) #define ORC_SWAP_L(x) ((((x)&0xff)<<24) | (((x)&0xff00)<<8) | (((x)&0xff0000)>>8) | (((x)&0xff000000)>>24)) -#define ORC_SWAP_Q(x) ((((x)&0xffULL)<<56) | (((x)&0xff00ULL)<<40) | (((x)&0xff0000ULL)<<24) | (((x)&0xff000000ULL)<<8) | (((x)&0xff00000000ULL)>>8) | (((x)&0xff0000000000ULL)>>24) | (((x)&0xff000000000000ULL)>>40) | (((x)&0xff00000000000000ULL)>>56)) +#define ORC_SWAP_Q(x) ((((x)&ORC_UINT64_C(0xff))<<56) | (((x)&ORC_UINT64_C(0xff00))<<40) | (((x)&ORC_UINT64_C(0xff0000))<<24) | (((x)&ORC_UINT64_C(0xff000000))<<8) | (((x)&ORC_UINT64_C(0xff00000000))>>8) | (((x)&ORC_UINT64_C(0xff0000000000))>>24) | (((x)&ORC_UINT64_C(0xff000000000000))>>40) | (((x)&ORC_UINT64_C(0xff00000000000000))>>56)) #define ORC_PTR_OFFSET(ptr,offset) ((void *)(((unsigned char *)(ptr)) + (offset))) #define ORC_DENORMAL(x) ((x) & ((((x)&0x7f800000) == 0) ? 0xff800000 : 0xffffffff)) #define ORC_ISNAN(x) ((((x)&0x7f800000) == 0x7f800000) && (((x)&0x007fffff) != 0)) -#define ORC_DENORMAL_DOUBLE(x) ((x) & ((((x)&0x7ff0000000000000ULL) == 0) ? 0xfff0000000000000ULL : 0xffffffffffffffffULL)) -#define ORC_ISNAN_DOUBLE(x) ((((x)&0x7ff0000000000000ULL) == 0x7ff0000000000000ULL) && (((x)&0x000fffffffffffffULL) != 0)) +#define ORC_DENORMAL_DOUBLE(x) ((x) & ((((x)&ORC_UINT64_C(0x7ff0000000000000)) == 0) ? ORC_UINT64_C(0xfff0000000000000) : ORC_UINT64_C(0xffffffffffffffff))) +#define ORC_ISNAN_DOUBLE(x) ((((x)&ORC_UINT64_C(0x7ff0000000000000)) == ORC_UINT64_C(0x7ff0000000000000)) && (((x)&ORC_UINT64_C(0x000fffffffffffff)) != 0)) #if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L #define ORC_RESTRICT restrict #elif defined(__GNUC__) && __GNUC__ >= 4 @@ -349,14 +354,6 @@ cogorc_memcpy_2d (orc_uint8 * d1, int d1_stride, const orc_uint8 * s1, orc_program_set_backup_function (p, _backup_cogorc_memcpy_2d); orc_program_add_destination (p, 1, "d1"); orc_program_add_source (p, 1, "s1"); - orc_program_add_constant (p, 0, 0x00000000, "c1"); - orc_program_add_constant (p, 0, 0x00000000, "c2"); - orc_program_add_constant (p, 0, 0x00000000, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_append_2 (p, "copyb", 0, ORC_VAR_D1, ORC_VAR_S1, ORC_VAR_D1, ORC_VAR_D1); @@ -454,14 +451,6 @@ cogorc_downsample_horiz_cosite_1tap (orc_uint8 * d1, const orc_uint16 * s1, _backup_cogorc_downsample_horiz_cosite_1tap); orc_program_add_destination (p, 1, "d1"); orc_program_add_source (p, 2, "s1"); - orc_program_add_constant (p, 0, 0x00000000, "c1"); - orc_program_add_constant (p, 0, 0x00000000, "c2"); - orc_program_add_constant (p, 0, 0x00000000, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_append_2 (p, "select0wb", 0, ORC_VAR_D1, ORC_VAR_S1, ORC_VAR_D1, ORC_VAR_D1); @@ -652,13 +641,6 @@ cogorc_downsample_horiz_cosite_3tap (orc_uint8 * d1, const orc_uint16 * s1, orc_program_add_source (p, 2, "s1"); orc_program_add_source (p, 2, "s2"); orc_program_add_constant (p, 4, 0x00000002, "c1"); - orc_program_add_constant (p, 0, 0x00000002, "c2"); - orc_program_add_constant (p, 0, 0x00000000, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_add_temporary (p, 1, "t1"); orc_program_add_temporary (p, 1, "t2"); orc_program_add_temporary (p, 1, "t3"); @@ -842,14 +824,6 @@ cogorc_downsample_420_jpeg (orc_uint8 * d1, const orc_uint16 * s1, orc_program_add_destination (p, 1, "d1"); orc_program_add_source (p, 2, "s1"); orc_program_add_source (p, 2, "s2"); - orc_program_add_constant (p, 0, 0x00000000, "c1"); - orc_program_add_constant (p, 0, 0x00000000, "c2"); - orc_program_add_constant (p, 0, 0x00000000, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_add_temporary (p, 2, "t1"); orc_program_add_temporary (p, 1, "t2"); orc_program_add_temporary (p, 1, "t3"); @@ -977,14 +951,6 @@ cogorc_downsample_vert_halfsite_2tap (orc_uint8 * d1, const orc_uint8 * s1, orc_program_add_destination (p, 1, "d1"); orc_program_add_source (p, 1, "s1"); orc_program_add_source (p, 1, "s2"); - orc_program_add_constant (p, 0, 0x00000000, "c1"); - orc_program_add_constant (p, 0, 0x00000000, "c2"); - orc_program_add_constant (p, 0, 0x00000000, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_append_2 (p, "avgub", 0, ORC_VAR_D1, ORC_VAR_S1, ORC_VAR_S2, ORC_VAR_D1); @@ -1163,13 +1129,6 @@ cogorc_downsample_vert_cosite_3tap (orc_uint8 * d1, const orc_uint8 * s1, orc_program_add_source (p, 1, "s2"); orc_program_add_source (p, 1, "s3"); orc_program_add_constant (p, 4, 0x00000002, "c1"); - orc_program_add_constant (p, 0, 0x00000002, "c2"); - orc_program_add_constant (p, 0, 0x00000000, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_add_temporary (p, 2, "t1"); orc_program_add_temporary (p, 2, "t2"); orc_program_add_temporary (p, 2, "t3"); @@ -1405,11 +1364,6 @@ cogorc_downsample_vert_halfsite_4tap (orc_uint8 * d1, const orc_uint8 * s1, orc_program_add_constant (p, 4, 0x0000001a, "c1"); orc_program_add_constant (p, 4, 0x00000006, "c2"); orc_program_add_constant (p, 4, 0x00000020, "c3"); - orc_program_add_constant (p, 0, 0x00000006, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_add_temporary (p, 2, "t1"); orc_program_add_temporary (p, 2, "t2"); orc_program_add_temporary (p, 2, "t3"); @@ -1482,7 +1436,7 @@ cogorc_upsample_horiz_cosite_1tap (guint8 * d1, const orc_uint8 * s1, int n) /* 1: copyb */ var35 = var33; /* 2: mergebw */ - var34.i = ((orc_uint8) var35) | ((orc_uint8) var35 << 8); + var34.i = ((orc_uint8) var35 & 0x00ff) | ((orc_uint8) var35 << 8); /* 3: storew */ ptr0[i] = var34; } @@ -1511,7 +1465,7 @@ _backup_cogorc_upsample_horiz_cosite_1tap (OrcExecutor * ex) /* 1: copyb */ var35 = var33; /* 2: mergebw */ - var34.i = ((orc_uint8) var35) | ((orc_uint8) var35 << 8); + var34.i = ((orc_uint8) var35 & 0x00ff) | ((orc_uint8) var35 << 8); /* 3: storew */ ptr0[i] = var34; } @@ -1537,14 +1491,6 @@ cogorc_upsample_horiz_cosite_1tap (guint8 * d1, const orc_uint8 * s1, int n) _backup_cogorc_upsample_horiz_cosite_1tap); orc_program_add_destination (p, 2, "d1"); orc_program_add_source (p, 1, "s1"); - orc_program_add_constant (p, 0, 0x00000000, "c1"); - orc_program_add_constant (p, 0, 0x00000000, "c2"); - orc_program_add_constant (p, 0, 0x00000000, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_add_temporary (p, 1, "t1"); orc_program_append_2 (p, "copyb", 0, ORC_VAR_T1, ORC_VAR_S1, ORC_VAR_D1, @@ -1600,7 +1546,7 @@ cogorc_upsample_horiz_cosite (guint8 * d1, const orc_uint8 * s1, /* 3: avgub */ var38 = ((orc_uint8) var37 + (orc_uint8) var35 + 1) >> 1; /* 4: mergebw */ - var36.i = ((orc_uint8) var37) | ((orc_uint8) var38 << 8); + var36.i = ((orc_uint8) var37 & 0x00ff) | ((orc_uint8) var38 << 8); /* 5: storew */ ptr0[i] = var36; } @@ -1637,7 +1583,7 @@ _backup_cogorc_upsample_horiz_cosite (OrcExecutor * ex) /* 3: avgub */ var38 = ((orc_uint8) var37 + (orc_uint8) var35 + 1) >> 1; /* 4: mergebw */ - var36.i = ((orc_uint8) var37) | ((orc_uint8) var38 << 8); + var36.i = ((orc_uint8) var37 & 0x00ff) | ((orc_uint8) var38 << 8); /* 5: storew */ ptr0[i] = var36; } @@ -1664,14 +1610,6 @@ cogorc_upsample_horiz_cosite (guint8 * d1, const orc_uint8 * s1, orc_program_add_destination (p, 2, "d1"); orc_program_add_source (p, 1, "s1"); orc_program_add_source (p, 1, "s2"); - orc_program_add_constant (p, 0, 0x00000000, "c1"); - orc_program_add_constant (p, 0, 0x00000000, "c2"); - orc_program_add_constant (p, 0, 0x00000000, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_add_temporary (p, 1, "t1"); orc_program_add_temporary (p, 1, "t2"); @@ -1783,14 +1721,6 @@ cogorc_upsample_vert_avgub (orc_uint8 * d1, const orc_uint8 * s1, orc_program_add_destination (p, 1, "d1"); orc_program_add_source (p, 1, "s1"); orc_program_add_source (p, 1, "s2"); - orc_program_add_constant (p, 0, 0x00000000, "c1"); - orc_program_add_constant (p, 0, 0x00000000, "c2"); - orc_program_add_constant (p, 0, 0x00000000, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_append_2 (p, "avgub", 0, ORC_VAR_D1, ORC_VAR_S1, ORC_VAR_S2, ORC_VAR_D1); @@ -1883,14 +1813,6 @@ orc_unpack_yuyv_y (orc_uint8 * d1, const orc_uint16 * s1, int n) orc_program_set_backup_function (p, _backup_orc_unpack_yuyv_y); orc_program_add_destination (p, 1, "d1"); orc_program_add_source (p, 2, "s1"); - orc_program_add_constant (p, 0, 0x00000000, "c1"); - orc_program_add_constant (p, 0, 0x00000000, "c2"); - orc_program_add_constant (p, 0, 0x00000000, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_append_2 (p, "select0wb", 0, ORC_VAR_D1, ORC_VAR_S1, ORC_VAR_D1, ORC_VAR_D1); @@ -1988,14 +1910,6 @@ orc_unpack_yuyv_u (orc_uint8 * d1, const orc_uint32 * s1, int n) orc_program_set_backup_function (p, _backup_orc_unpack_yuyv_u); orc_program_add_destination (p, 1, "d1"); orc_program_add_source (p, 4, "s1"); - orc_program_add_constant (p, 0, 0x00000000, "c1"); - orc_program_add_constant (p, 0, 0x00000000, "c2"); - orc_program_add_constant (p, 0, 0x00000000, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_add_temporary (p, 2, "t1"); orc_program_append_2 (p, "select0lw", 0, ORC_VAR_T1, ORC_VAR_S1, @@ -2096,14 +2010,6 @@ orc_unpack_yuyv_v (orc_uint8 * d1, const orc_uint32 * s1, int n) orc_program_set_backup_function (p, _backup_orc_unpack_yuyv_v); orc_program_add_destination (p, 1, "d1"); orc_program_add_source (p, 4, "s1"); - orc_program_add_constant (p, 0, 0x00000000, "c1"); - orc_program_add_constant (p, 0, 0x00000000, "c2"); - orc_program_add_constant (p, 0, 0x00000000, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_add_temporary (p, 2, "t1"); orc_program_append_2 (p, "select1lw", 0, ORC_VAR_T1, ORC_VAR_S1, @@ -2167,13 +2073,14 @@ orc_pack_yuyv (orc_uint32 * d1, const guint8 * s1, const orc_uint8 * s2, /* 4: loadb */ var38 = ptr5[i]; /* 5: mergebw */ - var44.i = ((orc_uint8) var42) | ((orc_uint8) var38 << 8); + var44.i = ((orc_uint8) var42 & 0x00ff) | ((orc_uint8) var38 << 8); /* 6: loadb */ var39 = ptr6[i]; /* 7: mergebw */ - var45.i = ((orc_uint8) var43) | ((orc_uint8) var39 << 8); + var45.i = ((orc_uint8) var43 & 0x00ff) | ((orc_uint8) var39 << 8); /* 8: mergewl */ - var40.i = ((orc_uint16) var44.i) | ((orc_uint16) var45.i << 16); + var40.i = + ((orc_uint16) var44.i & 0x0000ffff) | ((orc_uint16) var45.i << 16); /* 9: storel */ ptr0[i] = var40; } @@ -2218,13 +2125,14 @@ _backup_orc_pack_yuyv (OrcExecutor * ex) /* 4: loadb */ var38 = ptr5[i]; /* 5: mergebw */ - var44.i = ((orc_uint8) var42) | ((orc_uint8) var38 << 8); + var44.i = ((orc_uint8) var42 & 0x00ff) | ((orc_uint8) var38 << 8); /* 6: loadb */ var39 = ptr6[i]; /* 7: mergebw */ - var45.i = ((orc_uint8) var43) | ((orc_uint8) var39 << 8); + var45.i = ((orc_uint8) var43 & 0x00ff) | ((orc_uint8) var39 << 8); /* 8: mergewl */ - var40.i = ((orc_uint16) var44.i) | ((orc_uint16) var45.i << 16); + var40.i = + ((orc_uint16) var44.i & 0x0000ffff) | ((orc_uint16) var45.i << 16); /* 9: storel */ ptr0[i] = var40; } @@ -2252,14 +2160,6 @@ orc_pack_yuyv (orc_uint32 * d1, const guint8 * s1, const orc_uint8 * s2, orc_program_add_source (p, 2, "s1"); orc_program_add_source (p, 1, "s2"); orc_program_add_source (p, 1, "s3"); - orc_program_add_constant (p, 0, 0x00000000, "c1"); - orc_program_add_constant (p, 0, 0x00000000, "c2"); - orc_program_add_constant (p, 0, 0x00000000, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_add_temporary (p, 1, "t1"); orc_program_add_temporary (p, 1, "t2"); orc_program_add_temporary (p, 2, "t3"); @@ -2368,14 +2268,6 @@ orc_unpack_uyvy_y (orc_uint8 * d1, const orc_uint16 * s1, int n) orc_program_set_backup_function (p, _backup_orc_unpack_uyvy_y); orc_program_add_destination (p, 1, "d1"); orc_program_add_source (p, 2, "s1"); - orc_program_add_constant (p, 0, 0x00000000, "c1"); - orc_program_add_constant (p, 0, 0x00000000, "c2"); - orc_program_add_constant (p, 0, 0x00000000, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_append_2 (p, "select1wb", 0, ORC_VAR_D1, ORC_VAR_S1, ORC_VAR_D1, ORC_VAR_D1); @@ -2473,14 +2365,6 @@ orc_unpack_uyvy_u (orc_uint8 * d1, const orc_uint32 * s1, int n) orc_program_set_backup_function (p, _backup_orc_unpack_uyvy_u); orc_program_add_destination (p, 1, "d1"); orc_program_add_source (p, 4, "s1"); - orc_program_add_constant (p, 0, 0x00000000, "c1"); - orc_program_add_constant (p, 0, 0x00000000, "c2"); - orc_program_add_constant (p, 0, 0x00000000, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_add_temporary (p, 2, "t1"); orc_program_append_2 (p, "select0lw", 0, ORC_VAR_T1, ORC_VAR_S1, @@ -2581,14 +2465,6 @@ orc_unpack_uyvy_v (orc_uint8 * d1, const orc_uint32 * s1, int n) orc_program_set_backup_function (p, _backup_orc_unpack_uyvy_v); orc_program_add_destination (p, 1, "d1"); orc_program_add_source (p, 4, "s1"); - orc_program_add_constant (p, 0, 0x00000000, "c1"); - orc_program_add_constant (p, 0, 0x00000000, "c2"); - orc_program_add_constant (p, 0, 0x00000000, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_add_temporary (p, 2, "t1"); orc_program_append_2 (p, "select1lw", 0, ORC_VAR_T1, ORC_VAR_S1, @@ -2652,13 +2528,14 @@ orc_pack_uyvy (orc_uint32 * d1, const guint8 * s1, const orc_uint8 * s2, /* 4: loadb */ var38 = ptr5[i]; /* 5: mergebw */ - var44.i = ((orc_uint8) var38) | ((orc_uint8) var42 << 8); + var44.i = ((orc_uint8) var38 & 0x00ff) | ((orc_uint8) var42 << 8); /* 6: loadb */ var39 = ptr6[i]; /* 7: mergebw */ - var45.i = ((orc_uint8) var39) | ((orc_uint8) var43 << 8); + var45.i = ((orc_uint8) var39 & 0x00ff) | ((orc_uint8) var43 << 8); /* 8: mergewl */ - var40.i = ((orc_uint16) var44.i) | ((orc_uint16) var45.i << 16); + var40.i = + ((orc_uint16) var44.i & 0x0000ffff) | ((orc_uint16) var45.i << 16); /* 9: storel */ ptr0[i] = var40; } @@ -2703,13 +2580,14 @@ _backup_orc_pack_uyvy (OrcExecutor * ex) /* 4: loadb */ var38 = ptr5[i]; /* 5: mergebw */ - var44.i = ((orc_uint8) var38) | ((orc_uint8) var42 << 8); + var44.i = ((orc_uint8) var38 & 0x00ff) | ((orc_uint8) var42 << 8); /* 6: loadb */ var39 = ptr6[i]; /* 7: mergebw */ - var45.i = ((orc_uint8) var39) | ((orc_uint8) var43 << 8); + var45.i = ((orc_uint8) var39 & 0x00ff) | ((orc_uint8) var43 << 8); /* 8: mergewl */ - var40.i = ((orc_uint16) var44.i) | ((orc_uint16) var45.i << 16); + var40.i = + ((orc_uint16) var44.i & 0x0000ffff) | ((orc_uint16) var45.i << 16); /* 9: storel */ ptr0[i] = var40; } @@ -2737,14 +2615,6 @@ orc_pack_uyvy (orc_uint32 * d1, const guint8 * s1, const orc_uint8 * s2, orc_program_add_source (p, 2, "s1"); orc_program_add_source (p, 1, "s2"); orc_program_add_source (p, 1, "s3"); - orc_program_add_constant (p, 0, 0x00000000, "c1"); - orc_program_add_constant (p, 0, 0x00000000, "c2"); - orc_program_add_constant (p, 0, 0x00000000, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_add_temporary (p, 1, "t1"); orc_program_add_temporary (p, 1, "t2"); orc_program_add_temporary (p, 2, "t3"); @@ -2866,13 +2736,6 @@ orc_addc_convert_u8_s16 (orc_uint8 * d1, const gint16 * s1, int n) orc_program_add_destination (p, 1, "d1"); orc_program_add_source (p, 2, "s1"); orc_program_add_constant (p, 4, 0x00000080, "c1"); - orc_program_add_constant (p, 0, 0x00000000, "c2"); - orc_program_add_constant (p, 0, 0x00000000, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_add_temporary (p, 2, "t1"); orc_program_append_2 (p, "addw", 0, ORC_VAR_T1, ORC_VAR_S1, ORC_VAR_C1, @@ -2980,13 +2843,6 @@ orc_subc_convert_s16_u8 (gint16 * d1, const orc_uint8 * s1, int n) orc_program_add_destination (p, 2, "d1"); orc_program_add_source (p, 1, "s1"); orc_program_add_constant (p, 4, 0x00000080, "c1"); - orc_program_add_constant (p, 0, 0x00000000, "c2"); - orc_program_add_constant (p, 0, 0x00000000, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_add_temporary (p, 2, "t1"); orc_program_append_2 (p, "convubw", 0, ORC_VAR_T1, ORC_VAR_S1, ORC_VAR_D1, @@ -3076,14 +2932,6 @@ orc_splat_u8_ns (orc_uint8 * d1, int p1, int n) orc_program_set_name (p, "orc_splat_u8_ns"); orc_program_set_backup_function (p, _backup_orc_splat_u8_ns); orc_program_add_destination (p, 1, "d1"); - orc_program_add_constant (p, 0, 0x00000000, "c1"); - orc_program_add_constant (p, 0, 0x00000000, "c2"); - orc_program_add_constant (p, 0, 0x00000000, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_add_parameter (p, 1, "p1"); orc_program_append_2 (p, "copyb", 0, ORC_VAR_D1, ORC_VAR_P1, ORC_VAR_D1, @@ -3171,14 +3019,6 @@ orc_splat_s16_ns (gint16 * d1, int p1, int n) orc_program_set_name (p, "orc_splat_s16_ns"); orc_program_set_backup_function (p, _backup_orc_splat_s16_ns); orc_program_add_destination (p, 2, "d1"); - orc_program_add_constant (p, 0, 0x00000000, "c1"); - orc_program_add_constant (p, 0, 0x00000000, "c2"); - orc_program_add_constant (p, 0, 0x00000000, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_add_parameter (p, 2, "p1"); orc_program_append_2 (p, "copyw", 0, ORC_VAR_D1, ORC_VAR_P1, ORC_VAR_D1, @@ -3345,13 +3185,6 @@ orc_matrix2_u8 (guint8 * d1, const guint8 * s1, const guint8 * s2, int p1, orc_program_add_source (p, 1, "s1"); orc_program_add_source (p, 1, "s2"); orc_program_add_constant (p, 4, 0x00000006, "c1"); - orc_program_add_constant (p, 0, 0x00000000, "c2"); - orc_program_add_constant (p, 0, 0x00000000, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_add_parameter (p, 2, "p1"); orc_program_add_parameter (p, 2, "p2"); orc_program_add_parameter (p, 2, "p3"); @@ -3578,11 +3411,6 @@ orc_matrix2_11_u8 (guint8 * d1, const guint8 * s1, const guint8 * s2, int p1, orc_program_add_constant (p, 4, 0x00000010, "c1"); orc_program_add_constant (p, 4, 0x00000080, "c2"); orc_program_add_constant (p, 4, 0x00000008, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_add_parameter (p, 2, "p1"); orc_program_add_parameter (p, 2, "p2"); orc_program_add_temporary (p, 2, "t1"); @@ -3823,11 +3651,6 @@ orc_matrix2_12_u8 (guint8 * d1, const guint8 * s1, const guint8 * s2, int p1, orc_program_add_constant (p, 4, 0x00000010, "c1"); orc_program_add_constant (p, 4, 0x00000080, "c2"); orc_program_add_constant (p, 4, 0x00000008, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_add_parameter (p, 2, "p1"); orc_program_add_parameter (p, 2, "p2"); orc_program_add_temporary (p, 2, "t1"); @@ -4061,13 +3884,6 @@ orc_matrix3_u8 (guint8 * d1, const guint8 * s1, const guint8 * s2, orc_program_add_source (p, 1, "s2"); orc_program_add_source (p, 1, "s3"); orc_program_add_constant (p, 4, 0x00000006, "c1"); - orc_program_add_constant (p, 0, 0x00000000, "c2"); - orc_program_add_constant (p, 0, 0x00000000, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_add_parameter (p, 2, "p1"); orc_program_add_parameter (p, 2, "p2"); orc_program_add_parameter (p, 2, "p3"); @@ -4344,11 +4160,6 @@ orc_matrix3_100_u8 (guint8 * d1, const guint8 * s1, const guint8 * s2, orc_program_add_constant (p, 4, 0x00000010, "c1"); orc_program_add_constant (p, 4, 0x00000080, "c2"); orc_program_add_constant (p, 4, 0x00000008, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_add_parameter (p, 2, "p1"); orc_program_add_parameter (p, 2, "p2"); orc_program_add_parameter (p, 2, "p3"); @@ -4593,14 +4404,6 @@ orc_matrix3_100_offset_u8 (guint8 * d1, const guint8 * s1, const guint8 * s2, orc_program_add_source (p, 1, "s1"); orc_program_add_source (p, 1, "s2"); orc_program_add_source (p, 1, "s3"); - orc_program_add_constant (p, 0, 0x00000000, "c1"); - orc_program_add_constant (p, 0, 0x00000000, "c2"); - orc_program_add_constant (p, 0, 0x00000000, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_add_parameter (p, 2, "p1"); orc_program_add_parameter (p, 2, "p2"); orc_program_add_parameter (p, 2, "p3"); @@ -4837,14 +4640,6 @@ orc_matrix3_000_u8 (guint8 * d1, const guint8 * s1, const guint8 * s2, orc_program_add_source (p, 1, "s1"); orc_program_add_source (p, 1, "s2"); orc_program_add_source (p, 1, "s3"); - orc_program_add_constant (p, 0, 0x00000000, "c1"); - orc_program_add_constant (p, 0, 0x00000000, "c2"); - orc_program_add_constant (p, 0, 0x00000000, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_add_parameter (p, 2, "p1"); orc_program_add_parameter (p, 2, "p2"); orc_program_add_parameter (p, 2, "p3"); @@ -4933,13 +4728,14 @@ orc_pack_123x (guint32 * d1, const orc_uint8 * s1, const orc_uint8 * s2, /* 1: loadb */ var35 = ptr5[i]; /* 2: mergebw */ - var39.i = ((orc_uint8) var34) | ((orc_uint8) var35 << 8); + var39.i = ((orc_uint8) var34 & 0x00ff) | ((orc_uint8) var35 << 8); /* 3: loadb */ var36 = ptr6[i]; /* 5: mergebw */ - var40.i = ((orc_uint8) var36) | ((orc_uint8) var37 << 8); + var40.i = ((orc_uint8) var36 & 0x00ff) | ((orc_uint8) var37 << 8); /* 6: mergewl */ - var38.i = ((orc_uint16) var39.i) | ((orc_uint16) var40.i << 16); + var38.i = + ((orc_uint16) var39.i & 0x0000ffff) | ((orc_uint16) var40.i << 16); /* 7: storel */ ptr0[i] = var38; } @@ -4978,13 +4774,14 @@ _backup_orc_pack_123x (OrcExecutor * ex) /* 1: loadb */ var35 = ptr5[i]; /* 2: mergebw */ - var39.i = ((orc_uint8) var34) | ((orc_uint8) var35 << 8); + var39.i = ((orc_uint8) var34 & 0x00ff) | ((orc_uint8) var35 << 8); /* 3: loadb */ var36 = ptr6[i]; /* 5: mergebw */ - var40.i = ((orc_uint8) var36) | ((orc_uint8) var37 << 8); + var40.i = ((orc_uint8) var36 & 0x00ff) | ((orc_uint8) var37 << 8); /* 6: mergewl */ - var38.i = ((orc_uint16) var39.i) | ((orc_uint16) var40.i << 16); + var38.i = + ((orc_uint16) var39.i & 0x0000ffff) | ((orc_uint16) var40.i << 16); /* 7: storel */ ptr0[i] = var38; } @@ -5012,14 +4809,6 @@ orc_pack_123x (guint32 * d1, const orc_uint8 * s1, const orc_uint8 * s2, orc_program_add_source (p, 1, "s1"); orc_program_add_source (p, 1, "s2"); orc_program_add_source (p, 1, "s3"); - orc_program_add_constant (p, 0, 0x00000000, "c1"); - orc_program_add_constant (p, 0, 0x00000000, "c2"); - orc_program_add_constant (p, 0, 0x00000000, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_add_parameter (p, 1, "p1"); orc_program_add_temporary (p, 2, "t1"); orc_program_add_temporary (p, 2, "t2"); @@ -5082,15 +4871,16 @@ orc_pack_x123 (guint32 * d1, const orc_uint8 * s1, const orc_uint8 * s2, /* 1: loadb */ var35 = ptr4[i]; /* 2: mergebw */ - var39.i = ((orc_uint8) var34) | ((orc_uint8) var35 << 8); + var39.i = ((orc_uint8) var34 & 0x00ff) | ((orc_uint8) var35 << 8); /* 3: loadb */ var36 = ptr5[i]; /* 4: loadb */ var37 = ptr6[i]; /* 5: mergebw */ - var40.i = ((orc_uint8) var36) | ((orc_uint8) var37 << 8); + var40.i = ((orc_uint8) var36 & 0x00ff) | ((orc_uint8) var37 << 8); /* 6: mergewl */ - var38.i = ((orc_uint16) var39.i) | ((orc_uint16) var40.i << 16); + var38.i = + ((orc_uint16) var39.i & 0x0000ffff) | ((orc_uint16) var40.i << 16); /* 7: storel */ ptr0[i] = var38; } @@ -5127,15 +4917,16 @@ _backup_orc_pack_x123 (OrcExecutor * ex) /* 1: loadb */ var35 = ptr4[i]; /* 2: mergebw */ - var39.i = ((orc_uint8) var34) | ((orc_uint8) var35 << 8); + var39.i = ((orc_uint8) var34 & 0x00ff) | ((orc_uint8) var35 << 8); /* 3: loadb */ var36 = ptr5[i]; /* 4: loadb */ var37 = ptr6[i]; /* 5: mergebw */ - var40.i = ((orc_uint8) var36) | ((orc_uint8) var37 << 8); + var40.i = ((orc_uint8) var36 & 0x00ff) | ((orc_uint8) var37 << 8); /* 6: mergewl */ - var38.i = ((orc_uint16) var39.i) | ((orc_uint16) var40.i << 16); + var38.i = + ((orc_uint16) var39.i & 0x0000ffff) | ((orc_uint16) var40.i << 16); /* 7: storel */ ptr0[i] = var38; } @@ -5163,14 +4954,6 @@ orc_pack_x123 (guint32 * d1, const orc_uint8 * s1, const orc_uint8 * s2, orc_program_add_source (p, 1, "s1"); orc_program_add_source (p, 1, "s2"); orc_program_add_source (p, 1, "s3"); - orc_program_add_constant (p, 0, 0x00000000, "c1"); - orc_program_add_constant (p, 0, 0x00000000, "c2"); - orc_program_add_constant (p, 0, 0x00000000, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_add_parameter (p, 1, "p1"); orc_program_add_temporary (p, 2, "t1"); orc_program_add_temporary (p, 2, "t2"); @@ -5334,13 +5117,6 @@ cogorc_combine2_u8 (orc_uint8 * d1, const orc_uint8 * s1, const orc_uint8 * s2, orc_program_add_source (p, 1, "s1"); orc_program_add_source (p, 1, "s2"); orc_program_add_constant (p, 4, 0x00000008, "c1"); - orc_program_add_constant (p, 0, 0x00000000, "c2"); - orc_program_add_constant (p, 0, 0x00000000, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_add_parameter (p, 2, "p1"); orc_program_add_parameter (p, 2, "p2"); orc_program_add_temporary (p, 2, "t1"); @@ -5598,12 +5374,6 @@ cogorc_combine4_u8 (orc_uint8 * d1, const orc_uint8 * s1, const orc_uint8 * s2, orc_program_add_source (p, 1, "s4"); orc_program_add_constant (p, 4, 0x00000020, "c1"); orc_program_add_constant (p, 4, 0x00000006, "c2"); - orc_program_add_constant (p, 0, 0x00000000, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_add_parameter (p, 2, "p1"); orc_program_add_parameter (p, 2, "p2"); orc_program_add_parameter (p, 2, "p3"); @@ -5740,14 +5510,6 @@ cogorc_unpack_axyz_0 (orc_uint8 * d1, const orc_uint32 * s1, int n) orc_program_set_backup_function (p, _backup_cogorc_unpack_axyz_0); orc_program_add_destination (p, 1, "d1"); orc_program_add_source (p, 4, "s1"); - orc_program_add_constant (p, 0, 0x00000000, "c1"); - orc_program_add_constant (p, 0, 0x00000000, "c2"); - orc_program_add_constant (p, 0, 0x00000000, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_add_temporary (p, 2, "t1"); orc_program_append_2 (p, "select0lw", 0, ORC_VAR_T1, ORC_VAR_S1, @@ -5848,14 +5610,6 @@ cogorc_unpack_axyz_1 (orc_uint8 * d1, const orc_uint32 * s1, int n) orc_program_set_backup_function (p, _backup_cogorc_unpack_axyz_1); orc_program_add_destination (p, 1, "d1"); orc_program_add_source (p, 4, "s1"); - orc_program_add_constant (p, 0, 0x00000000, "c1"); - orc_program_add_constant (p, 0, 0x00000000, "c2"); - orc_program_add_constant (p, 0, 0x00000000, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_add_temporary (p, 2, "t1"); orc_program_append_2 (p, "select0lw", 0, ORC_VAR_T1, ORC_VAR_S1, @@ -5956,14 +5710,6 @@ cogorc_unpack_axyz_2 (orc_uint8 * d1, const orc_uint32 * s1, int n) orc_program_set_backup_function (p, _backup_cogorc_unpack_axyz_2); orc_program_add_destination (p, 1, "d1"); orc_program_add_source (p, 4, "s1"); - orc_program_add_constant (p, 0, 0x00000000, "c1"); - orc_program_add_constant (p, 0, 0x00000000, "c2"); - orc_program_add_constant (p, 0, 0x00000000, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_add_temporary (p, 2, "t1"); orc_program_append_2 (p, "select1lw", 0, ORC_VAR_T1, ORC_VAR_S1, @@ -6064,14 +5810,6 @@ cogorc_unpack_axyz_3 (orc_uint8 * d1, const orc_uint32 * s1, int n) orc_program_set_backup_function (p, _backup_cogorc_unpack_axyz_3); orc_program_add_destination (p, 1, "d1"); orc_program_add_source (p, 4, "s1"); - orc_program_add_constant (p, 0, 0x00000000, "c1"); - orc_program_add_constant (p, 0, 0x00000000, "c2"); - orc_program_add_constant (p, 0, 0x00000000, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_add_temporary (p, 2, "t1"); orc_program_append_2 (p, "select1lw", 0, ORC_VAR_T1, ORC_VAR_S1, @@ -6162,14 +5900,6 @@ cogorc_resample_horiz_1tap (orc_uint8 * d1, const orc_uint8 * s1, int p1, orc_program_set_backup_function (p, _backup_cogorc_resample_horiz_1tap); orc_program_add_destination (p, 1, "d1"); orc_program_add_source (p, 1, "s1"); - orc_program_add_constant (p, 0, 0x00000000, "c1"); - orc_program_add_constant (p, 0, 0x00000000, "c2"); - orc_program_add_constant (p, 0, 0x00000000, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_add_parameter (p, 4, "p1"); orc_program_add_parameter (p, 4, "p2"); @@ -6271,14 +6001,6 @@ cogorc_resample_horiz_2tap (orc_uint8 * d1, const orc_uint8 * s1, int p1, orc_program_set_backup_function (p, _backup_cogorc_resample_horiz_2tap); orc_program_add_destination (p, 1, "d1"); orc_program_add_source (p, 1, "s1"); - orc_program_add_constant (p, 0, 0x00000000, "c1"); - orc_program_add_constant (p, 0, 0x00000000, "c2"); - orc_program_add_constant (p, 0, 0x00000000, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_add_parameter (p, 4, "p1"); orc_program_add_parameter (p, 4, "p2"); @@ -6340,19 +6062,23 @@ cogorc_convert_I420_UYVY (orc_uint32 * d1, orc_uint32 * d2, /* 1: loadb */ var34 = ptr7[i]; /* 2: mergebw */ - var39.i = ((orc_uint8) var33) | ((orc_uint8) var34 << 8); + var39.i = ((orc_uint8) var33 & 0x00ff) | ((orc_uint8) var34 << 8); /* 3: loadw */ var35 = ptr4[i]; /* 4: mergebw */ - var36.x2[0] = ((orc_uint8) var39.x2[0]) | ((orc_uint8) var35.x2[0] << 8); - var36.x2[1] = ((orc_uint8) var39.x2[1]) | ((orc_uint8) var35.x2[1] << 8); + var36.x2[0] = + ((orc_uint8) var39.x2[0] & 0x00ff) | ((orc_uint8) var35.x2[0] << 8); + var36.x2[1] = + ((orc_uint8) var39.x2[1] & 0x00ff) | ((orc_uint8) var35.x2[1] << 8); /* 5: storel */ ptr0[i] = var36; /* 6: loadw */ var37 = ptr5[i]; /* 7: mergebw */ - var38.x2[0] = ((orc_uint8) var39.x2[0]) | ((orc_uint8) var37.x2[0] << 8); - var38.x2[1] = ((orc_uint8) var39.x2[1]) | ((orc_uint8) var37.x2[1] << 8); + var38.x2[0] = + ((orc_uint8) var39.x2[0] & 0x00ff) | ((orc_uint8) var37.x2[0] << 8); + var38.x2[1] = + ((orc_uint8) var39.x2[1] & 0x00ff) | ((orc_uint8) var37.x2[1] << 8); /* 8: storel */ ptr1[i] = var38; } @@ -6393,19 +6119,23 @@ _backup_cogorc_convert_I420_UYVY (OrcExecutor * ex) /* 1: loadb */ var34 = ptr7[i]; /* 2: mergebw */ - var39.i = ((orc_uint8) var33) | ((orc_uint8) var34 << 8); + var39.i = ((orc_uint8) var33 & 0x00ff) | ((orc_uint8) var34 << 8); /* 3: loadw */ var35 = ptr4[i]; /* 4: mergebw */ - var36.x2[0] = ((orc_uint8) var39.x2[0]) | ((orc_uint8) var35.x2[0] << 8); - var36.x2[1] = ((orc_uint8) var39.x2[1]) | ((orc_uint8) var35.x2[1] << 8); + var36.x2[0] = + ((orc_uint8) var39.x2[0] & 0x00ff) | ((orc_uint8) var35.x2[0] << 8); + var36.x2[1] = + ((orc_uint8) var39.x2[1] & 0x00ff) | ((orc_uint8) var35.x2[1] << 8); /* 5: storel */ ptr0[i] = var36; /* 6: loadw */ var37 = ptr5[i]; /* 7: mergebw */ - var38.x2[0] = ((orc_uint8) var39.x2[0]) | ((orc_uint8) var37.x2[0] << 8); - var38.x2[1] = ((orc_uint8) var39.x2[1]) | ((orc_uint8) var37.x2[1] << 8); + var38.x2[0] = + ((orc_uint8) var39.x2[0] & 0x00ff) | ((orc_uint8) var37.x2[0] << 8); + var38.x2[1] = + ((orc_uint8) var39.x2[1] & 0x00ff) | ((orc_uint8) var37.x2[1] << 8); /* 8: storel */ ptr1[i] = var38; } @@ -6436,14 +6166,6 @@ cogorc_convert_I420_UYVY (orc_uint32 * d1, orc_uint32 * d2, orc_program_add_source (p, 2, "s2"); orc_program_add_source (p, 1, "s3"); orc_program_add_source (p, 1, "s4"); - orc_program_add_constant (p, 0, 0x00000000, "c1"); - orc_program_add_constant (p, 0, 0x00000000, "c2"); - orc_program_add_constant (p, 0, 0x00000000, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_add_temporary (p, 2, "t1"); orc_program_append_2 (p, "mergebw", 0, ORC_VAR_T1, ORC_VAR_S3, ORC_VAR_S4, @@ -6510,19 +6232,23 @@ cogorc_convert_I420_YUY2 (orc_uint32 * d1, orc_uint32 * d2, /* 1: loadb */ var34 = ptr7[i]; /* 2: mergebw */ - var39.i = ((orc_uint8) var33) | ((orc_uint8) var34 << 8); + var39.i = ((orc_uint8) var33 & 0x00ff) | ((orc_uint8) var34 << 8); /* 3: loadw */ var35 = ptr4[i]; /* 4: mergebw */ - var36.x2[0] = ((orc_uint8) var35.x2[0]) | ((orc_uint8) var39.x2[0] << 8); - var36.x2[1] = ((orc_uint8) var35.x2[1]) | ((orc_uint8) var39.x2[1] << 8); + var36.x2[0] = + ((orc_uint8) var35.x2[0] & 0x00ff) | ((orc_uint8) var39.x2[0] << 8); + var36.x2[1] = + ((orc_uint8) var35.x2[1] & 0x00ff) | ((orc_uint8) var39.x2[1] << 8); /* 5: storel */ ptr0[i] = var36; /* 6: loadw */ var37 = ptr5[i]; /* 7: mergebw */ - var38.x2[0] = ((orc_uint8) var37.x2[0]) | ((orc_uint8) var39.x2[0] << 8); - var38.x2[1] = ((orc_uint8) var37.x2[1]) | ((orc_uint8) var39.x2[1] << 8); + var38.x2[0] = + ((orc_uint8) var37.x2[0] & 0x00ff) | ((orc_uint8) var39.x2[0] << 8); + var38.x2[1] = + ((orc_uint8) var37.x2[1] & 0x00ff) | ((orc_uint8) var39.x2[1] << 8); /* 8: storel */ ptr1[i] = var38; } @@ -6563,19 +6289,23 @@ _backup_cogorc_convert_I420_YUY2 (OrcExecutor * ex) /* 1: loadb */ var34 = ptr7[i]; /* 2: mergebw */ - var39.i = ((orc_uint8) var33) | ((orc_uint8) var34 << 8); + var39.i = ((orc_uint8) var33 & 0x00ff) | ((orc_uint8) var34 << 8); /* 3: loadw */ var35 = ptr4[i]; /* 4: mergebw */ - var36.x2[0] = ((orc_uint8) var35.x2[0]) | ((orc_uint8) var39.x2[0] << 8); - var36.x2[1] = ((orc_uint8) var35.x2[1]) | ((orc_uint8) var39.x2[1] << 8); + var36.x2[0] = + ((orc_uint8) var35.x2[0] & 0x00ff) | ((orc_uint8) var39.x2[0] << 8); + var36.x2[1] = + ((orc_uint8) var35.x2[1] & 0x00ff) | ((orc_uint8) var39.x2[1] << 8); /* 5: storel */ ptr0[i] = var36; /* 6: loadw */ var37 = ptr5[i]; /* 7: mergebw */ - var38.x2[0] = ((orc_uint8) var37.x2[0]) | ((orc_uint8) var39.x2[0] << 8); - var38.x2[1] = ((orc_uint8) var37.x2[1]) | ((orc_uint8) var39.x2[1] << 8); + var38.x2[0] = + ((orc_uint8) var37.x2[0] & 0x00ff) | ((orc_uint8) var39.x2[0] << 8); + var38.x2[1] = + ((orc_uint8) var37.x2[1] & 0x00ff) | ((orc_uint8) var39.x2[1] << 8); /* 8: storel */ ptr1[i] = var38; } @@ -6606,14 +6336,6 @@ cogorc_convert_I420_YUY2 (orc_uint32 * d1, orc_uint32 * d2, orc_program_add_source (p, 2, "s2"); orc_program_add_source (p, 1, "s3"); orc_program_add_source (p, 1, "s4"); - orc_program_add_constant (p, 0, 0x00000000, "c1"); - orc_program_add_constant (p, 0, 0x00000000, "c2"); - orc_program_add_constant (p, 0, 0x00000000, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_add_temporary (p, 2, "t1"); orc_program_append_2 (p, "mergebw", 0, ORC_VAR_T1, ORC_VAR_S3, ORC_VAR_S4, @@ -6688,21 +6410,23 @@ cogorc_convert_I420_AYUV (orc_uint32 * d1, orc_uint32 * d2, /* 1: loadupdb */ var43 = ptr7[i >> 1]; /* 2: mergebw */ - var44.i = ((orc_uint8) var42) | ((orc_uint8) var43 << 8); + var44.i = ((orc_uint8) var42 & 0x00ff) | ((orc_uint8) var43 << 8); /* 4: loadb */ var37 = ptr4[i]; /* 5: mergebw */ - var45.i = ((orc_uint8) var36) | ((orc_uint8) var37 << 8); + var45.i = ((orc_uint8) var36 & 0x00ff) | ((orc_uint8) var37 << 8); /* 6: mergewl */ - var38.i = ((orc_uint16) var45.i) | ((orc_uint16) var44.i << 16); + var38.i = + ((orc_uint16) var45.i & 0x0000ffff) | ((orc_uint16) var44.i << 16); /* 7: storel */ ptr0[i] = var38; /* 9: loadb */ var40 = ptr5[i]; /* 10: mergebw */ - var46.i = ((orc_uint8) var39) | ((orc_uint8) var40 << 8); + var46.i = ((orc_uint8) var39 & 0x00ff) | ((orc_uint8) var40 << 8); /* 11: mergewl */ - var41.i = ((orc_uint16) var46.i) | ((orc_uint16) var44.i << 16); + var41.i = + ((orc_uint16) var46.i & 0x0000ffff) | ((orc_uint16) var44.i << 16); /* 12: storel */ ptr1[i] = var41; } @@ -6751,21 +6475,23 @@ _backup_cogorc_convert_I420_AYUV (OrcExecutor * ex) /* 1: loadupdb */ var43 = ptr7[i >> 1]; /* 2: mergebw */ - var44.i = ((orc_uint8) var42) | ((orc_uint8) var43 << 8); + var44.i = ((orc_uint8) var42 & 0x00ff) | ((orc_uint8) var43 << 8); /* 4: loadb */ var37 = ptr4[i]; /* 5: mergebw */ - var45.i = ((orc_uint8) var36) | ((orc_uint8) var37 << 8); + var45.i = ((orc_uint8) var36 & 0x00ff) | ((orc_uint8) var37 << 8); /* 6: mergewl */ - var38.i = ((orc_uint16) var45.i) | ((orc_uint16) var44.i << 16); + var38.i = + ((orc_uint16) var45.i & 0x0000ffff) | ((orc_uint16) var44.i << 16); /* 7: storel */ ptr0[i] = var38; /* 9: loadb */ var40 = ptr5[i]; /* 10: mergebw */ - var46.i = ((orc_uint8) var39) | ((orc_uint8) var40 << 8); + var46.i = ((orc_uint8) var39 & 0x00ff) | ((orc_uint8) var40 << 8); /* 11: mergewl */ - var41.i = ((orc_uint16) var46.i) | ((orc_uint16) var44.i << 16); + var41.i = + ((orc_uint16) var46.i & 0x0000ffff) | ((orc_uint16) var44.i << 16); /* 12: storel */ ptr1[i] = var41; } @@ -6797,13 +6523,6 @@ cogorc_convert_I420_AYUV (orc_uint32 * d1, orc_uint32 * d2, orc_program_add_source (p, 1, "s3"); orc_program_add_source (p, 1, "s4"); orc_program_add_constant (p, 1, 0x000000ff, "c1"); - orc_program_add_constant (p, 0, 0x00000000, "c2"); - orc_program_add_constant (p, 0, 0x00000000, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_add_temporary (p, 2, "t1"); orc_program_add_temporary (p, 2, "t2"); orc_program_add_temporary (p, 1, "t3"); @@ -6995,14 +6714,6 @@ cogorc_convert_YUY2_I420 (orc_uint16 * d1, orc_uint16 * d2, orc_uint8 * d3, orc_program_add_destination (p, 1, "d4"); orc_program_add_source (p, 4, "s1"); orc_program_add_source (p, 4, "s2"); - orc_program_add_constant (p, 0, 0x00000000, "c1"); - orc_program_add_constant (p, 0, 0x00000000, "c2"); - orc_program_add_constant (p, 0, 0x00000000, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_add_temporary (p, 2, "t1"); orc_program_add_temporary (p, 2, "t2"); orc_program_add_temporary (p, 2, "t3"); @@ -7123,14 +6834,6 @@ cogorc_convert_UYVY_YUY2 (orc_uint32 * d1, int d1_stride, const orc_uint32 * s1, orc_program_set_backup_function (p, _backup_cogorc_convert_UYVY_YUY2); orc_program_add_destination (p, 4, "d1"); orc_program_add_source (p, 4, "s1"); - orc_program_add_constant (p, 0, 0x00000000, "c1"); - orc_program_add_constant (p, 0, 0x00000000, "c2"); - orc_program_add_constant (p, 0, 0x00000000, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_append_2 (p, "swapw", 1, ORC_VAR_D1, ORC_VAR_S1, ORC_VAR_D1, ORC_VAR_D1); @@ -7256,14 +6959,6 @@ cogorc_planar_chroma_420_422 (orc_uint8 * d1, int d1_stride, orc_uint8 * d2, orc_program_add_destination (p, 1, "d1"); orc_program_add_destination (p, 1, "d2"); orc_program_add_source (p, 1, "s1"); - orc_program_add_constant (p, 0, 0x00000000, "c1"); - orc_program_add_constant (p, 0, 0x00000000, "c2"); - orc_program_add_constant (p, 0, 0x00000000, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_append_2 (p, "copyb", 0, ORC_VAR_D1, ORC_VAR_S1, ORC_VAR_D1, ORC_VAR_D1); @@ -7381,14 +7076,6 @@ cogorc_planar_chroma_420_444 (orc_uint16 * d1, int d1_stride, orc_uint16 * d2, orc_program_add_destination (p, 2, "d1"); orc_program_add_destination (p, 2, "d2"); orc_program_add_source (p, 1, "s1"); - orc_program_add_constant (p, 0, 0x00000000, "c1"); - orc_program_add_constant (p, 0, 0x00000000, "c2"); - orc_program_add_constant (p, 0, 0x00000000, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_add_temporary (p, 2, "t1"); orc_program_append_2 (p, "splatbw", 0, ORC_VAR_T1, ORC_VAR_S1, ORC_VAR_D1, @@ -7500,14 +7187,6 @@ cogorc_planar_chroma_422_444 (orc_uint16 * d1, int d1_stride, orc_program_set_backup_function (p, _backup_cogorc_planar_chroma_422_444); orc_program_add_destination (p, 2, "d1"); orc_program_add_source (p, 1, "s1"); - orc_program_add_constant (p, 0, 0x00000000, "c1"); - orc_program_add_constant (p, 0, 0x00000000, "c2"); - orc_program_add_constant (p, 0, 0x00000000, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_add_temporary (p, 2, "t1"); orc_program_append_2 (p, "splatbw", 0, ORC_VAR_T1, ORC_VAR_S1, ORC_VAR_D1, @@ -7625,14 +7304,6 @@ cogorc_planar_chroma_444_422 (orc_uint8 * d1, int d1_stride, orc_program_set_backup_function (p, _backup_cogorc_planar_chroma_444_422); orc_program_add_destination (p, 1, "d1"); orc_program_add_source (p, 2, "s1"); - orc_program_add_constant (p, 0, 0x00000000, "c1"); - orc_program_add_constant (p, 0, 0x00000000, "c2"); - orc_program_add_constant (p, 0, 0x00000000, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_add_temporary (p, 1, "t1"); orc_program_add_temporary (p, 1, "t2"); @@ -7776,14 +7447,6 @@ cogorc_planar_chroma_444_420 (orc_uint8 * d1, int d1_stride, orc_program_add_destination (p, 1, "d1"); orc_program_add_source (p, 2, "s1"); orc_program_add_source (p, 2, "s2"); - orc_program_add_constant (p, 0, 0x00000000, "c1"); - orc_program_add_constant (p, 0, 0x00000000, "c2"); - orc_program_add_constant (p, 0, 0x00000000, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_add_temporary (p, 2, "t1"); orc_program_add_temporary (p, 1, "t2"); orc_program_add_temporary (p, 1, "t3"); @@ -7910,14 +7573,6 @@ cogorc_planar_chroma_422_420 (orc_uint8 * d1, int d1_stride, orc_program_add_destination (p, 1, "d1"); orc_program_add_source (p, 1, "s1"); orc_program_add_source (p, 1, "s2"); - orc_program_add_constant (p, 0, 0x00000000, "c1"); - orc_program_add_constant (p, 0, 0x00000000, "c2"); - orc_program_add_constant (p, 0, 0x00000000, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_append_2 (p, "avgub", 0, ORC_VAR_D1, ORC_VAR_S1, ORC_VAR_S2, ORC_VAR_D1); @@ -7979,15 +7634,20 @@ cogorc_convert_YUY2_AYUV (orc_uint64 * d1, int d1_stride, const orc_uint32 * s1, var39.x2[1] = (var36.x2[1] >> 8) & 0xff; var40.x2[1] = var36.x2[1] & 0xff; /* 3: mergebw */ - var41.x2[0] = ((orc_uint8) var37.x2[0]) | ((orc_uint8) var40.x2[0] << 8); - var41.x2[1] = ((orc_uint8) var37.x2[1]) | ((orc_uint8) var40.x2[1] << 8); + var41.x2[0] = + ((orc_uint8) var37.x2[0] & 0x00ff) | ((orc_uint8) var40.x2[0] << 8); + var41.x2[1] = + ((orc_uint8) var37.x2[1] & 0x00ff) | ((orc_uint8) var40.x2[1] << 8); /* 4: mergewl */ - var42.i = ((orc_uint16) var39.i) | ((orc_uint16) var39.i << 16); + var42.i = + ((orc_uint16) var39.i & 0x0000ffff) | ((orc_uint16) var39.i << 16); /* 5: mergewl */ var38.x2[0] = - ((orc_uint16) var41.x2[0]) | ((orc_uint16) var42.x2[0] << 16); + ((orc_uint16) var41.x2[0] & 0x0000ffff) | ((orc_uint16) var42. + x2[0] << 16); var38.x2[1] = - ((orc_uint16) var41.x2[1]) | ((orc_uint16) var42.x2[1] << 16); + ((orc_uint16) var41.x2[1] & 0x0000ffff) | ((orc_uint16) var42. + x2[1] << 16); /* 6: storeq */ ptr0[i] = var38; } @@ -8030,15 +7690,20 @@ _backup_cogorc_convert_YUY2_AYUV (OrcExecutor * ex) var39.x2[1] = (var36.x2[1] >> 8) & 0xff; var40.x2[1] = var36.x2[1] & 0xff; /* 3: mergebw */ - var41.x2[0] = ((orc_uint8) var37.x2[0]) | ((orc_uint8) var40.x2[0] << 8); - var41.x2[1] = ((orc_uint8) var37.x2[1]) | ((orc_uint8) var40.x2[1] << 8); + var41.x2[0] = + ((orc_uint8) var37.x2[0] & 0x00ff) | ((orc_uint8) var40.x2[0] << 8); + var41.x2[1] = + ((orc_uint8) var37.x2[1] & 0x00ff) | ((orc_uint8) var40.x2[1] << 8); /* 4: mergewl */ - var42.i = ((orc_uint16) var39.i) | ((orc_uint16) var39.i << 16); + var42.i = + ((orc_uint16) var39.i & 0x0000ffff) | ((orc_uint16) var39.i << 16); /* 5: mergewl */ var38.x2[0] = - ((orc_uint16) var41.x2[0]) | ((orc_uint16) var42.x2[0] << 16); + ((orc_uint16) var41.x2[0] & 0x0000ffff) | ((orc_uint16) var42. + x2[0] << 16); var38.x2[1] = - ((orc_uint16) var41.x2[1]) | ((orc_uint16) var42.x2[1] << 16); + ((orc_uint16) var41.x2[1] & 0x0000ffff) | ((orc_uint16) var42. + x2[1] << 16); /* 6: storeq */ ptr0[i] = var38; } @@ -8067,13 +7732,6 @@ cogorc_convert_YUY2_AYUV (orc_uint64 * d1, int d1_stride, const orc_uint32 * s1, orc_program_add_destination (p, 8, "d1"); orc_program_add_source (p, 4, "s1"); orc_program_add_constant (p, 2, 0x000000ff, "c1"); - orc_program_add_constant (p, 0, 0x00000000, "c2"); - orc_program_add_constant (p, 0, 0x00000000, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_add_temporary (p, 2, "t1"); orc_program_add_temporary (p, 2, "t2"); orc_program_add_temporary (p, 4, "t3"); @@ -8143,15 +7801,20 @@ cogorc_convert_UYVY_AYUV (orc_uint64 * d1, int d1_stride, const orc_uint32 * s1, var39.x2[1] = (var36.x2[1] >> 8) & 0xff; var40.x2[1] = var36.x2[1] & 0xff; /* 3: mergebw */ - var41.x2[0] = ((orc_uint8) var37.x2[0]) | ((orc_uint8) var39.x2[0] << 8); - var41.x2[1] = ((orc_uint8) var37.x2[1]) | ((orc_uint8) var39.x2[1] << 8); + var41.x2[0] = + ((orc_uint8) var37.x2[0] & 0x00ff) | ((orc_uint8) var39.x2[0] << 8); + var41.x2[1] = + ((orc_uint8) var37.x2[1] & 0x00ff) | ((orc_uint8) var39.x2[1] << 8); /* 4: mergewl */ - var42.i = ((orc_uint16) var40.i) | ((orc_uint16) var40.i << 16); + var42.i = + ((orc_uint16) var40.i & 0x0000ffff) | ((orc_uint16) var40.i << 16); /* 5: mergewl */ var38.x2[0] = - ((orc_uint16) var41.x2[0]) | ((orc_uint16) var42.x2[0] << 16); + ((orc_uint16) var41.x2[0] & 0x0000ffff) | ((orc_uint16) var42. + x2[0] << 16); var38.x2[1] = - ((orc_uint16) var41.x2[1]) | ((orc_uint16) var42.x2[1] << 16); + ((orc_uint16) var41.x2[1] & 0x0000ffff) | ((orc_uint16) var42. + x2[1] << 16); /* 6: storeq */ ptr0[i] = var38; } @@ -8194,15 +7857,20 @@ _backup_cogorc_convert_UYVY_AYUV (OrcExecutor * ex) var39.x2[1] = (var36.x2[1] >> 8) & 0xff; var40.x2[1] = var36.x2[1] & 0xff; /* 3: mergebw */ - var41.x2[0] = ((orc_uint8) var37.x2[0]) | ((orc_uint8) var39.x2[0] << 8); - var41.x2[1] = ((orc_uint8) var37.x2[1]) | ((orc_uint8) var39.x2[1] << 8); + var41.x2[0] = + ((orc_uint8) var37.x2[0] & 0x00ff) | ((orc_uint8) var39.x2[0] << 8); + var41.x2[1] = + ((orc_uint8) var37.x2[1] & 0x00ff) | ((orc_uint8) var39.x2[1] << 8); /* 4: mergewl */ - var42.i = ((orc_uint16) var40.i) | ((orc_uint16) var40.i << 16); + var42.i = + ((orc_uint16) var40.i & 0x0000ffff) | ((orc_uint16) var40.i << 16); /* 5: mergewl */ var38.x2[0] = - ((orc_uint16) var41.x2[0]) | ((orc_uint16) var42.x2[0] << 16); + ((orc_uint16) var41.x2[0] & 0x0000ffff) | ((orc_uint16) var42. + x2[0] << 16); var38.x2[1] = - ((orc_uint16) var41.x2[1]) | ((orc_uint16) var42.x2[1] << 16); + ((orc_uint16) var41.x2[1] & 0x0000ffff) | ((orc_uint16) var42. + x2[1] << 16); /* 6: storeq */ ptr0[i] = var38; } @@ -8231,13 +7899,6 @@ cogorc_convert_UYVY_AYUV (orc_uint64 * d1, int d1_stride, const orc_uint32 * s1, orc_program_add_destination (p, 8, "d1"); orc_program_add_source (p, 4, "s1"); orc_program_add_constant (p, 2, 0x000000ff, "c1"); - orc_program_add_constant (p, 0, 0x00000000, "c2"); - orc_program_add_constant (p, 0, 0x00000000, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_add_temporary (p, 2, "t1"); orc_program_add_temporary (p, 2, "t2"); orc_program_add_temporary (p, 4, "t3"); @@ -8390,14 +8051,6 @@ cogorc_convert_YUY2_Y42B (orc_uint16 * d1, int d1_stride, orc_uint8 * d2, orc_program_add_destination (p, 1, "d2"); orc_program_add_destination (p, 1, "d3"); orc_program_add_source (p, 4, "s1"); - orc_program_add_constant (p, 0, 0x00000000, "c1"); - orc_program_add_constant (p, 0, 0x00000000, "c2"); - orc_program_add_constant (p, 0, 0x00000000, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_add_temporary (p, 2, "t1"); orc_program_append_2 (p, "splitwb", 1, ORC_VAR_T1, ORC_VAR_D1, ORC_VAR_S1, @@ -8547,14 +8200,6 @@ cogorc_convert_UYVY_Y42B (orc_uint16 * d1, int d1_stride, orc_uint8 * d2, orc_program_add_destination (p, 1, "d2"); orc_program_add_destination (p, 1, "d3"); orc_program_add_source (p, 4, "s1"); - orc_program_add_constant (p, 0, 0x00000000, "c1"); - orc_program_add_constant (p, 0, 0x00000000, "c2"); - orc_program_add_constant (p, 0, 0x00000000, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_add_temporary (p, 2, "t1"); orc_program_append_2 (p, "splitwb", 1, ORC_VAR_D1, ORC_VAR_T1, ORC_VAR_S1, @@ -8716,14 +8361,6 @@ cogorc_convert_YUY2_Y444 (orc_uint16 * d1, int d1_stride, orc_uint16 * d2, orc_program_add_destination (p, 2, "d2"); orc_program_add_destination (p, 2, "d3"); orc_program_add_source (p, 4, "s1"); - orc_program_add_constant (p, 0, 0x00000000, "c1"); - orc_program_add_constant (p, 0, 0x00000000, "c2"); - orc_program_add_constant (p, 0, 0x00000000, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_add_temporary (p, 2, "t1"); orc_program_add_temporary (p, 1, "t2"); orc_program_add_temporary (p, 1, "t3"); @@ -8891,14 +8528,6 @@ cogorc_convert_UYVY_Y444 (orc_uint16 * d1, int d1_stride, orc_uint16 * d2, orc_program_add_destination (p, 2, "d2"); orc_program_add_destination (p, 2, "d3"); orc_program_add_source (p, 4, "s1"); - orc_program_add_constant (p, 0, 0x00000000, "c1"); - orc_program_add_constant (p, 0, 0x00000000, "c2"); - orc_program_add_constant (p, 0, 0x00000000, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_add_temporary (p, 2, "t1"); orc_program_add_temporary (p, 1, "t2"); orc_program_add_temporary (p, 1, "t3"); @@ -9086,14 +8715,6 @@ cogorc_convert_UYVY_I420 (orc_uint16 * d1, orc_uint16 * d2, orc_uint8 * d3, orc_program_add_destination (p, 1, "d4"); orc_program_add_source (p, 4, "s1"); orc_program_add_source (p, 4, "s2"); - orc_program_add_constant (p, 0, 0x00000000, "c1"); - orc_program_add_constant (p, 0, 0x00000000, "c2"); - orc_program_add_constant (p, 0, 0x00000000, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_add_temporary (p, 2, "t1"); orc_program_add_temporary (p, 2, "t2"); orc_program_add_temporary (p, 2, "t3"); @@ -9358,14 +8979,6 @@ cogorc_convert_AYUV_I420 (orc_uint16 * d1, int d1_stride, orc_uint16 * d2, orc_program_add_destination (p, 1, "d4"); orc_program_add_source (p, 8, "s1"); orc_program_add_source (p, 8, "s2"); - orc_program_add_constant (p, 0, 0x00000000, "c1"); - orc_program_add_constant (p, 0, 0x00000000, "c2"); - orc_program_add_constant (p, 0, 0x00000000, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_add_temporary (p, 4, "t1"); orc_program_add_temporary (p, 4, "t2"); orc_program_add_temporary (p, 4, "t3"); @@ -9468,8 +9081,10 @@ cogorc_convert_AYUV_YUY2 (orc_uint32 * d1, int d1_stride, const orc_uint64 * s1, var44.x2[0] = ((orc_uint16) var40.x2[0] >> 8) & 0xff; var44.x2[1] = ((orc_uint16) var40.x2[1] >> 8) & 0xff; /* 5: mergebw */ - var38.x2[0] = ((orc_uint8) var44.x2[0]) | ((orc_uint8) var43.x2[0] << 8); - var38.x2[1] = ((orc_uint8) var44.x2[1]) | ((orc_uint8) var43.x2[1] << 8); + var38.x2[0] = + ((orc_uint8) var44.x2[0] & 0x00ff) | ((orc_uint8) var43.x2[0] << 8); + var38.x2[1] = + ((orc_uint8) var44.x2[1] & 0x00ff) | ((orc_uint8) var43.x2[1] << 8); /* 6: storel */ ptr0[i] = var38; } @@ -9521,8 +9136,10 @@ _backup_cogorc_convert_AYUV_YUY2 (OrcExecutor * ex) var44.x2[0] = ((orc_uint16) var40.x2[0] >> 8) & 0xff; var44.x2[1] = ((orc_uint16) var40.x2[1] >> 8) & 0xff; /* 5: mergebw */ - var38.x2[0] = ((orc_uint8) var44.x2[0]) | ((orc_uint8) var43.x2[0] << 8); - var38.x2[1] = ((orc_uint8) var44.x2[1]) | ((orc_uint8) var43.x2[1] << 8); + var38.x2[0] = + ((orc_uint8) var44.x2[0] & 0x00ff) | ((orc_uint8) var43.x2[0] << 8); + var38.x2[1] = + ((orc_uint8) var44.x2[1] & 0x00ff) | ((orc_uint8) var43.x2[1] << 8); /* 6: storel */ ptr0[i] = var38; } @@ -9550,14 +9167,6 @@ cogorc_convert_AYUV_YUY2 (orc_uint32 * d1, int d1_stride, const orc_uint64 * s1, orc_program_set_backup_function (p, _backup_cogorc_convert_AYUV_YUY2); orc_program_add_destination (p, 4, "d1"); orc_program_add_source (p, 8, "s1"); - orc_program_add_constant (p, 0, 0x00000000, "c1"); - orc_program_add_constant (p, 0, 0x00000000, "c2"); - orc_program_add_constant (p, 0, 0x00000000, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_add_temporary (p, 2, "t1"); orc_program_add_temporary (p, 2, "t2"); orc_program_add_temporary (p, 2, "t3"); @@ -9639,8 +9248,10 @@ cogorc_convert_AYUV_UYVY (orc_uint32 * d1, int d1_stride, const orc_uint64 * s1, var44.x2[0] = ((orc_uint16) var40.x2[0] >> 8) & 0xff; var44.x2[1] = ((orc_uint16) var40.x2[1] >> 8) & 0xff; /* 5: mergebw */ - var38.x2[0] = ((orc_uint8) var43.x2[0]) | ((orc_uint8) var44.x2[0] << 8); - var38.x2[1] = ((orc_uint8) var43.x2[1]) | ((orc_uint8) var44.x2[1] << 8); + var38.x2[0] = + ((orc_uint8) var43.x2[0] & 0x00ff) | ((orc_uint8) var44.x2[0] << 8); + var38.x2[1] = + ((orc_uint8) var43.x2[1] & 0x00ff) | ((orc_uint8) var44.x2[1] << 8); /* 6: storel */ ptr0[i] = var38; } @@ -9692,8 +9303,10 @@ _backup_cogorc_convert_AYUV_UYVY (OrcExecutor * ex) var44.x2[0] = ((orc_uint16) var40.x2[0] >> 8) & 0xff; var44.x2[1] = ((orc_uint16) var40.x2[1] >> 8) & 0xff; /* 5: mergebw */ - var38.x2[0] = ((orc_uint8) var43.x2[0]) | ((orc_uint8) var44.x2[0] << 8); - var38.x2[1] = ((orc_uint8) var43.x2[1]) | ((orc_uint8) var44.x2[1] << 8); + var38.x2[0] = + ((orc_uint8) var43.x2[0] & 0x00ff) | ((orc_uint8) var44.x2[0] << 8); + var38.x2[1] = + ((orc_uint8) var43.x2[1] & 0x00ff) | ((orc_uint8) var44.x2[1] << 8); /* 6: storel */ ptr0[i] = var38; } @@ -9721,14 +9334,6 @@ cogorc_convert_AYUV_UYVY (orc_uint32 * d1, int d1_stride, const orc_uint64 * s1, orc_program_set_backup_function (p, _backup_cogorc_convert_AYUV_UYVY); orc_program_add_destination (p, 4, "d1"); orc_program_add_source (p, 8, "s1"); - orc_program_add_constant (p, 0, 0x00000000, "c1"); - orc_program_add_constant (p, 0, 0x00000000, "c2"); - orc_program_add_constant (p, 0, 0x00000000, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_add_temporary (p, 2, "t1"); orc_program_add_temporary (p, 2, "t2"); orc_program_add_temporary (p, 2, "t3"); @@ -9914,14 +9519,6 @@ cogorc_convert_AYUV_Y42B (orc_uint16 * d1, int d1_stride, orc_uint8 * d2, orc_program_add_destination (p, 1, "d2"); orc_program_add_destination (p, 1, "d3"); orc_program_add_source (p, 8, "s1"); - orc_program_add_constant (p, 0, 0x00000000, "c1"); - orc_program_add_constant (p, 0, 0x00000000, "c2"); - orc_program_add_constant (p, 0, 0x00000000, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_add_temporary (p, 4, "t1"); orc_program_add_temporary (p, 4, "t2"); orc_program_add_temporary (p, 2, "t3"); @@ -10082,14 +9679,6 @@ cogorc_convert_AYUV_Y444 (orc_uint8 * d1, int d1_stride, orc_uint8 * d2, orc_program_add_destination (p, 1, "d2"); orc_program_add_destination (p, 1, "d3"); orc_program_add_source (p, 4, "s1"); - orc_program_add_constant (p, 0, 0x00000000, "c1"); - orc_program_add_constant (p, 0, 0x00000000, "c2"); - orc_program_add_constant (p, 0, 0x00000000, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_add_temporary (p, 2, "t1"); orc_program_add_temporary (p, 2, "t2"); @@ -10156,12 +9745,14 @@ cogorc_convert_Y42B_YUY2 (orc_uint32 * d1, int d1_stride, const orc_uint16 * s1, /* 1: loadb */ var34 = ptr6[i]; /* 2: mergebw */ - var37.i = ((orc_uint8) var33) | ((orc_uint8) var34 << 8); + var37.i = ((orc_uint8) var33 & 0x00ff) | ((orc_uint8) var34 << 8); /* 3: loadw */ var35 = ptr4[i]; /* 4: mergebw */ - var36.x2[0] = ((orc_uint8) var35.x2[0]) | ((orc_uint8) var37.x2[0] << 8); - var36.x2[1] = ((orc_uint8) var35.x2[1]) | ((orc_uint8) var37.x2[1] << 8); + var36.x2[0] = + ((orc_uint8) var35.x2[0] & 0x00ff) | ((orc_uint8) var37.x2[0] << 8); + var36.x2[1] = + ((orc_uint8) var35.x2[1] & 0x00ff) | ((orc_uint8) var37.x2[1] << 8); /* 5: storel */ ptr0[i] = var36; } @@ -10200,12 +9791,14 @@ _backup_cogorc_convert_Y42B_YUY2 (OrcExecutor * ex) /* 1: loadb */ var34 = ptr6[i]; /* 2: mergebw */ - var37.i = ((orc_uint8) var33) | ((orc_uint8) var34 << 8); + var37.i = ((orc_uint8) var33 & 0x00ff) | ((orc_uint8) var34 << 8); /* 3: loadw */ var35 = ptr4[i]; /* 4: mergebw */ - var36.x2[0] = ((orc_uint8) var35.x2[0]) | ((orc_uint8) var37.x2[0] << 8); - var36.x2[1] = ((orc_uint8) var35.x2[1]) | ((orc_uint8) var37.x2[1] << 8); + var36.x2[0] = + ((orc_uint8) var35.x2[0] & 0x00ff) | ((orc_uint8) var37.x2[0] << 8); + var36.x2[1] = + ((orc_uint8) var35.x2[1] & 0x00ff) | ((orc_uint8) var37.x2[1] << 8); /* 5: storel */ ptr0[i] = var36; } @@ -10236,14 +9829,6 @@ cogorc_convert_Y42B_YUY2 (orc_uint32 * d1, int d1_stride, const orc_uint16 * s1, orc_program_add_source (p, 2, "s1"); orc_program_add_source (p, 1, "s2"); orc_program_add_source (p, 1, "s3"); - orc_program_add_constant (p, 0, 0x00000000, "c1"); - orc_program_add_constant (p, 0, 0x00000000, "c2"); - orc_program_add_constant (p, 0, 0x00000000, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_add_temporary (p, 2, "t1"); orc_program_append_2 (p, "mergebw", 0, ORC_VAR_T1, ORC_VAR_S2, ORC_VAR_S3, @@ -10307,12 +9892,14 @@ cogorc_convert_Y42B_UYVY (orc_uint32 * d1, int d1_stride, const orc_uint16 * s1, /* 1: loadb */ var34 = ptr6[i]; /* 2: mergebw */ - var37.i = ((orc_uint8) var33) | ((orc_uint8) var34 << 8); + var37.i = ((orc_uint8) var33 & 0x00ff) | ((orc_uint8) var34 << 8); /* 3: loadw */ var35 = ptr4[i]; /* 4: mergebw */ - var36.x2[0] = ((orc_uint8) var37.x2[0]) | ((orc_uint8) var35.x2[0] << 8); - var36.x2[1] = ((orc_uint8) var37.x2[1]) | ((orc_uint8) var35.x2[1] << 8); + var36.x2[0] = + ((orc_uint8) var37.x2[0] & 0x00ff) | ((orc_uint8) var35.x2[0] << 8); + var36.x2[1] = + ((orc_uint8) var37.x2[1] & 0x00ff) | ((orc_uint8) var35.x2[1] << 8); /* 5: storel */ ptr0[i] = var36; } @@ -10351,12 +9938,14 @@ _backup_cogorc_convert_Y42B_UYVY (OrcExecutor * ex) /* 1: loadb */ var34 = ptr6[i]; /* 2: mergebw */ - var37.i = ((orc_uint8) var33) | ((orc_uint8) var34 << 8); + var37.i = ((orc_uint8) var33 & 0x00ff) | ((orc_uint8) var34 << 8); /* 3: loadw */ var35 = ptr4[i]; /* 4: mergebw */ - var36.x2[0] = ((orc_uint8) var37.x2[0]) | ((orc_uint8) var35.x2[0] << 8); - var36.x2[1] = ((orc_uint8) var37.x2[1]) | ((orc_uint8) var35.x2[1] << 8); + var36.x2[0] = + ((orc_uint8) var37.x2[0] & 0x00ff) | ((orc_uint8) var35.x2[0] << 8); + var36.x2[1] = + ((orc_uint8) var37.x2[1] & 0x00ff) | ((orc_uint8) var35.x2[1] << 8); /* 5: storel */ ptr0[i] = var36; } @@ -10387,14 +9976,6 @@ cogorc_convert_Y42B_UYVY (orc_uint32 * d1, int d1_stride, const orc_uint16 * s1, orc_program_add_source (p, 2, "s1"); orc_program_add_source (p, 1, "s2"); orc_program_add_source (p, 1, "s3"); - orc_program_add_constant (p, 0, 0x00000000, "c1"); - orc_program_add_constant (p, 0, 0x00000000, "c2"); - orc_program_add_constant (p, 0, 0x00000000, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_add_temporary (p, 2, "t1"); orc_program_append_2 (p, "mergebw", 0, ORC_VAR_T1, ORC_VAR_S2, ORC_VAR_S3, @@ -10464,19 +10045,24 @@ cogorc_convert_Y42B_AYUV (orc_uint64 * d1, int d1_stride, const orc_uint16 * s1, /* 1: loadb */ var37 = ptr6[i]; /* 2: mergebw */ - var41.i = ((orc_uint8) var36) | ((orc_uint8) var37 << 8); + var41.i = ((orc_uint8) var36 & 0x00ff) | ((orc_uint8) var37 << 8); /* 4: loadw */ var39 = ptr4[i]; /* 5: mergebw */ - var42.x2[0] = ((orc_uint8) var38.x2[0]) | ((orc_uint8) var39.x2[0] << 8); - var42.x2[1] = ((orc_uint8) var38.x2[1]) | ((orc_uint8) var39.x2[1] << 8); + var42.x2[0] = + ((orc_uint8) var38.x2[0] & 0x00ff) | ((orc_uint8) var39.x2[0] << 8); + var42.x2[1] = + ((orc_uint8) var38.x2[1] & 0x00ff) | ((orc_uint8) var39.x2[1] << 8); /* 6: mergewl */ - var43.i = ((orc_uint16) var41.i) | ((orc_uint16) var41.i << 16); + var43.i = + ((orc_uint16) var41.i & 0x0000ffff) | ((orc_uint16) var41.i << 16); /* 7: mergewl */ var40.x2[0] = - ((orc_uint16) var42.x2[0]) | ((orc_uint16) var43.x2[0] << 16); + ((orc_uint16) var42.x2[0] & 0x0000ffff) | ((orc_uint16) var43. + x2[0] << 16); var40.x2[1] = - ((orc_uint16) var42.x2[1]) | ((orc_uint16) var43.x2[1] << 16); + ((orc_uint16) var42.x2[1] & 0x0000ffff) | ((orc_uint16) var43. + x2[1] << 16); /* 8: storeq */ ptr0[i] = var40; } @@ -10521,19 +10107,24 @@ _backup_cogorc_convert_Y42B_AYUV (OrcExecutor * ex) /* 1: loadb */ var37 = ptr6[i]; /* 2: mergebw */ - var41.i = ((orc_uint8) var36) | ((orc_uint8) var37 << 8); + var41.i = ((orc_uint8) var36 & 0x00ff) | ((orc_uint8) var37 << 8); /* 4: loadw */ var39 = ptr4[i]; /* 5: mergebw */ - var42.x2[0] = ((orc_uint8) var38.x2[0]) | ((orc_uint8) var39.x2[0] << 8); - var42.x2[1] = ((orc_uint8) var38.x2[1]) | ((orc_uint8) var39.x2[1] << 8); + var42.x2[0] = + ((orc_uint8) var38.x2[0] & 0x00ff) | ((orc_uint8) var39.x2[0] << 8); + var42.x2[1] = + ((orc_uint8) var38.x2[1] & 0x00ff) | ((orc_uint8) var39.x2[1] << 8); /* 6: mergewl */ - var43.i = ((orc_uint16) var41.i) | ((orc_uint16) var41.i << 16); + var43.i = + ((orc_uint16) var41.i & 0x0000ffff) | ((orc_uint16) var41.i << 16); /* 7: mergewl */ var40.x2[0] = - ((orc_uint16) var42.x2[0]) | ((orc_uint16) var43.x2[0] << 16); + ((orc_uint16) var42.x2[0] & 0x0000ffff) | ((orc_uint16) var43. + x2[0] << 16); var40.x2[1] = - ((orc_uint16) var42.x2[1]) | ((orc_uint16) var43.x2[1] << 16); + ((orc_uint16) var42.x2[1] & 0x0000ffff) | ((orc_uint16) var43. + x2[1] << 16); /* 8: storeq */ ptr0[i] = var40; } @@ -10565,13 +10156,6 @@ cogorc_convert_Y42B_AYUV (orc_uint64 * d1, int d1_stride, const orc_uint16 * s1, orc_program_add_source (p, 1, "s2"); orc_program_add_source (p, 1, "s3"); orc_program_add_constant (p, 1, 0x000000ff, "c1"); - orc_program_add_constant (p, 0, 0x00000000, "c2"); - orc_program_add_constant (p, 0, 0x00000000, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_add_temporary (p, 2, "t1"); orc_program_add_temporary (p, 2, "t2"); orc_program_add_temporary (p, 4, "t3"); @@ -10645,8 +10229,10 @@ cogorc_convert_Y444_YUY2 (orc_uint32 * d1, int d1_stride, const orc_uint16 * s1, /* 1: loadw */ var37 = ptr6[i]; /* 2: mergebw */ - var40.x2[0] = ((orc_uint8) var36.x2[0]) | ((orc_uint8) var37.x2[0] << 8); - var40.x2[1] = ((orc_uint8) var36.x2[1]) | ((orc_uint8) var37.x2[1] << 8); + var40.x2[0] = + ((orc_uint8) var36.x2[0] & 0x00ff) | ((orc_uint8) var37.x2[0] << 8); + var40.x2[1] = + ((orc_uint8) var36.x2[1] & 0x00ff) | ((orc_uint8) var37.x2[1] << 8); /* 3: splitlw */ var41.i = (var40.i >> 16) & 0xffff; var42.i = var40.i & 0xffff; @@ -10658,8 +10244,10 @@ cogorc_convert_Y444_YUY2 (orc_uint32 * d1, int d1_stride, const orc_uint16 * s1, /* 5: loadw */ var38 = ptr4[i]; /* 6: mergebw */ - var39.x2[0] = ((orc_uint8) var38.x2[0]) | ((orc_uint8) var43.x2[0] << 8); - var39.x2[1] = ((orc_uint8) var38.x2[1]) | ((orc_uint8) var43.x2[1] << 8); + var39.x2[0] = + ((orc_uint8) var38.x2[0] & 0x00ff) | ((orc_uint8) var43.x2[0] << 8); + var39.x2[1] = + ((orc_uint8) var38.x2[1] & 0x00ff) | ((orc_uint8) var43.x2[1] << 8); /* 7: storel */ ptr0[i] = var39; } @@ -10701,8 +10289,10 @@ _backup_cogorc_convert_Y444_YUY2 (OrcExecutor * ex) /* 1: loadw */ var37 = ptr6[i]; /* 2: mergebw */ - var40.x2[0] = ((orc_uint8) var36.x2[0]) | ((orc_uint8) var37.x2[0] << 8); - var40.x2[1] = ((orc_uint8) var36.x2[1]) | ((orc_uint8) var37.x2[1] << 8); + var40.x2[0] = + ((orc_uint8) var36.x2[0] & 0x00ff) | ((orc_uint8) var37.x2[0] << 8); + var40.x2[1] = + ((orc_uint8) var36.x2[1] & 0x00ff) | ((orc_uint8) var37.x2[1] << 8); /* 3: splitlw */ var41.i = (var40.i >> 16) & 0xffff; var42.i = var40.i & 0xffff; @@ -10714,8 +10304,10 @@ _backup_cogorc_convert_Y444_YUY2 (OrcExecutor * ex) /* 5: loadw */ var38 = ptr4[i]; /* 6: mergebw */ - var39.x2[0] = ((orc_uint8) var38.x2[0]) | ((orc_uint8) var43.x2[0] << 8); - var39.x2[1] = ((orc_uint8) var38.x2[1]) | ((orc_uint8) var43.x2[1] << 8); + var39.x2[0] = + ((orc_uint8) var38.x2[0] & 0x00ff) | ((orc_uint8) var43.x2[0] << 8); + var39.x2[1] = + ((orc_uint8) var38.x2[1] & 0x00ff) | ((orc_uint8) var43.x2[1] << 8); /* 7: storel */ ptr0[i] = var39; } @@ -10746,14 +10338,6 @@ cogorc_convert_Y444_YUY2 (orc_uint32 * d1, int d1_stride, const orc_uint16 * s1, orc_program_add_source (p, 2, "s1"); orc_program_add_source (p, 2, "s2"); orc_program_add_source (p, 2, "s3"); - orc_program_add_constant (p, 0, 0x00000000, "c1"); - orc_program_add_constant (p, 0, 0x00000000, "c2"); - orc_program_add_constant (p, 0, 0x00000000, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_add_temporary (p, 2, "t1"); orc_program_add_temporary (p, 4, "t2"); orc_program_add_temporary (p, 2, "t3"); @@ -10827,8 +10411,10 @@ cogorc_convert_Y444_UYVY (orc_uint32 * d1, int d1_stride, const orc_uint16 * s1, /* 1: loadw */ var37 = ptr6[i]; /* 2: mergebw */ - var40.x2[0] = ((orc_uint8) var36.x2[0]) | ((orc_uint8) var37.x2[0] << 8); - var40.x2[1] = ((orc_uint8) var36.x2[1]) | ((orc_uint8) var37.x2[1] << 8); + var40.x2[0] = + ((orc_uint8) var36.x2[0] & 0x00ff) | ((orc_uint8) var37.x2[0] << 8); + var40.x2[1] = + ((orc_uint8) var36.x2[1] & 0x00ff) | ((orc_uint8) var37.x2[1] << 8); /* 3: splitlw */ var41.i = (var40.i >> 16) & 0xffff; var42.i = var40.i & 0xffff; @@ -10840,8 +10426,10 @@ cogorc_convert_Y444_UYVY (orc_uint32 * d1, int d1_stride, const orc_uint16 * s1, /* 5: loadw */ var38 = ptr4[i]; /* 6: mergebw */ - var39.x2[0] = ((orc_uint8) var43.x2[0]) | ((orc_uint8) var38.x2[0] << 8); - var39.x2[1] = ((orc_uint8) var43.x2[1]) | ((orc_uint8) var38.x2[1] << 8); + var39.x2[0] = + ((orc_uint8) var43.x2[0] & 0x00ff) | ((orc_uint8) var38.x2[0] << 8); + var39.x2[1] = + ((orc_uint8) var43.x2[1] & 0x00ff) | ((orc_uint8) var38.x2[1] << 8); /* 7: storel */ ptr0[i] = var39; } @@ -10883,8 +10471,10 @@ _backup_cogorc_convert_Y444_UYVY (OrcExecutor * ex) /* 1: loadw */ var37 = ptr6[i]; /* 2: mergebw */ - var40.x2[0] = ((orc_uint8) var36.x2[0]) | ((orc_uint8) var37.x2[0] << 8); - var40.x2[1] = ((orc_uint8) var36.x2[1]) | ((orc_uint8) var37.x2[1] << 8); + var40.x2[0] = + ((orc_uint8) var36.x2[0] & 0x00ff) | ((orc_uint8) var37.x2[0] << 8); + var40.x2[1] = + ((orc_uint8) var36.x2[1] & 0x00ff) | ((orc_uint8) var37.x2[1] << 8); /* 3: splitlw */ var41.i = (var40.i >> 16) & 0xffff; var42.i = var40.i & 0xffff; @@ -10896,8 +10486,10 @@ _backup_cogorc_convert_Y444_UYVY (OrcExecutor * ex) /* 5: loadw */ var38 = ptr4[i]; /* 6: mergebw */ - var39.x2[0] = ((orc_uint8) var43.x2[0]) | ((orc_uint8) var38.x2[0] << 8); - var39.x2[1] = ((orc_uint8) var43.x2[1]) | ((orc_uint8) var38.x2[1] << 8); + var39.x2[0] = + ((orc_uint8) var43.x2[0] & 0x00ff) | ((orc_uint8) var38.x2[0] << 8); + var39.x2[1] = + ((orc_uint8) var43.x2[1] & 0x00ff) | ((orc_uint8) var38.x2[1] << 8); /* 7: storel */ ptr0[i] = var39; } @@ -10928,14 +10520,6 @@ cogorc_convert_Y444_UYVY (orc_uint32 * d1, int d1_stride, const orc_uint16 * s1, orc_program_add_source (p, 2, "s1"); orc_program_add_source (p, 2, "s2"); orc_program_add_source (p, 2, "s3"); - orc_program_add_constant (p, 0, 0x00000000, "c1"); - orc_program_add_constant (p, 0, 0x00000000, "c2"); - orc_program_add_constant (p, 0, 0x00000000, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_add_temporary (p, 2, "t1"); orc_program_add_temporary (p, 4, "t2"); orc_program_add_temporary (p, 2, "t3"); @@ -11010,13 +10594,14 @@ cogorc_convert_Y444_AYUV (orc_uint32 * d1, int d1_stride, const orc_uint8 * s1, /* 1: loadb */ var35 = ptr6[i]; /* 2: mergebw */ - var39.i = ((orc_uint8) var34) | ((orc_uint8) var35 << 8); + var39.i = ((orc_uint8) var34 & 0x00ff) | ((orc_uint8) var35 << 8); /* 4: loadb */ var37 = ptr4[i]; /* 5: mergebw */ - var40.i = ((orc_uint8) var36) | ((orc_uint8) var37 << 8); + var40.i = ((orc_uint8) var36 & 0x00ff) | ((orc_uint8) var37 << 8); /* 6: mergewl */ - var38.i = ((orc_uint16) var40.i) | ((orc_uint16) var39.i << 16); + var38.i = + ((orc_uint16) var40.i & 0x0000ffff) | ((orc_uint16) var39.i << 16); /* 7: storel */ ptr0[i] = var38; } @@ -11059,13 +10644,14 @@ _backup_cogorc_convert_Y444_AYUV (OrcExecutor * ex) /* 1: loadb */ var35 = ptr6[i]; /* 2: mergebw */ - var39.i = ((orc_uint8) var34) | ((orc_uint8) var35 << 8); + var39.i = ((orc_uint8) var34 & 0x00ff) | ((orc_uint8) var35 << 8); /* 4: loadb */ var37 = ptr4[i]; /* 5: mergebw */ - var40.i = ((orc_uint8) var36) | ((orc_uint8) var37 << 8); + var40.i = ((orc_uint8) var36 & 0x00ff) | ((orc_uint8) var37 << 8); /* 6: mergewl */ - var38.i = ((orc_uint16) var40.i) | ((orc_uint16) var39.i << 16); + var38.i = + ((orc_uint16) var40.i & 0x0000ffff) | ((orc_uint16) var39.i << 16); /* 7: storel */ ptr0[i] = var38; } @@ -11097,13 +10683,6 @@ cogorc_convert_Y444_AYUV (orc_uint32 * d1, int d1_stride, const orc_uint8 * s1, orc_program_add_source (p, 1, "s2"); orc_program_add_source (p, 1, "s3"); orc_program_add_constant (p, 1, 0x000000ff, "c1"); - orc_program_add_constant (p, 0, 0x00000000, "c2"); - orc_program_add_constant (p, 0, 0x00000000, "c3"); - orc_program_add_constant (p, 0, 0x00000000, "c4"); - orc_program_add_constant (p, 0, 0x00000000, "c5"); - orc_program_add_constant (p, 0, 0x00000000, "c6"); - orc_program_add_constant (p, 0, 0x00000000, "c7"); - orc_program_add_constant (p, 0, 0x00000000, "c8"); orc_program_add_temporary (p, 2, "t1"); orc_program_add_temporary (p, 2, "t2"); @@ -11289,11 +10868,12 @@ cogorc_convert_AYUV_ARGB (orc_uint32 * d1, int d1_stride, const orc_uint32 * s1, /* 36: convssswb */ var89 = ORC_CLAMP_SB (var79.i); /* 37: mergebw */ - var90.i = ((orc_uint8) var61) | ((orc_uint8) var87 << 8); + var90.i = ((orc_uint8) var61 & 0x00ff) | ((orc_uint8) var87 << 8); /* 38: mergebw */ - var91.i = ((orc_uint8) var88) | ((orc_uint8) var89 << 8); + var91.i = ((orc_uint8) var88 & 0x00ff) | ((orc_uint8) var89 << 8); /* 39: mergewl */ - var92.i = ((orc_uint16) var90.i) | ((orc_uint16) var91.i << 16); + var92.i = + ((orc_uint16) var90.i & 0x0000ffff) | ((orc_uint16) var91.i << 16); /* 41: addb */ var56.x4[0] = var92.x4[0] + var55.x4[0]; var56.x4[1] = var92.x4[1] + var55.x4[1]; @@ -11457,11 +11037,12 @@ _backup_cogorc_convert_AYUV_ARGB (OrcExecutor * ex) /* 36: convssswb */ var89 = ORC_CLAMP_SB (var79.i); /* 37: mergebw */ - var90.i = ((orc_uint8) var61) | ((orc_uint8) var87 << 8); + var90.i = ((orc_uint8) var61 & 0x00ff) | ((orc_uint8) var87 << 8); /* 38: mergebw */ - var91.i = ((orc_uint8) var88) | ((orc_uint8) var89 << 8); + var91.i = ((orc_uint8) var88 & 0x00ff) | ((orc_uint8) var89 << 8); /* 39: mergewl */ - var92.i = ((orc_uint16) var90.i) | ((orc_uint16) var91.i << 16); + var92.i = + ((orc_uint16) var90.i & 0x0000ffff) | ((orc_uint16) var91.i << 16); /* 41: addb */ var56.x4[0] = var92.x4[0] + var55.x4[0]; var56.x4[1] = var92.x4[1] + var55.x4[1]; @@ -11501,7 +11082,6 @@ cogorc_convert_AYUV_ARGB (orc_uint32 * d1, int d1_stride, const orc_uint32 * s1, orc_program_add_constant (p, 4, 0x00000004, "c5"); orc_program_add_constant (p, 4, 0x00000064, "c6"); orc_program_add_constant (p, 4, 0x00000068, "c7"); - orc_program_add_constant (p, 0, 0x00000080, "c8"); orc_program_add_temporary (p, 2, "t1"); orc_program_add_temporary (p, 2, "t2"); orc_program_add_temporary (p, 1, "t3"); @@ -11759,11 +11339,12 @@ cogorc_convert_AYUV_BGRA (orc_uint32 * d1, int d1_stride, const orc_uint32 * s1, /* 36: convssswb */ var89 = ORC_CLAMP_SB (var79.i); /* 37: mergebw */ - var90.i = ((orc_uint8) var89) | ((orc_uint8) var88 << 8); + var90.i = ((orc_uint8) var89 & 0x00ff) | ((orc_uint8) var88 << 8); /* 38: mergebw */ - var91.i = ((orc_uint8) var87) | ((orc_uint8) var61 << 8); + var91.i = ((orc_uint8) var87 & 0x00ff) | ((orc_uint8) var61 << 8); /* 39: mergewl */ - var92.i = ((orc_uint16) var90.i) | ((orc_uint16) var91.i << 16); + var92.i = + ((orc_uint16) var90.i & 0x0000ffff) | ((orc_uint16) var91.i << 16); /* 41: addb */ var56.x4[0] = var92.x4[0] + var55.x4[0]; var56.x4[1] = var92.x4[1] + var55.x4[1]; @@ -11927,11 +11508,12 @@ _backup_cogorc_convert_AYUV_BGRA (OrcExecutor * ex) /* 36: convssswb */ var89 = ORC_CLAMP_SB (var79.i); /* 37: mergebw */ - var90.i = ((orc_uint8) var89) | ((orc_uint8) var88 << 8); + var90.i = ((orc_uint8) var89 & 0x00ff) | ((orc_uint8) var88 << 8); /* 38: mergebw */ - var91.i = ((orc_uint8) var87) | ((orc_uint8) var61 << 8); + var91.i = ((orc_uint8) var87 & 0x00ff) | ((orc_uint8) var61 << 8); /* 39: mergewl */ - var92.i = ((orc_uint16) var90.i) | ((orc_uint16) var91.i << 16); + var92.i = + ((orc_uint16) var90.i & 0x0000ffff) | ((orc_uint16) var91.i << 16); /* 41: addb */ var56.x4[0] = var92.x4[0] + var55.x4[0]; var56.x4[1] = var92.x4[1] + var55.x4[1]; @@ -11971,7 +11553,6 @@ cogorc_convert_AYUV_BGRA (orc_uint32 * d1, int d1_stride, const orc_uint32 * s1, orc_program_add_constant (p, 4, 0x00000004, "c5"); orc_program_add_constant (p, 4, 0x00000064, "c6"); orc_program_add_constant (p, 4, 0x00000068, "c7"); - orc_program_add_constant (p, 0, 0x00000080, "c8"); orc_program_add_temporary (p, 2, "t1"); orc_program_add_temporary (p, 2, "t2"); orc_program_add_temporary (p, 1, "t3"); @@ -12229,11 +11810,12 @@ cogorc_convert_AYUV_ABGR (orc_uint32 * d1, int d1_stride, const orc_uint32 * s1, /* 36: convssswb */ var89 = ORC_CLAMP_SB (var79.i); /* 37: mergebw */ - var90.i = ((orc_uint8) var61) | ((orc_uint8) var89 << 8); + var90.i = ((orc_uint8) var61 & 0x00ff) | ((orc_uint8) var89 << 8); /* 38: mergebw */ - var91.i = ((orc_uint8) var88) | ((orc_uint8) var87 << 8); + var91.i = ((orc_uint8) var88 & 0x00ff) | ((orc_uint8) var87 << 8); /* 39: mergewl */ - var92.i = ((orc_uint16) var90.i) | ((orc_uint16) var91.i << 16); + var92.i = + ((orc_uint16) var90.i & 0x0000ffff) | ((orc_uint16) var91.i << 16); /* 41: addb */ var56.x4[0] = var92.x4[0] + var55.x4[0]; var56.x4[1] = var92.x4[1] + var55.x4[1]; @@ -12397,11 +11979,12 @@ _backup_cogorc_convert_AYUV_ABGR (OrcExecutor * ex) /* 36: convssswb */ var89 = ORC_CLAMP_SB (var79.i); /* 37: mergebw */ - var90.i = ((orc_uint8) var61) | ((orc_uint8) var89 << 8); + var90.i = ((orc_uint8) var61 & 0x00ff) | ((orc_uint8) var89 << 8); /* 38: mergebw */ - var91.i = ((orc_uint8) var88) | ((orc_uint8) var87 << 8); + var91.i = ((orc_uint8) var88 & 0x00ff) | ((orc_uint8) var87 << 8); /* 39: mergewl */ - var92.i = ((orc_uint16) var90.i) | ((orc_uint16) var91.i << 16); + var92.i = + ((orc_uint16) var90.i & 0x0000ffff) | ((orc_uint16) var91.i << 16); /* 41: addb */ var56.x4[0] = var92.x4[0] + var55.x4[0]; var56.x4[1] = var92.x4[1] + var55.x4[1]; @@ -12441,7 +12024,6 @@ cogorc_convert_AYUV_ABGR (orc_uint32 * d1, int d1_stride, const orc_uint32 * s1, orc_program_add_constant (p, 4, 0x00000004, "c5"); orc_program_add_constant (p, 4, 0x00000064, "c6"); orc_program_add_constant (p, 4, 0x00000068, "c7"); - orc_program_add_constant (p, 0, 0x00000080, "c8"); orc_program_add_temporary (p, 2, "t1"); orc_program_add_temporary (p, 2, "t2"); orc_program_add_temporary (p, 1, "t3"); @@ -12699,11 +12281,12 @@ cogorc_convert_AYUV_RGBA (orc_uint32 * d1, int d1_stride, const orc_uint32 * s1, /* 36: convssswb */ var89 = ORC_CLAMP_SB (var79.i); /* 37: mergebw */ - var90.i = ((orc_uint8) var87) | ((orc_uint8) var88 << 8); + var90.i = ((orc_uint8) var87 & 0x00ff) | ((orc_uint8) var88 << 8); /* 38: mergebw */ - var91.i = ((orc_uint8) var89) | ((orc_uint8) var61 << 8); + var91.i = ((orc_uint8) var89 & 0x00ff) | ((orc_uint8) var61 << 8); /* 39: mergewl */ - var92.i = ((orc_uint16) var90.i) | ((orc_uint16) var91.i << 16); + var92.i = + ((orc_uint16) var90.i & 0x0000ffff) | ((orc_uint16) var91.i << 16); /* 41: addb */ var56.x4[0] = var92.x4[0] + var55.x4[0]; var56.x4[1] = var92.x4[1] + var55.x4[1]; @@ -12867,11 +12450,12 @@ _backup_cogorc_convert_AYUV_RGBA (OrcExecutor * ex) /* 36: convssswb */ var89 = ORC_CLAMP_SB (var79.i); /* 37: mergebw */ - var90.i = ((orc_uint8) var87) | ((orc_uint8) var88 << 8); + var90.i = ((orc_uint8) var87 & 0x00ff) | ((orc_uint8) var88 << 8); /* 38: mergebw */ - var91.i = ((orc_uint8) var89) | ((orc_uint8) var61 << 8); + var91.i = ((orc_uint8) var89 & 0x00ff) | ((orc_uint8) var61 << 8); /* 39: mergewl */ - var92.i = ((orc_uint16) var90.i) | ((orc_uint16) var91.i << 16); + var92.i = + ((orc_uint16) var90.i & 0x0000ffff) | ((orc_uint16) var91.i << 16); /* 41: addb */ var56.x4[0] = var92.x4[0] + var55.x4[0]; var56.x4[1] = var92.x4[1] + var55.x4[1]; @@ -12911,7 +12495,6 @@ cogorc_convert_AYUV_RGBA (orc_uint32 * d1, int d1_stride, const orc_uint32 * s1, orc_program_add_constant (p, 4, 0x00000004, "c5"); orc_program_add_constant (p, 4, 0x00000064, "c6"); orc_program_add_constant (p, 4, 0x00000068, "c7"); - orc_program_add_constant (p, 0, 0x00000080, "c8"); orc_program_add_temporary (p, 2, "t1"); orc_program_add_temporary (p, 2, "t2"); orc_program_add_temporary (p, 1, "t3"); @@ -13175,11 +12758,12 @@ cogorc_convert_I420_BGRA (orc_uint32 * d1, const orc_uint8 * s1, /* 39: convssswb */ var87 = ORC_CLAMP_SB (var77.i); /* 40: mergebw */ - var88.i = ((orc_uint8) var87) | ((orc_uint8) var86 << 8); + var88.i = ((orc_uint8) var87 & 0x00ff) | ((orc_uint8) var86 << 8); /* 42: mergebw */ - var89.i = ((orc_uint8) var85) | ((orc_uint8) var54 << 8); + var89.i = ((orc_uint8) var85 & 0x00ff) | ((orc_uint8) var54 << 8); /* 43: mergewl */ - var90.i = ((orc_uint16) var88.i) | ((orc_uint16) var89.i << 16); + var90.i = + ((orc_uint16) var88.i & 0x0000ffff) | ((orc_uint16) var89.i << 16); /* 45: addb */ var56.x4[0] = var90.x4[0] + var55.x4[0]; var56.x4[1] = var90.x4[1] + var55.x4[1]; @@ -13347,11 +12931,12 @@ _backup_cogorc_convert_I420_BGRA (OrcExecutor * ex) /* 39: convssswb */ var87 = ORC_CLAMP_SB (var77.i); /* 40: mergebw */ - var88.i = ((orc_uint8) var87) | ((orc_uint8) var86 << 8); + var88.i = ((orc_uint8) var87 & 0x00ff) | ((orc_uint8) var86 << 8); /* 42: mergebw */ - var89.i = ((orc_uint8) var85) | ((orc_uint8) var54 << 8); + var89.i = ((orc_uint8) var85 & 0x00ff) | ((orc_uint8) var54 << 8); /* 43: mergewl */ - var90.i = ((orc_uint16) var88.i) | ((orc_uint16) var89.i << 16); + var90.i = + ((orc_uint16) var88.i & 0x0000ffff) | ((orc_uint16) var89.i << 16); /* 45: addb */ var56.x4[0] = var90.x4[0] + var55.x4[0]; var56.x4[1] = var90.x4[1] + var55.x4[1]; @@ -13674,11 +13259,12 @@ cogorc_convert_I420_BGRA_avg (orc_uint32 * d1, const orc_uint8 * s1, /* 43: convssswb */ var92 = ORC_CLAMP_SB (var82.i); /* 44: mergebw */ - var93.i = ((orc_uint8) var92) | ((orc_uint8) var91 << 8); + var93.i = ((orc_uint8) var92 & 0x00ff) | ((orc_uint8) var91 << 8); /* 46: mergebw */ - var94.i = ((orc_uint8) var90) | ((orc_uint8) var55 << 8); + var94.i = ((orc_uint8) var90 & 0x00ff) | ((orc_uint8) var55 << 8); /* 47: mergewl */ - var95.i = ((orc_uint16) var93.i) | ((orc_uint16) var94.i << 16); + var95.i = + ((orc_uint16) var93.i & 0x0000ffff) | ((orc_uint16) var94.i << 16); /* 49: addb */ var57.x4[0] = var95.x4[0] + var56.x4[0]; var57.x4[1] = var95.x4[1] + var56.x4[1]; @@ -13866,11 +13452,12 @@ _backup_cogorc_convert_I420_BGRA_avg (OrcExecutor * ex) /* 43: convssswb */ var92 = ORC_CLAMP_SB (var82.i); /* 44: mergebw */ - var93.i = ((orc_uint8) var92) | ((orc_uint8) var91 << 8); + var93.i = ((orc_uint8) var92 & 0x00ff) | ((orc_uint8) var91 << 8); /* 46: mergebw */ - var94.i = ((orc_uint8) var90) | ((orc_uint8) var55 << 8); + var94.i = ((orc_uint8) var90 & 0x00ff) | ((orc_uint8) var55 << 8); /* 47: mergewl */ - var95.i = ((orc_uint16) var93.i) | ((orc_uint16) var94.i << 16); + var95.i = + ((orc_uint16) var93.i & 0x0000ffff) | ((orc_uint16) var94.i << 16); /* 49: addb */ var57.x4[0] = var95.x4[0] + var56.x4[0]; var57.x4[1] = var95.x4[1] + var56.x4[1]; diff --git a/ext/cog/gstcogorc-dist.h b/ext/cog/gstcogorc-dist.h index a335875944..4f1dbd204d 100644 --- a/ext/cog/gstcogorc-dist.h +++ b/ext/cog/gstcogorc-dist.h @@ -24,6 +24,7 @@ typedef uint8_t orc_uint8; typedef uint16_t orc_uint16; typedef uint32_t orc_uint32; typedef uint64_t orc_uint64; +#define ORC_UINT64_C(x) UINT64_C(x) #elif defined(_MSC_VER) typedef signed __int8 orc_int8; typedef signed __int16 orc_int16; @@ -33,6 +34,7 @@ typedef unsigned __int8 orc_uint8; typedef unsigned __int16 orc_uint16; typedef unsigned __int32 orc_uint32; typedef unsigned __int64 orc_uint64; +#define ORC_UINT64_C(x) (x##Ui64) #else #include typedef signed char orc_int8; @@ -44,14 +46,16 @@ typedef unsigned int orc_uint32; #if INT_MAX == LONG_MAX typedef long long orc_int64; typedef unsigned long long orc_uint64; +#define ORC_UINT64_C(x) (x##ULL) #else typedef long orc_int64; typedef unsigned long orc_uint64; +#define ORC_UINT64_C(x) (x##UL) #endif #endif typedef union { orc_int16 i; orc_int8 x2[2]; } orc_union16; typedef union { orc_int32 i; float f; orc_int16 x2[2]; orc_int8 x4[4]; } orc_union32; -typedef union { orc_int64 i; double f; orc_int32 x2[2]; orc_int16 x4[4]; } orc_union64; +typedef union { orc_int64 i; double f; orc_int32 x2[2]; float x2f[2]; orc_int16 x4[4]; } orc_union64; #endif void cogorc_memcpy_2d (orc_uint8 * d1, int d1_stride, const orc_uint8 * s1, int s1_stride, int n, int m); void cogorc_downsample_horiz_cosite_1tap (orc_uint8 * d1, const orc_uint16 * s1, int n); diff --git a/win32/common/config.h b/win32/common/config.h index d49c056a71..c9ac11fc4d 100644 --- a/win32/common/config.h +++ b/win32/common/config.h @@ -24,7 +24,7 @@ #define GST_LICENSE "LGPL" /* package name in plugins */ -#define GST_PACKAGE_NAME "GStreamer Bad Plug-ins git" +#define GST_PACKAGE_NAME "GStreamer Bad Plug-ins prerelease" /* package origin */ #define GST_PACKAGE_ORIGIN "Unknown package origin" @@ -199,7 +199,7 @@ #undef USE_POISONING /* Version number of package */ -#define VERSION "0.10.20.1" +#define VERSION "0.10.20.2" /* Define to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel and VAX). */ From b9af27719dcfd604480e07a1f8392cc4429328a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Sat, 8 Jan 2011 03:12:11 +0000 Subject: [PATCH 283/448] cog, schroedinger: fix warnings when compiling with -DG_DISABLE_ASSERT --- ext/cog/gstcogdownsample.c | 1 + ext/cog/gstcogutils.c | 1 + ext/schroedinger/gstschroenc.c | 1 + ext/schroedinger/gstschroparse.c | 1 + ext/schroedinger/gstschroutils.c | 1 + 5 files changed, 5 insertions(+) diff --git a/ext/cog/gstcogdownsample.c b/ext/cog/gstcogdownsample.c index 5d6b4f9ed3..8bec086c01 100644 --- a/ext/cog/gstcogdownsample.c +++ b/ext/cog/gstcogdownsample.c @@ -357,6 +357,7 @@ gst_cogdownsample_transform (GstBaseTransform * base_transform, break; default: g_assert_not_reached (); + return GST_FLOW_ERROR; } frame = cog_virt_frame_new_unpack (frame); diff --git a/ext/cog/gstcogutils.c b/ext/cog/gstcogutils.c index 4d7c8b99f0..ff23862f88 100644 --- a/ext/cog/gstcogutils.c +++ b/ext/cog/gstcogutils.c @@ -126,6 +126,7 @@ gst_cog_buffer_wrap (GstBuffer * buf, GstVideoFormat format, int width, break; default: g_assert_not_reached (); + return NULL; } cog_frame_set_free_callback (frame, gst_cog_frame_free, buf); diff --git a/ext/schroedinger/gstschroenc.c b/ext/schroedinger/gstschroenc.c index b4e50a922c..7af28eac2a 100644 --- a/ext/schroedinger/gstschroenc.c +++ b/ext/schroedinger/gstschroenc.c @@ -600,6 +600,7 @@ gst_schro_enc_get_caps (GstBaseVideoEncoder * base_video_encoder) state->par_d, NULL); } else { g_assert_not_reached (); + caps = NULL; } return caps; diff --git a/ext/schroedinger/gstschroparse.c b/ext/schroedinger/gstschroparse.c index 25711c8d14..a734f2dc53 100644 --- a/ext/schroedinger/gstschroparse.c +++ b/ext/schroedinger/gstschroparse.c @@ -579,6 +579,7 @@ gst_schro_parse_get_caps (GstBaseVideoParse * base_video_parse) state->par_d, NULL); } else { g_assert_not_reached (); + caps = NULL; } return caps; diff --git a/ext/schroedinger/gstschroutils.c b/ext/schroedinger/gstschroutils.c index bb1f1bcd62..66514a3d53 100644 --- a/ext/schroedinger/gstschroutils.c +++ b/ext/schroedinger/gstschroutils.c @@ -95,6 +95,7 @@ gst_schro_buffer_wrap (GstBuffer * buf, GstVideoFormat format, int width, #endif default: g_assert_not_reached (); + return NULL; } schro_frame_set_free_callback (frame, gst_schro_frame_free, buf); From 0b4dfa685d313f698c3b6b05d5f6894c20bfbc38 Mon Sep 17 00:00:00 2001 From: Karol Sobczak Date: Mon, 10 Jan 2011 11:18:52 +0000 Subject: [PATCH 284/448] mpegtsdemux: fix re-syncing on invalid data after seek Or possibly even at startup. If we couldn't find a sync within the first few bytes, we'd just push more data into the adapter but never discard any of the invalid data at the beginning, so would never be able to re-sync. https://bugzilla.gnome.org/show_bug.cgi?id=639063 --- gst/mpegdemux/mpegtspacketizer.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/gst/mpegdemux/mpegtspacketizer.c b/gst/mpegdemux/mpegtspacketizer.c index 70cf3d7106..cbea99f9cd 100644 --- a/gst/mpegdemux/mpegtspacketizer.c +++ b/gst/mpegdemux/mpegtspacketizer.c @@ -2107,9 +2107,13 @@ mpegts_try_discover_packet_size (MpegTSPacketizer * packetizer) } GST_DEBUG ("have packetsize detected: %d of %u bytes", packetizer->know_packet_size, packetizer->packet_size); - /* flush to sync byte */ - if (pos > 0) + if (pos > 0) { + /* flush to sync byte */ gst_adapter_flush (packetizer->adapter, pos); + } else if (!packetizer->know_packet_size) { + /* drop invalid data and move to the next possible packets */ + gst_adapter_flush (packetizer->adapter, MPEGTS_MAX_PACKETSIZE); + } g_free (dest); } From d4441a3025dfc8b9836ff342b9c9dd20e6f4f82d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Mon, 10 Jan 2011 11:25:47 +0000 Subject: [PATCH 285/448] mpegtsdemux: fix silly way of creating caps --- gst/mpegdemux/mpegtspacketizer.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/gst/mpegdemux/mpegtspacketizer.c b/gst/mpegdemux/mpegtspacketizer.c index cbea99f9cd..9a9fd0c8cd 100644 --- a/gst/mpegdemux/mpegtspacketizer.c +++ b/gst/mpegdemux/mpegtspacketizer.c @@ -2089,15 +2089,11 @@ mpegts_try_discover_packet_size (MpegTSPacketizer * packetizer) if (dest[i] == 0x47 && dest[i + packetsize] == 0x47 && dest[i + packetsize * 2] == 0x47 && dest[i + packetsize * 3] == 0x47) { - gchar *str; packetizer->know_packet_size = TRUE; packetizer->packet_size = packetsize; - str = - g_strdup_printf - ("video/mpegts, systemstream=(boolean)true, packetsize=%d", - packetsize); - packetizer->caps = gst_caps_from_string ((const gchar *) str); - g_free (str); + packetizer->caps = gst_caps_new_simple ("video/mpegts", + "systemstream", G_TYPE_BOOLEAN, TRUE, + "packetsize", packetsize, NULL); pos = i; break; } From 0f393680e47d7c8919efe554e7da9a57046d6e0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Mon, 10 Jan 2011 14:54:10 +0000 Subject: [PATCH 286/448] Automatic update of common submodule From 46445ad to ccbaa85 --- common | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common b/common index 46445ad50f..ccbaa85fc5 160000 --- a/common +++ b/common @@ -1 +1 @@ -Subproject commit 46445ad50f184d2640dd205361e0446e9121ba5f +Subproject commit ccbaa85fc58099fb90f1b5a0fad4d92d45500d19 From d12c42a1da623c9bef1e56ed096b0ae2c5d38489 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Mon, 10 Jan 2011 16:36:45 +0000 Subject: [PATCH 287/448] Automatic update of common submodule From ccbaa85 to e572c87 --- common | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common b/common index ccbaa85fc5..e572c87c58 160000 --- a/common +++ b/common @@ -1 +1 @@ -Subproject commit ccbaa85fc58099fb90f1b5a0fad4d92d45500d19 +Subproject commit e572c87c582166a6c65edf2a6a0fa73e31a3b04c From ee0c9ae2f379402df301ff6ebe48b481d87094d9 Mon Sep 17 00:00:00 2001 From: Edward Hervey Date: Mon, 10 Jan 2011 19:11:22 +0100 Subject: [PATCH 288/448] mpegtspacketizer: Don't forget the GType when using caps_new_simple() --- gst/mpegdemux/mpegtspacketizer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst/mpegdemux/mpegtspacketizer.c b/gst/mpegdemux/mpegtspacketizer.c index 9a9fd0c8cd..a86ef0e810 100644 --- a/gst/mpegdemux/mpegtspacketizer.c +++ b/gst/mpegdemux/mpegtspacketizer.c @@ -2093,7 +2093,7 @@ mpegts_try_discover_packet_size (MpegTSPacketizer * packetizer) packetizer->packet_size = packetsize; packetizer->caps = gst_caps_new_simple ("video/mpegts", "systemstream", G_TYPE_BOOLEAN, TRUE, - "packetsize", packetsize, NULL); + "packetsize", G_TYPE_INT, packetsize, NULL); pos = i; break; } From 1e12a21d107e9e723b52cf0143e792a7ea5c2994 Mon Sep 17 00:00:00 2001 From: Stefan Kost Date: Tue, 11 Jan 2011 15:50:52 +0200 Subject: [PATCH 289/448] Automatic update of common submodule From e572c87 to f94d739 --- common | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common b/common index e572c87c58..f94d739915 160000 --- a/common +++ b/common @@ -1 +1 @@ -Subproject commit e572c87c582166a6c65edf2a6a0fa73e31a3b04c +Subproject commit f94d73991563ea2dcae2218b4847e32998f06816 From 24e89ab39cc00ce2027f0525bc280fc70a6040cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Tue, 11 Jan 2011 23:44:51 +0000 Subject: [PATCH 290/448] 0.10.20.3 pre-release --- configure.ac | 6 +++--- win32/common/config.h | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/configure.ac b/configure.ac index 757dffd415..6c9e33e0bc 100644 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ AC_PREREQ(2.60) dnl initialize autoconf dnl when going to/from release please set the nano (fourth number) right ! dnl releases only do Wall, cvs and prerelease does Werror too -AC_INIT(GStreamer Bad Plug-ins, 0.10.20.2, +AC_INIT(GStreamer Bad Plug-ins, 0.10.20.3, http://bugzilla.gnome.org/enter_bug.cgi?product=GStreamer, gst-plugins-bad) @@ -50,8 +50,8 @@ AC_LIBTOOL_WIN32_DLL AM_PROG_LIBTOOL dnl *** required versions of GStreamer stuff *** -GST_REQ=0.10.31.2 -GSTPB_REQ=0.10.31.2 +GST_REQ=0.10.31.3 +GSTPB_REQ=0.10.31.3 dnl *** autotools stuff **** diff --git a/win32/common/config.h b/win32/common/config.h index c9ac11fc4d..b1e9cae950 100644 --- a/win32/common/config.h +++ b/win32/common/config.h @@ -199,7 +199,7 @@ #undef USE_POISONING /* Version number of package */ -#define VERSION "0.10.20.2" +#define VERSION "0.10.20.3" /* Define to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel and VAX). */ From a2b5e7863e3b0522c9ddc3dada8390bae2ee45e3 Mon Sep 17 00:00:00 2001 From: Edward Hervey Date: Wed, 12 Jan 2011 11:57:29 +0100 Subject: [PATCH 291/448] y4mdec: Default colorspace is I420 https://bugzilla.gnome.org/show_bug.cgi?id=639296 --- gst/y4m/gsty4mdec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst/y4m/gsty4mdec.c b/gst/y4m/gsty4mdec.c index 7011bacf5b..0e6c3fab6f 100644 --- a/gst/y4m/gsty4mdec.c +++ b/gst/y4m/gsty4mdec.c @@ -280,7 +280,7 @@ static gboolean gst_y4m_dec_parse_header (GstY4mDec * y4mdec, char *header) { char *end; - int format = -1; + int format = 420; int interlaced_char = 0; if (memcmp (header, "YUV4MPEG2 ", 10) != 0) { From d63365fc5b714147305540284ac65a8d9e82a929 Mon Sep 17 00:00:00 2001 From: Stefan Kost Date: Wed, 12 Jan 2011 16:50:51 +0200 Subject: [PATCH 292/448] camerabin2: use g_error_free instead of g_free --- tests/examples/camerabin2/gst-camera2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/examples/camerabin2/gst-camera2.c b/tests/examples/camerabin2/gst-camera2.c index 68d9b20870..42b6e07a06 100644 --- a/tests/examples/camerabin2/gst-camera2.c +++ b/tests/examples/camerabin2/gst-camera2.c @@ -162,7 +162,7 @@ main (int argc, char *argv[]) builder = gtk_builder_new (); if (!gtk_builder_add_from_file (builder, UI_FILE, &error)) { g_warning ("Error: %s", error->message); - g_free (error); + g_error_free (error); return 1; } From f9dfd1effb6cb01ee4fc1d3b2050c3f0356c3bf3 Mon Sep 17 00:00:00 2001 From: Stefan Kost Date: Wed, 12 Jan 2011 16:55:07 +0200 Subject: [PATCH 293/448] asfmux: use g_error_free instead of g_free --- gst/asfmux/gstasfmux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst/asfmux/gstasfmux.c b/gst/asfmux/gstasfmux.c index 3c8921f4c7..2e85e1ae2e 100644 --- a/gst/asfmux/gstasfmux.c +++ b/gst/asfmux/gstasfmux.c @@ -919,7 +919,7 @@ gst_asf_mux_write_string_with_size (GstAsfMux * asfmux, if (error) { GST_WARNING_OBJECT (asfmux, "Error converting string " "to UTF-16: %s - %s", str, error->message); - g_free (error); + g_error_free (error); memset (str_buf, 0, str_size); } else { /* HACK: g_convert seems to add only a single byte null char to From 85a355fd84a7c50fe6d22e98c3fd122b75985e6e Mon Sep 17 00:00:00 2001 From: Teemu Katajisto Date: Thu, 13 Jan 2011 13:36:09 +0200 Subject: [PATCH 294/448] camerabin: set pad-negotiation-mode to active for output-selector Fixes #639413. --- gst/camerabin/gstcamerabin.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/gst/camerabin/gstcamerabin.c b/gst/camerabin/gstcamerabin.c index e7f13dae8f..9a94a063bf 100644 --- a/gst/camerabin/gstcamerabin.c +++ b/gst/camerabin/gstcamerabin.c @@ -615,6 +615,9 @@ camerabin_create_src_elements (GstCameraBin * camera) gst_camerabin_create_and_add_element (cbin, "output-selector"))) goto done; + /* Set pad-negotiation-mode to active */ + g_object_set (camera->src_out_sel, "pad-negotiation-mode", 2, NULL); + /* Set default "driver-name" for v4l2camsrc if not set */ /* FIXME: v4l2camsrc specific */ if (g_object_class_find_property (G_OBJECT_GET_CLASS (camera->src_vid_src), From 095eaa1752ebdf142c8abe8d186a8b59cb2878e8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Thu, 13 Jan 2011 16:27:04 +0000 Subject: [PATCH 295/448] docs: minor baseparse docs/comment fixes Remove copy'n'paste leftovers. --- gst/audioparsers/gstbaseparse.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/gst/audioparsers/gstbaseparse.c b/gst/audioparsers/gstbaseparse.c index 4cd759aacc..58c0ebe9eb 100644 --- a/gst/audioparsers/gstbaseparse.c +++ b/gst/audioparsers/gstbaseparse.c @@ -2590,8 +2590,8 @@ gst_base_parse_set_min_frame_size (GstBaseParse * parse, guint min_size) } /** - * gst_base_transform_set_passthrough: - * @trans: the #GstBaseParse to set + * gst_base_parse_set_passthrough: + * @parse: the #GstBaseParse to set * @passthrough: boolean indicating passthrough mode. * * Set passthrough mode for this parser. If operating in passthrough, @@ -2609,7 +2609,7 @@ gst_base_parse_set_passthrough (GstBaseParse * parse, gboolean passthrough) } /** - * gst_base_transform_set_frame_props: + * gst_base_parse_set_frame_props: * @parse: the #GstBaseParse to set * @fps_num: frames per second (numerator). * @fps_den: frames per second (denominator). @@ -2658,7 +2658,7 @@ gst_base_parse_set_frame_props (GstBaseParse * parse, guint fps_num, } /** - * gst_base_transform_get_sync: + * gst_base_parse_get_sync: * @parse: the #GstBaseParse to query * * Returns: TRUE if parser is considered 'in sync'. That is, frames have been @@ -2681,7 +2681,7 @@ gst_base_parse_get_sync (GstBaseParse * parse) } /** - * gst_base_transform_get_drain: + * gst_base_parse_get_drain: * @parse: the #GstBaseParse to query * * Returns: TRUE if parser is currently 'draining'. That is, leftover data From aba0899b19406562a54cb2633e2b63333022a503 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Thu, 13 Jan 2011 17:10:13 +0000 Subject: [PATCH 296/448] dcaparse: fix sync word for 14-bit little endian coding Fix copy'n'paste bug that made us look for the raw little endian sync word twice instead of looking for the 14-bit LE sync word as well. Fixes parsing of such streams (see #636234 for sample file). --- gst/audioparsers/gstdcaparse.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/gst/audioparsers/gstdcaparse.c b/gst/audioparsers/gstdcaparse.c index 3b074ccc0b..4573d3bbba 100644 --- a/gst/audioparsers/gstdcaparse.c +++ b/gst/audioparsers/gstdcaparse.c @@ -246,7 +246,7 @@ gst_dca_parse_find_sync (GstDcaParse * dcaparse, GstByteReader * reader, /* FIXME: verify syncs via _parse_header() here already */ - /* Raw big endian */ + /* Raw little endian */ off = gst_byte_reader_masked_scan_uint32 (reader, 0xffffffff, 0xfe7f0180, 0, GST_BUFFER_SIZE (buf)); if (off >= 0 && off < best_offset) { @@ -254,7 +254,7 @@ gst_dca_parse_find_sync (GstDcaParse * dcaparse, GstByteReader * reader, best_sync = 0xfe7f0180; } - /* Raw little endian */ + /* Raw big endian */ off = gst_byte_reader_masked_scan_uint32 (reader, 0xffffffff, 0x7ffe8001, 0, GST_BUFFER_SIZE (buf)); if (off >= 0 && off < best_offset) { @@ -265,15 +265,15 @@ gst_dca_parse_find_sync (GstDcaParse * dcaparse, GstByteReader * reader, /* FIXME: check next 2 bytes as well for 14-bit formats (but then don't * forget to adjust the *skipsize= in _check_valid_frame() */ - /* 14-bit big endian */ - off = gst_byte_reader_masked_scan_uint32 (reader, 0xffffffff, 0xfe7f0180, + /* 14-bit little endian */ + off = gst_byte_reader_masked_scan_uint32 (reader, 0xffffffff, 0xff1f00e8, 0, GST_BUFFER_SIZE (buf)); if (off >= 0 && off < best_offset) { best_offset = off; - best_sync = 0xfe7f0180; + best_sync = 0xff1f00e8; } - /* 14-bit little endian */ + /* 14-bit big endian */ off = gst_byte_reader_masked_scan_uint32 (reader, 0xffffffff, 0x1fffe800, 0, GST_BUFFER_SIZE (buf)); if (off >= 0 && off < best_offset) { @@ -317,6 +317,7 @@ gst_dca_parse_check_valid_frame (GstBaseParse * parse, GstBuffer * buf, /* didn't find anything that looks like a sync word, skip */ if (off < 0) { *skipsize = GST_BUFFER_SIZE (buf) - 3; + GST_DEBUG_OBJECT (dcaparse, "no sync, skipping %d bytes", *skipsize); return FALSE; } From b55775a9d39513d41da2cdc7cc6dc6b9013a769f Mon Sep 17 00:00:00 2001 From: Luciana Fujii Pontello Date: Thu, 13 Jan 2011 18:35:15 -0200 Subject: [PATCH 297/448] camerabin: Enable conversion flags Camerabin default should just work, so we need to enable audio, image and video conversions. https://bugzilla.gnome.org/show_bug.cgi?id=639456 --- gst/camerabin/gstcamerabin.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gst/camerabin/gstcamerabin.c b/gst/camerabin/gstcamerabin.c index 9a94a063bf..2744e58744 100644 --- a/gst/camerabin/gstcamerabin.c +++ b/gst/camerabin/gstcamerabin.c @@ -208,7 +208,9 @@ static guint camerabin_signals[LAST_SIGNAL]; #define DEFAULT_FLAGS GST_CAMERABIN_FLAG_SOURCE_RESIZE | \ GST_CAMERABIN_FLAG_VIEWFINDER_SCALE | \ - GST_CAMERABIN_FLAG_IMAGE_COLOR_CONVERSION + GST_CAMERABIN_FLAG_AUDIO_CONVERSION | \ + GST_CAMERABIN_FLAG_IMAGE_COLOR_CONVERSION | \ + GST_CAMERABIN_FLAG_VIDEO_COLOR_CONVERSION /* Using "bilinear" as default zoom method */ #define CAMERABIN_DEFAULT_ZOOM_METHOD 1 From 0b790b663c1423948794302b6ed88cefab236cff Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Wed, 12 Jan 2011 16:39:22 +0000 Subject: [PATCH 298/448] kate: ensure the kate pad does not shoot ahead of the video pad Sync both pads by waiting in the kate chain function. Do not reset our internal segment from segment updates, in order to be able to map video running time to kate running time, to give libtiger the timestamp it expects. This allows us to use running time to sync to video, which is The Right Way. https://bugzilla.gnome.org/show_bug.cgi?id=600929 --- ext/kate/gstkatetiger.c | 50 +++++++++++++++++++++++++++++++++++++++-- ext/kate/gstkatetiger.h | 1 + ext/kate/gstkateutil.c | 10 +++++++-- 3 files changed, 57 insertions(+), 4 deletions(-) diff --git a/ext/kate/gstkatetiger.c b/ext/kate/gstkatetiger.c index 932bb42592..81ac6f7555 100644 --- a/ext/kate/gstkatetiger.c +++ b/ext/kate/gstkatetiger.c @@ -309,6 +309,7 @@ gst_kate_tiger_init (GstKateTiger * tiger, GstKateTigerClass * gclass) GST_DEBUG_OBJECT (tiger, "gst_kate_tiger_init"); tiger->mutex = g_mutex_new (); + tiger->cond = g_cond_new (); tiger->katesinkpad = gst_pad_new_from_static_template (&kate_sink_factory, "subtitle_sink"); @@ -371,6 +372,9 @@ gst_kate_tiger_dispose (GObject * object) tiger->default_font_desc = NULL; } + g_cond_free (tiger->cond); + tiger->cond = NULL; + g_mutex_free (tiger->mutex); tiger->mutex = NULL; @@ -631,6 +635,34 @@ gst_kate_tiger_kate_chain (GstPad * pad, GstBuffer * buf) gst_object_unref (tagpad); } + /* we want to avoid shooting ahead of the video stream, or we will + get segment updates which will place us ahead of it, and we won't + be able to convert a video timestamp back into a kate timestamp */ + if (G_LIKELY (GST_BUFFER_TIMESTAMP_IS_VALID (buf))) { + while (1) { + gint64 kate_time, video_time; + kate_time = + gst_segment_to_running_time (&tiger->decoder.kate_segment, + GST_FORMAT_TIME, GST_BUFFER_TIMESTAMP (buf)); + video_time = + gst_segment_to_running_time (&tiger->video_segment, GST_FORMAT_TIME, + tiger->video_segment.last_stop); + GST_DEBUG_OBJECT (tiger, "Kate time %.2f, video time %.2f (kts %ld)", + kate_time / (float) GST_SECOND, video_time / (float) GST_SECOND, + (long) GST_BUFFER_TIMESTAMP (buf)); + if (kate_time <= video_time) { + break; + } + GST_LOG_OBJECT (tiger, "Waiting to return from chain function"); + g_cond_wait (tiger->cond, tiger->mutex); + if (tiger->decoder.kate_flushing) { + GST_DEBUG_OBJECT (tiger, "Flushing while waiting"); + break; + } + GST_LOG_OBJECT (tiger, "Woken up, checking time again"); + } + } + GST_KATE_TIGER_MUTEX_UNLOCK (tiger); gst_object_unref (tiger); @@ -669,8 +701,13 @@ gst_kate_tiger_video_set_caps (GstPad * pad, GstCaps * caps) static gdouble gst_kate_tiger_get_time (GstKateTiger * tiger) { - return gst_segment_to_running_time (&tiger->video_segment, GST_FORMAT_TIME, - tiger->video_segment.last_stop) / (gdouble) GST_SECOND; + gint64 rt = + gst_segment_to_running_time (&tiger->video_segment, GST_FORMAT_TIME, + tiger->video_segment.last_stop); + gint64 pos = + gst_segment_to_position (&tiger->decoder.kate_segment, GST_FORMAT_TIME, + rt); + return pos / (gdouble) GST_SECOND; } static GstFlowReturn @@ -695,6 +732,7 @@ gst_kate_tiger_video_chain (GstPad * pad, GstBuffer * buf) if (G_LIKELY (GST_BUFFER_TIMESTAMP_IS_VALID (buf))) { gst_segment_set_last_stop (&tiger->video_segment, GST_FORMAT_TIME, GST_BUFFER_TIMESTAMP (buf)); + g_cond_broadcast (tiger->cond); } /* draw on it */ @@ -755,6 +793,8 @@ gst_kate_tiger_change_state (GstElement * element, GstStateChange transition) case GST_STATE_CHANGE_PAUSED_TO_READY: GST_DEBUG_OBJECT (tiger, "PAUSED -> READY, clearing kate state"); GST_KATE_TIGER_MUTEX_LOCK (tiger); + gst_kate_util_decoder_base_set_flushing (&tiger->decoder, TRUE); + g_cond_broadcast (tiger->cond); if (tiger->tr) { tiger_renderer_destroy (tiger->tr); tiger->tr = NULL; @@ -904,6 +944,7 @@ gst_kate_tiger_handle_kate_event (GstPad * pad, GstEvent * event) case GST_EVENT_NEWSEGMENT: GST_INFO_OBJECT (tiger, "New segment on Kate pad"); GST_KATE_TIGER_MUTEX_LOCK (tiger); + g_cond_broadcast (tiger->cond); gst_kate_util_decoder_base_new_segment_event (&tiger->decoder, event); GST_KATE_TIGER_MUTEX_UNLOCK (tiger); gst_event_unref (event); @@ -912,6 +953,7 @@ gst_kate_tiger_handle_kate_event (GstPad * pad, GstEvent * event) GST_KATE_TIGER_MUTEX_LOCK (tiger); gst_kate_util_decoder_base_set_flushing (&tiger->decoder, TRUE); GST_KATE_TIGER_MUTEX_UNLOCK (tiger); + g_cond_broadcast (tiger->cond); gst_event_unref (event); break; case GST_EVENT_FLUSH_STOP: @@ -924,6 +966,9 @@ gst_kate_tiger_handle_kate_event (GstPad * pad, GstEvent * event) /* we ignore this, it just means we don't have anymore Kate packets, but the Tiger renderer will still draw (if appropriate) on incoming video */ GST_INFO_OBJECT (tiger, "EOS on Kate pad"); + GST_KATE_TIGER_MUTEX_LOCK (tiger); + g_cond_broadcast (tiger->cond); + GST_KATE_TIGER_MUTEX_UNLOCK (tiger); gst_event_unref (event); break; default: @@ -1000,6 +1045,7 @@ gst_kate_tiger_handle_video_event (GstPad * pad, GstEvent * event) gst_segment_init (&tiger->video_segment, GST_FORMAT_UNDEFINED); tiger->video_flushing = TRUE; GST_KATE_TIGER_MUTEX_UNLOCK (tiger); + g_cond_broadcast (tiger->cond); res = gst_pad_event_default (pad, event); break; case GST_EVENT_FLUSH_STOP: diff --git a/ext/kate/gstkatetiger.h b/ext/kate/gstkatetiger.h index 48884b1c22..d3880b32bf 100644 --- a/ext/kate/gstkatetiger.h +++ b/ext/kate/gstkatetiger.h @@ -94,6 +94,7 @@ struct _GstKateTiger gboolean swap_rgb; GMutex *mutex; + GCond *cond; GstSegment video_segment; gboolean video_flushing; diff --git a/ext/kate/gstkateutil.c b/ext/kate/gstkateutil.c index b873d0aca1..46ae19b9de 100644 --- a/ext/kate/gstkateutil.c +++ b/ext/kate/gstkateutil.c @@ -454,8 +454,14 @@ gst_kate_util_decoder_base_new_segment_event (GstKateDecoderBase * decoder, " %" GST_TIME_FORMAT " position %" GST_TIME_FORMAT, update, rate, arate, format, GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (time)); - gst_segment_set_newsegment_full (&decoder->kate_segment, update, rate, - arate, format, start, stop, time); + if (!update) { + /* Tiger uses this segment is used to remap the video running time to the + Kate running time. The sending of segment updates to keep streams in sync + does kinda rain on our parade though, and since we don't need these, + we just ignore those here */ + gst_segment_set_newsegment_full (&decoder->kate_segment, update, rate, + arate, format, start, stop, time); + } } gboolean From b496bf923c2144aa02535f59db2ae4f3e1a25c34 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Thu, 13 Jan 2011 15:27:36 +0100 Subject: [PATCH 299/448] qtmux: set src pads when starting file ... rather than at _init time, so they are also available following a pad (de)activation cycle. https://bugzilla.gnome.org/show_bug.cgi?id=639338 --- gst/qtmux/gstqtmux.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/gst/qtmux/gstqtmux.c b/gst/qtmux/gstqtmux.c index 0ac1e91141..1477db7c8e 100644 --- a/gst/qtmux/gstqtmux.c +++ b/gst/qtmux/gstqtmux.c @@ -469,13 +469,9 @@ gst_qt_mux_init (GstQTMux * qtmux, GstQTMuxClass * qtmux_klass) { GstElementClass *klass = GST_ELEMENT_CLASS (qtmux_klass); GstPadTemplate *templ; - GstCaps *caps; templ = gst_element_class_get_pad_template (klass, "src"); qtmux->srcpad = gst_pad_new_from_template (templ, "src"); - caps = gst_caps_copy (gst_pad_get_pad_template_caps (qtmux->srcpad)); - gst_pad_set_caps (qtmux->srcpad, caps); - gst_caps_unref (caps); gst_pad_use_fixed_caps (qtmux->srcpad); gst_element_add_pad (GST_ELEMENT (qtmux), qtmux->srcpad); @@ -1578,9 +1574,14 @@ static GstFlowReturn gst_qt_mux_start_file (GstQTMux * qtmux) { GstFlowReturn ret = GST_FLOW_OK; + GstCaps *caps; GST_DEBUG_OBJECT (qtmux, "starting file"); + caps = gst_caps_copy (gst_pad_get_pad_template_caps (qtmux->srcpad)); + gst_pad_set_caps (qtmux->srcpad, caps); + gst_caps_unref (caps); + /* let downstream know we think in BYTES and expect to do seeking later on */ gst_pad_push_event (qtmux->srcpad, gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES, 0, -1, 0)); From f59a1d28686690ca9189ec48243479aa2cf81e6a Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Thu, 13 Jan 2011 11:28:32 -0300 Subject: [PATCH 300/448] test: qtmux: Tests qtmux reuse Forces the use of qtmux after it has been put to PLAYING and back to NULL once https://bugzilla.gnome.org/show_bug.cgi?id=639338 --- tests/check/elements/qtmux.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/tests/check/elements/qtmux.c b/tests/check/elements/qtmux.c index 69816f7047..1db618cec9 100644 --- a/tests/check/elements/qtmux.c +++ b/tests/check/elements/qtmux.c @@ -355,6 +355,36 @@ GST_START_TEST (test_audio_pad_frag_streamable) GST_END_TEST; +GST_START_TEST (test_reuse) +{ + GstElement *qtmux = setup_qtmux (&srcvideotemplate, "video_%d"); + GstBuffer *inbuffer; + GstCaps *caps; + + gst_element_set_state (qtmux, GST_STATE_PLAYING); + gst_element_set_state (qtmux, GST_STATE_NULL); + gst_element_set_state (qtmux, GST_STATE_PLAYING); + gst_pad_set_active (mysrcpad, TRUE); + gst_pad_set_active (mysinkpad, TRUE); + + inbuffer = gst_buffer_new_and_alloc (1); + fail_unless (inbuffer != NULL); + caps = gst_caps_copy (gst_pad_get_pad_template_caps (mysrcpad)); + gst_buffer_set_caps (inbuffer, caps); + gst_caps_unref (caps); + GST_BUFFER_TIMESTAMP (inbuffer) = 0; + GST_BUFFER_DURATION (inbuffer) = 40 * GST_MSECOND; + ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1); + fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK); + + /* send eos to have all written */ + fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_eos ()) == TRUE); + + cleanup_qtmux (qtmux, "video_%d"); +} + +GST_END_TEST; + static Suite * qtmux_suite (void) { @@ -369,6 +399,8 @@ qtmux_suite (void) tcase_add_test (tc_chain, test_video_pad_frag_streamable); tcase_add_test (tc_chain, test_audio_pad_frag_streamable); + tcase_add_test (tc_chain, test_reuse); + return s; } From a6a982e8be06a861e23b377d8df4e3be8538ca53 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Fri, 14 Jan 2011 16:30:11 -0300 Subject: [PATCH 301/448] audioparsers: baseparse: Be careful to not lose the event ref Don't unref the event if it hasn't been handled, because the caller assumes it is still valid and might reuse it. I ran into this problem when transcoding an AVI (with mp3 inside) to gpp. https://bugzilla.gnome.org/show_bug.cgi?id=639555 --- gst/audioparsers/gstbaseparse.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/gst/audioparsers/gstbaseparse.c b/gst/audioparsers/gstbaseparse.c index 58c0ebe9eb..59355c7757 100644 --- a/gst/audioparsers/gstbaseparse.c +++ b/gst/audioparsers/gstbaseparse.c @@ -738,7 +738,10 @@ gst_base_parse_sink_event (GstPad * pad, GstEvent * event) * * Element-level event handler function. * - * Returns: TRUE if the event was handled and not need forwarding. + * The event will be unreffed only if it has been handled and this + * function returns %TRUE + * + * Returns: %TRUE if the event was handled and not need forwarding. */ static gboolean gst_base_parse_sink_eventfunc (GstBaseParse * parse, GstEvent * event) @@ -858,7 +861,9 @@ gst_base_parse_sink_eventfunc (GstBaseParse * parse, GstEvent * event) case GST_EVENT_FLUSH_START: parse->priv->flushing = TRUE; - handled = gst_pad_push_event (parse->srcpad, event); + handled = gst_pad_push_event (parse->srcpad, gst_event_ref (event)); + if (handled) + gst_event_unref (event); /* Wait for _chain() to exit by taking the srcpad STREAM_LOCK */ GST_PAD_STREAM_LOCK (parse->srcpad); GST_PAD_STREAM_UNLOCK (parse->srcpad); From 72709f24abf625a0592e1d83b4de71076d55d4d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Tue, 18 Jan 2011 13:00:11 +0000 Subject: [PATCH 302/448] 0.10.20.4 pre-release --- configure.ac | 2 +- docs/plugins/gst-plugins-bad-plugins.args | 16 ++++++++-------- docs/plugins/inspect/plugin-adpcmdec.xml | 2 +- docs/plugins/inspect/plugin-adpcmenc.xml | 2 +- docs/plugins/inspect/plugin-aiff.xml | 2 +- docs/plugins/inspect/plugin-amrwbenc.xml | 2 +- docs/plugins/inspect/plugin-apexsink.xml | 2 +- docs/plugins/inspect/plugin-asfmux.xml | 2 +- docs/plugins/inspect/plugin-assrender.xml | 2 +- docs/plugins/inspect/plugin-audioparsersbad.xml | 2 +- docs/plugins/inspect/plugin-autoconvert.xml | 2 +- docs/plugins/inspect/plugin-bayer.xml | 2 +- docs/plugins/inspect/plugin-bz2.xml | 2 +- docs/plugins/inspect/plugin-camerabin.xml | 2 +- docs/plugins/inspect/plugin-cdaudio.xml | 2 +- docs/plugins/inspect/plugin-cdxaparse.xml | 2 +- docs/plugins/inspect/plugin-celt.xml | 2 +- docs/plugins/inspect/plugin-cog.xml | 2 +- docs/plugins/inspect/plugin-coloreffects.xml | 2 +- docs/plugins/inspect/plugin-colorspace.xml | 2 +- docs/plugins/inspect/plugin-dataurisrc.xml | 2 +- docs/plugins/inspect/plugin-dc1394.xml | 2 +- docs/plugins/inspect/plugin-dccp.xml | 2 +- docs/plugins/inspect/plugin-debugutilsbad.xml | 2 +- docs/plugins/inspect/plugin-dfbvideosink.xml | 2 +- docs/plugins/inspect/plugin-dirac.xml | 2 +- docs/plugins/inspect/plugin-dtmf.xml | 2 +- docs/plugins/inspect/plugin-dtsdec.xml | 2 +- docs/plugins/inspect/plugin-dvb.xml | 2 +- docs/plugins/inspect/plugin-dvbsuboverlay.xml | 2 +- docs/plugins/inspect/plugin-dvdspu.xml | 2 +- docs/plugins/inspect/plugin-faac.xml | 2 +- docs/plugins/inspect/plugin-faad.xml | 2 +- docs/plugins/inspect/plugin-fbdevsink.xml | 2 +- docs/plugins/inspect/plugin-festival.xml | 2 +- docs/plugins/inspect/plugin-freeze.xml | 2 +- docs/plugins/inspect/plugin-frei0r.xml | 2 +- docs/plugins/inspect/plugin-gaudieffects.xml | 2 +- .../inspect/plugin-geometrictransform.xml | 2 +- docs/plugins/inspect/plugin-gsettings.xml | 2 +- docs/plugins/inspect/plugin-gsm.xml | 2 +- docs/plugins/inspect/plugin-gstsiren.xml | 2 +- docs/plugins/inspect/plugin-h264parse.xml | 2 +- docs/plugins/inspect/plugin-hdvparse.xml | 2 +- docs/plugins/inspect/plugin-id3tag.xml | 2 +- docs/plugins/inspect/plugin-interlace.xml | 2 +- docs/plugins/inspect/plugin-invtelecine.xml | 2 +- docs/plugins/inspect/plugin-ivfparse.xml | 2 +- docs/plugins/inspect/plugin-jp2kdecimator.xml | 2 +- docs/plugins/inspect/plugin-jpegformat.xml | 2 +- docs/plugins/inspect/plugin-kate.xml | 2 +- docs/plugins/inspect/plugin-ladspa.xml | 2 +- docs/plugins/inspect/plugin-legacyresample.xml | 2 +- docs/plugins/inspect/plugin-liveadder.xml | 2 +- docs/plugins/inspect/plugin-mimic.xml | 2 +- docs/plugins/inspect/plugin-mms.xml | 2 +- docs/plugins/inspect/plugin-modplug.xml | 2 +- docs/plugins/inspect/plugin-mpeg2enc.xml | 2 +- docs/plugins/inspect/plugin-mpeg4videoparse.xml | 2 +- docs/plugins/inspect/plugin-mpegdemux2.xml | 2 +- docs/plugins/inspect/plugin-mpegpsmux.xml | 2 +- docs/plugins/inspect/plugin-mpegtsmux.xml | 2 +- docs/plugins/inspect/plugin-mpegvideoparse.xml | 2 +- docs/plugins/inspect/plugin-mplex.xml | 2 +- docs/plugins/inspect/plugin-musepack.xml | 2 +- docs/plugins/inspect/plugin-musicbrainz.xml | 2 +- docs/plugins/inspect/plugin-mve.xml | 2 +- docs/plugins/inspect/plugin-mxf.xml | 2 +- docs/plugins/inspect/plugin-mythtv.xml | 2 +- docs/plugins/inspect/plugin-nas.xml | 2 +- docs/plugins/inspect/plugin-neon.xml | 2 +- docs/plugins/inspect/plugin-nsf.xml | 2 +- docs/plugins/inspect/plugin-nuvdemux.xml | 2 +- docs/plugins/inspect/plugin-ofa.xml | 2 +- docs/plugins/inspect/plugin-opencv.xml | 2 +- docs/plugins/inspect/plugin-pcapparse.xml | 2 +- docs/plugins/inspect/plugin-pnm.xml | 2 +- docs/plugins/inspect/plugin-qtmux.xml | 2 +- docs/plugins/inspect/plugin-rawparse.xml | 2 +- docs/plugins/inspect/plugin-real.xml | 2 +- docs/plugins/inspect/plugin-resindvd.xml | 2 +- docs/plugins/inspect/plugin-rfbsrc.xml | 2 +- docs/plugins/inspect/plugin-rsvg.xml | 2 +- docs/plugins/inspect/plugin-rtpmux.xml | 2 +- docs/plugins/inspect/plugin-scaletempo.xml | 2 +- docs/plugins/inspect/plugin-schro.xml | 2 +- docs/plugins/inspect/plugin-sdl.xml | 2 +- docs/plugins/inspect/plugin-sdp.xml | 2 +- docs/plugins/inspect/plugin-segmentclip.xml | 2 +- docs/plugins/inspect/plugin-shm.xml | 2 +- docs/plugins/inspect/plugin-sndfile.xml | 2 +- docs/plugins/inspect/plugin-soundtouch.xml | 2 +- docs/plugins/inspect/plugin-speed.xml | 2 +- docs/plugins/inspect/plugin-stereo.xml | 2 +- docs/plugins/inspect/plugin-subenc.xml | 2 +- docs/plugins/inspect/plugin-tta.xml | 2 +- docs/plugins/inspect/plugin-vcdsrc.xml | 2 +- docs/plugins/inspect/plugin-vdpau.xml | 2 +- docs/plugins/inspect/plugin-videomaxrate.xml | 2 +- docs/plugins/inspect/plugin-videomeasure.xml | 2 +- docs/plugins/inspect/plugin-videosignal.xml | 2 +- docs/plugins/inspect/plugin-vmnc.xml | 2 +- docs/plugins/inspect/plugin-vp8.xml | 2 +- docs/plugins/inspect/plugin-wildmidi.xml | 2 +- docs/plugins/inspect/plugin-xvid.xml | 2 +- docs/plugins/inspect/plugin-y4mdec.xml | 2 +- docs/plugins/inspect/plugin-zbar.xml | 2 +- win32/common/config.h | 2 +- 108 files changed, 115 insertions(+), 115 deletions(-) diff --git a/configure.ac b/configure.ac index 6c9e33e0bc..a63839ee72 100644 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ AC_PREREQ(2.60) dnl initialize autoconf dnl when going to/from release please set the nano (fourth number) right ! dnl releases only do Wall, cvs and prerelease does Werror too -AC_INIT(GStreamer Bad Plug-ins, 0.10.20.3, +AC_INIT(GStreamer Bad Plug-ins, 0.10.20.4, http://bugzilla.gnome.org/enter_bug.cgi?product=GStreamer, gst-plugins-bad) diff --git a/docs/plugins/gst-plugins-bad-plugins.args b/docs/plugins/gst-plugins-bad-plugins.args index 31494f8daa..507785e802 100644 --- a/docs/plugins/gst-plugins-bad-plugins.args +++ b/docs/plugins/gst-plugins-bad-plugins.args @@ -23100,7 +23100,7 @@ rw Flags Flags to control behaviour. -Enable source crop and scale|Enable scale for viewfinder|Enable colorspace conversion for still image +Enable source crop and scale|Enable scale for viewfinder|Enable audio conversion for video capture|Enable colorspace conversion for still image|Enable colorspace conversion for video capture @@ -26550,7 +26550,7 @@ rw splash make a big splash in the center. -4.62958e-299 +7.7486e-304 @@ -26560,7 +26560,7 @@ rw splash make a big splash in the center. -4.63015e-299 +4.62957e-299 @@ -26590,7 +26590,7 @@ rw ratiox x-ratio. -0 +2.35298e-310 @@ -26600,7 +26600,7 @@ rw ratioy y-ratio. -0 +2.35298e-310 @@ -27000,7 +27000,7 @@ rw lthresh threshold for edge lightening. -0 +6.9235e+228 @@ -27180,7 +27180,7 @@ rw blend blend factor. -4.74303e-322 +-6.17056e+303 @@ -27370,7 +27370,7 @@ rw HSync the hsync offset. -2.98023e-08 +1.783e-316 diff --git a/docs/plugins/inspect/plugin-adpcmdec.xml b/docs/plugins/inspect/plugin-adpcmdec.xml index 586a3da56a..5fed1998e7 100644 --- a/docs/plugins/inspect/plugin-adpcmdec.xml +++ b/docs/plugins/inspect/plugin-adpcmdec.xml @@ -3,7 +3,7 @@ ADPCM decoder ../../gst/adpcmdec/.libs/libgstadpcmdec.so libgstadpcmdec.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-adpcmenc.xml b/docs/plugins/inspect/plugin-adpcmenc.xml index 9aa84e5242..db77e25619 100644 --- a/docs/plugins/inspect/plugin-adpcmenc.xml +++ b/docs/plugins/inspect/plugin-adpcmenc.xml @@ -3,7 +3,7 @@ ADPCM encoder ../../gst/adpcmenc/.libs/libgstadpcmenc.so libgstadpcmenc.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-aiff.xml b/docs/plugins/inspect/plugin-aiff.xml index c63a3de8ca..251fc9af05 100644 --- a/docs/plugins/inspect/plugin-aiff.xml +++ b/docs/plugins/inspect/plugin-aiff.xml @@ -3,7 +3,7 @@ Create and parse Audio Interchange File Format (AIFF) files ../../gst/aiff/.libs/libgstaiff.so libgstaiff.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-amrwbenc.xml b/docs/plugins/inspect/plugin-amrwbenc.xml index bc96b0e1b3..59b53e43c3 100644 --- a/docs/plugins/inspect/plugin-amrwbenc.xml +++ b/docs/plugins/inspect/plugin-amrwbenc.xml @@ -3,7 +3,7 @@ Adaptive Multi-Rate Wide-Band Encoder ../../ext/amrwbenc/.libs/libgstamrwbenc.so libgstamrwbenc.so - 0.10.20.2 + 0.10.20.4 unknown gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-apexsink.xml b/docs/plugins/inspect/plugin-apexsink.xml index f4fb729a75..f63b4daa12 100644 --- a/docs/plugins/inspect/plugin-apexsink.xml +++ b/docs/plugins/inspect/plugin-apexsink.xml @@ -3,7 +3,7 @@ Apple AirPort Express Plugin ../../ext/apexsink/.libs/libgstapexsink.so libgstapexsink.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-asfmux.xml b/docs/plugins/inspect/plugin-asfmux.xml index fdbcbfcef3..e58698affd 100644 --- a/docs/plugins/inspect/plugin-asfmux.xml +++ b/docs/plugins/inspect/plugin-asfmux.xml @@ -3,7 +3,7 @@ ASF Muxer Plugin ../../gst/asfmux/.libs/libgstasfmux.so libgstasfmux.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-assrender.xml b/docs/plugins/inspect/plugin-assrender.xml index 4d59f26226..3259c9586f 100644 --- a/docs/plugins/inspect/plugin-assrender.xml +++ b/docs/plugins/inspect/plugin-assrender.xml @@ -3,7 +3,7 @@ ASS/SSA subtitle renderer ../../ext/assrender/.libs/libgstassrender.so libgstassrender.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-audioparsersbad.xml b/docs/plugins/inspect/plugin-audioparsersbad.xml index 2bbf5c585f..9742fe6b2e 100644 --- a/docs/plugins/inspect/plugin-audioparsersbad.xml +++ b/docs/plugins/inspect/plugin-audioparsersbad.xml @@ -3,7 +3,7 @@ audioparsers ../../gst/audioparsers/.libs/libgstaudioparsersbad.so libgstaudioparsersbad.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-autoconvert.xml b/docs/plugins/inspect/plugin-autoconvert.xml index fb91f17afd..8a9b37d8e9 100644 --- a/docs/plugins/inspect/plugin-autoconvert.xml +++ b/docs/plugins/inspect/plugin-autoconvert.xml @@ -3,7 +3,7 @@ Selects convertor element based on caps ../../gst/autoconvert/.libs/libgstautoconvert.so libgstautoconvert.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-bayer.xml b/docs/plugins/inspect/plugin-bayer.xml index 799434e135..91cbeaefcc 100644 --- a/docs/plugins/inspect/plugin-bayer.xml +++ b/docs/plugins/inspect/plugin-bayer.xml @@ -3,7 +3,7 @@ Elements to convert Bayer images ../../gst/bayer/.libs/libgstbayer.so libgstbayer.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-bz2.xml b/docs/plugins/inspect/plugin-bz2.xml index afe2d89ca7..d0abf69390 100644 --- a/docs/plugins/inspect/plugin-bz2.xml +++ b/docs/plugins/inspect/plugin-bz2.xml @@ -3,7 +3,7 @@ Compress or decompress streams ../../ext/bz2/.libs/libgstbz2.so libgstbz2.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-camerabin.xml b/docs/plugins/inspect/plugin-camerabin.xml index 0b14bf8e3c..92cab93d3a 100644 --- a/docs/plugins/inspect/plugin-camerabin.xml +++ b/docs/plugins/inspect/plugin-camerabin.xml @@ -3,7 +3,7 @@ High level api for DC (Digital Camera) application ../../gst/camerabin/.libs/libgstcamerabin.so libgstcamerabin.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-cdaudio.xml b/docs/plugins/inspect/plugin-cdaudio.xml index 89c266b2b5..79181da849 100644 --- a/docs/plugins/inspect/plugin-cdaudio.xml +++ b/docs/plugins/inspect/plugin-cdaudio.xml @@ -3,7 +3,7 @@ Play CD audio through the CD Drive ../../ext/cdaudio/.libs/libgstcdaudio.so libgstcdaudio.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-cdxaparse.xml b/docs/plugins/inspect/plugin-cdxaparse.xml index fbf9810ad5..d13c9c82af 100644 --- a/docs/plugins/inspect/plugin-cdxaparse.xml +++ b/docs/plugins/inspect/plugin-cdxaparse.xml @@ -3,7 +3,7 @@ Parse a .dat file (VCD) into raw mpeg1 ../../gst/cdxaparse/.libs/libgstcdxaparse.so libgstcdxaparse.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-celt.xml b/docs/plugins/inspect/plugin-celt.xml index 17c19db00a..480591d405 100644 --- a/docs/plugins/inspect/plugin-celt.xml +++ b/docs/plugins/inspect/plugin-celt.xml @@ -3,7 +3,7 @@ CELT plugin library ../../ext/celt/.libs/libgstcelt.so libgstcelt.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-cog.xml b/docs/plugins/inspect/plugin-cog.xml index d3b0db0fd7..aae4450f46 100644 --- a/docs/plugins/inspect/plugin-cog.xml +++ b/docs/plugins/inspect/plugin-cog.xml @@ -3,7 +3,7 @@ Cog plugin ../../ext/cog/.libs/libgstcog.so libgstcog.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-coloreffects.xml b/docs/plugins/inspect/plugin-coloreffects.xml index 105681fc33..1e11bd7ce7 100644 --- a/docs/plugins/inspect/plugin-coloreffects.xml +++ b/docs/plugins/inspect/plugin-coloreffects.xml @@ -3,7 +3,7 @@ Color Look-up Table filters ../../gst/coloreffects/.libs/libgstcoloreffects.so libgstcoloreffects.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-colorspace.xml b/docs/plugins/inspect/plugin-colorspace.xml index cf27b95a17..4fedf0054b 100644 --- a/docs/plugins/inspect/plugin-colorspace.xml +++ b/docs/plugins/inspect/plugin-colorspace.xml @@ -3,7 +3,7 @@ Colorspace conversion ../../gst/colorspace/.libs/libgstcolorspace.so libgstcolorspace.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad diff --git a/docs/plugins/inspect/plugin-dataurisrc.xml b/docs/plugins/inspect/plugin-dataurisrc.xml index cef7e17148..9313288bab 100644 --- a/docs/plugins/inspect/plugin-dataurisrc.xml +++ b/docs/plugins/inspect/plugin-dataurisrc.xml @@ -3,7 +3,7 @@ data: URI source ../../gst/dataurisrc/.libs/libgstdataurisrc.so libgstdataurisrc.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-dc1394.xml b/docs/plugins/inspect/plugin-dc1394.xml index 3ba7e8dc59..8e4d8a72e8 100644 --- a/docs/plugins/inspect/plugin-dc1394.xml +++ b/docs/plugins/inspect/plugin-dc1394.xml @@ -3,7 +3,7 @@ 1394 IIDC Video Source ../../ext/dc1394/.libs/libgstdc1394.so libgstdc1394.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-dccp.xml b/docs/plugins/inspect/plugin-dccp.xml index 0beb68df81..6ee767366e 100644 --- a/docs/plugins/inspect/plugin-dccp.xml +++ b/docs/plugins/inspect/plugin-dccp.xml @@ -3,7 +3,7 @@ transfer data over the network via DCCP. ../../gst/dccp/.libs/libgstdccp.so libgstdccp.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad DCCP diff --git a/docs/plugins/inspect/plugin-debugutilsbad.xml b/docs/plugins/inspect/plugin-debugutilsbad.xml index 7400471c8c..ee790a387f 100644 --- a/docs/plugins/inspect/plugin-debugutilsbad.xml +++ b/docs/plugins/inspect/plugin-debugutilsbad.xml @@ -3,7 +3,7 @@ Collection of elements that may or may not be useful for debugging ../../gst/debugutils/.libs/libgstdebugutilsbad.so libgstdebugutilsbad.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-dfbvideosink.xml b/docs/plugins/inspect/plugin-dfbvideosink.xml index e04d4e8680..0fae3cec42 100644 --- a/docs/plugins/inspect/plugin-dfbvideosink.xml +++ b/docs/plugins/inspect/plugin-dfbvideosink.xml @@ -3,7 +3,7 @@ DirectFB video output plugin ../../ext/directfb/.libs/libgstdfbvideosink.so libgstdfbvideosink.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-dirac.xml b/docs/plugins/inspect/plugin-dirac.xml index f03944b474..39265f116c 100644 --- a/docs/plugins/inspect/plugin-dirac.xml +++ b/docs/plugins/inspect/plugin-dirac.xml @@ -3,7 +3,7 @@ Dirac plugin ../../ext/dirac/.libs/libgstdirac.so libgstdirac.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-dtmf.xml b/docs/plugins/inspect/plugin-dtmf.xml index d84ca27992..12bab4fdca 100644 --- a/docs/plugins/inspect/plugin-dtmf.xml +++ b/docs/plugins/inspect/plugin-dtmf.xml @@ -3,7 +3,7 @@ DTMF plugins ../../gst/dtmf/.libs/libgstdtmf.so libgstdtmf.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-dtsdec.xml b/docs/plugins/inspect/plugin-dtsdec.xml index 926a1cb78c..f23b007cae 100644 --- a/docs/plugins/inspect/plugin-dtsdec.xml +++ b/docs/plugins/inspect/plugin-dtsdec.xml @@ -3,7 +3,7 @@ Decodes DTS audio streams ../../ext/dts/.libs/libgstdtsdec.so libgstdtsdec.so - 0.10.20.2 + 0.10.20.4 GPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-dvb.xml b/docs/plugins/inspect/plugin-dvb.xml index 08474d6354..d04722dff8 100644 --- a/docs/plugins/inspect/plugin-dvb.xml +++ b/docs/plugins/inspect/plugin-dvb.xml @@ -3,7 +3,7 @@ DVB elements ../../sys/dvb/.libs/libgstdvb.so libgstdvb.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-dvbsuboverlay.xml b/docs/plugins/inspect/plugin-dvbsuboverlay.xml index fdec8725eb..14aa3f72ac 100644 --- a/docs/plugins/inspect/plugin-dvbsuboverlay.xml +++ b/docs/plugins/inspect/plugin-dvbsuboverlay.xml @@ -3,7 +3,7 @@ DVB subtitle renderer ../../gst/dvbsuboverlay/.libs/libgstdvbsuboverlay.so libgstdvbsuboverlay.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-dvdspu.xml b/docs/plugins/inspect/plugin-dvdspu.xml index 27168511bb..5d996ad314 100644 --- a/docs/plugins/inspect/plugin-dvdspu.xml +++ b/docs/plugins/inspect/plugin-dvdspu.xml @@ -3,7 +3,7 @@ DVD Sub-picture Overlay element ../../gst/dvdspu/.libs/libgstdvdspu.so libgstdvdspu.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-faac.xml b/docs/plugins/inspect/plugin-faac.xml index ffd828e455..5c35e49ac4 100644 --- a/docs/plugins/inspect/plugin-faac.xml +++ b/docs/plugins/inspect/plugin-faac.xml @@ -3,7 +3,7 @@ Free AAC Encoder (FAAC) ../../ext/faac/.libs/libgstfaac.so libgstfaac.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-faad.xml b/docs/plugins/inspect/plugin-faad.xml index 0296d80c87..93104bea1a 100644 --- a/docs/plugins/inspect/plugin-faad.xml +++ b/docs/plugins/inspect/plugin-faad.xml @@ -3,7 +3,7 @@ Free AAC Decoder (FAAD) ../../ext/faad/.libs/libgstfaad.so libgstfaad.so - 0.10.20.2 + 0.10.20.4 GPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-fbdevsink.xml b/docs/plugins/inspect/plugin-fbdevsink.xml index 2d47128fee..4b325bc0b2 100644 --- a/docs/plugins/inspect/plugin-fbdevsink.xml +++ b/docs/plugins/inspect/plugin-fbdevsink.xml @@ -3,7 +3,7 @@ linux framebuffer video sink ../../sys/fbdev/.libs/libgstfbdevsink.so libgstfbdevsink.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-festival.xml b/docs/plugins/inspect/plugin-festival.xml index 7de0f6d015..a4dc05b5ea 100644 --- a/docs/plugins/inspect/plugin-festival.xml +++ b/docs/plugins/inspect/plugin-festival.xml @@ -3,7 +3,7 @@ Synthesizes plain text into audio ../../gst/festival/.libs/libgstfestival.so libgstfestival.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-freeze.xml b/docs/plugins/inspect/plugin-freeze.xml index b5b54560ca..6024872fb9 100644 --- a/docs/plugins/inspect/plugin-freeze.xml +++ b/docs/plugins/inspect/plugin-freeze.xml @@ -3,7 +3,7 @@ Stream freezer ../../gst/freeze/.libs/libgstfreeze.so libgstfreeze.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-frei0r.xml b/docs/plugins/inspect/plugin-frei0r.xml index 6b12c78a6f..d6b3b666b3 100644 --- a/docs/plugins/inspect/plugin-frei0r.xml +++ b/docs/plugins/inspect/plugin-frei0r.xml @@ -3,7 +3,7 @@ frei0r plugin library ../../gst/frei0r/.libs/libgstfrei0r.so libgstfrei0r.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-gaudieffects.xml b/docs/plugins/inspect/plugin-gaudieffects.xml index 8e20ab4d59..9a41249224 100644 --- a/docs/plugins/inspect/plugin-gaudieffects.xml +++ b/docs/plugins/inspect/plugin-gaudieffects.xml @@ -3,7 +3,7 @@ Gaudi video effects. ../../gst/gaudieffects/.libs/libgstgaudieffects.so libgstgaudieffects.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer diff --git a/docs/plugins/inspect/plugin-geometrictransform.xml b/docs/plugins/inspect/plugin-geometrictransform.xml index 8595004be1..39ced8625f 100644 --- a/docs/plugins/inspect/plugin-geometrictransform.xml +++ b/docs/plugins/inspect/plugin-geometrictransform.xml @@ -3,7 +3,7 @@ Various geometric image transform elements ../../gst/geometrictransform/.libs/libgstgeometrictransform.so libgstgeometrictransform.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-gsettings.xml b/docs/plugins/inspect/plugin-gsettings.xml index 3d8d5561f2..00c0e29b0e 100644 --- a/docs/plugins/inspect/plugin-gsettings.xml +++ b/docs/plugins/inspect/plugin-gsettings.xml @@ -3,7 +3,7 @@ GSettings plugin ../../ext/gsettings/.libs/libgstgsettingselements.so libgstgsettingselements.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-gsm.xml b/docs/plugins/inspect/plugin-gsm.xml index 390ded1e19..9c22a9e952 100644 --- a/docs/plugins/inspect/plugin-gsm.xml +++ b/docs/plugins/inspect/plugin-gsm.xml @@ -3,7 +3,7 @@ GSM encoder/decoder ../../ext/gsm/.libs/libgstgsm.so libgstgsm.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-gstsiren.xml b/docs/plugins/inspect/plugin-gstsiren.xml index 1edd584f62..1bfc8cca8d 100644 --- a/docs/plugins/inspect/plugin-gstsiren.xml +++ b/docs/plugins/inspect/plugin-gstsiren.xml @@ -3,7 +3,7 @@ Siren encoder/decoder/payloader/depayloader plugins ../../gst/siren/.libs/libgstsiren.so libgstsiren.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-h264parse.xml b/docs/plugins/inspect/plugin-h264parse.xml index bc58490007..82efb680bd 100644 --- a/docs/plugins/inspect/plugin-h264parse.xml +++ b/docs/plugins/inspect/plugin-h264parse.xml @@ -3,7 +3,7 @@ Element parsing raw h264 streams ../../gst/h264parse/.libs/libgsth264parse.so libgsth264parse.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-hdvparse.xml b/docs/plugins/inspect/plugin-hdvparse.xml index b18fb3798b..796dbd1937 100644 --- a/docs/plugins/inspect/plugin-hdvparse.xml +++ b/docs/plugins/inspect/plugin-hdvparse.xml @@ -3,7 +3,7 @@ HDV private stream parser ../../gst/hdvparse/.libs/libgsthdvparse.so libgsthdvparse.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer diff --git a/docs/plugins/inspect/plugin-id3tag.xml b/docs/plugins/inspect/plugin-id3tag.xml index aa3598ef1f..c0367e9ba4 100644 --- a/docs/plugins/inspect/plugin-id3tag.xml +++ b/docs/plugins/inspect/plugin-id3tag.xml @@ -3,7 +3,7 @@ ID3 v1 and v2 muxing plugin ../../gst/id3tag/.libs/libgstid3tag.so libgstid3tag.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-interlace.xml b/docs/plugins/inspect/plugin-interlace.xml index 365d1ff1ed..89021ed1c6 100644 --- a/docs/plugins/inspect/plugin-interlace.xml +++ b/docs/plugins/inspect/plugin-interlace.xml @@ -3,7 +3,7 @@ Create an interlaced video stream ../../gst/interlace/.libs/libgstinterlace.so libgstinterlace.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-invtelecine.xml b/docs/plugins/inspect/plugin-invtelecine.xml index d2ab52b4dd..d16c59864e 100644 --- a/docs/plugins/inspect/plugin-invtelecine.xml +++ b/docs/plugins/inspect/plugin-invtelecine.xml @@ -3,7 +3,7 @@ Inverse Telecine ../../gst/invtelecine/.libs/libgstinvtelecine.so libgstinvtelecine.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-ivfparse.xml b/docs/plugins/inspect/plugin-ivfparse.xml index dd7da9d28f..7d40d01f56 100644 --- a/docs/plugins/inspect/plugin-ivfparse.xml +++ b/docs/plugins/inspect/plugin-ivfparse.xml @@ -3,7 +3,7 @@ IVF parser ../../gst/ivfparse/.libs/libgstivfparse.so libgstivfparse.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-jp2kdecimator.xml b/docs/plugins/inspect/plugin-jp2kdecimator.xml index 2df75c8a34..dea3ad93aa 100644 --- a/docs/plugins/inspect/plugin-jp2kdecimator.xml +++ b/docs/plugins/inspect/plugin-jp2kdecimator.xml @@ -3,7 +3,7 @@ JPEG2000 decimator ../../gst/jp2kdecimator/.libs/libgstjp2kdecimator.so libgstjp2kdecimator.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-jpegformat.xml b/docs/plugins/inspect/plugin-jpegformat.xml index 03c2b595fa..d33815fa8a 100644 --- a/docs/plugins/inspect/plugin-jpegformat.xml +++ b/docs/plugins/inspect/plugin-jpegformat.xml @@ -3,7 +3,7 @@ JPEG interchange format plugin ../../gst/jpegformat/.libs/libgstjpegformat.so libgstjpegformat.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-kate.xml b/docs/plugins/inspect/plugin-kate.xml index 19fb170502..a7a71a61fe 100644 --- a/docs/plugins/inspect/plugin-kate.xml +++ b/docs/plugins/inspect/plugin-kate.xml @@ -3,7 +3,7 @@ Kate plugin ../../ext/kate/.libs/libgstkate.so libgstkate.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-ladspa.xml b/docs/plugins/inspect/plugin-ladspa.xml index d46d02a195..f89b261cb3 100644 --- a/docs/plugins/inspect/plugin-ladspa.xml +++ b/docs/plugins/inspect/plugin-ladspa.xml @@ -3,7 +3,7 @@ All LADSPA plugins ../../ext/ladspa/.libs/libgstladspa.so libgstladspa.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-legacyresample.xml b/docs/plugins/inspect/plugin-legacyresample.xml index ef960ca61e..1ce3d4bade 100644 --- a/docs/plugins/inspect/plugin-legacyresample.xml +++ b/docs/plugins/inspect/plugin-legacyresample.xml @@ -3,7 +3,7 @@ Resamples audio ../../gst/legacyresample/.libs/libgstlegacyresample.so libgstlegacyresample.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-liveadder.xml b/docs/plugins/inspect/plugin-liveadder.xml index 0aeacfb891..c7a1d6a88a 100644 --- a/docs/plugins/inspect/plugin-liveadder.xml +++ b/docs/plugins/inspect/plugin-liveadder.xml @@ -3,7 +3,7 @@ Adds multiple live discontinuous streams ../../gst/liveadder/.libs/libgstliveadder.so libgstliveadder.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-mimic.xml b/docs/plugins/inspect/plugin-mimic.xml index d4c56931cb..4f4e68af3c 100644 --- a/docs/plugins/inspect/plugin-mimic.xml +++ b/docs/plugins/inspect/plugin-mimic.xml @@ -3,7 +3,7 @@ Mimic codec ../../ext/mimic/.libs/libgstmimic.so libgstmimic.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-mms.xml b/docs/plugins/inspect/plugin-mms.xml index d0607d0be9..116623e8cf 100644 --- a/docs/plugins/inspect/plugin-mms.xml +++ b/docs/plugins/inspect/plugin-mms.xml @@ -3,7 +3,7 @@ Microsoft Multi Media Server streaming protocol support ../../ext/libmms/.libs/libgstmms.so libgstmms.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-modplug.xml b/docs/plugins/inspect/plugin-modplug.xml index a142537d4d..b143c83508 100644 --- a/docs/plugins/inspect/plugin-modplug.xml +++ b/docs/plugins/inspect/plugin-modplug.xml @@ -3,7 +3,7 @@ .MOD audio decoding ../../ext/modplug/.libs/libgstmodplug.so libgstmodplug.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-mpeg2enc.xml b/docs/plugins/inspect/plugin-mpeg2enc.xml index 9eb28e722f..4c2fee726d 100644 --- a/docs/plugins/inspect/plugin-mpeg2enc.xml +++ b/docs/plugins/inspect/plugin-mpeg2enc.xml @@ -3,7 +3,7 @@ High-quality MPEG-1/2 video encoder ../../ext/mpeg2enc/.libs/libgstmpeg2enc.so libgstmpeg2enc.so - 0.10.20.2 + 0.10.20.4 GPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-mpeg4videoparse.xml b/docs/plugins/inspect/plugin-mpeg4videoparse.xml index ca4c720cc7..912c0a4ab2 100644 --- a/docs/plugins/inspect/plugin-mpeg4videoparse.xml +++ b/docs/plugins/inspect/plugin-mpeg4videoparse.xml @@ -3,7 +3,7 @@ MPEG-4 video parser ../../gst/mpeg4videoparse/.libs/libgstmpeg4videoparse.so libgstmpeg4videoparse.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-mpegdemux2.xml b/docs/plugins/inspect/plugin-mpegdemux2.xml index c35498916e..1dbe6921ed 100644 --- a/docs/plugins/inspect/plugin-mpegdemux2.xml +++ b/docs/plugins/inspect/plugin-mpegdemux2.xml @@ -3,7 +3,7 @@ MPEG demuxers ../../gst/mpegdemux/.libs/libgstmpegdemux.so libgstmpegdemux.so - 0.10.20.2 + 0.10.20.4 unknown gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-mpegpsmux.xml b/docs/plugins/inspect/plugin-mpegpsmux.xml index c1b27311b6..ff54c2b6e5 100644 --- a/docs/plugins/inspect/plugin-mpegpsmux.xml +++ b/docs/plugins/inspect/plugin-mpegpsmux.xml @@ -3,7 +3,7 @@ MPEG-PS muxer ../../gst/mpegpsmux/.libs/libgstmpegpsmux.so libgstmpegpsmux.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-mpegtsmux.xml b/docs/plugins/inspect/plugin-mpegtsmux.xml index f1a6d550c6..c23ea98d6c 100644 --- a/docs/plugins/inspect/plugin-mpegtsmux.xml +++ b/docs/plugins/inspect/plugin-mpegtsmux.xml @@ -3,7 +3,7 @@ MPEG-TS muxer ../../gst/mpegtsmux/.libs/libgstmpegtsmux.so libgstmpegtsmux.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-mpegvideoparse.xml b/docs/plugins/inspect/plugin-mpegvideoparse.xml index 82c6121fd5..d6a6e86b34 100644 --- a/docs/plugins/inspect/plugin-mpegvideoparse.xml +++ b/docs/plugins/inspect/plugin-mpegvideoparse.xml @@ -3,7 +3,7 @@ MPEG-1 and MPEG-2 video parser ../../gst/mpegvideoparse/.libs/libgstmpegvideoparse.so libgstmpegvideoparse.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-mplex.xml b/docs/plugins/inspect/plugin-mplex.xml index 6d7669623e..8683056679 100644 --- a/docs/plugins/inspect/plugin-mplex.xml +++ b/docs/plugins/inspect/plugin-mplex.xml @@ -3,7 +3,7 @@ High-quality MPEG/DVD/SVCD/VCD video/audio multiplexer ../../ext/mplex/.libs/libgstmplex.so libgstmplex.so - 0.10.20.2 + 0.10.20.4 GPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-musepack.xml b/docs/plugins/inspect/plugin-musepack.xml index 9bc633d4f0..d4fd9e4403 100644 --- a/docs/plugins/inspect/plugin-musepack.xml +++ b/docs/plugins/inspect/plugin-musepack.xml @@ -3,7 +3,7 @@ Musepack decoder ../../ext/musepack/.libs/libgstmusepack.so libgstmusepack.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-musicbrainz.xml b/docs/plugins/inspect/plugin-musicbrainz.xml index 1ba564cfb4..f6a5d0f39c 100644 --- a/docs/plugins/inspect/plugin-musicbrainz.xml +++ b/docs/plugins/inspect/plugin-musicbrainz.xml @@ -3,7 +3,7 @@ A TRM signature producer based on libmusicbrainz ../../ext/musicbrainz/.libs/libgsttrm.so libgsttrm.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-mve.xml b/docs/plugins/inspect/plugin-mve.xml index 34d532790c..984c01fcc1 100644 --- a/docs/plugins/inspect/plugin-mve.xml +++ b/docs/plugins/inspect/plugin-mve.xml @@ -3,7 +3,7 @@ Interplay MVE movie format manipulation ../../gst/mve/.libs/libgstmve.so libgstmve.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-mxf.xml b/docs/plugins/inspect/plugin-mxf.xml index b7c500eae0..e32d1a5f46 100644 --- a/docs/plugins/inspect/plugin-mxf.xml +++ b/docs/plugins/inspect/plugin-mxf.xml @@ -3,7 +3,7 @@ MXF plugin library ../../gst/mxf/.libs/libgstmxf.so libgstmxf.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-mythtv.xml b/docs/plugins/inspect/plugin-mythtv.xml index 21d4b018ed..90d1eb4050 100644 --- a/docs/plugins/inspect/plugin-mythtv.xml +++ b/docs/plugins/inspect/plugin-mythtv.xml @@ -3,7 +3,7 @@ lib MythTV src ../../ext/mythtv/.libs/libgstmythtvsrc.so libgstmythtvsrc.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-nas.xml b/docs/plugins/inspect/plugin-nas.xml index c72cef3d1f..0b01234d6c 100644 --- a/docs/plugins/inspect/plugin-nas.xml +++ b/docs/plugins/inspect/plugin-nas.xml @@ -3,7 +3,7 @@ NAS (Network Audio System) support for GStreamer ../../ext/nas/.libs/libgstnassink.so libgstnassink.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-neon.xml b/docs/plugins/inspect/plugin-neon.xml index 59891a7665..c7cc2851c7 100644 --- a/docs/plugins/inspect/plugin-neon.xml +++ b/docs/plugins/inspect/plugin-neon.xml @@ -3,7 +3,7 @@ lib neon http client src ../../ext/neon/.libs/libgstneonhttpsrc.so libgstneonhttpsrc.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-nsf.xml b/docs/plugins/inspect/plugin-nsf.xml index 7f65aee8db..a80ef62e7c 100644 --- a/docs/plugins/inspect/plugin-nsf.xml +++ b/docs/plugins/inspect/plugin-nsf.xml @@ -3,7 +3,7 @@ Uses nosefart to decode .nsf files ../../gst/nsf/.libs/libgstnsf.so libgstnsf.so - 0.10.20.2 + 0.10.20.4 GPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-nuvdemux.xml b/docs/plugins/inspect/plugin-nuvdemux.xml index eb0f3ea2ae..8113f436ec 100644 --- a/docs/plugins/inspect/plugin-nuvdemux.xml +++ b/docs/plugins/inspect/plugin-nuvdemux.xml @@ -3,7 +3,7 @@ Demuxes MythTV NuppelVideo files ../../gst/nuvdemux/.libs/libgstnuvdemux.so libgstnuvdemux.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-ofa.xml b/docs/plugins/inspect/plugin-ofa.xml index 3ba130933a..d99e287cdb 100644 --- a/docs/plugins/inspect/plugin-ofa.xml +++ b/docs/plugins/inspect/plugin-ofa.xml @@ -3,7 +3,7 @@ Calculate MusicIP fingerprint from audio files ../../ext/ofa/.libs/libgstofa.so libgstofa.so - 0.10.20.2 + 0.10.20.4 GPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-opencv.xml b/docs/plugins/inspect/plugin-opencv.xml index eace0307c8..27f966b667 100644 --- a/docs/plugins/inspect/plugin-opencv.xml +++ b/docs/plugins/inspect/plugin-opencv.xml @@ -3,7 +3,7 @@ GStreamer OpenCV Plugins ../../ext/opencv/.libs/libgstopencv.so libgstopencv.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-pcapparse.xml b/docs/plugins/inspect/plugin-pcapparse.xml index 158ebe70fe..76dea64184 100644 --- a/docs/plugins/inspect/plugin-pcapparse.xml +++ b/docs/plugins/inspect/plugin-pcapparse.xml @@ -3,7 +3,7 @@ Element parsing raw pcap streams ../../gst/pcapparse/.libs/libgstpcapparse.so libgstpcapparse.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer diff --git a/docs/plugins/inspect/plugin-pnm.xml b/docs/plugins/inspect/plugin-pnm.xml index 87551d5d3b..50aec3d940 100644 --- a/docs/plugins/inspect/plugin-pnm.xml +++ b/docs/plugins/inspect/plugin-pnm.xml @@ -3,7 +3,7 @@ PNM plugin ../../gst/pnm/.libs/libgstpnm.so libgstpnm.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-qtmux.xml b/docs/plugins/inspect/plugin-qtmux.xml index be0ca02c11..95e0da613d 100644 --- a/docs/plugins/inspect/plugin-qtmux.xml +++ b/docs/plugins/inspect/plugin-qtmux.xml @@ -3,7 +3,7 @@ Quicktime Muxer plugin ../../gst/qtmux/.libs/libgstqtmux.so libgstqtmux.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-rawparse.xml b/docs/plugins/inspect/plugin-rawparse.xml index 8c33ef5d22..a94cd99148 100644 --- a/docs/plugins/inspect/plugin-rawparse.xml +++ b/docs/plugins/inspect/plugin-rawparse.xml @@ -3,7 +3,7 @@ Parses byte streams into raw frames ../../gst/rawparse/.libs/libgstrawparse.so libgstrawparse.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-real.xml b/docs/plugins/inspect/plugin-real.xml index ce86ab0138..117654d9d1 100644 --- a/docs/plugins/inspect/plugin-real.xml +++ b/docs/plugins/inspect/plugin-real.xml @@ -3,7 +3,7 @@ Decode REAL streams ../../gst/real/.libs/libgstreal.so libgstreal.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-resindvd.xml b/docs/plugins/inspect/plugin-resindvd.xml index 549a74ee3b..62c6d5c3d1 100644 --- a/docs/plugins/inspect/plugin-resindvd.xml +++ b/docs/plugins/inspect/plugin-resindvd.xml @@ -3,7 +3,7 @@ Resin DVD playback elements ../../ext/resindvd/.libs/libresindvd.so libresindvd.so - 0.10.20.2 + 0.10.20.4 GPL gst-plugins-bad GStreamer diff --git a/docs/plugins/inspect/plugin-rfbsrc.xml b/docs/plugins/inspect/plugin-rfbsrc.xml index 878ecbf7e2..50a30dcf36 100644 --- a/docs/plugins/inspect/plugin-rfbsrc.xml +++ b/docs/plugins/inspect/plugin-rfbsrc.xml @@ -3,7 +3,7 @@ Connects to a VNC server and decodes RFB stream ../../gst/librfb/.libs/libgstrfbsrc.so libgstrfbsrc.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-rsvg.xml b/docs/plugins/inspect/plugin-rsvg.xml index fef49353f7..ac2a937d35 100644 --- a/docs/plugins/inspect/plugin-rsvg.xml +++ b/docs/plugins/inspect/plugin-rsvg.xml @@ -3,7 +3,7 @@ RSVG plugin library ../../ext/rsvg/.libs/libgstrsvg.so libgstrsvg.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-rtpmux.xml b/docs/plugins/inspect/plugin-rtpmux.xml index 352e243c5a..49c05676f4 100644 --- a/docs/plugins/inspect/plugin-rtpmux.xml +++ b/docs/plugins/inspect/plugin-rtpmux.xml @@ -3,7 +3,7 @@ RTP Muxer plugins ../../gst/rtpmux/.libs/libgstrtpmux.so libgstrtpmux.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-scaletempo.xml b/docs/plugins/inspect/plugin-scaletempo.xml index 2918403964..aaff637f63 100644 --- a/docs/plugins/inspect/plugin-scaletempo.xml +++ b/docs/plugins/inspect/plugin-scaletempo.xml @@ -3,7 +3,7 @@ Scale audio tempo in sync with playback rate ../../gst/scaletempo/.libs/libgstscaletempoplugin.so libgstscaletempoplugin.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer diff --git a/docs/plugins/inspect/plugin-schro.xml b/docs/plugins/inspect/plugin-schro.xml index dd0ec0557f..9b39bce7ae 100644 --- a/docs/plugins/inspect/plugin-schro.xml +++ b/docs/plugins/inspect/plugin-schro.xml @@ -3,7 +3,7 @@ Schroedinger plugin ../../ext/schroedinger/.libs/libgstschro.so libgstschro.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-sdl.xml b/docs/plugins/inspect/plugin-sdl.xml index 91862dfc5c..4313c21ef2 100644 --- a/docs/plugins/inspect/plugin-sdl.xml +++ b/docs/plugins/inspect/plugin-sdl.xml @@ -3,7 +3,7 @@ SDL (Simple DirectMedia Layer) support for GStreamer ../../ext/sdl/.libs/libgstsdl.so libgstsdl.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-sdp.xml b/docs/plugins/inspect/plugin-sdp.xml index b4f18393dc..9461cb88be 100644 --- a/docs/plugins/inspect/plugin-sdp.xml +++ b/docs/plugins/inspect/plugin-sdp.xml @@ -3,7 +3,7 @@ configure streaming sessions using SDP ../../gst/sdp/.libs/libgstsdpelem.so libgstsdpelem.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-segmentclip.xml b/docs/plugins/inspect/plugin-segmentclip.xml index 1dbfe345d1..d20322bd19 100644 --- a/docs/plugins/inspect/plugin-segmentclip.xml +++ b/docs/plugins/inspect/plugin-segmentclip.xml @@ -3,7 +3,7 @@ Segment clip elements ../../gst/segmentclip/.libs/libgstsegmentclip.so libgstsegmentclip.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-shm.xml b/docs/plugins/inspect/plugin-shm.xml index 5a76f7c5e3..c01a0dffd3 100644 --- a/docs/plugins/inspect/plugin-shm.xml +++ b/docs/plugins/inspect/plugin-shm.xml @@ -3,7 +3,7 @@ shared memory sink source ../../sys/shm/.libs/libgstshm.so libgstshm.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-sndfile.xml b/docs/plugins/inspect/plugin-sndfile.xml index 3165a191af..572e214b1a 100644 --- a/docs/plugins/inspect/plugin-sndfile.xml +++ b/docs/plugins/inspect/plugin-sndfile.xml @@ -3,7 +3,7 @@ use libsndfile to read and write audio from and to files ../../ext/sndfile/.libs/libgstsndfile.so libgstsndfile.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-soundtouch.xml b/docs/plugins/inspect/plugin-soundtouch.xml index b731aa3913..25a89c692a 100644 --- a/docs/plugins/inspect/plugin-soundtouch.xml +++ b/docs/plugins/inspect/plugin-soundtouch.xml @@ -3,7 +3,7 @@ Audio Pitch Controller & BPM Detection ../../ext/soundtouch/.libs/libgstsoundtouch.so libgstsoundtouch.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-speed.xml b/docs/plugins/inspect/plugin-speed.xml index ca3b469a6c..32a4ac2f1a 100644 --- a/docs/plugins/inspect/plugin-speed.xml +++ b/docs/plugins/inspect/plugin-speed.xml @@ -3,7 +3,7 @@ Set speed/pitch on audio/raw streams (resampler) ../../gst/speed/.libs/libgstspeed.so libgstspeed.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-stereo.xml b/docs/plugins/inspect/plugin-stereo.xml index aee6a66139..df82f352b6 100644 --- a/docs/plugins/inspect/plugin-stereo.xml +++ b/docs/plugins/inspect/plugin-stereo.xml @@ -3,7 +3,7 @@ Muck with the stereo signal, enhance it's 'stereo-ness' ../../gst/stereo/.libs/libgststereo.so libgststereo.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-subenc.xml b/docs/plugins/inspect/plugin-subenc.xml index 6c5279fa3c..d67161e473 100644 --- a/docs/plugins/inspect/plugin-subenc.xml +++ b/docs/plugins/inspect/plugin-subenc.xml @@ -3,7 +3,7 @@ subtitle encoders ../../gst/subenc/.libs/libgstsubenc.so libgstsubenc.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-tta.xml b/docs/plugins/inspect/plugin-tta.xml index 7198d82f09..936947f834 100644 --- a/docs/plugins/inspect/plugin-tta.xml +++ b/docs/plugins/inspect/plugin-tta.xml @@ -3,7 +3,7 @@ TTA lossless audio format handling ../../gst/tta/.libs/libgsttta.so libgsttta.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-vcdsrc.xml b/docs/plugins/inspect/plugin-vcdsrc.xml index 82865aad5e..bb9de2d684 100644 --- a/docs/plugins/inspect/plugin-vcdsrc.xml +++ b/docs/plugins/inspect/plugin-vcdsrc.xml @@ -3,7 +3,7 @@ Asynchronous read from VCD disk ../../sys/vcd/.libs/libgstvcdsrc.so libgstvcdsrc.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-vdpau.xml b/docs/plugins/inspect/plugin-vdpau.xml index 1d3391e1fe..0218c221a6 100644 --- a/docs/plugins/inspect/plugin-vdpau.xml +++ b/docs/plugins/inspect/plugin-vdpau.xml @@ -3,7 +3,7 @@ Various elements utilizing VDPAU ../../sys/vdpau/.libs/libgstvdpau.so libgstvdpau.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer diff --git a/docs/plugins/inspect/plugin-videomaxrate.xml b/docs/plugins/inspect/plugin-videomaxrate.xml index de69ceb4e3..cd0b3118b9 100644 --- a/docs/plugins/inspect/plugin-videomaxrate.xml +++ b/docs/plugins/inspect/plugin-videomaxrate.xml @@ -3,7 +3,7 @@ Drop extra frames ../../gst/videomaxrate/.libs/libgstvideomaxrate.so libgstvideomaxrate.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-videomeasure.xml b/docs/plugins/inspect/plugin-videomeasure.xml index 774e3dd0f4..033f7a40d8 100644 --- a/docs/plugins/inspect/plugin-videomeasure.xml +++ b/docs/plugins/inspect/plugin-videomeasure.xml @@ -3,7 +3,7 @@ Various video measurers ../../gst/videomeasure/.libs/libgstvideomeasure.so libgstvideomeasure.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-videosignal.xml b/docs/plugins/inspect/plugin-videosignal.xml index 45ddbafcc5..57ee747221 100644 --- a/docs/plugins/inspect/plugin-videosignal.xml +++ b/docs/plugins/inspect/plugin-videosignal.xml @@ -3,7 +3,7 @@ Various video signal analysers ../../gst/videosignal/.libs/libgstvideosignal.so libgstvideosignal.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-vmnc.xml b/docs/plugins/inspect/plugin-vmnc.xml index 8fa5902d23..84615d72fb 100644 --- a/docs/plugins/inspect/plugin-vmnc.xml +++ b/docs/plugins/inspect/plugin-vmnc.xml @@ -3,7 +3,7 @@ VmWare Video Codec plugins ../../gst/vmnc/.libs/libgstvmnc.so libgstvmnc.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-vp8.xml b/docs/plugins/inspect/plugin-vp8.xml index 5fd55fb1ec..ca5415bd40 100644 --- a/docs/plugins/inspect/plugin-vp8.xml +++ b/docs/plugins/inspect/plugin-vp8.xml @@ -3,7 +3,7 @@ VP8 plugin ../../ext/vp8/.libs/libgstvp8.so libgstvp8.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-wildmidi.xml b/docs/plugins/inspect/plugin-wildmidi.xml index 3815c491c3..0eb64efd1e 100644 --- a/docs/plugins/inspect/plugin-wildmidi.xml +++ b/docs/plugins/inspect/plugin-wildmidi.xml @@ -3,7 +3,7 @@ Wildmidi Plugin ../../ext/timidity/.libs/libgstwildmidi.so libgstwildmidi.so - 0.10.20.2 + 0.10.20.4 GPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-xvid.xml b/docs/plugins/inspect/plugin-xvid.xml index 8a365bbb58..f8cf93a759 100644 --- a/docs/plugins/inspect/plugin-xvid.xml +++ b/docs/plugins/inspect/plugin-xvid.xml @@ -3,7 +3,7 @@ XviD plugin library ../../ext/xvid/.libs/libgstxvid.so libgstxvid.so - 0.10.20.2 + 0.10.20.4 GPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/docs/plugins/inspect/plugin-y4mdec.xml b/docs/plugins/inspect/plugin-y4mdec.xml index f782b943de..2136e25213 100644 --- a/docs/plugins/inspect/plugin-y4mdec.xml +++ b/docs/plugins/inspect/plugin-y4mdec.xml @@ -3,7 +3,7 @@ FIXME ../../gst/y4m/.libs/libgsty4mdec.so libgsty4mdec.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins diff --git a/docs/plugins/inspect/plugin-zbar.xml b/docs/plugins/inspect/plugin-zbar.xml index 0fdfb655fb..6888d31bbc 100644 --- a/docs/plugins/inspect/plugin-zbar.xml +++ b/docs/plugins/inspect/plugin-zbar.xml @@ -3,7 +3,7 @@ zbar barcode scanner ../../ext/zbar/.libs/libgstzbar.so libgstzbar.so - 0.10.20.2 + 0.10.20.4 LGPL gst-plugins-bad GStreamer Bad Plug-ins prerelease diff --git a/win32/common/config.h b/win32/common/config.h index b1e9cae950..1a7b585637 100644 --- a/win32/common/config.h +++ b/win32/common/config.h @@ -199,7 +199,7 @@ #undef USE_POISONING /* Version number of package */ -#define VERSION "0.10.20.3" +#define VERSION "0.10.20.4" /* Define to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel and VAX). */ From cbbdfee98a905247134f93be76d1a4ab7b49fc6f Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Tue, 18 Jan 2011 18:18:03 -0300 Subject: [PATCH 303/448] mxfdemux: Fix unitialized variable warning --- gst/mxf/mxfdemux.c | 1 + 1 file changed, 1 insertion(+) diff --git a/gst/mxf/mxfdemux.c b/gst/mxf/mxfdemux.c index 6e1faa0f43..3db4413713 100644 --- a/gst/mxf/mxfdemux.c +++ b/gst/mxf/mxfdemux.c @@ -805,6 +805,7 @@ gst_mxf_demux_update_essence_tracks (GstMXFDemux * demux) g_strdup_printf ("application/x-mxf-%s-%s", essence_container, essence_compression); } else { + name = NULL; g_assert_not_reached (); } From 289cd65abd5429ed2230b69cc1f009ce692a5411 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Wed, 19 Jan 2011 18:26:30 +0100 Subject: [PATCH 304/448] flacparse: mind gst_buffer_unref not liking NULL Fixes #639950. --- gst/audioparsers/gstflacparse.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/gst/audioparsers/gstflacparse.c b/gst/audioparsers/gstflacparse.c index 9243a0bdd7..378caf4289 100644 --- a/gst/audioparsers/gstflacparse.c +++ b/gst/audioparsers/gstflacparse.c @@ -961,6 +961,7 @@ gst_flac_parse_handle_headers (GstFlacParse * flacparse) GValue array = { 0, }; GstCaps *caps; GList *l; + gboolean res = TRUE; caps = gst_caps_new_simple ("audio/x-flac", "channels", G_TYPE_INT, flacparse->channels, @@ -1040,23 +1041,27 @@ push_headers: /* push header buffers; update caps, so when we push the first buffer the * negotiated caps will change to caps that include the streamheader field */ - for (l = flacparse->headers; l != NULL; l = l->next) { - GstBuffer *buf = GST_BUFFER (l->data); + while (flacparse->headers) { + GstBuffer *buf = GST_BUFFER (flacparse->headers->data); GstFlowReturn ret; - l->data = NULL; + flacparse->headers = + g_list_delete_link (flacparse->headers, flacparse->headers); buf = gst_buffer_make_metadata_writable (buf); gst_buffer_set_caps (buf, GST_PAD_CAPS (GST_BASE_PARSE_SRC_PAD (GST_BASE_PARSE (flacparse)))); ret = gst_base_parse_push_buffer (GST_BASE_PARSE (flacparse), buf); - if (ret != GST_FLOW_OK) - return FALSE; + if (ret != GST_FLOW_OK) { + res = FALSE; + break; + } } + g_list_foreach (flacparse->headers, (GFunc) gst_mini_object_unref, NULL); g_list_free (flacparse->headers); flacparse->headers = NULL; - return TRUE; + return res; } static gboolean From 07625c1b5d35380661780ec970c61572d3ad9c40 Mon Sep 17 00:00:00 2001 From: David Schleef Date: Wed, 19 Jan 2011 20:00:13 -0800 Subject: [PATCH 305/448] element-maker: Fix handling of debug category --- tools/gst-element-maker | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/tools/gst-element-maker b/tools/gst-element-maker index 67525ef7fc..53145bc3af 100755 --- a/tools/gst-element-maker +++ b/tools/gst-element-maker @@ -132,8 +132,8 @@ grep -A 10000 '^% includes' $templatedir/$class | tail -n +2|grep -m 1 -B 10000 cat < Date: Fri, 21 Jan 2011 21:13:22 +0000 Subject: [PATCH 306/448] Release 0.10.21 --- ChangeLog | 7160 ++++++++++++++++- NEWS | 194 +- RELEASE | 351 +- configure.ac | 6 +- docs/plugins/gst-plugins-bad-plugins.args | 12 +- docs/plugins/inspect/plugin-adpcmdec.xml | 4 +- docs/plugins/inspect/plugin-adpcmenc.xml | 4 +- docs/plugins/inspect/plugin-aiff.xml | 4 +- docs/plugins/inspect/plugin-amrwbenc.xml | 4 +- docs/plugins/inspect/plugin-apexsink.xml | 4 +- docs/plugins/inspect/plugin-asfmux.xml | 4 +- docs/plugins/inspect/plugin-assrender.xml | 4 +- .../inspect/plugin-audioparsersbad.xml | 4 +- docs/plugins/inspect/plugin-autoconvert.xml | 4 +- docs/plugins/inspect/plugin-bayer.xml | 4 +- docs/plugins/inspect/plugin-bz2.xml | 4 +- docs/plugins/inspect/plugin-camerabin.xml | 4 +- docs/plugins/inspect/plugin-cdaudio.xml | 4 +- docs/plugins/inspect/plugin-cdxaparse.xml | 4 +- docs/plugins/inspect/plugin-celt.xml | 4 +- docs/plugins/inspect/plugin-cog.xml | 4 +- docs/plugins/inspect/plugin-coloreffects.xml | 4 +- docs/plugins/inspect/plugin-colorspace.xml | 2 +- docs/plugins/inspect/plugin-dataurisrc.xml | 4 +- docs/plugins/inspect/plugin-dc1394.xml | 4 +- docs/plugins/inspect/plugin-dccp.xml | 2 +- docs/plugins/inspect/plugin-debugutilsbad.xml | 4 +- docs/plugins/inspect/plugin-dfbvideosink.xml | 4 +- docs/plugins/inspect/plugin-dirac.xml | 4 +- docs/plugins/inspect/plugin-dtmf.xml | 4 +- docs/plugins/inspect/plugin-dtsdec.xml | 4 +- docs/plugins/inspect/plugin-dvb.xml | 4 +- docs/plugins/inspect/plugin-dvbsuboverlay.xml | 4 +- docs/plugins/inspect/plugin-dvdspu.xml | 4 +- docs/plugins/inspect/plugin-faac.xml | 4 +- docs/plugins/inspect/plugin-faad.xml | 4 +- docs/plugins/inspect/plugin-fbdevsink.xml | 4 +- docs/plugins/inspect/plugin-festival.xml | 4 +- docs/plugins/inspect/plugin-freeze.xml | 4 +- docs/plugins/inspect/plugin-frei0r.xml | 4 +- docs/plugins/inspect/plugin-gaudieffects.xml | 2 +- .../inspect/plugin-geometrictransform.xml | 4 +- docs/plugins/inspect/plugin-gsettings.xml | 4 +- docs/plugins/inspect/plugin-gsm.xml | 4 +- docs/plugins/inspect/plugin-gstsiren.xml | 4 +- docs/plugins/inspect/plugin-h264parse.xml | 4 +- docs/plugins/inspect/plugin-hdvparse.xml | 2 +- docs/plugins/inspect/plugin-id3tag.xml | 4 +- docs/plugins/inspect/plugin-interlace.xml | 4 +- docs/plugins/inspect/plugin-invtelecine.xml | 4 +- docs/plugins/inspect/plugin-ivfparse.xml | 4 +- docs/plugins/inspect/plugin-jp2kdecimator.xml | 4 +- docs/plugins/inspect/plugin-jpegformat.xml | 4 +- docs/plugins/inspect/plugin-kate.xml | 4 +- docs/plugins/inspect/plugin-ladspa.xml | 4 +- .../plugins/inspect/plugin-legacyresample.xml | 4 +- docs/plugins/inspect/plugin-liveadder.xml | 4 +- docs/plugins/inspect/plugin-mimic.xml | 4 +- docs/plugins/inspect/plugin-mms.xml | 4 +- docs/plugins/inspect/plugin-modplug.xml | 4 +- docs/plugins/inspect/plugin-mpeg2enc.xml | 4 +- .../inspect/plugin-mpeg4videoparse.xml | 4 +- docs/plugins/inspect/plugin-mpegdemux2.xml | 4 +- docs/plugins/inspect/plugin-mpegpsmux.xml | 4 +- docs/plugins/inspect/plugin-mpegtsmux.xml | 4 +- .../plugins/inspect/plugin-mpegvideoparse.xml | 4 +- docs/plugins/inspect/plugin-mplex.xml | 4 +- docs/plugins/inspect/plugin-musepack.xml | 4 +- docs/plugins/inspect/plugin-musicbrainz.xml | 4 +- docs/plugins/inspect/plugin-mve.xml | 4 +- docs/plugins/inspect/plugin-mxf.xml | 4 +- docs/plugins/inspect/plugin-mythtv.xml | 4 +- docs/plugins/inspect/plugin-nas.xml | 4 +- docs/plugins/inspect/plugin-neon.xml | 4 +- docs/plugins/inspect/plugin-nsf.xml | 4 +- docs/plugins/inspect/plugin-nuvdemux.xml | 4 +- docs/plugins/inspect/plugin-ofa.xml | 4 +- docs/plugins/inspect/plugin-opencv.xml | 4 +- docs/plugins/inspect/plugin-pcapparse.xml | 2 +- docs/plugins/inspect/plugin-pnm.xml | 4 +- docs/plugins/inspect/plugin-qtmux.xml | 4 +- docs/plugins/inspect/plugin-rawparse.xml | 4 +- docs/plugins/inspect/plugin-real.xml | 4 +- docs/plugins/inspect/plugin-resindvd.xml | 2 +- docs/plugins/inspect/plugin-rfbsrc.xml | 4 +- docs/plugins/inspect/plugin-rsvg.xml | 4 +- docs/plugins/inspect/plugin-rtpmux.xml | 4 +- docs/plugins/inspect/plugin-scaletempo.xml | 2 +- docs/plugins/inspect/plugin-schro.xml | 4 +- docs/plugins/inspect/plugin-sdl.xml | 4 +- docs/plugins/inspect/plugin-sdp.xml | 4 +- docs/plugins/inspect/plugin-segmentclip.xml | 4 +- docs/plugins/inspect/plugin-shm.xml | 4 +- docs/plugins/inspect/plugin-sndfile.xml | 4 +- docs/plugins/inspect/plugin-soundtouch.xml | 4 +- docs/plugins/inspect/plugin-speed.xml | 4 +- docs/plugins/inspect/plugin-stereo.xml | 4 +- docs/plugins/inspect/plugin-subenc.xml | 4 +- docs/plugins/inspect/plugin-tta.xml | 4 +- docs/plugins/inspect/plugin-vcdsrc.xml | 4 +- docs/plugins/inspect/plugin-vdpau.xml | 2 +- docs/plugins/inspect/plugin-videomaxrate.xml | 4 +- docs/plugins/inspect/plugin-videomeasure.xml | 4 +- docs/plugins/inspect/plugin-videosignal.xml | 4 +- docs/plugins/inspect/plugin-vmnc.xml | 4 +- docs/plugins/inspect/plugin-vp8.xml | 4 +- docs/plugins/inspect/plugin-wildmidi.xml | 4 +- docs/plugins/inspect/plugin-xvid.xml | 4 +- docs/plugins/inspect/plugin-y4mdec.xml | 2 +- docs/plugins/inspect/plugin-zbar.xml | 4 +- gst-plugins-bad.doap | 11 + win32/common/config.h | 4 +- 112 files changed, 7795 insertions(+), 345 deletions(-) diff --git a/ChangeLog b/ChangeLog index ca74376fe4..2a4d89805c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,11 +1,7163 @@ -=== release 0.10.20 === +=== release 0.10.21 === -2010-09-03 Tim-Philipp Müller +2011-01-21 Tim-Philipp Müller * configure.ac: - releasing 0.10.20, "For it is a Human Number" + releasing 0.10.21, "Pink Noise" -2010-09-03 00:03:50 +0100 Tim-Philipp Müller +2011-01-19 20:00:13 -0800 David Schleef + + * tools/gst-element-maker: + element-maker: Fix handling of debug category + +2011-01-19 18:26:30 +0100 Mark Nauwelaerts + + * gst/audioparsers/gstflacparse.c: + flacparse: mind gst_buffer_unref not liking NULL + Fixes #639950. + +2011-01-18 18:18:03 -0300 Thiago Santos + + * gst/mxf/mxfdemux.c: + mxfdemux: Fix unitialized variable warning + +2011-01-18 13:00:11 +0000 Tim-Philipp Müller + + * configure.ac: + * docs/plugins/gst-plugins-bad-plugins.args: + * docs/plugins/inspect/plugin-adpcmdec.xml: + * docs/plugins/inspect/plugin-adpcmenc.xml: + * docs/plugins/inspect/plugin-aiff.xml: + * docs/plugins/inspect/plugin-amrwbenc.xml: + * docs/plugins/inspect/plugin-apexsink.xml: + * docs/plugins/inspect/plugin-asfmux.xml: + * docs/plugins/inspect/plugin-assrender.xml: + * docs/plugins/inspect/plugin-audioparsersbad.xml: + * docs/plugins/inspect/plugin-autoconvert.xml: + * docs/plugins/inspect/plugin-bayer.xml: + * docs/plugins/inspect/plugin-bz2.xml: + * docs/plugins/inspect/plugin-camerabin.xml: + * docs/plugins/inspect/plugin-cdaudio.xml: + * docs/plugins/inspect/plugin-cdxaparse.xml: + * docs/plugins/inspect/plugin-celt.xml: + * docs/plugins/inspect/plugin-cog.xml: + * docs/plugins/inspect/plugin-coloreffects.xml: + * docs/plugins/inspect/plugin-colorspace.xml: + * docs/plugins/inspect/plugin-dataurisrc.xml: + * docs/plugins/inspect/plugin-dc1394.xml: + * docs/plugins/inspect/plugin-dccp.xml: + * docs/plugins/inspect/plugin-debugutilsbad.xml: + * docs/plugins/inspect/plugin-dfbvideosink.xml: + * docs/plugins/inspect/plugin-dirac.xml: + * docs/plugins/inspect/plugin-dtmf.xml: + * docs/plugins/inspect/plugin-dtsdec.xml: + * docs/plugins/inspect/plugin-dvb.xml: + * docs/plugins/inspect/plugin-dvbsuboverlay.xml: + * docs/plugins/inspect/plugin-dvdspu.xml: + * docs/plugins/inspect/plugin-faac.xml: + * docs/plugins/inspect/plugin-faad.xml: + * docs/plugins/inspect/plugin-fbdevsink.xml: + * docs/plugins/inspect/plugin-festival.xml: + * docs/plugins/inspect/plugin-freeze.xml: + * docs/plugins/inspect/plugin-frei0r.xml: + * docs/plugins/inspect/plugin-gaudieffects.xml: + * docs/plugins/inspect/plugin-geometrictransform.xml: + * docs/plugins/inspect/plugin-gsettings.xml: + * docs/plugins/inspect/plugin-gsm.xml: + * docs/plugins/inspect/plugin-gstsiren.xml: + * docs/plugins/inspect/plugin-h264parse.xml: + * docs/plugins/inspect/plugin-hdvparse.xml: + * docs/plugins/inspect/plugin-id3tag.xml: + * docs/plugins/inspect/plugin-interlace.xml: + * docs/plugins/inspect/plugin-invtelecine.xml: + * docs/plugins/inspect/plugin-ivfparse.xml: + * docs/plugins/inspect/plugin-jp2kdecimator.xml: + * docs/plugins/inspect/plugin-jpegformat.xml: + * docs/plugins/inspect/plugin-kate.xml: + * docs/plugins/inspect/plugin-ladspa.xml: + * docs/plugins/inspect/plugin-legacyresample.xml: + * docs/plugins/inspect/plugin-liveadder.xml: + * docs/plugins/inspect/plugin-mimic.xml: + * docs/plugins/inspect/plugin-mms.xml: + * docs/plugins/inspect/plugin-modplug.xml: + * docs/plugins/inspect/plugin-mpeg2enc.xml: + * docs/plugins/inspect/plugin-mpeg4videoparse.xml: + * docs/plugins/inspect/plugin-mpegdemux2.xml: + * docs/plugins/inspect/plugin-mpegpsmux.xml: + * docs/plugins/inspect/plugin-mpegtsmux.xml: + * docs/plugins/inspect/plugin-mpegvideoparse.xml: + * docs/plugins/inspect/plugin-mplex.xml: + * docs/plugins/inspect/plugin-musepack.xml: + * docs/plugins/inspect/plugin-musicbrainz.xml: + * docs/plugins/inspect/plugin-mve.xml: + * docs/plugins/inspect/plugin-mxf.xml: + * docs/plugins/inspect/plugin-mythtv.xml: + * docs/plugins/inspect/plugin-nas.xml: + * docs/plugins/inspect/plugin-neon.xml: + * docs/plugins/inspect/plugin-nsf.xml: + * docs/plugins/inspect/plugin-nuvdemux.xml: + * docs/plugins/inspect/plugin-ofa.xml: + * docs/plugins/inspect/plugin-opencv.xml: + * docs/plugins/inspect/plugin-pcapparse.xml: + * docs/plugins/inspect/plugin-pnm.xml: + * docs/plugins/inspect/plugin-qtmux.xml: + * docs/plugins/inspect/plugin-rawparse.xml: + * docs/plugins/inspect/plugin-real.xml: + * docs/plugins/inspect/plugin-resindvd.xml: + * docs/plugins/inspect/plugin-rfbsrc.xml: + * docs/plugins/inspect/plugin-rsvg.xml: + * docs/plugins/inspect/plugin-rtpmux.xml: + * docs/plugins/inspect/plugin-scaletempo.xml: + * docs/plugins/inspect/plugin-schro.xml: + * docs/plugins/inspect/plugin-sdl.xml: + * docs/plugins/inspect/plugin-sdp.xml: + * docs/plugins/inspect/plugin-segmentclip.xml: + * docs/plugins/inspect/plugin-shm.xml: + * docs/plugins/inspect/plugin-sndfile.xml: + * docs/plugins/inspect/plugin-soundtouch.xml: + * docs/plugins/inspect/plugin-speed.xml: + * docs/plugins/inspect/plugin-stereo.xml: + * docs/plugins/inspect/plugin-subenc.xml: + * docs/plugins/inspect/plugin-tta.xml: + * docs/plugins/inspect/plugin-vcdsrc.xml: + * docs/plugins/inspect/plugin-vdpau.xml: + * docs/plugins/inspect/plugin-videomaxrate.xml: + * docs/plugins/inspect/plugin-videomeasure.xml: + * docs/plugins/inspect/plugin-videosignal.xml: + * docs/plugins/inspect/plugin-vmnc.xml: + * docs/plugins/inspect/plugin-vp8.xml: + * docs/plugins/inspect/plugin-wildmidi.xml: + * docs/plugins/inspect/plugin-xvid.xml: + * docs/plugins/inspect/plugin-y4mdec.xml: + * docs/plugins/inspect/plugin-zbar.xml: + * win32/common/config.h: + 0.10.20.4 pre-release + +2011-01-14 16:30:11 -0300 Thiago Santos + + * gst/audioparsers/gstbaseparse.c: + audioparsers: baseparse: Be careful to not lose the event ref + Don't unref the event if it hasn't been handled, because the caller + assumes it is still valid and might reuse it. + I ran into this problem when transcoding an AVI (with mp3 inside) + to gpp. + https://bugzilla.gnome.org/show_bug.cgi?id=639555 + +2011-01-13 11:28:32 -0300 Thiago Santos + + * tests/check/elements/qtmux.c: + test: qtmux: Tests qtmux reuse + Forces the use of qtmux after it has been put to PLAYING and back + to NULL once + https://bugzilla.gnome.org/show_bug.cgi?id=639338 + +2011-01-13 15:27:36 +0100 Mark Nauwelaerts + + * gst/qtmux/gstqtmux.c: + qtmux: set src pads when starting file + ... rather than at _init time, so they are also available following a + pad (de)activation cycle. + https://bugzilla.gnome.org/show_bug.cgi?id=639338 + +2011-01-12 16:39:22 +0000 Vincent Penquerc'h + + * ext/kate/gstkatetiger.c: + * ext/kate/gstkatetiger.h: + * ext/kate/gstkateutil.c: + kate: ensure the kate pad does not shoot ahead of the video pad + Sync both pads by waiting in the kate chain function. + Do not reset our internal segment from segment updates, in order + to be able to map video running time to kate running time, to + give libtiger the timestamp it expects. This allows us to use + running time to sync to video, which is The Right Way. + https://bugzilla.gnome.org/show_bug.cgi?id=600929 + +2011-01-13 18:35:15 -0200 Luciana Fujii Pontello + + * gst/camerabin/gstcamerabin.c: + camerabin: Enable conversion flags + Camerabin default should just work, so we need to enable audio, image + and video conversions. + https://bugzilla.gnome.org/show_bug.cgi?id=639456 + +2011-01-13 17:10:13 +0000 Tim-Philipp Müller + + * gst/audioparsers/gstdcaparse.c: + dcaparse: fix sync word for 14-bit little endian coding + Fix copy'n'paste bug that made us look for the raw little endian + sync word twice instead of looking for the 14-bit LE sync word + as well. Fixes parsing of such streams (see #636234 for sample file). + +2011-01-13 16:27:04 +0000 Tim-Philipp Müller + + * gst/audioparsers/gstbaseparse.c: + docs: minor baseparse docs/comment fixes + Remove copy'n'paste leftovers. + +2011-01-13 13:36:09 +0200 Teemu Katajisto + + * gst/camerabin/gstcamerabin.c: + camerabin: set pad-negotiation-mode to active for output-selector + Fixes #639413. + +2011-01-12 16:55:07 +0200 Stefan Kost + + * gst/asfmux/gstasfmux.c: + asfmux: use g_error_free instead of g_free + +2011-01-12 16:50:51 +0200 Stefan Kost + + * tests/examples/camerabin2/gst-camera2.c: + camerabin2: use g_error_free instead of g_free + +2011-01-12 11:57:29 +0100 Edward Hervey + + * gst/y4m/gsty4mdec.c: + y4mdec: Default colorspace is I420 + https://bugzilla.gnome.org/show_bug.cgi?id=639296 + +2011-01-11 23:44:51 +0000 Tim-Philipp Müller + + * configure.ac: + * win32/common/config.h: + 0.10.20.3 pre-release + +2011-01-11 15:50:52 +0200 Stefan Kost + + * common: + Automatic update of common submodule + From e572c87 to f94d739 + +2011-01-10 19:11:22 +0100 Edward Hervey + + * gst/mpegdemux/mpegtspacketizer.c: + mpegtspacketizer: Don't forget the GType when using caps_new_simple() + +2011-01-10 16:36:45 +0000 Tim-Philipp Müller + + * common: + Automatic update of common submodule + From ccbaa85 to e572c87 + +2011-01-10 14:54:10 +0000 Tim-Philipp Müller + + * common: + Automatic update of common submodule + From 46445ad to ccbaa85 + +2011-01-10 11:25:47 +0000 Tim-Philipp Müller + + * gst/mpegdemux/mpegtspacketizer.c: + mpegtsdemux: fix silly way of creating caps + +2011-01-10 11:18:52 +0000 Karol Sobczak + + * gst/mpegdemux/mpegtspacketizer.c: + mpegtsdemux: fix re-syncing on invalid data after seek + Or possibly even at startup. If we couldn't find a sync within + the first few bytes, we'd just push more data into the adapter + but never discard any of the invalid data at the beginning, so + would never be able to re-sync. + https://bugzilla.gnome.org/show_bug.cgi?id=639063 + +2011-01-08 03:12:11 +0000 Tim-Philipp Müller + + * ext/cog/gstcogdownsample.c: + * ext/cog/gstcogutils.c: + * ext/schroedinger/gstschroenc.c: + * ext/schroedinger/gstschroparse.c: + * ext/schroedinger/gstschroutils.c: + cog, schroedinger: fix warnings when compiling with -DG_DISABLE_ASSERT + +2011-01-08 03:10:00 +0000 Tim-Philipp Müller + + * configure.ac: + * ext/cog/gstcogorc-dist.c: + * ext/cog/gstcogorc-dist.h: + * win32/common/config.h: + 0.10.20.2 pre-release + +2011-01-08 02:49:06 +0000 Tim-Philipp Müller + + * docs/plugins/gst-plugins-bad-plugins.args: + * docs/plugins/gst-plugins-bad-plugins.hierarchy: + * docs/plugins/inspect/plugin-adpcmdec.xml: + * docs/plugins/inspect/plugin-adpcmenc.xml: + * docs/plugins/inspect/plugin-aiff.xml: + * docs/plugins/inspect/plugin-amrwbenc.xml: + * docs/plugins/inspect/plugin-apexsink.xml: + * docs/plugins/inspect/plugin-asfmux.xml: + * docs/plugins/inspect/plugin-assrender.xml: + * docs/plugins/inspect/plugin-audioparsersbad.xml: + * docs/plugins/inspect/plugin-autoconvert.xml: + * docs/plugins/inspect/plugin-bayer.xml: + * docs/plugins/inspect/plugin-bz2.xml: + * docs/plugins/inspect/plugin-camerabin.xml: + * docs/plugins/inspect/plugin-cdaudio.xml: + * docs/plugins/inspect/plugin-cdxaparse.xml: + * docs/plugins/inspect/plugin-celt.xml: + * docs/plugins/inspect/plugin-cog.xml: + * docs/plugins/inspect/plugin-coloreffects.xml: + * docs/plugins/inspect/plugin-colorspace.xml: + * docs/plugins/inspect/plugin-dataurisrc.xml: + * docs/plugins/inspect/plugin-dc1394.xml: + * docs/plugins/inspect/plugin-dccp.xml: + * docs/plugins/inspect/plugin-debugutilsbad.xml: + * docs/plugins/inspect/plugin-dfbvideosink.xml: + * docs/plugins/inspect/plugin-dirac.xml: + * docs/plugins/inspect/plugin-dtmf.xml: + * docs/plugins/inspect/plugin-dtsdec.xml: + * docs/plugins/inspect/plugin-dvb.xml: + * docs/plugins/inspect/plugin-dvbsuboverlay.xml: + * docs/plugins/inspect/plugin-dvdspu.xml: + * docs/plugins/inspect/plugin-faac.xml: + * docs/plugins/inspect/plugin-faad.xml: + * docs/plugins/inspect/plugin-fbdevsink.xml: + * docs/plugins/inspect/plugin-festival.xml: + * docs/plugins/inspect/plugin-freeze.xml: + * docs/plugins/inspect/plugin-frei0r.xml: + * docs/plugins/inspect/plugin-gaudieffects.xml: + * docs/plugins/inspect/plugin-geometrictransform.xml: + * docs/plugins/inspect/plugin-gsettings.xml: + * docs/plugins/inspect/plugin-gsm.xml: + * docs/plugins/inspect/plugin-gstsiren.xml: + * docs/plugins/inspect/plugin-h264parse.xml: + * docs/plugins/inspect/plugin-hdvparse.xml: + * docs/plugins/inspect/plugin-id3tag.xml: + * docs/plugins/inspect/plugin-interlace.xml: + * docs/plugins/inspect/plugin-invtelecine.xml: + * docs/plugins/inspect/plugin-ivfparse.xml: + * docs/plugins/inspect/plugin-jp2kdecimator.xml: + * docs/plugins/inspect/plugin-jpegformat.xml: + * docs/plugins/inspect/plugin-kate.xml: + * docs/plugins/inspect/plugin-ladspa.xml: + * docs/plugins/inspect/plugin-legacyresample.xml: + * docs/plugins/inspect/plugin-liveadder.xml: + * docs/plugins/inspect/plugin-mimic.xml: + * docs/plugins/inspect/plugin-mms.xml: + * docs/plugins/inspect/plugin-modplug.xml: + * docs/plugins/inspect/plugin-mpeg2enc.xml: + * docs/plugins/inspect/plugin-mpeg4videoparse.xml: + * docs/plugins/inspect/plugin-mpegdemux2.xml: + * docs/plugins/inspect/plugin-mpegpsmux.xml: + * docs/plugins/inspect/plugin-mpegtsmux.xml: + * docs/plugins/inspect/plugin-mpegvideoparse.xml: + * docs/plugins/inspect/plugin-mplex.xml: + * docs/plugins/inspect/plugin-musepack.xml: + * docs/plugins/inspect/plugin-musicbrainz.xml: + * docs/plugins/inspect/plugin-mve.xml: + * docs/plugins/inspect/plugin-mxf.xml: + * docs/plugins/inspect/plugin-mythtv.xml: + * docs/plugins/inspect/plugin-nas.xml: + * docs/plugins/inspect/plugin-neon.xml: + * docs/plugins/inspect/plugin-nsf.xml: + * docs/plugins/inspect/plugin-nuvdemux.xml: + * docs/plugins/inspect/plugin-ofa.xml: + * docs/plugins/inspect/plugin-opencv.xml: + * docs/plugins/inspect/plugin-pcapparse.xml: + * docs/plugins/inspect/plugin-pnm.xml: + * docs/plugins/inspect/plugin-qtmux.xml: + * docs/plugins/inspect/plugin-rawparse.xml: + * docs/plugins/inspect/plugin-real.xml: + * docs/plugins/inspect/plugin-resindvd.xml: + * docs/plugins/inspect/plugin-rfbsrc.xml: + * docs/plugins/inspect/plugin-rsvg.xml: + * docs/plugins/inspect/plugin-rtpmux.xml: + * docs/plugins/inspect/plugin-scaletempo.xml: + * docs/plugins/inspect/plugin-schro.xml: + * docs/plugins/inspect/plugin-sdl.xml: + * docs/plugins/inspect/plugin-sdp.xml: + * docs/plugins/inspect/plugin-segmentclip.xml: + * docs/plugins/inspect/plugin-shm.xml: + * docs/plugins/inspect/plugin-sndfile.xml: + * docs/plugins/inspect/plugin-soundtouch.xml: + * docs/plugins/inspect/plugin-speed.xml: + * docs/plugins/inspect/plugin-stereo.xml: + * docs/plugins/inspect/plugin-subenc.xml: + * docs/plugins/inspect/plugin-tta.xml: + * docs/plugins/inspect/plugin-vcdsrc.xml: + * docs/plugins/inspect/plugin-vdpau.xml: + * docs/plugins/inspect/plugin-videomaxrate.xml: + * docs/plugins/inspect/plugin-videomeasure.xml: + * docs/plugins/inspect/plugin-videosignal.xml: + * docs/plugins/inspect/plugin-vmnc.xml: + * docs/plugins/inspect/plugin-vp8.xml: + * docs/plugins/inspect/plugin-wildmidi.xml: + * docs/plugins/inspect/plugin-xvid.xml: + * docs/plugins/inspect/plugin-y4mdec.xml: + * docs/plugins/inspect/plugin-zbar.xml: + docs: update docs + +2011-01-08 02:47:12 +0000 Tim-Philipp Müller + + * po/bg.po: + * po/ca.po: + * po/ja.po: + po: update translations + +2011-01-08 02:43:41 +0000 Tim-Philipp Müller + + * gst/camerabin/Makefile.am: + * gst/camerabin/camerabingeneral.c: + * gst/camerabin/gstcamerabin-marshal.list: + * gst/camerabin/gstinputselector.c: + * gst/camerabin/gstinputselector.h: + camerabin: use private input-selector that still has "select-all" property + The "select-all" property was removed when input-selector was moved + to core, but camerabin uses this, so make camerabin use a private + copy until a better fix is found. + +2011-01-08 00:32:21 +0000 Tim-Philipp Müller + + * tests/check/Makefile.am: + tests: Makefile.am clean-up + Avoid duplicates GST_CHECK_CFLAGS and GST_OPTIONS_CFLAGS are already in + AM_CFLAGS. Add LDADD instead of GST_CHECK_LIBS for consistency. + +2011-01-08 00:19:06 +0000 Tim-Philipp Müller + + * gst/smoothwave/demo-osssrc.c: + smoothwave: remove old 0.8 example containing code with sideeffects in g_return_if_fail() + May just as well remove it rather than fix it, so it doesn't show + up in greps for this any longer. + +2011-01-08 00:18:17 +0000 Tim-Philipp Müller + + * tests/check/elements/.gitignore: + tests: make git ignore new schroenc test binary + +2011-01-08 00:17:26 +0000 Tim-Philipp Müller + + * tests/check/Makefile.am: + tests: fix CFLAGS and LIBADD order in Makefile.am + +2011-01-08 00:08:11 +0000 Tim-Philipp Müller + + * tests/check/Makefile.am: + tests: never disable g_assert() and cast checks for the unit tests + The unit tests are riddled with g_assert() and friends, make sure we + don't disable assert and cast checks for the unit tests even if + this has been specified for the rest of the code base, e.g. via + --disable-glib-asserts. + +2011-01-08 00:01:01 +0000 Tim-Philipp Müller + + * ext/directfb/dfb-example.c: + directfb: don't put code with side-effects into g_assert() + It will all be turned into a NOOP if -DG_DISABLE_ASSERT is used + (as it is for pre-releases and releases). + +2011-01-07 23:57:21 +0000 Tim-Philipp Müller + + * ext/xvid/gstxvidenc.c: + xvidenc: don't put code with side effects into g_return_val_if_fail() + And don't use g_return*_if_fail() for error handling in elements. + +2011-01-07 18:49:02 +0000 Tim-Philipp Müller + + * gst/mpegvideoparse/mpegpacketiser.c: + * gst/mpegvideoparse/mpegpacketiser.h: + * gst/mpegvideoparse/mpegvideoparse.c: + * gst/mpegvideoparse/mpegvideoparse.h: + Revert "mpegvideoparse: fix timestamp generation" + This reverts commit 2271608c4314d6d0a685c18c5c47d55495586159. + This patch needs more work so it doesn't cause grave playback + regressions (multi-second freezes) with some files that have + slightly broken timestamps but play fine everywhere else. + https://bugzilla.gnome.org/show_bug.cgi?id=636279 + https://bugzilla.gnome.org/show_bug.cgi?id=632222 + +2011-01-07 15:47:39 +0000 Tim-Philipp Müller + + * configure.ac: + configure: fix --disable-external + +2011-01-07 14:51:46 +0000 Tim-Philipp Müller + + * configure.ac: + configure: use $LIBM instead of hard-coding -lm + +2011-01-07 15:22:07 +0200 Stefan Kost + + * gst-libs/gst/signalprocessor/gstsignalprocessor.c: + signalprocessor: don't leak the caps + +2011-01-07 02:10:33 +0000 Tim-Philipp Müller + + * gst/mpegdemux/flutspmtinfo.c: + * gst/mpegdemux/gstmpegtsdemux.c: + mpegtsdemux: fix PAT and PMT info-related object leaks + +2011-01-06 12:51:27 +0100 Edward Hervey + + * gst/jpegformat/gstjpegparse.c: + jpegparse: Fix unitialized variable on macosx + +2011-01-06 12:50:14 +0100 Edward Hervey + + * gst/jp2kdecimator/jp2kcodestream.c: + jp2kdecimator: Fix unitialized variables on macosx + +2011-01-06 12:49:43 +0100 Edward Hervey + + * gst/audioparsers/gstflacparse.c: + flacparse: Fix unitialized variable on macosx + +2010-12-15 15:58:48 -0800 David Schleef + + * gst/y4m/gsty4mdec.h: + y4mdec: Fix copyright + +2010-12-17 14:50:50 -0800 David Schleef + + * tools/element-templates/pushsrc: + * tools/gst-element-maker: + element-maker: improve pushsrc + +2011-01-05 16:43:45 +0100 Edward Hervey + + * gst/y4m/gsty4mdec.c: + y4m: Fix unitialized variables on macosx + +2011-01-05 13:44:04 +0000 Tim-Philipp Müller + + * gst/dvbsuboverlay/Makefile.am: + * gst/dvbsuboverlay/dvb-sub.c: + * gst/dvbsuboverlay/ffmpeg-colorspace.h: + dvbsuboverlay: some more minor clean-ups + +2011-01-04 16:03:01 +0100 Janne Grunau + + * gst/dvbsuboverlay/gstdvbsuboverlay.c: + dvbsuboverlay: fix leak of "clear screen" DVBSubtitles structs + +2011-01-04 13:51:21 +0000 Janne Grunau + + * gst/dvbsuboverlay/dvb-sub.c: + * gst/dvbsuboverlay/gstdvbsuboverlay.c: + dvbsuboverlay: fix two minor deinitialization memory leaks + +2011-01-03 23:55:59 +0000 Tim-Philipp Müller + + * tests/examples/Makefile.am: + examples: dist camerabin2 example as well + https://bugzilla.gnome.org/show_bug.cgi?id=638604 + +2011-01-03 23:49:51 +0000 Tim-Philipp Müller + + * gst/camerabin2/Makefile.am: + camerabin2: fix cflags and libs order in Makefile.am + +2011-01-03 23:47:33 +0000 Tim-Philipp Müller + + * gst-libs/gst/basecamerabinsrc/Makefile.am: + basecamerabinsrc: fix libs order in Makefile.am + +2011-01-03 23:46:02 +0000 Tim-Philipp Müller + + * gst-libs/gst/Makefile.am: + build: fix disting of experimental basecamerabinsrc lib used by camerabin2 + https://bugzilla.gnome.org/show_bug.cgi?id=638604 + +2011-01-03 17:10:36 -0600 Rob Clark + + * sys/dvb/camswclient.c: + * sys/dvb/gstdvbsrc.c: + dvb: fix build errors on macosx + fixes the following compile errors: + cc1: warnings being treated as errors + camswclient.c: In function 'cam_sw_client_open': + camswclient.c:81: warning: implicit declaration of function 'strncpy' + camswclient.c:81: warning: incompatible implicit declaration of built-in function 'strncpy' + camswclient.c:89: warning: implicit declaration of function 'strerror' + camswclient.c:89: warning: nested extern declaration of 'strerror' + camswclient.c:89: warning: format '%s' expects type 'char *', but argument 9 has type 'int' + camswclient.c: In function 'send_ca_pmt': + camswclient.c:129: warning: implicit declaration of function 'memcpy' + camswclient.c:129: warning: incompatible implicit declaration of built-in + function 'memcpy' + gstdvbsrc.c:48:19: error: error.h: No such file or directory + Signed-off-by: Rob Clark + +2011-01-03 20:05:52 +0100 Janne Grunau + + * gst/dvbsuboverlay/dvb-sub.c: + * gst/dvbsuboverlay/gstdvbsuboverlay.c: + dvbsuboverlay: remove unnecessary RGB -> YUV conversion by using YUV palettes + the default CLUTs still use RGB -> YUV conversions since the standard defines + them as RGBA values. + +2011-01-03 20:21:57 +0000 Tim-Philipp Müller + + * m4/Makefile.am: + * m4/esd.m4: + * m4/glib.m4: + * m4/gst-matroska.m4: + * m4/gst-shout2.m4: + * m4/gtk.m4: + * m4/ogg.m4: + * m4/vorbis.m4: + m4: remove some cruft + +2011-01-03 17:24:23 +0100 Mark Nauwelaerts + + * gst/qtmux/gstqtmux.c: + * gst/qtmux/gstqtmux.h: + qtmux: adjust nasty case timestamp tracking + That is, all sorts of problems arise with re-ordered input timestamps that + tend to defy automagic handling for every case, so allow for a few variations + that can be tried depending on circumstances. + Also try to document accordingly. + Also fixes #638288. + +2010-12-30 21:48:41 +0200 Felipe Contreras + + * gst/qtmux/gstqtmux.c: + qtmux: get rid of timestamp overprotectiveness + Signed-off-by: Felipe Contreras + +2011-01-03 16:56:57 +0100 Mark Nauwelaerts + + * gst/qtmux/atoms.c: + * gst/qtmux/atoms.h: + * gst/qtmux/atomsrecovery.c: + * gst/qtmux/gstqtmux.c: + qtmux: simplify and fix pts_offset storing + In particular, only write a ctts atom if and only if ever a non-zero offset. + +2011-01-03 10:43:15 +0100 Mark Nauwelaerts + + * gst/qtmux/gstqtmux.c: + qtmux: add some more documentation + +2010-12-03 15:23:00 +0100 Mark Nauwelaerts + + * gst/qtmux/atoms.c: + * gst/qtmux/atoms.h: + * gst/qtmux/gstqtmux.c: + * gst/qtmux/gstqtmux.h: + qtmux: remove large-file property + Rather, auto-determine if 64-bits fields are needed for a valid result, and + stick to plain 32-bits if not needed. + API: GstQTMux:large-file (removed) + +2011-01-03 18:13:37 +0200 Stefan Kost + + * sys/dvb/README: + README: fix the example pipeline + Fix the obvious outdated parts. Still this README looks outdated and should be + updated or removed. + +2011-01-02 19:38:01 -0800 David Schleef + + * tools/gst-element-maker: + element-maker: Add debug category + +2011-01-02 16:13:56 -0800 David Schleef + + * gst/colorspace/colorspace.c: + colorspace: Disable matrixing on big-endian + It's broken until someone writes better Orc code. Fixes #631232. + +2010-12-05 03:29:42 -0800 David Schleef + + * gst/mpegtsmux/tsmux/tsmuxstream.c: + mpegtsmux: Set adaptation flag when appropriate + Specifically, when there's stuff to go into the adaptation + header. + +2010-11-17 17:49:17 -0800 David Schleef + + * gst/mpegtsmux/mpegtsmux.c: + * gst/mpegtsmux/tsmux/tsmuxstream.c: + * gst/mpegtsmux/tsmux/tsmuxstream.h: + mpegtsmux: Set random_access_indicator for keyframes + +2010-12-31 16:20:22 +0000 Vincent Penquerc'h + + * ext/kate/gstkatetiger.c: + tiger: outline text by default, to make it easier to read + https://bugzilla.gnome.org/show_bug.cgi?id=638527 + +2011-01-02 15:11:52 +0000 Tim-Philipp Müller + + * LICENSE_readme: + * Makefile.am: + * configure.ac: + * docs/plugins/Makefile.am: + * docs/plugins/gst-plugins-bad-plugins-docs.sgml: + * docs/plugins/gst-plugins-bad-plugins-sections.txt: + * docs/plugins/gst-plugins-bad-plugins.args: + * docs/plugins/gst-plugins-bad-plugins.hierarchy: + * docs/plugins/inspect/plugin-jack.xml: + * ext/Makefile.am: + * ext/jack/.gitignore: + * ext/jack/Makefile.am: + * ext/jack/README: + * ext/jack/gstjack.c: + * ext/jack/gstjack.h: + * ext/jack/gstjackaudioclient.c: + * ext/jack/gstjackaudioclient.h: + * ext/jack/gstjackaudiosink.c: + * ext/jack/gstjackaudiosink.h: + * ext/jack/gstjackaudiosrc.c: + * ext/jack/gstjackaudiosrc.h: + * ext/jack/gstjackringbuffer.h: + * ext/jack/gstjackutil.c: + * ext/jack/gstjackutil.h: + * gst-plugins-bad.spec.in: + * tests/examples/Makefile.am: + * tests/examples/jack/Makefile.am: + * tests/examples/jack/jack_client.c: + jack: move plugin to gst-plugins-good + https://bugzilla.gnome.org/show_bug.cgi?id=621929 + +2011-01-02 13:52:36 +0000 Tim-Philipp Müller + + * ext/kate/gstkatedec.c: + * ext/kate/gstkatetiger.c: + * ext/kate/gstkateutil.c: + kate: fix caps and string leaks and some minor clean-ups + Don't leak source caps. Use GST_PTR_FORMAT to log caps, so + we don't need to leak strings from gst_caps_to_string(). + No need to use GST_DEBUG_FUNCPTR for vfuncs where the base + class will never look them up (like property getters/setters). + Don't use g_return_*_if_fail() for things that aren't directly + programming errors (by the application developer). + Fixes kate unit test under valgrind. + +2010-12-31 16:17:50 +0000 Vincent Penquerc'h + + * ext/kate/gstkateutil.c: + kate: reenable the sending of a message for tags + https://bugzilla.gnome.org/show_bug.cgi?id=638412 + +2011-01-02 13:29:06 +0000 Tim-Philipp Müller + + * gst/gaudieffects/Makefile.am: + gaudieffects: dist python examples + +2010-12-31 00:09:09 -0800 David Schleef + + * tools/gst-element-maker: + element-maker: Update FSF address + +2010-12-31 00:07:28 -0800 David Schleef + + * tools/Makefile.am: + * tools/gst-app-maker: + Add gst-app-maker + +2010-12-31 00:12:53 -0800 David Schleef + + * gst/dtmf/tone_detect.c: + dtmf: Fix build failure caused by previous commit + +2010-12-30 19:21:47 -0800 David Schleef + + * ext/cog/generate_tables.c: + * ext/cog/gstcms.c: + * ext/cog/gstcolorconvert.c: + cog: Use math-compat.h + +2010-12-30 19:21:21 -0800 David Schleef + + * gst/mpegdemux/gstmpegtsdemux.c: + mpegdemux: Fix c99-ism + +2010-12-30 19:12:23 -0800 David Schleef + + * gst/legacyresample/resample_functable.c: + * gst/legacyresample/resample_ref.c: + legacyresample: Use math-compat header + +2010-12-30 19:03:54 -0800 David Schleef + + * gst/gaudieffects/gstgaussblur.c: + * gst/geometrictransform/gstrotate.c: + change M_PI to G_PI + +2010-12-30 19:03:14 -0800 David Schleef + + * gst/frei0r/frei0r.h: + * gst/frei0r/gstfrei0r.h: + frei0r: convert uint32_t to guint32 + +2010-12-30 18:20:47 -0800 David Schleef + + * gst/dtmf/gstdtmfdetect.c: + * gst/dtmf/tone_detect.c: + * gst/dtmf/tone_detect.h: + dtmf: build fixes for MSVC + Use gint16 and G_PI. + +2010-12-30 18:19:47 -0800 David Schleef + + * gst/dtmf/tone_detect.c: + dtmf: reindent + +2010-12-30 18:02:06 -0800 David Schleef + + * gst/dataurisrc/gstdataurisrc.c: + dataurisrc: use g_ascii_strcasecmp() + +2010-12-31 01:38:02 +0000 Tim-Philipp Müller + + * Makefile.am: + * configure.ac: + * docs/plugins/Makefile.am: + * docs/plugins/gst-plugins-bad-plugins-docs.sgml: + * docs/plugins/gst-plugins-bad-plugins-sections.txt: + * docs/plugins/gst-plugins-bad-plugins.args: + * docs/plugins/gst-plugins-bad-plugins.hierarchy: + * docs/plugins/inspect/plugin-selector.xml: + * gst-plugins-bad.spec.in: + * gst/selector/.gitignore: + * gst/selector/Makefile.am: + * gst/selector/gstinputselector.c: + * gst/selector/gstinputselector.h: + * gst/selector/gstoutputselector.c: + * gst/selector/gstoutputselector.h: + * gst/selector/gstselector-marshal.list: + * gst/selector/gstselector.c: + * gst/selector/selector.vcproj: + * tests/check/Makefile.am: + * tests/check/elements/.gitignore: + * tests/check/elements/selector.c: + * tests/examples/Makefile.am: + * tests/examples/switch/.gitignore: + * tests/examples/switch/Makefile.am: + * tests/examples/switch/switcher.c: + * tests/icles/.gitignore: + * tests/icles/Makefile.am: + * tests/icles/output-selector-test.c: + selector: move input-selector and output-selector to core + https://bugzilla.gnome.org/show_bug.cgi?id=614306 + +2010-12-30 01:17:28 +0000 Tim-Philipp Müller + + * docs/plugins/gst-plugins-bad-plugins.args: + * docs/plugins/inspect/plugin-asfmux.xml: + * docs/plugins/inspect/plugin-audioparsersbad.xml: + * docs/plugins/inspect/plugin-autoconvert.xml: + * docs/plugins/inspect/plugin-bayer.xml: + * docs/plugins/inspect/plugin-coloreffects.xml: + * docs/plugins/inspect/plugin-colorspace.xml: + * docs/plugins/inspect/plugin-debugutilsbad.xml: + * docs/plugins/inspect/plugin-dvbsuboverlay.xml: + * docs/plugins/inspect/plugin-geometrictransform.xml: + * docs/plugins/inspect/plugin-interlace.xml: + * docs/plugins/inspect/plugin-jp2kdecimator.xml: + * docs/plugins/inspect/plugin-jpegformat.xml: + * docs/plugins/inspect/plugin-kate.xml: + * docs/plugins/inspect/plugin-opencv.xml: + * docs/plugins/inspect/plugin-qtmux.xml: + * docs/plugins/inspect/plugin-rsvg.xml: + * docs/plugins/inspect/plugin-videomeasure.xml: + * docs/plugins/inspect/plugin-y4mdec.xml: + * docs/plugins/inspect/plugin-zbar.xml: + docs: update plugin docs + +2010-12-30 01:14:29 +0000 Tim-Philipp Müller + + * Makefile.am: + * configure.ac: + * docs/plugins/Makefile.am: + * docs/plugins/gst-plugins-bad-plugins-docs.sgml: + * docs/plugins/gst-plugins-bad-plugins-sections.txt: + * docs/plugins/gst-plugins-bad-plugins.args: + * docs/plugins/gst-plugins-bad-plugins.hierarchy: + * docs/plugins/gst-plugins-bad-plugins.interfaces: + * docs/plugins/gst-plugins-bad-plugins.prerequisites: + * docs/plugins/inspect/plugin-valve.xml: + * gst-plugins-bad.spec.in: + * gst/valve/Makefile.am: + * gst/valve/gstvalve.c: + * gst/valve/gstvalve.h: + * tests/check/Makefile.am: + * tests/check/elements/.gitignore: + * tests/check/elements/valve.c: + valve: move valve element/plugin to core + https://bugzilla.gnome.org/show_bug.cgi?id=630808 + +2010-12-29 13:18:37 -0300 Thiago Santos + + * gst/camerabin2/gstwrappercamerabinsrc.c: + camerabin2: Various leak fixes + Various leak fixes and some code reorganization + +2010-12-27 17:18:29 -0300 Thiago Santos + + * tests/examples/camerabin2/.gitignore: + camerabin2: example: gitignore captured files + +2010-12-26 20:52:25 -0300 Thiago Santos + + * gst/camerabin2/gstwrappercamerabinsrc.c: + wrappercamerabinsrc: Implement video capture renegotiate + Handle caps renegotiation from camerabin2's renegotiate event + to allow video capture to be done with the user's requested + resolution. + +2010-12-26 20:47:40 -0300 Thiago Santos + + * tests/check/elements/camerabin2.c: + camerabin2: Add tests for video capture + Add a test for capturing multiple videos with different resolutions + in a sequence. + +2010-12-26 20:35:47 -0300 Thiago Santos + + * gst/camerabin2/gstcamerabin2.c: + camerabin2: Fix renegotiate event pushing + Use a hack to make the event upstream to reach the camera source + instead of going downstream and being useless. + This was already fixed this way for image srcpad renegotiate and + video srcpad was left unfixed. + +2010-12-24 09:10:48 -0300 Thiago Santos + + * gst/camerabin2/gstwrappercamerabinsrc.c: + * gst/camerabin2/gstwrappercamerabinsrc.h: + wrappercamerabinsrc: Refactor internal pipeline + Instead of linking 3 src pads from tee to the ghostpads, use 2 + srcpads and add an output-selector to completely split caps + negotiation of video/image modes. I don't think there is an + use case that would require image and video pads to be used + at the same time. + +2010-12-22 14:42:27 +0000 Vincent Penquerc'h + + * configure.ac: + configure: use -pthread for xvid configure check + https://bugzilla.gnome.org/show_bug.cgi?id=637823 + https://bugzilla.gnome.org/show_bug.cgi?id=637308 + +2010-12-28 17:16:05 -0300 Thiago Santos + + * gst/camerabin/gstcamerabin.c: + camerabin: mode can be only image or video + No need to check if camerabin is on video mode if it isn't on + image mode as those are the only 2 modes available. + Additionally, if mode gets corrupted somehow and would be neither + image or video it would cause a null pointer dereferencing some + lines of code below, so this is safer. + +2010-12-28 16:55:11 -0300 Thiago Santos + + * gst/camerabin/gstcamerabin.c: + camerabin: Remove unused variable + +2010-12-27 16:58:26 -0300 Thiago Santos + + * gst/asfmux/gstasf.c: + asfmux: Fix plugin package name/origin + +2010-12-27 13:20:28 +0100 Alessandro Decina + + * gst/dvbsuboverlay/gstdvbsuboverlay.c: + dvbsuboverlay: fix compiler warnings + +2010-12-27 11:10:53 +0000 Tim-Philipp Müller + + * gst/dvbsuboverlay/dvb-sub.c: + * gst/dvbsuboverlay/dvb-sub.h: + * gst/dvbsuboverlay/gstdvbsuboverlay.c: + dvbsuboverlay: clean-up: allocate flat array of rectangles + instead of an array of pointers to individually-allocated rectangles. + +2010-12-23 18:18:50 +0000 Vincent Penquerc'h + + * ext/kate/gstkatetiger.c: + * ext/kate/gstkatetiger.h: + tiger: fallback on headers in caps to initialize if headers are absent + When Totem switches streams, tiger will be reset, and start receiving + buffers from the middle of the stream, without being sent headers. + If this happens, try to get headers from the caps. + https://bugzilla.gnome.org/show_bug.cgi?id=638004 + +2010-12-26 17:19:00 +0000 Tim-Philipp Müller + + * gst-libs/gst/interfaces/photography.c: + photography: fix typo in property description + +2010-12-26 17:07:38 +0000 Tim-Philipp Müller + + * tests/examples/camerabin/gst-camera.c: + examples: fix gtk3 code path in camerabin example app + Just add rows via the combobox's model, which should work with + both gtk2 and gtk3, instead of using the gtk_combo_box_append_text() + convenience API (which was renamed to gtk_combo_box_text_append_text()). + Fixes compilation against gtk3 (there was a typo in the list store + variable name, spotted by Markus Vartiainen). + +2010-12-25 17:01:11 +0000 Vincent Penquerc'h + + * ext/kate/gstkatetiger.c: + kate: if seeking with GST_SEEK_TYPE_CUR, flush everything + We don't know how to calculate the target, so be safe. + https://bugzilla.gnome.org/show_bug.cgi?id=600929 + +2010-12-25 16:44:03 +0000 Tim-Philipp Müller + + * ext/kate/gstkatetiger.c: + tiger: move #if #else bits outside of macro + Some compilers/preprocessors don't like if/else/endif preprocessor + directives in the middle of macros. + +2010-12-24 14:44:23 +0000 Tim-Philipp Müller + + * gst/dvbsuboverlay/dvb-sub.c: + dvbsuboverlay: clean-up: merge private data struct into main struct + +2010-12-24 14:24:12 +0000 Tim-Philipp Müller + + * gst/dvbsuboverlay/dvb-sub.c: + * gst/dvbsuboverlay/dvb-sub.h: + * gst/dvbsuboverlay/gstdvbsuboverlay.c: + dvbsuboverlay: clean-up: dvb sub parser helper doesn't need to be a GObject + +2010-01-25 18:26:25 +0000 Vincent Penquerc'h + + * ext/kate/gstkate.c: + tiger: Give tiger primary rank + +2010-01-25 18:58:38 +0000 Vincent Penquerc'h + + * ext/kate/Makefile.am: + * ext/kate/gstkate.c: + * ext/kate/gstkatedec.c: + * ext/kate/gstkatedec.h: + * ext/kate/gstkateparse.c: + * ext/kate/gstkatespu.c: + * ext/kate/gstkatetiger.c: + * ext/kate/gstkatetiger.h: + * ext/kate/gstkateutil.c: + * ext/kate/gstkateutil.h: + kate: add segment tracking, and various other improvements + https://bugzilla.gnome.org/show_bug.cgi?id=600929 + +2010-12-24 10:15:46 +0000 Vincent Penquerc'h + + * gst/mve/gstmvedemux.c: + mve: do not use the pad buffer allocation functions in demuxers + https://bugzilla.gnome.org/show_bug.cgi?id=637929 + +2010-12-24 09:50:00 +0000 Vincent Penquerc'h + + * gst/mpegdemux/gstmpegtsdemux.c: + mpegdemux: do not use the pad buffer allocation functions in demuxers + https://bugzilla.gnome.org/show_bug.cgi?id=637931 + +2010-12-23 22:01:00 +0000 Tim-Philipp Müller + + * gst/mpeg4videoparse/mpeg4videoparse.c: + mpeg4videoparse: try harder to make buffer metadata writable before modifying + Also, check buffer for NULL-ness before dereferencing it. + https://bugzilla.gnome.org/show_bug.cgi?id=637824 + +2010-12-22 11:44:55 -0300 Thiago Santos + + * gst-libs/gst/basecamerabinsrc/gstbasecamerasrc.c: + basecamerasrc: Notify earlier + Notify about ready-for-capture changes earlier to allow camerabin2 + to do the videobin state switching before the capture starts. + +2010-12-21 19:22:36 -0300 Thiago Santos + + * gst/camerabin2/gstvideorecordingbin.c: + videorecordingbin: Fix leaks + +2010-12-21 11:04:00 -0300 Thiago Santos + + * tests/check/elements/camerabin2.c: + camerabin2: Refactor tests + Refactor tests case so that the same tests can be run for different + camera sources. + +2010-12-20 18:30:32 -0300 Thiago Santos + + * tests/check/elements/.gitignore: + tests: gitignore camerabin2 tests + Adds more camerabin2 elements tests to gitignore + +2010-12-20 18:09:26 -0300 Thiago Santos + + * gst/camerabin2/gstwrappercamerabinsrc.c: + wrappercamerabinsrc: Add converters for viewfinder branch + Viewfinder branch should have converters as it has to work + always anyway. + +2010-12-20 14:20:35 -0300 Thiago Santos + + * tests/check/Makefile.am: + * tests/check/elements/imagecapturebin.c: + imagecapturebin: Add another test case + Adds a test case to check if a sequence of buffers with different + caps can be pushed to imagecapturebin and saved correctly + +2010-12-20 02:59:14 -0300 Thiago Santos + + * tests/check/Makefile.am: + * tests/check/elements/viewfinderbin.c: + viewfinderbin: Add basic check test + Adds minimum check test. It's not a very useful test, but at least + it allows us to run it under valgrind and check for leaks automatically + +2010-12-20 02:58:44 -0300 Thiago Santos + + * gst/camerabin2/gstviewfinderbin.c: + viewfinderbin: Remove leaks + Removing various leaks from viewfinderbin + +2010-12-17 23:06:45 -0300 Thiago Santos + + * gst/camerabin2/gstcamerabin2.c: + camerabin2: more logs + +2010-12-17 23:06:23 -0300 Thiago Santos + + * tests/check/elements/camerabin2.c: + camerabin2: Small tests update + Increases timeout value so that tests won't fail with full + debug output. + Also removes buffer alloc from videotestsrc as this feature + isn't ready on camerabin2 + +2010-12-14 22:06:33 -0300 Thiago Santos + + * tests/check/elements/camerabin2.c: + camerabin2: Adds tests for image capture with different caps + Adds a test that tries sucessive captures with different caps + +2010-12-16 00:40:25 -0300 Thiago Santos + + * gst/camerabin2/gstwrappercamerabinsrc.c: + * gst/camerabin2/gstwrappercamerabinsrc.h: + wrappercamerabinsrc: Handle camerabin2 custom renegotiate events + +2010-12-15 14:05:54 -0300 Thiago Santos + + * gst/camerabin2/gstcamerabin2.c: + camerabin2: Use custom renegotiate event + Adds a custom renegotiate event that is pushed to the camerasrc pad + that needs renegotiation due to the user selecting a new capture + caps for that pad. + This is a way of notifying the source that it should update its caps, even + if it doesn't use pad allocs. + +2010-12-16 22:49:24 -0300 Thiago Santos + + * gst/camerabin2/gstwrappercamerabinsrc.c: + * gst/camerabin2/gstwrappercamerabinsrc.h: + wrappercamerabinsrc: Add local mode + +2010-12-14 18:42:51 -0300 Thiago Santos + + * gst/camerabin2/gstcamerabin2.c: + camerabin2: Adds properties for capture caps + Adds properties for selecting caps for video and image captures + +2010-12-19 19:40:54 -0300 Thiago Santos + + * gst-libs/gst/Makefile.am: + basecamerabinsrc: Fix makefile building order + basecamerabinsrc must be built after photography interface + as it depends on it. + +2010-12-10 17:45:40 +0200 Teemu Katajisto + + * gst/camerabin2/gstimagecapturebin.c: + camerabin2: remove abreviations from imagecapturebin + +2010-12-16 08:47:56 -0300 Thiago Santos + + * gst-libs/gst/basecamerabinsrc/gstbasecamerasrc.c: + basecamerasrc: Add some more logging + Adds some more logging and always assume capture has started before + start_capture is called. This helps on image captures that might + call finish_capture directly from start_capture or before start_capture + finishes. + +2010-12-15 22:35:16 -0300 Thiago Santos + + * gst-libs/gst/basecamerabinsrc/gstbasecamerasrc.c: + * gst-libs/gst/basecamerabinsrc/gstbasecamerasrc.h: + * gst/camerabin2/gstwrappercamerabinsrc.c: + basecamerasrc: More cleanup + Remove old legacy code copied from camerabin(1) that should be handled + by caps negotiation on camerabin2 + +2010-12-15 14:07:15 -0300 Thiago Santos + + * gst/camerabin2/gstwrappercamerabinsrc.c: + wrappercamerabinsrc: Remove unused variable + Remove wait_for_prepara variable that wasn't being used + +2010-12-14 17:23:10 -0300 Thiago Santos + + * gst/camerabin2/Makefile.am: + * gst/camerabin2/gstcamerabin2.c: + * gst/camerabin2/gstplugin.c: + * gst/camerabin2/gstv4l2camerasrc.c: + * gst/camerabin2/gstv4l2camerasrc.h: + * gst/camerabin2/gstwrappercamerabinsrc.c: + * gst/camerabin2/gstwrappercamerabinsrc.h: + * tests/check/elements/camerabin2.c: + camerabin2: Rename v4l2camerasrc to wrappercamerabinsrc + Use a better name for the element that wraps single pad src element + into a 3pad source required by camerabin2. + +2010-12-14 16:59:54 -0300 Thiago Santos + + * gst/camerabin2/gstv4l2camerasrc.c: + * gst/camerabin2/gstv4l2camerasrc.h: + v4l2camerasrc: remove video filter property code + Removes some unused custom video filter element property code + +2010-12-16 10:51:38 -0300 Thiago Santos + + * gst/camerabin2/gstviewfinderbin.c: + viewfinderbin: Fix video-sink property again + Avoid switching the element on the set_property function, instead wait + for the next NULL -> READY transition. + +2010-12-14 14:48:28 -0300 Thiago Santos + + * tests/check/elements/camerabin2.c: + camerabin2: Use videotestsrc on the tests + Use videotestsrc to avoid openning the camera device on the tests. + +2010-12-14 14:43:59 -0300 Thiago Santos + + * gst/camerabin2/gstv4l2camerasrc.c: + v4l2camerasrc: add video-src property + Adds a property to select the src element to be used internally + on v4l2camerasrc. Yeah, I know, this element should have a better + name. + +2010-12-13 17:56:14 -0300 Thiago Santos + + * tests/check/elements/camerabin2.c: + camerabin2: Add test for supported caps properties + Adds tests for checking that the supported caps properties work + as expected (using the respective pads get caps function) + +2010-12-14 08:44:36 -0300 Thiago Santos + + * gst/camerabin2/PORTING: + camerabin2: adds PORTING document + Adds a PORTING document to explain the differences from + camerabin to camerabin2 and help application developers on + porting from one to another. + +2010-12-13 19:36:41 -0300 Thiago Santos + + * configure.ac: + * gst-libs/gst/Makefile.am: + * gst-libs/gst/basecamerabinsrc/Makefile.am: + * gst-libs/gst/basecamerabinsrc/gstbasecamerasrc.c: + * gst-libs/gst/basecamerabinsrc/gstbasecamerasrc.h: + * gst-libs/gst/basecamerabinsrc/gstcamerabin-enum.c: + * gst-libs/gst/basecamerabinsrc/gstcamerabin-enum.h: + * gst/camerabin2/Makefile.am: + * gst/camerabin2/gstbasecamerasrc.c: + * gst/camerabin2/gstbasecamerasrc.h: + * gst/camerabin2/gstcamerabin-enum.c: + * gst/camerabin2/gstcamerabin-enum.h: + * gst/camerabin2/gstcamerabin2.c: + * gst/camerabin2/gstv4l2camerasrc.c: + * gst/camerabin2/gstv4l2camerasrc.h: + * tests/check/Makefile.am: + * tests/check/elements/camerabin2.c: + camerabin2: Move basecamerasrc to gst-libs + Move the base camera src class to gst-libs/gst/basecamerabinsrc to + allow it to be included from the tests. + +2010-12-14 14:28:49 +0200 Teemu Katajisto + + * gst/camerabin2/gstvideorecordingbin.c: + * gst/camerabin2/gstvideorecordingbin.h: + * tests/check/elements/videorecordingbin.c: + camerabin2: add videorecordingbin::video-muxer property + +2010-12-14 12:21:57 +0200 Teemu Katajisto + + * gst/camerabin2/gstvideorecordingbin.c: + * gst/camerabin2/gstvideorecordingbin.h: + * tests/check/elements/videorecordingbin.c: + camerabin2: add videorecordingbin::video-encoder property + +2010-12-14 09:58:35 +0200 Teemu Katajisto + + * gst/camerabin2/gstvideorecordingbin.c: + camerabin2: remove abbreviations from videorecordingbin + +2010-12-14 10:48:56 +0200 Teemu Katajisto + + * gst/camerabin2/gstimagecapturebin.c: + camerabin2: imagecapturebin: release objects and memory allocations + +2010-12-13 16:36:19 -0300 Thiago Santos + + * gst/camerabin2/gstcamerabin2.c: + * gst/camerabin2/gstcamerabin2.h: + camerabin2: Add camera-src property + Adds a property to select the camera source element to be used. + Changing only happens on the next NULL->READY transition + +2010-12-13 11:53:59 -0300 Thiago Santos + + * gst/camerabin2/gstcamerabin2.c: + * gst/camerabin2/gstcamerabin2.h: + camerabin2: Rename variables + Use better name for the variables, making the code clearer. Also + keep a ref for some internal elements to avoid fetching them + by name when needed later. + +2010-12-12 23:03:21 -0300 Thiago Santos + + * gst/camerabin2/gstbasecamerasrc.c: + * gst/camerabin2/gstcamerabin2.c: + camerabin2: Add properties for supported capture caps + Adds 2 property for getting the supported image/video capture + caps from the camera source. + +2010-12-12 20:46:16 -0300 Thiago Santos + + * gst/camerabin2/gstbasecamerasrc.c: + * gst/camerabin2/gstcamerabin-enum.h: + * gst/camerabin2/gstv4l2camerasrc.c: + camerabin2: Put enums inside their classes .c + Remove global list of properties' enums and put them + inside their classes .c + +2010-12-12 19:33:24 -0300 Thiago Santos + + * gst/camerabin2/gstcamerabin2.c: + * gst/camerabin2/gstviewfinderbin.c: + * gst/camerabin2/gstviewfinderbin.h: + * tests/check/elements/camerabin2.c: + viewfinderbin: Fixes to video-sink handling + Handle video-sink more carefully, checking if it should + be already added to the bin, and removing old ones when + replacing. + +2010-12-13 16:28:58 +0200 Teemu Katajisto + + * gst/camerabin2/gstimagecapturebin.c: + * gst/camerabin2/gstimagecapturebin.h: + * tests/check/elements/imagecapturebin.c: + camerabin2: add imagecapturebin::image-muxer property + +2010-12-13 12:08:22 +0200 Teemu Katajisto + + * gst/camerabin2/gstimagecapturebin.c: + * gst/camerabin2/gstimagecapturebin.h: + * tests/check/elements/imagecapturebin.c: + camerabin2: add imagecapturebin::image-encoder property + +2010-12-10 17:45:40 +0200 Teemu Katajisto + + * gst/camerabin2/gstimagecapturebin.c: + camerabin2: remove abreviations from imagecapturebin + +2010-12-10 12:08:48 -0300 André Dieb Martins + + * gst/camerabin2/gstcamerabin2.c: + * gst/camerabin2/gstcamerabin2.h: + * gst/camerabin2/gstviewfinderbin.c: + * gst/camerabin2/gstviewfinderbin.h: + * tests/check/elements/camerabin2.c: + camerabin2: implement viewfinderbin::video-sink property to override default video output + +2010-12-09 14:13:13 -0300 Thiago Santos + + * gst/camerabin2/gstbasecamerasrc.c: + basecamerasrc: Make construct_pipeline optional + Construct pipeline should be optional. Subclasses that don't + have internal elements don't need it. + +2010-12-09 12:23:01 +0200 Stefan Kost + + * gst/camerabin2/gstbasecamerasrc.c: + * gst/camerabin2/gstbasecamerasrc.h: + basecamerasrc: write more details on the api docs + +2010-12-09 12:22:26 +0200 Stefan Kost + + * gst/camerabin2/gstbasecamerasrc.h: + basecamerasrc: use the enum type for mode + +2010-12-09 12:21:16 +0200 Stefan Kost + + * gst/camerabin2/gstbasecamerasrc.c: + basecamerasrc: comment cleanups + +2010-12-22 21:44:47 +0000 Tim-Philipp Müller + + * gst/mpeg4videoparse/mpeg4videoparse.c: + mpeg4videoparse: ensure buffer metadata is writable before modifying it + https://bugzilla.gnome.org/show_bug.cgi?id=637824 + +2010-12-22 18:13:04 +0100 Edward Hervey + + * gst/id3tag/gstid3mux.c: + id3mux: Set to GST_RANK_PRIMARY + We want it to take precedence over any other id3 formatter. + +2010-12-21 18:01:28 +0100 Sebastian Dröge + + * gst/autoconvert/gstautoconvert.c: + autoconvert: Fix some more leaks and reorganize unref code + +2010-12-20 15:33:28 +0100 benjamin gaignard + + * gst/autoconvert/gstautoconvert.c: + autoconvert: Avoid some leaks in autoconvert + unref sink and src pad after gst_pad_by_direction calls unref + element if gst_auto_convert_activate_element failed. + See bug #637553. + +2010-12-21 17:03:43 +0100 Sebastian Dröge + + * tests/check/elements/asfmux.c: + asfmux: Fix buffer leak in the unit test + +2010-12-20 07:19:04 -0800 Saleem Abdulrasool + + * tests/examples/camerabin/gst-camera.c: + camerabin: fix for latest GTK+ API changes + +2010-12-20 17:47:29 +0100 Edward Hervey + + * common: + Automatic update of common submodule + From 169462a to 46445ad + +2010-12-20 11:06:52 -0300 Thiago Santos + + * tests/check/elements/camerabin.c: + camerabin: Fix caps leaks + Fix some caps leaks on unit tests + +2010-12-20 09:37:22 -0300 Thiago Santos + + * tests/check/elements/jifmux.c: + jifmux: Fix leaks on check test + Fix leaks in jifmux check test + +2010-12-20 13:51:03 +0200 Stefan Kost + + * gst-libs/gst/interfaces/photography.c: + photography: use a flags type instead of the uint + Also use 0 as default and let the implementation set something that they support. + +2010-12-20 11:14:49 +0200 Hu Gang + + * gst-libs/gst/interfaces/photography.c: + * gst-libs/gst/interfaces/photography.h: + photography: add missing property and cabability flag for noise reduction + +2010-12-19 17:23:24 +0530 Olivier Crête + + * tests/check/elements/autoconvert.c: + tests: Fix leak in autoconvert test + +2010-12-19 17:16:10 +0530 Olivier Crête + + * gst/autoconvert/gstautoconvert.c: + autoconvert: Use gst_caps_can_intersect() + +2010-12-19 12:53:34 +0100 Sebastian Dröge + + * gst/qtmux/gstqtmux.c: + qtmux: Free AtomInfo structs + +2010-12-19 12:50:30 +0100 Sebastian Dröge + + * gst/qtmux/gstqtmux.c: + qtmux: Free tag string after use + +2010-12-19 12:12:25 +0100 Sebastian Dröge + + * tests/check/pipelines/tagschecking.c: + tagschecking: Fix some more memory leaks + +2010-12-19 12:12:12 +0100 Sebastian Dröge + + * tests/check/elements/imagecapturebin.c: + imagecapturebin: Don't leak message in the unit test + +2010-12-19 12:09:41 +0100 Sebastian Dröge + + * gst/camerabin2/gstimagecapturebin.c: + imagecapturebin: Don't leak pad and sink + +2010-12-19 12:05:11 +0100 Sebastian Dröge + + * gst/camerabin2/gstimagecapturebin.c: + imagecapturebin: Don't leak pad template created from static pad template + +2010-12-19 12:03:03 +0100 Sebastian Dröge + + * gst/camerabin2/gstimagecapturebin.c: + imagecapturebin: Don't leak location string + +2010-12-19 12:00:25 +0100 Sebastian Dröge + + * gst/jpegformat/gstjifmux.c: + jifmux: Don't leak taglist + +2010-12-19 11:38:03 +0100 Sebastian Dröge + + * gst/autoconvert/gstautovideoconvert.c: + autovideoconvert: Don't leak pad templates created from static pad templates + +2010-12-19 11:20:25 +0100 Sebastian Dröge + + * gst/autoconvert/gstautovideoconvert.c: + autovideoconvert: Add autoconvert child before chaining up to parent state change function + ...and remove/unlink autoconvert child when going back to NULL. + +2010-12-19 11:19:38 +0100 Sebastian Dröge + + * tests/check/Makefile.am: + states: Ignore more vdpau elements in the generic states test + +2010-12-19 11:17:47 +0100 Sebastian Dröge + + * Makefile.am: + * tests/check/Makefile.am: + * tests/check/elements/.gitignore: + * tests/check/elements/autocolorspace.c: + * tests/check/elements/autovideoconvert.c: + autovideoconvert: Rename and adjust unit test too + +2010-12-18 12:48:42 -0800 Leo Singer + + * sys/applemedia/miovideosrc.c: + * sys/applemedia/qtkitvideosrc.m: + applemedia: fix compiler warning: redundant declaration of 'parent_class' + GST_BOILERPLATE_FULL declares parent_class as well. + https://bugzilla.gnome.org/show_bug.cgi?id=637532 + +2010-12-17 19:41:25 +0200 Lasse Laukkanen + + * gst/qtmux/gstqtmux.c: + qtmux: allow zero duration tracks + +2010-12-16 15:31:23 +0000 Tim-Philipp Müller + + * gst/dvbsuboverlay/dvb-sub.c: + * gst/dvbsuboverlay/dvb-sub.h: + * gst/dvbsuboverlay/gstdvbsuboverlay.c: + dvbsuboverlay: use GST_LOG etc. for logging + The dvbsub routines were originally designed as a mini lib with a + log callback (which from the looks of it in our case would always + be called and always assemble the string even with debug output + disabled). Some of these debug statements can probably be removed + or cleaned up some more. + +2010-12-16 00:19:13 +0000 Tim-Philipp Müller + + * gst/dvbsuboverlay/ffmpeg-colorspace.h: + dvbsuboverlay: remove some unused defines + +2010-12-16 00:13:18 +0000 Tim-Philipp Müller + + * gst/dvbsuboverlay/gstdvbsuboverlay.c: + dvbsuboverlay: fix atomic access + +2010-12-16 15:33:45 +0000 Janne Grunau + + * gst/dvbsuboverlay/gstdvbsuboverlay.c: + dvbsuboverlay: fix rendering artefacts + Initialize source x position for odd height special case. + +2010-12-16 11:29:07 +0100 Edward Hervey + + * gst/dvbsuboverlay/gstdvbsuboverlay.c: + dvbsuboverlay: The enable property is a boolean and not an integer + +2010-12-16 09:56:00 +0100 Sebastian Dröge + + * gst/autoconvert/Makefile.am: + * gst/autoconvert/gstautocolorspace.c: + * gst/autoconvert/gstautocolorspace.h: + * gst/autoconvert/gstautovideoconvert.c: + * gst/autoconvert/gstautovideoconvert.h: + * gst/autoconvert/plugin.c: + autoconvert: Rename autocolorspace to autovideoconvert + This doesn't just convert between color spaces. + +2010-12-15 12:45:38 -0800 David Schleef + + * tools/Makefile.am: + * tools/base.c: + * tools/element-maker: + * tools/element-templates/audiofilter: + * tools/element-templates/audiosink: + * tools/element-templates/audiosrc: + * tools/element-templates/base: + * tools/element-templates/baseaudiosink: + * tools/element-templates/baseaudiosrc: + * tools/element-templates/basertpdepayload: + * tools/element-templates/basertppayload: + * tools/element-templates/basesink: + * tools/element-templates/basesrc: + * tools/element-templates/basetransform: + * tools/element-templates/cddabasesrc: + * tools/element-templates/element: + * tools/element-templates/gobject: + * tools/element-templates/pushsrc: + * tools/element-templates/sinkpad: + * tools/element-templates/sinkpad-simple: + * tools/element-templates/srcpad: + * tools/element-templates/srcpad-simple: + * tools/element-templates/tagdemux: + * tools/element-templates/videosink: + * tools/gobject.c: + * tools/gst-element-maker: + * tools/gstaudiofilter.c: + * tools/gstaudiosink.c: + * tools/gstaudiosrc.c: + * tools/gstbaseaudiosink.c: + * tools/gstbaseaudiosrc.c: + * tools/gstbasertpdepayload.c: + * tools/gstbasertppayload.c: + * tools/gstbasesink.c: + * tools/gstbasesrc.c: + * tools/gstbasetransform.c: + * tools/gstcddabasesrc.c: + * tools/gstelement.c: + * tools/gstpushsrc.c: + * tools/gsttagdemux.c: + * tools/gstvideosink.c: + * tools/sinkpad-simple.c: + * tools/sinkpad.c: + * tools/srcpad-simple.c: + * tools/srcpad.c: + element-maker: Clean up directory + +2010-12-15 21:28:06 +0100 Benjamin Gaignard + + * gst/bayer/gstbayer2rgb.c: + bayer2rgb: Add framerate to the sink caps + Fixes bug #637224. + +2010-12-15 21:19:55 +0100 Benjamin Gaignard + + * tests/check/Makefile.am: + * tests/check/elements/autocolorspace.c: + autocolorspace: Add unit test + +2010-12-15 21:14:38 +0100 Benjamin Gaignard + + * gst/autoconvert/Makefile.am: + * gst/autoconvert/gstautocolorspace.c: + * gst/autoconvert/gstautocolorspace.h: + * gst/autoconvert/gstautoconvert.c: + * gst/autoconvert/plugin.c: + autocolorspace: Add autoconvert based video format convert element + Fixes bug #636106. + +2010-12-15 21:11:29 +0100 Sebastian Dröge + + * gst/dvbsuboverlay/gstdvbsuboverlay.c: + dvbsuboverlay: Rename DVB subtitling media type to subpicture/x-dvb + +2010-12-15 21:11:11 +0100 Sebastian Dröge + + * gst/mpegdemux/gstmpegtsdemux.c: + mpegtsdemux: Rename DVB subtitling media type to subpicture/x-dvb + +2010-12-15 20:54:35 +0100 Sebastian Dröge + + * gst/dvbsuboverlay/gstdvbsuboverlay.c: + dvbsuboverlay: Don't draw anything on the video if the enable property is set to FALSE + +2010-12-15 20:53:21 +0100 Sebastian Dröge + + * gst/dvbsuboverlay/gstdvbsuboverlay.c: + dvbsuboverlay: Add #defines for the property default values + +2010-12-15 20:51:12 +0100 Sebastian Dröge + + * gst/dvbsuboverlay/gstdvbsuboverlay.c: + dvbsuboverlay: Use g_atomic_int_get() for reading the max_page_timeout field + +2010-12-15 20:49:57 +0100 Sebastian Dröge + + * gst/mpegdemux/gstmpegtsdemux.c: + mpegtsdemux: Mark array static const and use G_N_ELEMENTS instead of sizeof + +2010-12-15 14:39:56 +0100 Janne Grunau + + * gst/mpegdemux/gstmpegtsdemux.c: + mpegtsdemux: add DESC_DVB_SUBTITLING descriptor for language parsing + +2010-12-15 14:23:58 +0100 Janne Grunau + + * gst/mpegdemux/gstmpegtsdemux.c: + mpegtsdemux: enable gather_pes only for DVB subtitle private streams + +2010-12-14 14:34:56 +0100 Janne Grunau + + * gst/dvbsuboverlay/gstdvbsuboverlay.c: + dvbsuboverlay: use atomic instructions to set/get enable property + +2010-12-14 14:28:45 +0100 Janne Grunau + + * gst/dvbsuboverlay/gstdvbsuboverlay.c: + * gst/dvbsuboverlay/gstdvbsuboverlay.h: + dvbsuboverlay: add property to limit page_time_out to a setable maximum + +2010-12-14 11:11:08 +0100 Janne Grunau + + * gst/dvbsuboverlay/gstdvbsuboverlay.c: + dvbsuboverlay: implement display definition segment subtitle windows + simplifies subtitle scaling in blit_i420() + +2010-12-11 17:25:29 +0100 Janne Grunau + + * gst/dvbsuboverlay/gstdvbsuboverlay.c: + dvbsuboverlay: scale subtitles according to the display size + Display size is either transmitted in the display definition segment or + implicitly defined to 720x576. The subtitle window information also present in + the display definition segment is not yet used. + +2010-12-11 17:10:25 +0100 Janne Grunau + + * gst/dvbsuboverlay/dvb-sub.c: + * gst/dvbsuboverlay/dvb-sub.h: + dvbsuboverlay: implement display definition segment parsing + +2010-12-10 12:27:54 +0100 Janne Grunau + + * gst/dvbsuboverlay/gstdvbsuboverlay.c: + dvbsuboverlay: fix luma stride for scaled subtitles (display width != width) + +2010-12-15 16:48:15 +0100 Edward Hervey + + * ext/rsvg/gstrsvgoverlay.c: + rsvgoverlay: Don't set uint on an int property + +2010-12-15 14:56:19 +0200 Stefan Kost + + * common: + Automatic update of common submodule + From 20742ae to 169462a + +2010-12-14 19:03:09 -0800 David Schleef + + * tools/Makefile.am: + * tools/element-maker: + * tools/gstaudiofilter.c: + * tools/gstaudiosink.c: + * tools/gstaudiosrc.c: + * tools/gstbaseaudiosink.c: + * tools/gstbaseaudiosrc.c: + * tools/gstbasertpdepayload.c: + * tools/gstbasertppayload.c: + * tools/gstbasesink.c: + * tools/gstbasesrc.c: + * tools/gstbasetransform.c: + * tools/gstcddabasesrc.c: + * tools/gstelement.c: + * tools/gstpushsrc.c: + * tools/gsttagdemux.c: + * tools/gstvideosink.c: + * tools/sinkpad-simple.c: + * tools/sinkpad.c: + * tools/srcpad-simple.c: + * tools/srcpad.c: + element-maker: improve generation of several classes + Better creation of pads, test and fix many other classes. Most + classes work now, although might not create functional elements. + +2010-12-13 23:32:30 -0800 David Schleef + + * configure.ac: + * gst/y4m/Makefile.am: + * gst/y4m/gsty4mdec.c: + * gst/y4m/gsty4mdec.h: + y4mdec: Add y4mdec + Feel the y4m love. It seeks. It works in pitivi. + +2010-12-13 23:15:05 +0000 Francis Rammeloo + + * sys/winscreencap/gstgdiscreencapsrc.c: + gdiscreencapsrc: fix memory leak + Structure members of ICONINFO struct filled by GetIconInfo() must + be deleted when no longer needed according to the API reference. + https://bugzilla.gnome.org/show_bug.cgi?id=611428 + +2010-12-13 16:23:37 +0100 Mark Nauwelaerts + + * gst/jpegformat/gstjpegparse.c: + jpegparse: avoid leaking tag event + +2010-12-13 15:17:29 +0100 Mark Nauwelaerts + + * gst/audioparsers/gstac3parse.c: + ac3parse: relax bsid checking + ... to the widest possible spec interpretation. + Fixes #637062. + +2010-12-13 16:23:45 +0200 Stefan Kost + + * common: + Automatic update of common submodule + From 011bcc8 to 20742ae + +2010-12-12 23:34:02 +0000 Matthew Ife + + * gst/librfb/rfbdecoder.c: + * gst/librfb/rfbdecoder.h: + rfbsrc: fail more gracefully if source gets disconnected or geometry changes + Don't get caught in an infinite loop if the source gets disconnected and also + support gracefully failing upon detecting the frame geometry has increased + (rather than segfaulting). + https://bugzilla.gnome.org/show_bug.cgi?id=635397 + +2010-12-12 22:13:13 +0100 Mark Nauwelaerts + + * gst/jpegformat/gstjpegparse.c: + jpegparse: avoid leaking converted comment string + +2010-12-12 12:01:38 +0100 Sebastian Dröge + + * gst/videomeasure/gstvideomeasure_ssim.c: + ssim: Set classification to Filter/Analyzer/Video instead of Filter/Converter/Video + Fixes bug #636109. + +2010-12-12 02:24:00 +1100 Jan Schmidt + + * gst/gaudieffects/burn-example.py: + * gst/gaudieffects/gstburn.c: + gaudieffects: Avoid divide by 0 in burn element + +2010-12-12 02:16:49 +1100 Jan Schmidt + + * ext/resindvd/resindvdsrc.c: + * ext/resindvd/resindvdsrc.h: + resindvd: Defer pushing tag updates until streaming. + Push tag/title info updates in the streaming thread, avoiding + spurious losses of the downstream events when flushing. + See: https://bugzilla.gnome.org/show_bug.cgi?id=594222 + +2010-11-16 17:18:33 +1100 Jan Schmidt + + * ext/resindvd/resindvdsrc.c: + resindvd: Attempt to use glib language setting for DVD menus/audio + +2010-11-16 17:09:06 +1100 Jan Schmidt + + * ext/resindvd/resindvdsrc.c: + resindvd: Fix silly typo in button state tracking. + +2010-12-10 00:58:58 +0100 Ole André Vadla Ravnås + + * sys/applemedia/vtdec.c: + * sys/applemedia/vtenc.c: + applemedia: only enqueue buffers in the VideoToolbox callbacks + These callbacks may fire from any thread, hence we should only enqueue + buffers and let the streaming thread take care of the rest as soon as + the blocking encode or decode operation has finished. + +2010-11-19 15:53:55 +0100 Ole André Vadla Ravnås + + * sys/applemedia/coremediactx.h: + * sys/applemedia/cvapi.c: + * sys/applemedia/dynapi-internal.h: + * sys/applemedia/dynapi.c: + * sys/applemedia/dynapi.h: + applemedia: bring back Leopard compatibility + At least as far as miovideosrc is concerned. Turns out that CoreVideo's + CVPixelBufferGetIOSurface is not present in Leopard's version of CoreVideo. + We solve this by making it possible for symbols to be marked as optional. + +2010-11-29 13:47:11 +0100 Christian Berentsen + + * sys/winks/ksvideohelpers.c: + winks: fix framerate fraction range mapping + Min and max may be slightly different but compress to the same fraction. + +2010-12-09 18:06:38 +0100 Wim Taymans + + * ext/jp2k/gstjasperdec.c: + jasperdec: don't fail hard on decoding error + don't post an error and return GST_FLOW_ERROR on a simple decoding error. We can + just resume and continue decoding the next image. + +2010-12-09 11:54:17 +0100 Alessandro Decina + + * sys/applemedia/qtkitvideosrc.m: + qtkitvideosrc: reset the queue condition to NO_FRAMES in unlockStop. + Fixes a segfault in create: when going PLAYING -> PAUSED -> PLAYING. + +2010-12-09 11:04:19 +0100 Alessandro Decina + + * sys/applemedia/qtkitvideosrc.m: + qtkitvideosrc: run the mainRunLoop for a while if not running. + QTCaptureSession::addInput and QTCaptureSession::addOutput call + NSObject::performSelectorOnMainThread internally so they need the mainRunLoop to + run at least for a while to complete. + +2010-12-07 19:40:28 -0300 Thiago Santos + + * gst/camerabin2/gstbasecamerasrc.c: + * gst/camerabin2/gstbasecamerasrc.h: + * gst/camerabin2/gstv4l2camerasrc.c: + * gst/camerabin2/gstv4l2camerasrc.h: + basecamerasrc: Remove ghostpads + Remove ghost pads from basecamerasrc. Different implementations + of camera sources might not use ghostpads and use default pads. + +2010-12-07 19:12:40 -0300 Thiago Santos + + * gst/camerabin2/gstbasecamerasrc.c: + * gst/camerabin2/gstbasecamerasrc.h: + * gst/camerabin2/gstv4l2camerasrc.c: + basecamerasrc: Removing ununsed methods + Remove one unused method _finish_image_capture() + +2010-12-06 11:05:17 -0300 Thiago Santos + + * tests/check/Makefile.am: + * tests/examples/Makefile.am: + camerabin2: Only run tests if experimental is enabled + Only run camerabin2 tests and build examples if experimental + plugins are enabled + +2010-12-06 10:06:37 -0300 Thiago Santos + + * gst/camerabin2/gstbasecamerasrc.c: + * gst/camerabin2/gstv4l2camerasrc.c: + camerabin2: Cleanup + Removing commented code + +2010-12-05 11:18:09 -0300 Thiago Santos + + * gst/camerabin2/gstbasecamerasrc.c: + * gst/camerabin2/gstbasecamerasrc.h: + * gst/camerabin2/gstv4l2camerasrc.c: + * gst/camerabin2/gstv4l2camerasrc.h: + basecamerasrc: Move start/stop capture signals to basecamerasrc + Move start/stop signals and ready-for-capture to basecamerasrc + as this should be present on all camera sources + +2010-12-04 10:15:34 -0300 Thiago Santos + + * gst/camerabin2/gstbasecamerasrc.c: + * gst/camerabin2/gstbasecamerasrc.h: + * gst/camerabin2/gstv4l2camerasrc.c: + * gst/camerabin2/gstv4l2camerasrc.h: + basecamerasrc: Add mode property + Move mode property from v4l2camerasrc to basecamerasrc, as all + camera sources should handle it. + +2010-12-04 00:27:17 -0300 Thiago Santos + + * gst/camerabin2/gstcamerabin2.c: + * gst/camerabin2/gstcamerabin2.h: + camerabin2: Reset all elements on video recording branch before capture + We need to reset the elements from the video recording branch, including + the queue and capsfilter in order to clear the eos state and activate + the pads. + This makes it possible to record multiple videos with camerabin2 in a + sequence, otherwise the source would get a unexpected return and + push EOS, stopping the whole pipeline. + +2010-12-03 12:13:07 -0300 Thiago Santos + + * tests/check/elements/camerabin2.c: + camerabin2: Fix tests capture location creation + Fixes capture location creation to use multifilesink location + like strings. E.g. using capture_%d instead of capture_0 to let + camerabin2 handle the %d replacing + +2010-12-03 12:12:32 -0300 Thiago Santos + + * gst/camerabin2/gstcamerabin2.c: + * gst/camerabin2/gstv4l2camerasrc.c: + camerabin2: More debug logs + Sprinkle some more debugging logs + +2010-12-03 12:11:59 -0300 Thiago Santos + + * tests/examples/camerabin2/gst-camera2.c: + examples: camerabin2: Print more info + Add some printing for error/eos cases. + +2010-12-02 03:44:37 -0300 Thiago Santos + + * gst/camerabin2/gstcamerabin2.c: + * gst/camerabin2/gstvideorecordingbin.c: + camerabin2: Various fixes + As video recording bin's state is locked, we should always + remember of setting it to NULL when camerabin2 goes to NULL + Be more careful when using elements that might not + have been created yet + And do not set location property recursively on videorecordingbin + +2010-12-02 03:08:52 -0300 Thiago Santos + + * tests/check/Makefile.am: + * tests/check/elements/camerabin2.c: + camerabin2: Adding tests for camerabin2 + Adds some basic tests for camerabin2 + +2010-12-02 02:21:49 -0300 Thiago Santos + + * tests/check/Makefile.am: + * tests/check/elements/.gitignore: + * tests/check/elements/imagecapturebin.c: + * tests/check/elements/videorecordingbin.c: + tests: camerabin2: adds tests for elements + Adds basic tests for both imagecapturebin and for + videorecordingbin elements + +2010-12-02 01:33:19 -0300 Thiago Santos + + * gst/camerabin2/gstviewfinderbin.c: + viewfinderbin: Improve elements creation + Be more careful with cleanup of elements. Also add some logs and + improve docs a little. + +2010-12-02 00:19:05 -0300 Thiago Santos + + * gst/camerabin2/gstcamerabin-enum.c: + * gst/camerabin2/gstcamerabin-enum.h: + camerabin2: remove unused code + General cleanup, removing unused bits + +2010-11-30 20:13:27 -0300 Thiago Santos + + * configure.ac: + * gst/camerabin2/gstcamerabin2.c: + * gst/camerabin2/gstcamerabin2.h: + * gst/camerabin2/gstimagecapturebin.c: + * gst/camerabin2/gstimagecapturebin.h: + * gst/camerabin2/gstvideorecordingbin.c: + * gst/camerabin2/gstvideorecordingbin.h: + camerabin2: adds location property + Adds a location property to enable applications to select + the captured files names. Locations are handled just like + multifilesink ones + Also disables -Wformat-nonliteral to allow to use non-literals + on g_strdup_printf on camerabin and generate a sequence of + locations for captures. + +2010-11-30 20:15:47 -0300 Thiago Santos + + * gst/camerabin2/gstcamerabin2.c: + camerabin2: Fix set/get property function names + Add more consistency to the function names by using + gst_camera_bin as the other functions. + +2010-11-30 18:19:20 -0300 Thiago Santos + + * gst/camerabin2/gstcamerabin2.c: + * gst/camerabin2/gstcamerabin2.h: + camerabin2: Handle vidbin state change individually + Keep vidbin state locked to avoid it going to playing without + being used and leaving an empty file created. + Check the docs on the code for details on the handling. + +2010-11-30 11:40:18 -0300 Thiago Santos + + * configure.ac: + * gst/camerabin2/gstcamerabin2.c: + camerabin2: Keep it under --enable-experimental + camerabin2 is still under heavy development, activate it only if + the --enable-experimental flag is on. + Also add a note to the docs. + +2010-11-30 11:06:33 -0300 Thiago Santos + + * gst/camerabin2/gstcamerabin-enum.h: + * gst/camerabin2/gstv4l2camerasrc.c: + v4l2camerasrc: Add ready-for-capture property + Adds property that informs if v4l2camerasrc is available + for starting a new capture. + It is useful for applications to know (via deep-notify) when the + property changes and a new capture is possible. Note, however, that + starting a new capture from the notify callback will cause a deadlock. + +2010-11-30 09:28:50 -0300 Thiago Santos + + * gst/camerabin2/gstcamerabin-enum.c: + * gst/camerabin2/gstcamerabin-enum.h: + * gst/camerabin2/gstcamerabin2.c: + * gst/camerabin2/gstcamerabin2.h: + * gst/camerabin2/gstv4l2camerasrc.c: + * gst/camerabin2/gstv4l2camerasrc.h: + camerabin2: Update v4l2camerasrc to use start/stop signals + Removes the old logic for v4l2camerasrc that used the mode + property switching to start/stop captures to make it identical + to camerabin2 behavior and to allow the future addition of + pausing a video recording. + This also removes the MODE_PREVIEW as it became useless. + +2010-11-29 18:53:34 -0300 Thiago Santos + + * gst/camerabin2/gstcamerabin2.c: + * gst/camerabin2/gstcamerabin2.h: + camerabin2: Cleanup capturing flag + Cleanup capturing flag when the source switches back to the + viewfinder mode + +2010-11-29 18:24:35 -0300 Thiago Santos + + * gst/camerabin2/gstv4l2camerasrc.h: + v4l2camerasrc: Remove unnecessary padding + +2010-11-29 15:49:26 -0300 Thiago Santos + + * gst/camerabin2/gstv4l2camerasrc.c: + * gst/camerabin2/gstv4l2camerasrc.h: + v4l2camerasrc: Implement video capture + Implements video capture on v4l2camerasrc by using the mode property, + when mode is set to video, the pad probe pushes a new segment + and starts pushing buffers on the pad, when it the property is + sent back to preview, the pad probe pushes an EOS and stops + pushing buffers. + This is controlled by a Recording State variable, that is protected + by the GST_OBJECT_LOCK. I don't think locking for every buffer is + nice, so we could find an alternative lockless way here. + +2010-11-29 12:57:21 -0300 Thiago Santos + + * gst/camerabin2/gstv4l2camerasrc.c: + v4l2camerasrc: Fix image capture + Once a image is captured, v4l2camerasrc should return to the + preview mode and stop capturing. + +2010-11-29 11:31:26 -0300 Thiago Santos + + * gst/camerabin2/gstcamerabin-enum.c: + * gst/camerabin2/gstcamerabin2.c: + camerabin2: Keep mode definition at -enum file + Use 'mode' enum definition from gstcamerabin-enum file to avoid + conflicts between v4l2camerasrc and gstcamerabin2 modes. + For now there is a MODE_PREVIEW there that is only used on the + camerasrc, not sure if we are keeping it at the future, but for + now this works. + +2010-11-29 10:46:38 -0300 Thiago Santos + + * gst/camerabin2/gstv4l2camerasrc.c: + v4l2camerasrc: Adds mode property + Adds mode property to v4l2camerasrc + +2010-11-29 10:45:30 -0300 Thiago Santos + + * gst/camerabin2/camerabingeneral.c: + * gst/camerabin2/camerabingeneral.h: + * gst/camerabin2/gstcamerabin2.c: + * gst/camerabin2/gstv4l2camerasrc.c: + camerabin2: Adding debug categories + Adding debug categories to v4l2camerasrc and camerabin2, also + removing generic category from camerabingeneral. + +2010-11-26 23:55:12 -0300 Thiago Santos + + * configure.ac: + * tests/examples/Makefile.am: + * tests/examples/camerabin2/.gitignore: + * tests/examples/camerabin2/Makefile.am: + * tests/examples/camerabin2/gst-camera2.c: + * tests/examples/camerabin2/gst-camera2.h: + * tests/examples/camerabin2/gst-camera2.ui: + examples: Adds camerabin2 example + Adds gtk camerabin2 example app + +2010-11-26 17:24:58 -0300 Thiago Santos + + * gst/camerabin2/gstcamerabin2.c: + * gst/camerabin2/gstcamerabin2.h: + camerabin2: Adding basic property and signals + Adds mode property to camerabin2, allowing users to + select between video and stills capture. Also adds + start/stop capture actions to trigger and stop + capturing + +2010-11-26 15:55:39 -0300 Thiago Santos + + * gst/camerabin2/gstimagecapturebin.c: + * gst/camerabin2/gstvideorecordingbin.c: + camerabin2: Set filesink's async to FALSE + In order to preroll, camerabin2 should have its filesinks in + the imagecapturebin and videorecordingbin with async=FALSE. + +2010-11-26 14:51:30 -0300 Thiago Santos + + * gst/camerabin2/gstcamerabin2.c: + camerabin2: Adding basic elements + Instantiating and linking basic elements on camerabin2 + so it at least shows the viewfinder when running. + +2010-11-26 10:14:46 -0300 Thiago Santos + + * gst/camerabin2/Makefile.am: + * gst/camerabin2/gstcamerabin2.c: + * gst/camerabin2/gstcamerabin2.h: + * gst/camerabin2/gstplugin.c: + camerabin2: Adds a stub element for camerabin2 + Adds camerabin2 element, it is now a pile of stubs. + +2010-11-25 22:05:39 -0300 Thiago Santos + + * gst/camerabin2/gstv4l2camerasrc.c: + camerabin2: v4l2camerasrc: Remove platform specific code + Remove platform specific code + +2010-11-25 21:49:47 -0300 Thiago Santos + + * gst/camerabin2/gstbasecamerasrc.c: + * gst/camerabin2/gstv4l2camerasrc.c: + camerabin2: Removing uneeded properties + Removing uneeded and unregistered properties. + +2010-11-25 20:55:36 -0300 Thiago Santos + + * gst/camerabin2/gstv4l2camerasrc.c: + camerabin2: v4l2camerasrc: Fix property warning + Avoid setting a property that doesn't exist. + +2010-11-25 20:53:04 -0300 Thiago Santos + + * gst/camerabin2/gstv4l2camerasrc.c: + * gst/camerabin2/gstv4l2camerasrc.h: + camerabin2: v4l2camerasrc: Remove unused variable + Removed unused leftover variable + +2010-11-25 14:57:13 -0300 Thiago Santos + + * gst/camerabin2/Makefile.am: + * gst/camerabin2/gstplugin.c: + * gst/camerabin2/gstvideorecordingbin.c: + * gst/camerabin2/gstvideorecordingbin.h: + camerabin2: Adds video recording bin + Adds an bin that is responsible for encoding and saving video + streams to files. + For now it is simply a ffmpegcolorspace ! theoraenc ! oggmux ! + filesink bin. + Still uncapable of recording audio. + +2010-11-25 13:00:50 -0300 Thiago Santos + + * gst/camerabin2/Makefile.am: + * gst/camerabin2/camerabingeneral.c: + * gst/camerabin2/camerabingeneral.h: + * gst/camerabin2/gstbasecamerasrc.c: + * gst/camerabin2/gstbasecamerasrc.h: + * gst/camerabin2/gstcamerabin-enum.c: + * gst/camerabin2/gstcamerabin-enum.h: + * gst/camerabin2/gstplugin.c: + * gst/camerabin2/gstv4l2camerasrc.c: + * gst/camerabin2/gstv4l2camerasrc.h: + camerabin2: Adding v4l2camerasrc from robclark's branch + Adds 3-pad v4l2 camera source from Rob Clark's camerabin + branch on http://gitorious.org/robclark-gstreamer/gst-plugins-bad + +2010-11-24 20:31:33 -0300 Thiago Santos + + * gst/camerabin2/Makefile.am: + * gst/camerabin2/gstimagecapturebin.c: + * gst/camerabin2/gstimagecapturebin.h: + * gst/camerabin2/gstplugin.c: + camerabin2: Adds new imagecapturebin + Adds an bin that is responsible for image captures. + It is a simple ffmpegcolorspace ! jpegenc ! jifmux ! multifilesink + for now. + +2010-11-24 20:15:38 -0300 Thiago Santos + + * gst/camerabin2/Makefile.am: + * gst/camerabin2/gstplugin.c: + * gst/camerabin2/gstviewfinderbin.c: + * gst/camerabin2/gstviewfinderbin.h: + camerabin2: Move plugin init to a separate file + Moves plugin init to gstplugin.c to allow multiple + elements to register themselves. + +2010-11-24 17:28:57 -0300 Thiago Santos + + * configure.ac: + * gst/camerabin2/Makefile.am: + * gst/camerabin2/gstviewfinderbin.c: + * gst/camerabin2/gstviewfinderbin.h: + camerabin2: viewfinderbin: Adds viewfinderbin element + Adds viewfinder bin element, one of the modules of camerabin2 + that is responsible for displaying the video from the camera. + For now it is only a bin with ffmpegcolorspace ! videoscale ! + autovideosink + +2010-12-08 19:36:48 +0100 Alessandro Decina + + * gst/dvbsuboverlay/gstdvbsuboverlay.c: + dvbsuboverlay: fix compiler warnings on OSX. + +2010-11-24 12:22:01 +0200 Stefan Kost + + * tests/icles/output-selector-test.c: + output-selector-test: don't hardcode videosinks and use more colorspace conv. + Use autovideosink instead of hardcoded sinks. Use an additional colorspace + converter between videotestsrc and timeoverlay. + +2010-12-08 15:18:32 +0000 Tim-Philipp Müller + + * configure.ac: + configure: require released versions of core/base instead of old git + +2010-12-07 15:44:00 +0100 Mark Nauwelaerts + + * gst/mpeg4videoparse/mpeg4videoparse.c: + mpeg4videoparse: re-use cleanup() in finalize() + ... and also favor finalize() rather than dispose(). + +2010-11-18 13:39:23 +0530 Arun Raghavan + + * gst/mpeg4videoparse/mpeg4videoparse.c: + * gst/mpeg4videoparse/mpeg4videoparse.h: + mpeg4videoparse: Set srcpad caps before forwarding newsegment + This holds all newsegement and most other events till there is enough + data to set srcpad caps, so that the downstream link is properly + negotiated before data starts flowing. + https://bugzilla.gnome.org/show_bug.cgi?id=635204 + +2010-11-18 23:29:51 +0530 Arun Raghavan + + * gst/mpeg4videoparse/mpeg4videoparse.c: + * gst/mpeg4videoparse/mpeg4videoparse.h: + mpeg4videoparse: Use sinkpad caps as base for srcpad caps + This way, we don't lose additional fields that come from upstream (like + profile/level for now). + https://bugzilla.gnome.org/show_bug.cgi?id=635202 + +2010-12-07 15:20:29 +0100 Mark Nauwelaerts + + * gst/mpeg4videoparse/mpeg4videoparse.c: + mpeg4videoparse: minor fix to error handling + We weren't handling unparseable codec_data in some cases. + https://bugzilla.gnome.org/show_bug.cgi?id=635202 + +2010-12-07 17:17:44 +0100 Sebastian Dröge + + * gst/dvbsuboverlay/gstdvbsuboverlay.c: + dvbsuboverlay: Implement nearest neighbour scaling for the subpictures + This becomes necessary when SDTV subtitles are used for HDTV videos. + +2010-12-07 14:55:28 +0100 Mark Nauwelaerts + + * gst/h264parse/gsth264parse.c: + h264parse: align code with comment + +2010-12-07 14:55:15 +0100 Mark Nauwelaerts + + * gst/h264parse/gsth264parse.c: + h264parse: re-use reset() in finalize() + +2010-11-17 19:16:12 +0530 Arun Raghavan + + * gst/h264parse/gsth264parse.c: + * gst/h264parse/gsth264parse.h: + h264parse: Set srcpad caps before forwarding newsegment + This holds all newsegement and most other events till there is enough + data to set srcpad caps, so that the downstream link is properly + negotiated before data starts flowing. + https://bugzilla.gnome.org/show_bug.cgi?id=635205 + +2010-12-06 19:00:28 +0100 Mark Nauwelaerts + + * gst/jpegformat/gstjpegparse.c: + jpegparse: try to convert comment tag to UTF-8 + +2010-12-06 18:19:20 +0100 Mark Nauwelaerts + + * gst/jpegformat/gstjpegparse.c: + jpegparse: discard incomplete image + ... as determined when finding SOI next image before an EOI. + +2010-12-06 18:18:11 +0100 Mark Nauwelaerts + + * gst/jpegformat/gstjpegparse.c: + jpegparse: avoid infinite loop when resyncing + +2010-12-06 22:48:09 +0530 Arun Raghavan + + * gst/rawparse/gstaudioparse.c: + audioparse: Allow implicit channel map for 1-/2-channel audio + This makes sure we don't set an empty channel map array for 1-/2-channel + audio, causing an assert later on. + +2010-12-06 17:08:55 +0100 Sebastian Dröge + + * gst/dvbsuboverlay/gstdvbsuboverlay.c: + dvbsuboverlay: Revert some parts of last commit that shouldn't be committed + +2010-12-06 17:05:28 +0100 Sebastian Dröge + + * gst/dvbsuboverlay/gstdvbsuboverlay.c: + dvbsuboverlay: Really choose the latest possible subpictures + And not the first subpictures that are still valid according to the + page timeout. + +2010-12-06 16:44:11 +0100 Sebastian Dröge + + * gst/dvbsuboverlay/gstdvbsuboverlay.c: + dvbsuboverlay: Refactor blending function and take average of all chroma values + +2010-12-03 17:35:36 +0100 Sebastian Dröge + + * gst/dvbsuboverlay/gstdvbsuboverlay.c: + dvbsuboverlay: Improve selection of current to be displayed subpictures + Drop all subpictures that are too old anyway and clear the currently + displayed subpictures if num_rects==0 happens. + +2010-12-03 16:21:15 +0100 Sebastian Dröge + + * gst/dvbsuboverlay/gstdvbsuboverlay.c: + dvbsuboverlay: Implement clipping of video buffers + Also don't clip subpicture buffers, they have no duration and + clipping them doesn't make much sense here. + +2010-12-03 16:08:13 +0100 Sebastian Dröge + + * gst/dvbsuboverlay/gstdvbsuboverlay.c: + * gst/dvbsuboverlay/gstdvbsuboverlay.h: + dvbsuboverlay: Clean up locking some more + +2010-12-03 16:05:56 +0100 Sebastian Dröge + + * gst/dvbsuboverlay/gstdvbsuboverlay.c: + dvbsuboverlay: Flush subtitles and all internal state when needed + +2010-12-03 15:52:21 +0100 Sebastian Dröge + + * gst/dvbsuboverlay/gstdvbsuboverlay.c: + dvbsuboverlay: Set the global library log function exactly once + And don't use one of the possibly many renderer instances, this is only + calling for crashes. + +2010-12-03 15:46:40 +0100 Sebastian Dröge + + * gst/dvbsuboverlay/gstdvbsuboverlay.c: + * gst/dvbsuboverlay/gstdvbsuboverlay.h: + dvbsuboverlay: Remove lots of commented out and unused code and clean up locking + +2010-12-01 09:59:14 +0200 Mart Raudsepp + + * gst/dvbsuboverlay/gstdvbsuboverlay.c: + dvbsuboverlay: Fix more of the blending, so it looks quite good now + * libdvbsub gives us alpha channel already, not transparency level, so + don't do another "alpha = 255 - alpha", this is done by libdvbsub. + * Fix alpha channel handling in interpolation - assrender had an additional + 1bpp alpha bitmap as a possible mask, we don't. So don't use the palette + index array as alpha values; bug from quick code porting long ago to + changing pixel colors (assrender has a single pixel color for whole + regions or something, unlike dvbsub, which has indexed colors). + * Don't forget to reassign our YUV and other local pixel color variables + after shifting to work on the bottom part of a 2x2 subsample block, or + it's obviously very blocky. + Remaining issues in blending: + * Should probably be interpolating or doing something else useful with the + resulting U and V channels, so that most of the source pixel UV values would + actually be actually cared about, except for just one out of possibly four. + * Don't convert AYUV to ARGB in libdvbsub, and then back from ARGB to AYUV in + dvbsuboverlay for no reason + * Re-factor the whole thing to something more like textoverlay blending + * Related to that, perhaps cache the current spu in a good format for quick + blending on each frame, after which the more often called blending parts + might become more straightforward + +2010-12-01 07:26:03 +0200 Mart Raudsepp + + * gst/dvbsuboverlay/gstdvbsuboverlay.c: + dvbsuboverlay: Fix blending bug regarding color channel addressing. + libdvbsub gives us ARGB ordered pixels right now, not RGBA. + +2010-12-01 07:20:07 +0200 Mart Raudsepp + + * gst/dvbsuboverlay/gstdvbsuboverlay.c: + dvbsuboverlay: Do blending calls when appropriate + This gives us actually shown subtitles, however with bugs in the + current blitting code, resulting in very transparent subtitles. + +2010-12-01 07:06:35 +0200 Mart Raudsepp + + * gst/dvbsuboverlay/gstdvbsuboverlay.c: + dvbsuboverlay: Implement fallback page_time_out honoring + The spec has a page_time_out in the page composition segment to ensure + subtitles don't get stuck on screen for too much longer than intended, + when future page composition segments get lost on bad reception, or other + problems. Honor it in the gst plugin side. + +2010-12-01 06:01:15 +0200 Mart Raudsepp + + * gst/dvbsuboverlay/gstdvbsuboverlay.c: + * gst/dvbsuboverlay/gstdvbsuboverlay.h: + dvbsuboverlay: Implement subtitle queueing and syncing with video + Push incoming subtitle pages in a FIFO queue (pending_subtitles) + and dequeue the head when it's time to show it (when video running + time reaches the subtitle page running time). + Keep the subtitle page, that is supposed to be blended on top of video + currently, in a separate object variable (current_subtitle). As a + next step we can then pre-render current_subtitle to a better to blend + format. + +2010-12-01 05:49:22 +0200 Mart Raudsepp + + * gst/dvbsuboverlay/dvb-sub.c: + dvbsuboverlay: Make the new dvb_subtitles_free() accept NULL + Don't crash if dvb_subtitles_free(NULL) gets passed, like most other + *_free functions are happy with. + +2010-12-01 05:26:02 +0200 Mart Raudsepp + + * gst/dvbsuboverlay/dvb-sub.c: + * gst/dvbsuboverlay/dvb-sub.h: + * gst/dvbsuboverlay/gstdvbsuboverlay.c: + dvbsuboverlay: Pass page_time_out and pts with the DVBSubtitles structure + Eases holding onto the information in gst plugins side queue of + DVBSubtitles, so we won't need to create yet another temporary struct + to keep the pts and page_time_out too. + And this really logically belongs at the toplevel information set anyway + and in that struct... + +2010-12-01 04:28:02 +0200 Mart Raudsepp + + * gst/dvbsuboverlay/dvb-sub.c: + * gst/dvbsuboverlay/dvb-sub.h: + dvbsuboverlay: Make the libdvbsub callback handler responsible for memory cleanup + We want to allow queueing of raw region image data in the gst plugin side, + and keep the data around until we pop the item from the queue. So make + the callback handler responsible for memory cleanup, if one is installed. + +2010-11-30 04:45:54 +0200 Mart Raudsepp + + * gst/dvbsuboverlay/gstdvbsuboverlay.c: + dvbsuboverlay: Work with GstClockTime instead of PTS for subtitle timing + Abuse libdvbsub PTS tracking to just store our running time in it, to get + it back in the callbacks. As GStreamer does its own PTS handling behind our + back (especially for video), we should just sync with video per running time, + not try to do it with PTS, which doesn't seem well accessible for video chain. + We can later relabel dvb-sub.c pts naming convention if wanted, it's just + passing along guint64 values, which GstClockTime fortunately is too. + The current idea is to collect the regions returned by the callback into + a FIFO buffer and pop and pre-render the top one into a separate + quick-to-blend cached format, which is then appropriately blended in the + video chain until the next one on top of the stack reaches the video chains + running time (or the fallback timer hits). + +2010-11-30 03:56:32 +0200 Mart Raudsepp + + * gst/dvbsuboverlay/dvb-sub.c: + dvbsuboverlay: Add FIXME note about non-constant PTS for a display set handling. + +2010-11-30 03:47:46 +0200 Mart Raudsepp + + * gst/dvbsuboverlay/dvb-sub.c: + * gst/dvbsuboverlay/dvb-sub.h: + dvbsuboverlay: Remove dvb_sub_feed() API + GStreamer will only use dvb_sub_feed_with_pts, as it has its own PES filter + to do the header parsing. + +2010-11-29 20:55:30 +0000 Tim-Philipp Müller + + * gst/dvbsuboverlay/TODO: + dvbsuboverlay: more TODO + +2010-11-29 20:10:17 +0000 Mart Raudsepp + + * gst/mpegdemux/gstmpegtsdemux.c: + gstmpegtsdemux: add temporary **HACK** for dvb subs testing so dvbsuboverlay gets whole packets + leio, what's the mpegts demux hack about? + my libdvbsub code can't handle cut packets + so the hack instructs the demuxer to gather full packets before pushing down, but it applies that to more PES packet types than just dvbsub, but I'm not sure if that's a bad thing + either way, needs a cleaner solution, either in demuxer, or I need to handle cut packets + ok, but really it should be fixed in the overlay, right? + or a parser be inserted + the problem is that I don't know from the first packet beforehand if it is a cut one or no + not + err, first buffer + just when I receive the next one I see if it has a valid timestamp on it or not + so I can't very well queue it up in the chain either, I might be blocking the very last subtitle for no reason or something + but you could just drop/ignore packets until you find one, right? + find what? + a complete packet? + the problem isn't that they aren't complete + the problem is that they are cut across multiple GstBuffers by the demuxer without the hack + sure, I understand that + but you can't easily determine if a GstBuffer contains he start fragment of a packet or not? + I guess I could parse the packet and see if its length is enough, just like the libdvbsub code eventually does too + I can, it has a timestamp if it's the first chunk + I just never know if I need to wait for more, without some parsing + ah ok + while the demuxer could just give me an uncut one in the first place + like it always does for program streams + that gather_pes is always set in gstmpegdemux, but not in gstmpegtsdemux + +2010-11-29 20:06:07 +0000 Mart Raudsepp + + * configure.ac: + * gst/dvbsuboverlay/Makefile.am: + * gst/dvbsuboverlay/TODO: + * gst/dvbsuboverlay/dvb-sub.c: + * gst/dvbsuboverlay/dvb-sub.h: + * gst/dvbsuboverlay/ffmpeg-colorspace.h: + * gst/dvbsuboverlay/gstdvbsuboverlay.c: + * gst/dvbsuboverlay/gstdvbsuboverlay.h: + dvbsuboverlay: initial version, work in progress + +2010-12-03 18:11:56 +0100 Mark Nauwelaerts + + * gst/audioparsers/gstaacparse.c: + * gst/audioparsers/gstac3parse.c: + * gst/audioparsers/gstamrparse.c: + audioparsers: update some documentation + +2010-12-03 18:11:38 +0100 Mark Nauwelaerts + + * docs/plugins/Makefile.am: + * docs/plugins/gst-plugins-bad-plugins-docs.sgml: + * docs/plugins/gst-plugins-bad-plugins-sections.txt: + * gst/audioparsers/gstmpegaudioparse.c: + mpegaudioparse: add to documentation + +2010-12-03 18:11:09 +0100 Mark Nauwelaerts + + * docs/plugins/Makefile.am: + * docs/plugins/gst-plugins-bad-plugins-docs.sgml: + * docs/plugins/gst-plugins-bad-plugins-sections.txt: + * gst/audioparsers/gstdcaparse.c: + dcaparse: add to documentation + +2010-12-03 18:09:41 +0100 Mark Nauwelaerts + + * docs/plugins/Makefile.am: + * docs/plugins/gst-plugins-bad-plugins-docs.sgml: + * docs/plugins/gst-plugins-bad-plugins-sections.txt: + * gst/qtmux/gstqtmux.c: + qtmux: add documentation + +2010-11-08 19:58:31 +0100 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: increase keyframe awareness + ... which is not particular relevant for audio parsing, but more so + in video cases. In particular, auto-determine if dealing with video (caps). + +2010-12-03 17:46:27 +0100 Benjamin Gaignard + + * Android.mk: + * sys/audioflingersink/Android.mk: + * sys/audioflingersink/GstAndroid.cpp: + * sys/audioflingersink/audioflinger_wrapper.cpp: + * sys/audioflingersink/audioflinger_wrapper.h: + * sys/audioflingersink/gstaudioflingerringbuffer.h: + * sys/audioflingersink/gstaudioflingersink.c: + * sys/audioflingersink/gstaudioflingersink.h: + sys: Add android audioflingersink + +2010-12-03 17:42:46 +0100 Benjamin Gaignard + + * Android.mk: + * android/NOTICE: + * android/aacparse.mk: + * android/amrparse.mk: + * android/h264parse.mk: + * android/metadata.mk: + * android/qtmux.mk: + * android/sdpelem.mk: + Add build system for Android + +2010-12-02 15:45:02 +0200 Stefan Kost + + * gst/camerabin/gstcamerabin.c: + camerabin: smal api doc update + +2010-12-02 05:39:14 -0300 Lasse Laukkanen + + * gst/camerabin/gstcamerabin.c: + camerabin: Avoid assertion on image finishing + As imgbin_finished() is scheduled from g_idle_add, it might + be run a little later than expected, this can lead to the application + setting camerabin to ready before imgbin_finished() runs. In this case, + the processing counter goes to 0 and an assertion happens. + This patch relaxes the imgbin_finished() check on the processing + counter. + +2010-12-01 23:14:56 -0800 David Schleef + + * tools/element-maker: + element-maker: Handle names with multiple underscores + +2010-12-01 23:04:57 -0800 David Schleef + + * gst/debugutils/Makefile.am: + * gst/debugutils/debugutilsbad.c: + * gst/debugutils/gstchopmydata.c: + * gst/debugutils/gstchopmydata.h: + chopmydata: Add new element + This element splits up a stream into randomly-sized buffers. + Useful (maybe) for testing parsers. + +2010-12-02 03:09:59 -0300 Thiago Santos + + * tests/check/Makefile.am: + tests: Remove leftover comment + Remove comment that doesn't make sense anymore + +2010-12-01 23:21:33 +0100 Alessandro Decina + + * sys/applemedia/miovideosrc.c: + applemedia: don't use the deprecated g_strcasecmp function. + Replace g_strcasecmp with g_ascii_strcasecmp. + +2010-12-01 23:20:36 +0100 Alessandro Decina + + * gst/pcapparse/gstpcapparse.c: + * sys/applemedia/mioapi.c: + Fix compiler warnings with gcc 4.2.1 on OSX. + +2010-12-01 15:28:53 +0100 Mark Nauwelaerts + + * gst/audioparsers/gstac3parse.c: + * gst/audioparsers/gstac3parse.h: + ac3parse: use proper EAC-3 caps + +2010-12-01 10:45:49 +0100 David Hoyt + + * gst/qtmux/gstqtmux.c: + qtmux: handle msvc ftruncate incompatibility + Fixes #636185. + +2010-10-09 17:39:36 -0700 David Schleef + + * tests/check/Makefile.am: + * tests/check/elements/schroenc.c: + Add a schroenc test + +2010-11-27 20:13:38 -0800 David Schleef + + * ext/dirac/gstdiracdec.cc: + * gst/liveadder/liveadder.c: + * gst/mpegpsmux/mpegpsmux.c: + * gst/pnm/gstpnmdec.c: + * gst/pnm/gstpnmenc.c: + Fix pad template memleaks + Pad templates returned by gst_static_pad_template_get() were not + being unreffed. + +2010-11-30 18:43:24 -0800 David Schleef + + * ext/vp8/gstvp8enc.c: + vp8enc: Readd setting of granulepos + Revert parts of last patch that removed setting of granulepos. + oggmux still requires correct granulepos in incoming packet. + +2010-11-29 20:21:31 -0800 David Schleef + + * ext/vp8/gstvp8enc.c: + vp8enc: Don't override timestamps set by base class + Because the base class does it correctly. + Fixes: #635720, #625558. + +2010-11-30 15:41:02 +0100 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: avoid unexpected stray metadata + +2010-11-30 15:40:28 +0100 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: use proper _NONE output value when applicable + +2010-11-15 20:03:01 +0100 Sebastian Dröge + + * configure.ac: + * gst/jp2kdecimator/Makefile.am: + * gst/jp2kdecimator/gstjp2kdecimator.c: + * gst/jp2kdecimator/gstjp2kdecimator.h: + * gst/jp2kdecimator/jp2kcodestream.c: + * gst/jp2kdecimator/jp2kcodestream.h: + jp2kdecimator: Add a JPEG2000 decimator element + This element drops information from JPEG2000 images without reencoding. + +2010-11-23 21:45:41 +0100 Sebastian Dröge + + * ext/jp2k/gstjasperenc.c: + jp2kenc: Emit SOP markers in every codestream packet + This makes parsing much easier, faster and more reliable. + +2010-11-27 16:07:19 -0600 Alejandro Gonzalez + + * gst/qtmux/gstqtmux.c: + qtmux: gst_qtmux_check_difference verify before subtract + Avoid negative overflow by checking the order of operands + on subtraction of unsigned integers. + https://bugzilla.gnome.org/show_bug.cgi?id=635878 + +2010-11-27 18:58:07 -0800 David Schleef + + * gst/mpegtsmux/mpegtsmux.c: + mpegtsmux: Fix some memleaks + +2010-11-15 11:37:39 -0800 David Schleef + + * ext/schroedinger/gstschroenc.c: + schroenc: minor memleak fix + +2010-11-25 19:31:35 +0100 Edward Hervey + + * gst-libs/gst/signalprocessor/gstsignalprocessor.c: + signalprocessor: Remove dead assignments + +2010-11-25 19:31:03 +0100 Edward Hervey + + * gst/videomeasure/gstvideomeasure_collector.c: + * gst/videomeasure/gstvideomeasure_ssim.c: + videomeasure: Remove dead assignments + +2010-11-25 19:25:27 +0100 Edward Hervey + + * gst/tta/gstttadec.c: + * gst/tta/gstttaparse.c: + tta: Remove dead assignments and useless variable + +2010-11-25 19:24:56 +0100 Edward Hervey + + * gst/stereo/gststereo.c: + stereo: Remove dead assignments + +2010-11-25 19:21:23 +0100 Edward Hervey + + * gst/sdp/gstsdpdemux.c: + sdp: Remove useless variables + +2010-11-25 19:21:11 +0100 Edward Hervey + + * gst/rtpmux/gstrtpmux.c: + rtpmux: Remove dead assignments + +2010-11-25 19:21:01 +0100 Edward Hervey + + * gst/real/gstrealaudiodec.c: + * gst/real/gstrealvideodec.c: + real: Remove dead assignments + +2010-11-25 19:20:51 +0100 Edward Hervey + + * gst/ivfparse/gstivfparse.c: + ivfparse: Remove dead assignments + +2010-11-25 19:06:49 +0100 Edward Hervey + + * gst/freeze/gstfreeze.c: + freeze: Remove dead assignments + +2010-11-25 19:06:38 +0100 Edward Hervey + + * gst/dvdspu/gstdvdspu.c: + dvdspu: Remove dead assignments + +2010-11-25 19:06:27 +0100 Edward Hervey + + * gst/dtmf/gstrtpdtmfdepay.c: + dtmf: Remove dead assignments + +2010-11-25 19:01:42 +0100 Edward Hervey + + * gst/dccp/gstdccp.c: + dccp: Remove dead assignments + +2010-11-25 18:56:42 +0100 Edward Hervey + + * gst/audioparsers/gstaacparse.c: + * gst/audioparsers/gstamrparse.c: + * gst/audioparsers/gstbaseparse.c: + audioparsers: Remove dead assignments + +2010-11-25 18:52:47 +0100 Edward Hervey + + * ext/vp8/gstvp8dec.c: + * ext/vp8/gstvp8enc.c: + vp8: Remove dead assignments + +2010-11-25 18:49:23 +0100 Edward Hervey + + * ext/sdl/sdlaudiosink.c: + sdlaudiosink: Remove dead assignments + +2010-11-25 18:47:15 +0100 Edward Hervey + + * ext/schroedinger/gstschrodec.c: + * ext/schroedinger/gstschroenc.c: + * ext/schroedinger/gstschroparse.c: + schroedinger: Remove dead assignments + +2010-11-25 18:43:30 +0100 Edward Hervey + + * ext/mimic/gstmimenc.c: + mimenc: Remove dead assignment + +2010-11-25 18:43:18 +0100 Edward Hervey + + * ext/cog/gstcogdownsample.c: + cogdownsample: Remove dead assignment + +2010-11-25 18:42:33 +0100 Edward Hervey + + * ext/opencv/gstcvdilateerode.c: + * ext/opencv/gstcvlaplace.c: + * ext/opencv/gstcvsmooth.c: + * ext/opencv/gstcvsobel.c: + * ext/opencv/gstedgedetect.c: + * ext/opencv/gstfaceblur.c: + * ext/opencv/gstfacedetect.c: + * ext/opencv/gstopencvutils.c: + * ext/opencv/gstopencvvideofilter.c: + * ext/opencv/gstpyramidsegment.c: + * ext/opencv/gsttemplatematch.c: + * ext/opencv/gsttextwrite.c: + opencv: Remove dead assignments + ... and fix indentation + +2010-11-25 18:33:37 +0100 Edward Hervey + + * ext/cog/gstcogcolorspace.c: + cogcolorspace: Remove dead assignment + +2010-11-25 18:30:56 +0100 Edward Hervey + + * ext/cog/cogframe.c: + cogframe: Remove dead assignments + +2010-11-25 18:29:31 +0100 Edward Hervey + + * ext/celt/gstceltenc.c: + celtenc: Initialize variable + In the case the tag_setter returns something, empty_tags would be + garbage value. + +2010-11-25 18:29:22 +0100 Edward Hervey + + * ext/celt/gstceltenc.c: + celtenc: Remove dead assignment + +2010-11-25 18:26:21 +0100 Edward Hervey + + * ext/assrender/gstassrender.c: + assrender: Remove dead assignments + +2010-11-25 17:14:23 +0100 Andoni Morales Alastruey + + * gst/audioparsers/gstbaseparse.c: + audioparse: fix possible division-by-zero + https://bugzilla.gnome.org/show_bug.cgi?id=635786 + +2010-10-23 01:56:04 +0200 Olivier Crête + + * sys/shm/shmpipe.c: + shm: Don't pass the ShmPipe to the function closing the shm area + +2010-10-23 01:22:43 +0200 Olivier Crête + + * sys/shm/shmpipe.c: + shm: Use the right counter when freeing buffers + +2010-10-23 01:12:49 +0200 Olivier Crête + + * sys/shm/Makefile.am: + * sys/shm/shmalloc.h: + shmalloc: Manually decide to use GLib or not in the shmalloc + So make it easier for embedders to use it with or without Glib + +2010-10-20 22:49:59 +0200 Olivier Crête + + * sys/shm/shmpipe.c: + shm: Remove duplicated arguement + +2010-10-20 22:39:21 +0200 Olivier Crête + + * sys/shm/shmpipe.c: + shm: Fix socket leak on connect() error + +2010-10-20 22:28:13 +0200 Olivier Crête + + * sys/shm/shmpipe.c: + * sys/shm/shmpipe.h: + shm: sp_client_recv returns negative on error, so make the retval signed + +2010-10-20 22:17:30 +0200 Olivier Crête + + * sys/shm/shmpipe.c: + shm: Rename confusingly named variable + +2010-10-20 22:14:09 +0200 Olivier Crête + + * sys/shm/shmpipe.c: + shm: Change permissions on old shm areas too + Change the permissions on old shm areas + +2010-10-20 22:01:36 +0200 Olivier Crête + + * sys/shm/shmpipe.c: + shm: Use the macro for the last error too + +2010-10-20 21:52:31 +0200 Olivier Crête + + * sys/shm/shmpipe.c: + shm: Use "ablock" for all ShmAllocBlock variables + Use the ablock variable name for ShmAllocBlocks and block for + ShmBlock + +2010-10-20 21:52:24 +0200 Olivier Crête + + * sys/shm/shmpipe.h: + shm: Add more comments + +2010-10-20 21:41:15 +0200 Youness Alaoui + + * sys/shm/shmpipe.c: + shm: stylist improvements + +2010-10-20 21:33:24 +0200 Youness Alaoui + + * sys/shm/shmalloc.c: + shm: Explain some fields + Explain what some of the fields in the allocator actually mean + +2010-11-22 15:26:06 +0100 Robert Swain + + * gst/interlace/gstinterlace.c: + interlace: Fix buffer timestamp and duration + The field rate is twice the frame rate of the src pad and so the duration of + one output buffer is src_fps_d / (2 * src_fps_n). + +2010-11-22 10:29:56 +0100 Robert Swain + + * gst/interlace/gstinterlace.c: + interlace: Rename pattern property to field-pattern + This is mostly for clarity of what the property means and, I believe, makes the + pattern-offset property more comprehensible. + +2010-11-22 10:27:22 +0100 Robert Swain + + * gst/interlace/gstinterlace.c: + interlace: Add pattern offset property + This property allows one to start at any point within the field pattern after + a discontinuity (whenever gst_interlace_reset () is called). Thus with the + 2:3:3:2 pattern, for example, one can start at offset 2 and achieve 3:2:2:3 + or offset 1 and achieve 3:3:2:2. + +2010-11-19 17:01:41 -0300 Lasse Laukkanen + + * gst/camerabin/camerabinimage.c: + * gst/camerabin/camerabinimage.h: + * gst/camerabin/gstcamerabin.c: + camerabin: Create imagebin elements when image mode is set in camerabin NULL state + This patch refactors imagebin element creation and linking into separate functions, + and adds re-using also for imagebin internally created elements. + So this refactoring allows creating imagebin elements already in NULL state when + application sets the image mode, and next state change from NULL to READY will be faster. + This reduces first capture latency. + Earlier the elements were both created and linked in NULL to READY state change. + +2010-11-22 12:23:30 +0100 Andoni Morales Alastruey + + * gst/mpegdemux/mpegtspacketizer.c: + mpegtsparse: Create a sub-buffer with the section length + +2010-11-19 15:23:41 -0500 Josh Doe + + * ext/opencv/gstcvdilateerode.c: + * ext/opencv/gstcvequalizehist.c: + * ext/opencv/gstcvlaplace.c: + * ext/opencv/gstcvsmooth.c: + * ext/opencv/gstcvsobel.c: + * ext/opencv/gstedgedetect.c: + * ext/opencv/gstfaceblur.c: + * ext/opencv/gstopencvutils.c: + * ext/opencv/gstopencvutils.h: + * ext/opencv/gstpyramidsegment.c: + * ext/opencv/gsttemplatematch.c: + * ext/opencv/gsttextwrite.c: + opencv: fix caps issues and extend supported caps for some elements + Some elements had vague caps, such as "video/x-raw-rgb", which caused problems + at least with textwrite. For other elements, the underlying OpenCV functions + support more than just one image type, so I increased the number of supported + caps. + I created a utility function "gst_opencv_caps_from_cv_image_type", so each + element creates caps directly from OpenCV image types, such as CV_8UC1 for + 8-bit grayscale. This function uses gstvideo to create uniform caps. + https://bugzilla.gnome.org/show_bug.cgi?id=635304 + +2010-11-22 17:43:12 -0300 Thiago Santos + + * gst/jpegformat/gstjpegparse.c: + jpegparse: Small optimization on tags parsing + Optimize a little avoiding copying a taglist when parsing xmp/exif + data. + +2010-09-17 09:52:12 -0300 Thiago Santos + + * gst/selector/gstoutputselector.c: + outputselector: Avoid losing the last_buffer when switching + This patch makes outputselector take an extra ref when pushing + the last_buffer to avoid it losing it during the switch function. + This makes resend-latest properly work if the active-pad is changed + during the switch function buffer pushing (on a pad probe, for example). + https://bugzilla.gnome.org/show_bug.cgi?id=629917 + +2010-09-17 09:44:02 -0300 Thiago Santos + + * gst/selector/gstoutputselector.c: + outputselector: Recheck pending switch after pushing buffer + This patch makes output-selector always recheck if there's a + pending pad switch after pushing a buffer, preventing that + it pushes a buffer on the 'wrong' pad. + https://bugzilla.gnome.org/show_bug.cgi?id=629917 + +2010-11-22 15:10:26 +0200 Olivier Aubert + + * ext/rsvg/Makefile.am: + * ext/rsvg/gstrsvg.c: + * ext/rsvg/gstrsvgoverlay.c: + * ext/rsvg/gstrsvgoverlay.h: + rsvgoverlay: scalable and relative svg overlay with cairo + Add a cairo+librsvg based overlay element to the rsvg plugin. + +2010-11-22 17:06:05 +0200 Stefan Kost + + * tests/check/Makefile.am: + make: remove traces or moved/removed plugins + +2010-11-22 17:05:23 +0200 Stefan Kost + + * Makefile.am: + make: add missinf trailing \ to fix the build + +2010-11-21 23:11:19 -0800 David Schleef + + * gst/colorspace/colorspace.c: + colorspace: remove incorrect check + +2010-11-19 17:55:36 +0100 Mark Nauwelaerts + + * gst/qtmux/gstqtmux.c: + qtmux: remove remnant of obsolete property + +2010-11-19 15:18:58 +0100 Mark Nauwelaerts + + * tests/check/elements/qtmux.c: + tests: qtmux: also unit test fragmented file cases + +2010-07-30 12:48:29 +0200 Marc-André Lureau + + * gst/qtmux/gstqtmux.c: + * gst/qtmux/gstqtmux.h: + qtmux: allow specifying trak timescale + This is mainly because Smoothstreaming client are broken and don't + take the TimeScale property into account. + +2010-11-19 17:41:41 +0100 Mark Nauwelaerts + + * gst/qtmux/atoms.c: + * gst/qtmux/atoms.h: + * gst/qtmux/gstqtmux.c: + qtmux: include sdtp atoms for ismv fragmented files + Based on patch by Marc-André Lureau + +2010-11-19 19:17:45 +0100 Mark Nauwelaerts + + * gst/qtmux/gstqtmux.c: + qtmux: enable default fragmented file for ismlmux + +2010-09-02 13:58:05 +0200 Marc-André Lureau + + * gst/qtmux/atoms.h: + * gst/qtmux/ftypcc.h: + * gst/qtmux/gstqtmuxmap.c: + * gst/qtmux/gstqtmuxmap.h: + qtmux: add ismlmux, for fragmented isml major brand + +2010-11-19 14:44:45 +0100 Mark Nauwelaerts + + * gst/qtmux/gstqtmux.c: + qtmux: finalize sinkpads list + +2010-07-22 19:40:07 +0200 Marc-André Lureau + + * gst/qtmux/gstqtmux.c: + qtmux: add moov in streamheader + +2010-08-06 13:26:27 +0200 Marc-André Lureau + + * gst/qtmux/gstqtmux.c: + * gst/qtmux/gstqtmux.h: + qtmux: add streamable property to avoid building fragmented mfra index + +2010-11-18 16:48:06 +0100 Mark Nauwelaerts + + * gst/qtmux/atoms.c: + * gst/qtmux/atoms.h: + * gst/qtmux/gstqtmux.c: + * gst/qtmux/gstqtmux.h: + qtmux: add mfra to fragmented file + Based on patch by Marc-André Lureau + +2010-11-15 15:17:59 +0100 Mark Nauwelaerts + + * gst/qtmux/atoms.c: + * gst/qtmux/atoms.h: + * gst/qtmux/gstqtmux.c: + * gst/qtmux/gstqtmux.h: + qtmux: optionally create fragmented file + In this mode, an initial empty moov (containing only stream metadata) is written, + followed by fragments containing actual data (along with required metadata). + New fragments are started either at keyframe (if such are sparse) or when + property configured duration exceeded. + Based on patch by Marc-André Lureau + Fixes #632911. + +2010-11-15 15:12:45 +0100 Mark Nauwelaerts + + * gst/qtmux/atoms.c: + qtmux: use helper to set atom flags from given uint + +2010-11-09 16:49:07 +0100 Mark Nauwelaerts + + * gst/qtmux/gstqtmux.c: + qtmux: refactor configuring and sending of moov + Based on patch by Marc-André Lureau + +2010-11-09 15:54:44 +0100 Mark Nauwelaerts + + * gst/qtmux/gstqtmux.c: + qtmux: refactor extra top-level atom handling + Also check a bit more for possible errors, and free proper items in such case. + +2010-11-09 15:01:15 +0100 Mark Nauwelaerts + + * gst/qtmux/gstqtmux.c: + qtmux: refactor slightly using buffer helper + +2010-11-05 13:48:57 +0100 Mark Nauwelaerts + + * gst/qtmux/gstqtmux.c: + qtmux: fix misinforming comment + +2010-11-05 12:08:15 +0100 Mark Nauwelaerts + + * gst/qtmux/atoms.c: + * gst/qtmux/atoms.h: + * gst/qtmux/gstqtmux.c: + qtmux: delegate mvex handling to atoms + ... which keeps qtmux simpler. + +2009-09-28 16:11:35 +0200 Marc-André Lureau + + * gst/qtmux/atoms.c: + * gst/qtmux/atoms.h: + * gst/qtmux/gstqtmux.c: + qtmux: add mvex/trex in header if fragmented + One "trex" is added per "trak". We don't support default values, + but the "trex" box is mandatory. + +2009-09-28 13:01:30 +0200 Marc-André Lureau + + * gst/qtmux/fourcc.h: + qtmux: add a couple of fourcc for fragmented mp4 + +2010-11-05 11:08:01 +0100 Mark Nauwelaerts + + * gst/qtmux/gstqtmux.c: + qtmux: avoid removing temp file when error occurred + +2009-09-30 17:16:30 +0200 Marc-André Lureau + + * gst/qtmux/gstqtmux.c: + qtmux: truncate buffer file after each send + +2009-09-28 16:53:51 +0200 Marc-André Lureau + + * gst/qtmux/gstqtmux.c: + qtmux: remove temp file when reset/finalize + +2010-08-18 02:00:10 +0530 Arun Raghavan + + * gst/jpegformat/gstjpegparse.c: + jpegformat: Push tags after setting srcpad caps + This patch defers emission of tag events till caps are set on the source + pad of jpegparse, so that these tags can be seen downstream. + https://bugzilla.gnome.org/show_bug.cgi?id=627211 + +2010-11-19 18:51:32 +0100 Alessandro Decina + + * gst/mpegdemux/mpegtsparse.c: + mpegtsparse: fix compiler warning + +2010-11-19 18:26:59 +0100 Andoni Morales Alastruey + + * gst/mpegdemux/mpegtspacketizer.c: + mpegtsparse: fix thinko + +2010-11-19 17:25:01 +0100 Andoni Morales Alastruey + + * gst/mpegdemux/mpegtspacketizer.c: + mpegtsparse: fix handling of TOT and TDT sections. Fixes #635281. + TDT and TOT sections, with PID=0x14, doesn't extend to several packets + and the section filter is not needed here and shouldn't be used at all + for these tables because the have a different structure. + For example, TDT tables were not parsed for odd hours because this bit + is the 'current_next_indicator' bit for the other sections, and the table + was discarded. + +2010-11-19 17:22:06 +0100 Andoni Morales Alastruey + + * gst/mpegdemux/mpegtsparse.c: + mpegtsparse: don't calculate the CRC for TOT tables. Fixes #635281. + TOT tables, with table_id=0x73, don't have a CRC, so don't calcute it + +2010-11-18 18:42:38 +0100 Andoni Morales Alastruey + + * sys/dvb/dvbbasebin.c: + dvbbasebin: Add TDT to the initial pids filter for dvbsrc. Fixes #635200. + +2010-11-16 17:35:36 +0100 Víctor Manuel Jáquez Leal + + * gst/jpegformat/gstjpegparse.c: + jpegparse: add gst_jpeg_parse_skip_marker () + https://bugzilla.gnome.org/show_bug.cgi?id=626618 + +2010-08-13 13:14:30 +0200 Víctor Manuel Jáquez Leal + + * gst/jpegformat/gstjpegparse.c: + jpegparse: use byte reader accessors + https://bugzilla.gnome.org/show_bug.cgi?id=626618 + +2010-11-17 10:49:30 +0100 Víctor Manuel Jáquez Leal + + * gst/jpegformat/gstjpegparse.c: + jpegparse: inline gst_jpeg_parse_sof () + No functional changes (hopefully). + https://bugzilla.gnome.org/show_bug.cgi?id=626618 + +2010-11-16 17:23:35 +0100 Víctor Manuel Jáquez Leal + + * gst/jpegformat/gstjpegparse.c: + jpegparse: fix typo + https://bugzilla.gnome.org/show_bug.cgi?id=626618 + +2010-11-18 10:58:06 -0300 Aleksey Lim + + * gst/camerabin/camerabinvideo.c: + * gst/camerabin/gstcamerabin.c: + camerabin: Do not use audio clock after stopping video capture + Adda provide clock function to camerabin to make it not + provide the audio clock of the record bin when no video + recording is happening + Fixes #613379 + +2010-11-17 16:23:42 +0100 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: use correct offset when adding index entry + ... bearing in mind that BUFFER_OFFSET is media specific and may not + reflect the basic offset after having been parsed. + +2010-11-17 14:30:09 +0100 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: enhancements for timestamp marked framed formats + That is, as such formats allow subclass to extract position from frame, + it is possible to extract duration (if not otherwise provided) + from (near) last frame, and a seek can fairly accurately target the required + position. + Fixes #631389. + +2010-11-16 17:06:14 +0100 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: refactor frame scanning peformed by _loop + +2010-11-16 18:04:00 +0100 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: slightly optimize sending of pending newsegment events + +2010-11-16 17:04:35 +0100 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: minor fixes and enhancements + Arrange for upstream as well as downstream flushing when seeking. + Also determine upstream size as well as seekability. Adjust some comments + to reality and employ debug statement in proper order. + +2010-11-17 15:33:36 +0100 Mark Nauwelaerts + + * gst/audioparsers/gstaacparse.c: + aacparse: minor cleanups + +2010-11-17 15:24:37 +0100 Mark Nauwelaerts + + * gst/audioparsers/gstaacparse.c: + aacparse: fix regression in ADIF src caps setting + +2010-11-16 12:11:53 +0100 Mark Nauwelaerts + + * gst/audioparsers/gstflacparse.c: + * gst/audioparsers/gstflacparse.h: + flacparse: parse seektable + Fixes #631389 (partially). + +2010-11-16 12:08:54 +0100 Mark Nauwelaerts + + * gst/audioparsers/gstflacparse.c: + flacparse: minor refactor and enable default baseparse segment clipping + +2010-11-12 00:40:33 +0100 Ole André Vadla Ravnås + + * sys/applemedia/celvideosrc.c: + * sys/applemedia/celvideosrc.h: + celvideosrc: fix nasty deadlock + We cannot call any CMBufferQueue functions while holding the lock that + our callback also depends on. So now we make use of CMBufferQueue's + trigger API in order to get notified when the queue has data. + +2010-11-11 23:41:44 +0100 Ole André Vadla Ravnås + + * sys/applemedia/cmapi.c: + * sys/applemedia/cmapi.h: + cmapi: cover CMBufferQueue's trigger API + +2010-11-11 21:42:03 +0100 Ole André Vadla Ravnås + + * sys/applemedia/celvideosrc.c: + celvideosrc: unlock should also notify + Otherwise we depend on being woken up by the CoreMedia queue getting + its next buffer. + +2010-11-10 23:16:51 +0100 Ole André Vadla Ravnås + + * sys/applemedia/vtdec.c: + * sys/applemedia/vtdec.h: + * sys/applemedia/vtenc.c: + * sys/applemedia/vtenc.h: + applemedia: don't push synchronously from callback + The codec that called us might be holding locks to shared resources, so + we should never push downstream from within its buffer callback. + Note that a GstBufferList is not used here because we need to preserve + the buffer metadata held by our GstBuffer subclasses. + +2010-11-10 20:52:47 +0100 Ole André Vadla Ravnås + + * sys/applemedia/vtenc.c: + vtenc: bump H.264 level from 1.3 to 3.0 + This should be turned into a property. + +2010-11-10 20:44:15 +0100 Ole André Vadla Ravnås + + * sys/applemedia/celvideosrc.c: + * sys/applemedia/celvideosrc.h: + celvideosrc: add basic device selection support + +2010-11-10 20:51:27 +0100 Ole André Vadla Ravnås + + * sys/applemedia/cvapi.c: + * sys/applemedia/cvapi.h: + cvapi: add wrapper for IO surface access + To be used in a future video sink for zero-copy rendering. + +2010-11-10 20:25:28 +0100 Ole André Vadla Ravnås + + * sys/applemedia/celapi.c: + * sys/applemedia/celapi.h: + celapi: add capture port type constants + +2010-11-09 22:43:14 +0200 Mart Raudsepp + + * ext/assrender/gstassrender.c: + assrender: Remove unused src_stride variable from blit functions + +2010-11-09 18:10:43 -0300 Thiago Santos + + * Makefile.am: + * win32/common/libgstphotography.def: + win32: Adding photography interface .def file + Adds check-exports to -bad to have photography interface + .def file created + Fixes #578629 + +2010-11-09 19:38:25 +0100 Mark Nauwelaerts + + * gst/audioparsers/gstmpegaudioparse.c: + mpegaudioparse: fix silly leak in _reset + +2010-11-08 23:54:31 +0100 Ole André Vadla Ravnås + + * sys/applemedia/celvideosrc.c: + * sys/applemedia/vtdec.c: + * sys/applemedia/vtenc.c: + * sys/applemedia/vth264decbin.c: + * sys/applemedia/vth264encbin.c: + applemedia: biplanar is actually NV12, not I420 + D'oh! + +2010-11-08 21:22:13 +0100 Ole André Vadla Ravnås + + * sys/applemedia/vtenc.c: + * sys/applemedia/vtenc.h: + vtenc: remove keyframe enforcement workaround + Was only needed for old iOS where the H.264 encoder didn't support + kVTEncodeFrameOptionKey_ForceKeyFrame. + +2010-11-08 18:56:52 +0100 Ole André Vadla Ravnås + + * sys/applemedia/cvapi.c: + * sys/applemedia/cvapi.h: + cvapi: add a few extra bits of wrapping + +2010-11-08 15:08:19 +0100 Ole André Vadla Ravnås + + * sys/applemedia/coremediabuffer.c: + * sys/applemedia/corevideobuffer.c: + * sys/applemedia/cvapi.h: + applemedia: lock CVPixelBuffer read-only + As per Apple's docs, this may improve performance by avoiding redundant + invalidations of existing caches of the buffer contents. + +2010-11-08 10:33:58 -0300 Lasse Laukkanen + + * tests/examples/camerabin/gst-camerabin-test.c: + examples: camerabin: Remove gstring leak + Simplify gst-camerabin-test by removing GString and replacing + with gchar for the filename handling. Also removes a leak of + the GString data. + +2010-11-08 16:00:21 +0200 Stefan Kost + + * ext/rsvg/gstrsvgdec.c: + rsvgdec: avoid reffing the element in chain + +2010-11-08 15:45:48 +0200 Stefan Kost + + * ext/rsvg/gstrsvgdec.c: + rsvgdec: add some minimal logging to track what it is doing + +2010-11-08 13:52:49 +0100 Ole André Vadla Ravnås + + * sys/applemedia/celvideosrc.c: + celvideosrc: put planar first in template caps + +2010-11-08 13:49:04 +0100 Ole André Vadla Ravnås + + * sys/applemedia/cvapi.h: + * sys/applemedia/vtdec.c: + * sys/applemedia/vtenc.c: + * sys/applemedia/vth264decbin.c: + * sys/applemedia/vth264encbin.c: + applemedia: improve vtenc/vtdec performance + Profiling of H.264 encode and decode revealed that conversions + between packed and planar were happening behind the scenes. + Hence we now choose I420 instead of YUY2. + +2010-10-22 18:07:00 +0300 Lasse Laukkanen + + * tests/examples/camerabin/gst-camerabin-test.c: + examples: add async bus handler to gst-camerabin-test + Splits the bus handler into sync and async, keeping the + prepare-xwindow handling at the sync for faster handling and + moving the others to the async handler + +2010-11-06 12:27:32 +0000 Tim-Philipp Müller + + * configure.ac: + configure: we still require Gtk+ >= 2.14.0 when compiling against 2.0 + The check for the minor version was dropped in one of the previous + commits. + +2010-11-05 16:51:57 +0100 Ole André Vadla Ravnås + + * sys/applemedia/celvideosrc.c: + * sys/applemedia/celvideosrc.h: + celvideosrc: measure fps when statistics is enabled + Also refactor timestamping slightly. + +2010-11-05 15:14:08 +0100 Ole André Vadla Ravnås + + * sys/applemedia/celvideosrc.c: + * sys/applemedia/celvideosrc.h: + celvideosrc: update to new Celestial and MediaToolbox APIs + This means celvideosrc is no longer compatible with iOS 3.x. + +2010-11-05 15:08:56 +0100 Ole André Vadla Ravnås + + * sys/applemedia/celvideosrc.c: + celvideosrc: fix debug category description + +2010-11-05 15:08:02 +0100 Ole André Vadla Ravnås + + * sys/applemedia/celapi.c: + * sys/applemedia/celapi.h: + celapi: update to reflect new API on iOS 4.x + Also add remaining property constants for device and stream. + +2010-11-05 15:07:38 +0100 Ole André Vadla Ravnås + + * sys/applemedia/mtapi.c: + * sys/applemedia/mtapi.h: + mtapi: update to reflect new API on iOS 4.x + Also add remaining property constants for device and stream. + +2010-11-05 10:56:51 +0100 Sebastian Dröge + + * gst/colorspace/gstcolorspaceorc-dist.c: + * gst/colorspace/gstcolorspaceorc-dist.h: + colorspace: Update generated ORC sources + +2010-08-26 17:08:19 -0300 Thiago Santos + + * gst/camerabin/gstcamerabin-enum.h: + * gst/camerabin/gstcamerabin.c: + * gst/camerabin/gstcamerabin.h: + * tests/check/elements/camerabin.c: + camerabin: Adds 'idle' property + Adds 'idle', a read-only boolean property that tells applications + if there is any capturing/saving/encoding going on in camerabin. If + not, it is safe to set it to NULL and release resources without + losing data. + +2010-05-05 13:58:07 +0300 Lasse Laukkanen + + * gst/camerabin/gstcamerabin-enum.h: + * gst/camerabin/gstcamerabin.c: + * tests/check/elements/camerabin.c: + camerabin: Add "ready-for-capture" property + Add "ready-for-capture" property to indicate if preparing a new + capture is possible. + "ready-for-capture" changes before the 'image-done' signal, so + the application can be notified that it can do a new capture + even before the previous one has finished encoding/saving. + +2010-11-05 00:32:35 +0000 Tim-Philipp Müller + + * configure.ac: + configure: don't even check for Gtk+ if --disable-examples is specified + There are Gtk+-based examples in plugin dirs and tests/icles/ too, and + we want to disable those as well then. + +2010-11-05 00:24:31 +0000 Tim-Philipp Müller + + * configure.ac: + configure: add --with-gtk option and default to Gtk+ 2.0 while the 3.0 API is still in flux + https://bugzilla.gnome.org/show_bug.cgi?id=634014 + +2010-11-03 00:04:27 +0000 Tim-Philipp Müller + + * configure.ac: + * tests/Makefile.am: + * tests/check/Makefile.am: + * tests/check/elements/.gitignore: + * tests/check/elements/zbar.c: + * tests/files/Makefile.am: + * tests/files/barcode.png: + tests: add very simple zbar unit test + Not valgrind clean yet (could be zbar's fault though). + +2010-11-04 19:25:24 +0100 Ole André Vadla Ravnås + + * sys/applemedia/avfvideosrc.m: + * sys/applemedia/celvideosrc.c: + * sys/applemedia/miovideosrc.c: + * sys/applemedia/qtkitvideosrc.m: + applemedia: make video source element details consistent + Inspired by the v4l2src element details. + +2010-11-04 19:11:04 +0100 Ole André Vadla Ravnås + + * sys/applemedia/avfvideosrc.m: + * sys/applemedia/qtkitvideosrc.m: + applemedia: consistently use gst_element_class_set_details_simple + +2010-11-04 19:02:50 +0100 Ole André Vadla Ravnås + + * sys/applemedia/celvideosrc.c: + * sys/applemedia/celvideosrc.h: + celvideosrc: update e-mail address + +2010-11-04 18:59:44 +0100 Ole André Vadla Ravnås + + * sys/applemedia/Makefile.am: + * sys/applemedia/celvideosrc.c: + * sys/applemedia/celvideosrc.h: + * sys/applemedia/iphonecamerasrc.c: + * sys/applemedia/iphonecamerasrc.h: + * sys/applemedia/plugin.m: + applemedia: rename iphonecamerasrc to celvideosrc + This is in order to improve consistency with the other three sources. + +2010-11-04 17:58:36 +0100 Ole André Vadla Ravnås + + * sys/applemedia/avfvideosrc.m: + avfvideosrc: don't explicitly empty the buffer queue + We're holding the only reference to it so there's no need to explicitly + empty it right before letting go of our reference. + +2010-11-04 17:50:33 +0100 Ole André Vadla Ravnås + + * sys/applemedia/avfvideosrc.m: + avfvideosrc: make buffer offset start from zero + +2010-11-04 17:47:25 +0100 Ole André Vadla Ravnås + + * sys/applemedia/qtkitvideosrc.m: + qtkitvideosrc: implement zero-copy by using buffer-factory + This means we'll wrap each CoreVideo buffer inside a GstBuffer instead of + making a copy. + +2010-11-04 17:44:12 +0100 Ole André Vadla Ravnås + + * sys/applemedia/bufferfactory.h: + * sys/applemedia/bufferfactory.m: + bufferfactory: add support for wrapping CVBuffer + +2010-11-04 17:24:03 +0100 Ole André Vadla Ravnås + + * sys/applemedia/qtkitvideosrc.m: + qtkitvideosrc: fix up refcounting + Should keep a strong reference to the device, but we don't need to manage + the reference count of elements of an NSMutableArray as it takes care of + that for us. + +2010-11-04 17:16:05 +0100 Ole André Vadla Ravnås + + * sys/applemedia/qtkitvideosrc.m: + qtkitvideosrc: simplify timestamping algorithm + Aligning timestamps on duration boundaries, skipping frames and so forth + are clearly things that fall outside the scope of a video source. + +2010-11-04 14:14:09 +0100 Ole André Vadla Ravnås + + * sys/applemedia/Makefile.am: + * sys/applemedia/avfvideosrc.h: + * sys/applemedia/avfvideosrc.m: + * sys/applemedia/bufferfactory.h: + * sys/applemedia/bufferfactory.m: + * sys/applemedia/plugin.m: + applemedia: add new iOS video source based on AVFoundation + This element makes use of the documented AVFoundation framework made + available starting with iOS 4.0, and hence this means we can finally + capture video using a public API. + +2010-11-04 14:24:36 +0100 Ole André Vadla Ravnås + + * sys/applemedia/vtdec.c: + * sys/applemedia/vtenc.c: + * sys/applemedia/vth264decbin.c: + applemedia: fix stream-format caps used for H.264 + The stream-format's "avc-sample" member is now called just "avc". + +2010-11-04 14:29:37 +0100 Ole André Vadla Ravnås + + * sys/applemedia/miovideodevice.c: + * sys/applemedia/plugin.m: + * sys/applemedia/qtkitvideosrc.m: + applemedia: update e-mail addresses + +2010-11-04 14:18:29 +0100 Sebastian Dröge + + * gst/colorspace/gstcolorspace.c: + colorspace: Inverse -base version check logic to actually make sense + +2010-11-03 18:34:28 -0400 Olivier Crête + + * gst/pcapparse/gstpcapparse.c: + * gst/pcapparse/gstpcapparse.h: + pcapparse: Add support for Linux Cooked Capture (SLL) frames + +2010-11-03 18:23:27 -0400 Olivier Crête + + * gst/pcapparse/gstpcapparse.c: + pcapparse: Fail on unknown version or linktype + The element only knows about major version 2 and only decodes linktype ethernet + +2010-11-03 18:02:49 -0400 Olivier Crête + + * gst/pcapparse/gstpcapparse.c: + pcapparse: Send error GstMessage if stream doesn't have the expected magic + +2010-11-03 16:16:24 +0100 Andoni Morales Alastruey + + * gst/mpegdemux/mpegtsparse.c: + mpegtsparse: send TDT tables messages in a serialized event downstream + https://bugzilla.gnome.org/show_bug.cgi?id=633917 + +2010-11-03 15:37:48 +0100 Sebastian Dröge + + * gst/colorspace/colorspace.c: + colorspace: Add support for IYU1 + +2010-11-03 15:12:42 +0100 Sebastian Dröge + + * gst/colorspace/colorspace.c: + * gst/colorspace/gstcolorspaceorc.orc: + colorspace: First version of YUV9 and YVU9 implementation + +2010-11-03 09:20:15 +0100 Sebastian Dröge + + * gst/colorspace/colorspace.c: + * gst/colorspace/gstcolorspace.c: + colorspace: Use GST_CHECK_PLUGINS_BASE_VERSION() instead of other hacks + +2010-10-18 15:32:14 +0200 Thijs Vermeir + + * gst/mpegvideoparse/mpegpacketiser.c: + * gst/mpegvideoparse/mpegpacketiser.h: + * gst/mpegvideoparse/mpegvideoparse.c: + * gst/mpegvideoparse/mpegvideoparse.h: + mpegvideoparse: fix timestamp generation + Use information from the gop header and picture + header to calculate the picture timestamp. (time_code + and temporal_reference) and adapt to upstream timestamps if + provided. + https://bugzilla.gnome.org/show_bug.cgi?id=632222 + +2010-11-02 23:08:30 +0100 Ole André Vadla Ravnås + + * sys/applemedia/vtapi.h: + * sys/applemedia/vtdec.c: + * sys/applemedia/vtdec.h: + * sys/applemedia/vtenc.c: + * sys/applemedia/vtenc.h: + applemedia: switch vtapi to CFTypeRef style typedefs + +2010-11-02 22:53:33 +0100 Ole André Vadla Ravnås + + * sys/applemedia/celapi.h: + * sys/applemedia/cmapi.c: + * sys/applemedia/cmapi.h: + * sys/applemedia/coremediabuffer.c: + * sys/applemedia/coremediabuffer.h: + * sys/applemedia/iphonecamerasrc.c: + * sys/applemedia/iphonecamerasrc.h: + * sys/applemedia/mioapi.h: + * sys/applemedia/miovideodevice.c: + * sys/applemedia/miovideodevice.h: + * sys/applemedia/miovideosrc.c: + * sys/applemedia/miovideosrc.h: + * sys/applemedia/mtapi.h: + * sys/applemedia/vtapi.h: + * sys/applemedia/vtdec.c: + * sys/applemedia/vtdec.h: + * sys/applemedia/vtenc.c: + applemedia: support public version of CoreMedia + Also rename the relevant API so we mirror the public API more closely, and + switch to CoreFoundation CFTypeRef style typedefs. We still support the old + private CoreMedia in order to not break OS X support. + This means that vtenc and vtdec are now compatible with iOS 4.x, and in + theory also future versions of OS X, where this API may turn public like + it has on iOS. + +2010-11-02 17:46:11 +0000 Tim-Philipp Müller + + * ext/zbar/gstzbar.c: + zbar: handle more formats that start with an 8-bit Y plane + We can handle most planar YUV layouts too, as long as we don't + tell zbar about the chroma planes. + +2010-11-02 17:18:52 +0000 Tim-Philipp Müller + + * ext/zbar/gstzbar.c: + * ext/zbar/gstzbar.h: + zbar: use correct stride + Fixes detection for images with a width that's not a multiple of four. + Based on patch by: Kaj-Michael Lang + Based on patch by: Stefan Kost + https://bugzilla.gnome.org/show_bug.cgi?id=630830 + +2010-11-02 16:54:59 +0000 Tim-Philipp Müller + + * gst/colorspace/gstcolorspace.c: + colorspace: fix build with current git of gst-plugins-base + ifdef tests don't work so well if we define them in the code + above in case they aren't defined. + +2010-11-02 16:35:57 +0000 Tim-Philipp Müller + + * ext/zbar/gstzbar.c: + zbar: minor clean-up + Fix typo and use DEFAULT_FOO define for property default. + +2010-11-02 16:32:55 +0000 Tim-Philipp Müller + + * ext/zbar/gstzbar.c: + zbar: disable cache by default + Since it breaks still image bar code detection. + +2010-11-02 16:05:37 +0100 Sebastian Dröge + + * gst/colorspace/colorspace.c: + * gst/colorspace/colorspace.h: + * gst/colorspace/gstcolorspace.c: + * gst/colorspace/gstcolorspace.h: + colorspace: Add support for 8 bit paletted RGB + This needs the 8 bit paletted support from -base + which will be committed after release. Without this + the 8 bit parts are disabled. + +2010-11-02 10:24:49 -0300 Thiago Santos + + * gst/camerabin/camerabinpreview.c: + camerabin: Add missing change to previous commits + Forgot to add this change to the latest commits. This fixes the build. + +2010-11-02 09:39:49 -0300 Thiago Santos + + * gst/camerabin/camerabinpreview.c: + camerabin: Fix leaks in the preview handling + Remember to unref the bus after adding the watch. + Remember to unref the element after getting it with + gst_bin_get_by_name. + +2010-11-02 09:38:20 -0300 Lasse Laukkanen + + * gst/camerabin/gstcamerabin.c: + camerabin: Do not leak a caps + gst_caps_replace doesn't take ownership, but refs the caps. So we + unref the remaining caps. + +2010-09-24 16:28:13 -0300 Thiago Santos + + * gst/camerabin/gstcamerabin.c: + camerabin: Reset pre-night-mode stored fps when mode changes + When switching between video/still modes the pre-night-mode fps + should be reset to prevent it being used in the incorrect mode, causing + the videosource to fail configuring itself + +2010-09-21 16:23:47 +0300 Teemu Katajisto + + * tests/examples/camerabin/gst-camerabin-test.c: + examples: camerabin: add support for setting many post-processing elements + Instead of taking a single element as input for the image post + processing option, take a list of comma separated elements + that will be used. + +2010-09-20 11:54:20 -0300 Thiago Santos + + * gst/camerabin/gstcamerabin.c: + * gst/camerabin/gstcamerabin.h: + camerabin: Store app preferred capture parameters separately + Store width/height/fps for video captures in a separate variable + than the one that stores the currently used value. + This prevents the user preferences to be lost when resetting + the currently used dimensions for night mode, for example + +2010-09-20 08:42:41 -0300 Thiago Santos + + * gst/camerabin/gstcamerabin.c: + camerabin: cleanup used caps when going to NULL + Resets used caps so that camerabin doesn't try to use them + when restarting, where elements/properties might have changed + and the old caps be incompatible + +2010-09-09 10:50:59 +0300 Teemu Katajisto + + * gst/camerabin/gstcamerabin.c: + camerabin: fix priority for idle_add function + Adds a higher priority to the idle_add function for when + the image bin finished the image capture. This reduces the + delay for the application to be notified about this. + +2010-11-01 23:04:44 +0200 Stefan Kost + + * gst/selector/gstinputselector.c: + inputselector: log times in human readable form + +2010-11-01 22:40:36 +0200 Stefan Kost + + * gst/selector/gstinputselector.c: + inputselector: move reoccuring logs to LOG and remove a double info + Less debug spew in DEBUG category. No need to log pad again if we use + GST_LOG_OBJECT(pad,...). + +2010-11-01 15:53:52 +0000 Tim-Philipp Müller + + * ext/cog/gstcogorc-dist.c: + * gst/colorspace/gstcolorspaceorc-dist.c: + * gst/colorspace/gstcolorspaceorc-dist.h: + cog, colorspace: update orc backup functions for latest changes + Should fix build on systems without the latest orc. + +2010-11-01 15:53:31 +0000 Tim-Philipp Müller + + * po/af.po: + * po/az.po: + * po/bg.po: + * po/ca.po: + * po/cs.po: + * po/da.po: + * po/de.po: + * po/el.po: + * po/en_GB.po: + * po/es.po: + * po/eu.po: + * po/fi.po: + * po/fr.po: + * po/gl.po: + * po/hu.po: + * po/id.po: + * po/it.po: + * po/ja.po: + * po/ky.po: + * po/lt.po: + * po/lv.po: + * po/mt.po: + * po/nb.po: + * po/nl.po: + * po/or.po: + * po/pl.po: + * po/pt_BR.po: + * po/ro.po: + * po/ru.po: + * po/sk.po: + * po/sl.po: + * po/sq.po: + * po/sr.po: + * po/sv.po: + * po/tr.po: + * po/uk.po: + * po/vi.po: + * po/zh_CN.po: + po: update for new translations + +2010-10-31 23:46:27 +0100 Sebastian Dröge + + * gst/colorspace/colorspace.c: + * gst/colorspace/gstcolorspace.c: + colorspace: Add support for RGB15 and BGR15 + +2010-10-31 23:44:20 +0100 Sebastian Dröge + + * gst/colorspace/colorspace.c: + * gst/colorspace/gstcolorspace.c: + colorspace: Add support for RGB16 and BGR16 + +2010-10-31 23:25:57 +0100 Sebastian Dröge + + * gst/colorspace/colorspace.c: + * gst/colorspace/gstcolorspaceorc.orc: + colorspace: Add support for Y16 + +2010-10-31 23:25:40 +0100 Sebastian Dröge + + * gst/colorspace/gstcolorspaceorc.orc: + colorspace: Fix Y800 ORC getline implementation + +2010-10-31 23:07:43 +0100 Sebastian Dröge + + * gst/colorspace/colorspace.c: + * gst/colorspace/gstcolorspace.c: + * gst/colorspace/gstcolorspaceorc.orc: + colorspace: Add support for A420 + +2010-10-31 23:00:07 +0100 Sebastian Dröge + + * gst/colorspace/colorspace.c: + colorspace: Add support for Y41B + +2010-10-31 22:39:38 +0100 Sebastian Dröge + + * gst/colorspace/colorspace.c: + * gst/colorspace/colorspace.h: + * gst/colorspace/gstcolorspace.c: + * gst/colorspace/gstcolorspace.h: + colorspace: Add support for SDTV/HDTV YUV conversions + +2010-10-31 22:21:35 +0100 Sebastian Dröge + + * gst/colorspace/colorspace.c: + colorspace: Add comment for the A420 getline/putline table row + +2010-10-31 20:40:09 +0100 Sebastian Dröge + + * gst/colorspace/colorspace.c: + * gst/colorspace/colorspace.h: + colorspace: Add const to the source arrays and the getline/putline table + +2010-10-31 19:42:30 +0100 Sebastian Dröge + + * gst/colorspace/colorspace.c: + colorspace: Make fast-path transform table const + +2010-10-31 19:39:33 +0100 Sebastian Dröge + + * gst/colorspace/colorspace.c: + colorspace: Only do the I420->YUY2 conversion once per scanline in the fast path + +2010-10-29 14:08:58 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: use only upstream duration if it provides one + +2010-10-25 14:15:50 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: reflow update_bitrate code + ... which makes local variables represent real state better, and avoids + triggering unneeded updates/actions. + +2010-10-25 14:13:51 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: add some debug statements + +2010-10-28 18:51:02 +0200 Sebastian Dröge + + * gst/gaudieffects/Makefile.am: + * gst/gaudieffects/gstplugin.c: + gaudieffects: Include gstcontroller header and add the required CFLAGS + +2010-10-27 14:57:36 +0200 Luis de Bethencourt + + * gst/gaudieffects/gstburn.c: + * gst/gaudieffects/gstburn.h: + * gst/gaudieffects/gstchromium.c: + * gst/gaudieffects/gstchromium.h: + * gst/gaudieffects/gstdilate.c: + * gst/gaudieffects/gstdilate.h: + * gst/gaudieffects/gstdodge.c: + * gst/gaudieffects/gstexclusion.c: + * gst/gaudieffects/gstexclusion.h: + * gst/gaudieffects/gstplugin.c: + * gst/gaudieffects/gstsolarize.c: + * gst/gaudieffects/gstsolarize.h: + gaudieffects: made filter parameters dynamic and controllable + +2010-07-01 15:07:41 +0200 Ole André Vadla Ravnås + + * sys/winks/gstksvideodevice.c: + winks: work around shutdown deadlock + GetOverlappedResult() might never return with some drivers. Time out + after 1000 ms. We cannot really fix this without either: + 1) Controlling the streaming thread so we can do CancelIo() from that + thread. + 2) Switch to using IO completion ports. + +2010-06-11 18:04:58 +0200 Ole André Vadla Ravnås + + * sys/winks/gstksvideodevice.c: + winks: remove JPEG validation hack + This should clearly not be done in a video source. + +2010-04-20 12:05:45 +0200 Ole André Vadla Ravnås + + * sys/winks/ksvideohelpers.c: + winks: set PrioritySubClass to KSPRIORITY_NORMAL instead of 1 + In order to match the reference implementation. + +2010-04-20 11:59:23 +0200 Ole André Vadla Ravnås + + * sys/winks/gstksvideodevice.c: + winks: retry when KsCreatePin fails with ERROR_NOT_READY + Turns out that the reference implementation does this, hence we need to + mirror this behaviour. This typically happens with hardware that takes + some time to initialize. + +2009-10-26 16:09:00 +0100 Ole André Vadla Ravnås + + * sys/winks/ksvideohelpers.c: + winks: improve framerate fraction conversions + * For instance 7.5 fps should be represented as 15/2 instead of 7/1. + * Clamp AvgTimePerFrame and dwBitRate to account for rounding errors. + +2009-10-12 17:26:15 +0200 Ole André Vadla Ravnås + + * sys/winks/gstksclock.c: + * sys/winks/gstksvideodevice.c: + * sys/winks/gstksvideodevice.h: + * sys/winks/gstksvideosrc.c: + * sys/winks/kshelpers.c: + * sys/winks/kshelpers.h: + * sys/winks/ksvideohelpers.c: + winks: improve error-handling + Most important part here is special-casing "device busy" so the application + is able to provide better feedback when another application is using the + device. + +2009-09-07 16:45:57 +0200 Ole André Vadla Ravnås + + * sys/winks/gstksvideodevice.c: + * sys/winks/gstksvideodevice.h: + * sys/winks/gstksvideosrc.c: + winks: performance improvements + * Make the driver write directly into each GstBuffer to avoid memcpy(). + * Don't memset() the buffer before reusing it. + * Recycle memory by keeping two spare buffers. Two because the sink + downstream may keep a ref to the previous buffer. + Note that we align buffers on highest possible byte boundary (4096) so we + don't have to take into account what kind of alignment the driver requires. + +2009-09-07 16:09:34 +0200 Ole André Vadla Ravnås + + * sys/winks/gstksclock.c: + * sys/winks/gstksclock.h: + * sys/winks/gstksvideodevice.c: + * sys/winks/gstksvideodevice.h: + * sys/winks/gstksvideosrc.c: + * sys/winks/gstksvideosrc.h: + winks: store priv pointer instead of looking it up + +2009-08-31 19:33:30 +0200 Ole André Vadla Ravnås + + * sys/winks/gstksvideosrc.c: + winks: post error message on flow-unexpected + +2009-08-31 19:28:50 +0200 Andres Colubri + + * sys/winks/gstksvideosrc.c: + * sys/winks/gstksvideosrc.h: + winks: add property probing support + +2009-08-31 19:26:36 +0200 Ole André Vadla Ravnås + + * sys/winks/gstksvideosrc.c: + * sys/winks/ksvideohelpers.c: + * sys/winks/ksvideohelpers.h: + winks: sort devices that look like cameras first + +2009-08-31 19:25:02 +0200 Knut Inge Hvidsten + + * sys/winks/ksvideohelpers.c: + winks: provide guessed pixel-aspect-ratio in caps + +2009-08-31 19:23:40 +0200 Ole André Vadla Ravnås + + * sys/winks/gstksclock.c: + winks: only try to change state when actually open + +2009-08-31 19:22:40 +0200 Ole André Vadla Ravnås + + * sys/winks/kshelpers.c: + * sys/winks/kshelpers.h: + * sys/winks/ksvideohelpers.c: + winks: ignore unsupported formats + +2010-10-28 16:14:34 +0200 Ole André Vadla Ravnås + + * sys/winks/gstksvideodevice.c: + * sys/winks/gstksvideosrc.c: + winks: adjust a couple of logging severities + Should clearly not be considered warnings, as they're quite common. + +2010-10-27 18:30:11 +0100 Ole André Vadla Ravnås + + * configure.ac: + * sys/Makefile.am: + * sys/applemedia/Makefile.am: + * sys/applemedia/celapi.c: + * sys/applemedia/celapi.h: + * sys/applemedia/cmapi.c: + * sys/applemedia/cmapi.h: + * sys/applemedia/coremediabuffer.c: + * sys/applemedia/coremediabuffer.h: + * sys/applemedia/coremediactx.c: + * sys/applemedia/coremediactx.h: + * sys/applemedia/corevideobuffer.c: + * sys/applemedia/corevideobuffer.h: + * sys/applemedia/cvapi.c: + * sys/applemedia/cvapi.h: + * sys/applemedia/dynapi-internal.h: + * sys/applemedia/dynapi.c: + * sys/applemedia/dynapi.h: + * sys/applemedia/iphonecamerasrc.c: + * sys/applemedia/iphonecamerasrc.h: + * sys/applemedia/mioapi.c: + * sys/applemedia/mioapi.h: + * sys/applemedia/miovideodevice.c: + * sys/applemedia/miovideodevice.h: + * sys/applemedia/miovideosrc.c: + * sys/applemedia/miovideosrc.h: + * sys/applemedia/mtapi.c: + * sys/applemedia/mtapi.h: + * sys/applemedia/plugin.m: + * sys/applemedia/qtkitvideosrc.h: + * sys/applemedia/qtkitvideosrc.m: + * sys/applemedia/vtapi.c: + * sys/applemedia/vtapi.h: + * sys/applemedia/vtdec.c: + * sys/applemedia/vtdec.h: + * sys/applemedia/vtenc.c: + * sys/applemedia/vtenc.h: + * sys/applemedia/vth264decbin.c: + * sys/applemedia/vth264decbin.h: + * sys/applemedia/vth264encbin.c: + * sys/applemedia/vth264encbin.h: + * sys/applemedia/vtutil.c: + * sys/applemedia/vtutil.h: + applemedia: New plugin for Apple multimedia APIs + Provides the following elements: + qtkitvideosrc: OS X video source relying on the QTKit API. Comes with + hard-coded caps as the API does not provide any way of querying for + formats supported by the hardware. Hasn't been tested a lot, but seems + to work. + miovideosrc: OS X video source which uses the undocumented/private + CoreMediaIOServices API, which is also the one used by iChat. + Present on latest version of Leopard and all versions of Snow Leopard. + Has been tested extensively with built-in cameras and TANDBERG's + PrecisionHD USB camera. + vtenc, vtdec: Generic codec wrappers which make use of the undocumented/ + private VideoToolbox API on OS X and iOS. List of codecs are currently + hard-coded to H.264 for vtenc, and H.264 + JPEG for vtdec. Can easily be + expanded by adding new entries to the lists, but haven't yet had time to + do that. Should probably also implement probing as available codecs depend + on the OS and its version, and there doesn't seem to be any way to + enumerate the available codecs. + vth264decbin, vth264encbin: Wrapper bins to make it easier to use + vtdec_h264/vtenc_h264 in live scenarios. + iphonecamerasrc: iPhone camera source relying on the undocumented/private + Celestial API. Tested on iOS 3.1 running on an iPhone 3GS. Stops working + after a few minutes, presumably because of a resource leak. Needs some + love. + Note that the iOS parts haven't yet been ported to iOS 4.x. + +2010-10-28 11:43:34 +0100 Sebastian Pölsterl + + * gst/mpegdemux/mpegtsparse.c: + mpegtsparse: Add tag event emission. Fixes #627253 + +2010-10-27 13:17:10 +0100 Jan Schmidt + + * common: + Automatic update of common submodule + From 7bbd708 to 011bcc8 + +2010-10-21 16:06:08 -0300 Thiago Santos + + * gst/camerabin/gstcamerabin.c: + camerabin: Check the source scene mode when creating it + As camerabin only gets notified of the changes from the + video source element, it should query the initial value + once the source is created so it initializes itself + correctly. + +2010-10-20 00:07:01 +0100 Tim-Philipp Müller + + * tests/check/Makefile.am: + tests: fix distcheck a bit more + Dist elements/parser.h header file, which fixes the 'make check' build. + +2010-10-19 23:40:36 +0100 Tim-Philipp Müller + + * tests/check/elements/valve.c: + tests: fix valve unit test + gst_buffer_pad_alloc() needs simple caps or NULL caps, + ANY caps are not allowed. + +2010-10-19 23:25:54 +0100 Tim-Philipp Müller + + * gst/audioparsers/gstdcaparse.c: + dcaparse: init variable to make osx build bot happy + gstdcaparse.c: In function 'gst_dca_parse_check_valid_frame': + gstdcaparse.c:246: warning: 'best_sync' may be used uninitialized in this function + +2010-10-19 00:15:20 +0100 Tim-Philipp Müller + + * gst/audioparsers/Makefile.am: + * gst/audioparsers/gstdcaparse.c: + * gst/audioparsers/gstdcaparse.h: + * gst/audioparsers/plugin.c: + audioparsers: add very basic dts/dca parser + Still some issues, e.g. with seekable queries in totem, but also + processing already-chunked input (created with matroskademux ! gdppay). + +2010-10-19 16:23:23 +0300 Stefan Kost + + * ext/amrwbenc/gstamrwbenc.c: + * ext/apexsink/gstapexsink.c: + * ext/artsd/gstartsdsink.c: + * ext/audiofile/gstafsink.c: + * ext/audioresample/gstaudioresample.c: + * ext/bz2/gstbz2dec.c: + * ext/bz2/gstbz2enc.c: + * ext/cdaudio/gstcdaudio.c: + * ext/cog/gstcogmse.c: + * ext/cog/gstlogoinsert.c: + * ext/dc1394/gstdc1394.c: + * ext/dirac/gstdiracenc.cc: + * ext/directfb/dfbvideosink.c: + * ext/divx/gstdivxenc.c: + * ext/dts/gstdtsdec.c: + * ext/faac/gstfaac.c: + * ext/jack/gstjackaudiosink.c: + * ext/jack/gstjackaudiosrc.c: + * ext/kate/gstkatedec.c: + * ext/kate/gstkateenc.c: + * ext/kate/gstkatetag.c: + * ext/kate/gstkatetiger.c: + * ext/kate/gstkateutil.c: + * ext/libfame/gstlibfame.c: + * ext/modplug/gstmodplug.cc: + * ext/mpeg2enc/gstmpeg2encoptions.cc: + * ext/mplex/gstmplexjob.cc: + * ext/musicbrainz/gsttrm.c: + * ext/mythtv/gstmythtvsrc.c: + * ext/nas/nassink.c: + * ext/neon/gstneonhttpsrc.c: + * ext/ofa/gstofa.c: + * ext/opencv/gstedgedetect.c: + * ext/opencv/gstfaceblur.c: + * ext/opencv/gstfacedetect.c: + * ext/opencv/gstpyramidsegment.c: + * ext/opencv/gsttemplatematch.c: + * ext/resindvd/resindvdbin.c: + * ext/resindvd/resindvdsrc.c: + * ext/sdl/sdlvideosink.c: + * ext/shout/gstshout.c: + * ext/snapshot/gstsnapshot.c: + * ext/sndfile/gstsfsink.c: + * ext/soundtouch/gstpitch.cc: + * ext/tarkin/gsttarkindec.c: + * ext/tarkin/gsttarkinenc.c: + * ext/xvid/gstxvidenc.c: + * ext/zbar/gstzbar.c: + various (ext): add missing G_PARAM_STATIC_STRINGS flags + Canonicalize property names as needed. + +2010-10-19 16:24:12 +0300 Stefan Kost + + * gst/videosignal/gstvideoanalyse.c: + videoanalyse: fix copy'n'paste off by one for param spec flags change + +2010-10-19 13:43:14 +0300 Stefan Kost + + * gst/asfmux/gstasfmux.c: + * gst/autoconvert/gstautoconvert.c: + * gst/camerabin/camerabinimage.c: + * gst/camerabin/camerabinvideo.c: + * gst/dccp/gstdccpclientsink.c: + * gst/dccp/gstdccpclientsrc.c: + * gst/dccp/gstdccpserversink.c: + * gst/dccp/gstdccpserversrc.c: + * gst/dtmf/gstdtmfsrc.c: + * gst/dtmf/gstrtpdtmfdepay.c: + * gst/dtmf/gstrtpdtmfsrc.c: + * gst/filter/gstiir.c: + * gst/freeze/gstfreeze.c: + * gst/games/gstpuzzle.c: + * gst/gaudieffects/gstburn.c: + * gst/gaudieffects/gstchromium.c: + * gst/gaudieffects/gstdilate.c: + * gst/gaudieffects/gstdodge.c: + * gst/gaudieffects/gstexclusion.c: + * gst/gaudieffects/gstsolarize.c: + * gst/h264parse/gsth264parse.c: + * gst/id3tag/gstid3mux.c: + * gst/librfb/gstrfbsrc.c: + * gst/mixmatrix/mixmatrix.c: + * gst/mpeg4videoparse/mpeg4videoparse.c: + * gst/mpegdemux/flutspatinfo.c: + * gst/mpegdemux/flutspmtinfo.c: + * gst/mpegdemux/flutspmtstreaminfo.c: + * gst/mpegdemux/gstmpegtsdemux.c: + * gst/mpegdemux/mpegtsparse.c: + * gst/mpegtsmux/mpegtsmux.c: + * gst/mve/gstmvemux.c: + * gst/nsf/gstnsf.c: + * gst/passthrough/gstpassthrough.c: + * gst/pcapparse/gstpcapparse.c: + * gst/playondemand/gstplayondemand.c: + * gst/pnm/gstpnmenc.c: + * gst/qtmux/gstqtmoovrecover.c: + * gst/real/gstrealaudiodec.c: + * gst/real/gstrealvideodec.c: + * gst/rtpmux/gstrtpmux.c: + * gst/scaletempo/gstscaletempo.c: + * gst/sdp/gstsdpdemux.c: + * gst/selector/gstinputselector.c: + * gst/selector/gstoutputselector.c: + * gst/smooth/gstsmooth.c: + * gst/speed/gstspeed.c: + * gst/stereo/gststereo.c: + * gst/subenc/gstsrtenc.c: + * gst/vbidec/gstvbidec.c: + * gst/videodrop/gstvideodrop.c: + * gst/videomeasure/gstvideomeasure_collector.c: + * gst/videomeasure/gstvideomeasure_ssim.c: + * gst/videosignal/gstvideoanalyse.c: + * gst/videosignal/gstvideodetect.c: + * gst/videosignal/gstvideomark.c: + various (gst): add missing G_PARAM_STATIC_STRINGS flags + Canonicalize property names as needed. + +2010-10-19 15:30:02 +0300 Stefan Kost + + * ext/artsd/gstartsdsink.c: + * ext/audiofile/gstafsink.c: + * ext/shout/gstshout.c: + * gst/smooth/gstsmooth.c: + various: wrap property registration and add a single fixme for long desc. + +2010-10-19 15:06:36 +0300 Stefan Kost + + * gst/pnm/gstpnmenc.c: + pnmenc: remove stray " in doc comment + +2010-10-19 13:44:25 +0300 Stefan Kost + + * gst/dtmf/gstdtmfsrc.c: + dtmfsrc: remove DEBUG_FUNCPTR from gobject vmethods + +2010-10-08 19:33:16 -0300 Thiago Santos + + * tests/check/elements/jifmux.c: + tests: jifmux: Adds tests for the new tags + Adds tests for the new exif tags in -base + +2010-10-09 17:36:07 -0700 David Schleef + + * ext/dirac/gstdiracenc.cc: + * ext/schroedinger/gstschroenc.c: + * ext/vp8/gstvp8dec.c: + * ext/vp8/gstvp8enc.c: + * gst-libs/gst/video/gstbasevideocodec.c: + * gst-libs/gst/video/gstbasevideocodec.h: + * gst-libs/gst/video/gstbasevideodecoder.c: + * gst-libs/gst/video/gstbasevideodecoder.h: + * gst-libs/gst/video/gstbasevideoencoder.c: + * gst-libs/gst/video/gstbasevideoencoder.h: + basevideo: Move common fields/functions to basecodec + +2010-09-28 18:21:57 +0300 Kaj-Michael Lang + + * ext/zbar/gstzbar.c: + * ext/zbar/gstzbar.h: + zbar: Make scanner cache optional + +2010-10-14 23:04:15 +0300 Stefan Kost + + * gst-libs/gst/interfaces/photography.h: + photography: actualy use the enum in the vmethods + If we introduce a new GstPhotographyNoiseReduction, lets also use it + in the vmethods + +2010-10-14 23:03:19 +0300 Stefan Kost + + * gst-libs/gst/interfaces/photography.h: + photography: retab interface struct fields + +2010-10-14 12:32:05 -0700 David Schleef + + * common: + Automatic update of common submodule + From 5a668bf to 7bbd708 + +2010-10-14 14:07:48 -0300 Thiago Santos + + * gst/camerabin/gstcamerabin-enum.h: + camerabin: Remove unused entry + Remove camerabin unused enum entry + +2010-10-14 13:41:00 -0300 Thiago Santos + + * gst-libs/gst/interfaces/photography.h: + photography: Avoid breaking ABI + Move the newly added functions/fields to the end of the structs + +2010-10-14 11:45:55 +0200 Thijs Vermeir + + * gst/mpegvideoparse/mpegpacketiser.c: + mpegvideoparse: accelerate search for start code + As the startcode always starts with 0x000001 some iterations + can be skipped if values > 1 are detected. + ~ 70% faster on HD video stream. + https://bugzilla.gnome.org/show_bug.cgi?id=632130 + +2010-10-14 16:48:21 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstac3parse.c: + ac3parse: properly parse e-ac3 frame header + Also add a few debug statements. + +2010-10-14 11:24:42 +0200 Mark Nauwelaerts + + * ext/faad/gstfaad.c: + faad: reflow opening and closing decoder + In particular, this reconfigures quite forcefully when renegotiation is needed. + Fixes #631501. + +2010-10-13 17:47:29 +0200 Mark Nauwelaerts + + * gst/qtmux/gstqtmux.c: + qtmux: prevent infinite loop when adjusting framerate + Fixes #632070. + +2010-10-12 21:46:37 -0300 Thiago Santos + + * tests/check/elements/jifmux.c: + tests: jifmux: update tests to the new datetime api + Update jifmux tests to use new gstdatetime API in core + +2010-10-12 09:37:56 -0300 Thiago Santos + + * gst/geometrictransform/Makefile.am: + * gst/geometrictransform/gstrotate.c: + * gst/geometrictransform/gstrotate.h: + * gst/geometrictransform/plugin.c: + geometrictransform: Adds rotate element + Adds a new rotate element to geometrictransform. It still + needs some work. But this is a good starting point. + Based on patch from Bert Douglas + +2010-10-13 11:00:01 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstflacparse.c: + flacparse: tweak setting buffer metadata; avoid timestamp jitter + Fixes #631993. + +2010-10-12 18:17:27 +0200 Mark Nauwelaerts + + * ext/faad/gstfaad.c: + * ext/faad/gstfaad.h: + faad: cater for renegotiation + At least, whenever either stream (e.g. ADTS) or upstream provides necessary + info for doing so. + Fixes #631501. + +2010-10-12 18:07:49 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstaacparse.c: + * gst/audioparsers/gstaacparse.h: + aacparse: streamline src caps setting + In particular, also set src caps whenever changes in stream warrant doing so. + +2010-10-12 16:13:07 +0100 Tim-Philipp Müller + + * sys/directdraw/gstdirectdrawsink.c: + directdrawsink: port GstXOverlay bits to new API + Don't use deprecated API. + +2010-10-12 16:35:55 +0200 Mark Nauwelaerts + + * tests/check/elements/faac.c: + faac: adjust unit test to faac modified output + +2010-10-10 12:32:33 +0100 Tim-Philipp Müller + + * tests/check/Makefile.am: + checks: remove variables from Makefile.am that aren't set + Remove some stuff that was copy'n'pasted from core but + doesn't apply here. The following vars aren't set: + CHECK_CFLAGS, CHECK_LIBS, GST_OBJ_CFLAGS, GST_OBJ_LIBS, + so we may just as well remove them. + +2010-10-12 12:11:37 +0200 Sebastian Dröge + + * tests/examples/camerabin/gst-camera.c: + examples: Fix compilation with GTK+ 3.0 + +2010-10-12 10:28:33 +0200 Sebastian Dröge + + * tests/check/elements/flacparse.c: + flacparse: Adjust unit tests to new flacparse behaviour + Garbage after frames is now included in the frames because flacparse + has no easy way to detect the real end of a frame. Decoders are + expected to everything after the frame because only decoding the + bitstream will reveal the real end of the frame. + Fixes bug #631814. + +2010-10-12 10:27:53 +0200 Sebastian Dröge + + * gst/audioparsers/gstflacparse.c: + flacparse: Don't drop the last frame if it is followed by garbage + See bug #631814. + +2010-10-11 17:49:46 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: perform bitrate handling and posting after newsegment sending + +2010-10-11 17:36:19 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: immediately post subclass provided bitrate + +2010-10-11 17:06:48 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstflacparse.c: + flacparse: fix parsing with unknown framesizes + Fixes #631814 (mostly). + +2010-10-11 17:05:28 +0200 Mark Nauwelaerts + + * ext/faac/gstfaac.c: + * ext/faac/gstfaac.h: + faac: handle trailing encoder output + +2010-10-11 14:25:41 +0200 Sebastian Dröge + + * ext/gsettings/gstswitchsrc.c: + switchsrc: Set the GST_ELEMENT_IS_SOURCE flag + +2010-09-13 19:07:55 +0100 Damien Lespiau + + * sys/dvb/gstdvbsrc.c: + dvbsrc: Fix example usage, bandwidth=8 not 8MHz + The bandwidth property is enum that takes the values 8, 7, 6, AUTO not + 8MHz. + +2010-10-08 17:01:29 -0400 Olivier Crête + + * sys/shm/shmalloc.h: + shm: Add C++ protection + Add c++ protection in the relevant places + +2010-10-08 12:44:45 -0700 David Schleef + + * common: + Automatic update of common submodule + From c4a8adc to 5a668bf + +2010-10-08 12:55:29 +0200 Sebastian Dröge + + * common: + Automatic update of common submodule + From 5e3c9bf to c4a8adc + +2010-10-07 23:37:36 +0200 Sebastian Dröge + + * gst/audioparsers/gstflacparse.c: + flacparse: Simplify frame header parsing by using lookup tables + Based on a patch by Felipe Contreras. + See bug #631200. + +2010-10-07 23:28:08 +0200 Sebastian Dröge + + * gst/audioparsers/gstflacparse.c: + * gst/audioparsers/gstflacparse.h: + flacparse: Don't parse the complete FLAC frames but only look for valid frame headers + Thanks to Felipe Contreras for the suggestion. This is partially + based on his patches and makes flacparse more than 3.5 times faster. + Looking for valid frame headers is unlikely to give false positives + because every frame header is at least 9 bytes long, contains a + 14 bit sync code and a 8 bit checksum over the first 8 bytes. + Fixes bug #631200. + +2010-10-07 11:59:30 +0200 Mark Nauwelaerts + + * gst/sdp/gstsdpdemux.c: + sdpdemux: workaround internal rtspsrc failing state change + Fixes #630046. + +2010-10-07 10:34:48 +0200 Sebastian Dröge + + * gst/rawparse/Makefile.am: + * gst/rawparse/gstaudioparse.c: + * gst/rawparse/gstaudioparse.h: + audioparse: Add support for setting the channel-positions + +2010-10-06 18:32:51 +0200 Sebastian Dröge + + * gst/audioparsers/gstflacparse.c: + flacparse: Really post tags only after the initial newsegment event + The first newsegment event will be send by the first call to + gst_base_parse_push_buffer() if necessary, posting the tags + before that is not a good idea. Instead do it from the + GstBaseParse::pre_push_buffer vfunc. + +2010-10-06 16:54:16 +0200 Sebastian Dröge + + * gst/coloreffects/gstchromahold.c: + chromahold: Fix hue calculation for red colors + Also make the calculation much more accurate... + +2010-10-06 15:21:09 +0200 Sebastian Dröge + + * gst/coloreffects/gstchromahold.c: + chromahold: Make everything greyscale if the target color is grey + +2010-10-06 11:55:34 +0200 Sebastian Dröge + + * gst/coloreffects/Makefile.am: + * gst/coloreffects/gstchromahold.c: + * gst/coloreffects/gstchromahold.h: + * gst/coloreffects/gstplugin.c: + chromahold: Add chromahold color effect + This effect converts all colors except a single one to + grey. The color is selected by an RGB triple and a + tolerance for the color matching in hue degree can be specified. + +2010-10-05 17:04:10 +0200 Mark Nauwelaerts + + * gst/sdp/gstsdpdemux.c: + sdpdemux: fix and reflow some exits + +2010-10-05 16:56:49 +0200 Mark Nauwelaerts + + * gst/sdp/gstsdpdemux.c: + sdpdemux: error out if no streams found in sdp message + +2010-10-05 16:47:51 +0200 Mark Nauwelaerts + + * gst/sdp/gstsdpdemux.c: + sdpdemux: unbreak standard manager setup + +2010-10-05 11:44:48 +0100 Tim-Philipp Müller + + * tests/check/elements/.gitignore: + .gitignore: ignore more unit test binaries + +2010-10-05 11:42:42 +0100 Tim-Philipp Müller + + * Makefile.am: + * configure.ac: + * docs/plugins/gst-plugins-bad-plugins-docs.sgml: + * docs/plugins/inspect/plugin-alsaspdif.xml: + * ext/Makefile.am: + * ext/alsaspdif/Makefile.am: + * ext/alsaspdif/alsaspdifsink.c: + * ext/alsaspdif/alsaspdifsink.h: + * gst-plugins-bad.spec.in: + * m4/Makefile.am: + * m4/gst-alsa.m4: + alsaspdif: remove alsaspdifsink element + Remove alsaspdifsink, it's not needed any longer. alsasink in -base + has been able to handle SPDIF for a while now. + +2010-10-05 11:17:52 +0100 Tim-Philipp Müller + + * gst/audioparsers/gstbaseparse.c: + Revert "baseparse: add skip property" + This reverts commit b5a3d60363d837a10f0533c141ec93d10b742312. + Reverting this for now, since no one really seems to remember why this + property exists or what it could possibly be good for. It seems to have + been in the original mp3parse since the beginning of time and was back- + ported from there. + +2010-10-04 10:41:52 +0200 Sebastian Dröge + + * gst/audioparsers/gstflacparse.c: + flacparse: Fix uninitialized variable compiler warnings + These warnings are wrong, the variables are only used if they were + initialized by the bit reader. + +2010-09-14 02:48:58 +0300 Felipe Contreras + + * gst/audioparsers/gstflacparse.c: + flacparse: fix picture parsing + Signed-off-by: Felipe Contreras + +2010-10-03 23:54:49 +0200 Sebastian Dröge + + * gst/audioparsers/gstflacparse.c: + flacparse: Push tags before the header buffers are pushed + +2010-08-02 20:50:21 +0300 Felipe Contreras + + * gst/audioparsers/gstflacparse.c: + flacparse: trivial caps fix + Signed-off-by: Felipe Contreras + +2010-10-03 23:45:46 -0300 Thiago Santos + + * gst/qtmux/gstqtmux.c: + qtmux: Add G_PARAM_STATIC_STRINGS + Add G_PARAM_STATIC_STRINGS to qtmux properties + +2010-10-03 23:14:53 -0300 Thiago Santos + + * tests/check/Makefile.am: + tests: valve: Fix tests build + Adds missing cflags/libs to valve check test to + fix build + +2010-10-03 23:50:29 +0200 Sebastian Dröge + + * gst/audioparsers/gstbaseparse.c: + audioparser: Let the format string agree with the parameters to fix compiler warning + +2010-10-03 15:55:22 +0200 Sebastian Dröge + + * sys/vdpau/mpeg/gstvdpmpegdec.c: + vdpau: Check return values of the bitreader functions + +2010-10-03 15:41:20 +0200 Sebastian Dröge + + * gst/audioparsers/gstac3parse.c: + ac3parse: Use unchecked versions of the bitreader get functions + We didn't check the return values anyway... + +2010-09-28 13:52:29 +0300 Stefan Kost + + * gst/valve/gstvalve.c: + valve: no need to ref the object in _chain + Don't ref the pad in chain, like elsewhere + +2010-09-22 15:44:43 +0530 Arun Raghavan + + * gst/audioparsers/gstbaseparse.c: + baseparse: Fix debug output + We lose the reference to the buffer after gst_pad_push(), so the debug + print should happen before. + https://bugzilla.gnome.org/show_bug.cgi?id=622276 + +2010-10-01 12:34:55 +0200 Mark Nauwelaerts + + * tests/check/Makefile.am: + * tests/check/elements/flacparse.c: + * tests/check/elements/parser.c: + * tests/check/elements/parser.h: + audioparsers: add flacparse unit test + ... and tweak parser test helper in the process. + +2010-09-29 16:12:42 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: support reverse playback + ... in pull mode or upstream driven. + +2010-09-27 12:16:43 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: remove done TODOs and update documentation + +2010-09-25 14:40:54 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: use determined seekability in answering SEEKING query + +2010-09-25 14:32:06 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: add skip property + +2010-09-25 13:59:39 +0200 Mark Nauwelaerts + + * tests/check/Makefile.am: + * tests/check/elements/ac3parse.c: + * tests/check/elements/mpegaudioparse.c: + audioparsers: add ac3parse and mpegaudioparse unit test + +2010-09-25 13:59:18 +0200 Mark Nauwelaerts + + * gst/audioparsers/Makefile.am: + * gst/audioparsers/gstmpegaudioparse.c: + * gst/audioparsers/gstmpegaudioparse.h: + * gst/audioparsers/plugin.c: + mpegaudioparse: initial version + ... adequately equivalent to mp3parse, so lets boldly set it + to higher rank. + +2010-09-25 14:01:07 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstaacparse.c: + aacparse: set minimum frame size at _start + ... rather than one time at _init. + +2010-09-25 13:50:51 +0200 Mark Nauwelaerts + + * tests/check/Makefile.am: + * tests/check/elements/aacparse.c: + * tests/check/elements/aacparse_data.h: + * tests/check/elements/amrparse.c: + * tests/check/elements/amrparse_data.h: + * tests/check/elements/parser.c: + * tests/check/elements/parser.h: + audioparsers: refactor existing unit tests using common helper + +2010-09-22 15:07:09 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstaacparse.c: + * gst/audioparsers/gstac3parse.c: + * gst/audioparsers/gstamrparse.c: + * gst/audioparsers/gstbaseparse.c: + * gst/audioparsers/gstbaseparse.h: + baseparse: use _set_frame_props to configure frame lead_in and lead_out + ... provided a corresponding decoder with sufficient leading and following + frames to carry out full decoding for a particular segment. + +2010-09-22 14:13:17 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstaacparse.c: + * gst/audioparsers/gstac3parse.c: + * gst/audioparsers/gstamrparse.c: + * gst/audioparsers/gstbaseparse.c: + * gst/audioparsers/gstbaseparse.h: + * gst/audioparsers/gstflacparse.c: + baseparse: use _set_duration to configure duration update interval + ... as it logically belongs there as one or the other; either subclass + can provide a duration, or an estimate must be made (reguarly updated). + +2010-09-22 13:55:20 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: localize use of provided fps information + +2010-09-22 12:13:12 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: seek table and accurate seek support + +2010-09-21 13:57:10 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: proper and more extended segment and seek handling + That is, loop pause handling, segment seek support, newsegment for gaps, etc + +2010-09-21 10:57:04 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + * gst/audioparsers/gstbaseparse.h: + baseparse: add index support + +2010-09-21 09:59:56 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: refactor state reset + +2010-09-20 16:39:37 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: prevent indefinite resyncing + +2010-09-20 13:57:55 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: specific EOS handling if no output so far + +2010-09-20 13:31:57 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: adjust _set_frame_prop documentation and set default as claimed + +2010-09-20 13:30:54 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: fix bitrate copy-and-paste and update heuristic + +2010-09-17 18:33:29 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: post duration message if average bitrates is updated + +2010-09-17 18:24:22 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstaacparse.c: + * gst/audioparsers/gstbaseparse.c: + * gst/audioparsers/gstbaseparse.h: + baseparse: remove is_seekable vmethod and use a set_seek instead + Seekability, like duration, etc is unlikely to change (frequently), and + the default assumption covers most cases, so let subclass set when needed. + At the same time, allow subclass to indicate if it has seek-metadata (table) + available, and possibly have it provide an average bitrate. + +2010-09-17 17:35:40 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstac3parse.c: + ac3parse: remove redundant default is_seekable + +2010-09-17 17:21:46 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + * gst/audioparsers/gstbaseparse.h: + baseparse: add another hook for subclass prior to pushing buffer + ... and allow subclass to perform custom segment clipping, or to + emit tags or messages at this time. + +2010-09-17 17:19:37 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: 0 converts to 0 by default + +2010-09-16 18:56:46 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + * gst/audioparsers/gstbaseparse.h: + basepase: refactor conversion using helper function and export default convert + +2010-09-16 18:35:47 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: streamline query handling + +2010-09-16 11:51:20 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + * gst/audioparsers/gstbaseparse.h: + baseparse: cleanup struct and remove unused member + +2010-08-16 11:04:37 +0200 Mark Nauwelaerts + + * gst/audioparsers/plugin.c: + audioparsers: increase ranks to enable auto-plugging + Because we can, and should, have some shakedown testing before having + these make it into -good later on ... + +2010-09-22 16:07:24 +0530 Arun Raghavan + + * gst/audioparsers/gstbaseparse.c: + baseparse: Allow chaining of subclass event handlers + This allows the child class to chain its event handler with + GstBaseParse, so that subclasses don't have to duplicate all the default + event handling logic. + https://bugzilla.gnome.org/show_bug.cgi?id=622276 + +2010-09-30 17:48:35 -0400 Olivier Crête + + * tests/check/elements/valve.c: + tests: Fix caps leak in the valve test + +2010-09-30 17:24:29 -0400 Olivier Crête + + * tests/check/Makefile.am: + * tests/check/elements/.gitignore: + * tests/check/elements/valve.c: + valve: Add unit tests + Add a unit test for the valve element. + +2010-09-30 16:26:19 -0400 Olivier Crête + + * gst/valve/gstvalve.c: + * gst/valve/gstvalve.h: + valve: Make the drop variable into an atomic. + Using an atomic allows us to avoid locking the whole object all time time. + As suggested by Stefan Kost. + +2010-09-30 16:22:04 -0400 Olivier Crête + + * gst/valve/gstvalve.c: + valve: Correctly set the DISCONT flag after dropping buffers + +2010-09-30 16:16:47 -0400 Olivier Crête + + * gst/valve/gstvalve.c: + valve: Remove superflous checking casts + +2010-09-30 16:13:23 -0400 Olivier Crête + + * gst/valve/gstvalve.c: + valve: Fix style, improve comments + Minor improvements to the comments and break a few overly long lines + +2010-09-30 16:07:29 -0400 Olivier Crête + + * gst/rtpmux/gstrtpdtmfmux.c: + * gst/rtpmux/gstrtpmux.c: + rtpmux: Improve documentation + Add an example pipeline, and try to explain a bit more what it does. + +2010-09-29 17:34:00 -0300 Thiago Santos + + * gst/camerabin/gstcamerabin.c: + camerabin: Do not wrongly fail when starting a capture + If the elements are in NULL/READY and changing state to + PAUSED/PLAYING while a capture is started + camerabin might not set the active_bin properly causing the + capture start to fail. + This patch fixes it by checking the current and pending state + of the branches instead of only the current one + +2010-09-29 10:13:06 +0200 Mark Nauwelaerts + + * ext/faad/gstfaad.c: + faad: reverse playback; cater for decoder delay + ... thereby actually using the gather and decode queues. + +2010-09-29 10:08:17 +0200 Mark Nauwelaerts + + * ext/faad/gstfaad.c: + faad: tweak output buffer timestamping + In particular, avoid packetised input leading to initial to non-0 output ts. + +2010-09-28 16:20:50 +0200 Sebastian Dröge + + * gst/frei0r/gstfrei0r.c: + frei0r: Use static caps instead of converting strings to caps all the time + +2010-09-28 16:14:14 +0200 Sebastian Dröge + + * gst/frei0r/gstfrei0r.c: + frei0r: Fix crashes if plugins don't provide correct property information + The vertigo plugin for example claims to have 3 properties but + the 3rd property does nothing and has a NULL name. + Fixes bug #630783. + Thanks to Martti Kühne for debugging this. + +2010-09-28 14:26:11 +0300 Stefan Kost + + * gst/valve/gstvalve.c: + valve: move default: parst in the switch statement to the end + Now sure if it matters, but the previous form looks weired. + +2010-09-28 14:23:01 +0300 Stefan Kost + + * gst/valve/gstvalve.c: + valve: move debug-category registration to type init + +2010-09-28 14:22:18 +0300 Stefan Kost + + * gst/liveadder/liveadder.c: + liveadder: move debug-category registration to type init + +2010-09-28 14:17:45 +0300 Stefan Kost + + * gst/liveadder/liveadder.c: + liveadder: GST_BOILERPLATE already sets parent_class + +2010-09-28 14:16:58 +0300 Stefan Kost + + * gst/liveadder/liveadder.c: + liveadder: use base_init for pad_templates and element_details + +2010-09-28 14:15:57 +0300 Stefan Kost + + * gst/liveadder/liveadder.c: + liveadder: use G_PARAM_STATIC_STRINGS on properties + +2010-09-28 14:15:13 +0300 Stefan Kost + + * gst/valve/gstvalve.c: + valve: use G_PARAM_STATIC_STRINGS on properties + +2010-09-28 14:07:39 +0300 Stefan Kost + + * gst/valve/gstvalve.c: + valve: GST_BOILERPLATE already sets parent_class + +2010-09-28 14:08:29 +0300 Stefan Kost + + * gst/videomeasure/gstvideomeasure_collector.c: + videomeassure: GST_BOILERPLATE already sets parent_class + +2010-09-28 11:35:53 +0300 Hu Gang + + * docs/plugins/gst-plugins-bad-plugins-sections.txt: + * gst-libs/gst/interfaces/photography.c: + * gst-libs/gst/interfaces/photography.h: + * gst/camerabin/gstcamerabin-enum.h: + photography: extend photography iface + Add more color tone modes and add NoseReduction settings. + Fixes #616814. + +2010-09-26 20:41:25 +0100 Tim-Philipp Müller + + * ext/resindvd/resindvdsrc.c: + resindvdsrc: improve error messages on read erros + Provide i18n-ed error messages when a read error happens, + and point out that the error could be happening because the + DVD is scrambled. + https://bugzilla.gnome.org/show_bug.cgi?id=613633 + +2010-09-24 00:05:17 +0100 Tim-Philipp Müller + + * configure.ac: + configure: set plugin release datetime + +2010-09-25 12:33:58 +0200 Sebastian Dröge + + * ext/ofa/gstofa.c: + ofa: Call g_object_notify() after the fingerprint was created + +2010-09-25 10:46:34 +0200 Sebastian Dröge + + * gst/frei0r/gstfrei0r.c: + * gst/frei0r/gstfrei0rfilter.c: + * gst/frei0r/gstfrei0rfilter.h: + * gst/frei0r/gstfrei0rmixer.c: + * gst/frei0r/gstfrei0rmixer.h: + * gst/frei0r/gstfrei0rsrc.c: + * gst/frei0r/gstfrei0rsrc.h: + frei0r: Fix scanning of plugin subdirectories and support different vendors + The frei0r spec specifies, that plugins can be in subdirectories inside + the main plugin directories to introduce new namespaces called vendors. + +2010-09-24 22:47:01 +0200 Sebastian Dröge + + * gst/frei0r/frei0r.h: + frei0r: Update frei0r interface specification to 1.2 + +2010-09-24 22:43:51 +0200 Sebastian Dröge + + * gst/frei0r/gstfrei0r.c: + frei0r: Add support for the FREI0R_PATH environment variable + This was added in version 1.2 of the spec and replaces the default + list of directories. + +2010-09-23 14:15:08 +0300 Lasse Laukkanen + + * gst/debugutils/fpsdisplaysink.c: + fpsdisplaysink: initialize interval_ts and last_frames_* counters + Initialize interval_ts to first QOS event timestamp, otherwise the + fps statistics are printed always after one rendered frame. + Also, initialize last_frames_* counters, the values are bogus e.g. after + PLAYING-NULL-PLAYING state change. + +2010-09-24 13:29:55 +0300 Stefan Kost + + * gst/rtpmux/gstrtpdtmfmux.c: + rtpdtmfmux: remove unused variable + +2010-09-24 13:25:22 +0300 Stefan Kost + + * gst/rtpmux/gstrtpdtmfmux.c: + rtpdtmfmux: remove unused signal boilerplate + +2010-09-24 13:24:48 +0300 Stefan Kost + + * gst/rtpmux/gstrtpmux.c: + rtpmux: no need to ref pad in _chain() + +2010-09-22 23:41:32 -0300 Thiago Santos + + * tests/examples/camerabin/gst-camera.c: + camerabin: example: make gst-camera use flags + Enable all convertion flags in gst-camera example app + for safety. + Fixes #603063 + +2010-09-22 23:39:07 -0300 Thiago Santos + + * gst/camerabin/camerabinvideo.c: + * gst/camerabin/gstcamerabin-enum.c: + * gst/camerabin/gstcamerabin-enum.h: + camerabin: Adds new video-colorspace-flag to flags + Adds a new flag to allow a colorspace convertion before + the video encoder element. + Fixes #603063 + +2010-09-22 22:39:49 -0300 Thiago Santos + + * gst/camerabin/camerabingeneral.c: + * gst/camerabin/camerabinpreview.c: + * gst/camerabin/camerabinvideo.c: + * gst/camerabin/gstcamerabin.c: + camerabin: Use link_full version for disabling hierarchy check + Disable hierarchy checks when linking because we are already + handling the element adding to bins and it should be done + correctly. + +2010-09-22 21:03:56 -0300 Thiago Santos + + * gst/camerabin/camerabinvideo.c: + * gst/camerabin/gstcamerabin.c: + camerabin: Set queues to silent + We currently don't use queues' signals, so set them + to silent. + +2010-09-22 11:57:28 -0700 David Schleef + + * ext/schroedinger/gstschrodec.c: + schrodec: Fix class definition + Class structures should include parent class, not the parent + instance structure. + +2010-09-22 16:41:33 +0200 Wim Taymans + + * gst/pcapparse/gstpcapparse.c: + * gst/pcapparse/gstpcapparse.h: + pcapparse: fix weird caps code + Remove the weird (failing) code to figure out caps on the srcpad. + Add a caps property to decide what caps to put on the outgoing buffers. + Fix an event leak. + +2010-09-21 18:13:37 -0700 David Schleef + + * gst/colorspace/colorspace.c: + colorspace: quiet a GST_ERROR + +2010-09-21 19:07:05 +0200 Wim Taymans + + * gst/sdp/gstsdpdemux.c: + * gst/sdp/gstsdpdemux.h: + sdpdemux: add property to disable redirect + Add a property to avoid redirection to the rtsp-sdp:// url but instead embeds an + rtspsrc element inside sdpdemux as the session manager. + Based on patch by Marco Ballesio. + Fixes #630046 + +2010-09-21 18:45:03 +0200 Edward Hervey + + * ext/sdl/sdlvideosink.c: + sdlvideosink: Fix function prototype for touchy compilers + +2010-09-21 18:34:19 +0200 Edward Hervey + + * common: + Automatic update of common submodule + From 080e025 to 5e3c9bf + +2010-09-21 16:31:07 +0200 Edward Hervey + + * ext/sdl/sdlvideosink.c: + sdl: Port to new XOverlay API + Fixes #630253 + +2010-09-21 16:26:34 +0200 Edward Hervey + + * sys/vdpau/gstvdpsink.c: + vdpau: Use the new XOverlay API + Fixes #630254 + +2010-09-21 10:59:42 -0300 Thiago Santos + + * tests/examples/camerabin/gst-camera.c: + * tests/examples/camerabin/gst-camerabin-test.c: + camerabin: examples: do not use deprecated GstXOverlay functions + Replace the deprecated gst_x_overlay_set_xwindow_id with + gst_x_overlay_set_window_handle + Fixes #630255 + +2010-09-21 12:33:18 +0200 Sebastian Dröge + + * configure.ac: + configure: Use -DGST_DISABLE_DEPRECATED again for GIT versions + +2010-09-21 12:29:06 +0200 Sebastian Dröge + + * sys/dshowdecwrapper/gstdshowaudiodec.cpp: + * sys/dshowdecwrapper/gstdshowvideodec.cpp: + dshowdecwrapper: Don't use GST_FLOW_IS_FATAL() + And don't error out on UNEXPECTED + +2010-09-21 12:27:56 +0200 Sebastian Dröge + + * ext/spc/gstspc.c: + spc: Don't use GST_FLOW_IS_FATAL() + +2010-09-21 12:27:20 +0200 Sebastian Dröge + + * ext/mplex/gstmplex.cc: + mplex: Don't use GST_FLOW_IS_SUCCESS() + +2010-08-27 19:17:14 +0200 Sebastian Dröge + + * tests/icles/pitch-test.c: + pitch-test: Don't use deprecated GstController API + +2010-08-27 19:00:38 +0200 Sebastian Dröge + + * ext/timidity/gsttimidity.c: + timidity: Don't post an error message on the bus for UNEXPECTED + Also don't use GST_FLOW_IS_FATAL() + +2010-08-27 19:00:18 +0200 Sebastian Dröge + + * ext/timidity/gstwildmidi.c: + wildmidi: Don't use GST_FLOW_IS_FATAL() + +2010-08-27 18:58:23 +0200 Sebastian Dröge + + * ext/gme/gstgme.c: + gme: Post an error message on the bus for fatal errors + Also don't use GST_FLOW_IS_FATAL(). + +2010-08-27 18:56:23 +0200 Sebastian Dröge + + * ext/sndfile/gstsfsink.c: + sfsink: Don't use GST_FLOW_IS_FATAL() + +2010-08-27 18:52:54 +0200 Sebastian Dröge + + * gst/tta/gstttaparse.c: + ttaparse: Don't post an error message on UNEXPECTED + Also don't use GST_FLOW_IS_FATAL() + +2010-08-27 18:51:59 +0200 Sebastian Dröge + + * gst/sdp/gstsdpdemux.c: + sdpdemux: Don't use GST_FLOW_IS_SUCCESS() + +2010-08-27 18:51:24 +0200 Sebastian Dröge + + * gst/rawparse/gstrawparse.c: + rawparse: Don't use GST_FLOW_IS_FATAL() + +2010-08-27 18:50:30 +0200 Sebastian Dröge + + * gst/nuvdemux/gstnuvdemux.c: + nuvdemux: Don't use GST_FLOW_IS_FATAL() + And don't post an error message for WRONG_STATE or UNEXPECTED. + +2010-08-27 18:49:12 +0200 Sebastian Dröge + + * gst/nsf/gstnsf.c: + * gst/nsf/nes_apu.c: + nsf: Don't use GST_FLOW_IS_FATAL() + +2010-08-27 18:48:25 +0200 Sebastian Dröge + + * gst/mxf/mxfdemux.c: + mxfdemux: Don't use GST_FLOW_IS_FATAL() + +2010-08-27 18:47:03 +0200 Sebastian Dröge + + * gst/mve/gstmvedemux.c: + * gst/mve/gstmvedemux.h: + mvedemux: Add proper flow return aggregation + NOT_LINKED should only be returned if all streams returned NOT_LINKED. + +2010-08-27 18:41:06 +0200 Sebastian Dröge + + * gst/mpegdemux/gstmpegdemux.c: + * gst/mpegdemux/gstmpegtsdemux.c: + * gst/mpegdemux/mpegtsparse.c: + mpegdemux: Don't use GST_FLOW_IS_FATAL() + And fix some minor issues related to its usage. + +2010-08-27 18:36:26 +0200 Sebastian Dröge + + * gst/autoconvert/gstautoconvert.c: + autoconvert: Don't use GST_FLOW_IS_FATAL() + +2010-08-27 18:35:10 +0200 Sebastian Dröge + + * gst/audioparsers/gstbaseparse.c: + baseparse: Don't use GST_FLOW_IS_FATAL() + Also don't post an error message for UNEXPECTED and do it + for NOT_LINKED. + +2010-08-27 18:33:49 +0200 Sebastian Dröge + + * gst/asfmux/gstasfparse.c: + asfparse: Don't use GST_FLOW_IS_FATAL() + Also don't push EOS downstream on WRONG_STATE, it will be dropped anyway. + +2010-08-27 18:32:46 +0200 Sebastian Dröge + + * gst-libs/gst/video/gstbasevideodecoder.c: + basevideodecoder: Don't use GST_FLOW_IS_SUCCESS() + +2010-08-27 18:32:33 +0200 Sebastian Dröge + + * gst/aiff/aiffparse.c: + aiffparse: Don't use GST_FLOW_IS_FATAL() + +2010-09-20 21:46:49 -0300 Thiago Santos + + * gst/camerabin/gstcamerabin.c: + camerabin: Mention photography interface in docs + Add a note to docs about getting the videosource and accessing + its photography interface (in case it has it) + Fixes #616923 + +2010-08-25 14:04:59 +0300 Lasse Laukkanen + + * gst/camerabin/gstcamerabin.c: + camerabin: Adds missing variable initialization + Adds missing app_src_vid initialization + +2010-08-26 15:33:59 +0300 Teemu Katajisto + + * gst/camerabin/gstcamerabin.c: + camerabin: check state change to playing for imagebin and videobin + Properly check and handle error cases related to imagebin and + videobin state changes. + +2010-06-28 21:48:26 -0300 Thiago Santos + + * gst/camerabin/camerabinimage.c: + camerabin: Remove useless src template pad + camerabin imagebin doesn't need a src template pad. + +2010-06-21 09:34:43 -0300 Thiago Santos + + * gst/camerabin/camerabinpreview.c: + * gst/camerabin/camerabinpreview.h: + * gst/camerabin/gstcamerabin.c: + camerabin: Forward tag events to preview pipeline + Forward tag events from image pipeline to preview pipeline so + that preview elements can use capture tags information + +2010-06-21 16:17:24 +0300 Hoseok Chang + + * gst/camerabin/camerabinpreview.c: + * gst/camerabin/camerabinpreview.h: + * gst/camerabin/gstcamerabin-enum.h: + * gst/camerabin/gstcamerabin.c: + * gst/camerabin/gstcamerabin.h: + camerabin: add "preview-source-filter" property + Adds 'preview-source-filter' for adding an element to proccess + the preview images before posting them to the bus. + +2010-05-25 15:39:43 +0300 Lasse Laukkanen + + * tests/examples/camerabin/gst-camerabin-test.c: + camerabin: update tag names in test application to latest gst definitions + +2010-05-17 13:44:36 -0300 Thiago Santos + + * gst/camerabin/gstcamerabin.c: + * gst/camerabin/gstcamerabin.h: + camerabin: Make block-after-capture resetting more consistent + Adds another boolean to help controlling viewfinder blocking, + making it possible for the applications to reset the viewfinder + blocking after capture was started but before the blocking + actually happens. + +2010-05-12 21:11:27 -0300 Thiago Santos + + * gst/camerabin/gstcamerabin.c: + camerabin: Unblock the viewfinder when going to READY + Unblock the viewfinder when going to ready to avoid + blocking when setting camerabin to playing again and + attemping to capture. Keep the property as is. + +2010-09-20 17:19:33 -0300 Thiago Santos + + * gst/camerabin/gstcamerabin.c: + camerabin: add monitoring and support for photoiface zoom for video-source + Makes camerabin aware of changes in its videosource zoom property. + +2010-09-20 16:22:30 -0300 Thiago Santos + + * gst/camerabin/gstcamerabin.c: + * gst/camerabin/gstcamerabin.h: + * tests/check/elements/camerabin.c: + * tests/examples/camerabin/gst-camerabin-test.c: + camerabin: Change zoom property from int to float + Updates zoom property for a more natural type and + makes it consistent with the photography API + +2010-09-19 18:51:35 -0300 Thiago Santos + + * gst-libs/gst/interfaces/photography.c: + * gst-libs/gst/interfaces/photography.h: + photography: Add zoom property + Adds a property to set/get the zoom as a float + +2010-06-08 10:04:52 +0300 Lasse Laukkanen + + * gst/camerabin/gstcamerabin.c: + * gst/camerabin/gstcamerabin.h: + camerabin: remove caching photography interface settings + Camerabin doesn't implement photography interface, so we + don't need caching the video source properties anymore. + +2010-04-22 17:46:59 +0300 Teemu Katajisto + + * tests/examples/camerabin/Makefile.am: + * tests/examples/camerabin/gst-camera.c: + * tests/examples/camerabin/gst-camerabin-test.c: + examples: camerabin: use photoiface properties through video-source + Fixes #616923 + +2010-04-22 14:03:34 +0300 Teemu Katajisto + + * tests/check/elements/camerabin.c: + tests: camerabin: remove photoiface property/settings tests + Fixes #616923 + +2010-08-31 18:06:15 -0300 Teemu Katajisto + + * gst/camerabin/Makefile.am: + * gst/camerabin/gstcamerabin.c: + * gst/camerabin/gstcamerabinphotography.c: + * gst/camerabin/gstcamerabinphotography.h: + camerabin: remove photography interface implementation from camerabin + Remove notify signal proxy for video-source. Application can use + video-source directly from now on to get notified of property changes. + Add monitoring scene-mode property change to select lowest possible + framerate for video capture when night mode is selected. + Fixes #616923 + +2010-04-29 12:44:29 +0300 Teemu Katajisto + + * tests/examples/camerabin/gst-camerabin-test.c: + examples: camerabin: add --no-xwindow option and fix option handling + Add --no-xwindow option to not to create xwindow. Also fix zoom and + mute option types and filename string handling. + +2010-04-29 13:24:18 +0300 Lasse Laukkanen + + * gst-libs/gst/interfaces/photography.c: + * gst-libs/gst/interfaces/photography.h: + photography: Add image-preview-supported-caps interface property + Adds a readable property to gstphotography interface to query + what are the allowed preview caps supported. + Patch by Tommi Myöhänen + +2010-09-20 12:34:06 -0700 David Schleef + + * gst-libs/gst/video/gstbasevideocodec.c: + * gst-libs/gst/video/gstbasevideocodec.h: + * gst-libs/gst/video/gstbasevideoutils.h: + basevideo: Remove unused code + +2010-09-20 11:26:59 -0700 David Schleef + + * gst-libs/gst/video/gstbasevideodecoder.c: + basevideo: Remove check for old -base + +2010-09-19 19:33:40 -0700 David Schleef + + * gst-libs/gst/video/gstbasevideoencoder.c: + * gst-libs/gst/video/gstbasevideoencoder.h: + * gst-libs/gst/video/gstbasevideoutils.h: + basevideo: Add handling of GstForceKeyUnit events + +2010-09-18 19:25:49 -0700 David Schleef + + * gst/invtelecine/gstinvtelecine.c: + invtelecine: Fix name of 30p/60i pattern + +2010-09-18 19:21:47 -0700 David Schleef + + * ext/schroedinger/gstschrodec.c: + * gst-libs/gst/video/gstbasevideodecoder.c: + * gst-libs/gst/video/gstbasevideodecoder.h: + basevideodecoder: add capture pattern handling + Move typical scan_for_sync() usage into base class, which just + calls gst_adapter_masked_scan_uint32(). + +2010-09-18 19:14:36 -0700 David Schleef + + * gst-libs/gst/video/gstbasevideodecoder.c: + basevideodecoder: Don't blow away field information + Also, set field flags correctly. + +2010-09-18 17:28:48 -0700 David Schleef + + * ext/schroedinger/gstschrodec.c: + * ext/vp8/gstvp8dec.c: + * gst-libs/gst/video/gstbasevideodecoder.c: + * gst-libs/gst/video/gstbasevideodecoder.h: + * gst-libs/gst/video/gstbasevideoutils.h: + basevideo: Move deadline to frame structure + +2010-09-18 14:57:32 -0700 David Schleef + + * gst/interlace/gstinterlace.c: + interlace: Add allow-rff property. Fix timestamping + +2010-09-18 13:32:07 -0700 David Schleef + + * gst/interlace/gstinterlace.c: + interlace: merge telecine into normal operation + +2010-09-08 15:08:50 +0200 Robert Swain + + * gst/interlace/gstinterlace.c: + interlace: Add telecine support + +2010-09-17 08:43:48 +0200 Sebastian Dröge + + * configure.ac: + * ext/cog/Makefile.am: + * ext/cog/cogvirtframe.c: + * ext/cog/gstcog.c: + * ext/cog/gstcogmse.c: + cog: Allow compilation without orc + Also don't ignore --disable-orc. Fixes bug #629897. + +2010-09-14 16:17:47 -0300 Thiago Santos + + * tests/check/elements/camerabin.c: + camerabin: Adds a new test to check sequential capture of images + Adds a new test case that shoots a sequence of image capture + and check that the files are valid. + Also adds taglist checking capabilities to tests. + +2010-09-15 17:54:49 -0300 Thiago Santos + + * gst/qtmux/atoms.c: + * gst/qtmux/atoms.h: + * gst/qtmux/fourcc.h: + * gst/qtmux/gstqtmux.c: + * gst/qtmux/gstqtmux.h: + qtmux: Follow xmp serialization guidelines closer + qt and isom variants have different ways of serializing + xmp, follow these guidelines. + Those can be found in Adobe's xmp docs. + +2010-09-15 21:47:09 +0100 Tim-Philipp Müller + + * gst/colorspace/gstcolorspaceorc-dist.c: + * gst/colorspace/gstcolorspaceorc-dist.h: + colorspace: add orc-dist files + Should fix build without orc or too old orc. + +2010-09-15 17:51:26 +0100 Tim-Philipp Müller + + * gst/debugutils/gstchecksumsink.h: + checksumsink: fix up copyright in header file + +2010-09-12 14:59:42 +0100 Tim-Philipp Müller + + * pkgconfig/gstreamer-libs-uninstalled.pc.in: + * pkgconfig/gstreamer-libs.pc.in: + * pkgconfig/gstreamer-plugins-uninstalled.pc.in: + * pkgconfig/gstreamer-plugins.pc.in: + pkgconfig: remove some old unused files from 0.8 days + +2010-09-15 18:38:03 +0300 Stefan Kost + + * Makefile.am: + metadata: add removed files to cruft vars + +2010-09-15 18:13:55 +0300 Stefan Kost + + * tests/check/elements/jifmux.c: + tests: add missing stdio include + +2010-09-15 18:10:33 +0300 Stefan Kost + + * configure.ac: + * docs/plugins/Makefile.am: + * docs/plugins/gst-plugins-bad-plugins-docs.sgml: + * docs/plugins/gst-plugins-bad-plugins-sections.txt: + * docs/plugins/inspect/plugin-metadata.xml: + * ext/Makefile.am: + * ext/metadata/.gitignore: + * ext/metadata/Makefile.am: + * ext/metadata/README: + * ext/metadata/TODO: + * ext/metadata/gstbasemetadata.c: + * ext/metadata/gstbasemetadata.h: + * ext/metadata/gstmetadata.c: + * ext/metadata/gstmetadatademux.c: + * ext/metadata/gstmetadatademux.h: + * ext/metadata/gstmetadatamux.c: + * ext/metadata/gstmetadatamux.h: + * ext/metadata/metadata.c: + * ext/metadata/metadata.h: + * ext/metadata/metadata_mapping.htm: + * ext/metadata/metadataexif.c: + * ext/metadata/metadataexif.h: + * ext/metadata/metadataiptc.c: + * ext/metadata/metadataiptc.h: + * ext/metadata/metadatamuxjpeg.c: + * ext/metadata/metadatamuxjpeg.h: + * ext/metadata/metadatamuxpng.c: + * ext/metadata/metadatamuxpng.h: + * ext/metadata/metadataparsejpeg.c: + * ext/metadata/metadataparsejpeg.h: + * ext/metadata/metadataparsepng.c: + * ext/metadata/metadataparsepng.h: + * ext/metadata/metadataparseutil.c: + * ext/metadata/metadataparseutil.h: + * ext/metadata/metadatatags.c: + * ext/metadata/metadatatags.h: + * ext/metadata/metadatatypes.c: + * ext/metadata/metadatatypes.h: + * ext/metadata/metadataxmp.c: + * ext/metadata/metadataxmp.h: + * tests/check/Makefile.am: + * tests/check/pipelines/.gitignore: + * tests/check/pipelines/metadata.c: + * tests/icles/Makefile.am: + metadata: remove metadata plugin + This plugins functionality is replaced by utility libraries in base for exif + and xmp. Jpeg images can use this via jpegformat plugin. + Fixes #486659 + +2010-09-14 11:28:56 -0700 David Schleef + + * gst/bayer/gstbayer2rgb.c: + bayer2rgb: Add format=bggr/etc. to caps + +2010-09-13 18:49:43 -0700 David Schleef + + * gst/colorspace/Makefile.am: + * gst/colorspace/colorspace.c: + * gst/colorspace/colorspace.h: + * gst/colorspace/gstcolorspace.c: + * gst/colorspace/gstcolorspace.h: + * gst/colorspace/gstcolorspaceorc.orc: + colorspace: Add conversion code + Work in progress. Colorspace handles most format conversion using + 3-stage getline/matrix/putline process using an AYUV or ARGB + intermediate, with most functions handled by Orc. There is also + a table of single-pass conversions, all handled by Orc. The plan + is to add optional stages for various chroma upsampling/downsampling + algorithms, dithering, and float/int16 intermediates, and then have + Orc create multi-stage functions at runtime. + +2010-09-13 12:48:50 -0700 David Schleef + + * configure.ac: + * gst/colorspace/Makefile.am: + * gst/colorspace/gstcolorspace.c: + * gst/colorspace/gstcolorspace.h: + * gst/colorspace/gstcolorspaceorc.orc: + * gst/colorspace/yuv2rgb.c: + * gst/colorspace/yuv2rgb.h: + colorspace: Revive element + Now based on Orc. + +2010-09-09 14:49:06 -0400 Tristan Matthews + + * ext/jack/Makefile.am: + * ext/jack/gstjackaudiosink.c: + * ext/jack/gstjackaudiosrc.c: + jack: added translatable text for server not found error + +2010-08-09 14:32:57 +0200 Olivier Crête + + * ext/celt/gstceltenc.c: + celtenc: Change bitrate to bits/sec + +2010-09-10 13:36:24 -0300 Thiago Santos + + * gst/jpegformat/gstjifmux.c: + jifmux: Reset tags when going to READY + Reset the tagsetter tags when going to READY state + +2010-09-10 13:33:16 -0300 Thiago Santos + + * gst/jpegformat/gstjifmux.c: + * gst/jpegformat/gstjpegparse.c: + jpegformat: Fix element description + Use saner categories for jifmux/jpegparse elements + +2010-09-10 11:31:46 -0300 Thiago Santos + + * gst/camerabin/gstcamerabin.c: + camerabin: Set tags to more elements + Remove check for 'Muxer' category when setting tags + for tagsetters. Set them to all tagsetters in the + pipelines. + +2010-09-10 18:35:27 +0200 Mark Nauwelaerts + + * gst/sdp/gstsdpdemux.c: + sdpdemux: redirect SDP with an rtsp control URL + When we find an SDP with an rtsp:// url as the global control attribute or when + all streams have an rtsp:// control attribute, post an redirect message with an + rtsp-sdp:// url containing the SDP. + Fixes #628214 + +2010-09-10 10:29:38 -0300 Thiago Santos + + * gst/geometrictransform/gstfisheye.c: + * gst/geometrictransform/gsttunnel.c: + geometrictransform: Fix build with debugging disabled + Add some ifdefs to prevent build failures due to unused + variables + +2010-09-09 23:59:17 +0300 Stefan Kost + + * tests/check/Makefile.am: + * tests/check/generic/states.c: + tests: allow running state tests for all elements + Now one can use GST_NO_STATE_IGNORE_ELEMENTS=1 make generic/states.check + to try elements that would normaly be skipped. + +2010-09-09 17:18:06 +0200 Edward Hervey + + * configure.ac: + configure.ac: Remove dependency on libswscale + It's not used in the gst opencv plugin. + +2010-09-09 15:03:24 +0100 Tim-Philipp Müller + + * configure.ac: + * ext/opencv/Makefile.am: + opencv: define CV_NO_BACKWARD_COMPATIBILITY to suppress warnings caused by compat header + Compile with -DCV_NO_BACKWARD_COMPATIBILITY for now, so that the compat header + doesn't get included, which causes compiler warnings that (it seems) can't be + switched off easily. As a result, we also specify a max. version in configure, + so the build doesn't break if our code doesn't compile against newer opencv + versions any more with that flag. + +2010-09-09 11:07:47 +0100 Tim-Philipp Müller + + * ext/opencv/Makefile.am: + opencv: avoid 'unused' compiler warnings with inline functions in opencv headers + Override CV_INLINE to avoid 'unused' gcc warnings. GLib will take care of defining + 'inline' sufficiently and OpenCV's define isn't good enough to avoid 'unused' + compiler warnings (at least in version 2.1.0). + +2010-09-09 10:27:49 +0100 Tim-Philipp Müller + + * ext/opencv/gstopencv.c: + opencv: update plugin source package name and origin + +2010-09-08 23:59:38 -0300 Thiago Santos + + * ext/opencv/gstfacedetect.c: + * ext/opencv/gstfacedetect.h: + facedetect: Add more parameters + Expose the parameters of cvHaarDetectObjects in facedetect + element. + +2010-09-08 14:59:54 -0300 Thiago Santos + + * ext/opencv/Makefile.am: + * ext/opencv/basicfilters/Makefile.am: + * ext/opencv/basicfilters/gstcvdilate.c: + * ext/opencv/basicfilters/gstcvdilate.h: + * ext/opencv/basicfilters/gstcvdilateerode.c: + * ext/opencv/basicfilters/gstcvdilateerode.h: + * ext/opencv/basicfilters/gstcvequalizehist.c: + * ext/opencv/basicfilters/gstcvequalizehist.h: + * ext/opencv/basicfilters/gstcverode.c: + * ext/opencv/basicfilters/gstcverode.h: + * ext/opencv/basicfilters/gstcvlaplace.c: + * ext/opencv/basicfilters/gstcvlaplace.h: + * ext/opencv/basicfilters/gstcvsmooth.c: + * ext/opencv/basicfilters/gstcvsmooth.h: + * ext/opencv/basicfilters/gstcvsobel.c: + * ext/opencv/basicfilters/gstcvsobel.h: + * ext/opencv/edgedetect/Makefile.am: + * ext/opencv/edgedetect/gstedgedetect.c: + * ext/opencv/edgedetect/gstedgedetect.h: + * ext/opencv/faceblur/Makefile.am: + * ext/opencv/faceblur/gstfaceblur.c: + * ext/opencv/faceblur/gstfaceblur.h: + * ext/opencv/facedetect/Makefile.am: + * ext/opencv/facedetect/gstfacedetect.c: + * ext/opencv/facedetect/gstfacedetect.h: + * ext/opencv/gstcvdilate.c: + * ext/opencv/gstcvdilate.h: + * ext/opencv/gstcvdilateerode.c: + * ext/opencv/gstcvdilateerode.h: + * ext/opencv/gstcvequalizehist.c: + * ext/opencv/gstcvequalizehist.h: + * ext/opencv/gstcverode.c: + * ext/opencv/gstcverode.h: + * ext/opencv/gstcvlaplace.c: + * ext/opencv/gstcvlaplace.h: + * ext/opencv/gstcvsmooth.c: + * ext/opencv/gstcvsmooth.h: + * ext/opencv/gstcvsobel.c: + * ext/opencv/gstcvsobel.h: + * ext/opencv/gstedgedetect.c: + * ext/opencv/gstedgedetect.h: + * ext/opencv/gstfaceblur.c: + * ext/opencv/gstfaceblur.h: + * ext/opencv/gstfacedetect.c: + * ext/opencv/gstfacedetect.h: + * ext/opencv/gstopencvutils.c: + * ext/opencv/gstpyramidsegment.c: + * ext/opencv/gstpyramidsegment.h: + * ext/opencv/gsttemplatematch.c: + * ext/opencv/gsttemplatematch.h: + * ext/opencv/gsttextwrite.c: + * ext/opencv/gsttextwrite.h: + * ext/opencv/pyramidsegment/Makefile.am: + * ext/opencv/pyramidsegment/gstpyramidsegment.c: + * ext/opencv/pyramidsegment/gstpyramidsegment.h: + * ext/opencv/templatematch/Makefile.am: + * ext/opencv/templatematch/gsttemplatematch.c: + * ext/opencv/templatematch/gsttemplatematch.h: + * ext/opencv/textwrite/Makefile.am: + * ext/opencv/textwrite/gsttextwrite.c: + * ext/opencv/textwrite/gsttextwrite.h: + opencv: Refactor files structure + Remove internal folders and put all code inside the main plugin + folder. Also fixes some building warnings. + +2010-09-08 00:08:44 -0300 Thiago Santos + + * configure.ac: + * docs/plugins/Makefile.am: + * docs/plugins/gst-plugins-bad-plugins-docs.sgml: + * docs/plugins/gst-plugins-bad-plugins-sections.txt: + * docs/plugins/gst-plugins-bad-plugins.args: + * docs/plugins/gst-plugins-bad-plugins.hierarchy: + * docs/plugins/gst-plugins-bad-plugins.interfaces: + * docs/plugins/gst-plugins-bad-plugins.prerequisites: + * docs/plugins/inspect/plugin-opencv.xml: + * ext/Makefile.am: + * ext/opencv/Makefile.am: + opencv: Adds new plugin opencv + Moves opencv plugin from http://github.com/Elleo/gst-opencv + into -bad module. + +2010-09-05 23:09:26 -0300 Thiago Santos + + * ext/opencv/facedetect/gstfacedetect.c: + facedetect: Post an useful message + Add a message to be post when faces are found on a frame that + contains all faces on a single message and also has + timestamp/running/segment times for that buffer so it + can be identified. + This message is called 'facedetect' and has a 'faces' list + of structures with all faces. + The old 'face' message is still posted for each face found, but + it is not really useful as it doesn't have any reference to the + buffer that generated it. + +2010-09-05 17:53:24 -0300 Thiago Santos + + * ext/opencv/facedetect/Makefile.am: + * ext/opencv/facedetect/gstfacedetect.c: + * ext/opencv/facedetect/gstfacedetect.h: + facedetect: Use GstOpencvVideoFilter as the base class + Port facedetect to use GstOpencvVideoFilter as the base class + to inherit all the goodness that GstBaseTransform/GstVideoFilter + already handles. + +2010-09-03 20:27:31 -0300 Thiago Santos + + * ext/opencv/Makefile.am: + * ext/opencv/basicfilters/Makefile.am: + * ext/opencv/basicfilters/gstcvdilate.c: + * ext/opencv/basicfilters/gstcvdilateerode.c: + * ext/opencv/basicfilters/gstcvdilateerode.h: + * ext/opencv/basicfilters/gstcvequalizehist.c: + * ext/opencv/basicfilters/gstcvequalizehist.h: + * ext/opencv/basicfilters/gstcverode.c: + * ext/opencv/basicfilters/gstcvlaplace.c: + * ext/opencv/basicfilters/gstcvlaplace.h: + * ext/opencv/basicfilters/gstcvsmooth.c: + * ext/opencv/basicfilters/gstcvsmooth.h: + * ext/opencv/basicfilters/gstcvsobel.c: + * ext/opencv/basicfilters/gstcvsobel.h: + * ext/opencv/gstopencvbasetrans.c: + * ext/opencv/gstopencvbasetrans.h: + * ext/opencv/gstopencvvideofilter.c: + * ext/opencv/gstopencvvideofilter.h: + opencvbasetrans: Use GstVideoFilter as the base class + Port from GstBaseTransform to GstVideoFilter as the base class. + +2010-05-24 19:28:59 -0300 Thiago Santos + + * ext/opencv/basicfilters/Makefile.am: + * ext/opencv/basicfilters/gstcvlaplace.c: + * ext/opencv/basicfilters/gstcvlaplace.h: + * ext/opencv/gstopencv.c: + * ext/opencv/gstopencvbasetrans.c: + * ext/opencv/gstopencvbasetrans.h: + cvlaplace: adds new cvlaplace element + Adds new cvlaplace element. + Also adds a new opencvbasetransform function to be overriden + by children classes: the cv_set_caps, it allows children classes + to know what are they going to handle and prepare properly. + +2010-05-19 20:11:39 -0300 Thiago Santos + + * ext/opencv/basicfilters/Makefile.am: + * ext/opencv/basicfilters/gstcvsobel.c: + * ext/opencv/basicfilters/gstcvsobel.h: + * ext/opencv/gstopencv.c: + * ext/opencv/gstopencvutils.c: + Adds new element cvsobel + +2010-05-17 19:04:49 -0300 Thiago Santos + + * ext/opencv/basicfilters/Makefile.am: + * ext/opencv/basicfilters/gstcvequalizehist.c: + * ext/opencv/basicfilters/gstcvequalizehist.h: + * ext/opencv/gstopencv.c: + Adds new element cvequalizehist + +2010-05-16 19:14:54 -0300 Thiago Santos + + * ext/opencv/basicfilters/Makefile.am: + * ext/opencv/basicfilters/gstcvdilate.c: + * ext/opencv/basicfilters/gstcvdilate.h: + * ext/opencv/basicfilters/gstcvdilateerode.c: + * ext/opencv/basicfilters/gstcvdilateerode.h: + * ext/opencv/basicfilters/gstcverode.c: + * ext/opencv/basicfilters/gstcverode.h: + * ext/opencv/gstopencv.c: + Adds new elements cvdilate and cverode + Adds 2 similar elements (so similar they have their own baseclass), + cvdilate and cverode. + +2010-05-16 17:03:51 -0300 Thiago Santos + + * ext/opencv/basicfilters/gstcvsmooth.c: + * ext/opencv/gstopencvbasetrans.c: + cvsmooth: Improve parameters docs + +2010-05-16 16:37:12 -0300 Thiago Santos + + * ext/opencv/basicfilters/gstcvsmooth.c: + cvsmooth: Deactivating blur-no-scale + Deactivate blur-no-scale because basetransform doesn't provide a way + to override getcaps for pads, always using templatecaps independent + of properties. + +2010-05-16 11:42:08 -0300 Thiago Santos + + * ext/opencv/basicfilters/gstcvsmooth.c: + * ext/opencv/gstopencvbasetrans.c: + * ext/opencv/gstopencvutils.c: + * ext/opencv/gstopencvutils.h: + cvsmooth: Add support for video/x-raw-gray + +2010-05-16 00:46:01 -0300 Thiago Santos + + * ext/opencv/Makefile.am: + * ext/opencv/gstopencvbasetrans.c: + * ext/opencv/gstopencvutils.c: + * ext/opencv/gstopencvutils.h: + Adding gstopencvutils + Adds a file to keep utilitary functions together + +2010-05-11 20:11:42 -0300 Thiago Santos + + * ext/opencv/Makefile.am: + * ext/opencv/basicfilters/gstcvsmooth.c: + * ext/opencv/basicfilters/gstcvsmooth.h: + * ext/opencv/gstopencv.c: + cvsmooth: Adds new element cvsmooth + Adds new cvsmooth element + +2010-05-05 01:24:54 -0300 Thiago Santos + + * ext/opencv/Makefile.am: + * ext/opencv/basicfilters/Makefile.am: + * ext/opencv/gstopencvbasetrans.c: + * ext/opencv/gstopencvbasetrans.h: + gstopencvbasetrans: Adds this new base class + Adds GstOpencvBaseTransform as base class for simple 1:1 + opencv filters + +2010-04-26 17:18:54 -0300 Thiago Santos + + * ext/opencv/pyramidsegment/gstpyramidsegment.c: + pyramidsegment: Allocate a new buffer for output + Use a newly allocated buffer for output, and release the intermediary + image used. + Also add a TODO for performance improvement + +2010-04-26 17:34:12 -0300 Thiago Santos + + * ext/opencv/faceblur/gstfaceblur.c: + * ext/opencv/facedetect/gstfacedetect.c: + * ext/opencv/templatematch/gsttemplatematch.c: + * ext/opencv/textwrite/gsttextwrite.c: + faceblur: facedetect: templatematch: textwrite: Set buffer to writable + These elements operates in place, set buffer to writable before + operating. + +2010-04-26 16:17:23 -0300 Thiago Santos + + * ext/opencv/edgedetect/gstedgedetect.c: + edgedetect: Fix chain buffer handling + Allocate a new output buffer instead of using the input buffer + pointing to the internal cvCEdge opencv's IplImage data, which + might change, consequently changing the buffer. + +2010-04-25 16:27:04 -0300 Thiago Santos + + * ext/opencv/edgedetect/gstedgedetect.c: + * ext/opencv/faceblur/gstfaceblur.c: + * ext/opencv/facedetect/gstfacedetect.c: + * ext/opencv/pyramidsegment/gstpyramidsegment.c: + * ext/opencv/templatematch/gsttemplatematch.c: + * ext/opencv/textwrite/gsttextwrite.c: + configure: enable -Werror to improve code + -Werror on git version is useful to keep code clean. + +2010-03-02 13:55:05 +0530 Sreerenj Balachandran + + * ext/opencv/textwrite/gsttextwrite.c: + * ext/opencv/textwrite/gsttextwrite.h: + Added the property for setting the RGB colours. modified: ext/opencv/textwrite/gsttextwrite.c modified: ext/opencv/textwrite/gsttextwrite.h + +2010-03-02 13:18:19 +0530 Sreerenj Balachandran + + * ext/opencv/textwrite/gsttextwrite.c: + * ext/opencv/textwrite/gsttextwrite.h: + Added the property for setting the "thickness" of font modified: ext/opencv/textwrite/gsttextwrite.c modified: ext/opencv/textwrite/gsttextwrite.h + +2010-03-02 12:45:58 +0530 Sreerenj Balachandran + + * ext/opencv/textwrite/gsttextwrite.c: + * ext/opencv/textwrite/gsttextwrite.h: + Added the property for setting x and y co-ordinates modified: ext/opencv/textwrite/gsttextwrite.c modified: ext/opencv/textwrite/gsttextwrite.h + +2010-03-02 12:41:25 +0530 Sreerenj Balachandran + + * ext/opencv/textwrite/gsttextwrite.c: + * ext/opencv/textwrite/gsttextwrite.h: + added the propery for setting x and y co-ordinates modified: ext/opencv/textwrite/gsttextwrite.c modified: ext/opencv/textwrite/gsttextwrite.h + +2010-02-28 14:36:35 +0000 Mike Sheldon + + * ext/opencv/facedetect/gstfacedetect.c: + Apply Stefan's faceblur fixes to facedetect + +2010-02-28 14:32:00 +0000 Sreerenj Balachandran + + * ext/opencv/Makefile.am: + * ext/opencv/gstopencv.c: + * ext/opencv/textwrite/Makefile.am: + * ext/opencv/textwrite/gsttextwrite.c: + * ext/opencv/textwrite/gsttextwrite.h: + Add simple text overlay plugin + +2010-02-19 22:50:18 +0200 Stefan Kost + + * ext/opencv/faceblur/gstfaceblur.c: + faceblur: fix handling of profile property. + Dup and free the string. Fixes leaking new values and avoids crashing + gst-inspect. + +2009-12-18 11:23:59 +0000 Mike Sheldon + + * ext/opencv/templatematch/gsttemplatematch.h: + Fix includes in template matching element + +2009-05-26 12:59:04 +0100 Mike Sheldon + + * ext/opencv/edgedetect/gstedgedetect.c: + * ext/opencv/edgedetect/gstedgedetect.h: + * ext/opencv/faceblur/gstfaceblur.c: + * ext/opencv/faceblur/gstfaceblur.h: + * ext/opencv/facedetect/gstfacedetect.c: + * ext/opencv/facedetect/gstfacedetect.h: + * ext/opencv/gstopencv.c: + * ext/opencv/pyramidsegment/gstpyramidsegment.c: + * ext/opencv/pyramidsegment/gstpyramidsegment.h: + * ext/opencv/templatematch/gsttemplatematch.c: + * ext/opencv/templatematch/gsttemplatematch.h: + Bring code in to line with general Gstreamer standards + +2009-05-25 12:57:11 +0100 Mike Sheldon + + * ext/opencv/templatematch/gsttemplatematch.c: + Fix segfault in template match element if no template has been set Add template matching python example Add autotool, libtool and pkgconfig dependencies to debian control file + +2009-05-25 11:26:28 +0100 Mike Sheldon + + * ext/opencv/Makefile.am: + * ext/opencv/faceblur/Makefile.am: + * ext/opencv/faceblur/gstfaceblur.c: + * ext/opencv/faceblur/gstfaceblur.h: + * ext/opencv/gstopencv.c: + Add a plugin for automatically blurring faces in videos and images + +2009-05-13 12:19:43 +0300 Noam + + * ext/opencv/templatematch/gsttemplatematch.c: + * ext/opencv/templatematch/gsttemplatematch.h: + Added control for changing method + +2009-05-13 11:55:31 +0300 Noam + + * ext/opencv/Makefile.am: + * ext/opencv/gstopencv.c: + * ext/opencv/templatematch/Makefile.am: + * ext/opencv/templatematch/gsttemplatematch.c: + * ext/opencv/templatematch/gsttemplatematch.h: + Added templatematch element + +2009-05-08 11:55:20 +0530 kapil + + * ext/opencv/Makefile.am: + * ext/opencv/edgedetect/Makefile.am: + * ext/opencv/edgedetect/gstedgedetect.c: + * ext/opencv/edgedetect/gstedgedetect.h: + * ext/opencv/facedetect/Makefile.am: + * ext/opencv/facedetect/gstfacedetect.c: + * ext/opencv/facedetect/gstfacedetect.h: + * ext/opencv/gstopencv.c: + * ext/opencv/pyramidsegment/Makefile.am: + * ext/opencv/pyramidsegment/gstpyramidsegment.c: + * ext/opencv/pyramidsegment/gstpyramidsegment.h: + Registering all elements under opencv plugin + +2009-05-06 15:49:42 +0100 Mike Sheldon + + * ext/opencv/facedetect/gstfacedetect.c: + Fix the profile parameter in the facedetect element to accept a string correctly + +2009-05-06 15:33:48 +0100 Mike Sheldon + + * ext/opencv/edgedetect/gstedgedetect.c: + * ext/opencv/facedetect/gstfacedetect.c: + * ext/opencv/pyramidsegment/gstpyramidsegment.c: + Release OpenCV images when finalizing elements + +2009-05-06 16:38:15 +0530 kapil + + * ext/opencv/edgedetect/gstedgedetect.h: + * ext/opencv/facedetect/gstfacedetect.h: + * ext/opencv/pyramidsegment/gstpyramidsegment.h: + Fixed compile errors + +2009-04-20 18:40:13 +0300 Mike Sheldon + + * ext/opencv/facedetect/gstfacedetect.c: + Make face detect send a bus message when a face is detected Write a simple python example for face detection + +2009-04-18 23:43:37 +0300 Mike Sheldon + + * ext/opencv/Makefile.am: + * ext/opencv/edgedetect/gstedgedetect.c: + * ext/opencv/edgedetect/gstedgedetect.h: + * ext/opencv/facedetect/Makefile.am: + * ext/opencv/facedetect/gstfacedetect.c: + * ext/opencv/facedetect/gstfacedetect.h: + * ext/opencv/pyramidsegment/gstpyramidsegment.c: + * ext/opencv/pyramidsegment/gstpyramidsegment.h: + Add face detection element Clean up some generated files Update a few old comments + +2008-12-18 23:48:40 +0000 Mike Sheldon + + * ext/opencv/Makefile: + * ext/opencv/Makefile.in: + * ext/opencv/edgedetect/Makefile: + * ext/opencv/edgedetect/Makefile.in: + * ext/opencv/pyramidsegment/Makefile: + * ext/opencv/pyramidsegment/Makefile.in: + * Remove some autotools generated files + +2008-12-18 23:43:36 +0000 Mike Sheldon + + * ext/opencv/Makefile: + * ext/opencv/Makefile.am: + * ext/opencv/Makefile.in: + * ext/opencv/edgedetect/Makefile: + * ext/opencv/edgedetect/Makefile.am: + * ext/opencv/edgedetect/Makefile.in: + * ext/opencv/edgedetect/gstedgedetect.c: + * ext/opencv/edgedetect/gstedgedetect.h: + * ext/opencv/pyramidsegment/Makefile: + * ext/opencv/pyramidsegment/Makefile.am: + * ext/opencv/pyramidsegment/Makefile.in: + * ext/opencv/pyramidsegment/gstpyramidsegment.c: + * ext/opencv/pyramidsegment/gstpyramidsegment.h: + * Make it possible to set threshold2 at runtime * Implement pyramid segmentation element * Make masking optional on edgedetect * Clean up edgedetect, add element details * Implemented edge detect element + +2010-09-08 16:57:57 -0300 Thiago Santos + + * gst/id3tag/id3tag.c: + id3mux: Map GST_TAG_ALBUM_ARTIST + Map GST_TAG_ALBUM_ARTIST to TPE2 as it is done in + -base id3tag mappings. + +2010-08-09 00:15:03 +0100 Tim-Philipp Müller + + * common: + * configure.ac: + * tests/check/Makefile.am: + Use AG_GST_CHECK_GST_PLUGINS_{GOOD,UGLY,BAD,FFMPEG} macros from common + to find plugin directories for the various modules our unit tests depend + on in an uninstalled environment. This makes sure these plugins are found + even when distchecking (which happens from a subdirectory, which means + that the currently used trick to find the uninstalled directories of + these modules doesn't work in that case). + +2010-09-07 19:16:24 +0100 Tim-Philipp Müller + + * docs/plugins/gst-plugins-bad-plugins-docs.sgml: + docs: update plugin docs sgml file a bit + +2010-09-07 15:22:28 -0300 Thiago Santos + + * docs/plugins/.gitignore: + docs: add 2 new files to gitignore + Adds gst-plugins-bad-plugins.args.new and + gst-plugins-bad-plugins.signals.new to .gitignore + +2010-09-07 14:45:12 -0300 Thiago Santos + + * gst/jpegformat/gstjifmux.c: + jifmux: Make it more colorspace smart + This makes it able to recombine rgb images, making it possible + to add tags to rgb jpegs as well. + Uses a simple strategy to check what are the possible colorspaces + and avoid adding jfif to ones that aren't YUV/Gray. + +2010-09-07 10:26:29 -0300 Thiago Santos + + * tests/check/elements/jifmux.c: + tests: jifmux: Adds tests for new ppi tags + Adds tests to check if libexif can read our + EXIF_TAG_X/Y_RESOLUTION tags. + +2010-09-07 13:28:20 +0200 Robert Swain + + * gst/interlace/gstinterlace.c: + interlace: Fix element details + +2010-09-07 11:42:30 +0100 Tim-Philipp Müller + + * common: + Automatic update of common submodule + From c2e10bf to aa0d1d0 + +2010-09-07 11:34:35 +0100 Tim-Philipp Müller + + * docs/plugins/gst-plugins-bad-plugins.args: + * docs/plugins/gst-plugins-bad-plugins.hierarchy: + * docs/plugins/inspect/plugin-cog.xml: + * docs/plugins/inspect/plugin-debugutilsbad.xml: + * docs/plugins/inspect/plugin-interlace.xml: + * docs/plugins/inspect/plugin-sdl.xml: + * docs/plugins/inspect/plugin-videomeasure.xml: + * docs/plugins/inspect/plugin-videosignal.xml: + docs: update plugin introspection data for recent changes + +2010-09-07 11:28:44 +0100 Tim-Philipp Müller + + * docs/plugins/inspect/plugin-aacparse.xml: + * docs/plugins/inspect/plugin-aiffparse.xml: + * docs/plugins/inspect/plugin-amrparse.xml: + * docs/plugins/inspect/plugin-amrwb.xml: + * docs/plugins/inspect/plugin-dvbsrc.xml: + * docs/plugins/inspect/plugin-flacparse.xml: + * docs/plugins/inspect/plugin-gstrtpmanager.xml: + * docs/plugins/inspect/plugin-mpegtsparse.xml: + * docs/plugins/inspect/plugin-x264.xml: + docs: remove introspection files for plugins that have been merged, moved or renamed + The aacparse, amrparse, flacparse plugins have been merged into the audioparsersbad + plugin. The aiffparse plugin has been renamed to aiff since it also contains an + aiff muxer now. The amrwb plugin has been renamed to amrwbenc. The dvbsrc plugin + has been renamed to dvb. The gstrtpmanager plugin has moved to -good. The x264 + plugin has moved to -ugly. And the mpegtsparse plugin has been merged into the + mpegdemux2 plugin. + +2010-09-07 00:16:00 +0100 Tim-Philipp Müller + + * .gitignore: + * tests/examples/Makefile.am: + tests: fix distcheck by disting new jack example directory + Also add test binary to ignores. + +2010-09-06 17:17:54 -0400 Tristan Matthews + + * configure.ac: + * tests/examples/Makefile.am: + * tests/examples/jack/Makefile.am: + * tests/examples/jack/jack_client.c: + examples: add test to demonstrate jack_client_t usage + +2010-09-06 16:11:31 -0400 Tristan Matthews + + * ext/jack/gstjack.c: + * ext/jack/gstjack.h: + * ext/jack/gstjackaudioclient.c: + * ext/jack/gstjackaudioclient.h: + * ext/jack/gstjackaudiosink.c: + * ext/jack/gstjackaudiosink.h: + * ext/jack/gstjackaudiosrc.c: + * ext/jack/gstjackaudiosrc.h: + jack: added client property + +2010-06-17 16:26:07 -0400 Tristan Matthews + + * ext/jack/gstjackbin.c: + jack: removed unused file gstjackbin.c + This is a 0.8 leftover. + +2010-09-06 14:12:00 +0200 Mark Nauwelaerts + + * gst/audioparsers/gstbaseparse.c: + baseparse: non-TIME seek event is simply not handled + +2010-09-06 09:28:46 -0300 Thiago Santos + + * configure.ac: + configure: Bump -core/-base requirements to 0.10.30.1 + We need 0.10.30.1 to have latest tags in core/base for jifmux + tests. + +2010-08-26 02:54:55 -0400 Youness Alaoui + + * gst/dtmf/gstdtmfsrc.c: + dtmfsrc: Make the dtmfsrc accept events sent with gst_element_send_event + The doc says to use gst_element_send_event on the pipeline, but if + we are to call it on the element itself, it's a noop. This should make it + handle the event properly before delegating it to basesrc. + +2010-09-05 16:30:05 +0200 Carl-Anton Ingmarsson + + * sys/vdpau/gstvdpvideopostprocess.c: + vdpauvideopostprocess: set new framerate on output caps instead of input caps + It's not allowed to change the caps provided by the setcaps function. + https://bugzilla.gnome.org/show_bug.cgi?id=628326 + +2010-09-06 03:23:26 -0700 David Schleef + + * tools/element-maker: + element-maker: Take parameters on command line + Now it's actually useful. + +2010-09-06 03:04:13 -0700 David Schleef + + * gst/interlace/gstinterlace.c: + interlace: Add documentation + +2010-09-06 10:29:21 +0200 Sebastian Dröge + + * gst/debugutils/fpsdisplaysink.c: + fpsdisplay: Use G_GUINT64_FORMAT instead of %llu + Fixes compiler warnings on 64 bit architectures. + +2010-09-06 11:03:07 +0300 Stefan Kost + + * gst/selector/gstinputselector.c: + inputselector: sync with copy in -base + Use _get_caps_reffed to avoid copies. + +2010-08-24 11:50:47 +0300 Stefan Kost + + * gst/selector/gstoutputselector.c: + outputselector: move the debug init to the boilerplate macro + +2010-08-24 11:50:09 +0300 Stefan Kost + + * gst/selector/gstinputselector.c: + inputselector: use GST_BOILERPLATE macro + +2010-08-24 11:26:52 +0300 Stefan Kost + + * gst/debugutils/fpsdisplaysink.c: + * gst/debugutils/fpsdisplaysink.h: + fpsdisplaysink: don't add a g_mainloop dependency + Just update the fps-message from the probe handler. + +2010-08-18 11:35:44 +0300 Stefan Kost + + * gst/debugutils/fpsdisplaysink.c: + fpsdisplaysink: small cleanup + Add one one example and lower the fon't size for the overlay. + +2010-08-23 09:51:25 -0500 Rob Clark + + * gst/debugutils/fpsdisplaysink.c: + * gst/debugutils/fpsdisplaysink.h: + fpsdisplaysink: measure fps in terms of wall clock time + Measure fps in terms of system clock, rather than pipeline clock, to get + an accurate meaure of fps. + +2010-09-05 22:41:24 -0700 David Schleef + + * gst/debugutils/Makefile.am: + * gst/debugutils/debugutilsbad.c: + * gst/debugutils/gstchecksumsink.c: + * gst/debugutils/gstchecksumsink.h: + checksumsink: Add new element + +2010-09-05 22:30:54 -0700 David Schleef + + * gst/videomeasure/gstvideomeasure_ssim.c: + ssim: Add I420 support + +2010-09-05 21:34:30 -0700 David Schleef + + * gst/interlace/gstinterlace.c: + interlace: Add more formats + +2010-09-05 18:58:36 -0700 David Schleef + + * common: + Automatic update of common submodule + From d3d9acf to c2e10bf + +2010-09-05 23:40:08 +1000 Jan Schmidt + + * docs/plugins/gst-plugins-bad-plugins.args.new: + * docs/plugins/gst-plugins-bad-plugins.signals.new: + Remove .new docs files from the repository + +2010-09-05 15:34:13 -0700 Jonathan Rosser + + * ext/cog/cogvirtframe.c: + cog: Fix cog_virt_frame_new_convert_u8() + Conversion was using uninitialized data instead of source frame. + Fixes #626425. + +2010-09-05 12:06:31 -0700 David Schleef + + * configure.ac: + * ext/cog/gstcogorc-dist.c: + cog: Fix generated Orc code + Also drop required Orc back down to 0.4.7. + +2010-08-30 21:22:14 -0300 Thiago Santos + + * gst/camerabin/camerabinimage.c: + * gst/camerabin/gstcamerabin.c: + camerabin: Use jifmux instead of metadatamux + Use jifmux element to write exif/xmp tags instead of metadatamux + +2010-08-30 21:21:49 -0300 Thiago Santos + + * gst/camerabin/Makefile.am: + * gst/camerabin/gstcamerabin.c: + camerabin: Use new tags from -base + Replace private tags from metadata plugin with the new generic tags + from -base. + +2010-09-03 14:12:23 -0300 Thiago Santos + + * tests/check/elements/camerabin.c: + camerabin: Refactor tests + The tests were done in 2 steps, first there was a suite + that generated the files (while checking that camerabin + was operating correctly). Then there was a second suite + that was run to check that all files were playable with + playbin2. Those second tests were not being run because + they were checking if camerabin was initialized, and it + never was as those tests didn't use a 'setup' function. + This commit refactors the tests by removing this second + suite and merging its validation with the first suite's + functions. + +2010-08-24 14:43:50 -0300 Thiago Santos + + * tests/check/elements/jifmux.c: + tests: jifmux: Adds geo location tags tests + Adds some more tests for geo location tags. + Also use libexif constants for the exif tags' ids. + +2010-08-24 09:02:59 -0300 Thiago Santos + + * tests/check/elements/jifmux.c: + tests: jifmux: Refactor testing code a little + Refactor testing code to allow testing for cases where the + same gstreamer tag is mapped to multiple exif tags. + +2010-08-23 11:57:37 -0300 Thiago Santos + + * tests/check/Makefile.am: + * tests/check/elements/jifmux.c: + jifmux: More tests for exif tags + Refactors some code and add some more tests for exif tags + +2010-09-02 11:18:27 -0300 Thiago Santos + + * gst/jpegformat/gstjifmux.c: + jifmux: Do not limit the size of the image on 16bits + Use guint instead of guint16 to represent the size of the encoded image, + this would make some recombined images lose most of their data and + show like a big black image with a small line of content on top. + Also adds a minor log message. + +2010-08-21 17:01:29 -0300 Thiago Santos + + * gst/jpegformat/gstjifmux.c: + * gst/jpegformat/gstjifmux.h: + jifmux: Set output pad caps + Set output pad caps to guarantee caps on the buffers being + pushed downstream. + +2010-08-20 08:34:35 -0300 Thiago Santos + + * gst/jpegformat/gstjifmux.c: + jifmux: Detect EOI correctly + EOI are not always at the last 4 bytes. We need to search + the last 5 bytes to find the 0xFFD9 sequence as jpegenc seems + to round the buffer size to the next 4 multiple. + +2010-08-19 22:43:47 -0300 Thiago Santos + + * gst/jpegformat/gstjifmux.c: + jifmux: Put APP0 first always + Fixes the order of the APP0/APP1 markers. APP0 should + be first. + +2010-09-02 01:32:10 +0200 Carl-Anton Ingmarsson + + * sys/vdpau/h264/gstvdph264dec.c: + vdpauh264dec: parse "pixel-aspect-ratio" from stream + +2010-09-02 01:04:15 +0200 Carl-Anton Ingmarsson + + * sys/vdpau/basevideodecoder/gstbasevideodecoder.c: + * sys/vdpau/basevideodecoder/gstbasevideodecoder.h: + vdpau: remove non working unused code from GstBaseVideoDecoder + +2010-09-02 00:17:49 +0200 Carl-Anton Ingmarsson + + * sys/vdpau/basevideodecoder/gstbasevideodecoder.c: + vdpau: GstBaseVideoDecoder set default par to 1/1 + +2010-09-01 23:47:21 +0200 Carl-Anton Ingmarsson + + * sys/vdpau/basevideodecoder/gstbasevideodecoder.c: + * sys/vdpau/basevideodecoder/gstbasevideodecoder.h: + * sys/vdpau/h264/gstvdph264dec.c: + * sys/vdpau/mpeg/gstvdpmpegdec.c: + * sys/vdpau/mpeg/gstvdpmpegframe.c: + * sys/vdpau/mpeg/gstvdpmpegframe.h: + * sys/vdpau/mpeg4/gstmpeg4frame.h: + * sys/vdpau/mpeg4/gstvdpmpeg4dec.c: + * sys/vdpau/mpeg4/gstvdpmpeg4dec.h: + * sys/vdpau/mpeg4/mpeg4util.c: + vdpau: remove gst_base_video_decoder_get_current_frame + we now pass the current frame to GstBaseVideoDecoder::parse_data + also fixup some errors in vdpaumpeg4dec so that it now gives correct output + +2010-09-01 22:03:05 +0200 Carl-Anton Ingmarsson + + * sys/vdpau/basevideodecoder/gstbasevideodecoder.c: + * sys/vdpau/basevideodecoder/gstbasevideodecoder.h: + * sys/vdpau/basevideodecoder/gstvideoframe.c: + * sys/vdpau/basevideodecoder/gstvideoframe.h: + vdpau: rework GstBaseVideoDecoder timestamping + timestamps are now chosen in the following order: + upstream -> parsed by decoder -> calculated from timestamp offset + we also check the timestamps supplied from upstream/decoder to see if they + atleast is increasing. + +2010-09-01 17:45:19 +0200 Carl-Anton Ingmarsson + + * sys/vdpau/gstvdp/gstvdpdecoder.c: + vdpau: fix invalid unref + +2010-09-05 12:19:32 +0200 Sebastian Dröge + + * common: + Automatic update of common submodule + From ec60217 to d3d9acf + +2010-09-05 11:45:35 +0200 Edward Hervey + + * configure.ac: + configure.ac: Bump orc requirement to 0.4.8.1 + 0.4.7 creates code with unavailable symbols + 0.4.8 creates buggy code + Let's use git head of orc (which still won't work because git head + of orc still claims to be 0.4.8) + This allows all the rest of -bad to build properly. + +2010-07-14 21:00:12 +0200 Edward Hervey + + * ext/timidity/gsttimidity.c: + timidity: Fix unitialized variables (gcc 4.4.4) + +2010-09-04 11:35:16 -0700 David Schleef + + * ext/cog/gstcogorc-dist.c: + * ext/cog/gstcogorc-dist.h: + cog: update disted Orc files + +2010-08-26 22:03:20 -0700 David Schleef + + * ext/sdl/sdlvideosink.c: + sdlvideosink: Re-enable YVYU and UYVY + YVYU on my machine appears to be doing software conversion + (and doing it incorrectly). + +2010-08-26 20:15:43 -0700 David Schleef + + * tools/base.c: + * tools/element-maker: + element-maker: construct element names + +2010-08-22 21:43:20 -0700 David Schleef + + * configure.ac: + * gst/interlace/Makefile.am: + * gst/interlace/gstinterlace.c: + interlace: new element + +2010-08-20 17:24:23 -0700 David Schleef + + * ext/cog/gstcogcolorspace.c: + * ext/cog/gstcogorc.orc: + cog: Add fast paths for colorspace conversion + +2010-08-20 17:23:17 -0700 David Schleef + + * configure.ac: + configure: require Orc 0.4.7 + +2010-08-13 21:58:01 -0700 David Schleef + + * tools/element-maker: + * tools/gstelement.c: + element-maker: Fix up GstElement + +2010-08-13 21:54:54 -0700 David Schleef + + * ext/cog/cogvirtframe.c: + * ext/cog/gstcogcolorspace.c: + * ext/cog/gstcogorc.orc: + cog: Improvements in colorspace and scaler + Add fast paths for YUV->YUV conversions and Orc code for all. + Use Orc for horizontal resampling. + +2010-06-11 14:39:30 -0700 David Schleef + + * ext/cog/Makefile.am: + * ext/cog/gstcog.c: + * ext/cog/gstcogdownsample.c: + * ext/cog/gstcogfilter.c: + * ext/cog/gstcogmse.c: + * ext/cog/gstcogscale.c: + * ext/cog/gstcolorconvert.c: + * ext/cog/gstlogoinsert.c: + cog: minor cleanups + Improve element descriptions, remove unused files, code cleanup. + +2010-09-03 10:03:04 +0100 Tim-Philipp Müller + + * configure.ac: + * docs/plugins/gst-plugins-bad-plugins.args: + * docs/plugins/gst-plugins-bad-plugins.args.new: + * docs/plugins/gst-plugins-bad-plugins.hierarchy: + * docs/plugins/gst-plugins-bad-plugins.signals.new: + * docs/plugins/inspect/plugin-adpcmdec.xml: + * docs/plugins/inspect/plugin-adpcmenc.xml: + * docs/plugins/inspect/plugin-aiff.xml: + * docs/plugins/inspect/plugin-alsaspdif.xml: + * docs/plugins/inspect/plugin-amrwbenc.xml: + * docs/plugins/inspect/plugin-apexsink.xml: + * docs/plugins/inspect/plugin-asfmux.xml: + * docs/plugins/inspect/plugin-assrender.xml: + * docs/plugins/inspect/plugin-audioparsersbad.xml: + * docs/plugins/inspect/plugin-autoconvert.xml: + * docs/plugins/inspect/plugin-bayer.xml: + * docs/plugins/inspect/plugin-bz2.xml: + * docs/plugins/inspect/plugin-camerabin.xml: + * docs/plugins/inspect/plugin-cdaudio.xml: + * docs/plugins/inspect/plugin-cdxaparse.xml: + * docs/plugins/inspect/plugin-celt.xml: + * docs/plugins/inspect/plugin-cog.xml: + * docs/plugins/inspect/plugin-coloreffects.xml: + * docs/plugins/inspect/plugin-dataurisrc.xml: + * docs/plugins/inspect/plugin-dc1394.xml: + * docs/plugins/inspect/plugin-dccp.xml: + * docs/plugins/inspect/plugin-debugutilsbad.xml: + * docs/plugins/inspect/plugin-dfbvideosink.xml: + * docs/plugins/inspect/plugin-dirac.xml: + * docs/plugins/inspect/plugin-dtmf.xml: + * docs/plugins/inspect/plugin-dtsdec.xml: + * docs/plugins/inspect/plugin-dvb.xml: + * docs/plugins/inspect/plugin-dvdspu.xml: + * docs/plugins/inspect/plugin-faac.xml: + * docs/plugins/inspect/plugin-faad.xml: + * docs/plugins/inspect/plugin-fbdevsink.xml: + * docs/plugins/inspect/plugin-festival.xml: + * docs/plugins/inspect/plugin-freeze.xml: + * docs/plugins/inspect/plugin-frei0r.xml: + * docs/plugins/inspect/plugin-gaudieffects.xml: + * docs/plugins/inspect/plugin-geometrictransform.xml: + * docs/plugins/inspect/plugin-gsettings.xml: + * docs/plugins/inspect/plugin-gsm.xml: + * docs/plugins/inspect/plugin-gstsiren.xml: + * docs/plugins/inspect/plugin-h264parse.xml: + * docs/plugins/inspect/plugin-hdvparse.xml: + * docs/plugins/inspect/plugin-id3tag.xml: + * docs/plugins/inspect/plugin-invtelecine.xml: + * docs/plugins/inspect/plugin-ivfparse.xml: + * docs/plugins/inspect/plugin-jack.xml: + * docs/plugins/inspect/plugin-jpegformat.xml: + * docs/plugins/inspect/plugin-kate.xml: + * docs/plugins/inspect/plugin-ladspa.xml: + * docs/plugins/inspect/plugin-legacyresample.xml: + * docs/plugins/inspect/plugin-liveadder.xml: + * docs/plugins/inspect/plugin-metadata.xml: + * docs/plugins/inspect/plugin-mimic.xml: + * docs/plugins/inspect/plugin-mms.xml: + * docs/plugins/inspect/plugin-modplug.xml: + * docs/plugins/inspect/plugin-mpeg2enc.xml: + * docs/plugins/inspect/plugin-mpeg4videoparse.xml: + * docs/plugins/inspect/plugin-mpegdemux2.xml: + * docs/plugins/inspect/plugin-mpegpsmux.xml: + * docs/plugins/inspect/plugin-mpegtsmux.xml: + * docs/plugins/inspect/plugin-mpegvideoparse.xml: + * docs/plugins/inspect/plugin-mplex.xml: + * docs/plugins/inspect/plugin-musepack.xml: + * docs/plugins/inspect/plugin-musicbrainz.xml: + * docs/plugins/inspect/plugin-mve.xml: + * docs/plugins/inspect/plugin-mxf.xml: + * docs/plugins/inspect/plugin-mythtv.xml: + * docs/plugins/inspect/plugin-nas.xml: + * docs/plugins/inspect/plugin-neon.xml: + * docs/plugins/inspect/plugin-nsf.xml: + * docs/plugins/inspect/plugin-nuvdemux.xml: + * docs/plugins/inspect/plugin-ofa.xml: + * docs/plugins/inspect/plugin-pcapparse.xml: + * docs/plugins/inspect/plugin-pnm.xml: + * docs/plugins/inspect/plugin-qtmux.xml: + * docs/plugins/inspect/plugin-rawparse.xml: + * docs/plugins/inspect/plugin-real.xml: + * docs/plugins/inspect/plugin-resindvd.xml: + * docs/plugins/inspect/plugin-rfbsrc.xml: + * docs/plugins/inspect/plugin-rsvg.xml: + * docs/plugins/inspect/plugin-rtpmux.xml: + * docs/plugins/inspect/plugin-scaletempo.xml: + * docs/plugins/inspect/plugin-schro.xml: + * docs/plugins/inspect/plugin-sdl.xml: + * docs/plugins/inspect/plugin-sdp.xml: + * docs/plugins/inspect/plugin-segmentclip.xml: + * docs/plugins/inspect/plugin-selector.xml: + * docs/plugins/inspect/plugin-shm.xml: + * docs/plugins/inspect/plugin-sndfile.xml: + * docs/plugins/inspect/plugin-soundtouch.xml: + * docs/plugins/inspect/plugin-speed.xml: + * docs/plugins/inspect/plugin-stereo.xml: + * docs/plugins/inspect/plugin-subenc.xml: + * docs/plugins/inspect/plugin-tta.xml: + * docs/plugins/inspect/plugin-valve.xml: + * docs/plugins/inspect/plugin-vcdsrc.xml: + * docs/plugins/inspect/plugin-vdpau.xml: + * docs/plugins/inspect/plugin-videomaxrate.xml: + * docs/plugins/inspect/plugin-videomeasure.xml: + * docs/plugins/inspect/plugin-videosignal.xml: + * docs/plugins/inspect/plugin-vmnc.xml: + * docs/plugins/inspect/plugin-vp8.xml: + * docs/plugins/inspect/plugin-wildmidi.xml: + * docs/plugins/inspect/plugin-xvid.xml: + * docs/plugins/inspect/plugin-zbar.xml: + * win32/common/config.h: + Back to development + Temporarily disable -DGST_DISABLE_DEPRECATED for git builds until + the code is updated for the GST_FLOW_IS_* macro deprecations. + +2010-09-01 22:05:43 +0200 Andoni Morales Alastruey + + * gst/mpegtsmux/tsmux/tsmux.c: + * gst/mpegtsmux/tsmux/tsmuxstream.c: + * gst/mpegtsmux/tsmux/tsmuxstream.h: + mpegtsmux: Initialize PES packet before getting the header size. + The PES header length is calculated before setting the dynamic flags, returning + a wrong value. Small frames that should be sent in a single TS packet are + spawned to a new packet because of that error. For audio streams where a single + frame can cope in one TS packet it introduces a huge overhead. + For a 100B packet, we prepare a TS packet with a payload of(100+9)B. Then, we + write the TS header using this value in tsmux_write_ts_header, and call + tsmux_stream_get_data(). The dynamic flags where not set yet and now + tsmux_stream_pes_header_length() returns 14B instead of 9B. The payload of the + TS packet is 114B, 5B more than what was calculated. 109B are sent in a first + packet and the remaining 5B are sent in another one. + Fixes bug #628548. + +2010-09-02 10:23:30 +0200 Sebastian Dröge + + * ext/cog/gstcogcolorspace.c: + cogcolorspace: Classify as Filter/Converter/Video instead of effect + Fixes bug #628570. + +2010-09-01 18:30:17 +0200 Thibault Saunier + + * gst/videosignal/gstvideoanalyse.c: + videoanalyse: Use correct element classification + This is no effect but an analyzer. Fixes bug #628527. + +=== release 0.10.20 === + +2010-09-03 00:23:02 +0100 Tim-Philipp Müller + + * ChangeLog: + * NEWS: + * RELEASE: + * configure.ac: + * ext/cog/gstcogorc-dist.c: + * ext/cog/gstcogorc-dist.h: + * gst-plugins-bad.doap: + * win32/common/config.h: + Release 0.10.20 + +2010-09-03 00:21:06 +0100 Tim-Philipp Müller + + * docs/plugins/gst-plugins-bad-plugins.args: + * docs/plugins/gst-plugins-bad-plugins.hierarchy: + * docs/plugins/gst-plugins-bad-plugins.interfaces: + * docs/plugins/gst-plugins-bad-plugins.prerequisites: + * docs/plugins/inspect/plugin-adpcmdec.xml: + * docs/plugins/inspect/plugin-adpcmenc.xml: + * docs/plugins/inspect/plugin-aiff.xml: + * docs/plugins/inspect/plugin-alsaspdif.xml: + * docs/plugins/inspect/plugin-amrwbenc.xml: + * docs/plugins/inspect/plugin-apexsink.xml: + * docs/plugins/inspect/plugin-asfmux.xml: + * docs/plugins/inspect/plugin-assrender.xml: + * docs/plugins/inspect/plugin-audioparsersbad.xml: + * docs/plugins/inspect/plugin-autoconvert.xml: + * docs/plugins/inspect/plugin-bayer.xml: + * docs/plugins/inspect/plugin-bz2.xml: + * docs/plugins/inspect/plugin-camerabin.xml: + * docs/plugins/inspect/plugin-cdaudio.xml: + * docs/plugins/inspect/plugin-cdxaparse.xml: + * docs/plugins/inspect/plugin-celt.xml: + * docs/plugins/inspect/plugin-cog.xml: + * docs/plugins/inspect/plugin-coloreffects.xml: + * docs/plugins/inspect/plugin-dataurisrc.xml: + * docs/plugins/inspect/plugin-dc1394.xml: + * docs/plugins/inspect/plugin-dccp.xml: + * docs/plugins/inspect/plugin-debugutilsbad.xml: + * docs/plugins/inspect/plugin-dfbvideosink.xml: + * docs/plugins/inspect/plugin-dirac.xml: + * docs/plugins/inspect/plugin-dtmf.xml: + * docs/plugins/inspect/plugin-dtsdec.xml: + * docs/plugins/inspect/plugin-dvb.xml: + * docs/plugins/inspect/plugin-dvdspu.xml: + * docs/plugins/inspect/plugin-faac.xml: + * docs/plugins/inspect/plugin-faad.xml: + * docs/plugins/inspect/plugin-fbdevsink.xml: + * docs/plugins/inspect/plugin-festival.xml: + * docs/plugins/inspect/plugin-freeze.xml: + * docs/plugins/inspect/plugin-frei0r.xml: + * docs/plugins/inspect/plugin-gaudieffects.xml: + * docs/plugins/inspect/plugin-geometrictransform.xml: + * docs/plugins/inspect/plugin-gsettings.xml: + * docs/plugins/inspect/plugin-gsm.xml: + * docs/plugins/inspect/plugin-gstsiren.xml: + * docs/plugins/inspect/plugin-h264parse.xml: + * docs/plugins/inspect/plugin-hdvparse.xml: + * docs/plugins/inspect/plugin-id3tag.xml: + * docs/plugins/inspect/plugin-invtelecine.xml: + * docs/plugins/inspect/plugin-ivfparse.xml: + * docs/plugins/inspect/plugin-jack.xml: + * docs/plugins/inspect/plugin-jpegformat.xml: + * docs/plugins/inspect/plugin-kate.xml: + * docs/plugins/inspect/plugin-ladspa.xml: + * docs/plugins/inspect/plugin-legacyresample.xml: + * docs/plugins/inspect/plugin-liveadder.xml: + * docs/plugins/inspect/plugin-metadata.xml: + * docs/plugins/inspect/plugin-mimic.xml: + * docs/plugins/inspect/plugin-mms.xml: + * docs/plugins/inspect/plugin-modplug.xml: + * docs/plugins/inspect/plugin-mpeg2enc.xml: + * docs/plugins/inspect/plugin-mpeg4videoparse.xml: + * docs/plugins/inspect/plugin-mpegdemux2.xml: + * docs/plugins/inspect/plugin-mpegpsmux.xml: + * docs/plugins/inspect/plugin-mpegtsmux.xml: + * docs/plugins/inspect/plugin-mpegvideoparse.xml: + * docs/plugins/inspect/plugin-mplex.xml: + * docs/plugins/inspect/plugin-musepack.xml: + * docs/plugins/inspect/plugin-musicbrainz.xml: + * docs/plugins/inspect/plugin-mve.xml: + * docs/plugins/inspect/plugin-mxf.xml: + * docs/plugins/inspect/plugin-mythtv.xml: + * docs/plugins/inspect/plugin-nas.xml: + * docs/plugins/inspect/plugin-neon.xml: + * docs/plugins/inspect/plugin-nsf.xml: + * docs/plugins/inspect/plugin-nuvdemux.xml: + * docs/plugins/inspect/plugin-ofa.xml: + * docs/plugins/inspect/plugin-pcapparse.xml: + * docs/plugins/inspect/plugin-pnm.xml: + * docs/plugins/inspect/plugin-qtmux.xml: + * docs/plugins/inspect/plugin-rawparse.xml: + * docs/plugins/inspect/plugin-real.xml: + * docs/plugins/inspect/plugin-resindvd.xml: + * docs/plugins/inspect/plugin-rfbsrc.xml: + * docs/plugins/inspect/plugin-rsvg.xml: + * docs/plugins/inspect/plugin-rtpmux.xml: + * docs/plugins/inspect/plugin-scaletempo.xml: + * docs/plugins/inspect/plugin-schro.xml: + * docs/plugins/inspect/plugin-sdl.xml: + * docs/plugins/inspect/plugin-sdp.xml: + * docs/plugins/inspect/plugin-segmentclip.xml: + * docs/plugins/inspect/plugin-selector.xml: + * docs/plugins/inspect/plugin-shm.xml: + * docs/plugins/inspect/plugin-sndfile.xml: + * docs/plugins/inspect/plugin-soundtouch.xml: + * docs/plugins/inspect/plugin-speed.xml: + * docs/plugins/inspect/plugin-stereo.xml: + * docs/plugins/inspect/plugin-subenc.xml: + * docs/plugins/inspect/plugin-tta.xml: + * docs/plugins/inspect/plugin-valve.xml: + * docs/plugins/inspect/plugin-vcdsrc.xml: + * docs/plugins/inspect/plugin-vdpau.xml: + * docs/plugins/inspect/plugin-videomaxrate.xml: + * docs/plugins/inspect/plugin-videomeasure.xml: + * docs/plugins/inspect/plugin-videosignal.xml: + * docs/plugins/inspect/plugin-vmnc.xml: + * docs/plugins/inspect/plugin-vp8.xml: + * docs/plugins/inspect/plugin-wildmidi.xml: + * docs/plugins/inspect/plugin-xvid.xml: + * docs/plugins/inspect/plugin-zbar.xml: + docs: update for release + +2010-09-03 00:19:33 +0100 Tim-Philipp Müller * po/LINGUAS: * po/el.po: diff --git a/NEWS b/NEWS index c13dc907d3..65ed416fde 100644 --- a/NEWS +++ b/NEWS @@ -1,4 +1,196 @@ -This is GStreamer Bad Plug-ins 0.10.20, "For it is a Human Number" +This is GStreamer Bad Plug-ins 0.10.21, "Pink Noise" + +Changes since 0.10.20: + + * alsaspdif: removed alsaspdifsink element (replaced by alsasink device=spdif) + * metadata: remove metadata plugin + * jack: jack plugin has moved to gst-plugins-good (0.10.27) + * selector: input-selector and output-selector have moved to GStreamer core (0.10.32) + * valve: has moved to gstreamer core (0.10.32) + * applemedia: new plugin for Apple multimedia APIs (avfvideosrc, celvideosrc, qtkitvideosrc, miovideosrc, vth264decbin, vth264encbin, vtdec, vtenc) + * applemedia: new iOS video source based on AVFoundation + * y4mdec: new y4mdec element + * dcaparse: new dts/dca audio parser + * camerabin2: new camerabin element (work-in-progress, experimental) + * opencv: new plugin with elements facedetect, faceblur, edgedetect, cvsobel, cvsmooth, cvlaplace, cverode, cvequalizehist, cvdilate, textwrite, templatematch, pyramidsegment + * interlace: new element + * geometrictransform: new rotate element + * jp2kdecimator: add a JPEG2000 decimator element (drop details without reencoding) + * audioparsers: add dcaparse, a dts/dca parser, and mpegaudioparse (mp3parse replacement) + * autoconvert: add autovideoconvert, an autoconvert based video format converter + * checksumsink, chopmydata: new debug elements + * dvbsuboverlay: new element to overlay DVB subtitle + * rsvgoverlay: new element for scalable and relative svg overlay with cairo + * qtmux: add new ismlmux element, for fragmented isml major brand + * ac3parse: properly parse E-AC3 frame header and use proper EAC-3 caps + * ac3parse: relax BSID checking, performance improvements + * applemedia mtapi: update to reflect new API on iOS 4.x + * applemedia vtenc: bump H.264 level from 1.3 to 3.0 + * applemedia vtenc: remove keyframe enforcement workaround + * applemedia celapi: update to reflect new API on iOS 4.x + * applemedia cvapi: add wrapper for IO surface access + * audioparse: add support for setting the channel-positions + * audioparsers: increase ranks to enable auto-plugging (incl. new mp3 parser) + * baseparse: enhancements for timestamp marked framed formats + * baseparse: increase keyframe awareness + * baseparse: perform bitrate handling and posting after newsegment sending + * baseparse: post duration message if average bitrates is updated + * baseparse: prevent indefinite resyncing + * baseparse: add index support, seek table and accurate seek support + * baseparse: support reverse playback + * baseparse: use determined seekability in answering SEEKING query + * basevideo: Add handling of GstForceKeyUnit events + * basevideodecoder: add capture pattern handling; don't blow away field information + * bayer2rgb: add format=bggr/etc. to caps, add framerate to the sink caps + * camerabin: add "preview-source-filter","ready-for-capture", "idle" properties + * camerabin: change "zoom" property from int to float + * camerabin: enable all conversion flags by default to make it work out-of-the-box everywhere + * coloreffects: Add chromahold effect + * cog: improvements in colorspace and scaler; add fast paths for colorspace conversion + * colorspace: revive element and add support for many more pixellayouts/colorspaces + * colorspace: add support for SDTV/HDTV YUV conversions + * dtmfsrc: Make the dtmfsrc accept events sent with gst_element_send_event + * tools: misc. improvements to element-maker tool + * faac: handle trailing encoder output + * faad: support reverse playback; cater for decoder delay and renegotiation + * faad: tweak output buffer timestamping + * flacparse: don't drop the last frame if it is followed by garbage + * flacparse: don't parse the complete FLAC frames but only look for valid frame headers (for performance) + * flacparse: fix picture parsing, fix parsing with unknown framesizes + * flacparse: parse seektable + * frei0r: add support for the FREI0R_PATH environment variable + * frei0r: fix crashes if plugins don't provide correct property information + * frei0r: fix scanning of plugin subdirectories and support different vendors + * frei0r: update frei0r interface specification to 1.2 + * gaudieffects: avoid divide by 0 in burn element, make filter parameters dynamic and controllable + * id3mux: map GST_TAG_ALBUM_ARTIST, give PRIMARY rank + * invtelecine: Fix name of 30p/60i pattern + * jasperdec: don't fail hard on decoding error + * jifmux: detect EOI correctly; do not limit the size of the image on 16bits + * jp2kenc: Emit SOP markers in every codestream packet + * jpegparse: avoid infinite loop when resyncing; discard incomplete image + * kate: add segment tracking, and various other improvements + * kate: ensure the kate pad does not shoot ahead of the video pad + * mpegtsdemux: extract language for DVB subtitle streams + * mpegtsdemux: enable gather_pes only for DVB subtitle private streams + * mpegtsdemux: fix re-syncing on invalid data after seek + * mpegtsmux: Initialize PES packet before getting the header size + * mpegtsmux: Set adaptation flag when appropriate + * mpegtsmux: Set random_access_indicator for keyframes + * mpegtsparse: send TDT tables messages in a serialized event downstream + * ofa: Call g_object_notify() after the fingerprint was created + * pcapparse: Add support for Linux Cooked Capture (SLL) frames + * photography: add missing property and cabability flag for noise reduction + * photography: Add "zoom" and "image-preview-supported-caps" interface properties + * photography: add gst_photography_{set,get}_noise_reduction() and CAPS_NOISE_REDUCTION flag + * qtmux: add support for fragmented mp4 + * qtmux: add "streamable" property to avoid building fragmented mfra index + * qtmux: timestamp tracking fixes and many other fixes + * resindvd: attempt to use glib language setting for DVD menus/audio + * resindvd: improve error messages on read errors; button state tracking fixes + * rfbsrc: fail more gracefully if source gets disconnected or geometry changes + * sdlvideosink: re-enable YVYU and UYVY support + * sdpdemux: error out if no streams found in sdp message + * sdpdemux: redirect SDP with an rtsp control URL and add property to disable redirect + * ssim: add I420 support + * tiger: outline text by default, to make it easier to read + * winks: add property probing support; fix framerate fraction range mapping + * winks: ignore unsupported formats; work around shutdown deadlock + * winks: performance improvements + * zbar: make scanner cache optional, disable it by default + * zbar: use correct strides, support more formats + +Bugs fixed since 0.10.20: + + * 628609 : The qtwrapperaudiodec_samr decoder doesn't handle buffers containing many AMR frames properly + * 639296 : [y4mdec] Doesn't handle files which don't specify a colorspace + * 613379 : camerabin: Do not use audio clock after stopping video capture + * 636279 : REGRESSION: Video often freezes during playback of mpeg2 files + * 630255 : [examples] camerabin example still uses old GstXOverlay interface + * 631232 : [colorspace] AYUV/ARGB handling broken on big endian systems + * 627229 : fpsdisplaysink should not measure fps relative to pipeline clock + * 435120 : cairosvgoverlay + * 486659 : xmp/exif metadata handling + * 578629 : libgstphotography missing exports for MSVC + * 587223 : mpegtsdemux seg.fault due to invalid PMT_pid + * 598078 : osxvideosrc doesn't build in snow leopard x86_64 + * 600929 : [kate] tiger element doesn't handle segments and text/video synchronization properly + * 603063 : camerabin example fails to start recording + * 611428 : [gdiscreencapsrc] leaks memory (ICONINFO) + * 613633 : [resindvd] scrambled DVDs yield useless generic error message if dvdcss is not available + * 616814 : Photography interface extension: colour tone mode and noise reduction settings + * 616923 : camerabin: remove photography interface implementation + * 618045 : [cogcolorspace] No Y41B support + * 618542 : DVB subtitles support + * 625558 : [basevideoencoder] [vp8] encoder timestamps are wrong when there are gaps + * 626425 : cog_virt_frame_new_convert_u8 has bogus source data + * 627134 : photography interface: add API for capture correction + * 627211 : jpegformat: Push tags after setting srcpad caps + * 627253 : [mpegtsparse] Post tags of channel and currently running event + * 627992 : dtmfsrc doesn't support gst_element_send_event + * 628326 : vdpau: don't change structure in setcaps function + * 628527 : videoanalyse: classificication is wrong + * 628548 : [mpegtsmux] Initialize PES packet before getting the header size + * 628570 : cogcolorspace: element classificication is wrong + * 629554 : dvbsrc: Fix example usage, bandwidth=8 not 8MHz + * 629897 : [cog] Ignores --disable-orc and always requires orc + * 629910 : jpegparse: properly clean up comment string + * 629917 : [output-selector] Recheck pending_pad after pushing a buffer + * 630046 : sdpdemux: Add optional support for rtspsrc as session element + * 630253 : [sdl] Still uses old GstXOverlay interface + * 630254 : [vdpau] Still uses old GstXOverlay interface + * 630783 : [frei0r] Crashes if broken plugins don't give correct property information + * 630808 : valve: move to core + * 631200 : flacparse: major performance improvements + * 631389 : [flacparse] backport/check corner case fixes done in flacdec + * 631449 : [audioparse] doest not support several channel numbers + * 631501 : [faad] failed to dynamically switch from 2 audio channels to 6 + * 631814 : [flacparse] unit test failures + * 631993 : [flacparse] imperfect timestamping + * 632070 : qtmux: infinite loop + * 632668 : Gaudi Effects [review] + * 632885 : Gaudi Effects dynamically controllable parameters [review] + * 632911 : qtmux: add fragmented mp4 support (isml brand) + * 633466 : [katedec] Pushes events before the final caps are known + * 633917 : [mpegtsparse] [PATCH] Send TDT messages in an serialized event downstream + * 635200 : [dvbbasebin] [PATCH] Add TDT to the initial pids filter for dvbsrc + * 635202 : mpeg4videoparse: Minor fixes + * 635204 : mpeg4videoparse: Set srcpad caps before forwarding newsegment + * 635205 : h264parse: Set srcpad caps before forwarding newsegment + * 635229 : celtenc: uninitialized tags variable can cause segfault + * 635304 : [opencv] fix caps issues and extend supported caps for some elements [PATCH] + * 635397 : rfbsrc: avoid infinite loop if source gets disconnected and don't crash if frame geometry changes + * 635529 : interlace: Add pattern offset and fix timestamps + * 635720 : vp8enc incorrectly sets timestamps based on theoretical framerate + * 635786 : [audioparse] Fix division-by-zero exception + * 635878 : [qtmux] gst_qtmux_check_difference subtract 2 unsigned numbers without taking care of the result sign + * 636106 : autocolorspace: new plugin for auto space convertor selection + * 636109 : [SSIM] klass should be Filter/Effect/Video + * 636185 : qtmux: msvc incompatibility + * 637062 : [ac3parse] parse problems on some MTS streams + * 637224 : [bayer2rgb] missing framerate in sink caps + * 637308 : gst-plugins-bad did not find xvidcore on my box + * 637359 : Internal GStreamer error, during pcap to mp4 conversion + * 637403 : qtmux do not store 1st TS when detect 1st buffer + * 637486 : qtmux: error if no buffers have arrived to one pad at EOS + * 637532 : applemedia: redundant declaration of 'parent_class' + * 637590 : [PATCH] fix gst-plugins-bad compile against latest gtk+ + * 637824 : mpeg4videoparse: gst_buffer_is_metadata_writable warning (regression) + * 637929 : mve: do not use the pad buffer allocation functions in demuxers + * 637931 : mpegdemux: do not use the pad buffer allocation functions in demuxers + * 638004 : tiger: fallback on headers in caps to initialize if headers are absent + * 638288 : qtmux: fails to handle out-of-order buffers without duration + * 638412 : kate: reenable the sending of a message for tags + * 638527 : tiger: outline text by default, to make it easier to read + * 638604 : basecamerasrc isn't build by default but camerabin2 is and requires it + * 639063 : mpegtsparse: fix (re)sync with invalid data at beginning + * 639338 : [qtmux] Protect against copying a null caps + * 639413 : Camerabin should use output-selector:pad-negotiation-mode=active + * 639456 : [camerabin] Should have all conversion flags enabled by default + * 639555 : [audioparsers] Be careful to not lose the event ref + * 639950 : flacparse: avoid unref'ing NULL buffer + * 630830 : zbar: Fixes, single frame scan and width/stride fix + * 635281 : [mpegtsparse] TDT packets are only parsed for odd hours Changes since 0.10.19: diff --git a/RELEASE b/RELEASE index 8f8ae896c3..f35e3d6374 100644 --- a/RELEASE +++ b/RELEASE @@ -1,5 +1,5 @@ -Release notes for GStreamer Bad Plug-ins 0.10.20 "For it is a Human Number" +Release notes for GStreamer Bad Plug-ins 0.10.21 "Pink Noise" @@ -60,122 +60,195 @@ contains a set of well-supported plug-ins, but might pose problems for Features of this release - * asfmux streaming fixes and improvements - * new video effects plugins: coloreffects, gaudieffects, geometrictransform - * new gsettings plugin with gsettings{audio,video}{src,sink} elements - * new ivfparse element - * new rtmpsrc element - * new shmsink and shmsrc elements for IPC using shared memory - * new videomaxrate element - * dshowvideosink improvements - * vdpau: H.264 and MPEG-4 decoder (not enabled for autoplugging yet though) - * vp8enc: support multipass encoding and keyframe-only mode - * neonhttpsrc: timeout properties and cookie support - * h264parse and mpegvideoparse: can periodically insert codec data into stream now - * build: require GLib >= 2.20, automake >= 1.10, autoconf >= 2.60, want orc - * asfmux: deprecate "is-live" property, replaced by new "streamable" property - * asfmux: don't set the 'seekable' flag in headers if we are streaming - * asfmux: put headers into "streamheader" field in output caps for streaming - * asfmux: write preroll info in the header at initialization - * bayer: support more formats in bayer2rgb, add rgb2bayer element - * camerabin: make viewfinder-sink property work with bins - * celt: add support for celt 0.8, remove support for celt < 0.5 - * celtenc: add "prediction" and "start band" properties - * coloreffects: new element with heat, sepia, xray and cross-process effects - * dshowvideosink: many fixes and improvements - * fpsdisplaysink: add "fps-update-interval" and read-only "max-fps"/"min-fps" properties - * frei0r: check for plugins in /usr/{local/,}lib{32,64}/frei0r-1 too - * gaudieffects: new plugin with burn, chromium, dilate, dodge, exclusion, gaussianblur and solarize video effect elements - * geometrictransform: new plugin with circle, diffuse, kaleidoscope, marble, pinch, sphere, twirl, and waterripple, fisheye, mirror, square, tunnel, bulge, stretch video effect elements - * gsettings: new GSettings plugin with audio/video sources and sinks (to replace gconf plugin) - * h264parse: add "config-interval" property to insert SPS/PPS at periodic intervals - * h264parse: handle 3-byte bytestream sync codes; process incoming timestamps more correctly - * id3mux: add support for beats-per-minute tag - * invtelecine: support more video formats, more pulldown formats, add "verify-field-flags" property - * ivfparse: add simple IVF parser element (simple framing for VP8 video data) - * jpegformat: add exif writing to jifmux and exif parsing to jpegparse - * jpegparse: skip extra 0xff markers, optimize jpeg image parsing - * mimic: lots of fixes and clean-ups - * mpeg4videoparse: add "config-interval" property to re-insert config in stream - * mpegtsmux: start pmt at 0x020; take all the pmt in the streamheaders - * mpegtsparse: actually work when we have small buffers coming in - * mpegvideoparse: apply previous timestamp when there isn't any newer - * neonhttpsrc: add "connect-timeout", "read-timeout" and "cookies" properties - * qtmux: write audio/video stream bitrates into header, if available - * qtmux: write track-number etc. tags even if count is not available - * rtmpsrc: new RTMP source element based on librtmp - * rtpdtmfmux: add priority sink pads and drop buffers on non-priority sink pads when something is incoming on the priority sink - * rtpmux: add support for GstBufferLists; aggregate incoming segments; fix buffer leak - * shm: add new shm-based shmsink and shmsrc elements for IPC using shared memory - * vdpau: add H.264 decoder and MPEG-4 part 2 decoder; countless other fixes and improvements - * videomaxrate: new plugin/element to limit videorate conditionally based on threshold - * vp8dec: mark discont buffers, set decoder deadline from the QoS information - * vp8enc: allow a maximum keyframe distance of 0, i.e. all frames are keyframes - * vp8enc: fix handling of invisible/alt ref frames - * vp8enc: add support for enabling automatic insertion of alt-ref frames by the encoder - * vp8enc: implement multipass encoding - * wildmidi: Add support for wildmidi 0.2.3 + * alsaspdif: removed alsaspdifsink element (replaced by alsasink device=spdif) + * metadata: remove metadata plugin + * jack: jack plugin has moved to gst-plugins-good (0.10.27) + * selector: input-selector and output-selector have moved to GStreamer core (0.10.32) + * valve: has moved to gstreamer core (0.10.32) + * applemedia: new plugin for Apple multimedia APIs (avfvideosrc, celvideosrc, qtkitvideosrc, miovideosrc, vth264decbin, vth264encbin, vtdec, vtenc) + * applemedia: new iOS video source based on AVFoundation + * y4mdec: new y4mdec element + * dcaparse: new dts/dca audio parser + * camerabin2: new camerabin element (work-in-progress, experimental) + * opencv: new plugin with elements facedetect, faceblur, edgedetect, cvsobel, cvsmooth, cvlaplace, cverode, cvequalizehist, cvdilate, textwrite, templatematch, pyramidsegment + * interlace: new element + * geometrictransform: new rotate element + * jp2kdecimator: add a JPEG2000 decimator element (drop details without reencoding) + * audioparsers: add dcaparse, a dts/dca parser, and mpegaudioparse (mp3parse replacement) + * autoconvert: add autovideoconvert, an autoconvert based video format converter + * checksumsink, chopmydata: new debug elements + * dvbsuboverlay: new element to overlay DVB subtitle + * rsvgoverlay: new element for scalable and relative svg overlay with cairo + * qtmux: add new ismlmux element, for fragmented isml major brand + * ac3parse: properly parse E-AC3 frame header and use proper EAC-3 caps + * ac3parse: relax BSID checking, performance improvements + * applemedia mtapi: update to reflect new API on iOS 4.x + * applemedia vtenc: bump H.264 level from 1.3 to 3.0 + * applemedia vtenc: remove keyframe enforcement workaround + * applemedia celapi: update to reflect new API on iOS 4.x + * applemedia cvapi: add wrapper for IO surface access + * audioparse: add support for setting the channel-positions + * audioparsers: increase ranks to enable auto-plugging (incl. new mp3 parser) + * baseparse: enhancements for timestamp marked framed formats + * baseparse: increase keyframe awareness + * baseparse: perform bitrate handling and posting after newsegment sending + * baseparse: post duration message if average bitrates is updated + * baseparse: prevent indefinite resyncing + * baseparse: add index support, seek table and accurate seek support + * baseparse: support reverse playback + * baseparse: use determined seekability in answering SEEKING query + * basevideo: Add handling of GstForceKeyUnit events + * basevideodecoder: add capture pattern handling; don't blow away field information + * bayer2rgb: add format=bggr/etc. to caps, add framerate to the sink caps + * camerabin: add "preview-source-filter","ready-for-capture", "idle" properties + * camerabin: change "zoom" property from int to float + * camerabin: enable all conversion flags by default to make it work out-of-the-box everywhere + * coloreffects: Add chromahold effect + * cog: improvements in colorspace and scaler; add fast paths for colorspace conversion + * colorspace: revive element and add support for many more pixellayouts/colorspaces + * colorspace: add support for SDTV/HDTV YUV conversions + * dtmfsrc: Make the dtmfsrc accept events sent with gst_element_send_event + * tools: misc. improvements to element-maker tool + * faac: handle trailing encoder output + * faad: support reverse playback; cater for decoder delay and renegotiation + * faad: tweak output buffer timestamping + * flacparse: don't drop the last frame if it is followed by garbage + * flacparse: don't parse the complete FLAC frames but only look for valid frame headers (for performance) + * flacparse: fix picture parsing, fix parsing with unknown framesizes + * flacparse: parse seektable + * frei0r: add support for the FREI0R_PATH environment variable + * frei0r: fix crashes if plugins don't provide correct property information + * frei0r: fix scanning of plugin subdirectories and support different vendors + * frei0r: update frei0r interface specification to 1.2 + * gaudieffects: avoid divide by 0 in burn element, make filter parameters dynamic and controllable + * id3mux: map GST_TAG_ALBUM_ARTIST, give PRIMARY rank + * invtelecine: Fix name of 30p/60i pattern + * jasperdec: don't fail hard on decoding error + * jifmux: detect EOI correctly; do not limit the size of the image on 16bits + * jp2kenc: Emit SOP markers in every codestream packet + * jpegparse: avoid infinite loop when resyncing; discard incomplete image + * kate: add segment tracking, and various other improvements + * kate: ensure the kate pad does not shoot ahead of the video pad + * mpegtsdemux: extract language for DVB subtitle streams + * mpegtsdemux: enable gather_pes only for DVB subtitle private streams + * mpegtsdemux: fix re-syncing on invalid data after seek + * mpegtsmux: Initialize PES packet before getting the header size + * mpegtsmux: Set adaptation flag when appropriate + * mpegtsmux: Set random_access_indicator for keyframes + * mpegtsparse: send TDT tables messages in a serialized event downstream + * ofa: Call g_object_notify() after the fingerprint was created + * pcapparse: Add support for Linux Cooked Capture (SLL) frames + * photography: add missing property and cabability flag for noise reduction + * photography: Add "zoom" and "image-preview-supported-caps" interface properties + * photography: add gst_photography_{set,get}_noise_reduction() and CAPS_NOISE_REDUCTION flag + * qtmux: add support for fragmented mp4 + * qtmux: add "streamable" property to avoid building fragmented mfra index + * qtmux: timestamp tracking fixes and many other fixes + * resindvd: attempt to use glib language setting for DVD menus/audio + * resindvd: improve error messages on read errors; button state tracking fixes + * rfbsrc: fail more gracefully if source gets disconnected or geometry changes + * sdlvideosink: re-enable YVYU and UYVY support + * sdpdemux: error out if no streams found in sdp message + * sdpdemux: redirect SDP with an rtsp control URL and add property to disable redirect + * ssim: add I420 support + * tiger: outline text by default, to make it easier to read + * winks: add property probing support; fix framerate fraction range mapping + * winks: ignore unsupported formats; work around shutdown deadlock + * winks: performance improvements + * zbar: make scanner cache optional, disable it by default + * zbar: use correct strides, support more formats Bugs fixed in this release - * 625908 : [geometrictransform] Some more configuration options for effects - * 625076 : neonhttpsrc: add connect-timeout and read-timeout properties - * 620746 : basevideodecoder: remove spurious warning - * 566614 : bayer2rgb: Make first line configurable - * 570428 : autogen.sh fails - * 574290 : [dshowvideosink] make set_xwindow_id() in PLAYING state work - * 579926 : [directshowvideosink] Doesn't update the last frame after a seek with the pipeline in PAUSED state. - * 580967 : shared memory based sink and source - * 591622 : [vdpau] needs better error/failure handling - * 602551 : dshowvideosink window close doesn't cause gst-launch to exit - * 602936 : [ mp4mux] Lipsync issue when converting mkv to mp4 using h264/aac - * 613346 : [dshowvideosink] Add support for updating video caps - * 616265 : Add a GSettings plugin that provides the same services as the GConf plugin - * 618336 : [mpegvideoparse] mpegvideoparse makes some streams unplayable - * 618522 : [asfmux][patch] Improve support for streaming - * 618921 : [dshowvideosink] Replace CoIntialize with CoInitializeEx for bettrer integration with GStreamer threads - * 618936 : [dshowvideosink] close the created window in ::stop() - * 620324 : Format warning in ivfparse - * 620717 : [geometrytransform] Incomplete template caps - * 620825 : [geometrytransform] Make properties controllable and threadsafe - * 620978 : insert NAL7/8 always when encountering I frame - * 621205 : [mpeg4videoparse] add config-interval property to insert mpeg4video config data in regular intervals - * 621348 : [vp8enc] Implement multipass encoding - * 621523 : [id3mux] write beats-per-minute tag - * 622369 : [rtmpsrc] crash if correct server but wrong video file name - * 622484 : [qtmux] missing track number tag when transcoding to aac - * 622690 : elements/jpegparse check fails - * 622692 : pipelines/metadata check fails - * 622725 : [mpgtsparse] Doesn't remove pids from pes_pids - * 623272 : [dshowvideosink] setting force-aspect-ratio has no effect after the sink's renderer has been configured - * 623365 : [qtmux and variant] Don't store codec tags - * 623550 : doesn't compile with celt 0.8 - * 623678 : qtmux: Write AAC/H.264 bitrate if available - * 623710 : [frei0r] Load frei0r plugins in /usr/lib64/frei0r-1 too - * 623713 : [dshowaudiodec][patch] Fix compilation error - * 623722 : gstwildmidi element update to newer library version - * 623802 : camerabin: Bin based viewfinder sink support is broken - * 623854 : jpegparse reads a wrong EXIF section size - * 623881 : aiffmux.c divide by zero - * 623883 : [winks] gstksvideosrc.c error on MSVC using gst_element_class_set_details() - * 625003 : [examples] Don't use GdkDraw - * 625138 : [dshowvideosrc] Don't use a range in the caps if min==max - * 625174 : neonhttpsrc: adds cookies support - * 625496 : qtmux - misc fix on btrt box - * 625722 : [geometrictransform] Some new effect elements for cheese - * 625817 : coloreffects: new plugin for lookup table color mapping - * 625959 : geometrictransform: make CircleGeometricTransform " radius " property relative - * 626049 : [vdpau] crashes in states.check unit test - * 626603 : generic/states check fails with gsettings element installed - * 626670 : gaudieffects: Fails to link inline functions properly - * 626815 : vp8dec: infinite loop if EOS event before started - * 627413 : jifmux causes broken jpeg images at least with some rgb pixel format - * 627918 : Do not install gst-camera.ui - * 627991 : rtpmux will freeze whenever a flush is sent - * 624212 : mp4mux produces incorrect frame rates when h264 input uses bframes - * 619158 : IVF parser plugin - * 619484 : vp8dec: s/IMG_FMT_I420/VPX_IMG_FMT_I420/ - * 621404 : [dvbsrc] Set stats-reporting-interval on construction + * 628609 : The qtwrapperaudiodec_samr decoder doesn't handle buffers containing many AMR frames properly + * 639296 : [y4mdec] Doesn't handle files which don't specify a colorspace + * 613379 : camerabin: Do not use audio clock after stopping video capture + * 636279 : REGRESSION: Video often freezes during playback of mpeg2 files + * 630255 : [examples] camerabin example still uses old GstXOverlay interface + * 631232 : [colorspace] AYUV/ARGB handling broken on big endian systems + * 627229 : fpsdisplaysink should not measure fps relative to pipeline clock + * 435120 : cairosvgoverlay + * 486659 : xmp/exif metadata handling + * 578629 : libgstphotography missing exports for MSVC + * 587223 : mpegtsdemux seg.fault due to invalid PMT_pid + * 598078 : osxvideosrc doesn't build in snow leopard x86_64 + * 600929 : [kate] tiger element doesn't handle segments and text/video synchronization properly + * 603063 : camerabin example fails to start recording + * 611428 : [gdiscreencapsrc] leaks memory (ICONINFO) + * 613633 : [resindvd] scrambled DVDs yield useless generic error message if dvdcss is not available + * 616814 : Photography interface extension: colour tone mode and noise reduction settings + * 616923 : camerabin: remove photography interface implementation + * 618045 : [cogcolorspace] No Y41B support + * 618542 : DVB subtitles support + * 625558 : [basevideoencoder] [vp8] encoder timestamps are wrong when there are gaps + * 626425 : cog_virt_frame_new_convert_u8 has bogus source data + * 627134 : photography interface: add API for capture correction + * 627211 : jpegformat: Push tags after setting srcpad caps + * 627253 : [mpegtsparse] Post tags of channel and currently running event + * 627992 : dtmfsrc doesn't support gst_element_send_event + * 628326 : vdpau: don't change structure in setcaps function + * 628527 : videoanalyse: classificication is wrong + * 628548 : [mpegtsmux] Initialize PES packet before getting the header size + * 628570 : cogcolorspace: element classificication is wrong + * 629554 : dvbsrc: Fix example usage, bandwidth=8 not 8MHz + * 629897 : [cog] Ignores --disable-orc and always requires orc + * 629910 : jpegparse: properly clean up comment string + * 629917 : [output-selector] Recheck pending_pad after pushing a buffer + * 630046 : sdpdemux: Add optional support for rtspsrc as session element + * 630253 : [sdl] Still uses old GstXOverlay interface + * 630254 : [vdpau] Still uses old GstXOverlay interface + * 630783 : [frei0r] Crashes if broken plugins don't give correct property information + * 630808 : valve: move to core + * 631200 : flacparse: major performance improvements + * 631389 : [flacparse] backport/check corner case fixes done in flacdec + * 631449 : [audioparse] doest not support several channel numbers + * 631501 : [faad] failed to dynamically switch from 2 audio channels to 6 + * 631814 : [flacparse] unit test failures + * 631993 : [flacparse] imperfect timestamping + * 632070 : qtmux: infinite loop + * 632668 : Gaudi Effects [review] + * 632885 : Gaudi Effects dynamically controllable parameters [review] + * 632911 : qtmux: add fragmented mp4 support (isml brand) + * 633466 : [katedec] Pushes events before the final caps are known + * 633917 : [mpegtsparse] [PATCH] Send TDT messages in an serialized event downstream + * 635200 : [dvbbasebin] [PATCH] Add TDT to the initial pids filter for dvbsrc + * 635202 : mpeg4videoparse: Minor fixes + * 635204 : mpeg4videoparse: Set srcpad caps before forwarding newsegment + * 635205 : h264parse: Set srcpad caps before forwarding newsegment + * 635229 : celtenc: uninitialized tags variable can cause segfault + * 635304 : [opencv] fix caps issues and extend supported caps for some elements [PATCH] + * 635397 : rfbsrc: avoid infinite loop if source gets disconnected and don't crash if frame geometry changes + * 635529 : interlace: Add pattern offset and fix timestamps + * 635720 : vp8enc incorrectly sets timestamps based on theoretical framerate + * 635786 : [audioparse] Fix division-by-zero exception + * 635878 : [qtmux] gst_qtmux_check_difference subtract 2 unsigned numbers without taking care of the result sign + * 636106 : autocolorspace: new plugin for auto space convertor selection + * 636109 : [SSIM] klass should be Filter/Effect/Video + * 636185 : qtmux: msvc incompatibility + * 637062 : [ac3parse] parse problems on some MTS streams + * 637224 : [bayer2rgb] missing framerate in sink caps + * 637308 : gst-plugins-bad did not find xvidcore on my box + * 637359 : Internal GStreamer error, during pcap to mp4 conversion + * 637403 : qtmux do not store 1st TS when detect 1st buffer + * 637486 : qtmux: error if no buffers have arrived to one pad at EOS + * 637532 : applemedia: redundant declaration of 'parent_class' + * 637590 : [PATCH] fix gst-plugins-bad compile against latest gtk+ + * 637824 : mpeg4videoparse: gst_buffer_is_metadata_writable warning (regression) + * 637929 : mve: do not use the pad buffer allocation functions in demuxers + * 637931 : mpegdemux: do not use the pad buffer allocation functions in demuxers + * 638004 : tiger: fallback on headers in caps to initialize if headers are absent + * 638288 : qtmux: fails to handle out-of-order buffers without duration + * 638412 : kate: reenable the sending of a message for tags + * 638527 : tiger: outline text by default, to make it easier to read + * 638604 : basecamerasrc isn't build by default but camerabin2 is and requires it + * 639063 : mpegtsparse: fix (re)sync with invalid data at beginning + * 639338 : [qtmux] Protect against copying a null caps + * 639413 : Camerabin should use output-selector:pad-negotiation-mode=active + * 639456 : [camerabin] Should have all conversion flags enabled by default + * 639555 : [audioparsers] Be careful to not lose the event ref + * 639950 : flacparse: avoid unref'ing NULL buffer + * 630830 : zbar: Fixes, single frame scan and width/stride fix + * 635281 : [mpegtsparse] TDT packets are only parsed for odd hours Download @@ -204,39 +277,61 @@ Applications Contributors to this release + * Alejandro Gonzalez + * Aleksey Lim * Alessandro Decina - * Andoni Morales * Andoni Morales Alastruey + * Andres Colubri + * André Dieb Martins * Arun Raghavan - * Austin Lund - * Bastien Nocera - * Benjamin Otte + * Benjamin Gaignard * Carl-Anton Ingmarsson + * Christian Berentsen + * Damien Lespiau * David Hoyt * David Schleef * Edward Hervey - * Filippo Argiolas + * Felipe Contreras + * Francis Rammeloo + * Hoseok Chang + * Hu Gang * Jan Schmidt - * Jonathan Matthew - * Julien Moutte + * Janne Grunau + * Jonathan Rosser + * Josh Doe + * Kaj-Michael Lang + * Karol Sobczak + * Knut Inge Hvidsten + * Lasse Laukkanen + * Leo Singer + * Luciana Fujii Pontello * Luis de Bethencourt * Marc-André Lureau * Mark Nauwelaerts - * Michael Smith + * Mart Raudsepp + * Matthew Ife + * Mike Sheldon + * Noam + * Ole André Vadla Ravnås + * Olivier Aubert * Olivier Crête - * Philip Jägenstedt - * Philippe Normand - * Raimo Jarvi + * Rob Clark * Robert Swain - * Sameer Naik + * Saleem Abdulrasool * Sebastian Dröge * Sebastian Pölsterl + * Sreerenj Balachandran * Stefan Kost + * Teemu Katajisto * Thiago Santos + * Thibault Saunier * Thijs Vermeir * Tim-Philipp Müller + * Tristan Matthews + * Vincent Penquerc'h * Víctor Manuel Jáquez Leal + * Wim Taymans * Youness Alaoui - * Zaheer Abbas Merali - * Руслан Ижбулатов + * benjamin gaignard + * kapil   \ No newline at end of file diff --git a/configure.ac b/configure.ac index a63839ee72..fa6193d9d1 100644 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ AC_PREREQ(2.60) dnl initialize autoconf dnl when going to/from release please set the nano (fourth number) right ! dnl releases only do Wall, cvs and prerelease does Werror too -AC_INIT(GStreamer Bad Plug-ins, 0.10.20.4, +AC_INIT(GStreamer Bad Plug-ins, 0.10.21, http://bugzilla.gnome.org/enter_bug.cgi?product=GStreamer, gst-plugins-bad) @@ -50,8 +50,8 @@ AC_LIBTOOL_WIN32_DLL AM_PROG_LIBTOOL dnl *** required versions of GStreamer stuff *** -GST_REQ=0.10.31.3 -GSTPB_REQ=0.10.31.3 +GST_REQ=0.10.32 +GSTPB_REQ=0.10.32 dnl *** autotools stuff **** diff --git a/docs/plugins/gst-plugins-bad-plugins.args b/docs/plugins/gst-plugins-bad-plugins.args index 507785e802..5f7867d3cf 100644 --- a/docs/plugins/gst-plugins-bad-plugins.args +++ b/docs/plugins/gst-plugins-bad-plugins.args @@ -26550,7 +26550,7 @@ rw splash make a big splash in the center. -7.7486e-304 +4.62957e-299 @@ -26560,7 +26560,7 @@ rw splash make a big splash in the center. -4.62957e-299 +0 @@ -26590,7 +26590,7 @@ rw ratiox x-ratio. -2.35298e-310 +2.34233e-310 @@ -26600,7 +26600,7 @@ rw ratioy y-ratio. -2.35298e-310 +2.34233e-310 @@ -27180,7 +27180,7 @@ rw blend blend factor. --6.17056e+303 +0 @@ -27370,7 +27370,7 @@ rw HSync the hsync offset. -1.783e-316 +8.25792e-317 diff --git a/docs/plugins/inspect/plugin-adpcmdec.xml b/docs/plugins/inspect/plugin-adpcmdec.xml index 5fed1998e7..ea4d7c1bb8 100644 --- a/docs/plugins/inspect/plugin-adpcmdec.xml +++ b/docs/plugins/inspect/plugin-adpcmdec.xml @@ -3,10 +3,10 @@ ADPCM decoder ../../gst/adpcmdec/.libs/libgstadpcmdec.so libgstadpcmdec.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-adpcmenc.xml b/docs/plugins/inspect/plugin-adpcmenc.xml index db77e25619..6bd02f9a7a 100644 --- a/docs/plugins/inspect/plugin-adpcmenc.xml +++ b/docs/plugins/inspect/plugin-adpcmenc.xml @@ -3,10 +3,10 @@ ADPCM encoder ../../gst/adpcmenc/.libs/libgstadpcmenc.so libgstadpcmenc.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-aiff.xml b/docs/plugins/inspect/plugin-aiff.xml index 251fc9af05..34ba2d0b0b 100644 --- a/docs/plugins/inspect/plugin-aiff.xml +++ b/docs/plugins/inspect/plugin-aiff.xml @@ -3,10 +3,10 @@ Create and parse Audio Interchange File Format (AIFF) files ../../gst/aiff/.libs/libgstaiff.so libgstaiff.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-amrwbenc.xml b/docs/plugins/inspect/plugin-amrwbenc.xml index 59b53e43c3..30193a4f14 100644 --- a/docs/plugins/inspect/plugin-amrwbenc.xml +++ b/docs/plugins/inspect/plugin-amrwbenc.xml @@ -3,10 +3,10 @@ Adaptive Multi-Rate Wide-Band Encoder ../../ext/amrwbenc/.libs/libgstamrwbenc.so libgstamrwbenc.so - 0.10.20.4 + 0.10.21 unknown gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-apexsink.xml b/docs/plugins/inspect/plugin-apexsink.xml index f63b4daa12..2461df82bd 100644 --- a/docs/plugins/inspect/plugin-apexsink.xml +++ b/docs/plugins/inspect/plugin-apexsink.xml @@ -3,10 +3,10 @@ Apple AirPort Express Plugin ../../ext/apexsink/.libs/libgstapexsink.so libgstapexsink.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-asfmux.xml b/docs/plugins/inspect/plugin-asfmux.xml index e58698affd..d696168b70 100644 --- a/docs/plugins/inspect/plugin-asfmux.xml +++ b/docs/plugins/inspect/plugin-asfmux.xml @@ -3,10 +3,10 @@ ASF Muxer Plugin ../../gst/asfmux/.libs/libgstasfmux.so libgstasfmux.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-assrender.xml b/docs/plugins/inspect/plugin-assrender.xml index 3259c9586f..2b1d2096f1 100644 --- a/docs/plugins/inspect/plugin-assrender.xml +++ b/docs/plugins/inspect/plugin-assrender.xml @@ -3,10 +3,10 @@ ASS/SSA subtitle renderer ../../ext/assrender/.libs/libgstassrender.so libgstassrender.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-audioparsersbad.xml b/docs/plugins/inspect/plugin-audioparsersbad.xml index 9742fe6b2e..bcb472e251 100644 --- a/docs/plugins/inspect/plugin-audioparsersbad.xml +++ b/docs/plugins/inspect/plugin-audioparsersbad.xml @@ -3,10 +3,10 @@ audioparsers ../../gst/audioparsers/.libs/libgstaudioparsersbad.so libgstaudioparsersbad.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-autoconvert.xml b/docs/plugins/inspect/plugin-autoconvert.xml index 8a9b37d8e9..eb94791d07 100644 --- a/docs/plugins/inspect/plugin-autoconvert.xml +++ b/docs/plugins/inspect/plugin-autoconvert.xml @@ -3,10 +3,10 @@ Selects convertor element based on caps ../../gst/autoconvert/.libs/libgstautoconvert.so libgstautoconvert.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-bayer.xml b/docs/plugins/inspect/plugin-bayer.xml index 91cbeaefcc..8ec0494403 100644 --- a/docs/plugins/inspect/plugin-bayer.xml +++ b/docs/plugins/inspect/plugin-bayer.xml @@ -3,10 +3,10 @@ Elements to convert Bayer images ../../gst/bayer/.libs/libgstbayer.so libgstbayer.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-bz2.xml b/docs/plugins/inspect/plugin-bz2.xml index d0abf69390..e839fb99a0 100644 --- a/docs/plugins/inspect/plugin-bz2.xml +++ b/docs/plugins/inspect/plugin-bz2.xml @@ -3,10 +3,10 @@ Compress or decompress streams ../../ext/bz2/.libs/libgstbz2.so libgstbz2.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-camerabin.xml b/docs/plugins/inspect/plugin-camerabin.xml index 92cab93d3a..57225e4110 100644 --- a/docs/plugins/inspect/plugin-camerabin.xml +++ b/docs/plugins/inspect/plugin-camerabin.xml @@ -3,10 +3,10 @@ High level api for DC (Digital Camera) application ../../gst/camerabin/.libs/libgstcamerabin.so libgstcamerabin.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-cdaudio.xml b/docs/plugins/inspect/plugin-cdaudio.xml index 79181da849..2645ffbd76 100644 --- a/docs/plugins/inspect/plugin-cdaudio.xml +++ b/docs/plugins/inspect/plugin-cdaudio.xml @@ -3,10 +3,10 @@ Play CD audio through the CD Drive ../../ext/cdaudio/.libs/libgstcdaudio.so libgstcdaudio.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-cdxaparse.xml b/docs/plugins/inspect/plugin-cdxaparse.xml index d13c9c82af..6e2b1e41a3 100644 --- a/docs/plugins/inspect/plugin-cdxaparse.xml +++ b/docs/plugins/inspect/plugin-cdxaparse.xml @@ -3,10 +3,10 @@ Parse a .dat file (VCD) into raw mpeg1 ../../gst/cdxaparse/.libs/libgstcdxaparse.so libgstcdxaparse.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-celt.xml b/docs/plugins/inspect/plugin-celt.xml index 480591d405..6ff0a2c7bf 100644 --- a/docs/plugins/inspect/plugin-celt.xml +++ b/docs/plugins/inspect/plugin-celt.xml @@ -3,10 +3,10 @@ CELT plugin library ../../ext/celt/.libs/libgstcelt.so libgstcelt.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-cog.xml b/docs/plugins/inspect/plugin-cog.xml index aae4450f46..6f93c49088 100644 --- a/docs/plugins/inspect/plugin-cog.xml +++ b/docs/plugins/inspect/plugin-cog.xml @@ -3,10 +3,10 @@ Cog plugin ../../ext/cog/.libs/libgstcog.so libgstcog.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-coloreffects.xml b/docs/plugins/inspect/plugin-coloreffects.xml index 1e11bd7ce7..1fe65f9848 100644 --- a/docs/plugins/inspect/plugin-coloreffects.xml +++ b/docs/plugins/inspect/plugin-coloreffects.xml @@ -3,10 +3,10 @@ Color Look-up Table filters ../../gst/coloreffects/.libs/libgstcoloreffects.so libgstcoloreffects.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-colorspace.xml b/docs/plugins/inspect/plugin-colorspace.xml index 4fedf0054b..ec537ebe69 100644 --- a/docs/plugins/inspect/plugin-colorspace.xml +++ b/docs/plugins/inspect/plugin-colorspace.xml @@ -3,7 +3,7 @@ Colorspace conversion ../../gst/colorspace/.libs/libgstcolorspace.so libgstcolorspace.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad diff --git a/docs/plugins/inspect/plugin-dataurisrc.xml b/docs/plugins/inspect/plugin-dataurisrc.xml index 9313288bab..fa030d89c4 100644 --- a/docs/plugins/inspect/plugin-dataurisrc.xml +++ b/docs/plugins/inspect/plugin-dataurisrc.xml @@ -3,10 +3,10 @@ data: URI source ../../gst/dataurisrc/.libs/libgstdataurisrc.so libgstdataurisrc.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-dc1394.xml b/docs/plugins/inspect/plugin-dc1394.xml index 8e4d8a72e8..9cc17fc6bd 100644 --- a/docs/plugins/inspect/plugin-dc1394.xml +++ b/docs/plugins/inspect/plugin-dc1394.xml @@ -3,10 +3,10 @@ 1394 IIDC Video Source ../../ext/dc1394/.libs/libgstdc1394.so libgstdc1394.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-dccp.xml b/docs/plugins/inspect/plugin-dccp.xml index 6ee767366e..edf5b38d06 100644 --- a/docs/plugins/inspect/plugin-dccp.xml +++ b/docs/plugins/inspect/plugin-dccp.xml @@ -3,7 +3,7 @@ transfer data over the network via DCCP. ../../gst/dccp/.libs/libgstdccp.so libgstdccp.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad DCCP diff --git a/docs/plugins/inspect/plugin-debugutilsbad.xml b/docs/plugins/inspect/plugin-debugutilsbad.xml index ee790a387f..771ffea545 100644 --- a/docs/plugins/inspect/plugin-debugutilsbad.xml +++ b/docs/plugins/inspect/plugin-debugutilsbad.xml @@ -3,10 +3,10 @@ Collection of elements that may or may not be useful for debugging ../../gst/debugutils/.libs/libgstdebugutilsbad.so libgstdebugutilsbad.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-dfbvideosink.xml b/docs/plugins/inspect/plugin-dfbvideosink.xml index 0fae3cec42..0c70895d91 100644 --- a/docs/plugins/inspect/plugin-dfbvideosink.xml +++ b/docs/plugins/inspect/plugin-dfbvideosink.xml @@ -3,10 +3,10 @@ DirectFB video output plugin ../../ext/directfb/.libs/libgstdfbvideosink.so libgstdfbvideosink.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-dirac.xml b/docs/plugins/inspect/plugin-dirac.xml index 39265f116c..bd93fd152f 100644 --- a/docs/plugins/inspect/plugin-dirac.xml +++ b/docs/plugins/inspect/plugin-dirac.xml @@ -3,10 +3,10 @@ Dirac plugin ../../ext/dirac/.libs/libgstdirac.so libgstdirac.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-dtmf.xml b/docs/plugins/inspect/plugin-dtmf.xml index 12bab4fdca..6c3f7d05c2 100644 --- a/docs/plugins/inspect/plugin-dtmf.xml +++ b/docs/plugins/inspect/plugin-dtmf.xml @@ -3,10 +3,10 @@ DTMF plugins ../../gst/dtmf/.libs/libgstdtmf.so libgstdtmf.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-dtsdec.xml b/docs/plugins/inspect/plugin-dtsdec.xml index f23b007cae..1fa8b3bb9e 100644 --- a/docs/plugins/inspect/plugin-dtsdec.xml +++ b/docs/plugins/inspect/plugin-dtsdec.xml @@ -3,10 +3,10 @@ Decodes DTS audio streams ../../ext/dts/.libs/libgstdtsdec.so libgstdtsdec.so - 0.10.20.4 + 0.10.21 GPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-dvb.xml b/docs/plugins/inspect/plugin-dvb.xml index d04722dff8..e6ec4f3325 100644 --- a/docs/plugins/inspect/plugin-dvb.xml +++ b/docs/plugins/inspect/plugin-dvb.xml @@ -3,10 +3,10 @@ DVB elements ../../sys/dvb/.libs/libgstdvb.so libgstdvb.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-dvbsuboverlay.xml b/docs/plugins/inspect/plugin-dvbsuboverlay.xml index 14aa3f72ac..d851692dc7 100644 --- a/docs/plugins/inspect/plugin-dvbsuboverlay.xml +++ b/docs/plugins/inspect/plugin-dvbsuboverlay.xml @@ -3,10 +3,10 @@ DVB subtitle renderer ../../gst/dvbsuboverlay/.libs/libgstdvbsuboverlay.so libgstdvbsuboverlay.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-dvdspu.xml b/docs/plugins/inspect/plugin-dvdspu.xml index 5d996ad314..bc68134d9a 100644 --- a/docs/plugins/inspect/plugin-dvdspu.xml +++ b/docs/plugins/inspect/plugin-dvdspu.xml @@ -3,10 +3,10 @@ DVD Sub-picture Overlay element ../../gst/dvdspu/.libs/libgstdvdspu.so libgstdvdspu.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-faac.xml b/docs/plugins/inspect/plugin-faac.xml index 5c35e49ac4..3e59202b9b 100644 --- a/docs/plugins/inspect/plugin-faac.xml +++ b/docs/plugins/inspect/plugin-faac.xml @@ -3,10 +3,10 @@ Free AAC Encoder (FAAC) ../../ext/faac/.libs/libgstfaac.so libgstfaac.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-faad.xml b/docs/plugins/inspect/plugin-faad.xml index 93104bea1a..682e892679 100644 --- a/docs/plugins/inspect/plugin-faad.xml +++ b/docs/plugins/inspect/plugin-faad.xml @@ -3,10 +3,10 @@ Free AAC Decoder (FAAD) ../../ext/faad/.libs/libgstfaad.so libgstfaad.so - 0.10.20.4 + 0.10.21 GPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-fbdevsink.xml b/docs/plugins/inspect/plugin-fbdevsink.xml index 4b325bc0b2..b9aede2d9d 100644 --- a/docs/plugins/inspect/plugin-fbdevsink.xml +++ b/docs/plugins/inspect/plugin-fbdevsink.xml @@ -3,10 +3,10 @@ linux framebuffer video sink ../../sys/fbdev/.libs/libgstfbdevsink.so libgstfbdevsink.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-festival.xml b/docs/plugins/inspect/plugin-festival.xml index a4dc05b5ea..eef78927d4 100644 --- a/docs/plugins/inspect/plugin-festival.xml +++ b/docs/plugins/inspect/plugin-festival.xml @@ -3,10 +3,10 @@ Synthesizes plain text into audio ../../gst/festival/.libs/libgstfestival.so libgstfestival.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-freeze.xml b/docs/plugins/inspect/plugin-freeze.xml index 6024872fb9..ccbf9309f1 100644 --- a/docs/plugins/inspect/plugin-freeze.xml +++ b/docs/plugins/inspect/plugin-freeze.xml @@ -3,10 +3,10 @@ Stream freezer ../../gst/freeze/.libs/libgstfreeze.so libgstfreeze.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-frei0r.xml b/docs/plugins/inspect/plugin-frei0r.xml index d6b3b666b3..f0e73d306c 100644 --- a/docs/plugins/inspect/plugin-frei0r.xml +++ b/docs/plugins/inspect/plugin-frei0r.xml @@ -3,10 +3,10 @@ frei0r plugin library ../../gst/frei0r/.libs/libgstfrei0r.so libgstfrei0r.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-gaudieffects.xml b/docs/plugins/inspect/plugin-gaudieffects.xml index 9a41249224..7a0c464ba9 100644 --- a/docs/plugins/inspect/plugin-gaudieffects.xml +++ b/docs/plugins/inspect/plugin-gaudieffects.xml @@ -3,7 +3,7 @@ Gaudi video effects. ../../gst/gaudieffects/.libs/libgstgaudieffects.so libgstgaudieffects.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad GStreamer diff --git a/docs/plugins/inspect/plugin-geometrictransform.xml b/docs/plugins/inspect/plugin-geometrictransform.xml index 39ced8625f..5d6dcc3c53 100644 --- a/docs/plugins/inspect/plugin-geometrictransform.xml +++ b/docs/plugins/inspect/plugin-geometrictransform.xml @@ -3,10 +3,10 @@ Various geometric image transform elements ../../gst/geometrictransform/.libs/libgstgeometrictransform.so libgstgeometrictransform.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-gsettings.xml b/docs/plugins/inspect/plugin-gsettings.xml index 00c0e29b0e..98c95281f2 100644 --- a/docs/plugins/inspect/plugin-gsettings.xml +++ b/docs/plugins/inspect/plugin-gsettings.xml @@ -3,10 +3,10 @@ GSettings plugin ../../ext/gsettings/.libs/libgstgsettingselements.so libgstgsettingselements.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-gsm.xml b/docs/plugins/inspect/plugin-gsm.xml index 9c22a9e952..cf9f9d33a5 100644 --- a/docs/plugins/inspect/plugin-gsm.xml +++ b/docs/plugins/inspect/plugin-gsm.xml @@ -3,10 +3,10 @@ GSM encoder/decoder ../../ext/gsm/.libs/libgstgsm.so libgstgsm.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-gstsiren.xml b/docs/plugins/inspect/plugin-gstsiren.xml index 1bfc8cca8d..d436d93506 100644 --- a/docs/plugins/inspect/plugin-gstsiren.xml +++ b/docs/plugins/inspect/plugin-gstsiren.xml @@ -3,10 +3,10 @@ Siren encoder/decoder/payloader/depayloader plugins ../../gst/siren/.libs/libgstsiren.so libgstsiren.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-h264parse.xml b/docs/plugins/inspect/plugin-h264parse.xml index 82efb680bd..d941af7508 100644 --- a/docs/plugins/inspect/plugin-h264parse.xml +++ b/docs/plugins/inspect/plugin-h264parse.xml @@ -3,10 +3,10 @@ Element parsing raw h264 streams ../../gst/h264parse/.libs/libgsth264parse.so libgsth264parse.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-hdvparse.xml b/docs/plugins/inspect/plugin-hdvparse.xml index 796dbd1937..4039c2fd23 100644 --- a/docs/plugins/inspect/plugin-hdvparse.xml +++ b/docs/plugins/inspect/plugin-hdvparse.xml @@ -3,7 +3,7 @@ HDV private stream parser ../../gst/hdvparse/.libs/libgsthdvparse.so libgsthdvparse.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad GStreamer diff --git a/docs/plugins/inspect/plugin-id3tag.xml b/docs/plugins/inspect/plugin-id3tag.xml index c0367e9ba4..e3b3f583bd 100644 --- a/docs/plugins/inspect/plugin-id3tag.xml +++ b/docs/plugins/inspect/plugin-id3tag.xml @@ -3,10 +3,10 @@ ID3 v1 and v2 muxing plugin ../../gst/id3tag/.libs/libgstid3tag.so libgstid3tag.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-interlace.xml b/docs/plugins/inspect/plugin-interlace.xml index 89021ed1c6..48a56f006b 100644 --- a/docs/plugins/inspect/plugin-interlace.xml +++ b/docs/plugins/inspect/plugin-interlace.xml @@ -3,10 +3,10 @@ Create an interlaced video stream ../../gst/interlace/.libs/libgstinterlace.so libgstinterlace.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-invtelecine.xml b/docs/plugins/inspect/plugin-invtelecine.xml index d16c59864e..9ecbc29aa6 100644 --- a/docs/plugins/inspect/plugin-invtelecine.xml +++ b/docs/plugins/inspect/plugin-invtelecine.xml @@ -3,10 +3,10 @@ Inverse Telecine ../../gst/invtelecine/.libs/libgstinvtelecine.so libgstinvtelecine.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-ivfparse.xml b/docs/plugins/inspect/plugin-ivfparse.xml index 7d40d01f56..8738413e59 100644 --- a/docs/plugins/inspect/plugin-ivfparse.xml +++ b/docs/plugins/inspect/plugin-ivfparse.xml @@ -3,10 +3,10 @@ IVF parser ../../gst/ivfparse/.libs/libgstivfparse.so libgstivfparse.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-jp2kdecimator.xml b/docs/plugins/inspect/plugin-jp2kdecimator.xml index dea3ad93aa..5faa24885d 100644 --- a/docs/plugins/inspect/plugin-jp2kdecimator.xml +++ b/docs/plugins/inspect/plugin-jp2kdecimator.xml @@ -3,10 +3,10 @@ JPEG2000 decimator ../../gst/jp2kdecimator/.libs/libgstjp2kdecimator.so libgstjp2kdecimator.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-jpegformat.xml b/docs/plugins/inspect/plugin-jpegformat.xml index d33815fa8a..16835a96e7 100644 --- a/docs/plugins/inspect/plugin-jpegformat.xml +++ b/docs/plugins/inspect/plugin-jpegformat.xml @@ -3,10 +3,10 @@ JPEG interchange format plugin ../../gst/jpegformat/.libs/libgstjpegformat.so libgstjpegformat.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-kate.xml b/docs/plugins/inspect/plugin-kate.xml index a7a71a61fe..eb32c11930 100644 --- a/docs/plugins/inspect/plugin-kate.xml +++ b/docs/plugins/inspect/plugin-kate.xml @@ -3,10 +3,10 @@ Kate plugin ../../ext/kate/.libs/libgstkate.so libgstkate.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-ladspa.xml b/docs/plugins/inspect/plugin-ladspa.xml index f89b261cb3..a504393f0b 100644 --- a/docs/plugins/inspect/plugin-ladspa.xml +++ b/docs/plugins/inspect/plugin-ladspa.xml @@ -3,10 +3,10 @@ All LADSPA plugins ../../ext/ladspa/.libs/libgstladspa.so libgstladspa.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-legacyresample.xml b/docs/plugins/inspect/plugin-legacyresample.xml index 1ce3d4bade..1fc80f4a0e 100644 --- a/docs/plugins/inspect/plugin-legacyresample.xml +++ b/docs/plugins/inspect/plugin-legacyresample.xml @@ -3,10 +3,10 @@ Resamples audio ../../gst/legacyresample/.libs/libgstlegacyresample.so libgstlegacyresample.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-liveadder.xml b/docs/plugins/inspect/plugin-liveadder.xml index c7a1d6a88a..c3b58b9a38 100644 --- a/docs/plugins/inspect/plugin-liveadder.xml +++ b/docs/plugins/inspect/plugin-liveadder.xml @@ -3,10 +3,10 @@ Adds multiple live discontinuous streams ../../gst/liveadder/.libs/libgstliveadder.so libgstliveadder.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-mimic.xml b/docs/plugins/inspect/plugin-mimic.xml index 4f4e68af3c..f90e0f5470 100644 --- a/docs/plugins/inspect/plugin-mimic.xml +++ b/docs/plugins/inspect/plugin-mimic.xml @@ -3,10 +3,10 @@ Mimic codec ../../ext/mimic/.libs/libgstmimic.so libgstmimic.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-mms.xml b/docs/plugins/inspect/plugin-mms.xml index 116623e8cf..c85173cefa 100644 --- a/docs/plugins/inspect/plugin-mms.xml +++ b/docs/plugins/inspect/plugin-mms.xml @@ -3,10 +3,10 @@ Microsoft Multi Media Server streaming protocol support ../../ext/libmms/.libs/libgstmms.so libgstmms.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-modplug.xml b/docs/plugins/inspect/plugin-modplug.xml index b143c83508..4e5509da50 100644 --- a/docs/plugins/inspect/plugin-modplug.xml +++ b/docs/plugins/inspect/plugin-modplug.xml @@ -3,10 +3,10 @@ .MOD audio decoding ../../ext/modplug/.libs/libgstmodplug.so libgstmodplug.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-mpeg2enc.xml b/docs/plugins/inspect/plugin-mpeg2enc.xml index 4c2fee726d..2b62e3c981 100644 --- a/docs/plugins/inspect/plugin-mpeg2enc.xml +++ b/docs/plugins/inspect/plugin-mpeg2enc.xml @@ -3,10 +3,10 @@ High-quality MPEG-1/2 video encoder ../../ext/mpeg2enc/.libs/libgstmpeg2enc.so libgstmpeg2enc.so - 0.10.20.4 + 0.10.21 GPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-mpeg4videoparse.xml b/docs/plugins/inspect/plugin-mpeg4videoparse.xml index 912c0a4ab2..50385821e8 100644 --- a/docs/plugins/inspect/plugin-mpeg4videoparse.xml +++ b/docs/plugins/inspect/plugin-mpeg4videoparse.xml @@ -3,10 +3,10 @@ MPEG-4 video parser ../../gst/mpeg4videoparse/.libs/libgstmpeg4videoparse.so libgstmpeg4videoparse.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-mpegdemux2.xml b/docs/plugins/inspect/plugin-mpegdemux2.xml index 1dbe6921ed..01f8015fbc 100644 --- a/docs/plugins/inspect/plugin-mpegdemux2.xml +++ b/docs/plugins/inspect/plugin-mpegdemux2.xml @@ -3,10 +3,10 @@ MPEG demuxers ../../gst/mpegdemux/.libs/libgstmpegdemux.so libgstmpegdemux.so - 0.10.20.4 + 0.10.21 unknown gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-mpegpsmux.xml b/docs/plugins/inspect/plugin-mpegpsmux.xml index ff54c2b6e5..288f4fa463 100644 --- a/docs/plugins/inspect/plugin-mpegpsmux.xml +++ b/docs/plugins/inspect/plugin-mpegpsmux.xml @@ -3,10 +3,10 @@ MPEG-PS muxer ../../gst/mpegpsmux/.libs/libgstmpegpsmux.so libgstmpegpsmux.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-mpegtsmux.xml b/docs/plugins/inspect/plugin-mpegtsmux.xml index c23ea98d6c..f1cdcaa912 100644 --- a/docs/plugins/inspect/plugin-mpegtsmux.xml +++ b/docs/plugins/inspect/plugin-mpegtsmux.xml @@ -3,10 +3,10 @@ MPEG-TS muxer ../../gst/mpegtsmux/.libs/libgstmpegtsmux.so libgstmpegtsmux.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-mpegvideoparse.xml b/docs/plugins/inspect/plugin-mpegvideoparse.xml index d6a6e86b34..d281c555a6 100644 --- a/docs/plugins/inspect/plugin-mpegvideoparse.xml +++ b/docs/plugins/inspect/plugin-mpegvideoparse.xml @@ -3,10 +3,10 @@ MPEG-1 and MPEG-2 video parser ../../gst/mpegvideoparse/.libs/libgstmpegvideoparse.so libgstmpegvideoparse.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-mplex.xml b/docs/plugins/inspect/plugin-mplex.xml index 8683056679..9e16222194 100644 --- a/docs/plugins/inspect/plugin-mplex.xml +++ b/docs/plugins/inspect/plugin-mplex.xml @@ -3,10 +3,10 @@ High-quality MPEG/DVD/SVCD/VCD video/audio multiplexer ../../ext/mplex/.libs/libgstmplex.so libgstmplex.so - 0.10.20.4 + 0.10.21 GPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-musepack.xml b/docs/plugins/inspect/plugin-musepack.xml index d4fd9e4403..f03e65728a 100644 --- a/docs/plugins/inspect/plugin-musepack.xml +++ b/docs/plugins/inspect/plugin-musepack.xml @@ -3,10 +3,10 @@ Musepack decoder ../../ext/musepack/.libs/libgstmusepack.so libgstmusepack.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-musicbrainz.xml b/docs/plugins/inspect/plugin-musicbrainz.xml index f6a5d0f39c..058f28171e 100644 --- a/docs/plugins/inspect/plugin-musicbrainz.xml +++ b/docs/plugins/inspect/plugin-musicbrainz.xml @@ -3,10 +3,10 @@ A TRM signature producer based on libmusicbrainz ../../ext/musicbrainz/.libs/libgsttrm.so libgsttrm.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-mve.xml b/docs/plugins/inspect/plugin-mve.xml index 984c01fcc1..fdcafe19ed 100644 --- a/docs/plugins/inspect/plugin-mve.xml +++ b/docs/plugins/inspect/plugin-mve.xml @@ -3,10 +3,10 @@ Interplay MVE movie format manipulation ../../gst/mve/.libs/libgstmve.so libgstmve.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-mxf.xml b/docs/plugins/inspect/plugin-mxf.xml index e32d1a5f46..f5261fae5f 100644 --- a/docs/plugins/inspect/plugin-mxf.xml +++ b/docs/plugins/inspect/plugin-mxf.xml @@ -3,10 +3,10 @@ MXF plugin library ../../gst/mxf/.libs/libgstmxf.so libgstmxf.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-mythtv.xml b/docs/plugins/inspect/plugin-mythtv.xml index 90d1eb4050..923c5f4082 100644 --- a/docs/plugins/inspect/plugin-mythtv.xml +++ b/docs/plugins/inspect/plugin-mythtv.xml @@ -3,10 +3,10 @@ lib MythTV src ../../ext/mythtv/.libs/libgstmythtvsrc.so libgstmythtvsrc.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-nas.xml b/docs/plugins/inspect/plugin-nas.xml index 0b01234d6c..97e9ae50e5 100644 --- a/docs/plugins/inspect/plugin-nas.xml +++ b/docs/plugins/inspect/plugin-nas.xml @@ -3,10 +3,10 @@ NAS (Network Audio System) support for GStreamer ../../ext/nas/.libs/libgstnassink.so libgstnassink.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-neon.xml b/docs/plugins/inspect/plugin-neon.xml index c7cc2851c7..ef39b73d1d 100644 --- a/docs/plugins/inspect/plugin-neon.xml +++ b/docs/plugins/inspect/plugin-neon.xml @@ -3,10 +3,10 @@ lib neon http client src ../../ext/neon/.libs/libgstneonhttpsrc.so libgstneonhttpsrc.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-nsf.xml b/docs/plugins/inspect/plugin-nsf.xml index a80ef62e7c..3df601eb03 100644 --- a/docs/plugins/inspect/plugin-nsf.xml +++ b/docs/plugins/inspect/plugin-nsf.xml @@ -3,10 +3,10 @@ Uses nosefart to decode .nsf files ../../gst/nsf/.libs/libgstnsf.so libgstnsf.so - 0.10.20.4 + 0.10.21 GPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-nuvdemux.xml b/docs/plugins/inspect/plugin-nuvdemux.xml index 8113f436ec..970a23657f 100644 --- a/docs/plugins/inspect/plugin-nuvdemux.xml +++ b/docs/plugins/inspect/plugin-nuvdemux.xml @@ -3,10 +3,10 @@ Demuxes MythTV NuppelVideo files ../../gst/nuvdemux/.libs/libgstnuvdemux.so libgstnuvdemux.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-ofa.xml b/docs/plugins/inspect/plugin-ofa.xml index d99e287cdb..df1a4e3061 100644 --- a/docs/plugins/inspect/plugin-ofa.xml +++ b/docs/plugins/inspect/plugin-ofa.xml @@ -3,10 +3,10 @@ Calculate MusicIP fingerprint from audio files ../../ext/ofa/.libs/libgstofa.so libgstofa.so - 0.10.20.4 + 0.10.21 GPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-opencv.xml b/docs/plugins/inspect/plugin-opencv.xml index 27f966b667..7a63aa09e0 100644 --- a/docs/plugins/inspect/plugin-opencv.xml +++ b/docs/plugins/inspect/plugin-opencv.xml @@ -3,10 +3,10 @@ GStreamer OpenCV Plugins ../../ext/opencv/.libs/libgstopencv.so libgstopencv.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-pcapparse.xml b/docs/plugins/inspect/plugin-pcapparse.xml index 76dea64184..10902f80b6 100644 --- a/docs/plugins/inspect/plugin-pcapparse.xml +++ b/docs/plugins/inspect/plugin-pcapparse.xml @@ -3,7 +3,7 @@ Element parsing raw pcap streams ../../gst/pcapparse/.libs/libgstpcapparse.so libgstpcapparse.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad GStreamer diff --git a/docs/plugins/inspect/plugin-pnm.xml b/docs/plugins/inspect/plugin-pnm.xml index 50aec3d940..900f7f62bd 100644 --- a/docs/plugins/inspect/plugin-pnm.xml +++ b/docs/plugins/inspect/plugin-pnm.xml @@ -3,10 +3,10 @@ PNM plugin ../../gst/pnm/.libs/libgstpnm.so libgstpnm.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-qtmux.xml b/docs/plugins/inspect/plugin-qtmux.xml index 95e0da613d..c8482541a6 100644 --- a/docs/plugins/inspect/plugin-qtmux.xml +++ b/docs/plugins/inspect/plugin-qtmux.xml @@ -3,10 +3,10 @@ Quicktime Muxer plugin ../../gst/qtmux/.libs/libgstqtmux.so libgstqtmux.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-rawparse.xml b/docs/plugins/inspect/plugin-rawparse.xml index a94cd99148..0cb0e1acab 100644 --- a/docs/plugins/inspect/plugin-rawparse.xml +++ b/docs/plugins/inspect/plugin-rawparse.xml @@ -3,10 +3,10 @@ Parses byte streams into raw frames ../../gst/rawparse/.libs/libgstrawparse.so libgstrawparse.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-real.xml b/docs/plugins/inspect/plugin-real.xml index 117654d9d1..9d1d6a0814 100644 --- a/docs/plugins/inspect/plugin-real.xml +++ b/docs/plugins/inspect/plugin-real.xml @@ -3,10 +3,10 @@ Decode REAL streams ../../gst/real/.libs/libgstreal.so libgstreal.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-resindvd.xml b/docs/plugins/inspect/plugin-resindvd.xml index 62c6d5c3d1..ef048148d8 100644 --- a/docs/plugins/inspect/plugin-resindvd.xml +++ b/docs/plugins/inspect/plugin-resindvd.xml @@ -3,7 +3,7 @@ Resin DVD playback elements ../../ext/resindvd/.libs/libresindvd.so libresindvd.so - 0.10.20.4 + 0.10.21 GPL gst-plugins-bad GStreamer diff --git a/docs/plugins/inspect/plugin-rfbsrc.xml b/docs/plugins/inspect/plugin-rfbsrc.xml index 50a30dcf36..e5edcbec13 100644 --- a/docs/plugins/inspect/plugin-rfbsrc.xml +++ b/docs/plugins/inspect/plugin-rfbsrc.xml @@ -3,10 +3,10 @@ Connects to a VNC server and decodes RFB stream ../../gst/librfb/.libs/libgstrfbsrc.so libgstrfbsrc.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-rsvg.xml b/docs/plugins/inspect/plugin-rsvg.xml index ac2a937d35..6f51000284 100644 --- a/docs/plugins/inspect/plugin-rsvg.xml +++ b/docs/plugins/inspect/plugin-rsvg.xml @@ -3,10 +3,10 @@ RSVG plugin library ../../ext/rsvg/.libs/libgstrsvg.so libgstrsvg.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-rtpmux.xml b/docs/plugins/inspect/plugin-rtpmux.xml index 49c05676f4..f4718dc205 100644 --- a/docs/plugins/inspect/plugin-rtpmux.xml +++ b/docs/plugins/inspect/plugin-rtpmux.xml @@ -3,10 +3,10 @@ RTP Muxer plugins ../../gst/rtpmux/.libs/libgstrtpmux.so libgstrtpmux.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-scaletempo.xml b/docs/plugins/inspect/plugin-scaletempo.xml index aaff637f63..70519cd6a2 100644 --- a/docs/plugins/inspect/plugin-scaletempo.xml +++ b/docs/plugins/inspect/plugin-scaletempo.xml @@ -3,7 +3,7 @@ Scale audio tempo in sync with playback rate ../../gst/scaletempo/.libs/libgstscaletempoplugin.so libgstscaletempoplugin.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad GStreamer diff --git a/docs/plugins/inspect/plugin-schro.xml b/docs/plugins/inspect/plugin-schro.xml index 9b39bce7ae..e8c8b41a78 100644 --- a/docs/plugins/inspect/plugin-schro.xml +++ b/docs/plugins/inspect/plugin-schro.xml @@ -3,10 +3,10 @@ Schroedinger plugin ../../ext/schroedinger/.libs/libgstschro.so libgstschro.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-sdl.xml b/docs/plugins/inspect/plugin-sdl.xml index 4313c21ef2..871e24543a 100644 --- a/docs/plugins/inspect/plugin-sdl.xml +++ b/docs/plugins/inspect/plugin-sdl.xml @@ -3,10 +3,10 @@ SDL (Simple DirectMedia Layer) support for GStreamer ../../ext/sdl/.libs/libgstsdl.so libgstsdl.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-sdp.xml b/docs/plugins/inspect/plugin-sdp.xml index 9461cb88be..015a898782 100644 --- a/docs/plugins/inspect/plugin-sdp.xml +++ b/docs/plugins/inspect/plugin-sdp.xml @@ -3,10 +3,10 @@ configure streaming sessions using SDP ../../gst/sdp/.libs/libgstsdpelem.so libgstsdpelem.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-segmentclip.xml b/docs/plugins/inspect/plugin-segmentclip.xml index d20322bd19..b64be372e0 100644 --- a/docs/plugins/inspect/plugin-segmentclip.xml +++ b/docs/plugins/inspect/plugin-segmentclip.xml @@ -3,10 +3,10 @@ Segment clip elements ../../gst/segmentclip/.libs/libgstsegmentclip.so libgstsegmentclip.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-shm.xml b/docs/plugins/inspect/plugin-shm.xml index c01a0dffd3..f45fff3920 100644 --- a/docs/plugins/inspect/plugin-shm.xml +++ b/docs/plugins/inspect/plugin-shm.xml @@ -3,10 +3,10 @@ shared memory sink source ../../sys/shm/.libs/libgstshm.so libgstshm.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-sndfile.xml b/docs/plugins/inspect/plugin-sndfile.xml index 572e214b1a..5161cccca0 100644 --- a/docs/plugins/inspect/plugin-sndfile.xml +++ b/docs/plugins/inspect/plugin-sndfile.xml @@ -3,10 +3,10 @@ use libsndfile to read and write audio from and to files ../../ext/sndfile/.libs/libgstsndfile.so libgstsndfile.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-soundtouch.xml b/docs/plugins/inspect/plugin-soundtouch.xml index 25a89c692a..3934de78cd 100644 --- a/docs/plugins/inspect/plugin-soundtouch.xml +++ b/docs/plugins/inspect/plugin-soundtouch.xml @@ -3,10 +3,10 @@ Audio Pitch Controller & BPM Detection ../../ext/soundtouch/.libs/libgstsoundtouch.so libgstsoundtouch.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-speed.xml b/docs/plugins/inspect/plugin-speed.xml index 32a4ac2f1a..52e7f76176 100644 --- a/docs/plugins/inspect/plugin-speed.xml +++ b/docs/plugins/inspect/plugin-speed.xml @@ -3,10 +3,10 @@ Set speed/pitch on audio/raw streams (resampler) ../../gst/speed/.libs/libgstspeed.so libgstspeed.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-stereo.xml b/docs/plugins/inspect/plugin-stereo.xml index df82f352b6..9d76108c07 100644 --- a/docs/plugins/inspect/plugin-stereo.xml +++ b/docs/plugins/inspect/plugin-stereo.xml @@ -3,10 +3,10 @@ Muck with the stereo signal, enhance it's 'stereo-ness' ../../gst/stereo/.libs/libgststereo.so libgststereo.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-subenc.xml b/docs/plugins/inspect/plugin-subenc.xml index d67161e473..cf47978af6 100644 --- a/docs/plugins/inspect/plugin-subenc.xml +++ b/docs/plugins/inspect/plugin-subenc.xml @@ -3,10 +3,10 @@ subtitle encoders ../../gst/subenc/.libs/libgstsubenc.so libgstsubenc.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-tta.xml b/docs/plugins/inspect/plugin-tta.xml index 936947f834..0468a59003 100644 --- a/docs/plugins/inspect/plugin-tta.xml +++ b/docs/plugins/inspect/plugin-tta.xml @@ -3,10 +3,10 @@ TTA lossless audio format handling ../../gst/tta/.libs/libgsttta.so libgsttta.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-vcdsrc.xml b/docs/plugins/inspect/plugin-vcdsrc.xml index bb9de2d684..5647e95c46 100644 --- a/docs/plugins/inspect/plugin-vcdsrc.xml +++ b/docs/plugins/inspect/plugin-vcdsrc.xml @@ -3,10 +3,10 @@ Asynchronous read from VCD disk ../../sys/vcd/.libs/libgstvcdsrc.so libgstvcdsrc.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-vdpau.xml b/docs/plugins/inspect/plugin-vdpau.xml index 0218c221a6..2d509cfe84 100644 --- a/docs/plugins/inspect/plugin-vdpau.xml +++ b/docs/plugins/inspect/plugin-vdpau.xml @@ -3,7 +3,7 @@ Various elements utilizing VDPAU ../../sys/vdpau/.libs/libgstvdpau.so libgstvdpau.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad GStreamer diff --git a/docs/plugins/inspect/plugin-videomaxrate.xml b/docs/plugins/inspect/plugin-videomaxrate.xml index cd0b3118b9..59fc04f344 100644 --- a/docs/plugins/inspect/plugin-videomaxrate.xml +++ b/docs/plugins/inspect/plugin-videomaxrate.xml @@ -3,10 +3,10 @@ Drop extra frames ../../gst/videomaxrate/.libs/libgstvideomaxrate.so libgstvideomaxrate.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-videomeasure.xml b/docs/plugins/inspect/plugin-videomeasure.xml index 033f7a40d8..e1068f6143 100644 --- a/docs/plugins/inspect/plugin-videomeasure.xml +++ b/docs/plugins/inspect/plugin-videomeasure.xml @@ -3,10 +3,10 @@ Various video measurers ../../gst/videomeasure/.libs/libgstvideomeasure.so libgstvideomeasure.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-videosignal.xml b/docs/plugins/inspect/plugin-videosignal.xml index 57ee747221..53a3b9b071 100644 --- a/docs/plugins/inspect/plugin-videosignal.xml +++ b/docs/plugins/inspect/plugin-videosignal.xml @@ -3,10 +3,10 @@ Various video signal analysers ../../gst/videosignal/.libs/libgstvideosignal.so libgstvideosignal.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-vmnc.xml b/docs/plugins/inspect/plugin-vmnc.xml index 84615d72fb..df56077290 100644 --- a/docs/plugins/inspect/plugin-vmnc.xml +++ b/docs/plugins/inspect/plugin-vmnc.xml @@ -3,10 +3,10 @@ VmWare Video Codec plugins ../../gst/vmnc/.libs/libgstvmnc.so libgstvmnc.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-vp8.xml b/docs/plugins/inspect/plugin-vp8.xml index ca5415bd40..d9e5ce07d2 100644 --- a/docs/plugins/inspect/plugin-vp8.xml +++ b/docs/plugins/inspect/plugin-vp8.xml @@ -3,10 +3,10 @@ VP8 plugin ../../ext/vp8/.libs/libgstvp8.so libgstvp8.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-wildmidi.xml b/docs/plugins/inspect/plugin-wildmidi.xml index 0eb64efd1e..da37c34e91 100644 --- a/docs/plugins/inspect/plugin-wildmidi.xml +++ b/docs/plugins/inspect/plugin-wildmidi.xml @@ -3,10 +3,10 @@ Wildmidi Plugin ../../ext/timidity/.libs/libgstwildmidi.so libgstwildmidi.so - 0.10.20.4 + 0.10.21 GPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-xvid.xml b/docs/plugins/inspect/plugin-xvid.xml index f8cf93a759..eda7e1d689 100644 --- a/docs/plugins/inspect/plugin-xvid.xml +++ b/docs/plugins/inspect/plugin-xvid.xml @@ -3,10 +3,10 @@ XviD plugin library ../../ext/xvid/.libs/libgstxvid.so libgstxvid.so - 0.10.20.4 + 0.10.21 GPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/docs/plugins/inspect/plugin-y4mdec.xml b/docs/plugins/inspect/plugin-y4mdec.xml index 2136e25213..55816b21f5 100644 --- a/docs/plugins/inspect/plugin-y4mdec.xml +++ b/docs/plugins/inspect/plugin-y4mdec.xml @@ -3,7 +3,7 @@ FIXME ../../gst/y4m/.libs/libgsty4mdec.so libgsty4mdec.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad GStreamer Bad Plug-ins diff --git a/docs/plugins/inspect/plugin-zbar.xml b/docs/plugins/inspect/plugin-zbar.xml index 6888d31bbc..0176145320 100644 --- a/docs/plugins/inspect/plugin-zbar.xml +++ b/docs/plugins/inspect/plugin-zbar.xml @@ -3,10 +3,10 @@ zbar barcode scanner ../../ext/zbar/.libs/libgstzbar.so libgstzbar.so - 0.10.20.4 + 0.10.21 LGPL gst-plugins-bad - GStreamer Bad Plug-ins prerelease + GStreamer Bad Plug-ins source release Unknown package origin diff --git a/gst-plugins-bad.doap b/gst-plugins-bad.doap index d86079c14a..2ec1153d84 100644 --- a/gst-plugins-bad.doap +++ b/gst-plugins-bad.doap @@ -33,6 +33,17 @@ real live maintainer, or some actual wide use. + + + 0.10.21 + 0.10 + Pink Noise + 2011-01-21 + + + + + 0.10.20 diff --git a/win32/common/config.h b/win32/common/config.h index 1a7b585637..af55e3fe76 100644 --- a/win32/common/config.h +++ b/win32/common/config.h @@ -24,7 +24,7 @@ #define GST_LICENSE "LGPL" /* package name in plugins */ -#define GST_PACKAGE_NAME "GStreamer Bad Plug-ins prerelease" +#define GST_PACKAGE_NAME "GStreamer Bad Plug-ins source release" /* package origin */ #define GST_PACKAGE_ORIGIN "Unknown package origin" @@ -199,7 +199,7 @@ #undef USE_POISONING /* Version number of package */ -#define VERSION "0.10.20.4" +#define VERSION "0.10.21" /* Define to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel and VAX). */ From 03fc02132fadca956674c925c36109fe79cb00b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Mon, 24 Jan 2011 11:18:29 +0000 Subject: [PATCH 307/448] Back to development --- configure.ac | 2 +- docs/plugins/gst-plugins-bad-plugins.args | 12 ++++++------ docs/plugins/gst-plugins-bad-plugins.hierarchy | 2 -- docs/plugins/inspect/plugin-adpcmdec.xml | 4 ++-- docs/plugins/inspect/plugin-adpcmenc.xml | 4 ++-- docs/plugins/inspect/plugin-aiff.xml | 4 ++-- docs/plugins/inspect/plugin-amrwbenc.xml | 4 ++-- docs/plugins/inspect/plugin-apexsink.xml | 4 ++-- docs/plugins/inspect/plugin-asfmux.xml | 4 ++-- docs/plugins/inspect/plugin-assrender.xml | 4 ++-- docs/plugins/inspect/plugin-audioparsersbad.xml | 4 ++-- docs/plugins/inspect/plugin-autoconvert.xml | 4 ++-- docs/plugins/inspect/plugin-bayer.xml | 4 ++-- docs/plugins/inspect/plugin-bz2.xml | 4 ++-- docs/plugins/inspect/plugin-camerabin.xml | 4 ++-- docs/plugins/inspect/plugin-cdaudio.xml | 4 ++-- docs/plugins/inspect/plugin-cdxaparse.xml | 4 ++-- docs/plugins/inspect/plugin-celt.xml | 4 ++-- docs/plugins/inspect/plugin-cog.xml | 4 ++-- docs/plugins/inspect/plugin-coloreffects.xml | 4 ++-- docs/plugins/inspect/plugin-colorspace.xml | 2 +- docs/plugins/inspect/plugin-dataurisrc.xml | 4 ++-- docs/plugins/inspect/plugin-dc1394.xml | 4 ++-- docs/plugins/inspect/plugin-dccp.xml | 2 +- docs/plugins/inspect/plugin-debugutilsbad.xml | 4 ++-- docs/plugins/inspect/plugin-dfbvideosink.xml | 4 ++-- docs/plugins/inspect/plugin-dirac.xml | 4 ++-- docs/plugins/inspect/plugin-dtmf.xml | 4 ++-- docs/plugins/inspect/plugin-dtsdec.xml | 4 ++-- docs/plugins/inspect/plugin-dvb.xml | 4 ++-- docs/plugins/inspect/plugin-dvbsuboverlay.xml | 4 ++-- docs/plugins/inspect/plugin-dvdspu.xml | 4 ++-- docs/plugins/inspect/plugin-faac.xml | 4 ++-- docs/plugins/inspect/plugin-faad.xml | 4 ++-- docs/plugins/inspect/plugin-fbdevsink.xml | 4 ++-- docs/plugins/inspect/plugin-festival.xml | 4 ++-- docs/plugins/inspect/plugin-freeze.xml | 4 ++-- docs/plugins/inspect/plugin-frei0r.xml | 4 ++-- docs/plugins/inspect/plugin-gaudieffects.xml | 2 +- docs/plugins/inspect/plugin-geometrictransform.xml | 4 ++-- docs/plugins/inspect/plugin-gsettings.xml | 4 ++-- docs/plugins/inspect/plugin-gsm.xml | 4 ++-- docs/plugins/inspect/plugin-gstsiren.xml | 4 ++-- docs/plugins/inspect/plugin-h264parse.xml | 4 ++-- docs/plugins/inspect/plugin-hdvparse.xml | 2 +- docs/plugins/inspect/plugin-id3tag.xml | 4 ++-- docs/plugins/inspect/plugin-interlace.xml | 4 ++-- docs/plugins/inspect/plugin-invtelecine.xml | 4 ++-- docs/plugins/inspect/plugin-ivfparse.xml | 4 ++-- docs/plugins/inspect/plugin-jp2kdecimator.xml | 4 ++-- docs/plugins/inspect/plugin-jpegformat.xml | 4 ++-- docs/plugins/inspect/plugin-kate.xml | 4 ++-- docs/plugins/inspect/plugin-ladspa.xml | 4 ++-- docs/plugins/inspect/plugin-legacyresample.xml | 4 ++-- docs/plugins/inspect/plugin-liveadder.xml | 4 ++-- docs/plugins/inspect/plugin-mimic.xml | 4 ++-- docs/plugins/inspect/plugin-mms.xml | 4 ++-- docs/plugins/inspect/plugin-modplug.xml | 4 ++-- docs/plugins/inspect/plugin-mpeg2enc.xml | 4 ++-- docs/plugins/inspect/plugin-mpeg4videoparse.xml | 4 ++-- docs/plugins/inspect/plugin-mpegdemux2.xml | 4 ++-- docs/plugins/inspect/plugin-mpegpsmux.xml | 4 ++-- docs/plugins/inspect/plugin-mpegtsmux.xml | 4 ++-- docs/plugins/inspect/plugin-mpegvideoparse.xml | 4 ++-- docs/plugins/inspect/plugin-mplex.xml | 4 ++-- docs/plugins/inspect/plugin-musepack.xml | 4 ++-- docs/plugins/inspect/plugin-musicbrainz.xml | 4 ++-- docs/plugins/inspect/plugin-mve.xml | 4 ++-- docs/plugins/inspect/plugin-mxf.xml | 4 ++-- docs/plugins/inspect/plugin-mythtv.xml | 4 ++-- docs/plugins/inspect/plugin-nas.xml | 4 ++-- docs/plugins/inspect/plugin-neon.xml | 4 ++-- docs/plugins/inspect/plugin-nsf.xml | 4 ++-- docs/plugins/inspect/plugin-nuvdemux.xml | 4 ++-- docs/plugins/inspect/plugin-ofa.xml | 4 ++-- docs/plugins/inspect/plugin-opencv.xml | 4 ++-- docs/plugins/inspect/plugin-pcapparse.xml | 2 +- docs/plugins/inspect/plugin-pnm.xml | 4 ++-- docs/plugins/inspect/plugin-qtmux.xml | 4 ++-- docs/plugins/inspect/plugin-rawparse.xml | 4 ++-- docs/plugins/inspect/plugin-real.xml | 4 ++-- docs/plugins/inspect/plugin-resindvd.xml | 2 +- docs/plugins/inspect/plugin-rfbsrc.xml | 4 ++-- docs/plugins/inspect/plugin-rsvg.xml | 4 ++-- docs/plugins/inspect/plugin-rtpmux.xml | 4 ++-- docs/plugins/inspect/plugin-scaletempo.xml | 2 +- docs/plugins/inspect/plugin-schro.xml | 4 ++-- docs/plugins/inspect/plugin-sdl.xml | 4 ++-- docs/plugins/inspect/plugin-sdp.xml | 4 ++-- docs/plugins/inspect/plugin-segmentclip.xml | 4 ++-- docs/plugins/inspect/plugin-shm.xml | 4 ++-- docs/plugins/inspect/plugin-sndfile.xml | 4 ++-- docs/plugins/inspect/plugin-soundtouch.xml | 4 ++-- docs/plugins/inspect/plugin-speed.xml | 4 ++-- docs/plugins/inspect/plugin-stereo.xml | 4 ++-- docs/plugins/inspect/plugin-subenc.xml | 4 ++-- docs/plugins/inspect/plugin-tta.xml | 4 ++-- docs/plugins/inspect/plugin-vcdsrc.xml | 4 ++-- docs/plugins/inspect/plugin-vdpau.xml | 2 +- docs/plugins/inspect/plugin-videomaxrate.xml | 4 ++-- docs/plugins/inspect/plugin-videomeasure.xml | 4 ++-- docs/plugins/inspect/plugin-videosignal.xml | 4 ++-- docs/plugins/inspect/plugin-vmnc.xml | 4 ++-- docs/plugins/inspect/plugin-vp8.xml | 4 ++-- docs/plugins/inspect/plugin-wildmidi.xml | 4 ++-- docs/plugins/inspect/plugin-xvid.xml | 4 ++-- docs/plugins/inspect/plugin-y4mdec.xml | 2 +- docs/plugins/inspect/plugin-zbar.xml | 4 ++-- win32/common/config.h | 4 ++-- 109 files changed, 210 insertions(+), 212 deletions(-) diff --git a/configure.ac b/configure.ac index fa6193d9d1..36dc6a7015 100644 --- a/configure.ac +++ b/configure.ac @@ -3,7 +3,7 @@ AC_PREREQ(2.60) dnl initialize autoconf dnl when going to/from release please set the nano (fourth number) right ! dnl releases only do Wall, cvs and prerelease does Werror too -AC_INIT(GStreamer Bad Plug-ins, 0.10.21, +AC_INIT(GStreamer Bad Plug-ins, 0.10.21.1, http://bugzilla.gnome.org/enter_bug.cgi?product=GStreamer, gst-plugins-bad) diff --git a/docs/plugins/gst-plugins-bad-plugins.args b/docs/plugins/gst-plugins-bad-plugins.args index 5f7867d3cf..f6f1b5816c 100644 --- a/docs/plugins/gst-plugins-bad-plugins.args +++ b/docs/plugins/gst-plugins-bad-plugins.args @@ -26550,7 +26550,7 @@ rw splash make a big splash in the center. -4.62957e-299 +7.7486e-304 @@ -26560,7 +26560,7 @@ rw splash make a big splash in the center. -0 +4.62957e-299 @@ -26590,7 +26590,7 @@ rw ratiox x-ratio. -2.34233e-310 +2.31928e-310 @@ -26600,7 +26600,7 @@ rw ratioy y-ratio. -2.34233e-310 +2.31928e-310 @@ -27180,7 +27180,7 @@ rw blend blend factor. -0 +-6.17056e+303 @@ -27370,7 +27370,7 @@ rw HSync the hsync offset. -8.25792e-317 +2.38039e-316 diff --git a/docs/plugins/gst-plugins-bad-plugins.hierarchy b/docs/plugins/gst-plugins-bad-plugins.hierarchy index c711d8d42d..84322e7d5a 100644 --- a/docs/plugins/gst-plugins-bad-plugins.hierarchy +++ b/docs/plugins/gst-plugins-bad-plugins.hierarchy @@ -1,7 +1,5 @@ GObject GstColorBalanceChannel - GstMixerTrack - GstMixerOptions GstObject GstBus GstClock diff --git a/docs/plugins/inspect/plugin-adpcmdec.xml b/docs/plugins/inspect/plugin-adpcmdec.xml index ea4d7c1bb8..fba62a5cf8 100644 --- a/docs/plugins/inspect/plugin-adpcmdec.xml +++ b/docs/plugins/inspect/plugin-adpcmdec.xml @@ -3,10 +3,10 @@ ADPCM decoder ../../gst/adpcmdec/.libs/libgstadpcmdec.so libgstadpcmdec.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-adpcmenc.xml b/docs/plugins/inspect/plugin-adpcmenc.xml index 6bd02f9a7a..acfa8c7c19 100644 --- a/docs/plugins/inspect/plugin-adpcmenc.xml +++ b/docs/plugins/inspect/plugin-adpcmenc.xml @@ -3,10 +3,10 @@ ADPCM encoder ../../gst/adpcmenc/.libs/libgstadpcmenc.so libgstadpcmenc.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-aiff.xml b/docs/plugins/inspect/plugin-aiff.xml index 34ba2d0b0b..f616fff130 100644 --- a/docs/plugins/inspect/plugin-aiff.xml +++ b/docs/plugins/inspect/plugin-aiff.xml @@ -3,10 +3,10 @@ Create and parse Audio Interchange File Format (AIFF) files ../../gst/aiff/.libs/libgstaiff.so libgstaiff.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-amrwbenc.xml b/docs/plugins/inspect/plugin-amrwbenc.xml index 30193a4f14..e70e68bdf6 100644 --- a/docs/plugins/inspect/plugin-amrwbenc.xml +++ b/docs/plugins/inspect/plugin-amrwbenc.xml @@ -3,10 +3,10 @@ Adaptive Multi-Rate Wide-Band Encoder ../../ext/amrwbenc/.libs/libgstamrwbenc.so libgstamrwbenc.so - 0.10.21 + 0.10.21.1 unknown gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-apexsink.xml b/docs/plugins/inspect/plugin-apexsink.xml index 2461df82bd..95dcedc7da 100644 --- a/docs/plugins/inspect/plugin-apexsink.xml +++ b/docs/plugins/inspect/plugin-apexsink.xml @@ -3,10 +3,10 @@ Apple AirPort Express Plugin ../../ext/apexsink/.libs/libgstapexsink.so libgstapexsink.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-asfmux.xml b/docs/plugins/inspect/plugin-asfmux.xml index d696168b70..b9c21a78c9 100644 --- a/docs/plugins/inspect/plugin-asfmux.xml +++ b/docs/plugins/inspect/plugin-asfmux.xml @@ -3,10 +3,10 @@ ASF Muxer Plugin ../../gst/asfmux/.libs/libgstasfmux.so libgstasfmux.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-assrender.xml b/docs/plugins/inspect/plugin-assrender.xml index 2b1d2096f1..6786697f17 100644 --- a/docs/plugins/inspect/plugin-assrender.xml +++ b/docs/plugins/inspect/plugin-assrender.xml @@ -3,10 +3,10 @@ ASS/SSA subtitle renderer ../../ext/assrender/.libs/libgstassrender.so libgstassrender.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-audioparsersbad.xml b/docs/plugins/inspect/plugin-audioparsersbad.xml index bcb472e251..eb908af26e 100644 --- a/docs/plugins/inspect/plugin-audioparsersbad.xml +++ b/docs/plugins/inspect/plugin-audioparsersbad.xml @@ -3,10 +3,10 @@ audioparsers ../../gst/audioparsers/.libs/libgstaudioparsersbad.so libgstaudioparsersbad.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-autoconvert.xml b/docs/plugins/inspect/plugin-autoconvert.xml index eb94791d07..0dd7873c1b 100644 --- a/docs/plugins/inspect/plugin-autoconvert.xml +++ b/docs/plugins/inspect/plugin-autoconvert.xml @@ -3,10 +3,10 @@ Selects convertor element based on caps ../../gst/autoconvert/.libs/libgstautoconvert.so libgstautoconvert.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-bayer.xml b/docs/plugins/inspect/plugin-bayer.xml index 8ec0494403..0bb15c67fb 100644 --- a/docs/plugins/inspect/plugin-bayer.xml +++ b/docs/plugins/inspect/plugin-bayer.xml @@ -3,10 +3,10 @@ Elements to convert Bayer images ../../gst/bayer/.libs/libgstbayer.so libgstbayer.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-bz2.xml b/docs/plugins/inspect/plugin-bz2.xml index e839fb99a0..a5af38ea4b 100644 --- a/docs/plugins/inspect/plugin-bz2.xml +++ b/docs/plugins/inspect/plugin-bz2.xml @@ -3,10 +3,10 @@ Compress or decompress streams ../../ext/bz2/.libs/libgstbz2.so libgstbz2.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-camerabin.xml b/docs/plugins/inspect/plugin-camerabin.xml index 57225e4110..91a386f105 100644 --- a/docs/plugins/inspect/plugin-camerabin.xml +++ b/docs/plugins/inspect/plugin-camerabin.xml @@ -3,10 +3,10 @@ High level api for DC (Digital Camera) application ../../gst/camerabin/.libs/libgstcamerabin.so libgstcamerabin.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-cdaudio.xml b/docs/plugins/inspect/plugin-cdaudio.xml index 2645ffbd76..b28ef3498c 100644 --- a/docs/plugins/inspect/plugin-cdaudio.xml +++ b/docs/plugins/inspect/plugin-cdaudio.xml @@ -3,10 +3,10 @@ Play CD audio through the CD Drive ../../ext/cdaudio/.libs/libgstcdaudio.so libgstcdaudio.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-cdxaparse.xml b/docs/plugins/inspect/plugin-cdxaparse.xml index 6e2b1e41a3..a9480090e6 100644 --- a/docs/plugins/inspect/plugin-cdxaparse.xml +++ b/docs/plugins/inspect/plugin-cdxaparse.xml @@ -3,10 +3,10 @@ Parse a .dat file (VCD) into raw mpeg1 ../../gst/cdxaparse/.libs/libgstcdxaparse.so libgstcdxaparse.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-celt.xml b/docs/plugins/inspect/plugin-celt.xml index 6ff0a2c7bf..8b359667ca 100644 --- a/docs/plugins/inspect/plugin-celt.xml +++ b/docs/plugins/inspect/plugin-celt.xml @@ -3,10 +3,10 @@ CELT plugin library ../../ext/celt/.libs/libgstcelt.so libgstcelt.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-cog.xml b/docs/plugins/inspect/plugin-cog.xml index 6f93c49088..bf0fd83dd5 100644 --- a/docs/plugins/inspect/plugin-cog.xml +++ b/docs/plugins/inspect/plugin-cog.xml @@ -3,10 +3,10 @@ Cog plugin ../../ext/cog/.libs/libgstcog.so libgstcog.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-coloreffects.xml b/docs/plugins/inspect/plugin-coloreffects.xml index 1fe65f9848..99d3a37b25 100644 --- a/docs/plugins/inspect/plugin-coloreffects.xml +++ b/docs/plugins/inspect/plugin-coloreffects.xml @@ -3,10 +3,10 @@ Color Look-up Table filters ../../gst/coloreffects/.libs/libgstcoloreffects.so libgstcoloreffects.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-colorspace.xml b/docs/plugins/inspect/plugin-colorspace.xml index ec537ebe69..d8eeb1cc66 100644 --- a/docs/plugins/inspect/plugin-colorspace.xml +++ b/docs/plugins/inspect/plugin-colorspace.xml @@ -3,7 +3,7 @@ Colorspace conversion ../../gst/colorspace/.libs/libgstcolorspace.so libgstcolorspace.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad diff --git a/docs/plugins/inspect/plugin-dataurisrc.xml b/docs/plugins/inspect/plugin-dataurisrc.xml index fa030d89c4..8945d1e048 100644 --- a/docs/plugins/inspect/plugin-dataurisrc.xml +++ b/docs/plugins/inspect/plugin-dataurisrc.xml @@ -3,10 +3,10 @@ data: URI source ../../gst/dataurisrc/.libs/libgstdataurisrc.so libgstdataurisrc.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-dc1394.xml b/docs/plugins/inspect/plugin-dc1394.xml index 9cc17fc6bd..c58f73244d 100644 --- a/docs/plugins/inspect/plugin-dc1394.xml +++ b/docs/plugins/inspect/plugin-dc1394.xml @@ -3,10 +3,10 @@ 1394 IIDC Video Source ../../ext/dc1394/.libs/libgstdc1394.so libgstdc1394.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-dccp.xml b/docs/plugins/inspect/plugin-dccp.xml index edf5b38d06..3455b24633 100644 --- a/docs/plugins/inspect/plugin-dccp.xml +++ b/docs/plugins/inspect/plugin-dccp.xml @@ -3,7 +3,7 @@ transfer data over the network via DCCP. ../../gst/dccp/.libs/libgstdccp.so libgstdccp.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad DCCP diff --git a/docs/plugins/inspect/plugin-debugutilsbad.xml b/docs/plugins/inspect/plugin-debugutilsbad.xml index 771ffea545..f8e716df43 100644 --- a/docs/plugins/inspect/plugin-debugutilsbad.xml +++ b/docs/plugins/inspect/plugin-debugutilsbad.xml @@ -3,10 +3,10 @@ Collection of elements that may or may not be useful for debugging ../../gst/debugutils/.libs/libgstdebugutilsbad.so libgstdebugutilsbad.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-dfbvideosink.xml b/docs/plugins/inspect/plugin-dfbvideosink.xml index 0c70895d91..390dfbe721 100644 --- a/docs/plugins/inspect/plugin-dfbvideosink.xml +++ b/docs/plugins/inspect/plugin-dfbvideosink.xml @@ -3,10 +3,10 @@ DirectFB video output plugin ../../ext/directfb/.libs/libgstdfbvideosink.so libgstdfbvideosink.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-dirac.xml b/docs/plugins/inspect/plugin-dirac.xml index bd93fd152f..0fd1f0522e 100644 --- a/docs/plugins/inspect/plugin-dirac.xml +++ b/docs/plugins/inspect/plugin-dirac.xml @@ -3,10 +3,10 @@ Dirac plugin ../../ext/dirac/.libs/libgstdirac.so libgstdirac.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-dtmf.xml b/docs/plugins/inspect/plugin-dtmf.xml index 6c3f7d05c2..f44eb4463a 100644 --- a/docs/plugins/inspect/plugin-dtmf.xml +++ b/docs/plugins/inspect/plugin-dtmf.xml @@ -3,10 +3,10 @@ DTMF plugins ../../gst/dtmf/.libs/libgstdtmf.so libgstdtmf.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-dtsdec.xml b/docs/plugins/inspect/plugin-dtsdec.xml index 1fa8b3bb9e..6b9fb5a00f 100644 --- a/docs/plugins/inspect/plugin-dtsdec.xml +++ b/docs/plugins/inspect/plugin-dtsdec.xml @@ -3,10 +3,10 @@ Decodes DTS audio streams ../../ext/dts/.libs/libgstdtsdec.so libgstdtsdec.so - 0.10.21 + 0.10.21.1 GPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-dvb.xml b/docs/plugins/inspect/plugin-dvb.xml index e6ec4f3325..ade2596295 100644 --- a/docs/plugins/inspect/plugin-dvb.xml +++ b/docs/plugins/inspect/plugin-dvb.xml @@ -3,10 +3,10 @@ DVB elements ../../sys/dvb/.libs/libgstdvb.so libgstdvb.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-dvbsuboverlay.xml b/docs/plugins/inspect/plugin-dvbsuboverlay.xml index d851692dc7..2341db7160 100644 --- a/docs/plugins/inspect/plugin-dvbsuboverlay.xml +++ b/docs/plugins/inspect/plugin-dvbsuboverlay.xml @@ -3,10 +3,10 @@ DVB subtitle renderer ../../gst/dvbsuboverlay/.libs/libgstdvbsuboverlay.so libgstdvbsuboverlay.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-dvdspu.xml b/docs/plugins/inspect/plugin-dvdspu.xml index bc68134d9a..17b178fce3 100644 --- a/docs/plugins/inspect/plugin-dvdspu.xml +++ b/docs/plugins/inspect/plugin-dvdspu.xml @@ -3,10 +3,10 @@ DVD Sub-picture Overlay element ../../gst/dvdspu/.libs/libgstdvdspu.so libgstdvdspu.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-faac.xml b/docs/plugins/inspect/plugin-faac.xml index 3e59202b9b..22394b7b6d 100644 --- a/docs/plugins/inspect/plugin-faac.xml +++ b/docs/plugins/inspect/plugin-faac.xml @@ -3,10 +3,10 @@ Free AAC Encoder (FAAC) ../../ext/faac/.libs/libgstfaac.so libgstfaac.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-faad.xml b/docs/plugins/inspect/plugin-faad.xml index 682e892679..2854eab4f4 100644 --- a/docs/plugins/inspect/plugin-faad.xml +++ b/docs/plugins/inspect/plugin-faad.xml @@ -3,10 +3,10 @@ Free AAC Decoder (FAAD) ../../ext/faad/.libs/libgstfaad.so libgstfaad.so - 0.10.21 + 0.10.21.1 GPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-fbdevsink.xml b/docs/plugins/inspect/plugin-fbdevsink.xml index b9aede2d9d..76ec0e3dff 100644 --- a/docs/plugins/inspect/plugin-fbdevsink.xml +++ b/docs/plugins/inspect/plugin-fbdevsink.xml @@ -3,10 +3,10 @@ linux framebuffer video sink ../../sys/fbdev/.libs/libgstfbdevsink.so libgstfbdevsink.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-festival.xml b/docs/plugins/inspect/plugin-festival.xml index eef78927d4..57f5814fde 100644 --- a/docs/plugins/inspect/plugin-festival.xml +++ b/docs/plugins/inspect/plugin-festival.xml @@ -3,10 +3,10 @@ Synthesizes plain text into audio ../../gst/festival/.libs/libgstfestival.so libgstfestival.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-freeze.xml b/docs/plugins/inspect/plugin-freeze.xml index ccbf9309f1..90462d08c1 100644 --- a/docs/plugins/inspect/plugin-freeze.xml +++ b/docs/plugins/inspect/plugin-freeze.xml @@ -3,10 +3,10 @@ Stream freezer ../../gst/freeze/.libs/libgstfreeze.so libgstfreeze.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-frei0r.xml b/docs/plugins/inspect/plugin-frei0r.xml index f0e73d306c..94f516fb58 100644 --- a/docs/plugins/inspect/plugin-frei0r.xml +++ b/docs/plugins/inspect/plugin-frei0r.xml @@ -3,10 +3,10 @@ frei0r plugin library ../../gst/frei0r/.libs/libgstfrei0r.so libgstfrei0r.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-gaudieffects.xml b/docs/plugins/inspect/plugin-gaudieffects.xml index 7a0c464ba9..a3c33a5a44 100644 --- a/docs/plugins/inspect/plugin-gaudieffects.xml +++ b/docs/plugins/inspect/plugin-gaudieffects.xml @@ -3,7 +3,7 @@ Gaudi video effects. ../../gst/gaudieffects/.libs/libgstgaudieffects.so libgstgaudieffects.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad GStreamer diff --git a/docs/plugins/inspect/plugin-geometrictransform.xml b/docs/plugins/inspect/plugin-geometrictransform.xml index 5d6dcc3c53..d03c3057ce 100644 --- a/docs/plugins/inspect/plugin-geometrictransform.xml +++ b/docs/plugins/inspect/plugin-geometrictransform.xml @@ -3,10 +3,10 @@ Various geometric image transform elements ../../gst/geometrictransform/.libs/libgstgeometrictransform.so libgstgeometrictransform.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-gsettings.xml b/docs/plugins/inspect/plugin-gsettings.xml index 98c95281f2..a009c25a28 100644 --- a/docs/plugins/inspect/plugin-gsettings.xml +++ b/docs/plugins/inspect/plugin-gsettings.xml @@ -3,10 +3,10 @@ GSettings plugin ../../ext/gsettings/.libs/libgstgsettingselements.so libgstgsettingselements.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-gsm.xml b/docs/plugins/inspect/plugin-gsm.xml index cf9f9d33a5..f89cfc2f78 100644 --- a/docs/plugins/inspect/plugin-gsm.xml +++ b/docs/plugins/inspect/plugin-gsm.xml @@ -3,10 +3,10 @@ GSM encoder/decoder ../../ext/gsm/.libs/libgstgsm.so libgstgsm.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-gstsiren.xml b/docs/plugins/inspect/plugin-gstsiren.xml index d436d93506..bb15abe0f6 100644 --- a/docs/plugins/inspect/plugin-gstsiren.xml +++ b/docs/plugins/inspect/plugin-gstsiren.xml @@ -3,10 +3,10 @@ Siren encoder/decoder/payloader/depayloader plugins ../../gst/siren/.libs/libgstsiren.so libgstsiren.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-h264parse.xml b/docs/plugins/inspect/plugin-h264parse.xml index d941af7508..14977a52c8 100644 --- a/docs/plugins/inspect/plugin-h264parse.xml +++ b/docs/plugins/inspect/plugin-h264parse.xml @@ -3,10 +3,10 @@ Element parsing raw h264 streams ../../gst/h264parse/.libs/libgsth264parse.so libgsth264parse.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-hdvparse.xml b/docs/plugins/inspect/plugin-hdvparse.xml index 4039c2fd23..2589fb6d9b 100644 --- a/docs/plugins/inspect/plugin-hdvparse.xml +++ b/docs/plugins/inspect/plugin-hdvparse.xml @@ -3,7 +3,7 @@ HDV private stream parser ../../gst/hdvparse/.libs/libgsthdvparse.so libgsthdvparse.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad GStreamer diff --git a/docs/plugins/inspect/plugin-id3tag.xml b/docs/plugins/inspect/plugin-id3tag.xml index e3b3f583bd..ce7a2942ce 100644 --- a/docs/plugins/inspect/plugin-id3tag.xml +++ b/docs/plugins/inspect/plugin-id3tag.xml @@ -3,10 +3,10 @@ ID3 v1 and v2 muxing plugin ../../gst/id3tag/.libs/libgstid3tag.so libgstid3tag.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-interlace.xml b/docs/plugins/inspect/plugin-interlace.xml index 48a56f006b..d9865ec080 100644 --- a/docs/plugins/inspect/plugin-interlace.xml +++ b/docs/plugins/inspect/plugin-interlace.xml @@ -3,10 +3,10 @@ Create an interlaced video stream ../../gst/interlace/.libs/libgstinterlace.so libgstinterlace.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-invtelecine.xml b/docs/plugins/inspect/plugin-invtelecine.xml index 9ecbc29aa6..119cf474ce 100644 --- a/docs/plugins/inspect/plugin-invtelecine.xml +++ b/docs/plugins/inspect/plugin-invtelecine.xml @@ -3,10 +3,10 @@ Inverse Telecine ../../gst/invtelecine/.libs/libgstinvtelecine.so libgstinvtelecine.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-ivfparse.xml b/docs/plugins/inspect/plugin-ivfparse.xml index 8738413e59..181f384b4a 100644 --- a/docs/plugins/inspect/plugin-ivfparse.xml +++ b/docs/plugins/inspect/plugin-ivfparse.xml @@ -3,10 +3,10 @@ IVF parser ../../gst/ivfparse/.libs/libgstivfparse.so libgstivfparse.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-jp2kdecimator.xml b/docs/plugins/inspect/plugin-jp2kdecimator.xml index 5faa24885d..1f0e7fdc2c 100644 --- a/docs/plugins/inspect/plugin-jp2kdecimator.xml +++ b/docs/plugins/inspect/plugin-jp2kdecimator.xml @@ -3,10 +3,10 @@ JPEG2000 decimator ../../gst/jp2kdecimator/.libs/libgstjp2kdecimator.so libgstjp2kdecimator.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-jpegformat.xml b/docs/plugins/inspect/plugin-jpegformat.xml index 16835a96e7..d802193df2 100644 --- a/docs/plugins/inspect/plugin-jpegformat.xml +++ b/docs/plugins/inspect/plugin-jpegformat.xml @@ -3,10 +3,10 @@ JPEG interchange format plugin ../../gst/jpegformat/.libs/libgstjpegformat.so libgstjpegformat.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-kate.xml b/docs/plugins/inspect/plugin-kate.xml index eb32c11930..60db3590f7 100644 --- a/docs/plugins/inspect/plugin-kate.xml +++ b/docs/plugins/inspect/plugin-kate.xml @@ -3,10 +3,10 @@ Kate plugin ../../ext/kate/.libs/libgstkate.so libgstkate.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-ladspa.xml b/docs/plugins/inspect/plugin-ladspa.xml index a504393f0b..c9511b7e07 100644 --- a/docs/plugins/inspect/plugin-ladspa.xml +++ b/docs/plugins/inspect/plugin-ladspa.xml @@ -3,10 +3,10 @@ All LADSPA plugins ../../ext/ladspa/.libs/libgstladspa.so libgstladspa.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-legacyresample.xml b/docs/plugins/inspect/plugin-legacyresample.xml index 1fc80f4a0e..c3ae53dfc2 100644 --- a/docs/plugins/inspect/plugin-legacyresample.xml +++ b/docs/plugins/inspect/plugin-legacyresample.xml @@ -3,10 +3,10 @@ Resamples audio ../../gst/legacyresample/.libs/libgstlegacyresample.so libgstlegacyresample.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-liveadder.xml b/docs/plugins/inspect/plugin-liveadder.xml index c3b58b9a38..109a4762d8 100644 --- a/docs/plugins/inspect/plugin-liveadder.xml +++ b/docs/plugins/inspect/plugin-liveadder.xml @@ -3,10 +3,10 @@ Adds multiple live discontinuous streams ../../gst/liveadder/.libs/libgstliveadder.so libgstliveadder.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-mimic.xml b/docs/plugins/inspect/plugin-mimic.xml index f90e0f5470..202795df1e 100644 --- a/docs/plugins/inspect/plugin-mimic.xml +++ b/docs/plugins/inspect/plugin-mimic.xml @@ -3,10 +3,10 @@ Mimic codec ../../ext/mimic/.libs/libgstmimic.so libgstmimic.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-mms.xml b/docs/plugins/inspect/plugin-mms.xml index c85173cefa..fd3d4d8cc0 100644 --- a/docs/plugins/inspect/plugin-mms.xml +++ b/docs/plugins/inspect/plugin-mms.xml @@ -3,10 +3,10 @@ Microsoft Multi Media Server streaming protocol support ../../ext/libmms/.libs/libgstmms.so libgstmms.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-modplug.xml b/docs/plugins/inspect/plugin-modplug.xml index 4e5509da50..0e717bb86e 100644 --- a/docs/plugins/inspect/plugin-modplug.xml +++ b/docs/plugins/inspect/plugin-modplug.xml @@ -3,10 +3,10 @@ .MOD audio decoding ../../ext/modplug/.libs/libgstmodplug.so libgstmodplug.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-mpeg2enc.xml b/docs/plugins/inspect/plugin-mpeg2enc.xml index 2b62e3c981..0797f9adff 100644 --- a/docs/plugins/inspect/plugin-mpeg2enc.xml +++ b/docs/plugins/inspect/plugin-mpeg2enc.xml @@ -3,10 +3,10 @@ High-quality MPEG-1/2 video encoder ../../ext/mpeg2enc/.libs/libgstmpeg2enc.so libgstmpeg2enc.so - 0.10.21 + 0.10.21.1 GPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-mpeg4videoparse.xml b/docs/plugins/inspect/plugin-mpeg4videoparse.xml index 50385821e8..5915e60fb1 100644 --- a/docs/plugins/inspect/plugin-mpeg4videoparse.xml +++ b/docs/plugins/inspect/plugin-mpeg4videoparse.xml @@ -3,10 +3,10 @@ MPEG-4 video parser ../../gst/mpeg4videoparse/.libs/libgstmpeg4videoparse.so libgstmpeg4videoparse.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-mpegdemux2.xml b/docs/plugins/inspect/plugin-mpegdemux2.xml index 01f8015fbc..571a42f9be 100644 --- a/docs/plugins/inspect/plugin-mpegdemux2.xml +++ b/docs/plugins/inspect/plugin-mpegdemux2.xml @@ -3,10 +3,10 @@ MPEG demuxers ../../gst/mpegdemux/.libs/libgstmpegdemux.so libgstmpegdemux.so - 0.10.21 + 0.10.21.1 unknown gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-mpegpsmux.xml b/docs/plugins/inspect/plugin-mpegpsmux.xml index 288f4fa463..65b5036b76 100644 --- a/docs/plugins/inspect/plugin-mpegpsmux.xml +++ b/docs/plugins/inspect/plugin-mpegpsmux.xml @@ -3,10 +3,10 @@ MPEG-PS muxer ../../gst/mpegpsmux/.libs/libgstmpegpsmux.so libgstmpegpsmux.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-mpegtsmux.xml b/docs/plugins/inspect/plugin-mpegtsmux.xml index f1cdcaa912..291c001e69 100644 --- a/docs/plugins/inspect/plugin-mpegtsmux.xml +++ b/docs/plugins/inspect/plugin-mpegtsmux.xml @@ -3,10 +3,10 @@ MPEG-TS muxer ../../gst/mpegtsmux/.libs/libgstmpegtsmux.so libgstmpegtsmux.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-mpegvideoparse.xml b/docs/plugins/inspect/plugin-mpegvideoparse.xml index d281c555a6..2aa5386813 100644 --- a/docs/plugins/inspect/plugin-mpegvideoparse.xml +++ b/docs/plugins/inspect/plugin-mpegvideoparse.xml @@ -3,10 +3,10 @@ MPEG-1 and MPEG-2 video parser ../../gst/mpegvideoparse/.libs/libgstmpegvideoparse.so libgstmpegvideoparse.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-mplex.xml b/docs/plugins/inspect/plugin-mplex.xml index 9e16222194..1979969e87 100644 --- a/docs/plugins/inspect/plugin-mplex.xml +++ b/docs/plugins/inspect/plugin-mplex.xml @@ -3,10 +3,10 @@ High-quality MPEG/DVD/SVCD/VCD video/audio multiplexer ../../ext/mplex/.libs/libgstmplex.so libgstmplex.so - 0.10.21 + 0.10.21.1 GPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-musepack.xml b/docs/plugins/inspect/plugin-musepack.xml index f03e65728a..027cda9b81 100644 --- a/docs/plugins/inspect/plugin-musepack.xml +++ b/docs/plugins/inspect/plugin-musepack.xml @@ -3,10 +3,10 @@ Musepack decoder ../../ext/musepack/.libs/libgstmusepack.so libgstmusepack.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-musicbrainz.xml b/docs/plugins/inspect/plugin-musicbrainz.xml index 058f28171e..c6a0668f9a 100644 --- a/docs/plugins/inspect/plugin-musicbrainz.xml +++ b/docs/plugins/inspect/plugin-musicbrainz.xml @@ -3,10 +3,10 @@ A TRM signature producer based on libmusicbrainz ../../ext/musicbrainz/.libs/libgsttrm.so libgsttrm.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-mve.xml b/docs/plugins/inspect/plugin-mve.xml index fdcafe19ed..82ead0da84 100644 --- a/docs/plugins/inspect/plugin-mve.xml +++ b/docs/plugins/inspect/plugin-mve.xml @@ -3,10 +3,10 @@ Interplay MVE movie format manipulation ../../gst/mve/.libs/libgstmve.so libgstmve.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-mxf.xml b/docs/plugins/inspect/plugin-mxf.xml index f5261fae5f..4428508c59 100644 --- a/docs/plugins/inspect/plugin-mxf.xml +++ b/docs/plugins/inspect/plugin-mxf.xml @@ -3,10 +3,10 @@ MXF plugin library ../../gst/mxf/.libs/libgstmxf.so libgstmxf.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-mythtv.xml b/docs/plugins/inspect/plugin-mythtv.xml index 923c5f4082..c7c533fde7 100644 --- a/docs/plugins/inspect/plugin-mythtv.xml +++ b/docs/plugins/inspect/plugin-mythtv.xml @@ -3,10 +3,10 @@ lib MythTV src ../../ext/mythtv/.libs/libgstmythtvsrc.so libgstmythtvsrc.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-nas.xml b/docs/plugins/inspect/plugin-nas.xml index 97e9ae50e5..488c4b2848 100644 --- a/docs/plugins/inspect/plugin-nas.xml +++ b/docs/plugins/inspect/plugin-nas.xml @@ -3,10 +3,10 @@ NAS (Network Audio System) support for GStreamer ../../ext/nas/.libs/libgstnassink.so libgstnassink.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-neon.xml b/docs/plugins/inspect/plugin-neon.xml index ef39b73d1d..2fae2b6898 100644 --- a/docs/plugins/inspect/plugin-neon.xml +++ b/docs/plugins/inspect/plugin-neon.xml @@ -3,10 +3,10 @@ lib neon http client src ../../ext/neon/.libs/libgstneonhttpsrc.so libgstneonhttpsrc.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-nsf.xml b/docs/plugins/inspect/plugin-nsf.xml index 3df601eb03..2020713746 100644 --- a/docs/plugins/inspect/plugin-nsf.xml +++ b/docs/plugins/inspect/plugin-nsf.xml @@ -3,10 +3,10 @@ Uses nosefart to decode .nsf files ../../gst/nsf/.libs/libgstnsf.so libgstnsf.so - 0.10.21 + 0.10.21.1 GPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-nuvdemux.xml b/docs/plugins/inspect/plugin-nuvdemux.xml index 970a23657f..ae15d8c7e7 100644 --- a/docs/plugins/inspect/plugin-nuvdemux.xml +++ b/docs/plugins/inspect/plugin-nuvdemux.xml @@ -3,10 +3,10 @@ Demuxes MythTV NuppelVideo files ../../gst/nuvdemux/.libs/libgstnuvdemux.so libgstnuvdemux.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-ofa.xml b/docs/plugins/inspect/plugin-ofa.xml index df1a4e3061..cdc9589ac8 100644 --- a/docs/plugins/inspect/plugin-ofa.xml +++ b/docs/plugins/inspect/plugin-ofa.xml @@ -3,10 +3,10 @@ Calculate MusicIP fingerprint from audio files ../../ext/ofa/.libs/libgstofa.so libgstofa.so - 0.10.21 + 0.10.21.1 GPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-opencv.xml b/docs/plugins/inspect/plugin-opencv.xml index 7a63aa09e0..6270b768aa 100644 --- a/docs/plugins/inspect/plugin-opencv.xml +++ b/docs/plugins/inspect/plugin-opencv.xml @@ -3,10 +3,10 @@ GStreamer OpenCV Plugins ../../ext/opencv/.libs/libgstopencv.so libgstopencv.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-pcapparse.xml b/docs/plugins/inspect/plugin-pcapparse.xml index 10902f80b6..ebf840750d 100644 --- a/docs/plugins/inspect/plugin-pcapparse.xml +++ b/docs/plugins/inspect/plugin-pcapparse.xml @@ -3,7 +3,7 @@ Element parsing raw pcap streams ../../gst/pcapparse/.libs/libgstpcapparse.so libgstpcapparse.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad GStreamer diff --git a/docs/plugins/inspect/plugin-pnm.xml b/docs/plugins/inspect/plugin-pnm.xml index 900f7f62bd..c2beb44845 100644 --- a/docs/plugins/inspect/plugin-pnm.xml +++ b/docs/plugins/inspect/plugin-pnm.xml @@ -3,10 +3,10 @@ PNM plugin ../../gst/pnm/.libs/libgstpnm.so libgstpnm.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-qtmux.xml b/docs/plugins/inspect/plugin-qtmux.xml index c8482541a6..ea5a9ac81b 100644 --- a/docs/plugins/inspect/plugin-qtmux.xml +++ b/docs/plugins/inspect/plugin-qtmux.xml @@ -3,10 +3,10 @@ Quicktime Muxer plugin ../../gst/qtmux/.libs/libgstqtmux.so libgstqtmux.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-rawparse.xml b/docs/plugins/inspect/plugin-rawparse.xml index 0cb0e1acab..0cbe1ce654 100644 --- a/docs/plugins/inspect/plugin-rawparse.xml +++ b/docs/plugins/inspect/plugin-rawparse.xml @@ -3,10 +3,10 @@ Parses byte streams into raw frames ../../gst/rawparse/.libs/libgstrawparse.so libgstrawparse.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-real.xml b/docs/plugins/inspect/plugin-real.xml index 9d1d6a0814..44b59fe0a8 100644 --- a/docs/plugins/inspect/plugin-real.xml +++ b/docs/plugins/inspect/plugin-real.xml @@ -3,10 +3,10 @@ Decode REAL streams ../../gst/real/.libs/libgstreal.so libgstreal.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-resindvd.xml b/docs/plugins/inspect/plugin-resindvd.xml index ef048148d8..5081bcfec8 100644 --- a/docs/plugins/inspect/plugin-resindvd.xml +++ b/docs/plugins/inspect/plugin-resindvd.xml @@ -3,7 +3,7 @@ Resin DVD playback elements ../../ext/resindvd/.libs/libresindvd.so libresindvd.so - 0.10.21 + 0.10.21.1 GPL gst-plugins-bad GStreamer diff --git a/docs/plugins/inspect/plugin-rfbsrc.xml b/docs/plugins/inspect/plugin-rfbsrc.xml index e5edcbec13..245aadf9bd 100644 --- a/docs/plugins/inspect/plugin-rfbsrc.xml +++ b/docs/plugins/inspect/plugin-rfbsrc.xml @@ -3,10 +3,10 @@ Connects to a VNC server and decodes RFB stream ../../gst/librfb/.libs/libgstrfbsrc.so libgstrfbsrc.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-rsvg.xml b/docs/plugins/inspect/plugin-rsvg.xml index 6f51000284..3b94b9ea1c 100644 --- a/docs/plugins/inspect/plugin-rsvg.xml +++ b/docs/plugins/inspect/plugin-rsvg.xml @@ -3,10 +3,10 @@ RSVG plugin library ../../ext/rsvg/.libs/libgstrsvg.so libgstrsvg.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-rtpmux.xml b/docs/plugins/inspect/plugin-rtpmux.xml index f4718dc205..27351aff92 100644 --- a/docs/plugins/inspect/plugin-rtpmux.xml +++ b/docs/plugins/inspect/plugin-rtpmux.xml @@ -3,10 +3,10 @@ RTP Muxer plugins ../../gst/rtpmux/.libs/libgstrtpmux.so libgstrtpmux.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-scaletempo.xml b/docs/plugins/inspect/plugin-scaletempo.xml index 70519cd6a2..347dd9c3c4 100644 --- a/docs/plugins/inspect/plugin-scaletempo.xml +++ b/docs/plugins/inspect/plugin-scaletempo.xml @@ -3,7 +3,7 @@ Scale audio tempo in sync with playback rate ../../gst/scaletempo/.libs/libgstscaletempoplugin.so libgstscaletempoplugin.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad GStreamer diff --git a/docs/plugins/inspect/plugin-schro.xml b/docs/plugins/inspect/plugin-schro.xml index e8c8b41a78..3bb341ad5c 100644 --- a/docs/plugins/inspect/plugin-schro.xml +++ b/docs/plugins/inspect/plugin-schro.xml @@ -3,10 +3,10 @@ Schroedinger plugin ../../ext/schroedinger/.libs/libgstschro.so libgstschro.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-sdl.xml b/docs/plugins/inspect/plugin-sdl.xml index 871e24543a..b6a98cbc5f 100644 --- a/docs/plugins/inspect/plugin-sdl.xml +++ b/docs/plugins/inspect/plugin-sdl.xml @@ -3,10 +3,10 @@ SDL (Simple DirectMedia Layer) support for GStreamer ../../ext/sdl/.libs/libgstsdl.so libgstsdl.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-sdp.xml b/docs/plugins/inspect/plugin-sdp.xml index 015a898782..77f4f631fb 100644 --- a/docs/plugins/inspect/plugin-sdp.xml +++ b/docs/plugins/inspect/plugin-sdp.xml @@ -3,10 +3,10 @@ configure streaming sessions using SDP ../../gst/sdp/.libs/libgstsdpelem.so libgstsdpelem.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-segmentclip.xml b/docs/plugins/inspect/plugin-segmentclip.xml index b64be372e0..3e2e837b60 100644 --- a/docs/plugins/inspect/plugin-segmentclip.xml +++ b/docs/plugins/inspect/plugin-segmentclip.xml @@ -3,10 +3,10 @@ Segment clip elements ../../gst/segmentclip/.libs/libgstsegmentclip.so libgstsegmentclip.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-shm.xml b/docs/plugins/inspect/plugin-shm.xml index f45fff3920..bd2f46df01 100644 --- a/docs/plugins/inspect/plugin-shm.xml +++ b/docs/plugins/inspect/plugin-shm.xml @@ -3,10 +3,10 @@ shared memory sink source ../../sys/shm/.libs/libgstshm.so libgstshm.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-sndfile.xml b/docs/plugins/inspect/plugin-sndfile.xml index 5161cccca0..bc014bd923 100644 --- a/docs/plugins/inspect/plugin-sndfile.xml +++ b/docs/plugins/inspect/plugin-sndfile.xml @@ -3,10 +3,10 @@ use libsndfile to read and write audio from and to files ../../ext/sndfile/.libs/libgstsndfile.so libgstsndfile.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-soundtouch.xml b/docs/plugins/inspect/plugin-soundtouch.xml index 3934de78cd..bc4817fac2 100644 --- a/docs/plugins/inspect/plugin-soundtouch.xml +++ b/docs/plugins/inspect/plugin-soundtouch.xml @@ -3,10 +3,10 @@ Audio Pitch Controller & BPM Detection ../../ext/soundtouch/.libs/libgstsoundtouch.so libgstsoundtouch.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-speed.xml b/docs/plugins/inspect/plugin-speed.xml index 52e7f76176..487a7f9d7e 100644 --- a/docs/plugins/inspect/plugin-speed.xml +++ b/docs/plugins/inspect/plugin-speed.xml @@ -3,10 +3,10 @@ Set speed/pitch on audio/raw streams (resampler) ../../gst/speed/.libs/libgstspeed.so libgstspeed.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-stereo.xml b/docs/plugins/inspect/plugin-stereo.xml index 9d76108c07..fc7f5e2c32 100644 --- a/docs/plugins/inspect/plugin-stereo.xml +++ b/docs/plugins/inspect/plugin-stereo.xml @@ -3,10 +3,10 @@ Muck with the stereo signal, enhance it's 'stereo-ness' ../../gst/stereo/.libs/libgststereo.so libgststereo.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-subenc.xml b/docs/plugins/inspect/plugin-subenc.xml index cf47978af6..9c37f4ca86 100644 --- a/docs/plugins/inspect/plugin-subenc.xml +++ b/docs/plugins/inspect/plugin-subenc.xml @@ -3,10 +3,10 @@ subtitle encoders ../../gst/subenc/.libs/libgstsubenc.so libgstsubenc.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-tta.xml b/docs/plugins/inspect/plugin-tta.xml index 0468a59003..46fa202bca 100644 --- a/docs/plugins/inspect/plugin-tta.xml +++ b/docs/plugins/inspect/plugin-tta.xml @@ -3,10 +3,10 @@ TTA lossless audio format handling ../../gst/tta/.libs/libgsttta.so libgsttta.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-vcdsrc.xml b/docs/plugins/inspect/plugin-vcdsrc.xml index 5647e95c46..0a89e414da 100644 --- a/docs/plugins/inspect/plugin-vcdsrc.xml +++ b/docs/plugins/inspect/plugin-vcdsrc.xml @@ -3,10 +3,10 @@ Asynchronous read from VCD disk ../../sys/vcd/.libs/libgstvcdsrc.so libgstvcdsrc.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-vdpau.xml b/docs/plugins/inspect/plugin-vdpau.xml index 2d509cfe84..385e840b71 100644 --- a/docs/plugins/inspect/plugin-vdpau.xml +++ b/docs/plugins/inspect/plugin-vdpau.xml @@ -3,7 +3,7 @@ Various elements utilizing VDPAU ../../sys/vdpau/.libs/libgstvdpau.so libgstvdpau.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad GStreamer diff --git a/docs/plugins/inspect/plugin-videomaxrate.xml b/docs/plugins/inspect/plugin-videomaxrate.xml index 59fc04f344..aced0ff963 100644 --- a/docs/plugins/inspect/plugin-videomaxrate.xml +++ b/docs/plugins/inspect/plugin-videomaxrate.xml @@ -3,10 +3,10 @@ Drop extra frames ../../gst/videomaxrate/.libs/libgstvideomaxrate.so libgstvideomaxrate.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-videomeasure.xml b/docs/plugins/inspect/plugin-videomeasure.xml index e1068f6143..6f6287d7ad 100644 --- a/docs/plugins/inspect/plugin-videomeasure.xml +++ b/docs/plugins/inspect/plugin-videomeasure.xml @@ -3,10 +3,10 @@ Various video measurers ../../gst/videomeasure/.libs/libgstvideomeasure.so libgstvideomeasure.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-videosignal.xml b/docs/plugins/inspect/plugin-videosignal.xml index 53a3b9b071..bed6211b1d 100644 --- a/docs/plugins/inspect/plugin-videosignal.xml +++ b/docs/plugins/inspect/plugin-videosignal.xml @@ -3,10 +3,10 @@ Various video signal analysers ../../gst/videosignal/.libs/libgstvideosignal.so libgstvideosignal.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-vmnc.xml b/docs/plugins/inspect/plugin-vmnc.xml index df56077290..4297561031 100644 --- a/docs/plugins/inspect/plugin-vmnc.xml +++ b/docs/plugins/inspect/plugin-vmnc.xml @@ -3,10 +3,10 @@ VmWare Video Codec plugins ../../gst/vmnc/.libs/libgstvmnc.so libgstvmnc.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-vp8.xml b/docs/plugins/inspect/plugin-vp8.xml index d9e5ce07d2..ce75b4273c 100644 --- a/docs/plugins/inspect/plugin-vp8.xml +++ b/docs/plugins/inspect/plugin-vp8.xml @@ -3,10 +3,10 @@ VP8 plugin ../../ext/vp8/.libs/libgstvp8.so libgstvp8.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-wildmidi.xml b/docs/plugins/inspect/plugin-wildmidi.xml index da37c34e91..0de455b497 100644 --- a/docs/plugins/inspect/plugin-wildmidi.xml +++ b/docs/plugins/inspect/plugin-wildmidi.xml @@ -3,10 +3,10 @@ Wildmidi Plugin ../../ext/timidity/.libs/libgstwildmidi.so libgstwildmidi.so - 0.10.21 + 0.10.21.1 GPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-xvid.xml b/docs/plugins/inspect/plugin-xvid.xml index eda7e1d689..16a9fea272 100644 --- a/docs/plugins/inspect/plugin-xvid.xml +++ b/docs/plugins/inspect/plugin-xvid.xml @@ -3,10 +3,10 @@ XviD plugin library ../../ext/xvid/.libs/libgstxvid.so libgstxvid.so - 0.10.21 + 0.10.21.1 GPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/docs/plugins/inspect/plugin-y4mdec.xml b/docs/plugins/inspect/plugin-y4mdec.xml index 55816b21f5..ab20ae84ea 100644 --- a/docs/plugins/inspect/plugin-y4mdec.xml +++ b/docs/plugins/inspect/plugin-y4mdec.xml @@ -3,7 +3,7 @@ FIXME ../../gst/y4m/.libs/libgsty4mdec.so libgsty4mdec.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad GStreamer Bad Plug-ins diff --git a/docs/plugins/inspect/plugin-zbar.xml b/docs/plugins/inspect/plugin-zbar.xml index 0176145320..b160fe54b1 100644 --- a/docs/plugins/inspect/plugin-zbar.xml +++ b/docs/plugins/inspect/plugin-zbar.xml @@ -3,10 +3,10 @@ zbar barcode scanner ../../ext/zbar/.libs/libgstzbar.so libgstzbar.so - 0.10.21 + 0.10.21.1 LGPL gst-plugins-bad - GStreamer Bad Plug-ins source release + GStreamer Bad Plug-ins git Unknown package origin diff --git a/win32/common/config.h b/win32/common/config.h index af55e3fe76..025e4327b7 100644 --- a/win32/common/config.h +++ b/win32/common/config.h @@ -24,7 +24,7 @@ #define GST_LICENSE "LGPL" /* package name in plugins */ -#define GST_PACKAGE_NAME "GStreamer Bad Plug-ins source release" +#define GST_PACKAGE_NAME "GStreamer Bad Plug-ins git" /* package origin */ #define GST_PACKAGE_ORIGIN "Unknown package origin" @@ -199,7 +199,7 @@ #undef USE_POISONING /* Version number of package */ -#define VERSION "0.10.21" +#define VERSION "0.10.21.1" /* Define to 1 if your processor stores words with the most significant byte first (like Motorola and SPARC, unlike Intel and VAX). */ From 0b3ad60269ececdfac4e66effc3d4918cbc95414 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Tue, 18 Jan 2011 17:31:06 -0300 Subject: [PATCH 308/448] camerabin: add names for more elements --- gst/camerabin/camerabingeneral.c | 4 +++- gst/camerabin/camerabingeneral.h | 2 +- gst/camerabin/camerabinvideo.c | 17 +++++++++++------ gst/camerabin/gstcamerabin.c | 29 +++++++++++++++++++---------- 4 files changed, 34 insertions(+), 18 deletions(-) diff --git a/gst/camerabin/camerabingeneral.c b/gst/camerabin/camerabingeneral.c index b82b22cfc9..f47b9d23bf 100644 --- a/gst/camerabin/camerabingeneral.c +++ b/gst/camerabin/camerabingeneral.c @@ -114,6 +114,7 @@ gst_camerabin_try_add_element (GstBin * bin, GstElement * new_elem) * gst_camerabin_create_and_add_element: * @bin: tries adding an element to this bin * @elem_name: name of the element to be created + * @instance_name: name of the instance of the element to be created * * Creates an element according to given name and * adds it to given @bin. Looks for an unconnected src pad @@ -122,7 +123,8 @@ gst_camerabin_try_add_element (GstBin * bin, GstElement * new_elem) * Returns: pointer to the new element if successful, NULL otherwise. */ GstElement * -gst_camerabin_create_and_add_element (GstBin * bin, const gchar * elem_name) +gst_camerabin_create_and_add_element (GstBin * bin, const gchar * elem_name, + const gchar * instance_name) { GstElement *new_elem; diff --git a/gst/camerabin/camerabingeneral.h b/gst/camerabin/camerabingeneral.h index 0e84e4ad28..12a4d46937 100644 --- a/gst/camerabin/camerabingeneral.h +++ b/gst/camerabin/camerabingeneral.h @@ -25,7 +25,7 @@ gboolean gst_camerabin_try_add_element (GstBin * bin, GstElement * new_elem); gboolean gst_camerabin_add_element (GstBin * bin, GstElement * new_elem); -GstElement *gst_camerabin_create_and_add_element (GstBin * bin, const gchar * elem_name); +GstElement *gst_camerabin_create_and_add_element (GstBin * bin, const gchar * elem_name, const gchar * instance_name); GstElement * gst_camerabin_setup_default_element (GstBin * bin, GstElement *user_elem, const gchar *auto_elem_name, const gchar *default_elem_name); diff --git a/gst/camerabin/camerabinvideo.c b/gst/camerabin/camerabinvideo.c index 6b0ed107bf..9100518767 100644 --- a/gst/camerabin/camerabinvideo.c +++ b/gst/camerabin/camerabinvideo.c @@ -542,7 +542,8 @@ gst_camerabin_video_create_elements (GstCameraBinVideo * vid) } /* Add tee element */ - if (!(vid->tee = gst_camerabin_create_and_add_element (vidbin, "tee"))) { + if (!(vid->tee = + gst_camerabin_create_and_add_element (vidbin, "tee", "video-tee"))) { goto error; } @@ -569,7 +570,7 @@ gst_camerabin_video_create_elements (GstCameraBinVideo * vid) if (vid->flags & GST_CAMERABIN_FLAG_VIDEO_COLOR_CONVERSION) { /* Add colorspace converter */ if (gst_camerabin_create_and_add_element (vidbin, - "ffmpegcolorspace") == NULL) { + "ffmpegcolorspace", "video-ffmpegcolorspace") == NULL) { goto error; } } @@ -581,7 +582,8 @@ gst_camerabin_video_create_elements (GstCameraBinVideo * vid) goto error; } } else if (!(vid->vid_enc = - gst_camerabin_create_and_add_element (vidbin, DEFAULT_VID_ENC))) { + gst_camerabin_create_and_add_element (vidbin, DEFAULT_VID_ENC, + "video-encoder"))) { goto error; } @@ -592,13 +594,15 @@ gst_camerabin_video_create_elements (GstCameraBinVideo * vid) goto error; } } else if (!(vid->muxer = - gst_camerabin_create_and_add_element (vidbin, DEFAULT_MUX))) { + gst_camerabin_create_and_add_element (vidbin, DEFAULT_MUX, + "video-muxer"))) { goto error; } /* Add sink element for storing the video */ if (!(vid->sink = - gst_camerabin_create_and_add_element (vidbin, DEFAULT_SINK))) { + gst_camerabin_create_and_add_element (vidbin, DEFAULT_SINK, + "video-sink"))) { goto error; } g_object_set (G_OBJECT (vid->sink), "location", vid->filename->str, "buffer-mode", 2, /* non buffered io */ @@ -648,7 +652,8 @@ gst_camerabin_video_create_elements (GstCameraBinVideo * vid) goto error; } } else if (!(vid->aud_enc = - gst_camerabin_create_and_add_element (vidbin, DEFAULT_AUD_ENC))) { + gst_camerabin_create_and_add_element (vidbin, DEFAULT_AUD_ENC, + "audio-encoder"))) { goto error; } diff --git a/gst/camerabin/gstcamerabin.c b/gst/camerabin/gstcamerabin.c index 2744e58744..0cc6444ae6 100644 --- a/gst/camerabin/gstcamerabin.c +++ b/gst/camerabin/gstcamerabin.c @@ -591,21 +591,26 @@ camerabin_create_src_elements (GstCameraBin * camera) goto done; } if (camera->flags & GST_CAMERABIN_FLAG_SOURCE_COLOR_CONVERSION) { - if (!gst_camerabin_create_and_add_element (cbin, "ffmpegcolorspace")) + if (!gst_camerabin_create_and_add_element (cbin, "ffmpegcolorspace", + "src-ffmpegcolorspace")) goto done; } if (!(camera->src_filter = - gst_camerabin_create_and_add_element (cbin, "capsfilter"))) + gst_camerabin_create_and_add_element (cbin, "capsfilter", + "src-capsfilter"))) goto done; if (camera->flags & GST_CAMERABIN_FLAG_SOURCE_RESIZE) { if (!(camera->src_zoom_crop = - gst_camerabin_create_and_add_element (cbin, "videocrop"))) + gst_camerabin_create_and_add_element (cbin, "videocrop", + "src-videocrop"))) goto done; if (!(camera->src_zoom_scale = - gst_camerabin_create_and_add_element (cbin, "videoscale"))) + gst_camerabin_create_and_add_element (cbin, "videoscale", + "src-videoscale"))) goto done; if (!(camera->src_zoom_filter = - gst_camerabin_create_and_add_element (cbin, "capsfilter"))) + gst_camerabin_create_and_add_element (cbin, "capsfilter", + "src-resize-capsfilter"))) goto done; } if (camera->app_video_filter) { @@ -614,7 +619,7 @@ camerabin_create_src_elements (GstCameraBin * camera) } } if (!(camera->src_out_sel = - gst_camerabin_create_and_add_element (cbin, "output-selector"))) + gst_camerabin_create_and_add_element (cbin, "output-selector", NULL))) goto done; /* Set pad-negotiation-mode to active */ @@ -681,7 +686,8 @@ camerabin_create_view_elements (GstCameraBin * camera) GstBin *cbin = GST_BIN (camera); if (!(camera->view_in_sel = - gst_camerabin_create_and_add_element (cbin, "input-selector"))) { + gst_camerabin_create_and_add_element (cbin, "input-selector", + NULL))) { goto error; } @@ -696,18 +702,21 @@ camerabin_create_view_elements (GstCameraBin * camera) /* Add videoscale in case we need to downscale frame for view finder */ if (camera->flags & GST_CAMERABIN_FLAG_VIEWFINDER_SCALE) { if (!(camera->view_scale = - gst_camerabin_create_and_add_element (cbin, "videoscale"))) { + gst_camerabin_create_and_add_element (cbin, "videoscale", + "vf-videoscale"))) { goto error; } /* Add capsfilter to maintain aspect ratio while scaling */ if (!(camera->aspect_filter = - gst_camerabin_create_and_add_element (cbin, "capsfilter"))) { + gst_camerabin_create_and_add_element (cbin, "capsfilter", + "vf-scale-capsfilter"))) { goto error; } } if (camera->flags & GST_CAMERABIN_FLAG_VIEWFINDER_COLOR_CONVERSION) { - if (!gst_camerabin_create_and_add_element (cbin, "ffmpegcolorspace")) { + if (!gst_camerabin_create_and_add_element (cbin, "ffmpegcolorspace", + "vf-ffmpegcolorspace")) { goto error; } } From 5dbee0c39c96f89d4af28ddc9a8622b861e41de0 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Mon, 24 Jan 2011 10:08:17 -0300 Subject: [PATCH 309/448] tests: imagecapturebin: Only run a test if -good is 0.10.27 or newer One test on imagecapturebin requires dcbba0932dc579abd6aab4460fa1a416374eda1b on good that was released on 0.10.27. https://bugzilla.gnome.org/show_bug.cgi?id=640286 --- tests/check/elements/imagecapturebin.c | 22 ++++++++++++++++++---- 1 file changed, 18 insertions(+), 4 deletions(-) diff --git a/tests/check/elements/imagecapturebin.c b/tests/check/elements/imagecapturebin.c index 6a1ecee721..34f71c7017 100644 --- a/tests/check/elements/imagecapturebin.c +++ b/tests/check/elements/imagecapturebin.c @@ -380,14 +380,28 @@ GST_END_TEST; static Suite * imagecapturebin_suite (void) { + GstElementFactory *jpegenc_factory; + Suite *s = suite_create ("imagecapturebin"); TCase *tc_chain = tcase_create ("general"); + jpegenc_factory = gst_element_factory_find ("jpegenc"); + suite_add_tcase (s, tc_chain); - tcase_add_test (tc_chain, test_simple_capture); - tcase_add_test (tc_chain, test_multiple_captures_different_caps); - tcase_add_test (tc_chain, test_setting_encoder); - tcase_add_test (tc_chain, test_setting_muxer); + if (jpegenc_factory) { + tcase_add_test (tc_chain, test_simple_capture); + + /* only adds this test if jpegenc contains the fix for its getcaps + * The fix on good: dcbba0932dc579abd6aab4460fa1a416374eda1b */ + if (gst_plugin_feature_check_version (jpegenc_factory, 0, 10, 27)) + tcase_add_test (tc_chain, test_multiple_captures_different_caps); + else + GST_WARNING ("Skipped test that needs gst-plugins-good 0.10.27"); + + tcase_add_test (tc_chain, test_setting_encoder); + tcase_add_test (tc_chain, test_setting_muxer); + } else + GST_WARNING ("Skipped imagecapturebin tests because jpegenc is missing"); return s; } From 7944a27ee3533d8a540ca2cbe2af70f3e0b0821d Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Mon, 24 Jan 2011 11:05:41 -0300 Subject: [PATCH 310/448] tests: camerabin2: Only run a test if -good 0.10.27 is present A camerabin2 tests depends on the commit dcbba0932dc579abd6aab4460fa1a416374eda1b for jpegenc on -good that was released on 0.10.27. This patch makes it check for this version before running the test. --- tests/check/elements/camerabin2.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/tests/check/elements/camerabin2.c b/tests/check/elements/camerabin2.c index 6f3e295cb0..3f65cc7f64 100644 --- a/tests/check/elements/camerabin2.c +++ b/tests/check/elements/camerabin2.c @@ -647,10 +647,17 @@ TestCaseDef tests[] = { static Suite * camerabin_suite (void) { + GstElementFactory *jpegenc_factory; Suite *s = suite_create ("camerabin2"); gint i; TCase *tc_generic = tcase_create ("generic"); + jpegenc_factory = gst_element_factory_find ("jpegenc"); + if (jpegenc_factory == NULL) { + GST_WARNING ("Skipping camerabin2 tests because jpegenc is missing"); + goto end; + } + suite_add_tcase (s, tc_generic); tcase_add_checked_fixture (tc_generic, setup_wrappercamerabinsrc_videotestsrc, teardown); @@ -667,10 +674,15 @@ camerabin_suite (void) tcase_add_test (tc_basic, test_single_image_capture); tcase_add_test (tc_basic, test_single_video_recording); tcase_add_test (tc_basic, test_image_video_cycle); - tcase_add_test (tc_basic, test_multiple_image_captures); + if (gst_plugin_feature_check_version (jpegenc_factory, 0, 10, 27)) + tcase_add_test (tc_basic, test_multiple_image_captures); + else + GST_WARNING ("Skipping image capture test because -good 0.10.27 is " + "needed"); tcase_add_test (tc_basic, test_multiple_video_recordings); } +end: return s; } From 162383e6b24c4b1ec79eb5126c3b0c722932365a Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Mon, 24 Jan 2011 11:55:41 -0300 Subject: [PATCH 311/448] tests: camerabin2: imagecapturebin2: fix warnings Warnings passed me by on the last commits to camerabin2 tests, fixing them. --- tests/check/elements/camerabin2.c | 3 ++- tests/check/elements/imagecapturebin.c | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/check/elements/camerabin2.c b/tests/check/elements/camerabin2.c index 3f65cc7f64..3c59dbeea3 100644 --- a/tests/check/elements/camerabin2.c +++ b/tests/check/elements/camerabin2.c @@ -674,7 +674,8 @@ camerabin_suite (void) tcase_add_test (tc_basic, test_single_image_capture); tcase_add_test (tc_basic, test_single_video_recording); tcase_add_test (tc_basic, test_image_video_cycle); - if (gst_plugin_feature_check_version (jpegenc_factory, 0, 10, 27)) + if (gst_plugin_feature_check_version ((GstPluginFeature *) jpegenc_factory, + 0, 10, 27)) tcase_add_test (tc_basic, test_multiple_image_captures); else GST_WARNING ("Skipping image capture test because -good 0.10.27 is " diff --git a/tests/check/elements/imagecapturebin.c b/tests/check/elements/imagecapturebin.c index 34f71c7017..5c5f73613b 100644 --- a/tests/check/elements/imagecapturebin.c +++ b/tests/check/elements/imagecapturebin.c @@ -393,7 +393,8 @@ imagecapturebin_suite (void) /* only adds this test if jpegenc contains the fix for its getcaps * The fix on good: dcbba0932dc579abd6aab4460fa1a416374eda1b */ - if (gst_plugin_feature_check_version (jpegenc_factory, 0, 10, 27)) + if (gst_plugin_feature_check_version ((GstPluginFeature *) jpegenc_factory, + 0, 10, 27)) tcase_add_test (tc_chain, test_multiple_captures_different_caps); else GST_WARNING ("Skipped test that needs gst-plugins-good 0.10.27"); From bc1f57a6457329a0217e7428f1846c6f185eecd4 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Wed, 29 Dec 2010 14:12:06 -0300 Subject: [PATCH 312/448] wrappercamerabinsrc: Use drop_eos function from camerabingeneral There was already a event probe function for dropping EOS on camerabingenereal, so use that instead of replicating the code --- gst/camerabin2/gstwrappercamerabinsrc.c | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/gst/camerabin2/gstwrappercamerabinsrc.c b/gst/camerabin2/gstwrappercamerabinsrc.c index ebf2d8e87b..707f70ab57 100644 --- a/gst/camerabin2/gstwrappercamerabinsrc.c +++ b/gst/camerabin2/gstwrappercamerabinsrc.c @@ -226,15 +226,6 @@ gst_wrapper_camera_bin_src_event (GstPad * pad, GstEvent * event) return src->srcpad_event_func (pad, event); } -static gboolean -src_event_probe (GstPad * pad, GstEvent * event, gpointer user_data) -{ - if (GST_EVENT_TYPE (event) == GST_EVENT_EOS) { - return FALSE; - } - return TRUE; -} - /** * gst_wrapper_camera_bin_src_construct_pipeline: * @bcamsrc: camerasrc object @@ -283,7 +274,7 @@ gst_wrapper_camera_bin_src_construct_pipeline (GstBaseCameraSrc * bcamsrc) pad = gst_element_get_static_pad (self->src_vid_src, "src"); self->src_event_probe_id = gst_pad_add_event_probe (pad, - (GCallback) src_event_probe, self); + (GCallback) gst_camerabin_drop_eos_probe, NULL); gst_object_unref (pad); } From 44e500cf7d694263fb0614b34d96ed197fdb192f Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Wed, 29 Dec 2010 23:48:31 -0300 Subject: [PATCH 313/448] camerabin2: tests: Use mainloops Use mainloops instead of sleeps to read bus messages and catch errors. --- tests/check/elements/camerabin2.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/tests/check/elements/camerabin2.c b/tests/check/elements/camerabin2.c index 3c59dbeea3..5a6fc7cddb 100644 --- a/tests/check/elements/camerabin2.c +++ b/tests/check/elements/camerabin2.c @@ -402,7 +402,8 @@ GST_START_TEST (test_single_image_capture) fail_unless (camera != NULL); g_signal_emit_by_name (camera, "start-capture", NULL); - g_usleep (G_USEC_PER_SEC * 3); + g_timeout_add_seconds (3, (GSourceFunc) g_main_loop_quit, main_loop); + g_main_loop_run (main_loop); gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL); check_file_validity (IMAGE_FILENAME, 0, NULL, 0, 0); @@ -444,7 +445,9 @@ GST_START_TEST (test_multiple_image_captures) gst_caps_unref (caps); g_signal_emit_by_name (camera, "start-capture", NULL); - g_usleep (G_USEC_PER_SEC * 1); + + g_timeout_add_seconds (3, (GSourceFunc) g_main_loop_quit, main_loop); + g_main_loop_run (main_loop); } g_usleep (G_USEC_PER_SEC * 3); @@ -478,7 +481,9 @@ GST_START_TEST (test_single_video_recording) g_signal_emit_by_name (camera, "start-capture", NULL); /* Record for one seconds */ - g_usleep (VIDEO_DURATION * G_USEC_PER_SEC); + g_timeout_add_seconds (VIDEO_DURATION, (GSourceFunc) g_main_loop_quit, + main_loop); + g_main_loop_run (main_loop); g_signal_emit_by_name (camera, "stop-capture", NULL); @@ -525,9 +530,13 @@ GST_START_TEST (test_multiple_video_recordings) gst_caps_unref (caps); g_signal_emit_by_name (camera, "start-capture", NULL); - g_usleep (VIDEO_DURATION * G_USEC_PER_SEC); + g_timeout_add_seconds (VIDEO_DURATION, (GSourceFunc) g_main_loop_quit, + main_loop); + g_main_loop_run (main_loop); g_signal_emit_by_name (camera, "stop-capture", NULL); - g_usleep (1 * G_USEC_PER_SEC); + + g_timeout_add_seconds (1, (GSourceFunc) g_main_loop_quit, main_loop); + g_main_loop_run (main_loop); } gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL); @@ -566,12 +575,15 @@ GST_START_TEST (test_image_video_cycle) /* take a picture */ g_object_set (camera, "mode", 1, NULL); g_signal_emit_by_name (camera, "start-capture", NULL); - g_usleep (G_USEC_PER_SEC * 3); + g_timeout_add_seconds (3, (GSourceFunc) g_main_loop_quit, main_loop); + g_main_loop_run (main_loop); /* now go to video */ g_object_set (camera, "mode", 2, NULL); g_signal_emit_by_name (camera, "start-capture", NULL); - g_usleep (G_USEC_PER_SEC * 5); + g_timeout_add_seconds (VIDEO_DURATION, (GSourceFunc) g_main_loop_quit, + main_loop); + g_main_loop_run (main_loop); g_signal_emit_by_name (camera, "stop-capture", NULL); /* wait for capture to finish */ From aa671439e1709b0aaec2a435c292aa3e2708ec91 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Thu, 30 Dec 2010 00:26:07 -0300 Subject: [PATCH 314/448] camerabin2: Add methods for preview image message posting Adds a helper struct and functions for implementing a preview message in camerabin2. --- .../gst/basecamerabinsrc/gstbasecamerasrc.h | 2 + gst/camerabin2/Makefile.am | 2 +- gst/camerabin2/camerabingeneral.c | 186 +++++++++++++++++- gst/camerabin2/camerabingeneral.h | 16 ++ 4 files changed, 204 insertions(+), 2 deletions(-) diff --git a/gst-libs/gst/basecamerabinsrc/gstbasecamerasrc.h b/gst-libs/gst/basecamerabinsrc/gstbasecamerasrc.h index 8ab0008048..70535bccff 100644 --- a/gst-libs/gst/basecamerabinsrc/gstbasecamerasrc.h +++ b/gst-libs/gst/basecamerabinsrc/gstbasecamerasrc.h @@ -52,6 +52,8 @@ typedef struct _GstBaseCameraSrcClass GstBaseCameraSrcClass; #define GST_BASE_CAMERA_SRC_IMAGE_PAD_NAME "imgsrc" #define GST_BASE_CAMERA_SRC_VIDEO_PAD_NAME "vidsrc" +#define GST_BASE_CAMERA_SRC_PREVIEW_MESSAGE_NAME "preview-image" + /** * GstBaseCameraSrc: */ diff --git a/gst/camerabin2/Makefile.am b/gst/camerabin2/Makefile.am index a4299be10f..cf32a7082f 100644 --- a/gst/camerabin2/Makefile.am +++ b/gst/camerabin2/Makefile.am @@ -17,7 +17,7 @@ libgstcamerabin2_la_CFLAGS = \ libgstcamerabin2_la_LIBADD = \ $(top_builddir)/gst-libs/gst/interfaces/libgstphotography-$(GST_MAJORMINOR).la \ $(top_builddir)/gst-libs/gst/basecamerabinsrc/libgstbasecamerabinsrc-$(GST_MAJORMINOR).la \ - $(GST_PLUGINS_BASE_LIBS) -lgstinterfaces-$(GST_MAJORMINOR) -lgsttag-$(GST_MAJORMINOR) \ + $(GST_PLUGINS_BASE_LIBS) -lgstinterfaces-$(GST_MAJORMINOR) -lgsttag-$(GST_MAJORMINOR) -lgstapp-$(GST_MAJORMINOR) \ $(GST_BASE_LIBS) $(GST_LIBS) libgstcamerabin2_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) diff --git a/gst/camerabin2/camerabingeneral.c b/gst/camerabin2/camerabingeneral.c index 0219a0fe3b..a354075b5e 100644 --- a/gst/camerabin2/camerabingeneral.c +++ b/gst/camerabin2/camerabingeneral.c @@ -28,8 +28,11 @@ */ #include -#include "camerabingeneral.h" #include +#include +#include +#include +#include "camerabingeneral.h" /** * gst_camerabin_add_element: @@ -272,3 +275,184 @@ gst_camerabin_drop_eos_probe (GstPad * pad, GstEvent * event, gpointer u_data) } return ret; } + +static GstFlowReturn +gst_camerabin_preview_pipeline_new_preroll (GstAppSink * appsink, + gpointer user_data) +{ + GstBuffer *buffer; + + buffer = gst_app_sink_pull_preroll (appsink); + gst_buffer_unref (buffer); + + return GST_FLOW_OK; +} + +static GstFlowReturn +gst_camerabin_preview_pipeline_new_buffer (GstAppSink * appsink, + gpointer user_data) +{ + GstBuffer *buffer; + GstStructure *s; + GstMessage *msg; + GstCameraBinPreviewPipelineData *data; + + data = user_data; + + buffer = gst_app_sink_pull_buffer (appsink); + s = gst_structure_new (GST_BASE_CAMERA_SRC_PREVIEW_MESSAGE_NAME, + "buffer", GST_TYPE_BUFFER, buffer, NULL); + gst_buffer_unref (buffer); + msg = gst_message_new_element (GST_OBJECT (data->element), s); + + GST_DEBUG_OBJECT (data->element, "sending message with preview image"); + if (gst_element_post_message (data->element, msg) == FALSE) { + GST_WARNING_OBJECT (data->element, + "This element has no bus, therefore no message sent!"); + } + + return GST_FLOW_OK; +} + +/** + * gst_camerabin_create_preview_pipeline: + * @element: Owner of this pipeline + * + * Creates a new previewing pipeline that can receive buffers + * to be posted as camerabin preview messages for @element + * + * Returns: The newly created #GstCameraBinPreviewPipelineData + */ +GstCameraBinPreviewPipelineData * +gst_camerabin_create_preview_pipeline (GstElement * element) +{ + GstCameraBinPreviewPipelineData *data; + GstElement *csp; + GstElement *csp2; + GstElement *vscale; + gboolean added = FALSE; + GstAppSinkCallbacks callbacks = { 0, }; + + data = g_new (GstCameraBinPreviewPipelineData, 1); + + data->pipeline = gst_pipeline_new ("preview-pipeline"); + data->appsrc = gst_element_factory_make ("appsrc", "preview-appsrc"); + data->capsfilter = gst_element_factory_make ("capsfilter", + "preview-capsfilter"); + data->appsink = gst_element_factory_make ("appsink", "preview-appsink"); + csp = gst_element_factory_make ("ffmpegcolorspace", "preview-csp0"); + csp2 = gst_element_factory_make ("ffmpegcolorspace", "preview-csp1"); + vscale = gst_element_factory_make ("videoscale", "preview-vscale"); + + if (!data->appsrc || !data->capsfilter || !data->appsink || !csp || + !csp2 || !vscale) { + goto error; + } + + gst_bin_add_many (GST_BIN (data->pipeline), data->appsrc, data->capsfilter, + data->appsink, csp, csp2, vscale, NULL); + added = TRUE; + + if (!gst_element_link_many (data->appsrc, csp, vscale, csp2, data->capsfilter, + data->appsink, NULL)) + goto error; + + callbacks.new_preroll = gst_camerabin_preview_pipeline_new_preroll; + callbacks.new_buffer = gst_camerabin_preview_pipeline_new_buffer; + gst_app_sink_set_callbacks ((GstAppSink *) data->appsink, &callbacks, data, + NULL); + + data->element = element; + + return data; +error: + GST_WARNING ("Failed to create camerabin's preview pipeline"); + if (!added) { + if (csp) + gst_object_unref (csp); + if (csp2) + gst_object_unref (csp2); + if (vscale) + gst_object_unref (vscale); + if (data->appsrc) + gst_object_unref (data->appsrc); + if (data->capsfilter) + gst_object_unref (data->capsfilter); + if (data->appsink) + gst_object_unref (data->appsink); + } + gst_camerabin_destroy_preview_pipeline (data); + return NULL; +} + +/** + * gst_camerabin_destroy_preview_pipeline: + * @preview: the #GstCameraBinPreviewPipelineData + * + * Frees a #GstCameraBinPreviewPipelineData + */ +void +gst_camerabin_destroy_preview_pipeline (GstCameraBinPreviewPipelineData * + preview) +{ + if (preview->pipeline) { + gst_element_set_state (preview->pipeline, GST_STATE_NULL); + gst_object_unref (preview->pipeline); + } + g_free (preview); +} + +/** + * gst_camerabin_preview_pipeline_post: + * @preview: the #GstCameraBinPreviewPipelineData + * @buffer: the buffer to be posted as a preview + * + * Converts the @buffer to the desired format and posts the preview + * message to the bus. + * + * Returns: %TRUE on success + */ +gboolean +gst_camerabin_preview_pipeline_post (GstCameraBinPreviewPipelineData * preview, + GstBuffer * buffer) +{ + g_return_val_if_fail (preview != NULL, FALSE); + g_return_val_if_fail (preview->pipeline != NULL, FALSE); + g_return_val_if_fail (buffer, FALSE); + + gst_app_src_push_buffer ((GstAppSrc *) preview->appsrc, + gst_buffer_ref (buffer)); + + return TRUE; +} + +/** + * gst_camerabin_preview_set_caps: + * @preview: the #GstCameraBinPreviewPipelineData + * @caps: the #GstCaps to be set + * + * The caps that preview buffers should have when posted + * on the bus + */ +void +gst_camerabin_preview_set_caps (GstCameraBinPreviewPipelineData * preview, + GstCaps * caps) +{ + GstState state, pending; + GstStateChangeReturn ret; + + g_return_if_fail (preview != NULL); + + ret = gst_element_get_state (preview->pipeline, &state, &pending, 0); + if (ret == GST_STATE_CHANGE_FAILURE) { + /* make it try again */ + state = GST_STATE_PLAYING; + pending = GST_STATE_VOID_PENDING; + } + + gst_element_set_state (preview->pipeline, GST_STATE_NULL); + g_object_set (preview->capsfilter, "caps", caps, NULL); + if (pending != GST_STATE_VOID_PENDING) + state = pending; + gst_element_set_state (preview->pipeline, state); +} diff --git a/gst/camerabin2/camerabingeneral.h b/gst/camerabin2/camerabingeneral.h index 7f453aca2f..096038b9a7 100644 --- a/gst/camerabin2/camerabingeneral.h +++ b/gst/camerabin2/camerabingeneral.h @@ -23,6 +23,22 @@ #include +typedef struct +{ + GstElement *pipeline; + + GstElement *appsrc; + GstElement *capsfilter; + GstElement *appsink; + + GstElement *element; +} GstCameraBinPreviewPipelineData; + +GstCameraBinPreviewPipelineData *gst_camerabin_create_preview_pipeline (GstElement * element); +void gst_camerabin_destroy_preview_pipeline (GstCameraBinPreviewPipelineData * preview); +gboolean gst_camerabin_preview_pipeline_post (GstCameraBinPreviewPipelineData * preview, GstBuffer * buffer); +void gst_camerabin_preview_set_caps (GstCameraBinPreviewPipelineData * preview, GstCaps * caps); + gboolean gst_camerabin_try_add_element (GstBin * bin, const gchar * srcpad, GstElement * new_elem, const gchar * dstpad); gboolean gst_camerabin_add_element (GstBin * bin, GstElement * new_elem); gboolean gst_camerabin_add_element_full (GstBin * bin, const gchar * srcpad, GstElement * new_elem, const gchar * dstpad); From 9863feb328c23c022dfe8c770c1cbd6e0c1c3815 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Thu, 30 Dec 2010 00:27:03 -0300 Subject: [PATCH 315/448] camerabin2: Implement previewing Implement previewing functionality using 2 properties. A boolean (post-previews) that indicates if previews should be posted, and a GstCaps (preview-caps) to provide the desired preview caps. wrappercamerabinsrc implements previewing by supplying the captured image to a pipeline to adapt it to the required caps before posting. --- gst/camerabin2/gstcamerabin2.c | 44 ++++++++++++- gst/camerabin2/gstcamerabin2.h | 2 + gst/camerabin2/gstwrappercamerabinsrc.c | 82 +++++++++++++++++++++++++ gst/camerabin2/gstwrappercamerabinsrc.h | 6 ++ 4 files changed, 133 insertions(+), 1 deletion(-) diff --git a/gst/camerabin2/gstcamerabin2.c b/gst/camerabin2/gstcamerabin2.c index 73a7fdf1c8..b17067b2d7 100644 --- a/gst/camerabin2/gstcamerabin2.c +++ b/gst/camerabin2/gstcamerabin2.c @@ -66,7 +66,9 @@ enum PROP_IMAGE_CAPTURE_SUPPORTED_CAPS, PROP_VIDEO_CAPTURE_SUPPORTED_CAPS, PROP_IMAGE_CAPTURE_CAPS, - PROP_VIDEO_CAPTURE_CAPS + PROP_VIDEO_CAPTURE_CAPS, + PROP_POST_PREVIEWS, + PROP_PREVIEW_CAPS }; enum @@ -82,6 +84,7 @@ static guint camerabin_signals[LAST_SIGNAL]; #define DEFAULT_MODE MODE_IMAGE #define DEFAULT_VID_LOCATION "vid_%d" #define DEFAULT_IMG_LOCATION "img_%d" +#define DEFAULT_POST_PREVIEWS TRUE /******************************** * Standard GObject boilerplate * @@ -328,6 +331,15 @@ gst_camera_bin_class_init (GstCameraBinClass * klass) "Caps for video capture", GST_TYPE_CAPS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (object_class, PROP_POST_PREVIEWS, + g_param_spec_boolean ("post-previews", "Post Previews", + "If capture preview images should be posted to the bus", + DEFAULT_POST_PREVIEWS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (object_class, PROP_PREVIEW_CAPS, + g_param_spec_boxed ("preview-caps", "Preview caps", + "The caps of the preview image to be posted", + GST_TYPE_CAPS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); /** * GstCameraBin::capture-start: @@ -357,6 +369,7 @@ gst_camera_bin_class_init (GstCameraBinClass * klass) static void gst_camera_bin_init (GstCameraBin * camera) { + camera->post_previews = DEFAULT_POST_PREVIEWS; camera->mode = DEFAULT_MODE; camera->video_location = g_strdup (DEFAULT_VID_LOCATION); camera->image_location = g_strdup (DEFAULT_IMG_LOCATION); @@ -465,6 +478,12 @@ gst_camera_bin_create_elements (GstCameraBin * camera) g_assert (camera->src != NULL); g_object_set (camera->src, "mode", camera->mode, NULL); + if (camera->src + && g_object_class_find_property (G_OBJECT_GET_CLASS (camera->src), + "preview-caps")) { + g_object_set (camera->src, "post-previews", camera->post_previews, + "preview-caps", camera->preview_caps, NULL); + } if (new_src) { gst_bin_add (GST_BIN_CAST (camera), gst_object_ref (camera->src)); camera->src_capture_notify_id = g_signal_connect (G_OBJECT (camera->src), @@ -603,6 +622,22 @@ gst_camera_bin_set_property (GObject * object, guint prop_id, } } break; + case PROP_POST_PREVIEWS: + camera->post_previews = g_value_get_boolean (value); + if (camera->src + && g_object_class_find_property (G_OBJECT_GET_CLASS (camera->src), + "post-previews")) + g_object_set (camera->src, "post-previews", camera->post_previews, + NULL); + break; + case PROP_PREVIEW_CAPS: + gst_caps_replace (&camera->preview_caps, + (GstCaps *) gst_value_get_caps (value)); + if (camera->src + && g_object_class_find_property (G_OBJECT_GET_CLASS (camera->src), + "preview-caps")) + g_object_set (camera->src, "preview-caps", camera->preview_caps, NULL); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -678,6 +713,13 @@ gst_camera_bin_get_property (GObject * object, guint prop_id, gst_caps_unref (caps); } break; + case PROP_POST_PREVIEWS: + g_value_set_boolean (value, camera->post_previews); + break; + case PROP_PREVIEW_CAPS: + if (camera->preview_caps) + gst_value_set_caps (value, camera->preview_caps); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; diff --git a/gst/camerabin2/gstcamerabin2.h b/gst/camerabin2/gstcamerabin2.h index 5664363784..29be9b294d 100644 --- a/gst/camerabin2/gstcamerabin2.h +++ b/gst/camerabin2/gstcamerabin2.h @@ -60,6 +60,8 @@ struct _GstCameraBin gint mode; gchar *video_location; gchar *image_location; + gboolean post_previews; + GstCaps *preview_caps; gboolean elements_created; }; diff --git a/gst/camerabin2/gstwrappercamerabinsrc.c b/gst/camerabin2/gstwrappercamerabinsrc.c index 707f70ab57..9fec1e43f7 100644 --- a/gst/camerabin2/gstwrappercamerabinsrc.c +++ b/gst/camerabin2/gstwrappercamerabinsrc.c @@ -38,9 +38,12 @@ enum { PROP_0, PROP_VIDEO_SRC, + PROP_POST_PREVIEWS, + PROP_PREVIEW_CAPS }; #define CAMERABIN_DEFAULT_VF_CAPS "video/x-raw-yuv,format=(fourcc)I420" +#define DEFAULT_POST_PREVIEWS TRUE /* Using "bilinear" as default zoom method */ #define CAMERABIN_DEFAULT_ZOOM_METHOD 1 @@ -64,6 +67,11 @@ gst_wrapper_camera_bin_src_dispose (GObject * object) self->app_vid_src = NULL; } + if (self->preview_pipeline) { + gst_camerabin_destroy_preview_pipeline (self->preview_pipeline); + self->preview_pipeline = NULL; + } + G_OBJECT_CLASS (parent_class)->dispose (object); } @@ -93,6 +101,16 @@ gst_wrapper_camera_bin_src_set_property (GObject * object, gst_object_ref (self->app_vid_src); } break; + case PROP_POST_PREVIEWS: + self->post_previews = g_value_get_boolean (value); + break; + case PROP_PREVIEW_CAPS: + gst_caps_replace (&self->preview_caps, + (GstCaps *) gst_value_get_caps (value)); + if (self->preview_pipeline) + gst_camerabin_preview_set_caps (self->preview_pipeline, + (GstCaps *) gst_value_get_caps (value)); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec); break; @@ -112,6 +130,13 @@ gst_wrapper_camera_bin_src_get_property (GObject * object, else g_value_set_object (value, self->app_vid_src); break; + case PROP_POST_PREVIEWS: + g_value_set_boolean (value, self->post_previews); + break; + case PROP_PREVIEW_CAPS: + if (self->preview_caps) + gst_value_set_caps (value, self->preview_caps); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec); break; @@ -151,6 +176,13 @@ gst_wrapper_camera_bin_src_imgsrc_probe (GstPad * pad, GstBuffer * buffer, if (self->image_capture_count > 0) { ret = TRUE; self->image_capture_count--; + + /* post preview */ + /* TODO This can likely be optimized if the viewfinder caps is the same as + * the preview caps, avoiding another scaling of the same buffer. */ + if (self->post_previews) + gst_camerabin_preview_pipeline_post (self->preview_pipeline, buffer); + if (self->image_capture_count == 0) { gst_base_camera_src_finish_capture (camerasrc); } @@ -190,6 +222,11 @@ gst_wrapper_camera_bin_src_vidsrc_probe (GstPad * pad, GstBuffer * buffer, gst_pad_push_event (pad, gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME, GST_BUFFER_TIMESTAMP (buffer), -1, 0)); self->video_rec_status = GST_VIDEO_RECORDING_STATUS_RUNNING; + + /* post preview */ + if (self->post_previews) + gst_camerabin_preview_pipeline_post (self->preview_pipeline, buffer); + ret = TRUE; } else if (self->video_rec_status == GST_VIDEO_RECORDING_STATUS_FINISHING) { /* send eos */ @@ -357,6 +394,12 @@ gst_wrapper_camera_bin_src_construct_pipeline (GstBaseCameraSrc * bcamsrc) gst_pad_set_active (self->imgsrc, TRUE); /* XXX ??? */ gst_pad_set_active (self->vidsrc, TRUE); /* XXX ??? */ + /* create the preview pipeline */ + self->preview_pipeline = + gst_camerabin_create_preview_pipeline (GST_ELEMENT_CAST (self)); + if (self->preview_caps) + gst_camerabin_preview_set_caps (self->preview_pipeline, self->preview_caps); + ret = TRUE; self->elements_created = TRUE; done: @@ -890,6 +933,30 @@ gst_wrapper_camera_bin_src_stop_capture (GstBaseCameraSrc * camerasrc) } } +static GstStateChangeReturn +gst_wrapper_camera_bin_src_change_state (GstElement * element, + GstStateChange trans) +{ + GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; + GstWrapperCameraBinSrc *self = GST_WRAPPER_CAMERA_BIN_SRC (element); + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, trans); + + switch (trans) { + case GST_STATE_CHANGE_READY_TO_NULL: + gst_element_set_state (self->preview_pipeline->pipeline, GST_STATE_NULL); + break; + case GST_STATE_CHANGE_NULL_TO_READY: + gst_element_set_state (self->preview_pipeline->pipeline, + GST_STATE_PLAYING); + break; + default: + break; + } + + return ret; +} + static void gst_wrapper_camera_bin_src_base_init (gpointer g_class) { @@ -907,9 +974,11 @@ static void gst_wrapper_camera_bin_src_class_init (GstWrapperCameraBinSrcClass * klass) { GObjectClass *gobject_class; + GstElementClass *gstelement_class; GstBaseCameraSrcClass *gstbasecamerasrc_class; gobject_class = G_OBJECT_CLASS (klass); + gstelement_class = GST_ELEMENT_CLASS (klass); gstbasecamerasrc_class = GST_BASE_CAMERA_SRC_CLASS (klass); gobject_class->dispose = gst_wrapper_camera_bin_src_dispose; @@ -924,6 +993,18 @@ gst_wrapper_camera_bin_src_class_init (GstWrapperCameraBinSrcClass * klass) "The video source element to be used", GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_POST_PREVIEWS, + g_param_spec_boolean ("post-previews", "Post Previews", + "If capture preview images should be posted to the bus", + DEFAULT_POST_PREVIEWS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_PREVIEW_CAPS, + g_param_spec_boxed ("preview-caps", "Preview caps", + "The caps of the preview image to be posted", + GST_TYPE_CAPS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + gstelement_class->change_state = gst_wrapper_camera_bin_src_change_state; + gstbasecamerasrc_class->construct_pipeline = gst_wrapper_camera_bin_src_construct_pipeline; gstbasecamerasrc_class->set_zoom = gst_wrapper_camera_bin_src_set_zoom; @@ -967,6 +1048,7 @@ gst_wrapper_camera_bin_src_init (GstWrapperCameraBinSrc * self, self->video_renegotiate = FALSE; self->image_renegotiate = FALSE; self->mode = GST_BASE_CAMERA_SRC_CAST (self)->mode; + self->post_previews = DEFAULT_POST_PREVIEWS; } gboolean diff --git a/gst/camerabin2/gstwrappercamerabinsrc.h b/gst/camerabin2/gstwrappercamerabinsrc.h index 2813e8b4b2..c74be279c9 100644 --- a/gst/camerabin2/gstwrappercamerabinsrc.h +++ b/gst/camerabin2/gstwrappercamerabinsrc.h @@ -25,6 +25,7 @@ #include #include +#include "camerabingeneral.h" G_BEGIN_DECLS #define GST_TYPE_WRAPPER_CAMERA_BIN_SRC \ @@ -107,6 +108,11 @@ struct _GstWrapperCameraBinSrc GstCaps *image_capture_caps; gboolean image_renegotiate; gboolean video_renegotiate; + + /* Preview convert pipeline */ + GstCameraBinPreviewPipelineData *preview_pipeline; + gboolean post_previews; + GstCaps *preview_caps; }; From 3a495eaafc9fe2f47c9f2d33bc8a65ad79fe6735 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Mon, 10 Jan 2011 15:19:04 -0300 Subject: [PATCH 316/448] wrappercamerabinsrc: Handle state change failures When its internal element fails to change state, don't act as if succeeded. --- gst/camerabin2/gstwrappercamerabinsrc.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/gst/camerabin2/gstwrappercamerabinsrc.c b/gst/camerabin2/gstwrappercamerabinsrc.c index 9fec1e43f7..2f3d793340 100644 --- a/gst/camerabin2/gstwrappercamerabinsrc.c +++ b/gst/camerabin2/gstwrappercamerabinsrc.c @@ -942,6 +942,9 @@ gst_wrapper_camera_bin_src_change_state (GstElement * element, ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, trans); + if (ret == GST_STATE_CHANGE_FAILURE) + goto end; + switch (trans) { case GST_STATE_CHANGE_READY_TO_NULL: gst_element_set_state (self->preview_pipeline->pipeline, GST_STATE_NULL); @@ -954,6 +957,7 @@ gst_wrapper_camera_bin_src_change_state (GstElement * element, break; } +end: return ret; } From 31dbc2eeba1f0472f549fcb607710245b6b74891 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Mon, 10 Jan 2011 15:19:52 -0300 Subject: [PATCH 317/448] wrappercamerabinsrc: Set output-selector pad-negotiation-mode to none Use output-selector none negotiation mode as it was the default before the last changes. This likely needs to be fixed to use 'active' on camerabin2 --- gst/camerabin2/gstwrappercamerabinsrc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/gst/camerabin2/gstwrappercamerabinsrc.c b/gst/camerabin2/gstwrappercamerabinsrc.c index 2f3d793340..9437b9ac1f 100644 --- a/gst/camerabin2/gstwrappercamerabinsrc.c +++ b/gst/camerabin2/gstwrappercamerabinsrc.c @@ -351,6 +351,7 @@ gst_wrapper_camera_bin_src_construct_pipeline (GstBaseCameraSrc * bcamsrc) self->output_selector = gst_element_factory_make ("output-selector", "outsel"); + g_object_set (self->output_selector, "pad-negotiation-mode", 0, NULL); gst_bin_add (GST_BIN (self), self->output_selector); { GstPad *pad = gst_element_get_static_pad (self->output_selector, "sink"); From f1d02cf0c0539b4c2b46fd63233055b28dd2a4ab Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Mon, 27 Dec 2010 11:29:42 -0300 Subject: [PATCH 318/448] camerabin2: Move to encodebin --- gst/camerabin2/Makefile.am | 2 +- gst/camerabin2/gstcamerabin2.c | 62 ++++++++++++++++++++++++++-------- gst/camerabin2/gstcamerabin2.h | 4 ++- 3 files changed, 52 insertions(+), 16 deletions(-) diff --git a/gst/camerabin2/Makefile.am b/gst/camerabin2/Makefile.am index cf32a7082f..cb905ff14a 100644 --- a/gst/camerabin2/Makefile.am +++ b/gst/camerabin2/Makefile.am @@ -17,7 +17,7 @@ libgstcamerabin2_la_CFLAGS = \ libgstcamerabin2_la_LIBADD = \ $(top_builddir)/gst-libs/gst/interfaces/libgstphotography-$(GST_MAJORMINOR).la \ $(top_builddir)/gst-libs/gst/basecamerabinsrc/libgstbasecamerabinsrc-$(GST_MAJORMINOR).la \ - $(GST_PLUGINS_BASE_LIBS) -lgstinterfaces-$(GST_MAJORMINOR) -lgsttag-$(GST_MAJORMINOR) -lgstapp-$(GST_MAJORMINOR) \ + $(GST_PLUGINS_BASE_LIBS) -lgstinterfaces-$(GST_MAJORMINOR) -lgsttag-$(GST_MAJORMINOR) -lgstapp-$(GST_MAJORMINOR) -lgstpbutils-$(GST_MAJORMINOR) \ $(GST_BASE_LIBS) $(GST_LIBS) libgstcamerabin2_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) diff --git a/gst/camerabin2/gstcamerabin2.c b/gst/camerabin2/gstcamerabin2.c index b17067b2d7..a9810dadfd 100644 --- a/gst/camerabin2/gstcamerabin2.c +++ b/gst/camerabin2/gstcamerabin2.c @@ -28,7 +28,7 @@ /* * Detail Topics: * - * videorecordingbin state management (for now on videobin) + * videorecordingbin state management (for now on called 'videobin') * - The problem: keeping videobin state in sync with camerabin will make it * go to playing when it might not be used, causing its internal * filesink to open a file that might be left blank. @@ -50,6 +50,7 @@ #endif #include +#include #include "gstcamerabin2.h" GST_DEBUG_CATEGORY_STATIC (gst_camera_bin_debug); @@ -188,15 +189,17 @@ gst_camera_bin_src_notify_readyforcapture (GObject * obj, GParamSpec * pspec, /* a video recording is about to start, we reset the videobin to clear eos/flushing state * also need to clean the queue ! capsfilter before it */ - gst_element_set_state (camera->videobin, GST_STATE_NULL); + gst_element_set_state (camera->encodebin, GST_STATE_NULL); + gst_element_set_state (camera->videosink, GST_STATE_NULL); gst_element_set_state (camera->videobin_queue, GST_STATE_NULL); gst_element_set_state (camera->videobin_capsfilter, GST_STATE_NULL); location = g_strdup_printf (camera->video_location, camera->video_index++); GST_DEBUG_OBJECT (camera, "Switching videobin location to %s", location); - g_object_set (camera->videobin, "location", location, NULL); + g_object_set (camera->videosink, "location", location, NULL); g_free (location); - gst_element_set_state (camera->videobin, GST_STATE_PLAYING); + gst_element_set_state (camera->encodebin, GST_STATE_PLAYING); + gst_element_set_state (camera->videosink, GST_STATE_PLAYING); gst_element_set_state (camera->videobin_capsfilter, GST_STATE_PLAYING); gst_element_set_state (camera->videobin_queue, GST_STATE_PLAYING); } @@ -226,9 +229,10 @@ gst_camera_bin_dispose (GObject * object) if (camerabin->viewfinderbin_capsfilter) gst_object_unref (camerabin->viewfinderbin_capsfilter); - - if (camerabin->videobin) - gst_object_unref (camerabin->videobin); + if (camerabin->videosink) + gst_object_unref (camerabin->videosink); + if (camerabin->encodebin) + gst_object_unref (camerabin->encodebin); if (camerabin->videobin_queue) gst_object_unref (camerabin->videobin_queue); if (camerabin->videobin_capsfilter) @@ -411,9 +415,31 @@ gst_camera_bin_create_elements (GstCameraBin * camera) if (!camera->elements_created) { - camera->videobin = - gst_element_factory_make ("videorecordingbin", "videobin"); + camera->encodebin = gst_element_factory_make ("encodebin", NULL); + camera->videosink = + gst_element_factory_make ("filesink", "videobin-filesink"); camera->imagebin = gst_element_factory_make ("imagecapturebin", "imagebin"); + g_object_set (camera->videosink, "async", FALSE, NULL); + + { + GstEncodingContainerProfile *prof; + GstCaps *caps; + + caps = gst_caps_new_simple ("application/ogg", NULL); + prof = gst_encoding_container_profile_new ("ogg", "theora+ogg", caps, + NULL); + gst_caps_unref (caps); + + caps = gst_caps_new_simple ("video/x-theora", NULL); + if (!gst_encoding_container_profile_add_profile (prof, + (GstEncodingProfile *) gst_encoding_video_profile_new (caps, + NULL, NULL, 1))) { + GST_WARNING_OBJECT (camera, "Failed to create encoding profiles"); + } + gst_caps_unref (caps); + g_object_set (camera->encodebin, "profile", prof, NULL); + gst_encoding_profile_unref (prof); + } camera->videobin_queue = gst_element_factory_make ("queue", "videobin-queue"); @@ -423,14 +449,19 @@ gst_camera_bin_create_elements (GstCameraBin * camera) gst_element_factory_make ("queue", "viewfinderbin-queue"); gst_bin_add_many (GST_BIN_CAST (camera), - gst_object_ref (camera->videobin), gst_object_ref (camera->imagebin), + gst_object_ref (camera->encodebin), + gst_object_ref (camera->videosink), + gst_object_ref (camera->imagebin), gst_object_ref (camera->videobin_queue), gst_object_ref (camera->imagebin_queue), gst_object_ref (camera->viewfinderbin_queue), NULL); /* Linking can be optimized TODO */ gst_element_link_many (camera->videobin_queue, camera->videobin_capsfilter, - camera->videobin, NULL); + NULL); + gst_element_link (camera->encodebin, camera->videosink); + gst_element_link (camera->videobin_capsfilter, camera->encodebin); + gst_element_link_many (camera->imagebin_queue, camera->imagebin_capsfilter, camera->imagebin, NULL); gst_element_link_many (camera->viewfinderbin_queue, @@ -444,9 +475,9 @@ gst_camera_bin_create_elements (GstCameraBin * camera) * the source's ready-for-capture goes to FALSE it means it is * starting recording, so we should prepare the video bin. */ - gst_element_set_locked_state (camera->videobin, TRUE); + gst_element_set_locked_state (camera->videosink, TRUE); - g_object_set (camera->videobin, "location", camera->video_location, NULL); + g_object_set (camera->videosink, "location", camera->video_location, NULL); g_object_set (camera->imagebin, "location", camera->image_location, NULL); } @@ -520,8 +551,11 @@ gst_camera_bin_change_state (GstElement * element, GstStateChange trans) ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, trans); switch (trans) { + case GST_STATE_CHANGE_PAUSED_TO_READY: + gst_element_set_state (camera->videosink, GST_STATE_READY); + break; case GST_STATE_CHANGE_READY_TO_NULL: - gst_element_set_state (camera->videobin, GST_STATE_NULL); + gst_element_set_state (camera->videosink, GST_STATE_NULL); break; default: break; diff --git a/gst/camerabin2/gstcamerabin2.h b/gst/camerabin2/gstcamerabin2.h index 29be9b294d..8802a55341 100644 --- a/gst/camerabin2/gstcamerabin2.h +++ b/gst/camerabin2/gstcamerabin2.h @@ -41,7 +41,9 @@ struct _GstCameraBin GstElement *user_src; gulong src_capture_notify_id; - GstElement *videobin; + //GstElement *videobin; + GstElement *encodebin; + GstElement *videosink; GstElement *videobin_queue; GstElement *videobin_capsfilter; From e5f267f682d28d18336ecdf9d0f68f945a8ee200 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Tue, 11 Jan 2011 08:44:41 -0300 Subject: [PATCH 319/448] camerabin2: Removing videorecordingbin Removing videorecordingbin as we now use encodebin for it --- gst/camerabin2/Makefile.am | 2 - gst/camerabin2/gstplugin.c | 3 - gst/camerabin2/gstvideorecordingbin.c | 360 ----------------------- gst/camerabin2/gstvideorecordingbin.h | 63 ---- tests/check/Makefile.am | 1 - tests/check/elements/videorecordingbin.c | 219 -------------- 6 files changed, 648 deletions(-) delete mode 100644 gst/camerabin2/gstvideorecordingbin.c delete mode 100644 gst/camerabin2/gstvideorecordingbin.h delete mode 100644 tests/check/elements/videorecordingbin.c diff --git a/gst/camerabin2/Makefile.am b/gst/camerabin2/Makefile.am index cb905ff14a..24f497ed57 100644 --- a/gst/camerabin2/Makefile.am +++ b/gst/camerabin2/Makefile.am @@ -2,7 +2,6 @@ plugin_LTLIBRARIES = libgstcamerabin2.la libgstcamerabin2_la_SOURCES = gstviewfinderbin.c \ gstimagecapturebin.c \ - gstvideorecordingbin.c \ camerabingeneral.c \ gstwrappercamerabinsrc.c \ gstcamerabin2.c \ @@ -25,7 +24,6 @@ libgstcamerabin2_la_LIBTOOLFLAGS = --tag=disable-static noinst_HEADERS = gstviewfinderbin.h \ gstimagecapturebin.h \ - gstvideorecordingbin.h \ camerabingeneral.h \ gstwrappercamerabinsrc.h \ gstcamerabin2.h diff --git a/gst/camerabin2/gstplugin.c b/gst/camerabin2/gstplugin.c index 16f20afedb..56fa78f800 100644 --- a/gst/camerabin2/gstplugin.c +++ b/gst/camerabin2/gstplugin.c @@ -25,7 +25,6 @@ #include "gstviewfinderbin.h" #include "gstimagecapturebin.h" -#include "gstvideorecordingbin.h" #include "gstwrappercamerabinsrc.h" #include "gstcamerabin2.h" @@ -36,8 +35,6 @@ plugin_init (GstPlugin * plugin) return FALSE; if (!gst_image_capture_bin_plugin_init (plugin)) return FALSE; - if (!gst_video_recording_bin_plugin_init (plugin)) - return FALSE; if (!gst_wrapper_camera_bin_src_plugin_init (plugin)) return FALSE; if (!gst_camera_bin_plugin_init (plugin)) diff --git a/gst/camerabin2/gstvideorecordingbin.c b/gst/camerabin2/gstvideorecordingbin.c deleted file mode 100644 index 30973d72ff..0000000000 --- a/gst/camerabin2/gstvideorecordingbin.c +++ /dev/null @@ -1,360 +0,0 @@ -/* GStreamer - * Copyright (C) 2010 Thiago Santos - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ -/** - * SECTION:element-gstvideorecordingbin - * - * The gstvideorecordingbin element does FIXME stuff. - * - * - * Example launch line - * |[ - * gst-launch -v videotestsrc num-buffers=3 ! videorecordingbin - * ]| - * FIXME Describe what the pipeline does. - * - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "gstvideorecordingbin.h" -#include "camerabingeneral.h" - -/* prototypes */ - - -enum -{ - PROP_0, - PROP_LOCATION, - PROP_VIDEO_ENCODER, - PROP_MUXER -}; - -#define DEFAULT_LOCATION "vidcap" -#define DEFAULT_COLORSPACE "ffmpegcolorspace" -#define DEFAULT_VIDEO_ENCODER "theoraenc" -#define DEFAULT_MUXER "oggmux" -#define DEFAULT_SINK "filesink" - -/* pad templates */ - -static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS ("video/x-raw-yuv; video/x-raw-rgb") - ); - -/* class initialization */ - -GST_BOILERPLATE (GstVideoRecordingBin, gst_video_recording_bin, GstBin, - GST_TYPE_BIN); - -/* GObject callbacks */ -static void gst_video_recording_bin_dispose (GObject * object); -static void gst_video_recording_bin_finalize (GObject * object); - -/* Element class functions */ -static GstStateChangeReturn -gst_video_recording_bin_change_state (GstElement * element, - GstStateChange trans); - -static void -gst_video_recording_bin_set_video_encoder (GstVideoRecordingBin * videobin, - GstElement * encoder) -{ - GST_DEBUG_OBJECT (GST_OBJECT (videobin), - "Setting video encoder %" GST_PTR_FORMAT, encoder); - - if (videobin->user_video_encoder) - g_object_unref (videobin->user_video_encoder); - - if (encoder) - g_object_ref (encoder); - - videobin->user_video_encoder = encoder; -} - -static void -gst_video_recording_bin_set_muxer (GstVideoRecordingBin * videobin, - GstElement * muxer) -{ - GST_DEBUG_OBJECT (GST_OBJECT (videobin), - "Setting video muxer %" GST_PTR_FORMAT, muxer); - - if (videobin->user_muxer) - g_object_unref (videobin->user_muxer); - - if (muxer) - g_object_ref (muxer); - - videobin->user_muxer = muxer; -} - -static void -gst_video_recording_bin_set_property (GObject * object, guint prop_id, - const GValue * value, GParamSpec * pspec) -{ - GstVideoRecordingBin *videobin = GST_VIDEO_RECORDING_BIN_CAST (object); - - switch (prop_id) { - case PROP_LOCATION: - if (videobin->location) - g_free (videobin->location); - - videobin->location = g_value_dup_string (value); - if (videobin->sink) { - g_object_set (videobin->sink, "location", videobin->location, NULL); - } - break; - case PROP_VIDEO_ENCODER: - gst_video_recording_bin_set_video_encoder (videobin, - g_value_get_object (value)); - break; - case PROP_MUXER: - gst_video_recording_bin_set_muxer (videobin, g_value_get_object (value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_video_recording_bin_get_property (GObject * object, guint prop_id, - GValue * value, GParamSpec * pspec) -{ - GstVideoRecordingBin *videobin = GST_VIDEO_RECORDING_BIN_CAST (object); - - switch (prop_id) { - case PROP_LOCATION: - g_value_set_string (value, videobin->location); - break; - case PROP_VIDEO_ENCODER: - g_value_set_object (value, videobin->video_encoder); - break; - case PROP_MUXER: - g_value_set_object (value, videobin->muxer); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); - break; - } -} - -static void -gst_video_recording_bin_base_init (gpointer g_class) -{ - GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); - - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&sink_template)); - - gst_element_class_set_details_simple (element_class, "Video Recording Bin", - "Sink/Video", "Video Recording Bin used in camerabin2", - "Thiago Santos "); -} - -static void -gst_video_recording_bin_class_init (GstVideoRecordingBinClass * klass) -{ - GObjectClass *gobject_class; - GstElementClass *element_class; - - gobject_class = G_OBJECT_CLASS (klass); - element_class = GST_ELEMENT_CLASS (klass); - - gobject_class->dispose = gst_video_recording_bin_dispose; - gobject_class->finalize = gst_video_recording_bin_finalize; - - gobject_class->set_property = gst_video_recording_bin_set_property; - gobject_class->get_property = gst_video_recording_bin_get_property; - - element_class->change_state = - GST_DEBUG_FUNCPTR (gst_video_recording_bin_change_state); - - g_object_class_install_property (gobject_class, PROP_LOCATION, - g_param_spec_string ("location", "Location", - "Location to save the captured files.", - DEFAULT_LOCATION, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, PROP_VIDEO_ENCODER, - g_param_spec_object ("video-encoder", "Video encoder", - "Video encoder GstElement (default is theoraenc).", - GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); - - g_object_class_install_property (gobject_class, PROP_MUXER, - g_param_spec_object ("video-muxer", "Video muxer", - "Video muxer GstElement (default is oggmux).", - GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); -} - -static void -gst_video_recording_bin_init (GstVideoRecordingBin * videobin, - GstVideoRecordingBinClass * videobin_class) -{ - GstPadTemplate *templ; - - templ = gst_static_pad_template_get (&sink_template); - videobin->ghostpad = - gst_ghost_pad_new_no_target_from_template ("sink", templ); - gst_object_unref (templ); - gst_element_add_pad (GST_ELEMENT_CAST (videobin), videobin->ghostpad); - - videobin->location = g_strdup (DEFAULT_LOCATION); - videobin->video_encoder = NULL; - videobin->user_video_encoder = NULL; - videobin->muxer = NULL; - videobin->user_muxer = NULL; -} - -static void -gst_video_recording_bin_dispose (GObject * object) -{ - GstVideoRecordingBin *videobin = GST_VIDEO_RECORDING_BIN_CAST (object); - - if (videobin->user_video_encoder) { - gst_object_unref (videobin->user_video_encoder); - videobin->user_video_encoder = NULL; - } - - if (videobin->user_muxer) { - gst_object_unref (videobin->user_muxer); - videobin->user_muxer = NULL; - } - - G_OBJECT_CLASS (parent_class)->dispose ((GObject *) videobin); -} - -static void -gst_video_recording_bin_finalize (GObject * object) -{ - GstVideoRecordingBin *videobin = GST_VIDEO_RECORDING_BIN_CAST (object); - - g_free (videobin->location); - videobin->location = NULL; - - G_OBJECT_CLASS (parent_class)->finalize ((GObject *) videobin); -} - - -static gboolean -gst_video_recording_bin_create_elements (GstVideoRecordingBin * videobin) -{ - GstElement *colorspace; - GstPad *pad = NULL; - - if (videobin->elements_created) - return TRUE; - - /* create elements */ - colorspace = - gst_camerabin_create_and_add_element (GST_BIN (videobin), - DEFAULT_COLORSPACE); - if (!colorspace) - goto error; - - if (videobin->user_video_encoder) { - videobin->video_encoder = videobin->user_video_encoder; - if (!gst_camerabin_add_element (GST_BIN (videobin), - videobin->video_encoder)) { - goto error; - } - } else { - videobin->video_encoder = - gst_camerabin_create_and_add_element (GST_BIN (videobin), - DEFAULT_VIDEO_ENCODER); - if (!videobin->video_encoder) - goto error; - } - - if (videobin->user_muxer) { - videobin->muxer = videobin->user_muxer; - if (!gst_camerabin_add_element (GST_BIN (videobin), videobin->muxer)) { - goto error; - } - } else { - videobin->muxer = - gst_camerabin_create_and_add_element (GST_BIN (videobin), - DEFAULT_MUXER); - if (!videobin->muxer) - goto error; - } - - videobin->sink = gst_camerabin_create_and_add_element (GST_BIN (videobin), - DEFAULT_SINK); - if (!videobin->sink) - goto error; - - g_object_set (videobin->sink, "location", videobin->location, "async", FALSE, - NULL); - - /* add ghostpad */ - pad = gst_element_get_static_pad (colorspace, "sink"); - if (!gst_ghost_pad_set_target (GST_GHOST_PAD (videobin->ghostpad), pad)) - goto error; - gst_object_unref (pad); - pad = NULL; - - videobin->elements_created = TRUE; - return TRUE; - -error: - GST_DEBUG_OBJECT (videobin, "Create elements failed"); - if (pad) - gst_object_unref (pad); - return FALSE; -} - -static GstStateChangeReturn -gst_video_recording_bin_change_state (GstElement * element, - GstStateChange trans) -{ - GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; - GstVideoRecordingBin *videobin = GST_VIDEO_RECORDING_BIN_CAST (element); - - switch (trans) { - case GST_STATE_CHANGE_NULL_TO_READY: - if (!gst_video_recording_bin_create_elements (videobin)) { - return GST_STATE_CHANGE_FAILURE; - } - break; - default: - break; - } - - ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, trans); - - switch (trans) { - case GST_STATE_CHANGE_READY_TO_NULL: - break; - default: - break; - } - - return ret; -} - -gboolean -gst_video_recording_bin_plugin_init (GstPlugin * plugin) -{ - return gst_element_register (plugin, "videorecordingbin", GST_RANK_NONE, - gst_video_recording_bin_get_type ()); -} diff --git a/gst/camerabin2/gstvideorecordingbin.h b/gst/camerabin2/gstvideorecordingbin.h deleted file mode 100644 index 167da29524..0000000000 --- a/gst/camerabin2/gstvideorecordingbin.h +++ /dev/null @@ -1,63 +0,0 @@ -/* GStreamer - * Copyright (C) 2010 Thiago Santos - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ -#ifndef _GST_VIDEO_RECORDING_BIN_H_ -#define _GST_VIDEO_RECORDING_BIN_H_ - -#include - -G_BEGIN_DECLS - -#define GST_TYPE_VIDEO_RECORDING_BIN (gst_video_recording_bin_get_type()) -#define GST_VIDEO_RECORDING_BIN(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_VIDEO_RECORDING_BIN,GstVideoRecordingBin)) -#define GST_VIDEO_RECORDING_BIN_CAST(obj) ((GstVideoRecordingBin *) obj) -#define GST_VIDEO_RECORDING_BIN_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_VIDEO_RECORDING_BIN,GstVideoRecordingBinClass)) -#define GST_IS_VIDEO_RECORDING_BIN(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_VIDEO_RECORDING_BIN)) -#define GST_IS_VIDEO_RECORDING_BIN_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_VIDEO_RECORDING_BIN)) - -typedef struct _GstVideoRecordingBin GstVideoRecordingBin; -typedef struct _GstVideoRecordingBinClass GstVideoRecordingBinClass; - -struct _GstVideoRecordingBin -{ - GstBin bin; - - GstPad *ghostpad; - GstElement *sink; - - /* props */ - gchar *location; - GstElement *video_encoder; - GstElement *user_video_encoder; - GstElement *muxer; - GstElement *user_muxer; - - gboolean elements_created; -}; - -struct _GstVideoRecordingBinClass -{ - GstBinClass bin_class; -}; - -GType gst_video_recording_bin_get_type (void); -gboolean gst_video_recording_bin_plugin_init (GstPlugin * plugin); - -G_END_DECLS - -#endif diff --git a/tests/check/Makefile.am b/tests/check/Makefile.am index 90c9a7ed52..6e0de76d7e 100644 --- a/tests/check/Makefile.am +++ b/tests/check/Makefile.am @@ -130,7 +130,6 @@ VALGRIND_TESTS_DISABLE = \ if BUILD_EXPERIMENTAL EXPERIMENTAL_CHECKS=elements/camerabin2 \ elements/imagecapturebin \ - elements/videorecordingbin \ elements/viewfinderbin endif diff --git a/tests/check/elements/videorecordingbin.c b/tests/check/elements/videorecordingbin.c deleted file mode 100644 index 96ed35119a..0000000000 --- a/tests/check/elements/videorecordingbin.c +++ /dev/null @@ -1,219 +0,0 @@ -/* GStreamer unit test for the videorecordingbin element - * Copyright (C) 2010 Thiago Santos - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include -#include - -#define N_BUFFERS 100 - -typedef struct -{ - GstElement *pipe; - GstElement *src; - GstElement *vrbin; -} GstVideoRecordingBinTestContext; - -static void -gstvideorecordingbin_init_test_context (GstVideoRecordingBinTestContext * ctx, - gint num_buffers) -{ - fail_unless (ctx != NULL); - - ctx->pipe = gst_pipeline_new ("pipeline"); - fail_unless (ctx->pipe != NULL); - ctx->src = gst_element_factory_make ("videotestsrc", "src"); - fail_unless (ctx->src != NULL, "Failed to create videotestsrc element"); - ctx->vrbin = gst_element_factory_make ("videorecordingbin", "icbin"); - fail_unless (ctx->vrbin != NULL, - "Failed to create videorecordingbin element"); - - if (num_buffers > 0) - g_object_set (ctx->src, "num-buffers", num_buffers, NULL); - - fail_unless (gst_bin_add (GST_BIN (ctx->pipe), ctx->src)); - fail_unless (gst_bin_add (GST_BIN (ctx->pipe), ctx->vrbin)); - fail_unless (gst_element_link (ctx->src, ctx->vrbin)); -} - -static void -gstvideorecordingbin_unset_test_context (GstVideoRecordingBinTestContext * ctx) -{ - gst_element_set_state (ctx->pipe, GST_STATE_NULL); - gst_object_unref (ctx->pipe); - memset (ctx, 0, sizeof (GstVideoRecordingBinTestContext)); -} - -static gchar * -make_test_file_name (gint num) -{ - return g_strdup_printf ("%s" G_DIR_SEPARATOR_S - "videorecordingbintest_%d.cap", g_get_tmp_dir (), num); -} - -GST_START_TEST (test_simple_recording) -{ - GstVideoRecordingBinTestContext ctx; - GstBus *bus; - GstMessage *msg; - gchar *test_file_name; - FILE *f; - - gstvideorecordingbin_init_test_context (&ctx, N_BUFFERS); - bus = gst_element_get_bus (ctx.pipe); - - test_file_name = make_test_file_name (0); - g_object_set (ctx.vrbin, "location", test_file_name, NULL); - - fail_if (gst_element_set_state (ctx.pipe, GST_STATE_PLAYING) == - GST_STATE_CHANGE_FAILURE); - - msg = gst_bus_timed_pop_filtered (bus, GST_SECOND * 10, - GST_MESSAGE_EOS | GST_MESSAGE_ERROR); - fail_unless (msg != NULL); - fail_unless (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_EOS); - - /* check there is a recorded file */ - fail_unless (g_file_test (test_file_name, G_FILE_TEST_EXISTS)); - fail_unless (g_file_test (test_file_name, G_FILE_TEST_IS_REGULAR)); - fail_if (g_file_test (test_file_name, G_FILE_TEST_IS_SYMLINK)); - - /* check the file isn't empty */ - f = fopen (test_file_name, "r"); - fseek (f, 0, SEEK_END); - fail_unless (ftell (f) > 0); - fclose (f); - - gstvideorecordingbin_unset_test_context (&ctx); - gst_object_unref (bus); - g_free (test_file_name); -} - -GST_END_TEST; - -GST_START_TEST (test_setting_video_encoder) -{ - GstVideoRecordingBinTestContext ctx; - GstBus *bus; - GstMessage *msg; - GstElement *encoder; - gchar *test_file_name; - FILE *f; - - gstvideorecordingbin_init_test_context (&ctx, N_BUFFERS); - bus = gst_element_get_bus (ctx.pipe); - - test_file_name = make_test_file_name (0); - g_object_set (ctx.vrbin, "location", test_file_name, NULL); - - encoder = gst_element_factory_make ("theoraenc", NULL); - g_object_set (ctx.vrbin, "video-encoder", encoder, NULL); - - fail_if (gst_element_set_state (ctx.pipe, GST_STATE_PLAYING) == - GST_STATE_CHANGE_FAILURE); - - msg = gst_bus_timed_pop_filtered (bus, GST_SECOND * 10, - GST_MESSAGE_EOS | GST_MESSAGE_ERROR); - fail_unless (msg != NULL); - fail_unless (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_EOS); - - /* check there is a recorded file */ - fail_unless (g_file_test (test_file_name, G_FILE_TEST_EXISTS)); - fail_unless (g_file_test (test_file_name, G_FILE_TEST_IS_REGULAR)); - fail_if (g_file_test (test_file_name, G_FILE_TEST_IS_SYMLINK)); - - /* check the file isn't empty */ - f = fopen (test_file_name, "r"); - fseek (f, 0, SEEK_END); - fail_unless (ftell (f) > 0); - fclose (f); - - gstvideorecordingbin_unset_test_context (&ctx); - gst_object_unref (bus); - g_free (test_file_name); -} - -GST_END_TEST; - -GST_START_TEST (test_setting_video_muxer) -{ - GstVideoRecordingBinTestContext ctx; - GstBus *bus; - GstMessage *msg; - GstElement *encoder; - GstElement *muxer; - gchar *test_file_name; - FILE *f; - - gstvideorecordingbin_init_test_context (&ctx, N_BUFFERS); - bus = gst_element_get_bus (ctx.pipe); - - test_file_name = make_test_file_name (0); - g_object_set (ctx.vrbin, "location", test_file_name, NULL); - - encoder = gst_element_factory_make ("theoraenc", NULL); - g_object_set (ctx.vrbin, "video-encoder", encoder, NULL); - - muxer = gst_element_factory_make ("oggmux", NULL); - g_object_set (ctx.vrbin, "video-muxer", muxer, NULL); - - fail_if (gst_element_set_state (ctx.pipe, GST_STATE_PLAYING) == - GST_STATE_CHANGE_FAILURE); - - msg = gst_bus_timed_pop_filtered (bus, GST_SECOND * 10, - GST_MESSAGE_EOS | GST_MESSAGE_ERROR); - fail_unless (msg != NULL); - fail_unless (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_EOS); - - /* check there is a recorded file */ - fail_unless (g_file_test (test_file_name, G_FILE_TEST_EXISTS)); - fail_unless (g_file_test (test_file_name, G_FILE_TEST_IS_REGULAR)); - fail_if (g_file_test (test_file_name, G_FILE_TEST_IS_SYMLINK)); - - /* check the file isn't empty */ - f = fopen (test_file_name, "r"); - fseek (f, 0, SEEK_END); - fail_unless (ftell (f) > 0); - fclose (f); - - gstvideorecordingbin_unset_test_context (&ctx); - gst_object_unref (bus); - g_free (test_file_name); -} - -GST_END_TEST; - -static Suite * -videorecordingbin_suite (void) -{ - Suite *s = suite_create ("videorecordingbin"); - TCase *tc_chain = tcase_create ("general"); - - suite_add_tcase (s, tc_chain); - tcase_add_test (tc_chain, test_simple_recording); - tcase_add_test (tc_chain, test_setting_video_encoder); - tcase_add_test (tc_chain, test_setting_video_muxer); - - return s; -} - -GST_CHECK_MAIN (videorecordingbin); From ccb1960a4208dcab514f1c9799642beb31951950 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Tue, 11 Jan 2011 09:12:24 -0300 Subject: [PATCH 320/448] camerabin2: Add a property to select the encoding profile Adds a video-profile to allow selecting which encoding profile to use for video recordings --- gst/camerabin2/gstcamerabin2.c | 27 ++++++++++++++++++++++----- gst/camerabin2/gstcamerabin2.h | 3 ++- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/gst/camerabin2/gstcamerabin2.c b/gst/camerabin2/gstcamerabin2.c index a9810dadfd..178f7cc2fb 100644 --- a/gst/camerabin2/gstcamerabin2.c +++ b/gst/camerabin2/gstcamerabin2.c @@ -50,7 +50,6 @@ #endif #include -#include #include "gstcamerabin2.h" GST_DEBUG_CATEGORY_STATIC (gst_camera_bin_debug); @@ -69,7 +68,8 @@ enum PROP_IMAGE_CAPTURE_CAPS, PROP_VIDEO_CAPTURE_CAPS, PROP_POST_PREVIEWS, - PROP_PREVIEW_CAPS + PROP_PREVIEW_CAPS, + PROP_VIDEO_ENCODING_PROFILE }; enum @@ -345,6 +345,12 @@ gst_camera_bin_class_init (GstCameraBinClass * klass) "The caps of the preview image to be posted", GST_TYPE_CAPS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (object_class, PROP_VIDEO_ENCODING_PROFILE, + gst_param_spec_mini_object ("video-profile", "Video Profile", + "The GstEncodingProfile to use for video recording", + GST_TYPE_ENCODING_PROFILE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** * GstCameraBin::capture-start: * @camera: the camera bin element @@ -421,7 +427,7 @@ gst_camera_bin_create_elements (GstCameraBin * camera) camera->imagebin = gst_element_factory_make ("imagecapturebin", "imagebin"); g_object_set (camera->videosink, "async", FALSE, NULL); - { + if (camera->video_profile == NULL) { GstEncodingContainerProfile *prof; GstCaps *caps; @@ -437,9 +443,10 @@ gst_camera_bin_create_elements (GstCameraBin * camera) GST_WARNING_OBJECT (camera, "Failed to create encoding profiles"); } gst_caps_unref (caps); - g_object_set (camera->encodebin, "profile", prof, NULL); - gst_encoding_profile_unref (prof); + + camera->video_profile = (GstEncodingProfile *) prof; } + g_object_set (camera->encodebin, "profile", camera->video_profile, NULL); camera->videobin_queue = gst_element_factory_make ("queue", "videobin-queue"); @@ -672,6 +679,10 @@ gst_camera_bin_set_property (GObject * object, guint prop_id, "preview-caps")) g_object_set (camera->src, "preview-caps", camera->preview_caps, NULL); break; + case PROP_VIDEO_ENCODING_PROFILE: + camera->video_profile = + (GstEncodingProfile *) gst_value_dup_mini_object (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -754,6 +765,12 @@ gst_camera_bin_get_property (GObject * object, guint prop_id, if (camera->preview_caps) gst_value_set_caps (value, camera->preview_caps); break; + case PROP_VIDEO_ENCODING_PROFILE: + if (camera->video_profile) { + gst_value_set_mini_object (value, + (GstMiniObject *) camera->video_profile); + } + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; diff --git a/gst/camerabin2/gstcamerabin2.h b/gst/camerabin2/gstcamerabin2.h index 8802a55341..8534674aa4 100644 --- a/gst/camerabin2/gstcamerabin2.h +++ b/gst/camerabin2/gstcamerabin2.h @@ -20,6 +20,7 @@ #define _GST_CAMERA_BIN_H_ #include +#include G_BEGIN_DECLS @@ -41,7 +42,6 @@ struct _GstCameraBin GstElement *user_src; gulong src_capture_notify_id; - //GstElement *videobin; GstElement *encodebin; GstElement *videosink; GstElement *videobin_queue; @@ -64,6 +64,7 @@ struct _GstCameraBin gchar *image_location; gboolean post_previews; GstCaps *preview_caps; + GstEncodingProfile *video_profile; gboolean elements_created; }; From a90f8210bbea2101be0baba0c4474f85a3d8f10b Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Tue, 11 Jan 2011 10:29:48 -0300 Subject: [PATCH 321/448] tests: camerabin2: Add preview image to tests Adds tests for checking that preview images are posted with the correct caps on tests --- tests/check/elements/camerabin2.c | 107 +++++++++++++++++++++++++++++- 1 file changed, 106 insertions(+), 1 deletion(-) diff --git a/tests/check/elements/camerabin2.c b/tests/check/elements/camerabin2.c index 5a6fc7cddb..93e3cf3852 100644 --- a/tests/check/elements/camerabin2.c +++ b/tests/check/elements/camerabin2.c @@ -169,6 +169,9 @@ static GstElement *camera; static GMainLoop *main_loop; guint32 test_id = 0; +static GstBuffer *preview_buffer; +static GstCaps *preview_caps; + /* helper function for filenames */ static const gchar * make_test_file_name (const gchar * base_name, gint num) @@ -240,12 +243,34 @@ capture_bus_cb (GstBus * bus, GstMessage * message, gpointer data) GST_INFO ("image captured"); g_object_get (camera, "ready-for-capture", &ready, NULL); fail_if (!ready, "not ready for capture"); + } else if (st && gst_structure_has_name (st, + GST_BASE_CAMERA_SRC_PREVIEW_MESSAGE_NAME)) { + GstBuffer *buf; + const GValue *value; + + value = gst_structure_get_value (st, "buffer"); + fail_unless (value != NULL); + buf = gst_value_get_buffer (value); + + if (preview_buffer) + gst_buffer_unref (preview_buffer); + preview_buffer = gst_buffer_ref (buf); } break; } return TRUE; } +static void +check_preview_image (void) +{ + fail_unless (preview_buffer != NULL); + if (preview_caps) { + fail_unless (gst_caps_can_intersect (GST_BUFFER_CAPS (preview_buffer), + preview_caps)); + } +} + static void setup_wrappercamerabinsrc_videotestsrc (void) { @@ -266,9 +291,13 @@ setup_wrappercamerabinsrc_videotestsrc (void) src = gst_element_factory_make ("wrappercamerabinsrc", NULL); testsrc = gst_element_factory_make ("videotestsrc", NULL); + preview_caps = gst_caps_new_simple ("video/x-raw-rgb", "width", G_TYPE_INT, + 320, "height", G_TYPE_INT, 240, NULL); + g_object_set (G_OBJECT (testsrc), "is-live", TRUE, "peer-alloc", FALSE, NULL); g_object_set (G_OBJECT (src), "video-src", testsrc, NULL); - g_object_set (G_OBJECT (camera), "camera-src", src, NULL); + g_object_set (G_OBJECT (camera), "camera-src", src, "preview-caps", + preview_caps, NULL); gst_object_unref (src); gst_object_unref (testsrc); @@ -291,6 +320,19 @@ teardown (void) if (camera) gst_check_teardown_element (camera); + camera = NULL; + + if (main_loop) + g_main_loop_unref (main_loop); + main_loop = NULL; + + if (preview_caps) + gst_caps_unref (preview_caps); + preview_caps = NULL; + + if (preview_buffer) + gst_buffer_unref (preview_buffer); + preview_buffer = NULL; GST_INFO ("done"); } @@ -405,6 +447,9 @@ GST_START_TEST (test_single_image_capture) g_timeout_add_seconds (3, (GSourceFunc) g_main_loop_quit, main_loop); g_main_loop_run (main_loop); + /* check that we got a preview image */ + check_preview_image (); + gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL); check_file_validity (IMAGE_FILENAME, 0, NULL, 0, 0); } @@ -448,6 +493,8 @@ GST_START_TEST (test_multiple_image_captures) g_timeout_add_seconds (3, (GSourceFunc) g_main_loop_quit, main_loop); g_main_loop_run (main_loop); + + check_preview_image (); } g_usleep (G_USEC_PER_SEC * 3); @@ -487,6 +534,8 @@ GST_START_TEST (test_single_video_recording) g_signal_emit_by_name (camera, "stop-capture", NULL); + check_preview_image (); + gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL); check_file_validity (VIDEO_FILENAME, 0, NULL, 0, 0); @@ -535,6 +584,8 @@ GST_START_TEST (test_multiple_video_recordings) g_main_loop_run (main_loop); g_signal_emit_by_name (camera, "stop-capture", NULL); + check_preview_image (); + g_timeout_add_seconds (1, (GSourceFunc) g_main_loop_quit, main_loop); g_main_loop_run (main_loop); } @@ -578,6 +629,8 @@ GST_START_TEST (test_image_video_cycle) g_timeout_add_seconds (3, (GSourceFunc) g_main_loop_quit, main_loop); g_main_loop_run (main_loop); + check_preview_image (); + /* now go to video */ g_object_set (camera, "mode", 2, NULL); g_signal_emit_by_name (camera, "start-capture", NULL); @@ -586,6 +639,8 @@ GST_START_TEST (test_image_video_cycle) g_main_loop_run (main_loop); g_signal_emit_by_name (camera, "stop-capture", NULL); + check_preview_image (); + /* wait for capture to finish */ g_usleep (G_USEC_PER_SEC); } @@ -600,6 +655,54 @@ GST_START_TEST (test_image_video_cycle) GST_END_TEST; + +GST_START_TEST (test_image_capture_previews) +{ + gint i; + gint widths[] = { 800, 640, 1280 }; + gint heights[] = { 600, 480, 1024 }; + + if (!camera) + return; + + /* set still image mode */ + g_object_set (camera, "mode", 1, + "location", make_test_file_name (IMAGE_FILENAME, -1), NULL); + + if (gst_element_set_state (GST_ELEMENT (camera), GST_STATE_PLAYING) == + GST_STATE_CHANGE_FAILURE) { + GST_WARNING ("setting camerabin to PLAYING failed"); + gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL); + gst_object_unref (camera); + camera = NULL; + } + fail_unless (camera != NULL); + GST_INFO ("starting capture"); + + for (i = 0; i < 3; i++) { + GstCaps *caps; + + caps = gst_caps_new_simple ("video/x-raw-rgb", "width", G_TYPE_INT, + widths[i], "height", G_TYPE_INT, heights[i], NULL); + + g_object_set (camera, "preview-caps", caps, NULL); + gst_caps_replace (&preview_caps, caps); + gst_caps_unref (caps); + + g_signal_emit_by_name (camera, "start-capture", NULL); + + g_timeout_add_seconds (3, (GSourceFunc) g_main_loop_quit, main_loop); + g_main_loop_run (main_loop); + + check_preview_image (); + } + + gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL); +} + +GST_END_TEST; + + GST_START_TEST (test_supported_caps) { GstCaps *padcaps = NULL; @@ -693,6 +796,8 @@ camerabin_suite (void) GST_WARNING ("Skipping image capture test because -good 0.10.27 is " "needed"); tcase_add_test (tc_basic, test_multiple_video_recordings); + + tcase_add_test (tc_basic, test_image_capture_previews); } end: From a715b46c7fba1826b17dd7823807fa7338492e3e Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Tue, 11 Jan 2011 14:50:48 -0300 Subject: [PATCH 322/448] camerabin2: Implement tagsetter interface --- gst/camerabin2/gstcamerabin2.c | 32 +++++ tests/check/Makefile.am | 1 + tests/check/elements/camerabin2.c | 228 ++++++++++++++++++++++++++++++ 3 files changed, 261 insertions(+) diff --git a/gst/camerabin2/gstcamerabin2.c b/gst/camerabin2/gstcamerabin2.c index 178f7cc2fb..fdee61fd55 100644 --- a/gst/camerabin2/gstcamerabin2.c +++ b/gst/camerabin2/gstcamerabin2.c @@ -103,6 +103,11 @@ GType gst_camera_bin_get_type (void) { static GType gst_camera_bin_type = 0; + static const GInterfaceInfo camerabin_tagsetter_info = { + NULL, + NULL, + NULL, + }; if (!gst_camera_bin_type) { static const GTypeInfo gst_camera_bin_info = { @@ -121,6 +126,9 @@ gst_camera_bin_get_type (void) gst_camera_bin_type = g_type_register_static (GST_TYPE_PIPELINE, "GstCameraBin2", &gst_camera_bin_info, 0); + + g_type_add_interface_static (gst_camera_bin_type, GST_TYPE_TAG_SETTER, + &camerabin_tagsetter_info); } return gst_camera_bin_type; @@ -149,7 +157,30 @@ gst_camera_bin_new_event_renegotiate (void) static void gst_camera_bin_start_capture (GstCameraBin * camerabin) { + const GstTagList *taglist; + GST_DEBUG_OBJECT (camerabin, "Received start-capture"); + + taglist = gst_tag_setter_get_tag_list (GST_TAG_SETTER (camerabin)); + if (taglist) { + GstPad *active_pad; + + GST_DEBUG_OBJECT (camerabin, "Pushing tags from application: %" + GST_PTR_FORMAT, taglist); + + if (camerabin->mode == MODE_IMAGE) { + active_pad = gst_element_get_static_pad (camerabin->src, + GST_BASE_CAMERA_SRC_IMAGE_PAD_NAME); + } else { + active_pad = gst_element_get_static_pad (camerabin->src, + GST_BASE_CAMERA_SRC_VIDEO_PAD_NAME); + } + + gst_pad_push_event (active_pad, + gst_event_new_tag (gst_tag_list_copy (taglist))); + gst_object_unref (active_pad); + } + g_signal_emit_by_name (camerabin->src, "start-capture", NULL); } @@ -559,6 +590,7 @@ gst_camera_bin_change_state (GstElement * element, GstStateChange trans) switch (trans) { case GST_STATE_CHANGE_PAUSED_TO_READY: + gst_tag_setter_reset_tags (GST_TAG_SETTER (camera)); gst_element_set_state (camera->videosink, GST_STATE_READY); break; case GST_STATE_CHANGE_READY_TO_NULL: diff --git a/tests/check/Makefile.am b/tests/check/Makefile.am index 6e0de76d7e..7826883a0e 100644 --- a/tests/check/Makefile.am +++ b/tests/check/Makefile.am @@ -201,6 +201,7 @@ elements_camerabin2_CFLAGS = \ elements_camerabin2_LDADD = \ $(top_builddir)/gst-libs/gst/interfaces/libgstphotography-@GST_MAJORMINOR@.la \ $(top_builddir)/gst-libs/gst/basecamerabinsrc/libgstbasecamerabinsrc-@GST_MAJORMINOR@.la \ + -lgstpbutils-$(GST_MAJORMINOR) \ $(GST_PLUGINS_BASE_LIBS) $(GST_BASE_LIBS) $(GST_LIBS) $(LDADD) elements_camerabin2_SOURCES = elements/camerabin2.c diff --git a/tests/check/elements/camerabin2.c b/tests/check/elements/camerabin2.c index 93e3cf3852..b41fe0e5fa 100644 --- a/tests/check/elements/camerabin2.c +++ b/tests/check/elements/camerabin2.c @@ -31,6 +31,7 @@ #include #include #include +#include #define IMAGE_FILENAME "image" #define VIDEO_FILENAME "video" @@ -171,6 +172,26 @@ guint32 test_id = 0; static GstBuffer *preview_buffer; static GstCaps *preview_caps; +static GstTagList *tags_found; + +static gboolean +validity_bus_cb (GstBus * bus, GstMessage * message, gpointer data); + +static void +validate_taglist_foreach (const GstTagList * list, const gchar * tag, + gpointer user_data) +{ + GstTagList *other = GST_TAG_LIST (user_data); + + const GValue *val1 = gst_tag_list_get_value_index (list, tag, 0); + const GValue *val2 = gst_tag_list_get_value_index (other, tag, 0); + + fail_if (val1 == NULL); + fail_if (val2 == NULL); + + fail_unless (gst_value_can_intersect (val1, val2)); +} + /* helper function for filenames */ static const gchar * @@ -271,6 +292,31 @@ check_preview_image (void) } } +static void +extract_jpeg_tags (const gchar * filename, gint num) +{ + GstBus *bus; + GMainLoop *loop = g_main_loop_new (NULL, FALSE); + const gchar *filepath = make_test_file_name (filename, num); + gchar *pipeline_str = g_strdup_printf ("filesrc location=%s ! " + "jpegparse ! fakesink", filepath); + GstElement *pipeline; + + pipeline = gst_parse_launch (pipeline_str, NULL); + fail_unless (pipeline != NULL); + g_free (pipeline_str); + + bus = gst_pipeline_get_bus (GST_PIPELINE (pipeline)); + gst_bus_add_watch (bus, (GstBusFunc) validity_bus_cb, loop); + + gst_element_set_state (pipeline, GST_STATE_PLAYING); + g_main_loop_run (loop); + gst_element_set_state (pipeline, GST_STATE_NULL); + + gst_object_unref (bus); + gst_object_unref (pipeline); +} + static void setup_wrappercamerabinsrc_videotestsrc (void) { @@ -334,6 +380,10 @@ teardown (void) gst_buffer_unref (preview_buffer); preview_buffer = NULL; + if (tags_found) + gst_tag_list_free (tags_found); + tags_found = NULL; + GST_INFO ("done"); } @@ -360,12 +410,32 @@ validity_bus_cb (GstBus * bus, GstMessage * message, gpointer data) g_main_loop_quit (loop); GST_DEBUG ("eos"); break; + case GST_MESSAGE_TAG:{ + GstTagList *taglist = NULL; + + gst_message_parse_tag (message, &taglist); + if (tags_found) { + gst_tag_list_insert (tags_found, taglist, GST_TAG_MERGE_REPLACE); + gst_tag_list_free (taglist); + } else { + tags_found = taglist; + } + } + break; default: break; } return TRUE; } +/* checks that tags in @tags_a are in @tags_b */ +static gboolean +taglist_is_subset (GstTagList * tags_a, GstTagList * tags_b) +{ + gst_tag_list_foreach (tags_a, validate_taglist_foreach, tags_b); + return TRUE; +} + /* Validate captured files by playing them with playbin * and checking that no errors occur. */ static gboolean @@ -417,6 +487,17 @@ check_file_validity (const gchar * filename, gint num, GstTagList * taglist, g_main_loop_run (loop); gst_element_set_state (playbin, GST_STATE_NULL); + /* special handling for images (jpg) as jpegparse isn't plugged by + * default due to its current low rank */ + if (taglist && strstr (filename, "image")) { + extract_jpeg_tags (filename, num); + } + + if (taglist) { + fail_unless (tags_found != NULL); + fail_unless (taglist_is_subset (taglist, tags_found)); + } + g_free (uri); gst_object_unref (bus); gst_object_unref (playbin); @@ -703,6 +784,150 @@ GST_START_TEST (test_image_capture_previews) GST_END_TEST; +GST_START_TEST (test_image_capture_with_tags) +{ + gint i; + GstTagList *taglists[3]; + + if (!camera) + return; + + taglists[0] = gst_tag_list_new_full (GST_TAG_COMMENT, "test1", + GST_TAG_GEO_LOCATION_LATITUDE, 36.6, GST_TAG_GEO_LOCATION_LONGITUDE, + -12.5, + GST_TAG_COPYRIGHT, "My copyright notice", + GST_TAG_DEVICE_MANUFACTURER, "MyFavoriteBrand", + GST_TAG_DEVICE_MODEL, "123v42.1", + GST_TAG_DESCRIPTION, "some description", + GST_TAG_APPLICATION_NAME, "camerabin2 test", + GST_TAG_GEO_LOCATION_ELEVATION, 300.85, NULL); + taglists[1] = gst_tag_list_new_full (GST_TAG_COMMENT, "test2", + GST_TAG_GEO_LOCATION_LATITUDE, 1.6, GST_TAG_GEO_LOCATION_LONGITUDE, + 0.0, + GST_TAG_COPYRIGHT, "some cp", + GST_TAG_DEVICE_MANUFACTURER, "ABRAND", + GST_TAG_DEVICE_MODEL, "abcd", + GST_TAG_DESCRIPTION, "desc", + GST_TAG_APPLICATION_NAME, "another cam test", + GST_TAG_GEO_LOCATION_ELEVATION, 10.0, NULL); + taglists[2] = gst_tag_list_new_full (GST_TAG_COMMENT, "test3", + GST_TAG_GEO_LOCATION_LATITUDE, 1.3, GST_TAG_GEO_LOCATION_LONGITUDE, + -5.0, + GST_TAG_COPYRIGHT, "CC", + GST_TAG_DEVICE_MANUFACTURER, "Homemade", + GST_TAG_DEVICE_MODEL, "xpto", + GST_TAG_DESCRIPTION, "another description", + GST_TAG_APPLICATION_NAME, "cam2 test", + GST_TAG_GEO_LOCATION_ELEVATION, 0.0, NULL); + + /* set still image mode */ + g_object_set (camera, "mode", 1, + "location", make_test_file_name (IMAGE_FILENAME, -1), NULL); + + if (gst_element_set_state (GST_ELEMENT (camera), GST_STATE_PLAYING) == + GST_STATE_CHANGE_FAILURE) { + GST_WARNING ("setting camerabin to PLAYING failed"); + gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL); + gst_object_unref (camera); + camera = NULL; + } + fail_unless (camera != NULL); + GST_INFO ("starting capture"); + + for (i = 0; i < 3; i++) { + gst_tag_setter_merge_tags (GST_TAG_SETTER (camera), taglists[i], + GST_TAG_MERGE_REPLACE); + + g_signal_emit_by_name (camera, "start-capture", NULL); + + g_timeout_add_seconds (3, (GSourceFunc) g_main_loop_quit, main_loop); + g_main_loop_run (main_loop); + } + + gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL); + + for (i = 0; i < 2; i++) { + check_file_validity (IMAGE_FILENAME, i, taglists[i], 0, 0); + gst_tag_list_free (taglists[i]); + } +} + +GST_END_TEST; + + +GST_START_TEST (test_video_capture_with_tags) +{ + gint i; + GstTagList *taglists[3]; + + if (!camera) + return; + + taglists[0] = gst_tag_list_new_full (GST_TAG_COMMENT, "test1", NULL); + taglists[1] = gst_tag_list_new_full (GST_TAG_COMMENT, "test2", NULL); + taglists[2] = gst_tag_list_new_full (GST_TAG_COMMENT, "test3", NULL); + + /* set video mode */ + g_object_set (camera, "mode", 2, + "location", make_test_file_name (VIDEO_FILENAME, -1), NULL); + + /* set a profile that has xmp support for more tags being saved */ + { + GstEncodingContainerProfile *profile; + GstCaps *caps; + + caps = + gst_caps_new_simple ("video/quicktime", "variant", G_TYPE_STRING, + "apple", NULL); + profile = gst_encoding_container_profile_new ("qt", "jpeg+qt", caps, NULL); + gst_caps_unref (caps); + + caps = gst_caps_new_simple ("image/jpeg", NULL); + if (!gst_encoding_container_profile_add_profile (profile, + (GstEncodingProfile *) gst_encoding_video_profile_new (caps, + NULL, NULL, 1))) { + GST_WARNING_OBJECT (camera, "Failed to create encoding profiles"); + } + gst_caps_unref (caps); + + g_object_set (camera, "video-profile", profile, NULL); + gst_encoding_profile_unref (profile); + } + + if (gst_element_set_state (GST_ELEMENT (camera), GST_STATE_PLAYING) == + GST_STATE_CHANGE_FAILURE) { + GST_WARNING ("setting camerabin to PLAYING failed"); + gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL); + gst_object_unref (camera); + camera = NULL; + } + fail_unless (camera != NULL); + GST_INFO ("starting capture"); + + for (i = 0; i < 3; i++) { + gst_tag_setter_merge_tags (GST_TAG_SETTER (camera), taglists[i], + GST_TAG_MERGE_REPLACE); + + g_signal_emit_by_name (camera, "start-capture", NULL); + + g_timeout_add_seconds (3, (GSourceFunc) g_main_loop_quit, main_loop); + g_main_loop_run (main_loop); + + g_signal_emit_by_name (camera, "stop-capture", NULL); + g_usleep (G_USEC_PER_SEC * 3); + } + + gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL); + + for (i = 0; i < 2; i++) { + check_file_validity (VIDEO_FILENAME, i, taglists[i], 0, 0); + gst_tag_list_free (taglists[i]); + } +} + +GST_END_TEST; + + GST_START_TEST (test_supported_caps) { GstCaps *padcaps = NULL; @@ -798,6 +1023,9 @@ camerabin_suite (void) tcase_add_test (tc_basic, test_multiple_video_recordings); tcase_add_test (tc_basic, test_image_capture_previews); + tcase_add_test (tc_basic, test_image_capture_with_tags); + + tcase_add_test (tc_basic, test_video_capture_with_tags); } end: From bccae0f994572e016af60ab834e3b5d1f416aed4 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Fri, 14 Jan 2011 08:12:25 -0300 Subject: [PATCH 323/448] camerabin2: Add image-done message Post an image-done message when a new image is saved to disk --- gst/camerabin2/PORTING | 3 +++ gst/camerabin2/gstcamerabin2.c | 40 +++++++++++++++++++++++++++++ gst/camerabin2/gstimagecapturebin.c | 2 +- 3 files changed, 44 insertions(+), 1 deletion(-) diff --git a/gst/camerabin2/PORTING b/gst/camerabin2/PORTING index fe090b5c1e..bf85050e55 100644 --- a/gst/camerabin2/PORTING +++ b/gst/camerabin2/PORTING @@ -12,3 +12,6 @@ capture. * Capture signals The signals were renamed from capture-start/stop to start/stop-capture as this is the usual naming on actions. + +* image-done +In camerabin, image-done is a signal, in camerabin2, it is a bus message diff --git a/gst/camerabin2/gstcamerabin2.c b/gst/camerabin2/gstcamerabin2.c index fdee61fd55..8b82c7fbb8 100644 --- a/gst/camerabin2/gstcamerabin2.c +++ b/gst/camerabin2/gstcamerabin2.c @@ -99,6 +99,8 @@ static void gst_camera_bin_init (GstCameraBin * camera); static void gst_camera_bin_dispose (GObject * object); static void gst_camera_bin_finalize (GObject * object); +static void gst_camera_bin_handle_message (GstBin * bin, GstMessage * message); + GType gst_camera_bin_get_type (void) { @@ -300,10 +302,12 @@ gst_camera_bin_class_init (GstCameraBinClass * klass) { GObjectClass *object_class; GstElementClass *element_class; + GstBinClass *bin_class; parent_class = g_type_class_peek_parent (klass); object_class = G_OBJECT_CLASS (klass); element_class = GST_ELEMENT_CLASS (klass); + bin_class = GST_BIN_CLASS (klass); object_class->dispose = gst_camera_bin_dispose; object_class->finalize = gst_camera_bin_finalize; @@ -312,6 +316,8 @@ gst_camera_bin_class_init (GstCameraBinClass * klass) element_class->change_state = GST_DEBUG_FUNCPTR (gst_camera_bin_change_state); + bin_class->handle_message = gst_camera_bin_handle_message; + klass->start_capture = gst_camera_bin_start_capture; klass->stop_capture = gst_camera_bin_stop_capture; @@ -433,6 +439,40 @@ gst_camera_bin_init (GstCameraBin * camera) gst_object_ref (camera->viewfinderbin_capsfilter), NULL); } +static void +gst_image_capture_bin_post_image_done (GstCameraBin * camera, + const gchar * filename) +{ + GstMessage *msg; + + g_return_if_fail (filename != NULL); + + msg = gst_message_new_element (GST_OBJECT_CAST (camera), + gst_structure_new ("image-done", "filename", G_TYPE_STRING, + filename, NULL)); + + if (!gst_element_post_message (GST_ELEMENT_CAST (camera), msg)) + GST_WARNING_OBJECT (camera, "Failed to post image-done message"); +} + +static void +gst_camera_bin_handle_message (GstBin * bin, GstMessage * message) +{ + if (GST_MESSAGE_TYPE (message) == GST_MESSAGE_ELEMENT) { + const GstStructure *structure = gst_message_get_structure (message); + const gchar *filename; + + if (gst_structure_has_name (structure, "GstMultiFileSink")) { + filename = gst_structure_get_string (structure, "filename"); + if (filename) { + gst_image_capture_bin_post_image_done (GST_CAMERA_BIN_CAST (bin), + filename); + } + } + } + GST_BIN_CLASS (parent_class)->handle_message (bin, message); +} + /** * gst_camera_bin_create_elements: * @param camera: the #GstCameraBin diff --git a/gst/camerabin2/gstimagecapturebin.c b/gst/camerabin2/gstimagecapturebin.c index b20cb46309..32419ef378 100644 --- a/gst/camerabin2/gstimagecapturebin.c +++ b/gst/camerabin2/gstimagecapturebin.c @@ -297,7 +297,7 @@ gst_image_capture_bin_create_elements (GstImageCaptureBin * imagebin) goto error; g_object_set (imagebin->sink, "location", imagebin->location, "async", FALSE, - NULL); + "post-messages", TRUE, NULL); /* add ghostpad */ pad = gst_element_get_static_pad (colorspace, "sink"); From 4ec3189575f95b3f85426c77205244d87551d6b8 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Wed, 19 Jan 2011 15:07:25 -0300 Subject: [PATCH 324/448] camerabin2: Update porting file Adds porting information about using encodebin on camerabin2 --- gst/camerabin2/PORTING | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/gst/camerabin2/PORTING b/gst/camerabin2/PORTING index bf85050e55..c9b6dd8256 100644 --- a/gst/camerabin2/PORTING +++ b/gst/camerabin2/PORTING @@ -15,3 +15,8 @@ this is the usual naming on actions. * image-done In camerabin, image-done is a signal, in camerabin2, it is a bus message + +* video recording encoder/muxer +In camerabin, video/audio encoder/muxer are selected by passing GstElements to +camerabin properties. In camerabin2, a GstEncodingProfile is passed as a +property and encodebin manages to instantiate the elements for the format. From c3d05d6006ed78d0d470ab7bbe9436fd43c60d5e Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Tue, 11 Jan 2011 15:52:03 +0000 Subject: [PATCH 325/448] dvdspu: don't write clipped lines to the output buffer We may not increment the output pointer, but it'll still be just off the end of the allocated area. https://bugzilla.gnome.org/show_bug.cgi?id=602847 --- gst/dvdspu/gstspu-vobsub-render.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/gst/dvdspu/gstspu-vobsub-render.c b/gst/dvdspu/gstspu-vobsub-render.c index 30de0eb801..06054085d1 100644 --- a/gst/dvdspu/gstspu-vobsub-render.c +++ b/gst/dvdspu/gstspu-vobsub-render.c @@ -515,10 +515,11 @@ gstspu_vobsub_render (GstDVDSpu * dvdspu, GstBuffer * buf) /* Render odd line */ state->vobsub.comp_last_x_ptr = state->vobsub.comp_last_x + 1; gstspu_vobsub_render_line (state, planes, &state->vobsub.cur_offsets[1]); - /* Blend the accumulated UV compositing buffers onto the output */ - gstspu_vobsub_blend_comp_buffers (state, planes); if (!clip) { + /* Blend the accumulated UV compositing buffers onto the output */ + gstspu_vobsub_blend_comp_buffers (state, planes); + /* Update all the output pointers */ planes[0] += state->Y_stride; planes[1] += state->UV_stride; From a791f5070cdc1b29c4c0415c2c74cf8d6d5ced65 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Mon, 24 Jan 2011 17:46:49 -0300 Subject: [PATCH 326/448] wrappercamerabinsrc: Check the start time of buffers Be careful when trying to create a newsegment event to avoid start times of -1 from invalid buffer timestamps --- gst/camerabin2/gstwrappercamerabinsrc.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/gst/camerabin2/gstwrappercamerabinsrc.c b/gst/camerabin2/gstwrappercamerabinsrc.c index 9437b9ac1f..faac60b4f0 100644 --- a/gst/camerabin2/gstwrappercamerabinsrc.c +++ b/gst/camerabin2/gstwrappercamerabinsrc.c @@ -217,10 +217,15 @@ gst_wrapper_camera_bin_src_vidsrc_probe (GstPad * pad, GstBuffer * buffer, if (self->video_rec_status == GST_VIDEO_RECORDING_STATUS_DONE) { /* NOP */ } else if (self->video_rec_status == GST_VIDEO_RECORDING_STATUS_STARTING) { + gint64 start = 0; + + if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (buffer))) + start = GST_BUFFER_TIMESTAMP (buffer); + /* send the newseg */ GST_DEBUG_OBJECT (self, "Starting video recording, pushing newsegment"); gst_pad_push_event (pad, gst_event_new_new_segment (FALSE, 1.0, - GST_FORMAT_TIME, GST_BUFFER_TIMESTAMP (buffer), -1, 0)); + GST_FORMAT_TIME, start, -1, 0)); self->video_rec_status = GST_VIDEO_RECORDING_STATUS_RUNNING; /* post preview */ From 10830c9544b4856fc39497f84df818662946274d Mon Sep 17 00:00:00 2001 From: Lasse Laukkanen Date: Wed, 12 Jan 2011 16:26:19 +0200 Subject: [PATCH 327/448] examples: camerabin: Don't set default values for GstPhotography interface settings Don't set any default values for source element GstPhotography interface settings, source elements should have sane defaults themselves. Also, setting scene-mode is tricky as it is a superset of other GstPhotography settings. This might cause problem with defaults e.g. setting scene-mode to 'night' may configure flash-mode as 'on' by definition, and after that we don't want to override this flash-mode setting with gst-camerabin-test default value. Moreover, user needs have an option to set scene mode first and then force some individual setting to a different value from the scene-mode definition. https://bugzilla.gnome.org/show_bug.cgi?id=639841 --- tests/examples/camerabin/gst-camerabin-test.c | 71 ++++++++++++------- 1 file changed, 46 insertions(+), 25 deletions(-) diff --git a/tests/examples/camerabin/gst-camerabin-test.c b/tests/examples/camerabin/gst-camerabin-test.c index 6ebd1e2373..ad8e6d2a5b 100644 --- a/tests/examples/camerabin/gst-camerabin-test.c +++ b/tests/examples/camerabin/gst-camerabin-test.c @@ -136,15 +136,6 @@ static gint view_framerate_num = 2825; static gint view_framerate_den = 100; static gboolean no_xwindow = FALSE; -/* photography interface command line options */ -static gfloat ev_compensation = 0.0; -static gint aperture = 0; -static gint flash_mode = 0; -static gint scene_mode = 6; -static gint64 exposure = 0; -static gint iso_speed = 0; -static gint wb_mode = 0; -static gint color_mode = 0; static gint mode = 1; static gint flags = 0x4f; static gboolean mute = FALSE; @@ -154,6 +145,24 @@ static gint capture_time = 10; static gint capture_count = 0; static gint capture_total = 1; +/* photography interface command line options */ +#define EV_COMPENSATION_NONE -G_MAXFLOAT +#define APERTURE_NONE -G_MAXINT +#define FLASH_MODE_NONE -G_MAXINT +#define SCENE_MODE_NONE -G_MAXINT +#define EXPOSURE_NONE -G_MAXINT64 +#define ISO_SPEED_NONE -G_MAXINT +#define WHITE_BALANCE_MODE_NONE -G_MAXINT +#define COLOR_TONE_MODE_NONE -G_MAXINT +static gfloat ev_compensation = EV_COMPENSATION_NONE; +static gint aperture = APERTURE_NONE; +static gint flash_mode = FLASH_MODE_NONE; +static gint scene_mode = SCENE_MODE_NONE; +static gint64 exposure = EXPOSURE_NONE; +static gint iso_speed = ISO_SPEED_NONE; +static gint wb_mode = WHITE_BALANCE_MODE_NONE; +static gint color_mode = COLOR_TONE_MODE_NONE; + /* audio capsfilter options */ static gint audio_bitrate = 128000; static gint audio_samplerate = 48000; @@ -634,14 +643,24 @@ run_pipeline (gpointer user_data) if (video_source) { if (GST_IS_ELEMENT (video_source) && gst_element_implements_interface (video_source, GST_TYPE_PHOTOGRAPHY)) { - g_object_set (video_source, "ev-compensation", ev_compensation, NULL); - g_object_set (video_source, "aperture", aperture, NULL); - g_object_set (video_source, "flash-mode", flash_mode, NULL); - g_object_set (video_source, "scene-mode", scene_mode, NULL); - g_object_set (video_source, "exposure", exposure, NULL); - g_object_set (video_source, "iso-speed", iso_speed, NULL); - g_object_set (video_source, "white-balance-mode", wb_mode, NULL); - g_object_set (video_source, "colour-tone-mode", color_mode, NULL); + /* Set GstPhotography interface options. If option not given as + command-line parameter use default of the source element. */ + if (scene_mode != SCENE_MODE_NONE) + g_object_set (video_source, "scene-mode", scene_mode, NULL); + if (ev_compensation != EV_COMPENSATION_NONE) + g_object_set (video_source, "ev-compensation", ev_compensation, NULL); + if (aperture != APERTURE_NONE) + g_object_set (video_source, "aperture", aperture, NULL); + if (flash_mode != FLASH_MODE_NONE) + g_object_set (video_source, "flash-mode", flash_mode, NULL); + if (exposure != EXPOSURE_NONE) + g_object_set (video_source, "exposure", exposure, NULL); + if (iso_speed != ISO_SPEED_NONE) + g_object_set (video_source, "iso-speed", iso_speed, NULL); + if (wb_mode != WHITE_BALANCE_MODE_NONE) + g_object_set (video_source, "white-balance-mode", wb_mode, NULL); + if (color_mode != COLOR_TONE_MODE_NONE) + g_object_set (video_source, "colour-tone-mode", color_mode, NULL); } g_object_unref (video_source); } @@ -669,27 +688,29 @@ main (int argc, char *argv[]) GOptionEntry options[] = { {"ev-compensation", '\0', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_STRING, &ev_option, - "EV compensation (-2.5..2.5, default = 0)", NULL}, + "EV compensation for source element GstPhotography interface", NULL}, {"aperture", '\0', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_INT, &aperture, - "Aperture (size of lens opening, default = 0 (auto))", NULL}, + "Aperture (size of lens opening) for source element GstPhotography interface", + NULL}, {"flash-mode", '\0', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_INT, &flash_mode, - "Flash mode (default = 0 (auto))", NULL}, + "Flash mode for source element GstPhotography interface", NULL}, {"scene-mode", '\0', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_INT, &scene_mode, - "Scene mode (default = 6 (auto))", NULL}, + "Scene mode for source element GstPhotography interface", NULL}, {"exposure", '\0', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_INT64, &exposure, - "Exposure (default = 0 (auto))", NULL}, + "Exposure time (in ms) for source element GstPhotography interface", + NULL}, {"iso-speed", '\0', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_INT, &iso_speed, - "ISO speed (default = 0 (auto))", NULL}, + "ISO speed for source element GstPhotography interface", NULL}, {"white-balance-mode", '\0', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_INT, &wb_mode, - "White balance mode (default = 0 (auto))", NULL}, + "White balance mode for source element GstPhotography interface", NULL}, {"colour-tone-mode", '\0', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_INT, &color_mode, - "Colour tone mode (default = 0 (auto))", NULL}, + "Colour tone mode for source element GstPhotography interface", NULL}, {"directory", '\0', 0, G_OPTION_ARG_STRING, &fn_option, "Directory for capture file(s) (default is current directory)", NULL}, {"mode", '\0', G_OPTION_FLAG_OPTIONAL_ARG, G_OPTION_ARG_INT, &mode, From 25062fc384635ac0a2457406c140518dc84802c3 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Mon, 24 Jan 2011 18:36:58 -0300 Subject: [PATCH 328/448] wrappercamerabinsrc: Remove unused macro --- gst/camerabin2/gstwrappercamerabinsrc.c | 1 - 1 file changed, 1 deletion(-) diff --git a/gst/camerabin2/gstwrappercamerabinsrc.c b/gst/camerabin2/gstwrappercamerabinsrc.c index faac60b4f0..afcd9518e7 100644 --- a/gst/camerabin2/gstwrappercamerabinsrc.c +++ b/gst/camerabin2/gstwrappercamerabinsrc.c @@ -42,7 +42,6 @@ enum PROP_PREVIEW_CAPS }; -#define CAMERABIN_DEFAULT_VF_CAPS "video/x-raw-yuv,format=(fourcc)I420" #define DEFAULT_POST_PREVIEWS TRUE /* Using "bilinear" as default zoom method */ From 97789fa5bcb9ed48ca2aaacbc7e5ee7da84b8e99 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Mon, 24 Jan 2011 18:37:12 -0300 Subject: [PATCH 329/448] examples: camerabin: add timing printing for preview image Measure and print the time taken to generate preview image. And fix a typo --- tests/examples/camerabin/gst-camerabin-test.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/tests/examples/camerabin/gst-camerabin-test.c b/tests/examples/camerabin/gst-camerabin-test.c index ad8e6d2a5b..6286b25ef7 100644 --- a/tests/examples/camerabin/gst-camerabin-test.c +++ b/tests/examples/camerabin/gst-camerabin-test.c @@ -183,6 +183,8 @@ static gchar *preview_caps_name = NULL; static Display *display = NULL; static Window window = 0; +GTimer *timer = NULL; + /* * Prototypes */ @@ -266,14 +268,14 @@ sync_bus_callback (GstBus * bus, GstMessage * message, gpointer data) size = GST_BUFFER_SIZE (buf); preview_filename = g_strdup_printf ("test_vga.rgb"); caps_string = gst_caps_to_string (GST_BUFFER_CAPS (buf)); - g_print ("writing buffer to %s, buffer caps: %s\n", - preview_filename, caps_string); + g_print ("writing buffer to %s, elapsed: %.2fs, buffer caps: %s\n", + preview_filename, g_timer_elapsed (timer, NULL), caps_string); g_free (caps_string); f = g_fopen (preview_filename, "w"); if (f) { written = fwrite (data_buf, size, 1, f); if (!written) { - g_print ("errro writing file\n"); + g_print ("error writing file\n"); } fclose (f); } else { @@ -668,6 +670,7 @@ run_pipeline (gpointer user_data) g_object_set (camera_bin, "zoom", zoom / 100.0f, NULL); capture_count++; + g_timer_start (timer); g_signal_emit_by_name (camera_bin, "capture-start", 0); @@ -808,6 +811,8 @@ main (int argc, char *argv[]) if (filename->len == 0) filename = g_string_append (filename, "."); + timer = g_timer_new (); + /* init */ if (setup_pipeline ()) { loop = g_main_loop_new (NULL, FALSE); @@ -830,6 +835,7 @@ main (int argc, char *argv[]) g_free (src_csp); g_free (src_format); g_free (target_times); + g_timer_destroy (timer); if (window) XDestroyWindow (display, window); From a875342c54c470c75e53f9a30b810b7af859813e Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Mon, 24 Jan 2011 23:32:30 -0300 Subject: [PATCH 330/448] rsvgoverlay: Do not segfault on unexistent files When passing an unexistent file to rsvgoverlay it would crash because the svg loading would fail without setting an error. This patch makes it check if the handle was actually created and logs an error in case it didn't. Maybe it should post an error to the bus, but the previous error handling didn't, so I just followed the same logic. --- ext/rsvg/gstrsvgoverlay.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/ext/rsvg/gstrsvgoverlay.c b/ext/rsvg/gstrsvgoverlay.c index 60fd1676d2..2a5bdc10d4 100644 --- a/ext/rsvg/gstrsvgoverlay.c +++ b/ext/rsvg/gstrsvgoverlay.c @@ -126,10 +126,14 @@ gst_rsvg_overlay_set_svg_data (GstRsvgOverlay * overlay, const gchar * data, else overlay->handle = rsvg_handle_new_from_data ((guint8 *) data, size, &error); - if (error) { - GST_ERROR_OBJECT (overlay, "Cannot read SVG data: %s\n%s", - error->message, data); - g_error_free (error); + if (error || overlay->handle == NULL) { + if (error) { + GST_ERROR_OBJECT (overlay, "Cannot read SVG data: %s\n%s", + error->message, data); + g_error_free (error); + } else { + GST_ERROR_OBJECT (overlay, "Cannot read SVG data: %s", data); + } } else { /* Get SVG dimension. */ RsvgDimensionData svg_dimension; From 3da135ce02b37bf16b9b6f5a56af41d4c395b5c8 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Fri, 14 Jan 2011 14:08:38 +0100 Subject: [PATCH 331/448] baseparse: avoid loop in frame locating interpolation --- gst/audioparsers/gstbaseparse.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/gst/audioparsers/gstbaseparse.c b/gst/audioparsers/gstbaseparse.c index 59355c7757..927c3556ee 100644 --- a/gst/audioparsers/gstbaseparse.c +++ b/gst/audioparsers/gstbaseparse.c @@ -3032,6 +3032,7 @@ gst_base_parse_locate_time (GstBaseParse * parse, GstClockTime * _time, gst_util_uint64_scale (hpos - lpos, time - ltime, htime - ltime) + lpos - chunk; } else { + /* should mean lpos == hpos, since lpos <= hpos is invariant */ newpos = lpos; /* we check this case once, but not forever, so break loop */ cont = FALSE; @@ -3065,8 +3066,7 @@ gst_base_parse_locate_time (GstBaseParse * parse, GstClockTime * _time, break; } else if (newtime > time) { /* overshoot */ - newpos -= newpos == hpos ? chunk : 0; - hpos = CLAMP (newpos, lpos, hpos); + hpos = (newpos >= hpos) ? MAX (lpos, hpos - chunk) : MAX (lpos, newpos); htime = newtime; } else if (newtime + tolerance > time) { /* close enough undershoot */ @@ -3076,9 +3076,10 @@ gst_base_parse_locate_time (GstBaseParse * parse, GstClockTime * _time, } else if (newtime < ltime) { /* so a position beyond lpos resulted in earlier time than ltime ... */ GST_DEBUG_OBJECT (parse, "non-ascending time; aborting"); + break; } else { /* undershoot too far */ - newpos += newpos == hpos ? chunk : 0; + newpos += newpos == lpos ? chunk : 0; lpos = CLAMP (newpos, lpos, hpos); ltime = newtime; } From 6395b4590886cf8d02d7198f8c4968c19a137848 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Tue, 25 Jan 2011 18:10:18 -0300 Subject: [PATCH 332/448] camerabin2: Handle videosink states more carefully When going to ready, camerabin2 could create an empty file if the videosink was put to ready. This patch only puts videosink to ready on the PAUSED_TO_READY state change if it is on PAUSED or PLAYING. --- gst/camerabin2/gstcamerabin2.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gst/camerabin2/gstcamerabin2.c b/gst/camerabin2/gstcamerabin2.c index 8b82c7fbb8..22d37e9937 100644 --- a/gst/camerabin2/gstcamerabin2.c +++ b/gst/camerabin2/gstcamerabin2.c @@ -630,8 +630,10 @@ gst_camera_bin_change_state (GstElement * element, GstStateChange trans) switch (trans) { case GST_STATE_CHANGE_PAUSED_TO_READY: + if (GST_STATE (camera->videosink) >= GST_STATE_PAUSED) + gst_element_set_state (camera->videosink, GST_STATE_READY); + gst_tag_setter_reset_tags (GST_TAG_SETTER (camera)); - gst_element_set_state (camera->videosink, GST_STATE_READY); break; case GST_STATE_CHANGE_READY_TO_NULL: gst_element_set_state (camera->videosink, GST_STATE_NULL); From b66dde57464029735750f3c415cd402596cc550d Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Wed, 26 Jan 2011 10:54:53 -0300 Subject: [PATCH 333/448] camerabin2: Add names to some elements Adds names to instances of some elements to make debugging easier --- gst/camerabin2/camerabingeneral.c | 13 +++++++----- gst/camerabin2/camerabingeneral.h | 5 +++-- gst/camerabin2/gstimagecapturebin.c | 9 ++++---- gst/camerabin2/gstwrappercamerabinsrc.c | 28 +++++++++++++++++-------- 4 files changed, 35 insertions(+), 20 deletions(-) diff --git a/gst/camerabin2/camerabingeneral.c b/gst/camerabin2/camerabingeneral.c index a354075b5e..d6c1c86744 100644 --- a/gst/camerabin2/camerabingeneral.c +++ b/gst/camerabin2/camerabingeneral.c @@ -138,6 +138,7 @@ gst_camerabin_try_add_element (GstBin * bin, const gchar * srcpad, * gst_camerabin_create_and_add_element: * @bin: tries adding an element to this bin * @elem_name: name of the element to be created + * @instance_name: name of the instance of the element to be created * * Creates an element according to given name and * adds it to given @bin. Looks for an unconnected src pad @@ -146,14 +147,15 @@ gst_camerabin_try_add_element (GstBin * bin, const gchar * srcpad, * Returns: pointer to the new element if successful, NULL otherwise. */ GstElement * -gst_camerabin_create_and_add_element (GstBin * bin, const gchar * elem_name) +gst_camerabin_create_and_add_element (GstBin * bin, const gchar * elem_name, + const gchar * instance_name) { GstElement *new_elem; g_return_val_if_fail (bin, FALSE); g_return_val_if_fail (elem_name, FALSE); - new_elem = gst_element_factory_make (elem_name, NULL); + new_elem = gst_element_factory_make (elem_name, instance_name); if (!new_elem) { GST_ELEMENT_ERROR (bin, CORE, MISSING_PLUGIN, (NULL), ("could not create \"%s\" element.", elem_name)); @@ -187,7 +189,8 @@ try_element (GstElement * bin, GstElement * element, gboolean unref) GstElement * gst_camerabin_setup_default_element (GstBin * bin, GstElement * user_elem, - const gchar * auto_elem_name, const gchar * default_elem_name) + const gchar * auto_elem_name, const gchar * default_elem_name, + const gchar * instance_name) { GstElement *elem; @@ -197,13 +200,13 @@ gst_camerabin_setup_default_element (GstBin * bin, GstElement * user_elem, } else { /* only try fallback if no specific sink was chosen */ GST_DEBUG_OBJECT (bin, "trying %s", auto_elem_name); - elem = gst_element_factory_make (auto_elem_name, NULL); + elem = gst_element_factory_make (auto_elem_name, instance_name); elem = try_element (GST_ELEMENT_CAST (bin), elem, TRUE); if (elem == NULL) { /* if default sink from config.h is different then try it too */ if (strcmp (default_elem_name, auto_elem_name)) { GST_DEBUG_OBJECT (bin, "trying %s", default_elem_name); - elem = gst_element_factory_make (default_elem_name, NULL); + elem = gst_element_factory_make (default_elem_name, instance_name); elem = try_element (GST_ELEMENT_CAST (bin), elem, TRUE); } } diff --git a/gst/camerabin2/camerabingeneral.h b/gst/camerabin2/camerabingeneral.h index 096038b9a7..4e0812a994 100644 --- a/gst/camerabin2/camerabingeneral.h +++ b/gst/camerabin2/camerabingeneral.h @@ -43,9 +43,10 @@ gboolean gst_camerabin_try_add_element (GstBin * bin, const gchar * srcpad, GstE gboolean gst_camerabin_add_element (GstBin * bin, GstElement * new_elem); gboolean gst_camerabin_add_element_full (GstBin * bin, const gchar * srcpad, GstElement * new_elem, const gchar * dstpad); -GstElement *gst_camerabin_create_and_add_element (GstBin * bin, const gchar * elem_name); +GstElement *gst_camerabin_create_and_add_element (GstBin * bin, const gchar * elem_name, const gchar * instance_name); -GstElement * gst_camerabin_setup_default_element (GstBin * bin, GstElement *user_elem, const gchar *auto_elem_name, const gchar *default_elem_name); +GstElement * gst_camerabin_setup_default_element (GstBin * bin, GstElement *user_elem, const gchar *auto_elem_name, const gchar *default_elem_name, + const gchar * instance_elem_name); void gst_camerabin_remove_elements_from_bin (GstBin * bin); diff --git a/gst/camerabin2/gstimagecapturebin.c b/gst/camerabin2/gstimagecapturebin.c index 32419ef378..2a5bcdba8e 100644 --- a/gst/camerabin2/gstimagecapturebin.c +++ b/gst/camerabin2/gstimagecapturebin.c @@ -261,7 +261,7 @@ gst_image_capture_bin_create_elements (GstImageCaptureBin * imagebin) /* create elements */ colorspace = gst_camerabin_create_and_add_element (GST_BIN (imagebin), - DEFAULT_COLORSPACE); + DEFAULT_COLORSPACE, "imagebin-colorspace"); if (!colorspace) goto error; @@ -273,7 +273,7 @@ gst_image_capture_bin_create_elements (GstImageCaptureBin * imagebin) } else { imagebin->encoder = gst_camerabin_create_and_add_element (GST_BIN (imagebin), - DEFAULT_ENCODER); + DEFAULT_ENCODER, "imagebin-encoder"); if (!imagebin->encoder) goto error; } @@ -286,13 +286,14 @@ gst_image_capture_bin_create_elements (GstImageCaptureBin * imagebin) } else { imagebin->muxer = gst_camerabin_create_and_add_element (GST_BIN (imagebin), - DEFAULT_MUXER); + DEFAULT_MUXER, "imagebin-muxer"); if (!imagebin->muxer) goto error; } imagebin->sink = - gst_camerabin_create_and_add_element (GST_BIN (imagebin), DEFAULT_SINK); + gst_camerabin_create_and_add_element (GST_BIN (imagebin), DEFAULT_SINK, + "imagebin-sink"); if (!imagebin->sink) goto error; diff --git a/gst/camerabin2/gstwrappercamerabinsrc.c b/gst/camerabin2/gstwrappercamerabinsrc.c index afcd9518e7..66bad9af8e 100644 --- a/gst/camerabin2/gstwrappercamerabinsrc.c +++ b/gst/camerabin2/gstwrappercamerabinsrc.c @@ -298,7 +298,8 @@ gst_wrapper_camera_bin_src_construct_pipeline (GstBaseCameraSrc * bcamsrc) /* Add application set or default video src element */ if (!(self->src_vid_src = gst_camerabin_setup_default_element (cbin, - self->app_vid_src, "autovideosrc", DEFAULT_VIDEOSRC))) { + self->app_vid_src, "autovideosrc", DEFAULT_VIDEOSRC, + "camerasrc-real-src"))) { self->src_vid_src = NULL; goto done; } else { @@ -319,24 +320,30 @@ gst_wrapper_camera_bin_src_construct_pipeline (GstBaseCameraSrc * bcamsrc) gst_object_unref (pad); } - if (!gst_camerabin_create_and_add_element (cbin, "ffmpegcolorspace")) + if (!gst_camerabin_create_and_add_element (cbin, "ffmpegcolorspace", + "src-colorspace")) goto done; if (!(self->src_filter = - gst_camerabin_create_and_add_element (cbin, "capsfilter"))) + gst_camerabin_create_and_add_element (cbin, "capsfilter", + "src-capsfilter"))) goto done; if (!(self->src_zoom_crop = - gst_camerabin_create_and_add_element (cbin, "videocrop"))) + gst_camerabin_create_and_add_element (cbin, "videocrop", + "zoom-crop"))) goto done; if (!(self->src_zoom_scale = - gst_camerabin_create_and_add_element (cbin, "videoscale"))) + gst_camerabin_create_and_add_element (cbin, "videoscale", + "zoom-scale"))) goto done; if (!(self->src_zoom_filter = - gst_camerabin_create_and_add_element (cbin, "capsfilter"))) + gst_camerabin_create_and_add_element (cbin, "capsfilter", + "zoom-capsfilter"))) goto done; - if (!(tee = gst_camerabin_create_and_add_element (cbin, "tee"))) + if (!(tee = + gst_camerabin_create_and_add_element (cbin, "tee", "camerasrc-tee"))) goto done; /* viewfinder pad */ @@ -345,9 +352,12 @@ gst_wrapper_camera_bin_src_construct_pipeline (GstBaseCameraSrc * bcamsrc) gst_object_unref (vf_pad); /* the viewfinder should always work, so we add some converters to it */ - if (!gst_camerabin_create_and_add_element (cbin, "ffmpegcolorspace")) + if (!gst_camerabin_create_and_add_element (cbin, "ffmpegcolorspace", + "viewfinder-colorspace")) goto done; - if (!(videoscale = gst_camerabin_create_and_add_element (cbin, "videoscale"))) + if (!(videoscale = + gst_camerabin_create_and_add_element (cbin, "videoscale", + "viewfinder-scale"))) goto done; /* image/video pad from tee */ From 68bff617327a81126c292a32054c9386d63de327 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Wed, 26 Jan 2011 11:40:43 -0300 Subject: [PATCH 334/448] camerabin2: Do not forget to unref some stuff Cleanup properly by unrefing the encoding profile and preview caps --- gst/camerabin2/gstcamerabin2.c | 6 ++++++ gst/camerabin2/gstwrappercamerabinsrc.c | 3 +++ 2 files changed, 9 insertions(+) diff --git a/gst/camerabin2/gstcamerabin2.c b/gst/camerabin2/gstcamerabin2.c index 22d37e9937..456a7ea261 100644 --- a/gst/camerabin2/gstcamerabin2.c +++ b/gst/camerabin2/gstcamerabin2.c @@ -278,6 +278,12 @@ gst_camera_bin_dispose (GObject * object) if (camerabin->imagebin_capsfilter) gst_object_unref (camerabin->imagebin_capsfilter); + if (camerabin->video_profile) + gst_encoding_profile_unref (camerabin->video_profile); + + if (camerabin->preview_caps) + gst_caps_replace (&camerabin->preview_caps, NULL); + G_OBJECT_CLASS (parent_class)->dispose (object); } diff --git a/gst/camerabin2/gstwrappercamerabinsrc.c b/gst/camerabin2/gstwrappercamerabinsrc.c index 66bad9af8e..864373bdc3 100644 --- a/gst/camerabin2/gstwrappercamerabinsrc.c +++ b/gst/camerabin2/gstwrappercamerabinsrc.c @@ -71,6 +71,9 @@ gst_wrapper_camera_bin_src_dispose (GObject * object) self->preview_pipeline = NULL; } + if (self->preview_caps) + gst_caps_replace (&self->preview_caps, NULL); + G_OBJECT_CLASS (parent_class)->dispose (object); } From 86ae3777fda5c5123aafabb7369193fe593b0d90 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Wed, 26 Jan 2011 14:27:21 -0300 Subject: [PATCH 335/448] tests: camerabin2: Use the correct for limit There are 3 taglists to be tested, not 2 --- tests/check/elements/camerabin2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/check/elements/camerabin2.c b/tests/check/elements/camerabin2.c index b41fe0e5fa..23c9379944 100644 --- a/tests/check/elements/camerabin2.c +++ b/tests/check/elements/camerabin2.c @@ -846,7 +846,7 @@ GST_START_TEST (test_image_capture_with_tags) gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL); - for (i = 0; i < 2; i++) { + for (i = 0; i < 3; i++) { check_file_validity (IMAGE_FILENAME, i, taglists[i], 0, 0); gst_tag_list_free (taglists[i]); } From 5d754e549a1ceca38736ba675dc8601e579223ee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Wed, 26 Jan 2011 18:45:56 +0000 Subject: [PATCH 336/448] jp2kdec, jp2kenc: add support v308 (4:4:4 YUV) Because we can. --- ext/jp2k/gstjasperdec.c | 2 +- ext/jp2k/gstjasperenc.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/jp2k/gstjasperdec.c b/ext/jp2k/gstjasperdec.c index 588a98ff4d..595134c461 100644 --- a/ext/jp2k/gstjasperdec.c +++ b/ext/jp2k/gstjasperdec.c @@ -65,7 +65,7 @@ static GstStaticPadTemplate gst_jasper_dec_src_template = GST_STATIC_CAPS (GST_VIDEO_CAPS_RGB "; " GST_VIDEO_CAPS_BGR "; " GST_VIDEO_CAPS_RGBx "; " GST_VIDEO_CAPS_xRGB "; " GST_VIDEO_CAPS_BGRx "; " GST_VIDEO_CAPS_xBGR "; " - GST_VIDEO_CAPS_YUV ("{ I420, YV12, YUY2, UYVY, Y41B, Y42B }")) + GST_VIDEO_CAPS_YUV ("{ I420, YV12, YUY2, UYVY, Y41B, Y42B, v308 }")) ); static void gst_jasper_dec_set_property (GObject * object, guint prop_id, diff --git a/ext/jp2k/gstjasperenc.c b/ext/jp2k/gstjasperenc.c index a372be2ab8..27073e22a8 100644 --- a/ext/jp2k/gstjasperenc.c +++ b/ext/jp2k/gstjasperenc.c @@ -49,7 +49,7 @@ static GstStaticPadTemplate gst_jasper_enc_sink_template = GST_STATIC_CAPS (GST_VIDEO_CAPS_RGB "; " GST_VIDEO_CAPS_BGR "; " GST_VIDEO_CAPS_RGBx "; " GST_VIDEO_CAPS_xRGB "; " GST_VIDEO_CAPS_BGRx "; " GST_VIDEO_CAPS_xBGR "; " - GST_VIDEO_CAPS_YUV ("{ I420, YV12 }")) + GST_VIDEO_CAPS_YUV ("{ I420, YV12, v308 }")) ); static GstStaticPadTemplate gst_jasper_enc_src_template = From 44da64d86bb3da531bf9ebc32037af34635fa364 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Thu, 27 Jan 2011 17:29:12 +0100 Subject: [PATCH 337/448] basevideodecoder: Initialize some variables to make gcc 4.6 happy --- gst-libs/gst/video/gstbasevideodecoder.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst-libs/gst/video/gstbasevideodecoder.c b/gst-libs/gst/video/gstbasevideodecoder.c index bcad36717a..eba17a4cac 100644 --- a/gst-libs/gst/video/gstbasevideodecoder.c +++ b/gst-libs/gst/video/gstbasevideodecoder.c @@ -319,7 +319,7 @@ gst_base_video_decoder_src_event (GstPad * pad, GstEvent * event) GstSeekFlags flags; GstSeekType cur_type, stop_type; gint64 cur, stop; - gint64 tcur, tstop; + gint64 tcur = -1, tstop = -1; GST_DEBUG ("seek event"); From 36e037be6786eae66ab7f6520e23a3e57ed3640e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Thu, 27 Jan 2011 17:32:49 +0100 Subject: [PATCH 338/448] vdpau: Initialize some variables to make gcc 4.6 happy --- sys/vdpau/gstvdpvideopostprocess.c | 3 +++ sys/vdpau/h264/gstvdph264dec.c | 3 +-- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/sys/vdpau/gstvdpvideopostprocess.c b/sys/vdpau/gstvdpvideopostprocess.c index 1091c0e8c4..0b6f338705 100644 --- a/sys/vdpau/gstvdpvideopostprocess.c +++ b/sys/vdpau/gstvdpvideopostprocess.c @@ -248,6 +248,9 @@ gst_vdp_vpp_get_required_pictures (GstVdpVideoPostProcess * vpp) case GST_VDP_DEINTERLACE_METHOD_TEMPORAL_SPATIAL: ret = 2; break; + default: + g_assert_not_reached (); + break; } return ret; diff --git a/sys/vdpau/h264/gstvdph264dec.c b/sys/vdpau/h264/gstvdph264dec.c index 2a237b1500..4abc009616 100644 --- a/sys/vdpau/h264/gstvdph264dec.c +++ b/sys/vdpau/h264/gstvdph264dec.c @@ -168,8 +168,7 @@ gst_vdp_h264_dec_calculate_poc (GstVdpH264Dec * h264_dec, GstH264Slice * slice) { GstH264Picture *pic; GstH264Sequence *seq; - - guint poc; + guint poc = 0; pic = slice->picture; seq = pic->sequence; From fcd0f5cb7accf8b3b466f5567076a2da75f04f23 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Fri, 10 Dec 2010 14:40:05 +0100 Subject: [PATCH 339/448] baseparse: reduce locking ... which is either already mute and/or implicitly handled by STREAM_LOCK. --- gst/audioparsers/gstbaseparse.c | 27 +++------------------------ gst/audioparsers/gstbaseparse.h | 22 ---------------------- 2 files changed, 3 insertions(+), 46 deletions(-) diff --git a/gst/audioparsers/gstbaseparse.c b/gst/audioparsers/gstbaseparse.c index 927c3556ee..15455cee39 100644 --- a/gst/audioparsers/gstbaseparse.c +++ b/gst/audioparsers/gstbaseparse.c @@ -392,7 +392,6 @@ gst_base_parse_finalize (GObject * object) GstBaseParse *parse = GST_BASE_PARSE (object); GstEvent **p_ev; - g_mutex_free (parse->parse_lock); g_object_unref (parse->adapter); if (parse->pending_segment) { @@ -494,7 +493,6 @@ gst_base_parse_init (GstBaseParse * parse, GstBaseParseClass * bclass) gst_element_add_pad (GST_ELEMENT (parse), parse->srcpad); GST_DEBUG_OBJECT (parse, "src created"); - parse->parse_lock = g_mutex_new (); parse->adapter = gst_adapter_new (); parse->priv->pad_mode = GST_ACTIVATE_NONE; @@ -1909,9 +1907,7 @@ gst_base_parse_chain (GstPad * pad, GstBuffer * buffer) /* Synchronization loop */ for (;;) { - GST_BASE_PARSE_LOCK (parse); min_size = parse->priv->min_frame_size; - GST_BASE_PARSE_UNLOCK (parse); if (G_UNLIKELY (parse->priv->drain)) { min_size = gst_adapter_available (parse->adapter); @@ -2182,9 +2178,7 @@ gst_base_parse_scan_frame (GstBaseParse * parse, GstBaseParseClass * klass, while (TRUE) { - GST_BASE_PARSE_LOCK (parse); min_size = parse->priv->min_frame_size; - GST_BASE_PARSE_UNLOCK (parse); ret = gst_base_parse_pull_range (parse, min_size, &buffer); if (ret != GST_FLOW_OK) @@ -2523,7 +2517,6 @@ gst_base_parse_set_duration (GstBaseParse * parse, { g_return_if_fail (parse != NULL); - GST_BASE_PARSE_LOCK (parse); if (parse->priv->upstream_has_duration) { GST_DEBUG_OBJECT (parse, "using upstream duration; discarding update"); goto exit; @@ -2549,7 +2542,7 @@ gst_base_parse_set_duration (GstBaseParse * parse, GST_DEBUG_OBJECT (parse, "set update interval: %d", interval); parse->priv->update_interval = interval; exit: - GST_BASE_PARSE_UNLOCK (parse); + return; } /** @@ -2588,10 +2581,8 @@ gst_base_parse_set_min_frame_size (GstBaseParse * parse, guint min_size) { g_return_if_fail (parse != NULL); - GST_BASE_PARSE_LOCK (parse); parse->priv->min_frame_size = min_size; GST_LOG_OBJECT (parse, "set frame_min_size: %d", min_size); - GST_BASE_PARSE_UNLOCK (parse); } /** @@ -2607,10 +2598,8 @@ gst_base_parse_set_passthrough (GstBaseParse * parse, gboolean passthrough) { g_return_if_fail (parse != NULL); - GST_BASE_PARSE_LOCK (parse); parse->priv->passthrough = passthrough; GST_LOG_OBJECT (parse, "set passthrough: %d", passthrough); - GST_BASE_PARSE_UNLOCK (parse); } /** @@ -2633,7 +2622,6 @@ gst_base_parse_set_frame_props (GstBaseParse * parse, guint fps_num, { g_return_if_fail (parse != NULL); - GST_BASE_PARSE_LOCK (parse); parse->priv->fps_num = fps_num; parse->priv->fps_den = fps_den; if (!fps_num || !fps_den) { @@ -2659,7 +2647,6 @@ gst_base_parse_set_frame_props (GstBaseParse * parse, guint fps_num, "lead out: %d frames = %" G_GUINT64_FORMAT " ms", lead_in, parse->priv->lead_in_ts / GST_MSECOND, lead_out, parse->priv->lead_out_ts / GST_MSECOND); - GST_BASE_PARSE_UNLOCK (parse); } /** @@ -2676,10 +2663,8 @@ gst_base_parse_get_sync (GstBaseParse * parse) g_return_val_if_fail (parse != NULL, FALSE); - GST_BASE_PARSE_LOCK (parse); /* losing sync is pretty much a discont (and vice versa), no ? */ ret = !parse->priv->discont; - GST_BASE_PARSE_UNLOCK (parse); GST_DEBUG_OBJECT (parse, "sync: %d", ret); return ret; @@ -2699,10 +2684,8 @@ gst_base_parse_get_drain (GstBaseParse * parse) g_return_val_if_fail (parse != NULL, FALSE); - GST_BASE_PARSE_LOCK (parse); /* losing sync is pretty much a discont (and vice versa), no ? */ ret = parse->priv->drain; - GST_BASE_PARSE_UNLOCK (parse); GST_DEBUG_OBJECT (parse, "drain: %d", ret); return ret; @@ -2784,7 +2767,7 @@ gst_base_parse_query (GstPad * pad, GstQuery * query) GST_DEBUG_OBJECT (parse, "position query"); gst_query_parse_position (query, &format, NULL); - g_mutex_lock (parse->parse_lock); + GST_OBJECT_LOCK (parse); if (format == GST_FORMAT_BYTES) { dest_value = parse->priv->offset; res = TRUE; @@ -2793,7 +2776,7 @@ gst_base_parse_query (GstPad * pad, GstQuery * query) dest_value = parse->segment.last_stop; res = TRUE; } - g_mutex_unlock (parse->parse_lock); + GST_OBJECT_UNLOCK (parse); if (res) gst_query_set_position (query, format, dest_value); @@ -2802,10 +2785,8 @@ gst_base_parse_query (GstPad * pad, GstQuery * query) if (!res) { /* no precise result, upstream no idea either, then best estimate */ /* priv->offset is updated in both PUSH/PULL modes */ - g_mutex_lock (parse->parse_lock); res = gst_base_parse_convert (parse, GST_FORMAT_BYTES, parse->priv->offset, format, &dest_value); - g_mutex_unlock (parse->parse_lock); } } break; @@ -2823,9 +2804,7 @@ gst_base_parse_query (GstPad * pad, GstQuery * query) /* otherwise best estimate from us */ if (!res) { - g_mutex_lock (parse->parse_lock); res = gst_base_parse_get_duration (parse, format, &duration); - g_mutex_unlock (parse->parse_lock); if (res) gst_query_set_duration (query, format, duration); } diff --git a/gst/audioparsers/gstbaseparse.h b/gst/audioparsers/gstbaseparse.h index 27547a9925..605bf843a1 100644 --- a/gst/audioparsers/gstbaseparse.h +++ b/gst/audioparsers/gstbaseparse.h @@ -110,26 +110,6 @@ G_BEGIN_DECLS */ #define GST_BASE_PARSE_BUFFER_FLAG_NO_FRAME GST_BUFFER_FLAG_LAST -/** - * GST_BASE_PARSE_LOCK: - * @obj: base parse instance - * - * Obtain a lock to protect the parse function from concurrent access. - * - * Since: 0.10.x - */ -#define GST_BASE_PARSE_LOCK(obj) g_mutex_lock (GST_BASE_PARSE_CAST (obj)->parse_lock) - -/** - * GST_BASE_PARSE_UNLOCK: - * @obj: base parse instance - * - * Release the lock that protects the parse function from concurrent access. - * - * Since: 0.10.x - */ -#define GST_BASE_PARSE_UNLOCK(obj) g_mutex_unlock (GST_BASE_PARSE_CAST (obj)->parse_lock) - /** * GstBaseParseSeekable: @@ -173,8 +153,6 @@ struct _GstBaseParse { /* Segment event that closes the running segment prior to SEEK */ GstEvent *close_segment; - GMutex *parse_lock; - /*< private >*/ gpointer _gst_reserved[GST_PADDING_LARGE]; GstBaseParsePrivate *priv; From 695c9599f4ff2fa586c8d62e39753cf92fa8f9a7 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Fri, 10 Dec 2010 14:56:13 +0100 Subject: [PATCH 340/448] baseparse: minor typo and debug statement cleanup --- gst/audioparsers/gstbaseparse.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/gst/audioparsers/gstbaseparse.c b/gst/audioparsers/gstbaseparse.c index 15455cee39..1dee0346e2 100644 --- a/gst/audioparsers/gstbaseparse.c +++ b/gst/audioparsers/gstbaseparse.c @@ -686,11 +686,11 @@ gst_base_parse_sink_event (GstPad * pad, GstEvent * event) gboolean handled = FALSE; gboolean ret = TRUE; - parse = GST_BASE_PARSE (gst_pad_get_parent (pad)); bclass = GST_BASE_PARSE_GET_CLASS (parse); - GST_DEBUG_OBJECT (parse, "handling event %d", GST_EVENT_TYPE (event)); + GST_DEBUG_OBJECT (parse, "handling event %d, %s", GST_EVENT_TYPE (event), + GST_EVENT_TYPE_NAME (event)); /* Cache all events except EOS, NEWSEGMENT and FLUSH_STOP if we have a * pending segment */ @@ -2397,7 +2397,7 @@ gst_base_parse_sink_activate (GstPad * sinkpad) /** * gst_base_parse_activate: * @parse: #GstBaseParse. - * @active: TRUE if element will be activated, FALSE if disactivated. + * @active: TRUE if element will be activated, FALSE if deactivated. * * Returns: TRUE if the operation succeeded. */ @@ -2564,6 +2564,7 @@ gst_base_parse_set_seek (GstBaseParse * parse, { parse->priv->seekable = seek; parse->priv->bitrate = bitrate; + GST_DEBUG_OBJECT (parse, "seek %d, bitrate %d", seek, bitrate); } From e54e2a9616fe759b09a6908bab4535d09bafbe6f Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Fri, 10 Dec 2010 15:59:49 +0100 Subject: [PATCH 341/448] baseparse: fix reverse playback handling --- gst/audioparsers/gstbaseparse.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/gst/audioparsers/gstbaseparse.c b/gst/audioparsers/gstbaseparse.c index 1dee0346e2..aee1c9af1d 100644 --- a/gst/audioparsers/gstbaseparse.c +++ b/gst/audioparsers/gstbaseparse.c @@ -2153,11 +2153,17 @@ gst_base_parse_handle_previous_fragment (GstBaseParse * parse) if (ret != GST_FLOW_OK) goto exit; + /* offset will increase again as fragment is processed/parsed */ + parse->priv->last_offset = offset; + gst_adapter_push (parse->adapter, buffer); ret = gst_base_parse_process_fragment (parse, FALSE); if (ret != GST_FLOW_OK) goto exit; + /* force previous fragment */ + parse->priv->offset = -1; + exit: return ret; } @@ -2275,7 +2281,9 @@ gst_base_parse_loop (GstPad * pad) * first fragment (closest to stop time) is handled normally below, * then we pull in fragments going backwards */ if (parse->segment.rate < 0.0) { - if (GST_CLOCK_TIME_IS_VALID (parse->priv->last_ts)) { + /* check if we jumped back to a previous fragment, + * which is a post-first fragment */ + if (parse->priv->offset < 0) { ret = gst_base_parse_handle_previous_fragment (parse); goto done; } @@ -2294,6 +2302,8 @@ gst_base_parse_loop (GstPad * pad) GST_DEBUG_OBJECT (parse, "downstream has reached end of segment"); /* push what was accumulated during loop run */ gst_base_parse_process_fragment (parse, TRUE); + /* force previous fragment */ + parse->priv->offset = -1; ret = GST_FLOW_OK; } From f4f7306e37bd9af1d0d083f88987921319603d36 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Thu, 6 Jan 2011 11:16:56 +0100 Subject: [PATCH 342/448] baseparse: pass all available data to subclass rather than minimum Also reduce some adapter calls and add a few debug statements. --- gst/audioparsers/gstbaseparse.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/gst/audioparsers/gstbaseparse.c b/gst/audioparsers/gstbaseparse.c index aee1c9af1d..c9493168ce 100644 --- a/gst/audioparsers/gstbaseparse.c +++ b/gst/audioparsers/gstbaseparse.c @@ -76,7 +76,7 @@ * #GstAdapter. * * - * A buffer of min_frame_size bytes is passed to subclass with + * A buffer of (at least) min_frame_size bytes is passed to subclass with * @check_valid_frame. Subclass checks the contents and returns TRUE * if the buffer contains a valid frame. It also needs to set the * @framesize according to the detected frame size. If buffer didn't @@ -1874,7 +1874,7 @@ gst_base_parse_chain (GstPad * pad, GstBuffer * buffer) guint fsize = 0; gint skip = -1; const guint8 *data; - guint min_size; + guint min_size, av; GstClockTime timestamp; parse = GST_BASE_PARSE (GST_OBJECT_PARENT (pad)); @@ -1908,9 +1908,10 @@ gst_base_parse_chain (GstPad * pad, GstBuffer * buffer) /* Synchronization loop */ for (;;) { min_size = parse->priv->min_frame_size; + av = gst_adapter_available (parse->adapter); if (G_UNLIKELY (parse->priv->drain)) { - min_size = gst_adapter_available (parse->adapter); + min_size = av; GST_DEBUG_OBJECT (parse, "draining, data left: %d", min_size); if (G_UNLIKELY (!min_size)) { gst_buffer_unref (tmpbuf); @@ -1919,14 +1920,15 @@ gst_base_parse_chain (GstPad * pad, GstBuffer * buffer) } /* Collect at least min_frame_size bytes */ - if (gst_adapter_available (parse->adapter) < min_size) { + if (av < min_size) { GST_DEBUG_OBJECT (parse, "not enough data available (only %d bytes)", - gst_adapter_available (parse->adapter)); + av); gst_buffer_unref (tmpbuf); goto done; } - data = gst_adapter_peek (parse->adapter, min_size); + /* always pass all available data */ + data = gst_adapter_peek (parse->adapter, av); GST_BUFFER_DATA (tmpbuf) = (guint8 *) data; GST_BUFFER_SIZE (tmpbuf) = min_size; GST_BUFFER_OFFSET (tmpbuf) = parse->priv->offset; @@ -1946,6 +1948,7 @@ gst_base_parse_chain (GstPad * pad, GstBuffer * buffer) gst_buffer_unref (tmpbuf); goto done; } + GST_LOG_OBJECT (parse, "valid frame of size %d at pos %d", fsize, skip); break; } if (skip == -1) { @@ -2203,6 +2206,7 @@ gst_base_parse_scan_frame (GstBaseParse * parse, GstBaseParseClass * klass, skip = -1; if (klass->check_valid_frame (parse, buffer, &fsize, &skip)) { parse->priv->drain = FALSE; + GST_LOG_OBJECT (parse, "valid frame of size %d at pos %d", fsize, skip); break; } parse->priv->drain = FALSE; From 18b69e9320b8cad133e0b4696c32bcd8ffacc6c6 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Fri, 14 Jan 2011 15:26:37 +0100 Subject: [PATCH 343/448] baesparse: fix refactor regression in loop based parsing --- gst/audioparsers/gstbaseparse.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/gst/audioparsers/gstbaseparse.c b/gst/audioparsers/gstbaseparse.c index c9493168ce..63ac08d458 100644 --- a/gst/audioparsers/gstbaseparse.c +++ b/gst/audioparsers/gstbaseparse.c @@ -2236,9 +2236,15 @@ gst_base_parse_scan_frame (GstBaseParse * parse, GstBaseParseClass * klass, } } - if (fsize <= GST_BUFFER_SIZE (buffer)) { - outbuf = gst_buffer_create_sub (buffer, 0, fsize); - GST_BUFFER_OFFSET (outbuf) = GST_BUFFER_OFFSET (buffer); + /* Does the subclass want to skip too? */ + if (skip > 0) + parse->priv->offset += skip; + else if (skip < 0) + skip = 0; + + if (fsize + skip <= GST_BUFFER_SIZE (buffer)) { + outbuf = gst_buffer_create_sub (buffer, skip, fsize); + GST_BUFFER_OFFSET (outbuf) = GST_BUFFER_OFFSET (buffer) + skip; GST_BUFFER_TIMESTAMP (outbuf) = GST_CLOCK_TIME_NONE; gst_buffer_unref (buffer); } else { @@ -2254,10 +2260,6 @@ gst_base_parse_scan_frame (GstBaseParse * parse, GstBaseParseClass * klass, parse->priv->offset += fsize; - /* Does the subclass want to skip too? */ - if (skip > 0) - parse->priv->offset += skip; - *buf = outbuf; done: From 829507b650fa907af2dbd651d29a63f68763700f Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Thu, 6 Jan 2011 11:41:44 +0100 Subject: [PATCH 344/448] baseparse: allow increasing min_size for current frame parsing only Also check that subclass actually either directs to skip bytes or increases expected frame size to avoid going nowhere in bogus indefinite looping. --- gst/audioparsers/gstbaseparse.c | 51 +++++++++++++++++++++++++++------ 1 file changed, 42 insertions(+), 9 deletions(-) diff --git a/gst/audioparsers/gstbaseparse.c b/gst/audioparsers/gstbaseparse.c index 63ac08d458..b8b4435210 100644 --- a/gst/audioparsers/gstbaseparse.c +++ b/gst/audioparsers/gstbaseparse.c @@ -82,7 +82,8 @@ * @framesize according to the detected frame size. If buffer didn't * contain a valid frame, this call must return FALSE and optionally * set the @skipsize value to inform base class that how many bytes - * it needs to skip in order to find a valid frame. The passed buffer + * it needs to skip in order to find a valid frame. @framesize can always + * indicate a new minimum for current frame parsing. The passed buffer * is read-only. Note that @check_valid_frame might receive any small * amount of input data when leftover data is being drained (e.g. at EOS). * @@ -1874,7 +1875,7 @@ gst_base_parse_chain (GstPad * pad, GstBuffer * buffer) guint fsize = 0; gint skip = -1; const guint8 *data; - guint min_size, av; + guint old_min_size = 0, min_size, av; GstClockTime timestamp; parse = GST_BASE_PARSE (GST_OBJECT_PARENT (pad)); @@ -1905,11 +1906,17 @@ gst_base_parse_chain (GstPad * pad, GstBuffer * buffer) while (!parse->priv->flushing) { tmpbuf = gst_buffer_new (); + old_min_size = 0; /* Synchronization loop */ for (;;) { - min_size = parse->priv->min_frame_size; + min_size = MAX (parse->priv->min_frame_size, fsize); av = gst_adapter_available (parse->adapter); + /* loop safety check */ + if (G_UNLIKELY (old_min_size >= min_size)) + goto invalid_min; + old_min_size = min_size; + if (G_UNLIKELY (parse->priv->drain)) { min_size = av; GST_DEBUG_OBJECT (parse, "draining, data left: %d", min_size); @@ -1975,10 +1982,11 @@ gst_base_parse_chain (GstPad * pad, GstBuffer * buffer) if (!parse->priv->discont) parse->priv->sync_offset = parse->priv->offset; parse->priv->discont = TRUE; + /* something changed least; nullify loop check */ + old_min_size = 0; } - /* There is a possibility that subclass set the skip value to zero. - This means that it has probably found a frame but wants to ask - more data (by increasing the min_size) to be sure of this. */ + /* skip == 0 should imply subclass set min_size to need more data; + * we check this shortly */ if ((ret = gst_base_parse_check_sync (parse)) != GST_FLOW_OK) { gst_buffer_unref (tmpbuf); goto done; @@ -2033,6 +2041,15 @@ gst_base_parse_chain (GstPad * pad, GstBuffer * buffer) done: GST_LOG_OBJECT (parse, "chain leaving"); return ret; + + /* ERRORS */ +invalid_min: + { + GST_ELEMENT_ERROR (parse, STREAM, FAILED, (NULL), + ("min_size evolution %d -> %d; breaking to avoid looping", + old_min_size, min_size)); + return GST_FLOW_ERROR; + } } /* pull @size bytes at current offset, @@ -2180,14 +2197,18 @@ gst_base_parse_scan_frame (GstBaseParse * parse, GstBaseParseClass * klass, { GstBuffer *buffer, *outbuf; GstFlowReturn ret = GST_FLOW_OK; - guint fsize = 0, min_size; + guint fsize = 0, min_size, old_min_size = 0; gint skip = 0; g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR); while (TRUE) { - min_size = parse->priv->min_frame_size; + min_size = MAX (parse->priv->min_frame_size, fsize); + /* loop safety check */ + if (G_UNLIKELY (old_min_size >= min_size)) + goto invalid_min; + old_min_size = min_size; ret = gst_base_parse_pull_range (parse, min_size, &buffer); if (ret != GST_FLOW_OK) @@ -2227,8 +2248,11 @@ gst_base_parse_scan_frame (GstBaseParse * parse, GstBaseParseClass * klass, if (!parse->priv->discont) parse->priv->sync_offset = parse->priv->offset; parse->priv->discont = TRUE; + /* something changed least; nullify loop check */ + old_min_size = 0; } - /* skip == 0 should imply subclass set min_size to need more data ... */ + /* skip == 0 should imply subclass set min_size to need more data; + * we check this shortly */ GST_DEBUG_OBJECT (parse, "finding sync..."); gst_buffer_unref (buffer); if ((ret = gst_base_parse_check_sync (parse)) != GST_FLOW_OK) { @@ -2264,6 +2288,15 @@ gst_base_parse_scan_frame (GstBaseParse * parse, GstBaseParseClass * klass, done: return ret; + + /* ERRORS */ +invalid_min: + { + GST_ELEMENT_ERROR (parse, STREAM, FAILED, (NULL), + ("min_size evolution %d -> %d; breaking to avoid looping", + old_min_size, min_size)); + return GST_FLOW_ERROR; + } } /** From 3e9d5c4bf8703ef8bdc8dda3aac344c53581eaac Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Fri, 7 Jan 2011 15:58:49 +0100 Subject: [PATCH 345/448] baseparse: update some documentation Also add some more debug. --- gst/audioparsers/gstbaseparse.c | 14 +++++++++++--- gst/audioparsers/gstbaseparse.h | 2 +- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/gst/audioparsers/gstbaseparse.c b/gst/audioparsers/gstbaseparse.c index b8b4435210..23a06e3ea4 100644 --- a/gst/audioparsers/gstbaseparse.c +++ b/gst/audioparsers/gstbaseparse.c @@ -90,7 +90,8 @@ * * After valid frame is found, it will be passed again to subclass with * @parse_frame call. Now subclass is responsible for parsing the - * frame contents and setting the caps, buffer timestamp and duration + * frame contents and setting the caps, and buffer metadata (e.g. + * buffer timestamp and duration, or keyframe if applicable). * (although the latter can also be done by GstBaseParse if it is * appropriately configured, see below). * @@ -2202,6 +2203,9 @@ gst_base_parse_scan_frame (GstBaseParse * parse, GstBaseParseClass * klass, g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR); + GST_LOG_OBJECT (parse, "scanning for frame at offset %" G_GUINT64_FORMAT + " (%#" G_GINT64_MODIFIER "x)", parse->priv->offset, parse->priv->offset); + while (TRUE) { min_size = MAX (parse->priv->min_frame_size, fsize); @@ -2640,8 +2644,12 @@ gst_base_parse_set_min_frame_size (GstBaseParse * parse, guint min_size) * @parse: the #GstBaseParse to set * @passthrough: boolean indicating passthrough mode. * - * Set passthrough mode for this parser. If operating in passthrough, - * incoming buffers are pushed through unmodified. + * Set passthrough mode for this parser (which only applies operating in pull + * mode). If operating in passthrough, incoming buffers are pushed through + * unmodified. That is, no @check_valid_frame or @parse_frame callbacks + * will be invoked. On the ohter hand, @pre_push_buffer is still invoked, + * where subclass can perform as much or as little is appropriate for + * "passthrough" semantics. */ void gst_base_parse_set_passthrough (GstBaseParse * parse, gboolean passthrough) diff --git a/gst/audioparsers/gstbaseparse.h b/gst/audioparsers/gstbaseparse.h index 605bf843a1..6b45fd35bb 100644 --- a/gst/audioparsers/gstbaseparse.h +++ b/gst/audioparsers/gstbaseparse.h @@ -200,7 +200,7 @@ struct _GstBaseParse { * Called just prior to pushing a frame (after any pending * events have been sent) to give subclass a chance to perform * additional actions at this time (e.g. tag sending) or to - * decide whether this buffer should be dropped or no + * decide whether this buffer should be dropped or not * (e.g. custom segment clipping). * * Subclasses can override any of the available virtual methods or not, as From 400198b2cd2718f29c14ea1dc397af7ff01bc9f6 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Fri, 7 Jan 2011 16:39:51 +0100 Subject: [PATCH 346/448] baseparse: restrict duration scanning to pull mode and avoid extra set_caps call --- gst/audioparsers/gstbaseparse.c | 5 +++-- gst/audioparsers/gstbaseparse.h | 5 ----- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/gst/audioparsers/gstbaseparse.c b/gst/audioparsers/gstbaseparse.c index 23a06e3ea4..8f7a5d5238 100644 --- a/gst/audioparsers/gstbaseparse.c +++ b/gst/audioparsers/gstbaseparse.c @@ -1422,7 +1422,8 @@ gst_base_parse_handle_and_push_buffer (GstBaseParse * parse, /* check initial frame to determine if subclass/format can provide ts. * If so, that allows and enables extra seek and duration determining options */ if (G_UNLIKELY (parse->priv->first_frame_offset < 0 && ret == GST_FLOW_OK)) { - if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer)) { + if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) && + parse->priv->pad_mode == GST_ACTIVATE_PULL) { parse->priv->first_frame_offset = offset; parse->priv->first_frame_ts = GST_BUFFER_TIMESTAMP (buffer); GST_DEBUG_OBJECT (parse, "subclass provided ts %" GST_TIME_FORMAT @@ -3497,7 +3498,7 @@ gst_base_parse_sink_setcaps (GstPad * pad, GstCaps * caps) if (klass->set_sink_caps) res = klass->set_sink_caps (parse, caps); - return res && gst_pad_set_caps (pad, caps); + return res; } static void diff --git a/gst/audioparsers/gstbaseparse.h b/gst/audioparsers/gstbaseparse.h index 6b45fd35bb..5a4b67447a 100644 --- a/gst/audioparsers/gstbaseparse.h +++ b/gst/audioparsers/gstbaseparse.h @@ -234,11 +234,6 @@ struct _GstBaseParseClass { GstFormat dest_format, gint64 * dest_value); - gboolean (*find_frame) (GstBaseParse *parse, - GstFormat src_format, - gint64 src_value, - gint64 * dest_value); - gboolean (*event) (GstBaseParse *parse, GstEvent *event); From 1c89488c50501826ff1336e722ee0d1602c9715b Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Mon, 10 Jan 2011 15:34:48 +0100 Subject: [PATCH 347/448] baseparse: introduce a baseparse frame to serve as context ... and adjust subclass parsers accordingly --- gst/audioparsers/gstaacparse.c | 78 ++++------ gst/audioparsers/gstac3parse.c | 20 +-- gst/audioparsers/gstamrparse.c | 15 +- gst/audioparsers/gstbaseparse.c | 224 ++++++++++++++++----------- gst/audioparsers/gstbaseparse.h | 101 ++++++++---- gst/audioparsers/gstdcaparse.c | 20 +-- gst/audioparsers/gstflacparse.c | 66 ++++---- gst/audioparsers/gstmpegaudioparse.c | 34 ++-- 8 files changed, 324 insertions(+), 234 deletions(-) diff --git a/gst/audioparsers/gstaacparse.c b/gst/audioparsers/gstaacparse.c index 4dd2dc761b..140f5e4dff 100644 --- a/gst/audioparsers/gstaacparse.c +++ b/gst/audioparsers/gstaacparse.c @@ -77,10 +77,10 @@ static gboolean gst_aacparse_sink_setcaps (GstBaseParse * parse, GstCaps * caps); gboolean gst_aacparse_check_valid_frame (GstBaseParse * parse, - GstBuffer * buffer, guint * size, gint * skipsize); + GstBaseParseFrame * frame, guint * size, gint * skipsize); GstFlowReturn gst_aacparse_parse_frame (GstBaseParse * parse, - GstBuffer * buffer); + GstBaseParseFrame * frame); gboolean gst_aacparse_convert (GstBaseParse * parse, GstFormat src_format, @@ -147,8 +147,6 @@ gst_aacparse_class_init (GstAacParseClass * klass) parse_class->parse_frame = GST_DEBUG_FUNCPTR (gst_aacparse_parse_frame); parse_class->check_valid_frame = GST_DEBUG_FUNCPTR (gst_aacparse_check_valid_frame); - parse_class->get_frame_overhead = - GST_DEBUG_FUNCPTR (gst_aacparse_get_frame_overhead); } @@ -330,8 +328,8 @@ gst_aacparse_adts_get_frame_len (const guint8 * data) */ static gboolean gst_aacparse_check_adts_frame (GstAacParse * aacparse, - const guint8 * data, - const guint avail, guint * framesize, guint * needed_data) + const guint8 * data, const guint avail, gboolean drain, + guint * framesize, guint * needed_data) { if (G_UNLIKELY (avail < 2)) return FALSE; @@ -340,7 +338,7 @@ gst_aacparse_check_adts_frame (GstAacParse * aacparse, *framesize = gst_aacparse_adts_get_frame_len (data); /* In EOS mode this is enough. No need to examine the data further */ - if (gst_base_parse_get_drain (GST_BASE_PARSE (aacparse))) { + if (drain) { return TRUE; } @@ -408,7 +406,8 @@ gst_aacparse_parse_adts_header (GstAacParse * aacparse, const guint8 * data, */ static gboolean gst_aacparse_detect_stream (GstAacParse * aacparse, - const guint8 * data, const guint avail, guint * framesize, gint * skipsize) + const guint8 * data, const guint avail, gboolean drain, + guint * framesize, gint * skipsize) { gboolean found = FALSE; guint need_data = 0; @@ -444,7 +443,7 @@ gst_aacparse_detect_stream (GstAacParse * aacparse, return FALSE; } - if (gst_aacparse_check_adts_frame (aacparse, data, avail, + if (gst_aacparse_check_adts_frame (aacparse, data, avail, drain, framesize, &need_data)) { gint rate, channels; @@ -568,17 +567,19 @@ gst_aacparse_detect_stream (GstAacParse * aacparse, */ gboolean gst_aacparse_check_valid_frame (GstBaseParse * parse, - GstBuffer * buffer, guint * framesize, gint * skipsize) + GstBaseParseFrame * frame, guint * framesize, gint * skipsize) { const guint8 *data; GstAacParse *aacparse; gboolean ret = FALSE; gboolean sync; + GstBuffer *buffer; aacparse = GST_AACPARSE (parse); + buffer = frame->buffer; data = GST_BUFFER_DATA (buffer); - sync = gst_base_parse_get_sync (parse); + sync = GST_BASE_PARSE_FRAME_SYNC (frame); if (aacparse->header_type == DSPAAC_HEADER_ADIF || aacparse->header_type == DSPAAC_HEADER_NONE) { @@ -589,13 +590,14 @@ gst_aacparse_check_valid_frame (GstBaseParse * parse, } else if (aacparse->header_type == DSPAAC_HEADER_NOT_PARSED || sync == FALSE) { ret = gst_aacparse_detect_stream (aacparse, data, GST_BUFFER_SIZE (buffer), - framesize, skipsize); + GST_BASE_PARSE_FRAME_DRAIN (frame), framesize, skipsize); } else if (aacparse->header_type == DSPAAC_HEADER_ADTS) { guint needed_data = 1024; ret = gst_aacparse_check_adts_frame (aacparse, data, - GST_BUFFER_SIZE (buffer), framesize, &needed_data); + GST_BUFFER_SIZE (buffer), GST_BASE_PARSE_FRAME_DRAIN (frame), + framesize, &needed_data); if (!ret) { GST_DEBUG ("buffer didn't contain valid frame"); @@ -619,21 +621,39 @@ gst_aacparse_check_valid_frame (GstBaseParse * parse, * * Implementation of "parse_frame" vmethod in #GstBaseParse class. * + * Also determines frame overhead. + * ADTS streams have a 7 byte header in each frame. MP4 and ADIF streams don't have + * a per-frame header. + * + * We're making a couple of simplifying assumptions: + * + * 1. We count Program Configuration Elements rather than searching for them + * in the streams to discount them - the overhead is negligible. + * + * 2. We ignore CRC. This has a worst-case impact of (num_raw_blocks + 1)*16 + * bits, which should still not be significant enough to warrant the + * additional parsing through the headers + * * Returns: GST_FLOW_OK if frame was successfully parsed and can be pushed * forward. Otherwise appropriate error is returned. */ GstFlowReturn -gst_aacparse_parse_frame (GstBaseParse * parse, GstBuffer * buffer) +gst_aacparse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame) { GstAacParse *aacparse; + GstBuffer *buffer; GstFlowReturn ret = GST_FLOW_OK; gint rate, channels; aacparse = GST_AACPARSE (parse); + buffer = frame->buffer; if (G_UNLIKELY (aacparse->header_type != DSPAAC_HEADER_ADTS)) return ret; + /* see above */ + frame->overhead = 7; + gst_aacparse_parse_adts_header (aacparse, GST_BUFFER_DATA (buffer), &rate, &channels, NULL, NULL); GST_LOG_OBJECT (aacparse, "rate: %d, chans: %d", rate, channels); @@ -692,33 +712,3 @@ gst_aacparse_stop (GstBaseParse * parse) GST_DEBUG ("stop"); return TRUE; } - - -/** - * gst_aacparse_get_frame_overhead: - * @parse: #GstBaseParse. - * @buffer: #GstBuffer. - * - * Implementation of "get_frame_overhead" vmethod in #GstBaseParse class. ADTS - * streams have a 7 byte header in each frame. MP4 and ADIF streams don't have - * a per-frame header. - * - * We're making a couple of simplifying assumptions: - * - * 1. We count Program Configuration Elements rather than searching for them - * in the streams to discount them - the overhead is negligible. - * - * 2. We ignore CRC. This has a worst-case impact of (num_raw_blocks + 1)*16 - * bits, which should still not be significant enough to warrant the - * additional parsing through the headers - */ -gint -gst_aacparse_get_frame_overhead (GstBaseParse * parse, GstBuffer * buffer) -{ - GstAacParse *aacparse = GST_AACPARSE (parse); - - if (aacparse->header_type == DSPAAC_HEADER_ADTS) - return 7; - else - return 0; -} diff --git a/gst/audioparsers/gstac3parse.c b/gst/audioparsers/gstac3parse.c index 7e3a8b49c7..0c7fba33cd 100644 --- a/gst/audioparsers/gstac3parse.c +++ b/gst/audioparsers/gstac3parse.c @@ -160,9 +160,9 @@ static void gst_ac3_parse_finalize (GObject * object); static gboolean gst_ac3_parse_start (GstBaseParse * parse); static gboolean gst_ac3_parse_stop (GstBaseParse * parse); static gboolean gst_ac3_parse_check_valid_frame (GstBaseParse * parse, - GstBuffer * buffer, guint * size, gint * skipsize); + GstBaseParseFrame * frame, guint * size, gint * skipsize); static GstFlowReturn gst_ac3_parse_parse_frame (GstBaseParse * parse, - GstBuffer * buf); + GstBaseParseFrame * frame); GST_BOILERPLATE (GstAc3Parse, gst_ac3_parse, GstBaseParse, GST_TYPE_BASE_PARSE); @@ -384,11 +384,12 @@ gst_ac3_parse_frame_header (GstAc3Parse * parse, GstBuffer * buf, } static gboolean -gst_ac3_parse_check_valid_frame (GstBaseParse * parse, GstBuffer * buf, - guint * framesize, gint * skipsize) +gst_ac3_parse_check_valid_frame (GstBaseParse * parse, + GstBaseParseFrame * frame, guint * framesize, gint * skipsize) { - GstByteReader reader = GST_BYTE_READER_INIT_FROM_BUFFER (buf); GstAc3Parse *ac3parse = GST_AC3_PARSE (parse); + GstBuffer *buf = frame->buffer; + GstByteReader reader = GST_BYTE_READER_INIT_FROM_BUFFER (buf); gint off; gboolean sync, drain; @@ -421,8 +422,8 @@ gst_ac3_parse_check_valid_frame (GstBaseParse * parse, GstBuffer * buf, GST_LOG_OBJECT (parse, "got frame"); - sync = gst_base_parse_get_sync (parse); - drain = gst_base_parse_get_drain (parse); + sync = GST_BASE_PARSE_FRAME_SYNC (frame); + drain = GST_BASE_PARSE_FRAME_DRAIN (frame); if (!sync && !drain) { guint16 word = 0; @@ -451,9 +452,10 @@ gst_ac3_parse_check_valid_frame (GstBaseParse * parse, GstBuffer * buf, } static GstFlowReturn -gst_ac3_parse_parse_frame (GstBaseParse * parse, GstBuffer * buf) +gst_ac3_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame) { GstAc3Parse *ac3parse = GST_AC3_PARSE (parse); + GstBuffer *buf = frame->buffer; guint fsize, rate, chans, blocks, sid; gboolean eac; @@ -465,7 +467,7 @@ gst_ac3_parse_parse_frame (GstBaseParse * parse, GstBuffer * buf) if (G_UNLIKELY (sid)) { GST_LOG_OBJECT (parse, "sid: %d", sid); - GST_BUFFER_FLAG_SET (buf, GST_BASE_PARSE_BUFFER_FLAG_NO_FRAME); + frame->flags |= GST_BASE_PARSE_FRAME_FLAG_NO_FRAME; } if (G_UNLIKELY (ac3parse->sample_rate != rate || ac3parse->channels != chans diff --git a/gst/audioparsers/gstamrparse.c b/gst/audioparsers/gstamrparse.c index a182e765b4..191a0291b9 100644 --- a/gst/audioparsers/gstamrparse.c +++ b/gst/audioparsers/gstamrparse.c @@ -78,10 +78,10 @@ static gboolean gst_amrparse_sink_setcaps (GstBaseParse * parse, GstCaps * caps); gboolean gst_amrparse_check_valid_frame (GstBaseParse * parse, - GstBuffer * buffer, guint * framesize, gint * skipsize); + GstBaseParseFrame * frame, guint * framesize, gint * skipsize); GstFlowReturn gst_amrparse_parse_frame (GstBaseParse * parse, - GstBuffer * buffer); + GstBaseParseFrame * frame); #define _do_init(bla) \ GST_DEBUG_CATEGORY_INIT (gst_amrparse_debug, "amrparse", 0, \ @@ -267,13 +267,15 @@ gst_amrparse_parse_header (GstAmrParse * amrparse, */ gboolean gst_amrparse_check_valid_frame (GstBaseParse * parse, - GstBuffer * buffer, guint * framesize, gint * skipsize) + GstBaseParseFrame * frame, guint * framesize, gint * skipsize) { + GstBuffer *buffer; const guint8 *data; gint fsize, mode, dsize; GstAmrParse *amrparse; amrparse = GST_AMRPARSE (parse); + buffer = frame->buffer; data = GST_BUFFER_DATA (buffer); dsize = GST_BUFFER_SIZE (buffer); @@ -305,8 +307,8 @@ gst_amrparse_check_valid_frame (GstBaseParse * parse, * to contain a valid header as well (and there is enough data to * perform this check) */ - if (gst_base_parse_get_sync (parse) || gst_base_parse_get_drain (parse) || - (dsize >= fsize && (data[fsize] & 0x83) == 0)) { + if (GST_BASE_PARSE_FRAME_SYNC (frame) || GST_BASE_PARSE_FRAME_DRAIN (frame) + || (dsize >= fsize && (data[fsize] & 0x83) == 0)) { *framesize = fsize; return TRUE; } @@ -327,9 +329,8 @@ gst_amrparse_check_valid_frame (GstBaseParse * parse, * Returns: #GstFlowReturn defining the parsing status. */ GstFlowReturn -gst_amrparse_parse_frame (GstBaseParse * parse, GstBuffer * buffer) +gst_amrparse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame) { - gst_buffer_set_caps (buffer, GST_PAD_CAPS (parse->srcpad)); return GST_FLOW_OK; } diff --git a/gst/audioparsers/gstbaseparse.c b/gst/audioparsers/gstbaseparse.c index 8f7a5d5238..91898466f8 100644 --- a/gst/audioparsers/gstbaseparse.c +++ b/gst/audioparsers/gstbaseparse.c @@ -352,10 +352,9 @@ static GstFlowReturn gst_base_parse_chain (GstPad * pad, GstBuffer * buffer); static void gst_base_parse_loop (GstPad * pad); static gboolean gst_base_parse_check_frame (GstBaseParse * parse, - GstBuffer * buffer, guint * framesize, gint * skipsize); - + GstBaseParseFrame * frame, guint * framesize, gint * skipsize); static GstFlowReturn gst_base_parse_parse_frame (GstBaseParse * parse, - GstBuffer * buffer); + GstBaseParseFrame * frame); static gboolean gst_base_parse_sink_eventfunc (GstBaseParse * parse, GstEvent * event); @@ -504,6 +503,49 @@ gst_base_parse_init (GstBaseParse * parse, GstBaseParseClass * bclass) GST_DEBUG_OBJECT (parse, "init ok"); } +/** + * gst_base_parse_frame_init: + * @parse: #GstBaseParse. + * @fmt: #GstBaseParseFrame. + * + * Sets a #GstBaseParseFrame to initial state. Currently this means + * all fields are zero-ed. + */ +void +gst_base_parse_frame_init (GstBaseParse * parse, GstBaseParseFrame * frame) +{ + memset (frame, 0, sizeof (*frame)); +} + +/* clear == frame no longer to be used following this */ +static void +gst_base_parse_frame_clear (GstBaseParse * parse, GstBaseParseFrame * frame) +{ + /* limited for now */ + if (frame->buffer) { + gst_buffer_unref (frame->buffer); + frame->buffer = NULL; + } +} + +static inline void +gst_base_parse_frame_update (GstBaseParse * parse, GstBaseParseFrame * frame, + GstBuffer * buf) +{ + gst_buffer_replace (&frame->buffer, buf); + if (parse->priv->drain) { + frame->flags |= GST_BASE_PARSE_FRAME_FLAG_DRAIN; + } else { + frame->flags &= ~(GST_BASE_PARSE_FRAME_FLAG_DRAIN); + } + /* losing sync is pretty much a discont (and vice versa), no ? */ + if (!parse->priv->discont) { + frame->flags |= GST_BASE_PARSE_FRAME_FLAG_SYNC; + } else { + frame->flags &= ~(GST_BASE_PARSE_FRAME_FLAG_SYNC); + } +} + static void gst_base_parse_reset (GstBaseParse * parse) { @@ -587,9 +629,9 @@ gst_base_parse_reset (GstBaseParse * parse) */ static gboolean gst_base_parse_check_frame (GstBaseParse * parse, - GstBuffer * buffer, guint * framesize, gint * skipsize) + GstBaseParseFrame * frame, guint * framesize, gint * skipsize) { - *framesize = GST_BUFFER_SIZE (buffer); + *framesize = GST_BUFFER_SIZE (frame->buffer); *skipsize = 0; return TRUE; } @@ -603,8 +645,10 @@ gst_base_parse_check_frame (GstBaseParse * parse, * Default callback for parse_frame. */ static GstFlowReturn -gst_base_parse_parse_frame (GstBaseParse * parse, GstBuffer * buffer) +gst_base_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame) { + GstBuffer *buffer = frame->buffer; + if (!GST_BUFFER_TIMESTAMP_IS_VALID (buffer) && GST_CLOCK_TIME_IS_VALID (parse->priv->next_ts)) { GST_BUFFER_TIMESTAMP (buffer) = parse->priv->next_ts; @@ -1114,23 +1158,22 @@ gst_base_parse_post_bitrates (GstBaseParse * parse, gboolean post_min, * running average bitrate of the stream so far. */ static void -gst_base_parse_update_bitrates (GstBaseParse * parse, GstBuffer * buffer) +gst_base_parse_update_bitrates (GstBaseParse * parse, GstBaseParseFrame * frame) { /* Only update the tag on a 10 kbps delta */ static const gint update_threshold = 10000; GstBaseParseClass *klass; guint64 data_len, frame_dur; - gint overhead = 0, frame_bitrate, old_avg_bitrate; + gint overhead, frame_bitrate, old_avg_bitrate; gboolean update_min = FALSE, update_avg = FALSE, update_max = FALSE; + GstBuffer *buffer = frame->buffer; klass = GST_BASE_PARSE_GET_CLASS (parse); - if (klass->get_frame_overhead) { - overhead = klass->get_frame_overhead (parse, buffer); - if (overhead == -1) - return; - } + overhead = frame->overhead; + if (overhead == -1) + return; data_len = GST_BUFFER_SIZE (buffer) - overhead; parse->priv->data_bytecount += data_len; @@ -1391,11 +1434,16 @@ gst_base_parse_check_media (GstBaseParse * parse) * Returns: #GstFlowReturn */ static GstFlowReturn -gst_base_parse_handle_and_push_buffer (GstBaseParse * parse, - GstBaseParseClass * klass, GstBuffer * buffer) +gst_base_parse_handle_and_push_frame (GstBaseParse * parse, + GstBaseParseClass * klass, GstBaseParseFrame * frame) { GstFlowReturn ret; gint64 offset; + GstBuffer *buffer; + + g_return_val_if_fail (frame != NULL, GST_FLOW_ERROR); + + buffer = frame->buffer; if (parse->priv->discont) { GST_DEBUG_OBJECT (parse, "marking DISCONT"); @@ -1417,7 +1465,11 @@ gst_base_parse_handle_and_push_buffer (GstBaseParse * parse, /* store offset as it might get overwritten */ offset = GST_BUFFER_OFFSET (buffer); - ret = klass->parse_frame (parse, buffer); + ret = klass->parse_frame (parse, frame); + /* sync */ + buffer = frame->buffer; + /* subclass must play nice */ + g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR); /* check initial frame to determine if subclass/format can provide ts. * If so, that allows and enables extra seek and duration determining options */ @@ -1446,7 +1498,7 @@ gst_base_parse_handle_and_push_buffer (GstBaseParse * parse, } /* re-use default handler to add missing metadata as-much-as-possible */ - gst_base_parse_parse_frame (parse, buffer); + gst_base_parse_parse_frame (parse, frame); if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) && GST_BUFFER_DURATION_IS_VALID (buffer)) { parse->priv->next_ts = @@ -1468,34 +1520,40 @@ gst_base_parse_handle_and_push_buffer (GstBaseParse * parse, * frames to decide on the format and queues them internally */ /* convert internal flow to OK and mark discont for the next buffer. */ if (ret == GST_BASE_PARSE_FLOW_DROPPED) { - gst_buffer_unref (buffer); + gst_base_parse_frame_clear (parse, frame); return GST_FLOW_OK; } else if (ret != GST_FLOW_OK) { return ret; } - return gst_base_parse_push_buffer (parse, buffer); + return gst_base_parse_push_frame (parse, frame); } /** - * gst_base_parse_push_buffer: + * gst_base_parse_push_frame: * @parse: #GstBaseParse. - * @buffer: #GstBuffer. + * @frame: #GstBaseParseFrame. * - * Pushes the buffer downstream, sends any pending events and + * Pushes the frame downstream, sends any pending events and * does some timestamp and segment handling. * - * This must be called with srcpad STREAM_LOCK held. + * This must be called with sinkpad STREAM_LOCK held. * * Returns: #GstFlowReturn */ GstFlowReturn -gst_base_parse_push_buffer (GstBaseParse * parse, GstBuffer * buffer) +gst_base_parse_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame) { GstFlowReturn ret = GST_FLOW_OK; GstClockTime last_start = GST_CLOCK_TIME_NONE; GstClockTime last_stop = GST_CLOCK_TIME_NONE; GstBaseParseClass *klass = GST_BASE_PARSE_GET_CLASS (parse); + GstBuffer *buffer; + + g_return_val_if_fail (frame != NULL, GST_FLOW_ERROR); + g_return_val_if_fail (frame->buffer != NULL, GST_FLOW_ERROR); + + buffer = frame->buffer; GST_LOG_OBJECT (parse, "processing buffer of size %d with ts %" GST_TIME_FORMAT @@ -1505,13 +1563,12 @@ gst_base_parse_push_buffer (GstBaseParse * parse, GstBuffer * buffer) /* update stats */ parse->priv->bytecount += GST_BUFFER_SIZE (buffer); - if (!GST_BUFFER_FLAG_IS_SET (buffer, GST_BASE_PARSE_BUFFER_FLAG_NO_FRAME)) { + if (G_LIKELY (!(frame->flags & GST_BASE_PARSE_FRAME_FLAG_NO_FRAME))) { parse->priv->framecount++; if (GST_BUFFER_DURATION_IS_VALID (buffer)) { parse->priv->acc_duration += GST_BUFFER_DURATION (buffer); } } - GST_BUFFER_FLAG_UNSET (buffer, GST_BASE_PARSE_BUFFER_FLAG_NO_FRAME); if (parse->priv->update_interval && (parse->priv->framecount % parse->priv->update_interval) == 0) gst_base_parse_update_duration (parse); @@ -1525,8 +1582,6 @@ gst_base_parse_push_buffer (GstBaseParse * parse, GstBuffer * buffer) /* should have caps by now */ g_return_val_if_fail (GST_PAD_CAPS (parse->srcpad), GST_FLOW_ERROR); - gst_buffer_set_caps (buffer, GST_PAD_CAPS (parse->srcpad)); - /* segment adjustment magic; only if we are running the whole show */ if (!parse->priv->passthrough && parse->segment.rate > 0.0 && (parse->priv->pad_mode == GST_ACTIVATE_PULL || @@ -1615,7 +1670,7 @@ gst_base_parse_push_buffer (GstBaseParse * parse, GstBuffer * buffer) /* update bitrates and optionally post corresponding tags * (following newsegment) */ - gst_base_parse_update_bitrates (parse, buffer); + gst_base_parse_update_bitrates (parse, frame); if (G_UNLIKELY (parse->priv->pending_events)) { GList *l; @@ -1627,15 +1682,26 @@ gst_base_parse_push_buffer (GstBaseParse * parse, GstBuffer * buffer) parse->priv->pending_events = NULL; } - if (klass->pre_push_buffer) - ret = klass->pre_push_buffer (parse, buffer); - else - ret = GST_BASE_PARSE_FLOW_CLIP; + if (klass->pre_push_frame) { + ret = klass->pre_push_frame (parse, frame); + } else { + frame->flags |= GST_BASE_PARSE_FRAME_FLAG_CLIP; + } + + /* take final ownership of frame buffer */ + buffer = frame->buffer; + frame->buffer = NULL; + + /* subclass must play nice */ + g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR); + + /* decorate */ + gst_buffer_set_caps (buffer, GST_PAD_CAPS (parse->srcpad)); parse->priv->seen_keyframe |= parse->priv->is_video && !GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT); - if (ret == GST_BASE_PARSE_FLOW_CLIP) { + if (frame->flags & GST_BASE_PARSE_FRAME_FLAG_CLIP) { if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) && GST_CLOCK_TIME_IS_VALID (parse->segment.stop) && GST_BUFFER_TIMESTAMP (buffer) > @@ -1693,6 +1759,8 @@ gst_base_parse_push_buffer (GstBaseParse * parse, GstBuffer * buffer) parse->segment.last_stop < last_stop) gst_segment_set_last_stop (&parse->segment, GST_FORMAT_TIME, last_stop); + gst_base_parse_frame_clear (parse, frame); + return ret; } @@ -1879,16 +1947,19 @@ gst_base_parse_chain (GstPad * pad, GstBuffer * buffer) const guint8 *data; guint old_min_size = 0, min_size, av; GstClockTime timestamp; + GstBaseParseFrame _frame = { 0, }; + GstBaseParseFrame *frame; parse = GST_BASE_PARSE (GST_OBJECT_PARENT (pad)); bclass = GST_BASE_PARSE_GET_CLASS (parse); + frame = &_frame; if (G_LIKELY (buffer)) { GST_LOG_OBJECT (parse, "buffer size: %d, offset = %" G_GINT64_FORMAT, GST_BUFFER_SIZE (buffer), GST_BUFFER_OFFSET (buffer)); if (G_UNLIKELY (parse->priv->passthrough)) { - buffer = gst_buffer_make_metadata_writable (buffer); - return gst_base_parse_push_buffer (parse, buffer); + frame->buffer = gst_buffer_make_metadata_writable (buffer); + return gst_base_parse_push_frame (parse, frame); } /* upstream feeding us in reverse playback; * gather each fragment, then process it in single run */ @@ -1906,6 +1977,8 @@ gst_base_parse_chain (GstPad * pad, GstBuffer * buffer) /* Parse and push as many frames as possible */ /* Stop either when adapter is empty or we are flushing */ while (!parse->priv->flushing) { + gboolean res; + tmpbuf = gst_buffer_new (); old_min_size = 0; @@ -1949,7 +2022,10 @@ gst_base_parse_chain (GstPad * pad, GstBuffer * buffer) } skip = -1; - if (bclass->check_valid_frame (parse, tmpbuf, &fsize, &skip)) { + gst_base_parse_frame_update (parse, frame, tmpbuf); + res = bclass->check_valid_frame (parse, frame, &fsize, &skip); + gst_buffer_replace (&frame->buffer, NULL); + if (res) { if (gst_adapter_available (parse->adapter) < fsize) { GST_DEBUG_OBJECT (parse, "found valid frame but not enough data available (only %d bytes)", @@ -2031,7 +2107,8 @@ gst_base_parse_chain (GstPad * pad, GstBuffer * buffer) parse->priv->prev_ts = parse->priv->next_ts = timestamp; } - ret = gst_base_parse_handle_and_push_buffer (parse, bclass, outbuf); + frame->buffer = outbuf; + ret = gst_base_parse_handle_and_push_frame (parse, bclass, frame); GST_PAD_STREAM_UNLOCK (parse->srcpad); if (ret != GST_FLOW_OK) { @@ -2195,19 +2272,20 @@ exit: * ajusts sync, drain and offset going along */ static GstFlowReturn gst_base_parse_scan_frame (GstBaseParse * parse, GstBaseParseClass * klass, - GstBuffer ** buf, gboolean full) + GstBaseParseFrame * frame, gboolean full) { GstBuffer *buffer, *outbuf; GstFlowReturn ret = GST_FLOW_OK; guint fsize = 0, min_size, old_min_size = 0; gint skip = 0; - g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR); + g_return_val_if_fail (frame != NULL, GST_FLOW_ERROR); GST_LOG_OBJECT (parse, "scanning for frame at offset %" G_GUINT64_FORMAT " (%#" G_GINT64_MODIFIER "x)", parse->priv->offset, parse->priv->offset); while (TRUE) { + gboolean res; min_size = MAX (parse->priv->min_frame_size, fsize); /* loop safety check */ @@ -2230,7 +2308,10 @@ gst_base_parse_scan_frame (GstBaseParse * parse, GstBaseParseClass * klass, parse->priv->drain = TRUE; skip = -1; - if (klass->check_valid_frame (parse, buffer, &fsize, &skip)) { + gst_base_parse_frame_update (parse, frame, buffer); + res = klass->check_valid_frame (parse, frame, &fsize, &skip); + gst_buffer_replace (&frame->buffer, NULL); + if (res) { parse->priv->drain = FALSE; GST_LOG_OBJECT (parse, "valid frame of size %d at pos %d", fsize, skip); break; @@ -2289,7 +2370,7 @@ gst_base_parse_scan_frame (GstBaseParse * parse, GstBaseParseClass * klass, parse->priv->offset += fsize; - *buf = outbuf; + frame->buffer = outbuf; done: return ret; @@ -2315,8 +2396,8 @@ gst_base_parse_loop (GstPad * pad) { GstBaseParse *parse; GstBaseParseClass *klass; - GstBuffer *outbuf; GstFlowReturn ret = GST_FLOW_OK; + GstBaseParseFrame frame = { 0, }; parse = GST_BASE_PARSE (gst_pad_get_parent (pad)); klass = GST_BASE_PARSE_GET_CLASS (parse); @@ -2333,12 +2414,12 @@ gst_base_parse_loop (GstPad * pad) } } - ret = gst_base_parse_scan_frame (parse, klass, &outbuf, TRUE); + ret = gst_base_parse_scan_frame (parse, klass, &frame, TRUE); if (ret != GST_FLOW_OK) goto done; - /* This always unrefs the outbuf, even if error occurs */ - ret = gst_base_parse_handle_and_push_buffer (parse, klass, outbuf); + /* This always cleans up frame, even if error occurs */ + ret = gst_base_parse_handle_and_push_frame (parse, klass, &frame); /* eat expected eos signalling past segment in reverse playback */ if (parse->segment.rate < 0.0 && ret == GST_FLOW_UNEXPECTED && @@ -2708,48 +2789,6 @@ gst_base_parse_set_frame_props (GstBaseParse * parse, guint fps_num, lead_out, parse->priv->lead_out_ts / GST_MSECOND); } -/** - * gst_base_parse_get_sync: - * @parse: the #GstBaseParse to query - * - * Returns: TRUE if parser is considered 'in sync'. That is, frames have been - * continuously successfully parsed and pushed. - */ -gboolean -gst_base_parse_get_sync (GstBaseParse * parse) -{ - gboolean ret; - - g_return_val_if_fail (parse != NULL, FALSE); - - /* losing sync is pretty much a discont (and vice versa), no ? */ - ret = !parse->priv->discont; - - GST_DEBUG_OBJECT (parse, "sync: %d", ret); - return ret; -} - -/** - * gst_base_parse_get_drain: - * @parse: the #GstBaseParse to query - * - * Returns: TRUE if parser is currently 'draining'. That is, leftover data - * (e.g. in FLUSH or EOS situation) is being parsed. - */ -gboolean -gst_base_parse_get_drain (GstBaseParse * parse) -{ - gboolean ret; - - g_return_val_if_fail (parse != NULL, FALSE); - - /* losing sync is pretty much a discont (and vice versa), no ? */ - ret = parse->priv->drain; - - GST_DEBUG_OBJECT (parse, "drain: %d", ret); - return ret; -} - static gboolean gst_base_parse_get_duration (GstBaseParse * parse, GstFormat format, GstClockTime * duration) @@ -2941,6 +2980,7 @@ gst_base_parse_find_frame (GstBaseParse * parse, gint64 * pos, gboolean orig_drain, orig_discont; GstFlowReturn ret = GST_FLOW_OK; GstBuffer *buf = NULL; + GstBaseParseFrame frame = { 0, }; g_return_val_if_fail (GST_FLOW_ERROR, pos != NULL); g_return_val_if_fail (GST_FLOW_ERROR, time != NULL); @@ -2961,10 +3001,11 @@ gst_base_parse_find_frame (GstBaseParse * parse, gint64 * pos, /* jump elsewhere and locate next frame */ parse->priv->offset = *pos; - ret = gst_base_parse_scan_frame (parse, klass, &buf, FALSE); + ret = gst_base_parse_scan_frame (parse, klass, &frame, FALSE); if (ret != GST_FLOW_OK) goto done; + buf = frame.buffer; GST_LOG_OBJECT (parse, "peek parsing frame at offset %" G_GUINT64_FORMAT " (%#" G_GINT64_MODIFIER "x) of size %d", @@ -2972,12 +3013,13 @@ gst_base_parse_find_frame (GstBaseParse * parse, gint64 * pos, /* get offset first, subclass parsing might dump other stuff in there */ *pos = GST_BUFFER_OFFSET (buf); - ret = klass->parse_frame (parse, buf); + ret = klass->parse_frame (parse, &frame); + buf = frame.buffer; /* but it should provide proper time */ *time = GST_BUFFER_TIMESTAMP (buf); *duration = GST_BUFFER_DURATION (buf); - gst_buffer_unref (buf); + gst_base_parse_frame_clear (parse, &frame); GST_LOG_OBJECT (parse, "frame with time %" GST_TIME_FORMAT " at offset %" G_GINT64_FORMAT, diff --git a/gst/audioparsers/gstbaseparse.h b/gst/audioparsers/gstbaseparse.h index 5a4b67447a..d5d4415a18 100644 --- a/gst/audioparsers/gstbaseparse.h +++ b/gst/audioparsers/gstbaseparse.h @@ -90,25 +90,78 @@ G_BEGIN_DECLS #define GST_BASE_PARSE_FLOW_DROPPED GST_FLOW_CUSTOM_SUCCESS /** - * GST_BASE_PARSE_FLOW_CLIP: + * GstBaseParseFrameFlags: + * @GST_BASE_PARSE_FRAME_FLAG_NONE: no flag + * @GST_BASE_PARSE_FRAME_FLAG_SYNC: indicates if parsing is 'in sync' + * @GST_BASE_PARSE_FRAME_FLAG_DRAIN: indicates if parser is 'draining'. + * That is, leftover data (e.g. in FLUSH or EOS situation) is being parsed. + * @GST_BASE_PARSE_FRAME_FLAG_NO_FRAME: set to indicate this buffer should not be + * counted as frame, e.g. if this frame is dependent on a previous one. + * As it is not counted as a frame, bitrate increases but frame to time + * conversions are maintained. + * @GST_BASE_PARSE_FRAME_FLAG_CLIP: @pre_push_buffer can set this to indicate + * that regular segment clipping can still be performed (as opposed to + * any custom one having been done). * - * A #GstFlowReturn that can be returned from pre_push_buffer to - * indicate that regular segment clipping should be performed. + * Flags to be used in a #GstBaseParseFrame. * * Since: 0.10.x */ -#define GST_BASE_PARSE_FLOW_CLIP GST_FLOW_CUSTOM_SUCCESS_1 +typedef enum { + GST_BASE_PARSE_FRAME_FLAG_NONE = 0, + GST_BASE_PARSE_FRAME_FLAG_SYNC = (1 << 0), + GST_BASE_PARSE_FRAME_FLAG_DRAIN = (1 << 1), + GST_BASE_PARSE_FRAME_FLAG_NO_FRAME = (1 << 2), + GST_BASE_PARSE_FRAME_FLAG_CLIP = (1 << 3) +} GstBaseParseFrameFlags; /** - * GST_BASE_PARSE_BUFFER_FLAG_NO_FRAME: + * GstBaseParseFrame: + * @buffer: data to check for valid frame or parsed frame. + * Subclass is allowed to replace this buffer. + * @overhead: subclass can set this to indicates the metadata overhead + * for the given frame, which is then used to enable more accurate bitrate + * computations. If this is -1, it is assumed that this frame should be + * skipped in bitrate calculation. + * @flags: a combination of input and output #GstBaseParseFrameFlags that + * convey additional context to subclass or allow subclass to tune + * subsequent #GstBaseParse actions. * - * A #GstBufferFlag that can be set to have this buffer not counted as frame, - * e.g. if this frame is dependent on a previous one. As it is not counted as - * a frame, bitrate increases but frame to time conversions are maintained. + * Frame (context) data passed to each frame parsing virtual methods. In + * addition to providing the data to be checked for a valid frame or an already + * identified frame, it conveys additional metadata or control information + * from and to the subclass w.r.t. the particular frame in question (rather + * than global parameters). Some of these may apply to each parsing stage, others + * only to some a particular one. These parameters are effectively zeroed at start + * of each frame's processing, i.e. parsing virtual method invocation sequence. * * Since: 0.10.x */ -#define GST_BASE_PARSE_BUFFER_FLAG_NO_FRAME GST_BUFFER_FLAG_LAST +typedef struct { + GstBuffer *buffer; + guint flags; + gint overhead; +} GstBaseParseFrame; + +/** + * GST_BASE_PARSE_FRAME_SYNC: + * @frame: base parse frame instance + * + * Obtains current sync status indicated in frame. + * + * Since: 0.10.x + */ +#define GST_BASE_PARSE_FRAME_SYNC(frame) (!!(frame->flags & GST_BASE_PARSE_FRAME_FLAG_SYNC)) + +/** + * GST_BASE_PARSE_FRAME_DRAIN: + * @frame: base parse frame instance + * + * Obtains current drain status indicated in frame. + * + * Since: 0.10.x + */ +#define GST_BASE_PARSE_FRAME_DRAIN(frame) (!!(frame->flags & GST_BASE_PARSE_FRAME_FLAG_DRAIN)) /** @@ -118,6 +171,8 @@ G_BEGIN_DECLS * GST_BASE_PARSE_SEEK_TABLE: Additional metadata provides more accurate seeking. * * Indicates what level (of quality) of seeking is possible. + * + * Since: 0.10.x */ typedef enum _GstBaseParseSeekable { GST_BASE_PARSE_SEEK_NONE, @@ -221,12 +276,15 @@ struct _GstBaseParseClass { GstCaps *caps); gboolean (*check_valid_frame) (GstBaseParse *parse, - GstBuffer *buffer, + GstBaseParseFrame *frame, guint *framesize, gint *skipsize); GstFlowReturn (*parse_frame) (GstBaseParse *parse, - GstBuffer *buffer); + GstBaseParseFrame *frame); + + GstFlowReturn (*pre_push_frame) (GstBaseParse *parse, + GstBaseParseFrame *frame); gboolean (*convert) (GstBaseParse * parse, GstFormat src_format, @@ -240,21 +298,16 @@ struct _GstBaseParseClass { gboolean (*src_event) (GstBaseParse *parse, GstEvent *event); - gint (*get_frame_overhead) (GstBaseParse *parse, - GstBuffer *buf); - - GstFlowReturn (*pre_push_buffer) (GstBaseParse *parse, - GstBuffer *buf); - /*< private >*/ - gpointer _gst_reserved[GST_PADDING_LARGE]; + gpointer _gst_reserved[GST_PADDING_LARGE]; }; GType gst_base_parse_get_type (void); +void gst_base_parse_frame_init (GstBaseParse * parse, GstBaseParseFrame * frame); -GstFlowReturn gst_base_parse_push_buffer (GstBaseParse *parse, - GstBuffer *buffer); +GstFlowReturn gst_base_parse_push_frame (GstBaseParse *parse, + GstBaseParseFrame *frame); void gst_base_parse_set_duration (GstBaseParse *parse, GstFormat fmt, gint64 duration, gint interval); @@ -262,17 +315,13 @@ void gst_base_parse_set_duration (GstBaseParse *parse, void gst_base_parse_set_seek (GstBaseParse * parse, GstBaseParseSeekable seek, guint bitrate); -void gst_base_parse_set_min_frame_size (GstBaseParse *parse, - guint min_size); +void gst_base_parse_set_min_frame_size (GstBaseParse *parse, guint min_size); + void gst_base_parse_set_passthrough (GstBaseParse * parse, gboolean passthrough); void gst_base_parse_set_frame_props (GstBaseParse * parse, guint fps_num, guint fps_den, guint lead_in, guint lead_out); -gboolean gst_base_parse_get_sync (GstBaseParse * parse); - -gboolean gst_base_parse_get_drain (GstBaseParse * parse); - gboolean gst_base_parse_convert_default (GstBaseParse * parse, GstFormat src_format, gint64 src_value, GstFormat dest_format, gint64 * dest_value); diff --git a/gst/audioparsers/gstdcaparse.c b/gst/audioparsers/gstdcaparse.c index 4573d3bbba..8ef6acd0ff 100644 --- a/gst/audioparsers/gstdcaparse.c +++ b/gst/audioparsers/gstdcaparse.c @@ -70,9 +70,9 @@ static void gst_dca_parse_finalize (GObject * object); static gboolean gst_dca_parse_start (GstBaseParse * parse); static gboolean gst_dca_parse_stop (GstBaseParse * parse); static gboolean gst_dca_parse_check_valid_frame (GstBaseParse * parse, - GstBuffer * buffer, guint * size, gint * skipsize); + GstBaseParseFrame * frame, guint * size, gint * skipsize); static GstFlowReturn gst_dca_parse_parse_frame (GstBaseParse * parse, - GstBuffer * buf); + GstBaseParseFrame * frame); GST_BOILERPLATE (GstDcaParse, gst_dca_parse, GstBaseParse, GST_TYPE_BASE_PARSE); @@ -289,11 +289,12 @@ gst_dca_parse_find_sync (GstDcaParse * dcaparse, GstByteReader * reader, } static gboolean -gst_dca_parse_check_valid_frame (GstBaseParse * parse, GstBuffer * buf, - guint * framesize, gint * skipsize) +gst_dca_parse_check_valid_frame (GstBaseParse * parse, + GstBaseParseFrame * frame, guint * framesize, gint * skipsize) { - GstByteReader r = GST_BYTE_READER_INIT_FROM_BUFFER (buf); GstDcaParse *dcaparse = GST_DCA_PARSE (parse); + GstBuffer *buf = frame->buffer; + GstByteReader r = GST_BYTE_READER_INIT_FROM_BUFFER (buf); gboolean parser_draining; gboolean parser_in_sync; guint32 sync = 0; @@ -303,7 +304,7 @@ gst_dca_parse_check_valid_frame (GstBaseParse * parse, GstBuffer * buf, if (G_UNLIKELY (GST_BUFFER_SIZE (buf) < 16)) return FALSE; - parser_in_sync = gst_base_parse_get_sync (parse); + parser_in_sync = GST_BASE_PARSE_FRAME_SYNC (frame); if (G_LIKELY (parser_in_sync && dcaparse->last_sync != 0)) { off = gst_byte_reader_masked_scan_uint32 (&r, 0xffffffff, @@ -343,7 +344,7 @@ gst_dca_parse_check_valid_frame (GstBaseParse * parse, GstBuffer * buf, dcaparse->last_sync = sync; - parser_draining = gst_base_parse_get_drain (parse); + parser_draining = GST_BASE_PARSE_FRAME_DRAIN (frame); if (!parser_in_sync && !parser_draining) { /* check for second frame to be sure */ @@ -377,10 +378,11 @@ gst_dca_parse_check_valid_frame (GstBaseParse * parse, GstBuffer * buf, } static GstFlowReturn -gst_dca_parse_parse_frame (GstBaseParse * parse, GstBuffer * buf) +gst_dca_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame) { - GstByteReader r = GST_BYTE_READER_INIT_FROM_BUFFER (buf); GstDcaParse *dcaparse = GST_DCA_PARSE (parse); + GstBuffer *buf = frame->buffer; + GstByteReader r = GST_BYTE_READER_INIT_FROM_BUFFER (buf); guint size, rate, chans, samples; if (!gst_dca_parse_parse_header (dcaparse, &r, &size, &rate, &chans, diff --git a/gst/audioparsers/gstflacparse.c b/gst/audioparsers/gstflacparse.c index 378caf4289..f991095f81 100644 --- a/gst/audioparsers/gstflacparse.c +++ b/gst/audioparsers/gstflacparse.c @@ -193,13 +193,11 @@ static void gst_flac_parse_get_property (GObject * object, guint prop_id, static gboolean gst_flac_parse_start (GstBaseParse * parse); static gboolean gst_flac_parse_stop (GstBaseParse * parse); static gboolean gst_flac_parse_check_valid_frame (GstBaseParse * parse, - GstBuffer * buffer, guint * framesize, gint * skipsize); + GstBaseParseFrame * frame, guint * framesize, gint * skipsize); static GstFlowReturn gst_flac_parse_parse_frame (GstBaseParse * parse, - GstBuffer * buffer); -static gint gst_flac_parse_get_frame_overhead (GstBaseParse * parse, - GstBuffer * buffer); -static GstFlowReturn gst_flac_parse_pre_push_buffer (GstBaseParse * parse, - GstBuffer * buf); + GstBaseParseFrame * frame); +static GstFlowReturn gst_flac_parse_pre_push_frame (GstBaseParse * parse, + GstBaseParseFrame * frame); GST_BOILERPLATE (GstFlacParse, gst_flac_parse, GstBaseParse, GST_TYPE_BASE_PARSE); @@ -244,10 +242,8 @@ gst_flac_parse_class_init (GstFlacParseClass * klass) baseparse_class->check_valid_frame = GST_DEBUG_FUNCPTR (gst_flac_parse_check_valid_frame); baseparse_class->parse_frame = GST_DEBUG_FUNCPTR (gst_flac_parse_parse_frame); - baseparse_class->get_frame_overhead = - GST_DEBUG_FUNCPTR (gst_flac_parse_get_frame_overhead); - baseparse_class->pre_push_buffer = - GST_DEBUG_FUNCPTR (gst_flac_parse_pre_push_buffer); + baseparse_class->pre_push_frame = + GST_DEBUG_FUNCPTR (gst_flac_parse_pre_push_frame); } static void @@ -563,15 +559,17 @@ need_more_data: } static gboolean -gst_flac_parse_frame_is_valid (GstFlacParse * flacparse, GstBuffer * buffer, - guint * ret) +gst_flac_parse_frame_is_valid (GstFlacParse * flacparse, + GstBaseParseFrame * frame, guint * ret) { + GstBuffer *buffer; const guint8 *data; guint max, size, remaining; guint i, search_start, search_end; FrameHeaderCheckReturn header_ret; guint16 block_size; + buffer = frame->buffer; data = GST_BUFFER_DATA (buffer); size = GST_BUFFER_SIZE (buffer); @@ -621,7 +619,7 @@ gst_flac_parse_frame_is_valid (GstFlacParse * flacparse, GstBuffer * buffer, } /* For the last frame output everything to the end */ - if (G_UNLIKELY (gst_base_parse_get_drain (GST_BASE_PARSE (flacparse)))) { + if (G_UNLIKELY (GST_BASE_PARSE_FRAME_DRAIN (frame))) { if (flacparse->check_frame_checksums) { guint16 actual_crc = gst_flac_calculate_crc16 (data, size - 2); guint16 expected_crc = GST_READ_UINT16_BE (data + size - 2); @@ -648,9 +646,10 @@ need_more: static gboolean gst_flac_parse_check_valid_frame (GstBaseParse * parse, - GstBuffer * buffer, guint * framesize, gint * skipsize) + GstBaseParseFrame * frame, guint * framesize, gint * skipsize) { GstFlacParse *flacparse = GST_FLAC_PARSE (parse); + GstBuffer *buffer = frame->buffer; const guint8 *data = GST_BUFFER_DATA (buffer); if (G_UNLIKELY (GST_BUFFER_SIZE (buffer) < 4)) @@ -689,13 +688,13 @@ gst_flac_parse_check_valid_frame (GstBaseParse * parse, flacparse->sample_number = 0; GST_DEBUG_OBJECT (flacparse, "Found sync code"); - ret = gst_flac_parse_frame_is_valid (flacparse, buffer, &next); + ret = gst_flac_parse_frame_is_valid (flacparse, frame, &next); if (ret) { *framesize = next; return TRUE; } else { /* If we're at EOS and the frame was not valid, drop it! */ - if (G_UNLIKELY (gst_base_parse_get_drain (parse))) { + if (G_UNLIKELY (GST_BASE_PARSE_FRAME_DRAIN (frame))) { GST_WARNING_OBJECT (flacparse, "EOS"); return FALSE; } @@ -1044,6 +1043,7 @@ push_headers: while (flacparse->headers) { GstBuffer *buf = GST_BUFFER (flacparse->headers->data); GstFlowReturn ret; + GstBaseParseFrame frame; flacparse->headers = g_list_delete_link (flacparse->headers, flacparse->headers); @@ -1051,7 +1051,11 @@ push_headers: gst_buffer_set_caps (buf, GST_PAD_CAPS (GST_BASE_PARSE_SRC_PAD (GST_BASE_PARSE (flacparse)))); - ret = gst_base_parse_push_buffer (GST_BASE_PARSE (flacparse), buf); + /* init, set and give away frame */ + gst_base_parse_frame_init (GST_BASE_PARSE (flacparse), &frame); + frame.buffer = buf; + frame.overhead = -1; + ret = gst_base_parse_push_frame (GST_BASE_PARSE (flacparse), &frame); if (ret != GST_FLOW_OK) { res = FALSE; break; @@ -1175,9 +1179,10 @@ gst_flac_parse_generate_headers (GstFlacParse * flacparse) } static GstFlowReturn -gst_flac_parse_parse_frame (GstBaseParse * parse, GstBuffer * buffer) +gst_flac_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame) { GstFlacParse *flacparse = GST_FLAC_PARSE (parse); + GstBuffer *buffer = frame->buffer; const guint8 *data = GST_BUFFER_DATA (buffer); if (flacparse->state == GST_FLAC_PARSE_STATE_INIT) { @@ -1312,6 +1317,11 @@ gst_flac_parse_parse_frame (GstBaseParse * parse, GstBuffer * buffer) GST_BUFFER_DURATION (buffer) = GST_BUFFER_OFFSET (buffer) - GST_BUFFER_TIMESTAMP (buffer); + /* To simplify, we just assume that it's a fixed size header and ignore + * subframe headers. The first could lead us to being off by 88 bits and + * the second even less, so the total inaccuracy is negligible. */ + frame->overhead = 7; + /* Minimal size of a frame header */ gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), MAX (9, flacparse->min_framesize)); @@ -1324,22 +1334,8 @@ gst_flac_parse_parse_frame (GstBaseParse * parse, GstBuffer * buffer) } } -static gint -gst_flac_parse_get_frame_overhead (GstBaseParse * parse, GstBuffer * buffer) -{ - GstFlacParse *flacparse = GST_FLAC_PARSE (parse); - - if (flacparse->state != GST_FLAC_PARSE_STATE_DATA) - return -1; - else - /* To simplify, we just assume that it's a fixed size header and ignore - * subframe headers. The first could lead us to being off by 88 bits and - * the second even less, so the total inaccuracy is negligible. */ - return 7; -} - static GstFlowReturn -gst_flac_parse_pre_push_buffer (GstBaseParse * parse, GstBuffer * buf) +gst_flac_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame) { GstFlacParse *flacparse = GST_FLAC_PARSE (parse); @@ -1349,5 +1345,7 @@ gst_flac_parse_pre_push_buffer (GstBaseParse * parse, GstBuffer * buf) flacparse->tags = NULL; } - return GST_BASE_PARSE_FLOW_CLIP; + frame->flags |= GST_BASE_PARSE_FRAME_FLAG_CLIP; + + return GST_FLOW_OK; } diff --git a/gst/audioparsers/gstmpegaudioparse.c b/gst/audioparsers/gstmpegaudioparse.c index 889efec1f2..d95f8aeaad 100644 --- a/gst/audioparsers/gstmpegaudioparse.c +++ b/gst/audioparsers/gstmpegaudioparse.c @@ -82,11 +82,11 @@ static void gst_mpeg_audio_parse_finalize (GObject * object); static gboolean gst_mpeg_audio_parse_start (GstBaseParse * parse); static gboolean gst_mpeg_audio_parse_stop (GstBaseParse * parse); static gboolean gst_mpeg_audio_parse_check_valid_frame (GstBaseParse * parse, - GstBuffer * buffer, guint * size, gint * skipsize); + GstBaseParseFrame * frame, guint * size, gint * skipsize); static GstFlowReturn gst_mpeg_audio_parse_parse_frame (GstBaseParse * parse, - GstBuffer * buf); -static GstFlowReturn gst_mpeg_audio_parse_pre_push_buffer (GstBaseParse * parse, - GstBuffer * buf); + GstBaseParseFrame * frame); +static GstFlowReturn gst_mpeg_audio_parse_pre_push_frame (GstBaseParse * parse, + GstBaseParseFrame * frame); static gboolean gst_mpeg_audio_parse_convert (GstBaseParse * parse, GstFormat src_format, gint64 src_value, GstFormat dest_format, gint64 * dest_value); @@ -164,8 +164,8 @@ gst_mpeg_audio_parse_class_init (GstMpegAudioParseClass * klass) GST_DEBUG_FUNCPTR (gst_mpeg_audio_parse_check_valid_frame); parse_class->parse_frame = GST_DEBUG_FUNCPTR (gst_mpeg_audio_parse_parse_frame); - parse_class->pre_push_buffer = - GST_DEBUG_FUNCPTR (gst_mpeg_audio_parse_pre_push_buffer); + parse_class->pre_push_frame = + GST_DEBUG_FUNCPTR (gst_mpeg_audio_parse_pre_push_frame); parse_class->convert = GST_DEBUG_FUNCPTR (gst_mpeg_audio_parse_convert); /* register tags */ @@ -470,11 +470,12 @@ gst_mpeg_audio_parse_head_check (GstMpegAudioParse * mp3parse, } static gboolean -gst_mpeg_audio_parse_check_valid_frame (GstBaseParse * parse, GstBuffer * buf, - guint * framesize, gint * skipsize) +gst_mpeg_audio_parse_check_valid_frame (GstBaseParse * parse, + GstBaseParseFrame * frame, guint * framesize, gint * skipsize) { - GstByteReader reader = GST_BYTE_READER_INIT_FROM_BUFFER (buf); GstMpegAudioParse *mp3parse = GST_MPEG_AUDIO_PARSE (parse); + GstBuffer *buf = frame->buffer; + GstByteReader reader = GST_BYTE_READER_INIT_FROM_BUFFER (buf); gint off, bpf; gboolean sync, drain, valid, caps_change; guint32 header; @@ -519,8 +520,8 @@ gst_mpeg_audio_parse_check_valid_frame (GstBaseParse * parse, GstBuffer * buf, else caps_change = FALSE; - sync = gst_base_parse_get_sync (parse); - drain = gst_base_parse_get_drain (parse); + sync = GST_BASE_PARSE_FRAME_SYNC (frame); + drain = GST_BASE_PARSE_FRAME_DRAIN (frame); if (!drain && (!sync || caps_change)) { if (!gst_mp3parse_validate_extended (mp3parse, buf, header, bpf, drain, @@ -900,9 +901,11 @@ gst_mpeg_audio_parse_handle_first_frame (GstMpegAudioParse * mp3parse, } static GstFlowReturn -gst_mpeg_audio_parse_parse_frame (GstBaseParse * parse, GstBuffer * buf) +gst_mpeg_audio_parse_parse_frame (GstBaseParse * parse, + GstBaseParseFrame * frame) { GstMpegAudioParse *mp3parse = GST_MPEG_AUDIO_PARSE (parse); + GstBuffer *buf = frame->buffer; guint bitrate, layer, rate, channels, version, mode, crc; g_return_val_if_fail (GST_BUFFER_SIZE (buf) >= 4, GST_FLOW_ERROR); @@ -1122,7 +1125,8 @@ gst_mpeg_audio_parse_convert (GstBaseParse * parse, GstFormat src_format, } static GstFlowReturn -gst_mpeg_audio_parse_pre_push_buffer (GstBaseParse * parse, GstBuffer * buf) +gst_mpeg_audio_parse_pre_push_frame (GstBaseParse * parse, + GstBaseParseFrame * frame) { GstMpegAudioParse *mp3parse = GST_MPEG_AUDIO_PARSE (parse); GstTagList *taglist; @@ -1188,5 +1192,7 @@ gst_mpeg_audio_parse_pre_push_buffer (GstBaseParse * parse, GstBuffer * buf) } /* usual clipping applies */ - return GST_BASE_PARSE_FLOW_CLIP; + frame->flags |= GST_BASE_PARSE_FRAME_FLAG_CLIP; + + return GST_FLOW_OK; } From 6a45c4f65ecde09cfd995e3439203a76734561fc Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Mon, 10 Jan 2011 16:56:36 +0100 Subject: [PATCH 348/448] baseparse: refactor passthrough into format flags Also add a format flag to signal baseparse that subclass/format can provide (parsed) timestamp rather than an estimated one. In particular, such "strong" timestamp then allows to e.g. determine duration. --- gst/audioparsers/gstaacparse.c | 7 ++--- gst/audioparsers/gstbaseparse.c | 45 +++++++++++++++++++-------------- gst/audioparsers/gstbaseparse.h | 28 +++++++++++++++++--- gst/audioparsers/gstflacparse.c | 3 +++ 4 files changed, 58 insertions(+), 25 deletions(-) diff --git a/gst/audioparsers/gstaacparse.c b/gst/audioparsers/gstaacparse.c index 140f5e4dff..09e3e71f2c 100644 --- a/gst/audioparsers/gstaacparse.c +++ b/gst/audioparsers/gstaacparse.c @@ -267,7 +267,8 @@ gst_aacparse_sink_setcaps (GstBaseParse * parse, GstCaps * caps) /* arrange for metadata and get out of the way */ gst_aacparse_set_src_caps (aacparse, caps); - gst_base_parse_set_passthrough (parse, TRUE); + gst_base_parse_set_format (parse, + GST_BASE_PARSE_FORMAT_PASSTHROUGH, TRUE); } else return FALSE; @@ -542,7 +543,8 @@ gst_aacparse_detect_stream (GstAacParse * aacparse, /* arrange for metadata and get out of the way */ gst_aacparse_set_src_caps (aacparse, GST_PAD_CAPS (GST_BASE_PARSE_SINK_PAD (aacparse))); - gst_base_parse_set_passthrough (GST_BASE_PARSE (aacparse), TRUE); + gst_base_parse_set_format (GST_BASE_PARSE (aacparse), + GST_BASE_PARSE_FORMAT_PASSTHROUGH, TRUE); *framesize = avail; return TRUE; @@ -693,7 +695,6 @@ gst_aacparse_start (GstBaseParse * parse) aacparse = GST_AACPARSE (parse); GST_DEBUG ("start"); gst_base_parse_set_min_frame_size (GST_BASE_PARSE (aacparse), 1024); - gst_base_parse_set_passthrough (parse, FALSE); return TRUE; } diff --git a/gst/audioparsers/gstbaseparse.c b/gst/audioparsers/gstbaseparse.c index 91898466f8..a4505c197b 100644 --- a/gst/audioparsers/gstbaseparse.c +++ b/gst/audioparsers/gstbaseparse.c @@ -158,7 +158,7 @@ * Update the duration information with @gst_base_parse_set_duration * * - * Optionally passthrough using @gst_base_parse_set_passthrough + * Optionally passthrough using @gst_base_parse_set_format * * * Configure various baseparse parameters using @gst_base_parse_set_seek and @@ -220,7 +220,7 @@ struct _GstBaseParsePrivate gint64 estimated_duration; guint min_frame_size; - gboolean passthrough; + guint format; guint fps_num, fps_den; guint update_interval; guint bitrate; @@ -294,6 +294,12 @@ typedef struct _GstBaseParseSeek GstClockTime start_ts; } GstBaseParseSeek; +#define GST_BASE_PARSE_PASSTHROUGH(parse) \ + (parse->priv->format & GST_BASE_PARSE_FORMAT_PASSTHROUGH) +#define GST_BASE_PARSE_HAS_TIME(parse) \ + (parse->priv->format & GST_BASE_PARSE_FORMAT_HAS_TIME) + + static GstElementClass *parent_class = NULL; static void gst_base_parse_class_init (GstBaseParseClass * klass); @@ -571,7 +577,7 @@ gst_base_parse_reset (GstBaseParse * parse) parse->priv->first_frame_offset = -1; parse->priv->estimated_duration = -1; parse->priv->next_ts = 0; - parse->priv->passthrough = FALSE; + parse->priv->format = 0; parse->priv->post_min_bitrate = TRUE; parse->priv->post_avg_bitrate = TRUE; parse->priv->post_max_bitrate = TRUE; @@ -1471,10 +1477,11 @@ gst_base_parse_handle_and_push_frame (GstBaseParse * parse, /* subclass must play nice */ g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR); - /* check initial frame to determine if subclass/format can provide ts. + /* check if subclass/format can provide ts. * If so, that allows and enables extra seek and duration determining options */ if (G_UNLIKELY (parse->priv->first_frame_offset < 0 && ret == GST_FLOW_OK)) { if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) && + GST_BASE_PARSE_HAS_TIME (parse) && parse->priv->pad_mode == GST_ACTIVATE_PULL) { parse->priv->first_frame_offset = offset; parse->priv->first_frame_ts = GST_BUFFER_TIMESTAMP (buffer); @@ -1583,7 +1590,7 @@ gst_base_parse_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame) g_return_val_if_fail (GST_PAD_CAPS (parse->srcpad), GST_FLOW_ERROR); /* segment adjustment magic; only if we are running the whole show */ - if (!parse->priv->passthrough && parse->segment.rate > 0.0 && + if (!GST_BASE_PARSE_PASSTHROUGH (parse) && parse->segment.rate > 0.0 && (parse->priv->pad_mode == GST_ACTIVATE_PULL || parse->priv->upstream_seekable)) { /* segment times are typically estimates, @@ -1748,7 +1755,7 @@ gst_base_parse_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame) GST_BUFFER_SIZE (buffer), gst_flow_get_name (ret)); /* if we are not sufficiently in control, let upstream decide on EOS */ if (ret == GST_FLOW_UNEXPECTED && - (parse->priv->passthrough || + (GST_BASE_PARSE_PASSTHROUGH (parse) || (parse->priv->pad_mode == GST_ACTIVATE_PUSH && !parse->priv->upstream_seekable))) ret = GST_FLOW_OK; @@ -1957,7 +1964,7 @@ gst_base_parse_chain (GstPad * pad, GstBuffer * buffer) if (G_LIKELY (buffer)) { GST_LOG_OBJECT (parse, "buffer size: %d, offset = %" G_GINT64_FORMAT, GST_BUFFER_SIZE (buffer), GST_BUFFER_OFFSET (buffer)); - if (G_UNLIKELY (parse->priv->passthrough)) { + if (G_UNLIKELY (GST_BASE_PARSE_PASSTHROUGH (parse))) { frame->buffer = gst_buffer_make_metadata_writable (buffer); return gst_base_parse_push_frame (parse, frame); } @@ -2722,24 +2729,24 @@ gst_base_parse_set_min_frame_size (GstBaseParse * parse, guint min_size) } /** - * gst_base_parse_set_passthrough: - * @parse: the #GstBaseParse to set - * @passthrough: boolean indicating passthrough mode. + * gst_base_parse_set_format: + * @parse: the #GstBaseParseFormat to set or unset + * @flags: format flag to enable or disable + * @on: whether or not to enable * - * Set passthrough mode for this parser (which only applies operating in pull - * mode). If operating in passthrough, incoming buffers are pushed through - * unmodified. That is, no @check_valid_frame or @parse_frame callbacks - * will be invoked. On the ohter hand, @pre_push_buffer is still invoked, - * where subclass can perform as much or as little is appropriate for - * "passthrough" semantics. + * Set flags describing characteristics of parsed format. */ void -gst_base_parse_set_passthrough (GstBaseParse * parse, gboolean passthrough) +gst_base_parse_set_format (GstBaseParse * parse, GstBaseParseFormat flag, + gboolean on) { g_return_if_fail (parse != NULL); - parse->priv->passthrough = passthrough; - GST_LOG_OBJECT (parse, "set passthrough: %d", passthrough); + GST_LOG_OBJECT (parse, "set flag %d to %d", flag, on); + if (on) + parse->priv->format |= flag; + else + parse->priv->format &= ~flag; } /** diff --git a/gst/audioparsers/gstbaseparse.h b/gst/audioparsers/gstbaseparse.h index d5d4415a18..0438c42134 100644 --- a/gst/audioparsers/gstbaseparse.h +++ b/gst/audioparsers/gstbaseparse.h @@ -163,12 +163,33 @@ typedef struct { */ #define GST_BASE_PARSE_FRAME_DRAIN(frame) (!!(frame->flags & GST_BASE_PARSE_FRAME_FLAG_DRAIN)) +/** + * GstBaseParseFormat: + * @GST_BASE_PARSE_FORMAT_NONE: default setting + * @GST_BASE_PARSE_FORMAT_PASSTHROUGH: nature of format or configuration + * does not allow (much) parsing, so parser should operate in passthrough mode + * (which only applies operating in pull mode). That is, incoming buffers + * are pushed through unmodified, i.e. no @check_valid_frame or @parse_frame + * callbacks will be invoked. On the other hand, @pre_push_buffer is still invoked, + * where subclass can perform as much or as little is appropriate for + * "passthrough" semantics. + * @GST_BASE_PARSE_FORMAT_HAS_TIME: frames carry timing info which subclass + * can (generally) parse and provide. In particular, intrinsic time + * (rather than estimated) can be obtained following seek. + * + * Since: 0.10.x + */ +typedef enum _GstBaseParseFormat { + GST_BASE_PARSE_FORMAT_NONE = 0, + GST_BASE_PARSE_FORMAT_PASSTHROUGH = (1 << 0), + GST_BASE_PARSE_FORMAT_HAS_TIME = (1 << 1), +} GstBaseParseFormat; /** * GstBaseParseSeekable: * @GST_BASE_PARSE_SEEK_NONE: No seeking possible. - * GST_BASE_PARSE_SEEK_DEFAULT: Default seeking possible using estimated bitrate. - * GST_BASE_PARSE_SEEK_TABLE: Additional metadata provides more accurate seeking. + * @GST_BASE_PARSE_SEEK_DEFAULT: Default seeking possible using estimated bitrate. + * @GST_BASE_PARSE_SEEK_TABLE: Additional metadata provides more accurate seeking. * * Indicates what level (of quality) of seeking is possible. * @@ -317,7 +338,8 @@ void gst_base_parse_set_seek (GstBaseParse * parse, void gst_base_parse_set_min_frame_size (GstBaseParse *parse, guint min_size); -void gst_base_parse_set_passthrough (GstBaseParse * parse, gboolean passthrough); +void gst_base_parse_set_format (GstBaseParse * parse, GstBaseParseFormat flag, + gboolean on); void gst_base_parse_set_frame_props (GstBaseParse * parse, guint fps_num, guint fps_den, guint lead_in, guint lead_out); diff --git a/gst/audioparsers/gstflacparse.c b/gst/audioparsers/gstflacparse.c index f991095f81..8306e8e8b1 100644 --- a/gst/audioparsers/gstflacparse.c +++ b/gst/audioparsers/gstflacparse.c @@ -326,6 +326,9 @@ gst_flac_parse_start (GstBaseParse * parse) /* "fLaC" marker */ gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), 4); + /* inform baseclass we can come up with ts, based on counters in packets */ + gst_base_parse_set_format (GST_BASE_PARSE (flacparse), + GST_BASE_PARSE_FORMAT_HAS_TIME, TRUE); return TRUE; } From 2c872ad91329862e65a4ce7b4fb48ecfacf369b3 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Mon, 10 Jan 2011 17:07:38 +0100 Subject: [PATCH 349/448] baseparse: provide some more initial frame metadata in parse_frame ... and document accordingly. --- gst/audioparsers/gstbaseparse.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/gst/audioparsers/gstbaseparse.c b/gst/audioparsers/gstbaseparse.c index a4505c197b..ac9d7f2e14 100644 --- a/gst/audioparsers/gstbaseparse.c +++ b/gst/audioparsers/gstbaseparse.c @@ -93,7 +93,10 @@ * frame contents and setting the caps, and buffer metadata (e.g. * buffer timestamp and duration, or keyframe if applicable). * (although the latter can also be done by GstBaseParse if it is - * appropriately configured, see below). + * appropriately configured, see below). Frame is provided with + * timestamp derived from upstream (as much as generally possible), + * duration obtained form configuration (see below), and offset + * if meaningful (in pull mode). * * * Finally the buffer can be pushed downstream and parsing loop starts @@ -1469,6 +1472,9 @@ gst_base_parse_handle_and_push_frame (GstBaseParse * parse, GST_BUFFER_OFFSET (buffer), GST_BUFFER_OFFSET (buffer), GST_BUFFER_SIZE (buffer)); + /* use default handler to provide initial (upstream) metadata */ + gst_base_parse_parse_frame (parse, frame); + /* store offset as it might get overwritten */ offset = GST_BUFFER_OFFSET (buffer); ret = klass->parse_frame (parse, frame); @@ -1504,7 +1510,8 @@ gst_base_parse_handle_and_push_frame (GstBaseParse * parse, } } - /* re-use default handler to add missing metadata as-much-as-possible */ + /* again use default handler to add missing metadata; + * we may have new information on frame properties */ gst_base_parse_parse_frame (parse, frame); if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) && GST_BUFFER_DURATION_IS_VALID (buffer)) { From 18b347296c6b3534a767dc0b282f6449e075cf55 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Mon, 10 Jan 2011 16:59:59 +0100 Subject: [PATCH 350/448] baseparse: header style cleaning --- gst/audioparsers/gstbaseparse.h | 52 +++++++++++++++++---------------- 1 file changed, 27 insertions(+), 25 deletions(-) diff --git a/gst/audioparsers/gstbaseparse.h b/gst/audioparsers/gstbaseparse.h index 0438c42134..82ec5f6fb8 100644 --- a/gst/audioparsers/gstbaseparse.h +++ b/gst/audioparsers/gstbaseparse.h @@ -46,7 +46,7 @@ G_BEGIN_DECLS * * the name of the templates for the source pad */ -#define GST_BASE_PARSE_SRC_NAME "src" +#define GST_BASE_PARSE_SRC_NAME "src" /** * GST_BASE_PARSE_SRC_PAD: @@ -56,7 +56,7 @@ G_BEGIN_DECLS * * Since: 0.10.x */ -#define GST_BASE_PARSE_SRC_PAD(obj) (GST_BASE_PARSE_CAST (obj)->srcpad) +#define GST_BASE_PARSE_SRC_PAD(obj) (GST_BASE_PARSE_CAST (obj)->srcpad) /** * GST_BASE_PARSE_SINK_PAD: @@ -87,7 +87,7 @@ G_BEGIN_DECLS * * Since: 0.10.x */ -#define GST_BASE_PARSE_FLOW_DROPPED GST_FLOW_CUSTOM_SUCCESS +#define GST_BASE_PARSE_FLOW_DROPPED GST_FLOW_CUSTOM_SUCCESS /** * GstBaseParseFrameFlags: @@ -325,31 +325,33 @@ struct _GstBaseParseClass { GType gst_base_parse_get_type (void); -void gst_base_parse_frame_init (GstBaseParse * parse, GstBaseParseFrame * frame); +void gst_base_parse_frame_init (GstBaseParse * parse, + GstBaseParseFrame * frame); +GstFlowReturn gst_base_parse_push_frame (GstBaseParse *parse, + GstBaseParseFrame *frame); -GstFlowReturn gst_base_parse_push_frame (GstBaseParse *parse, - GstBaseParseFrame *frame); +void gst_base_parse_set_duration (GstBaseParse *parse, + GstFormat fmt, gint64 duration, + gint interval); +void gst_base_parse_set_seek (GstBaseParse * parse, + GstBaseParseSeekable seek, + guint bitrate); +void gst_base_parse_set_min_frame_size (GstBaseParse *parse, + guint min_size); +void gst_base_parse_set_format (GstBaseParse * parse, + GstBaseParseFormat flag, + gboolean on); +void gst_base_parse_set_frame_props (GstBaseParse * parse, + guint fps_num, guint fps_den, + guint lead_in, guint lead_out); -void gst_base_parse_set_duration (GstBaseParse *parse, - GstFormat fmt, gint64 duration, gint interval); +gboolean gst_base_parse_convert_default (GstBaseParse * parse, + GstFormat src_format, gint64 src_value, + GstFormat dest_format, gint64 * dest_value); -void gst_base_parse_set_seek (GstBaseParse * parse, - GstBaseParseSeekable seek, guint bitrate); - -void gst_base_parse_set_min_frame_size (GstBaseParse *parse, guint min_size); - -void gst_base_parse_set_format (GstBaseParse * parse, GstBaseParseFormat flag, - gboolean on); - -void gst_base_parse_set_frame_props (GstBaseParse * parse, guint fps_num, - guint fps_den, guint lead_in, guint lead_out); - -gboolean gst_base_parse_convert_default (GstBaseParse * parse, - GstFormat src_format, gint64 src_value, - GstFormat dest_format, gint64 * dest_value); - -gboolean gst_base_parse_add_index_entry (GstBaseParse * parse, guint64 offset, - GstClockTime ts, gboolean key, gboolean force); +gboolean gst_base_parse_add_index_entry (GstBaseParse * parse, + guint64 offset, GstClockTime ts, + gboolean key, gboolean force); G_END_DECLS From f3da619dd2d42177afdf64580b0e182127fa1eee Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Tue, 11 Jan 2011 12:05:13 +0100 Subject: [PATCH 351/448] baseparse: arrange for consistent event handling --- gst/audioparsers/gstbaseparse.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/gst/audioparsers/gstbaseparse.c b/gst/audioparsers/gstbaseparse.c index ac9d7f2e14..887bb8bb9f 100644 --- a/gst/audioparsers/gstbaseparse.c +++ b/gst/audioparsers/gstbaseparse.c @@ -985,8 +985,6 @@ gst_base_parse_src_event (GstPad * pad, GstEvent * event) if (!handled) ret = gst_pad_event_default (pad, event); - else - gst_event_unref (event); gst_object_unref (parse); return ret; @@ -3273,11 +3271,12 @@ gst_base_parse_handle_seek (GstBaseParse * parse, GstEvent * event) * it fails upstream */ if (format != GST_FORMAT_TIME) { /* default action delegates to upstream */ - return FALSE; + res = FALSE; + goto done; } else { gst_event_ref (event); - if (gst_pad_push_event (parse->sinkpad, event)) { - return TRUE; + if ((res = gst_pad_push_event (parse->sinkpad, event))) { + goto done; } } @@ -3439,6 +3438,9 @@ gst_base_parse_handle_seek (GstBaseParse * parse, GstEvent * event) (GstTaskFunction) gst_base_parse_loop, parse->sinkpad); GST_PAD_STREAM_UNLOCK (parse->sinkpad); + + /* handled seek */ + res = TRUE; } else { GstEvent *new_event; GstBaseParseSeek *seek; @@ -3479,6 +3481,9 @@ gst_base_parse_handle_seek (GstBaseParse * parse, GstEvent * event) } done: + /* handled event is ours to free */ + if (res) + gst_event_unref (event); return res; /* ERRORS */ From 559b3ead9301556d070a1d343184202e57aa33ce Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Tue, 11 Jan 2011 15:22:51 +0100 Subject: [PATCH 352/448] baseparse: proper initial values for index tracking variables --- gst/audioparsers/gstbaseparse.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/gst/audioparsers/gstbaseparse.c b/gst/audioparsers/gstbaseparse.c index 887bb8bb9f..00b964953f 100644 --- a/gst/audioparsers/gstbaseparse.c +++ b/gst/audioparsers/gstbaseparse.c @@ -274,7 +274,7 @@ struct _GstBaseParsePrivate GstClockTimeDiff idx_interval; /* ts and offset of last entry added */ GstClockTime index_last_ts; - guint64 index_last_offset; + gint64 index_last_offset; gboolean index_last_valid; /* timestamps currently produced are accurate, e.g. started from 0 onwards */ @@ -589,8 +589,8 @@ gst_base_parse_reset (GstBaseParse * parse) parse->priv->avg_bitrate = 0; parse->priv->posted_avg_bitrate = 0; - parse->priv->index_last_ts = 0; - parse->priv->index_last_offset = 0; + parse->priv->index_last_ts = GST_CLOCK_TIME_NONE; + parse->priv->index_last_offset = -1; parse->priv->index_last_valid = TRUE; parse->priv->upstream_seekable = FALSE; parse->priv->upstream_size = 0; @@ -1283,13 +1283,14 @@ gst_base_parse_add_index_entry (GstBaseParse * parse, guint64 offset, /* FIXME need better helper data structure that handles these issues * related to ongoing collecting of index entries */ - if (parse->priv->index_last_offset >= offset) { + if (parse->priv->index_last_offset >= (gint64) offset) { GST_DEBUG_OBJECT (parse, "already have entries up to offset " "0x%08" G_GINT64_MODIFIER "x", parse->priv->index_last_offset); goto exit; } - if (GST_CLOCK_DIFF (parse->priv->index_last_ts, ts) < + if (GST_CLOCK_TIME_IS_VALID (parse->priv->index_last_ts) && + GST_CLOCK_DIFF (parse->priv->index_last_ts, ts) < parse->priv->idx_interval) { GST_DEBUG_OBJECT (parse, "entry too close to last time %" GST_TIME_FORMAT, GST_TIME_ARGS (parse->priv->index_last_ts)); From b97e560f1a77b3bed546e937bb02e0a4a73b2b31 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Tue, 11 Jan 2011 15:23:29 +0100 Subject: [PATCH 353/448] baseparse: need proper frame duration to obtain sensible frame bitrate --- gst/audioparsers/gstbaseparse.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/gst/audioparsers/gstbaseparse.c b/gst/audioparsers/gstbaseparse.c index 00b964953f..a0319d89f0 100644 --- a/gst/audioparsers/gstbaseparse.c +++ b/gst/audioparsers/gstbaseparse.c @@ -1206,7 +1206,10 @@ gst_base_parse_update_bitrates (GstBaseParse * parse, GstBaseParseFrame * frame) gst_base_parse_post_bitrates (parse, FALSE, TRUE, FALSE); } - frame_bitrate = (8 * data_len * GST_SECOND) / frame_dur; + if (frame_dur) + frame_bitrate = (8 * data_len * GST_SECOND) / frame_dur; + else + return; GST_LOG_OBJECT (parse, "frame bitrate %u, avg bitrate %u", frame_bitrate, parse->priv->avg_bitrate); From 16342223ee699a471ff0c39407f7ca4bb8cddcf1 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Tue, 11 Jan 2011 15:24:02 +0100 Subject: [PATCH 354/448] baseparse: properly track upstream timestamps ... rather than with a delay. --- gst/audioparsers/gstbaseparse.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/gst/audioparsers/gstbaseparse.c b/gst/audioparsers/gstbaseparse.c index a0319d89f0..ee62f10914 100644 --- a/gst/audioparsers/gstbaseparse.c +++ b/gst/audioparsers/gstbaseparse.c @@ -2106,6 +2106,14 @@ gst_base_parse_chain (GstPad * pad, GstBuffer * buffer) break; } + /* move along with upstream timestamp (if any), + * but interpolate in between */ + timestamp = gst_adapter_prev_timestamp (parse->adapter, NULL); + if (GST_CLOCK_TIME_IS_VALID (timestamp) && + (parse->priv->prev_ts != timestamp)) { + parse->priv->prev_ts = parse->priv->next_ts = timestamp; + } + /* FIXME: Would it be more efficient to make a subbuffer instead? */ outbuf = gst_adapter_take_buffer (parse->adapter, fsize); outbuf = gst_buffer_make_metadata_writable (outbuf); @@ -2114,14 +2122,7 @@ gst_base_parse_chain (GstPad * pad, GstBuffer * buffer) GST_BUFFER_OFFSET (outbuf) = parse->priv->offset; parse->priv->offset += fsize; GST_BUFFER_TIMESTAMP (outbuf) = GST_CLOCK_TIME_NONE; - - /* move along with upstream timestamp (if any), - * but interpolate in between */ - timestamp = gst_adapter_prev_timestamp (parse->adapter, NULL); - if (GST_CLOCK_TIME_IS_VALID (timestamp) && - (parse->priv->prev_ts != timestamp)) { - parse->priv->prev_ts = parse->priv->next_ts = timestamp; - } + GST_BUFFER_DURATION (outbuf) = GST_CLOCK_TIME_NONE; frame->buffer = outbuf; ret = gst_base_parse_handle_and_push_frame (parse, bclass, frame); From ac8080f0035e4539b6370d751e499c8cfbfe9bc4 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Tue, 11 Jan 2011 15:24:23 +0100 Subject: [PATCH 355/448] baseparse: clarify some debug statements --- gst/audioparsers/gstbaseparse.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/gst/audioparsers/gstbaseparse.c b/gst/audioparsers/gstbaseparse.c index ee62f10914..88ed92713d 100644 --- a/gst/audioparsers/gstbaseparse.c +++ b/gst/audioparsers/gstbaseparse.c @@ -2559,7 +2559,7 @@ gst_base_parse_activate (GstBaseParse * parse, gboolean active) GstBaseParseClass *klass; gboolean result = FALSE; - GST_DEBUG_OBJECT (parse, "activate"); + GST_DEBUG_OBJECT (parse, "activate %d", active); klass = GST_BASE_PARSE_GET_CLASS (parse); @@ -2577,7 +2577,7 @@ gst_base_parse_activate (GstBaseParse * parse, gboolean active) parse->priv->pad_mode = GST_ACTIVATE_NONE; } - GST_DEBUG_OBJECT (parse, "activate: %d", result); + GST_DEBUG_OBJECT (parse, "activate return: %d", result); return result; } @@ -2597,14 +2597,14 @@ gst_base_parse_sink_activate_push (GstPad * pad, gboolean active) parse = GST_BASE_PARSE (gst_pad_get_parent (pad)); - GST_DEBUG_OBJECT (parse, "sink activate push"); + GST_DEBUG_OBJECT (parse, "sink activate push %d", active); result = gst_base_parse_activate (parse, active); if (result) parse->priv->pad_mode = active ? GST_ACTIVATE_PUSH : GST_ACTIVATE_NONE; - GST_DEBUG_OBJECT (parse, "sink activate push: %d", result); + GST_DEBUG_OBJECT (parse, "sink activate push return: %d", result); gst_object_unref (parse); return result; @@ -2626,7 +2626,7 @@ gst_base_parse_sink_activate_pull (GstPad * sinkpad, gboolean active) parse = GST_BASE_PARSE (gst_pad_get_parent (sinkpad)); - GST_DEBUG_OBJECT (parse, "activate pull"); + GST_DEBUG_OBJECT (parse, "activate pull %d", active); result = gst_base_parse_activate (parse, active); @@ -2645,7 +2645,7 @@ gst_base_parse_sink_activate_pull (GstPad * sinkpad, gboolean active) if (result) parse->priv->pad_mode = active ? GST_ACTIVATE_PULL : GST_ACTIVATE_NONE; - GST_DEBUG_OBJECT (parse, "sink activate pull: %d", result); + GST_DEBUG_OBJECT (parse, "sink activate pull return: %d", result); gst_object_unref (parse); return result; From 3ba33399939efd4337e6787b66b691ef9cb3a66c Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Wed, 12 Jan 2011 14:40:37 +0100 Subject: [PATCH 356/448] baseparse: ensure non-empty candidate frames --- gst/audioparsers/gstbaseparse.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gst/audioparsers/gstbaseparse.c b/gst/audioparsers/gstbaseparse.c index 88ed92713d..c02541d4bd 100644 --- a/gst/audioparsers/gstbaseparse.c +++ b/gst/audioparsers/gstbaseparse.c @@ -1958,7 +1958,7 @@ gst_base_parse_chain (GstPad * pad, GstBuffer * buffer) GstFlowReturn ret = GST_FLOW_OK; GstBuffer *outbuf = NULL; GstBuffer *tmpbuf = NULL; - guint fsize = 0; + guint fsize = 1; gint skip = -1; const guint8 *data; guint old_min_size = 0, min_size, av; @@ -2293,7 +2293,7 @@ gst_base_parse_scan_frame (GstBaseParse * parse, GstBaseParseClass * klass, { GstBuffer *buffer, *outbuf; GstFlowReturn ret = GST_FLOW_OK; - guint fsize = 0, min_size, old_min_size = 0; + guint fsize = 1, min_size, old_min_size = 0; gint skip = 0; g_return_val_if_fail (frame != NULL, GST_FLOW_ERROR); From 57babfca39f9216268277580bec0249181a445f6 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Thu, 13 Jan 2011 15:26:21 +0100 Subject: [PATCH 357/448] amrparse: properly check for sufficient available data prior to access --- gst/audioparsers/gstamrparse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst/audioparsers/gstamrparse.c b/gst/audioparsers/gstamrparse.c index 191a0291b9..a668817ae5 100644 --- a/gst/audioparsers/gstamrparse.c +++ b/gst/audioparsers/gstamrparse.c @@ -308,7 +308,7 @@ gst_amrparse_check_valid_frame (GstBaseParse * parse, * perform this check) */ if (GST_BASE_PARSE_FRAME_SYNC (frame) || GST_BASE_PARSE_FRAME_DRAIN (frame) - || (dsize >= fsize && (data[fsize] & 0x83) == 0)) { + || (dsize > fsize && (data[fsize] & 0x83) == 0)) { *framesize = fsize; return TRUE; } From 479865c1b324b95f52da13bad2690834566f44d8 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Fri, 14 Jan 2011 15:16:04 +0100 Subject: [PATCH 358/448] baseparse: reverse playback; mind keyframes for fragment boundary --- gst/audioparsers/gstbaseparse.c | 110 ++++++++++++++++++++++++-------- 1 file changed, 82 insertions(+), 28 deletions(-) diff --git a/gst/audioparsers/gstbaseparse.c b/gst/audioparsers/gstbaseparse.c index c02541d4bd..ee3f2e9d7b 100644 --- a/gst/audioparsers/gstbaseparse.c +++ b/gst/audioparsers/gstbaseparse.c @@ -285,6 +285,7 @@ struct _GstBaseParsePrivate /* reverse playback */ GSList *buffers_pending; GSList *buffers_queued; + GSList *buffers_send; GstClockTime last_ts; gint64 last_offset; }; @@ -394,6 +395,9 @@ gst_base_parse_clear_queues (GstBaseParse * parse) NULL); g_slist_free (parse->priv->buffers_pending); parse->priv->buffers_pending = NULL; + g_slist_foreach (parse->priv->buffers_send, (GFunc) gst_buffer_unref, NULL); + g_slist_free (parse->priv->buffers_send); + parse->priv->buffers_send = NULL; } static void @@ -1816,6 +1820,50 @@ gst_base_parse_drain (GstBaseParse * parse) parse->priv->drain = FALSE; } +/** + * gst_base_parse_process_fragment: + * @parse: #GstBaseParse. + * + * Sends buffers collected in send_buffers downstream, and ensures that list + * is empty at the end (errors or not). + */ +static GstFlowReturn +gst_base_parse_send_buffers (GstBaseParse * parse) +{ + GSList *send = NULL; + GstBuffer *buf; + GstFlowReturn ret = GST_FLOW_OK; + + send = parse->priv->buffers_send; + + /* send buffers */ + while (send) { + buf = GST_BUFFER_CAST (send->data); + GST_LOG_OBJECT (parse, "pushing buffer %p, timestamp %" + GST_TIME_FORMAT ", duration %" GST_TIME_FORMAT + ", offset %" G_GINT64_FORMAT, buf, + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)), + GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_BUFFER_OFFSET (buf)); + + /* iterate output queue an push downstream */ + ret = gst_pad_push (parse->srcpad, buf); + send = g_slist_delete_link (send, send); + + /* clear any leftover if error */ + if (G_UNLIKELY (ret != GST_FLOW_OK)) { + while (send) { + buf = GST_BUFFER_CAST (send->data); + gst_buffer_unref (buf); + send = g_slist_delete_link (send, send); + } + } + } + + parse->priv->buffers_send = send; + + return ret; +} + /** * gst_base_parse_process_fragment: * @parse: #GstBaseParse. @@ -1831,7 +1879,7 @@ gst_base_parse_process_fragment (GstBaseParse * parse, gboolean push_only) { GstBuffer *buf; GstFlowReturn ret = GST_FLOW_OK; - GSList *send = NULL; + gboolean seen_key = FALSE, seen_delta = FALSE; if (push_only) goto push; @@ -1861,6 +1909,11 @@ gst_base_parse_process_fragment (GstBaseParse * parse, gboolean push_only) gst_base_parse_drain (parse); push: + if (parse->priv->buffers_send) { + buf = GST_BUFFER_CAST (parse->priv->buffers_send->data); + seen_key |= !GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT); + } + /* add metadata (if needed to queued buffers */ GST_LOG_OBJECT (parse, "last timestamp: %" GST_TIME_FORMAT, GST_TIME_ARGS (parse->priv->last_ts)); @@ -1885,38 +1938,39 @@ push: GST_WARNING_OBJECT (parse, "could not determine time for buffer"); } + parse->priv->last_ts = GST_BUFFER_TIMESTAMP (buf); + /* reverse order for ascending sending */ - send = g_slist_prepend (send, buf); + /* send downstream at keyframe not preceded by a keyframe + * (e.g. that should identify start of collection of IDR nals) */ + if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT)) { + if (seen_key) { + ret = gst_base_parse_send_buffers (parse); + /* if a problem, throw all to sending */ + if (ret != GST_FLOW_OK) { + parse->priv->buffers_send = + g_slist_reverse (parse->priv->buffers_queued); + parse->priv->buffers_queued = NULL; + break; + } + seen_key = FALSE; + } + } else { + seen_delta = TRUE; + } + + seen_key |= !GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT); + + parse->priv->buffers_send = + g_slist_prepend (parse->priv->buffers_send, buf); parse->priv->buffers_queued = g_slist_delete_link (parse->priv->buffers_queued, parse->priv->buffers_queued); } - /* send buffers */ - while (send) { - buf = GST_BUFFER_CAST (send->data); - GST_LOG_OBJECT (parse, "pushing buffer %p, timestamp %" - GST_TIME_FORMAT ", duration %" GST_TIME_FORMAT - ", offset %" G_GINT64_FORMAT, buf, - GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)), - GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_BUFFER_OFFSET (buf)); - - if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (parse->priv->last_ts))) - parse->priv->last_ts = GST_BUFFER_TIMESTAMP (buf); - - /* iterate output queue an push downstream */ - ret = gst_pad_push (parse->srcpad, buf); - send = g_slist_delete_link (send, send); - - /* clear any leftover if error */ - if (G_UNLIKELY (ret != GST_FLOW_OK)) { - while (send) { - buf = GST_BUFFER_CAST (send->data); - gst_buffer_unref (buf); - send = g_slist_delete_link (send, send); - } - } - } + /* audio may have all marked as keyframe, so arrange to send here */ + if (!seen_delta) + ret = gst_base_parse_send_buffers (parse); /* any trailing unused no longer usable (ideally none) */ if (G_UNLIKELY (gst_adapter_available (parse->adapter))) { @@ -3494,7 +3548,7 @@ done: /* ERRORS */ negative_rate: { - GST_DEBUG_OBJECT (parse, "negative playback rates are not supported yet."); + GST_DEBUG_OBJECT (parse, "negative playback rates delegated upstream."); res = FALSE; goto done; } From 7f805f17b2b6c6747ccdfd9b3d7ccbe26d4e4fd1 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Fri, 21 Jan 2011 14:53:39 +0100 Subject: [PATCH 359/448] baseparse: tune default duration estimate update interval Rather than a fixed default frame count, estimate frame count to aim for an interval duration depending on fps if available, otherwise use old fixed default. --- gst/audioparsers/gstbaseparse.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/gst/audioparsers/gstbaseparse.c b/gst/audioparsers/gstbaseparse.c index ee3f2e9d7b..5be6363384 100644 --- a/gst/audioparsers/gstbaseparse.c +++ b/gst/audioparsers/gstbaseparse.c @@ -225,7 +225,7 @@ struct _GstBaseParsePrivate guint min_frame_size; guint format; guint fps_num, fps_den; - guint update_interval; + gint update_interval; guint bitrate; guint lead_in, lead_out; GstClockTime lead_in_ts, lead_out_ts; @@ -570,7 +570,7 @@ gst_base_parse_reset (GstBaseParse * parse) parse->priv->flushing = FALSE; parse->priv->offset = 0; parse->priv->sync_offset = 0; - parse->priv->update_interval = 50; + parse->priv->update_interval = -1; parse->priv->fps_num = parse->priv->fps_den = 0; parse->priv->frame_duration = GST_CLOCK_TIME_NONE; parse->priv->lead_in = parse->priv->lead_out = 0; @@ -1127,8 +1127,12 @@ gst_base_parse_update_duration (GstBaseParse * aacparse) gst_object_unref (GST_OBJECT (peer)); if (qres) { if (gst_base_parse_convert (parse, pformat, ptot, - GST_FORMAT_TIME, &dest_value)) + GST_FORMAT_TIME, &dest_value)) { parse->priv->estimated_duration = dest_value; + GST_LOG_OBJECT (parse, + "updated estimated duration to %" GST_TIME_FORMAT, + GST_TIME_ARGS (dest_value)); + } } } } @@ -1589,7 +1593,10 @@ gst_base_parse_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame) parse->priv->acc_duration += GST_BUFFER_DURATION (buffer); } } - if (parse->priv->update_interval && + /* 0 means disabled */ + if (parse->priv->update_interval < 0) + parse->priv->update_interval = 50; + else if (parse->priv->update_interval > 0 && (parse->priv->framecount % parse->priv->update_interval) == 0) gst_base_parse_update_duration (parse); @@ -2851,6 +2858,12 @@ gst_base_parse_set_frame_props (GstBaseParse * parse, guint fps_num, gst_util_uint64_scale (GST_SECOND, fps_den * lead_in, fps_num); parse->priv->lead_out_ts = gst_util_uint64_scale (GST_SECOND, fps_den * lead_out, fps_num); + /* aim for about 1.5s to estimate duration */ + if (parse->priv->update_interval < 0) { + parse->priv->update_interval = fps_num * 3 / (fps_den * 2); + GST_LOG_OBJECT (parse, "estimated update interval to %d frames", + parse->priv->update_interval); + } } GST_LOG_OBJECT (parse, "set fps: %d/%d => duration: %" G_GINT64_FORMAT " ms", fps_num, fps_den, parse->priv->frame_duration / GST_MSECOND); From 8e4b8b813d742a094aefdf82b394106d9e33ab52 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Thu, 27 Jan 2011 16:52:34 +0100 Subject: [PATCH 360/448] ac3parse: improve handling of dependent substream frames In particular, timestamps of these should track main-stream timestamps. --- gst/audioparsers/gstac3parse.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/gst/audioparsers/gstac3parse.c b/gst/audioparsers/gstac3parse.c index 0c7fba33cd..e001bc37ec 100644 --- a/gst/audioparsers/gstac3parse.c +++ b/gst/audioparsers/gstac3parse.c @@ -466,8 +466,17 @@ gst_ac3_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame) GST_LOG_OBJECT (parse, "size: %u, rate: %u, chans: %u", fsize, rate, chans); if (G_UNLIKELY (sid)) { + /* dependent frame, no need to (ac)count for or consider further */ GST_LOG_OBJECT (parse, "sid: %d", sid); frame->flags |= GST_BASE_PARSE_FRAME_FLAG_NO_FRAME; + /* TODO maybe also mark as DELTA_UNIT, + * if that does not surprise baseparse elsewhere */ + /* occupies same time space as previous base frame */ + if (G_LIKELY (GST_BUFFER_TIMESTAMP (buf) >= GST_BUFFER_DURATION (buf))) + GST_BUFFER_TIMESTAMP (buf) -= GST_BUFFER_DURATION (buf); + /* only return if we already arranged for caps */ + if (G_LIKELY (ac3parse->sample_rate > 0)) + return GST_FLOW_OK; } if (G_UNLIKELY (ac3parse->sample_rate != rate || ac3parse->channels != chans From b33b88e4bb2d192f7064feb558e325813f4b06ba Mon Sep 17 00:00:00 2001 From: Arun Raghavan Date: Fri, 14 May 2010 02:08:03 +0530 Subject: [PATCH 361/448] h263parse: Add an h263parse element This adds an h263parse element for parsing H.263 streams, breaking them up into frame-sized buffers, and exporting metadata such as profile and level. https://bugzilla.gnome.org/show_bug.cgi?id=622276 --- configure.ac | 2 + gst/h263parse/Makefile.am | 9 + gst/h263parse/gstbaseparse.c | 3525 ++++++++++++++++++++++++++++++++++ gst/h263parse/gstbaseparse.h | 290 +++ gst/h263parse/gsth263parse.c | 328 ++++ gst/h263parse/gsth263parse.h | 94 + gst/h263parse/h263parse.c | 823 ++++++++ 7 files changed, 5071 insertions(+) create mode 100644 gst/h263parse/Makefile.am create mode 100644 gst/h263parse/gstbaseparse.c create mode 100644 gst/h263parse/gstbaseparse.h create mode 100644 gst/h263parse/gsth263parse.c create mode 100644 gst/h263parse/gsth263parse.h create mode 100644 gst/h263parse/h263parse.c diff --git a/configure.ac b/configure.ac index 36dc6a7015..e8ac029012 100644 --- a/configure.ac +++ b/configure.ac @@ -308,6 +308,7 @@ AG_GST_CHECK_PLUGIN(freeze) AG_GST_CHECK_PLUGIN(frei0r) AG_GST_CHECK_PLUGIN(gaudieffects) AG_GST_CHECK_PLUGIN(geometrictransform) +AG_GST_CHECK_PLUGIN(h263parse) AG_GST_CHECK_PLUGIN(h264parse) AG_GST_CHECK_PLUGIN(hdvparse) AG_GST_CHECK_PLUGIN(id3tag) @@ -1727,6 +1728,7 @@ gst/freeze/Makefile gst/frei0r/Makefile gst/gaudieffects/Makefile gst/geometrictransform/Makefile +gst/h263parse/Makefile gst/h264parse/Makefile gst/hdvparse/Makefile gst/id3tag/Makefile diff --git a/gst/h263parse/Makefile.am b/gst/h263parse/Makefile.am new file mode 100644 index 0000000000..3ea9c20020 --- /dev/null +++ b/gst/h263parse/Makefile.am @@ -0,0 +1,9 @@ +plugin_LTLIBRARIES = libgsth263parse.la + +libgsth263parse_la_SOURCES = h263parse.c gsth263parse.c gstbaseparse.c +libgsth263parse_la_CFLAGS = $(GST_CFLAGS) +libgsth263parse_la_LIBADD = $(GST_BASE_LIBS) $(GST_LIBS) +libgsth263parse_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) +libgsth263parse_la_LIBTOOLFLAGS = --tag=disable-static + +noinst_HEADERS = gsth263parse.h gstbaseparse.h diff --git a/gst/h263parse/gstbaseparse.c b/gst/h263parse/gstbaseparse.c new file mode 100644 index 0000000000..734119493a --- /dev/null +++ b/gst/h263parse/gstbaseparse.c @@ -0,0 +1,3525 @@ +/* GStreamer + * Copyright (C) 2008 Nokia Corporation. All rights reserved. + * Contact: Stefan Kost + * Copyright (C) 2008 Sebastian Dröge . + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/** + * SECTION:gstbaseparse + * @short_description: Base class for stream parsers + * @see_also: #GstBaseTransform + * + * This base class is for parser elements that process data and splits it + * into separate audio/video/whatever frames. + * + * It provides for: + * + * One sinkpad and one srcpad + * Handles state changes + * Does flushing + * Push mode + * Pull mode + * Handles events (NEWSEGMENT/EOS/FLUSH) + * Handles seeking in both modes + * + * Handles POSITION/DURATION/SEEKING/FORMAT/CONVERT queries + * + * + * + * The purpose of this base class is to provide a basic functionality of + * a parser and share a lot of rather complex code. + * + * Description of the parsing mechanism: + * + * + * Set-up phase + * + * GstBaseParse class calls @set_sink_caps to inform the subclass about + * incoming sinkpad caps. Subclass should set the srcpad caps accordingly. + * + * + * GstBaseParse calls @start to inform subclass that data processing is + * about to start now. + * + * + * At least in this point subclass needs to tell the GstBaseParse class + * how big data chunks it wants to receive (min_frame_size). It can do + * this with @gst_base_parse_set_min_frame_size. + * + * + * GstBaseParse class sets up appropriate data passing mode (pull/push) + * and starts to process the data. + * + * + * + * + * + * Parsing phase + * + * GstBaseParse gathers at least min_frame_size bytes of data either + * by pulling it from upstream or collecting buffers into internal + * #GstAdapter. + * + * + * A buffer of min_frame_size bytes is passed to subclass with + * @check_valid_frame. Subclass checks the contents and returns TRUE + * if the buffer contains a valid frame. It also needs to set the + * @framesize according to the detected frame size. If buffer didn't + * contain a valid frame, this call must return FALSE and optionally + * set the @skipsize value to inform base class that how many bytes + * it needs to skip in order to find a valid frame. The passed buffer + * is read-only. Note that @check_valid_frame might receive any small + * amount of input data when leftover data is being drained (e.g. at EOS). + * + * + * After valid frame is found, it will be passed again to subclass with + * @parse_frame call. Now subclass is responsible for parsing the + * frame contents and setting the caps, buffer timestamp and duration + * (although the latter can also be done by GstBaseParse if it is + * appropriately configured, see below). + * + * + * Finally the buffer can be pushed downstream and parsing loop starts + * over again. Just prior to actually pushing the buffer in question, + * it is passed to @pre_push_buffer which gives subclass yet one + * last chance to examine buffer metadata, or to send some custom (tag) + * events, or to perform custom (segment) filtering. + * + * + * During the parsing process GstBaseParseClass will handle both srcpad and + * sinkpad events. They will be passed to subclass if @event or + * @src_event callbacks have been provided. + * + * + * + * + * Shutdown phase + * + * GstBaseParse class calls @stop to inform the subclass that data + * parsing will be stopped. + * + * + * + * + * + * Subclass is responsible for providing pad template caps for + * source and sink pads. The pads need to be named "sink" and "src". It also + * needs to set the fixed caps on srcpad, when the format is ensured (e.g. + * when base class calls subclass' @set_sink_caps function). + * + * This base class uses GST_FORMAT_DEFAULT as a meaning of frames. So, + * subclass conversion routine needs to know that conversion from + * GST_FORMAT_TIME to GST_FORMAT_DEFAULT must return the + * frame number that can be found from the given byte position. + * + * GstBaseParse uses subclasses conversion methods also for seeking (or otherwise + * uses its own default one, see also below). + * + * Subclass @start and @stop functions will be called to inform the beginning + * and end of data processing. + * + * Things that subclass need to take care of: + * + * Provide pad templates + * + * Fixate the source pad caps when appropriate + * + * + * Inform base class how big data chunks should be retrieved. This is + * done with @gst_base_parse_set_min_frame_size function. + * + * + * Examine data chunks passed to subclass with @check_valid_frame + * and tell if they contain a valid frame + * + * + * Set the caps and timestamp to frame that is passed to subclass with + * @parse_frame function. + * + * Provide conversion functions + * + * Update the duration information with @gst_base_parse_set_duration + * + * + * Optionally passthrough using @gst_base_parse_set_passthrough + * + * + * Configure various baseparse parameters using @gst_base_parse_set_seek and + * @gst_base_parse_set_frame_props. + * + * + * In particular, if subclass is unable to determine a duration, but + * parsing (or specs) yields a frames per seconds rate, then this can be + * provided to GstBaseParse to enable it to cater for + * buffer time metadata (which will be taken from upstream as much as possible). + * Internally keeping track of frame durations and respective + * sizes that have been pushed provides GstBaseParse with an estimated bitrate. + * A default @convert (used if not overriden) will then use these + * rates to perform obvious conversions. These rates are also used to update + * (estimated) duration at regular frame intervals. + * + * + * + */ + +/* TODO: + * - In push mode provide a queue of adapter-"queued" buffers for upstream + * buffer metadata + * - Queue buffers/events until caps are set + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include + +#include "gstbaseparse.h" + +#define MIN_FRAMES_TO_POST_BITRATE 10 +#define TARGET_DIFFERENCE (20 * GST_SECOND) + +GST_DEBUG_CATEGORY_STATIC (gst_base_parse_debug); +#define GST_CAT_DEFAULT gst_base_parse_debug + +/* Supported formats */ +static GstFormat fmtlist[] = { + GST_FORMAT_DEFAULT, + GST_FORMAT_BYTES, + GST_FORMAT_TIME, + 0 +}; + +#define GST_BASE_PARSE_GET_PRIVATE(obj) \ + (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_BASE_PARSE, GstBaseParsePrivate)) + +struct _GstBaseParsePrivate +{ + GstActivateMode pad_mode; + + gint64 duration; + GstFormat duration_fmt; + gint64 estimated_duration; + + guint min_frame_size; + gboolean passthrough; + guint fps_num, fps_den; + guint update_interval; + guint bitrate; + guint lead_in, lead_out; + GstClockTime lead_in_ts, lead_out_ts; + GstBaseParseSeekable seekable; + + gboolean discont; + gboolean flushing; + gboolean drain; + + gint64 offset; + gint64 sync_offset; + GstClockTime next_ts; + GstClockTime prev_ts; + GstClockTime frame_duration; + gboolean seen_keyframe; + gboolean is_video; + + guint64 framecount; + guint64 bytecount; + guint64 data_bytecount; + guint64 acc_duration; + GstClockTime first_frame_ts; + gint64 first_frame_offset; + + gboolean post_min_bitrate; + gboolean post_avg_bitrate; + gboolean post_max_bitrate; + guint min_bitrate; + guint avg_bitrate; + guint max_bitrate; + guint posted_avg_bitrate; + + GList *pending_events; + + GstBuffer *cache; + + /* index entry storage, either ours or provided */ + GstIndex *index; + gint index_id; + gboolean own_index; + /* seek table entries only maintained if upstream is BYTE seekable */ + gboolean upstream_seekable; + gboolean upstream_has_duration; + gint64 upstream_size; + /* minimum distance between two index entries */ + GstClockTimeDiff idx_interval; + /* ts and offset of last entry added */ + GstClockTime index_last_ts; + guint64 index_last_offset; + gboolean index_last_valid; + + /* timestamps currently produced are accurate, e.g. started from 0 onwards */ + gboolean exact_position; + /* seek events are temporarily kept to match them with newsegments */ + GSList *pending_seeks; + + /* reverse playback */ + GSList *buffers_pending; + GSList *buffers_queued; + GstClockTime last_ts; + gint64 last_offset; +}; + +typedef struct _GstBaseParseSeek +{ + GstSegment segment; + gboolean accurate; + gint64 offset; + GstClockTime start_ts; +} GstBaseParseSeek; + +static GstElementClass *parent_class = NULL; + +static void gst_base_parse_class_init (GstBaseParseClass * klass); +static void gst_base_parse_init (GstBaseParse * parse, + GstBaseParseClass * klass); + +GType +gst_base_parse_get_type (void) +{ + static GType base_parse_type = 0; + + if (!base_parse_type) { + static const GTypeInfo base_parse_info = { + sizeof (GstBaseParseClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) gst_base_parse_class_init, + NULL, + NULL, + sizeof (GstBaseParse), + 0, + (GInstanceInitFunc) gst_base_parse_init, + }; + + base_parse_type = g_type_register_static (GST_TYPE_ELEMENT, + "GstH263BaseParseBad", &base_parse_info, G_TYPE_FLAG_ABSTRACT); + } + return base_parse_type; +} + +static void gst_base_parse_finalize (GObject * object); + +static GstStateChangeReturn gst_base_parse_change_state (GstElement * element, + GstStateChange transition); +static void gst_base_parse_reset (GstBaseParse * parse); + +static void gst_base_parse_set_index (GstElement * element, GstIndex * index); +static GstIndex *gst_base_parse_get_index (GstElement * element); + +static gboolean gst_base_parse_sink_activate (GstPad * sinkpad); +static gboolean gst_base_parse_sink_activate_push (GstPad * pad, + gboolean active); +static gboolean gst_base_parse_sink_activate_pull (GstPad * pad, + gboolean active); +static gboolean gst_base_parse_handle_seek (GstBaseParse * parse, + GstEvent * event); +static void gst_base_parse_handle_tag (GstBaseParse * parse, GstEvent * event); + +static gboolean gst_base_parse_src_event (GstPad * pad, GstEvent * event); +static gboolean gst_base_parse_sink_event (GstPad * pad, GstEvent * event); +static gboolean gst_base_parse_query (GstPad * pad, GstQuery * query); +static gboolean gst_base_parse_sink_setcaps (GstPad * pad, GstCaps * caps); +static const GstQueryType *gst_base_parse_get_querytypes (GstPad * pad); + +static GstFlowReturn gst_base_parse_chain (GstPad * pad, GstBuffer * buffer); +static void gst_base_parse_loop (GstPad * pad); + +static gboolean gst_base_parse_check_frame (GstBaseParse * parse, + GstBuffer * buffer, guint * framesize, gint * skipsize); + +static GstFlowReturn gst_base_parse_parse_frame (GstBaseParse * parse, + GstBuffer * buffer); + +static gboolean gst_base_parse_sink_eventfunc (GstBaseParse * parse, + GstEvent * event); + +static gboolean gst_base_parse_src_eventfunc (GstBaseParse * parse, + GstEvent * event); + +static void gst_base_parse_drain (GstBaseParse * parse); + +static void gst_base_parse_post_bitrates (GstBaseParse * parse, + gboolean post_min, gboolean post_avg, gboolean post_max); + +static gint64 gst_base_parse_find_offset (GstBaseParse * parse, + GstClockTime time, gboolean before, GstClockTime * _ts); +static GstFlowReturn gst_base_parse_locate_time (GstBaseParse * parse, + GstClockTime * _time, gint64 * _offset); + +static GstFlowReturn gst_base_parse_process_fragment (GstBaseParse * parse, + gboolean push_only); + +static void +gst_base_parse_clear_queues (GstBaseParse * parse) +{ + g_slist_foreach (parse->priv->buffers_queued, (GFunc) gst_buffer_unref, NULL); + g_slist_free (parse->priv->buffers_queued); + parse->priv->buffers_queued = NULL; + g_slist_foreach (parse->priv->buffers_pending, (GFunc) gst_buffer_unref, + NULL); + g_slist_free (parse->priv->buffers_pending); + parse->priv->buffers_pending = NULL; +} + +static void +gst_base_parse_finalize (GObject * object) +{ + GstBaseParse *parse = GST_BASE_PARSE (object); + GstEvent **p_ev; + + g_object_unref (parse->adapter); + + if (parse->pending_segment) { + p_ev = &parse->pending_segment; + gst_event_replace (p_ev, NULL); + } + if (parse->close_segment) { + p_ev = &parse->close_segment; + gst_event_replace (p_ev, NULL); + } + + if (parse->priv->cache) { + gst_buffer_unref (parse->priv->cache); + parse->priv->cache = NULL; + } + + g_list_foreach (parse->priv->pending_events, (GFunc) gst_mini_object_unref, + NULL); + g_list_free (parse->priv->pending_events); + parse->priv->pending_events = NULL; + + if (parse->priv->index) { + gst_object_unref (parse->priv->index); + parse->priv->index = NULL; + } + + gst_base_parse_clear_queues (parse); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +gst_base_parse_class_init (GstBaseParseClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *gstelement_class; + + gobject_class = G_OBJECT_CLASS (klass); + g_type_class_add_private (klass, sizeof (GstBaseParsePrivate)); + parent_class = g_type_class_peek_parent (klass); + gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_base_parse_finalize); + + gstelement_class = (GstElementClass *) klass; + gstelement_class->change_state = + GST_DEBUG_FUNCPTR (gst_base_parse_change_state); + gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_base_parse_set_index); + gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_base_parse_get_index); + + /* Default handlers */ + klass->check_valid_frame = gst_base_parse_check_frame; + klass->parse_frame = gst_base_parse_parse_frame; + klass->src_event = gst_base_parse_src_eventfunc; + klass->convert = gst_base_parse_convert_default; + + GST_DEBUG_CATEGORY_INIT (gst_base_parse_debug, "h263baseparse", 0, + "baseparse element"); +} + +static void +gst_base_parse_init (GstBaseParse * parse, GstBaseParseClass * bclass) +{ + GstPadTemplate *pad_template; + + GST_DEBUG_OBJECT (parse, "gst_base_parse_init"); + + parse->priv = GST_BASE_PARSE_GET_PRIVATE (parse); + + pad_template = + gst_element_class_get_pad_template (GST_ELEMENT_CLASS (bclass), "sink"); + g_return_if_fail (pad_template != NULL); + parse->sinkpad = gst_pad_new_from_template (pad_template, "sink"); + gst_pad_set_event_function (parse->sinkpad, + GST_DEBUG_FUNCPTR (gst_base_parse_sink_event)); + gst_pad_set_setcaps_function (parse->sinkpad, + GST_DEBUG_FUNCPTR (gst_base_parse_sink_setcaps)); + gst_pad_set_chain_function (parse->sinkpad, + GST_DEBUG_FUNCPTR (gst_base_parse_chain)); + gst_pad_set_activate_function (parse->sinkpad, + GST_DEBUG_FUNCPTR (gst_base_parse_sink_activate)); + gst_pad_set_activatepush_function (parse->sinkpad, + GST_DEBUG_FUNCPTR (gst_base_parse_sink_activate_push)); + gst_pad_set_activatepull_function (parse->sinkpad, + GST_DEBUG_FUNCPTR (gst_base_parse_sink_activate_pull)); + gst_element_add_pad (GST_ELEMENT (parse), parse->sinkpad); + + GST_DEBUG_OBJECT (parse, "sinkpad created"); + + pad_template = + gst_element_class_get_pad_template (GST_ELEMENT_CLASS (bclass), "src"); + g_return_if_fail (pad_template != NULL); + parse->srcpad = gst_pad_new_from_template (pad_template, "src"); + gst_pad_set_event_function (parse->srcpad, + GST_DEBUG_FUNCPTR (gst_base_parse_src_event)); + gst_pad_set_query_type_function (parse->srcpad, + GST_DEBUG_FUNCPTR (gst_base_parse_get_querytypes)); + gst_pad_set_query_function (parse->srcpad, + GST_DEBUG_FUNCPTR (gst_base_parse_query)); + gst_pad_use_fixed_caps (parse->srcpad); + gst_element_add_pad (GST_ELEMENT (parse), parse->srcpad); + GST_DEBUG_OBJECT (parse, "src created"); + + parse->adapter = gst_adapter_new (); + + parse->priv->pad_mode = GST_ACTIVATE_NONE; + + /* init state */ + gst_base_parse_reset (parse); + GST_DEBUG_OBJECT (parse, "init ok"); +} + +static void +gst_base_parse_reset (GstBaseParse * parse) +{ + GST_OBJECT_LOCK (parse); + gst_segment_init (&parse->segment, GST_FORMAT_TIME); + parse->priv->duration = -1; + parse->priv->min_frame_size = 1; + parse->priv->discont = TRUE; + parse->priv->flushing = FALSE; + parse->priv->offset = 0; + parse->priv->sync_offset = 0; + parse->priv->update_interval = 50; + parse->priv->fps_num = parse->priv->fps_den = 0; + parse->priv->frame_duration = GST_CLOCK_TIME_NONE; + parse->priv->lead_in = parse->priv->lead_out = 0; + parse->priv->lead_in_ts = parse->priv->lead_out_ts = 0; + parse->priv->seekable = GST_BASE_PARSE_SEEK_DEFAULT; + parse->priv->bitrate = 0; + parse->priv->framecount = 0; + parse->priv->bytecount = 0; + parse->priv->acc_duration = 0; + parse->priv->first_frame_ts = GST_CLOCK_TIME_NONE; + parse->priv->first_frame_offset = -1; + parse->priv->estimated_duration = -1; + parse->priv->next_ts = 0; + parse->priv->passthrough = FALSE; + parse->priv->post_min_bitrate = TRUE; + parse->priv->post_avg_bitrate = TRUE; + parse->priv->post_max_bitrate = TRUE; + parse->priv->min_bitrate = G_MAXUINT; + parse->priv->max_bitrate = 0; + parse->priv->avg_bitrate = 0; + parse->priv->posted_avg_bitrate = 0; + + parse->priv->index_last_ts = 0; + parse->priv->index_last_offset = 0; + parse->priv->index_last_valid = TRUE; + parse->priv->upstream_seekable = FALSE; + parse->priv->upstream_size = 0; + parse->priv->upstream_has_duration = FALSE; + parse->priv->idx_interval = 0; + parse->priv->exact_position = TRUE; + parse->priv->seen_keyframe = FALSE; + + parse->priv->last_ts = GST_CLOCK_TIME_NONE; + parse->priv->last_offset = 0; + + if (parse->pending_segment) { + gst_event_unref (parse->pending_segment); + parse->pending_segment = NULL; + } + + g_list_foreach (parse->priv->pending_events, (GFunc) gst_mini_object_unref, + NULL); + g_list_free (parse->priv->pending_events); + parse->priv->pending_events = NULL; + + if (parse->priv->cache) { + gst_buffer_unref (parse->priv->cache); + parse->priv->cache = NULL; + } + + g_slist_foreach (parse->priv->pending_seeks, (GFunc) g_free, NULL); + g_slist_free (parse->priv->pending_seeks); + parse->priv->pending_seeks = NULL; + + GST_OBJECT_UNLOCK (parse); +} + +/** + * gst_base_parse_check_frame: + * @parse: #GstBaseParse. + * @buffer: GstBuffer. + * @framesize: This will be set to tell the found frame size in bytes. + * @skipsize: Output parameter that tells how much data needs to be skipped + * in order to find the following frame header. + * + * Default callback for check_valid_frame. + * + * Returns: Always TRUE. + */ +static gboolean +gst_base_parse_check_frame (GstBaseParse * parse, + GstBuffer * buffer, guint * framesize, gint * skipsize) +{ + *framesize = GST_BUFFER_SIZE (buffer); + *skipsize = 0; + return TRUE; +} + + +/** + * gst_base_parse_parse_frame: + * @parse: #GstBaseParse. + * @buffer: #GstBuffer. + * + * Default callback for parse_frame. + */ +static GstFlowReturn +gst_base_parse_parse_frame (GstBaseParse * parse, GstBuffer * buffer) +{ + if (!GST_BUFFER_TIMESTAMP_IS_VALID (buffer) && + GST_CLOCK_TIME_IS_VALID (parse->priv->next_ts)) { + GST_BUFFER_TIMESTAMP (buffer) = parse->priv->next_ts; + } + if (!GST_BUFFER_DURATION_IS_VALID (buffer) && + GST_CLOCK_TIME_IS_VALID (parse->priv->frame_duration)) { + GST_BUFFER_DURATION (buffer) = parse->priv->frame_duration; + } + return GST_FLOW_OK; +} + +/** + * gst_base_parse_convert: + * @parse: #GstBaseParse. + * @src_format: #GstFormat describing the source format. + * @src_value: Source value to be converted. + * @dest_format: #GstFormat defining the converted format. + * @dest_value: Pointer where the conversion result will be put. + * + * Converts using configured "convert" vmethod in #GstBaseParse class. + * + * Returns: TRUE if conversion was successful. + */ +static gboolean +gst_base_parse_convert (GstBaseParse * parse, + GstFormat src_format, + gint64 src_value, GstFormat dest_format, gint64 * dest_value) +{ + GstBaseParseClass *klass = GST_BASE_PARSE_GET_CLASS (parse); + gboolean ret; + + g_return_val_if_fail (dest_value != NULL, FALSE); + + if (!klass->convert) + return FALSE; + + ret = klass->convert (parse, src_format, src_value, dest_format, dest_value); + +#ifndef GST_DISABLE_GST_DEBUG + { + if (ret) { + if (src_format == GST_FORMAT_TIME && dest_format == GST_FORMAT_BYTES) { + GST_LOG_OBJECT (parse, + "TIME -> BYTES: %" GST_TIME_FORMAT " -> %" G_GINT64_FORMAT, + GST_TIME_ARGS (src_value), *dest_value); + } else if (dest_format == GST_FORMAT_TIME && + src_format == GST_FORMAT_BYTES) { + GST_LOG_OBJECT (parse, + "BYTES -> TIME: %" G_GINT64_FORMAT " -> %" GST_TIME_FORMAT, + src_value, GST_TIME_ARGS (*dest_value)); + } else { + GST_LOG_OBJECT (parse, + "%s -> %s: %" G_GINT64_FORMAT " -> %" G_GINT64_FORMAT, + GST_STR_NULL (gst_format_get_name (src_format)), + GST_STR_NULL (gst_format_get_name (dest_format)), + src_value, *dest_value); + } + } else { + GST_DEBUG_OBJECT (parse, "conversion failed"); + } + } +#endif + + return ret; +} + +/** + * gst_base_parse_sink_event: + * @pad: #GstPad that received the event. + * @event: #GstEvent to be handled. + * + * Handler for sink pad events. + * + * Returns: TRUE if the event was handled. + */ +static gboolean +gst_base_parse_sink_event (GstPad * pad, GstEvent * event) +{ + GstBaseParse *parse; + GstBaseParseClass *bclass; + gboolean handled = FALSE; + gboolean ret = TRUE; + + parse = GST_BASE_PARSE (gst_pad_get_parent (pad)); + bclass = GST_BASE_PARSE_GET_CLASS (parse); + + GST_DEBUG_OBJECT (parse, "handling event %d, %s", GST_EVENT_TYPE (event), + GST_EVENT_TYPE_NAME (event)); + + /* Cache all events except EOS, NEWSEGMENT and FLUSH_STOP if we have a + * pending segment */ + if (parse->pending_segment && GST_EVENT_TYPE (event) != GST_EVENT_EOS + && GST_EVENT_TYPE (event) != GST_EVENT_NEWSEGMENT + && GST_EVENT_TYPE (event) != GST_EVENT_FLUSH_START + && GST_EVENT_TYPE (event) != GST_EVENT_FLUSH_STOP) { + + if (GST_EVENT_TYPE (event) == GST_EVENT_TAG) + /* See if any bitrate tags were posted */ + gst_base_parse_handle_tag (parse, event); + + parse->priv->pending_events = + g_list_append (parse->priv->pending_events, event); + ret = TRUE; + } else { + + if (GST_EVENT_TYPE (event) == GST_EVENT_EOS && + parse->priv->framecount < MIN_FRAMES_TO_POST_BITRATE) + /* We've not posted bitrate tags yet - do so now */ + gst_base_parse_post_bitrates (parse, TRUE, TRUE, TRUE); + + if (bclass->event) + handled = bclass->event (parse, event); + + if (!handled) + handled = gst_base_parse_sink_eventfunc (parse, event); + + if (!handled) + ret = gst_pad_event_default (pad, event); + } + + gst_object_unref (parse); + GST_DEBUG_OBJECT (parse, "event handled"); + return ret; +} + + +/** + * gst_base_parse_sink_eventfunc: + * @parse: #GstBaseParse. + * @event: #GstEvent to be handled. + * + * Element-level event handler function. + * + * Returns: TRUE if the event was handled and not need forwarding. + */ +static gboolean +gst_base_parse_sink_eventfunc (GstBaseParse * parse, GstEvent * event) +{ + gboolean handled = FALSE; + GstEvent **eventp; + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_NEWSEGMENT: + { + gdouble rate, applied_rate; + GstFormat format; + gint64 start, stop, pos, next_ts, offset = 0; + gboolean update; + + gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate, + &format, &start, &stop, &pos); + + GST_DEBUG_OBJECT (parse, "newseg rate %g, applied rate %g, " + "format %d, start = %" GST_TIME_FORMAT ", stop = %" GST_TIME_FORMAT + ", pos = %" GST_TIME_FORMAT, rate, applied_rate, format, + GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (pos)); + + if (format == GST_FORMAT_BYTES) { + GstClockTime seg_start, seg_stop; + GstBaseParseSeek *seek = NULL; + GSList *node; + + /* stop time is allowed to be open-ended, but not start & pos */ + seg_stop = GST_CLOCK_TIME_NONE; + seg_start = 0; + offset = pos; + + GST_OBJECT_LOCK (parse); + for (node = parse->priv->pending_seeks; node; node = node->next) { + GstBaseParseSeek *tmp = node->data; + + if (tmp->offset == pos) { + seek = tmp; + break; + } + } + parse->priv->pending_seeks = + g_slist_remove (parse->priv->pending_seeks, seek); + GST_OBJECT_UNLOCK (parse); + + if (seek) { + GST_DEBUG_OBJECT (parse, + "Matched newsegment to%s seek: %" GST_SEGMENT_FORMAT, + seek->accurate ? " accurate" : "", &seek->segment); + seg_start = seek->segment.start; + seg_stop = seek->segment.stop; + next_ts = seek->start_ts; + parse->priv->exact_position = seek->accurate; + g_free (seek); + } else { + /* best attempt convert */ + /* as these are only estimates, stop is kept open-ended to avoid + * premature cutting */ + gst_base_parse_convert (parse, GST_FORMAT_BYTES, start, + GST_FORMAT_TIME, (gint64 *) & seg_start); + parse->priv->exact_position = (start == 0); + next_ts = seg_start; + } + + gst_event_unref (event); + event = gst_event_new_new_segment_full (update, rate, applied_rate, + GST_FORMAT_TIME, seg_start, seg_stop, seg_start); + format = GST_FORMAT_TIME; + start = seg_start; + stop = seg_stop; + GST_DEBUG_OBJECT (parse, "Converted incoming segment to TIME. " + "start = %" GST_TIME_FORMAT ", stop = %" GST_TIME_FORMAT, + GST_TIME_ARGS (seg_start), GST_TIME_ARGS (seg_stop)); + } else if (format != GST_FORMAT_TIME) { + /* Unknown incoming segment format. Output a default open-ended + * TIME segment */ + gst_event_unref (event); + event = gst_event_new_new_segment_full (update, rate, applied_rate, + GST_FORMAT_TIME, 0, GST_CLOCK_TIME_NONE, 0); + format = GST_FORMAT_TIME; + next_ts = start = 0; + stop = GST_CLOCK_TIME_NONE; + } else { + /* not considered BYTE seekable if it is talking to us in TIME, + * whatever else it might claim */ + parse->priv->upstream_seekable = FALSE; + next_ts = start; + } + + gst_segment_set_newsegment_full (&parse->segment, update, rate, + applied_rate, format, start, stop, start); + + /* save the segment for later, right before we push a new buffer so that + * the caps are fixed and the next linked element can receive + * the segment. */ + eventp = &parse->pending_segment; + gst_event_replace (eventp, event); + gst_event_unref (event); + handled = TRUE; + + /* but finish the current segment */ + GST_DEBUG_OBJECT (parse, "draining current segment"); + if (parse->segment.rate > 0.0) + gst_base_parse_drain (parse); + else + gst_base_parse_process_fragment (parse, FALSE); + gst_adapter_clear (parse->adapter); + parse->priv->offset = offset; + parse->priv->sync_offset = offset; + parse->priv->next_ts = next_ts; + parse->priv->last_ts = GST_CLOCK_TIME_NONE; + parse->priv->discont = TRUE; + parse->priv->seen_keyframe = FALSE; + break; + } + + case GST_EVENT_FLUSH_START: + parse->priv->flushing = TRUE; + handled = gst_pad_push_event (parse->srcpad, event); + /* Wait for _chain() to exit by taking the srcpad STREAM_LOCK */ + GST_PAD_STREAM_LOCK (parse->srcpad); + GST_PAD_STREAM_UNLOCK (parse->srcpad); + + break; + + case GST_EVENT_FLUSH_STOP: + gst_adapter_clear (parse->adapter); + gst_base_parse_clear_queues (parse); + parse->priv->flushing = FALSE; + parse->priv->discont = TRUE; + parse->priv->last_ts = GST_CLOCK_TIME_NONE; + break; + + case GST_EVENT_EOS: + if (parse->segment.rate > 0.0) + gst_base_parse_drain (parse); + else + gst_base_parse_process_fragment (parse, FALSE); + + /* If we STILL have zero frames processed, fire an error */ + if (parse->priv->framecount == 0) { + GST_ELEMENT_ERROR (parse, STREAM, WRONG_TYPE, + ("No valid frames found before end of stream"), (NULL)); + } + /* newsegment before eos */ + if (parse->pending_segment) { + gst_pad_push_event (parse->srcpad, parse->pending_segment); + parse->pending_segment = NULL; + } + break; + + default: + break; + } + + return handled; +} + + +/** + * gst_base_parse_src_event: + * @pad: #GstPad that received the event. + * @event: #GstEvent that was received. + * + * Handler for source pad events. + * + * Returns: TRUE if the event was handled. + */ +static gboolean +gst_base_parse_src_event (GstPad * pad, GstEvent * event) +{ + GstBaseParse *parse; + GstBaseParseClass *bclass; + gboolean handled = FALSE; + gboolean ret = TRUE; + + parse = GST_BASE_PARSE (gst_pad_get_parent (pad)); + bclass = GST_BASE_PARSE_GET_CLASS (parse); + + GST_DEBUG_OBJECT (parse, "event %d, %s", GST_EVENT_TYPE (event), + GST_EVENT_TYPE_NAME (event)); + + if (bclass->src_event) + handled = bclass->src_event (parse, event); + + if (!handled) + ret = gst_pad_event_default (pad, event); + else + gst_event_unref (event); + + gst_object_unref (parse); + return ret; +} + + +/** + * gst_base_parse_src_eventfunc: + * @parse: #GstBaseParse. + * @event: #GstEvent that was received. + * + * Default srcpad event handler. + * + * Returns: TRUE if the event was handled and can be dropped. + */ +static gboolean +gst_base_parse_src_eventfunc (GstBaseParse * parse, GstEvent * event) +{ + gboolean handled = FALSE; + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_SEEK: + { + if (parse->priv->seekable > GST_BASE_PARSE_SEEK_NONE) { + handled = gst_base_parse_handle_seek (parse, event); + } + break; + } + default: + break; + } + return handled; +} + + +/** + * gst_base_parse_convert_default: + * @parse: #GstBaseParse. + * @src_format: #GstFormat describing the source format. + * @src_value: Source value to be converted. + * @dest_format: #GstFormat defining the converted format. + * @dest_value: Pointer where the conversion result will be put. + * + * Default implementation of "convert" vmethod in #GstBaseParse class. + * + * Returns: TRUE if conversion was successful. + */ +gboolean +gst_base_parse_convert_default (GstBaseParse * parse, + GstFormat src_format, + gint64 src_value, GstFormat dest_format, gint64 * dest_value) +{ + gboolean ret = FALSE; + guint64 bytes, duration; + + if (G_UNLIKELY (src_format == dest_format)) { + *dest_value = src_value; + return TRUE; + } + + if (G_UNLIKELY (src_value == -1)) { + *dest_value = -1; + return TRUE; + } + + if (G_UNLIKELY (src_value == 0)) { + *dest_value = 0; + return TRUE; + } + + /* need at least some frames */ + if (!parse->priv->framecount) + return FALSE; + + duration = parse->priv->acc_duration / GST_MSECOND; + bytes = parse->priv->bytecount; + + if (G_UNLIKELY (!duration || !bytes)) + return FALSE; + + if (src_format == GST_FORMAT_BYTES) { + if (dest_format == GST_FORMAT_TIME) { + /* BYTES -> TIME conversion */ + GST_DEBUG_OBJECT (parse, "converting bytes -> time"); + *dest_value = gst_util_uint64_scale (src_value, duration, bytes); + *dest_value *= GST_MSECOND; + GST_DEBUG_OBJECT (parse, "conversion result: %" G_GINT64_FORMAT " ms", + *dest_value / GST_MSECOND); + ret = TRUE; + } + } else if (src_format == GST_FORMAT_TIME) { + if (dest_format == GST_FORMAT_BYTES) { + GST_DEBUG_OBJECT (parse, "converting time -> bytes"); + *dest_value = gst_util_uint64_scale (src_value / GST_MSECOND, bytes, + duration); + GST_DEBUG_OBJECT (parse, + "time %" G_GINT64_FORMAT " ms in bytes = %" G_GINT64_FORMAT, + src_value / GST_MSECOND, *dest_value); + ret = TRUE; + } + } else if (src_format == GST_FORMAT_DEFAULT) { + /* DEFAULT == frame-based */ + if (dest_format == GST_FORMAT_TIME) { + if (parse->priv->fps_den) { + *dest_value = gst_util_uint64_scale (src_value, + GST_SECOND * parse->priv->fps_den, parse->priv->fps_num); + ret = TRUE; + } + } else if (dest_format == GST_FORMAT_BYTES) { + } + } + + return ret; +} + +/** + * gst_base_parse_update_duration: + * @parse: #GstBaseParse. + * + */ +static void +gst_base_parse_update_duration (GstBaseParse * aacparse) +{ + GstPad *peer; + GstBaseParse *parse; + + parse = GST_BASE_PARSE (aacparse); + + peer = gst_pad_get_peer (parse->sinkpad); + if (peer) { + GstFormat pformat = GST_FORMAT_BYTES; + gboolean qres = FALSE; + gint64 ptot, dest_value; + + qres = gst_pad_query_duration (peer, &pformat, &ptot); + gst_object_unref (GST_OBJECT (peer)); + if (qres) { + if (gst_base_parse_convert (parse, pformat, ptot, + GST_FORMAT_TIME, &dest_value)) + parse->priv->estimated_duration = dest_value; + } + } +} + +static void +gst_base_parse_post_bitrates (GstBaseParse * parse, gboolean post_min, + gboolean post_avg, gboolean post_max) +{ + GstTagList *taglist = gst_tag_list_new (); + + if (post_min && parse->priv->post_min_bitrate) + gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, + GST_TAG_MINIMUM_BITRATE, parse->priv->min_bitrate, NULL); + + if (post_avg && parse->priv->post_avg_bitrate) { + parse->priv->posted_avg_bitrate = parse->priv->avg_bitrate; + gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE, + parse->priv->avg_bitrate, NULL); + } + + if (post_max && parse->priv->post_max_bitrate) + gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, + GST_TAG_MAXIMUM_BITRATE, parse->priv->max_bitrate, NULL); + + GST_DEBUG_OBJECT (parse, "Updated bitrates. Min: %u, Avg: %u, Max: %u", + parse->priv->min_bitrate, parse->priv->avg_bitrate, + parse->priv->max_bitrate); + + gst_element_found_tags_for_pad (GST_ELEMENT (parse), parse->srcpad, taglist); +} + +/** + * gst_base_parse_update_bitrates: + * @parse: #GstBaseParse. + * @buffer: Current frame as a #GstBuffer + * + * Keeps track of the minimum and maximum bitrates, and also maintains a + * running average bitrate of the stream so far. + */ +static void +gst_base_parse_update_bitrates (GstBaseParse * parse, GstBuffer * buffer) +{ + /* Only update the tag on a 10 kbps delta */ + static const gint update_threshold = 10000; + + GstBaseParseClass *klass; + guint64 data_len, frame_dur; + gint overhead = 0, frame_bitrate, old_avg_bitrate; + gboolean update_min = FALSE, update_avg = FALSE, update_max = FALSE; + + klass = GST_BASE_PARSE_GET_CLASS (parse); + + if (klass->get_frame_overhead) { + overhead = klass->get_frame_overhead (parse, buffer); + if (overhead == -1) + return; + } + + data_len = GST_BUFFER_SIZE (buffer) - overhead; + parse->priv->data_bytecount += data_len; + + /* duration should be valid by now, + * either set by subclass or maybe based on fps settings */ + if (GST_BUFFER_DURATION_IS_VALID (buffer) && parse->priv->acc_duration != 0) { + /* Calculate duration of a frame from buffer properties */ + frame_dur = GST_BUFFER_DURATION (buffer); + parse->priv->avg_bitrate = (8 * parse->priv->data_bytecount * GST_SECOND) / + parse->priv->acc_duration; + + } else { + /* No way to figure out frame duration (is this even possible?) */ + return; + } + + /* override if subclass provided bitrate, e.g. metadata based */ + if (parse->priv->bitrate) { + parse->priv->avg_bitrate = parse->priv->bitrate; + /* spread this (confirmed) info ASAP */ + if (parse->priv->posted_avg_bitrate != parse->priv->avg_bitrate) + gst_base_parse_post_bitrates (parse, FALSE, TRUE, FALSE); + } + + frame_bitrate = (8 * data_len * GST_SECOND) / frame_dur; + + GST_LOG_OBJECT (parse, "frame bitrate %u, avg bitrate %u", frame_bitrate, + parse->priv->avg_bitrate); + + if (parse->priv->framecount < MIN_FRAMES_TO_POST_BITRATE) { + goto exit; + } else if (parse->priv->framecount == MIN_FRAMES_TO_POST_BITRATE) { + /* always post all at threshold time */ + update_min = update_max = update_avg = TRUE; + } else { + if (frame_bitrate < parse->priv->min_bitrate) { + parse->priv->min_bitrate = frame_bitrate; + update_min = TRUE; + } + + if (frame_bitrate > parse->priv->max_bitrate) { + parse->priv->max_bitrate = frame_bitrate; + update_max = TRUE; + } + + old_avg_bitrate = parse->priv->posted_avg_bitrate; + if ((gint) (old_avg_bitrate - parse->priv->avg_bitrate) > update_threshold + || (gint) (parse->priv->avg_bitrate - old_avg_bitrate) > + update_threshold) + update_avg = TRUE; + } + + if ((update_min || update_avg || update_max)) + gst_base_parse_post_bitrates (parse, update_min, update_avg, update_max); + + /* If average bitrate changes that much and no valid (time) duration provided, + * then post a new duration message so applications can update their cached + * values */ + if (update_avg && !(parse->priv->duration_fmt == GST_FORMAT_TIME && + GST_CLOCK_TIME_IS_VALID (parse->priv->duration))) + gst_element_post_message (GST_ELEMENT (parse), + gst_message_new_duration (GST_OBJECT (parse), GST_FORMAT_TIME, -1)); + +exit: + return; +} + +/** + * gst_base_parse_add_index_entry: + * @parse: #GstBaseParse. + * @offset: offset of entry + * @ts: timestamp associated with offset + * @key: whether entry refers to keyframe + * @force: add entry disregarding sanity checks + * + * Adds an entry to the index associating @offset to @ts. It is recommended + * to only add keyframe entries. @force allows to bypass checks, such as + * whether the stream is (upstream) seekable, another entry is already "close" + * to the new entry, etc. + * + * Returns: #gboolean indicating whether entry was added + */ +gboolean +gst_base_parse_add_index_entry (GstBaseParse * parse, guint64 offset, + GstClockTime ts, gboolean key, gboolean force) +{ + gboolean ret = FALSE; + GstIndexAssociation associations[2]; + + GST_LOG_OBJECT (parse, "Adding key=%d index entry %" GST_TIME_FORMAT + " @ offset 0x%08" G_GINT64_MODIFIER "x", key, GST_TIME_ARGS (ts), offset); + + if (G_LIKELY (!force)) { + + if (!parse->priv->upstream_seekable) { + GST_DEBUG_OBJECT (parse, "upstream not seekable; discarding"); + goto exit; + } + + /* FIXME need better helper data structure that handles these issues + * related to ongoing collecting of index entries */ + if (parse->priv->index_last_offset >= offset) { + GST_DEBUG_OBJECT (parse, "already have entries up to offset " + "0x%08" G_GINT64_MODIFIER "x", parse->priv->index_last_offset); + goto exit; + } + + if (GST_CLOCK_DIFF (parse->priv->index_last_ts, ts) < + parse->priv->idx_interval) { + GST_DEBUG_OBJECT (parse, "entry too close to last time %" GST_TIME_FORMAT, + GST_TIME_ARGS (parse->priv->index_last_ts)); + goto exit; + } + + /* if last is not really the last one */ + if (!parse->priv->index_last_valid) { + GstClockTime prev_ts; + + gst_base_parse_find_offset (parse, ts, TRUE, &prev_ts); + if (GST_CLOCK_DIFF (prev_ts, ts) < parse->priv->idx_interval) { + GST_DEBUG_OBJECT (parse, + "entry too close to existing entry %" GST_TIME_FORMAT, + GST_TIME_ARGS (prev_ts)); + parse->priv->index_last_offset = offset; + parse->priv->index_last_ts = ts; + goto exit; + } + } + } + + associations[0].format = GST_FORMAT_TIME; + associations[0].value = ts; + associations[1].format = GST_FORMAT_BYTES; + associations[1].value = offset; + + /* index might change on-the-fly, although that would be nutty app ... */ + GST_OBJECT_LOCK (parse); + gst_index_add_associationv (parse->priv->index, parse->priv->index_id, + (key) ? GST_ASSOCIATION_FLAG_KEY_UNIT : GST_ASSOCIATION_FLAG_NONE, + 2, (const GstIndexAssociation *) &associations); + GST_OBJECT_UNLOCK (parse); + + if (key) { + parse->priv->index_last_offset = offset; + parse->priv->index_last_ts = ts; + } + + ret = TRUE; + +exit: + return ret; +} + +/* check for seekable upstream, above and beyond a mere query */ +static void +gst_base_parse_check_seekability (GstBaseParse * parse) +{ + GstQuery *query; + gboolean seekable = FALSE; + gint64 start = -1, stop = -1; + guint idx_interval = 0; + + query = gst_query_new_seeking (GST_FORMAT_BYTES); + if (!gst_pad_peer_query (parse->sinkpad, query)) { + GST_DEBUG_OBJECT (parse, "seeking query failed"); + goto done; + } + + gst_query_parse_seeking (query, NULL, &seekable, &start, &stop); + + /* try harder to query upstream size if we didn't get it the first time */ + if (seekable && stop == -1) { + GstFormat fmt = GST_FORMAT_BYTES; + + GST_DEBUG_OBJECT (parse, "doing duration query to fix up unset stop"); + gst_pad_query_peer_duration (parse->sinkpad, &fmt, &stop); + } + + /* if upstream doesn't know the size, it's likely that it's not seekable in + * practice even if it technically may be seekable */ + if (seekable && (start != 0 || stop <= start)) { + GST_DEBUG_OBJECT (parse, "seekable but unknown start/stop -> disable"); + seekable = FALSE; + } + + /* let's not put every single frame into our index */ + if (seekable) { + if (stop < 10 * 1024 * 1024) + idx_interval = 100; + else if (stop < 100 * 1024 * 1024) + idx_interval = 500; + else + idx_interval = 1000; + } + +done: + gst_query_unref (query); + + GST_DEBUG_OBJECT (parse, "seekable: %d (%" G_GUINT64_FORMAT " - %" + G_GUINT64_FORMAT ")", seekable, start, stop); + parse->priv->upstream_seekable = seekable; + parse->priv->upstream_size = seekable ? stop : 0; + + GST_DEBUG_OBJECT (parse, "idx_interval: %ums", idx_interval); + parse->priv->idx_interval = idx_interval * GST_MSECOND; +} + +/* some misc checks on upstream */ +static void +gst_base_parse_check_upstream (GstBaseParse * parse) +{ + GstFormat fmt = GST_FORMAT_TIME; + gint64 stop; + + if (gst_pad_query_peer_duration (parse->sinkpad, &fmt, &stop)) + if (GST_CLOCK_TIME_IS_VALID (stop) && stop) { + /* upstream has one, accept it also, and no further updates */ + gst_base_parse_set_duration (parse, GST_FORMAT_TIME, stop, 0); + parse->priv->upstream_has_duration = TRUE; + } + + GST_DEBUG_OBJECT (parse, "upstream_has_duration: %d", + parse->priv->upstream_has_duration); +} + +/* checks src caps to determine if dealing with audio or video */ +/* TODO maybe forego automagic stuff and let subclass configure it ? */ +static void +gst_base_parse_check_media (GstBaseParse * parse) +{ + GstCaps *caps; + GstStructure *s; + + caps = GST_PAD_CAPS (parse->srcpad); + if (G_LIKELY (caps) && (s = gst_caps_get_structure (caps, 0))) { + parse->priv->is_video = + g_str_has_prefix (gst_structure_get_name (s), "video"); + } else { + /* historical default */ + parse->priv->is_video = FALSE; + } + + GST_DEBUG_OBJECT (parse, "media is video == %d", parse->priv->is_video); +} + +/** + * gst_base_parse_handle_and_push_buffer: + * @parse: #GstBaseParse. + * @klass: #GstBaseParseClass. + * @buffer: #GstBuffer. + * + * Parses the frame from given buffer and pushes it forward. Also performs + * timestamp handling and checks the segment limits. + * + * This is called with srcpad STREAM_LOCK held. + * + * Returns: #GstFlowReturn + */ +static GstFlowReturn +gst_base_parse_handle_and_push_buffer (GstBaseParse * parse, + GstBaseParseClass * klass, GstBuffer * buffer) +{ + GstFlowReturn ret; + gint64 offset; + + if (parse->priv->discont) { + GST_DEBUG_OBJECT (parse, "marking DISCONT"); + GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT); + parse->priv->discont = FALSE; + } + + /* some one-time start-up */ + if (G_UNLIKELY (!parse->priv->framecount)) { + gst_base_parse_check_seekability (parse); + gst_base_parse_check_upstream (parse); + } + + GST_LOG_OBJECT (parse, + "parsing frame at offset %" G_GUINT64_FORMAT + " (%#" G_GINT64_MODIFIER "x) of size %d", + GST_BUFFER_OFFSET (buffer), GST_BUFFER_OFFSET (buffer), + GST_BUFFER_SIZE (buffer)); + + /* store offset as it might get overwritten */ + offset = GST_BUFFER_OFFSET (buffer); + ret = klass->parse_frame (parse, buffer); + + /* check initial frame to determine if subclass/format can provide ts. + * If so, that allows and enables extra seek and duration determining options */ + if (G_UNLIKELY (parse->priv->first_frame_offset < 0 && ret == GST_FLOW_OK)) { + if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer)) { + parse->priv->first_frame_offset = offset; + parse->priv->first_frame_ts = GST_BUFFER_TIMESTAMP (buffer); + GST_DEBUG_OBJECT (parse, "subclass provided ts %" GST_TIME_FORMAT + " for first frame at offset %" G_GINT64_FORMAT, + GST_TIME_ARGS (parse->priv->first_frame_ts), + parse->priv->first_frame_offset); + if (!GST_CLOCK_TIME_IS_VALID (parse->priv->duration)) { + gint64 off; + GstClockTime last_ts = G_MAXINT64; + + GST_DEBUG_OBJECT (parse, "no duration; trying scan to determine"); + gst_base_parse_locate_time (parse, &last_ts, &off); + if (GST_CLOCK_TIME_IS_VALID (last_ts)) + gst_base_parse_set_duration (parse, GST_FORMAT_TIME, last_ts, 0); + } + } else { + /* disable further checks */ + parse->priv->first_frame_offset = 0; + } + } + + /* re-use default handler to add missing metadata as-much-as-possible */ + gst_base_parse_parse_frame (parse, buffer); + if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) && + GST_BUFFER_DURATION_IS_VALID (buffer)) { + parse->priv->next_ts = + GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer); + } else { + /* we lost track, do not produce bogus time next time around + * (probably means parser subclass has given up on parsing as well) */ + GST_DEBUG_OBJECT (parse, "no next fallback timestamp"); + parse->priv->next_ts = GST_CLOCK_TIME_NONE; + } + + if (parse->priv->upstream_seekable && parse->priv->exact_position && + GST_BUFFER_TIMESTAMP_IS_VALID (buffer)) + gst_base_parse_add_index_entry (parse, offset, + GST_BUFFER_TIMESTAMP (buffer), + !GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT), FALSE); + + /* First buffers are dropped, this means that the subclass needs more + * frames to decide on the format and queues them internally */ + /* convert internal flow to OK and mark discont for the next buffer. */ + if (ret == GST_BASE_PARSE_FLOW_DROPPED) { + gst_buffer_unref (buffer); + return GST_FLOW_OK; + } else if (ret != GST_FLOW_OK) { + return ret; + } + + return gst_base_parse_push_buffer (parse, buffer); +} + +/** + * gst_base_parse_push_buffer: + * @parse: #GstBaseParse. + * @buffer: #GstBuffer. + * + * Pushes the buffer downstream, sends any pending events and + * does some timestamp and segment handling. + * + * This must be called with srcpad STREAM_LOCK held. + * + * Returns: #GstFlowReturn + */ +GstFlowReturn +gst_base_parse_push_buffer (GstBaseParse * parse, GstBuffer * buffer) +{ + GstFlowReturn ret = GST_FLOW_OK; + GstClockTime last_start = GST_CLOCK_TIME_NONE; + GstClockTime last_stop = GST_CLOCK_TIME_NONE; + GstBaseParseClass *klass = GST_BASE_PARSE_GET_CLASS (parse); + + GST_LOG_OBJECT (parse, + "processing buffer of size %d with ts %" GST_TIME_FORMAT + ", duration %" GST_TIME_FORMAT, GST_BUFFER_SIZE (buffer), + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)), + GST_TIME_ARGS (GST_BUFFER_DURATION (buffer))); + + /* update stats */ + parse->priv->bytecount += GST_BUFFER_SIZE (buffer); + if (!GST_BUFFER_FLAG_IS_SET (buffer, GST_BASE_PARSE_BUFFER_FLAG_NO_FRAME)) { + parse->priv->framecount++; + if (GST_BUFFER_DURATION_IS_VALID (buffer)) { + parse->priv->acc_duration += GST_BUFFER_DURATION (buffer); + } + } + GST_BUFFER_FLAG_UNSET (buffer, GST_BASE_PARSE_BUFFER_FLAG_NO_FRAME); + if (parse->priv->update_interval && + (parse->priv->framecount % parse->priv->update_interval) == 0) + gst_base_parse_update_duration (parse); + + if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer)) + last_start = last_stop = GST_BUFFER_TIMESTAMP (buffer); + if (last_start != GST_CLOCK_TIME_NONE + && GST_BUFFER_DURATION_IS_VALID (buffer)) + last_stop = last_start + GST_BUFFER_DURATION (buffer); + + /* should have caps by now */ + g_return_val_if_fail (GST_PAD_CAPS (parse->srcpad), GST_FLOW_ERROR); + + gst_buffer_set_caps (buffer, GST_PAD_CAPS (parse->srcpad)); + + /* segment adjustment magic; only if we are running the whole show */ + if (!parse->priv->passthrough && parse->segment.rate > 0.0 && + (parse->priv->pad_mode == GST_ACTIVATE_PULL || + parse->priv->upstream_seekable)) { + /* segment times are typically estimates, + * actual frame data might lead subclass to different timestamps, + * so override segment start from what is supplied there */ + if (G_UNLIKELY (parse->pending_segment && !parse->priv->exact_position && + GST_CLOCK_TIME_IS_VALID (last_start))) { + gst_event_unref (parse->pending_segment); + parse->segment.start = + MIN ((guint64) last_start, (guint64) parse->segment.stop); + GST_DEBUG_OBJECT (parse, + "adjusting pending segment start to %" GST_TIME_FORMAT, + GST_TIME_ARGS (parse->segment.start)); + parse->pending_segment = + gst_event_new_new_segment (FALSE, parse->segment.rate, + parse->segment.format, parse->segment.start, parse->segment.stop, + parse->segment.start); + } + /* handle gaps, e.g. non-zero start-time, in as much not handled by above */ + if (GST_CLOCK_TIME_IS_VALID (parse->segment.last_stop) && + GST_CLOCK_TIME_IS_VALID (last_start)) { + GstClockTimeDiff diff; + + /* only send newsegments with increasing start times, + * otherwise if these go back and forth downstream (sinks) increase + * accumulated time and running_time */ + diff = GST_CLOCK_DIFF (parse->segment.last_stop, last_start); + if (G_UNLIKELY (diff > 2 * GST_SECOND && last_start > parse->segment.start + && (!GST_CLOCK_TIME_IS_VALID (parse->segment.stop) || + last_start < parse->segment.stop))) { + GST_DEBUG_OBJECT (parse, + "Gap of %" G_GINT64_FORMAT " ns detected in stream " + "(%" GST_TIME_FORMAT " -> %" GST_TIME_FORMAT "). " + "Sending updated NEWSEGMENT events", diff, + GST_TIME_ARGS (parse->segment.last_stop), + GST_TIME_ARGS (last_start)); + if (G_UNLIKELY (parse->pending_segment)) { + gst_event_unref (parse->pending_segment); + parse->segment.start = last_start; + parse->pending_segment = + gst_event_new_new_segment (FALSE, parse->segment.rate, + parse->segment.format, parse->segment.start, parse->segment.stop, + parse->segment.start); + } else { + /* send newsegment events such that the gap is not accounted in + * accum time, hence running_time */ + /* close ahead of gap */ + gst_pad_push_event (parse->srcpad, + gst_event_new_new_segment (TRUE, parse->segment.rate, + parse->segment.format, parse->segment.last_stop, + parse->segment.last_stop, parse->segment.last_stop)); + /* skip gap */ + gst_pad_push_event (parse->srcpad, + gst_event_new_new_segment (FALSE, parse->segment.rate, + parse->segment.format, last_start, parse->segment.stop, + last_start)); + } + /* align segment view with downstream, + * prevents double-counting accum when closing segment */ + gst_segment_set_newsegment (&parse->segment, FALSE, + parse->segment.rate, parse->segment.format, last_start, + parse->segment.stop, last_start); + parse->segment.last_stop = last_start; + } + } + } + + /* and should then also be linked downstream, so safe to send some events */ + if (G_UNLIKELY (parse->close_segment)) { + /* only set up by loop */ + GST_DEBUG_OBJECT (parse, "loop sending close segment"); + gst_pad_push_event (parse->srcpad, parse->close_segment); + parse->close_segment = NULL; + } + if (G_UNLIKELY (parse->pending_segment)) { + GST_DEBUG_OBJECT (parse, "%s push pending segment", + parse->priv->pad_mode == GST_ACTIVATE_PULL ? "loop" : "chain"); + gst_pad_push_event (parse->srcpad, parse->pending_segment); + parse->pending_segment = NULL; + + /* have caps; check identity */ + gst_base_parse_check_media (parse); + } + + /* update bitrates and optionally post corresponding tags + * (following newsegment) */ + gst_base_parse_update_bitrates (parse, buffer); + + if (G_UNLIKELY (parse->priv->pending_events)) { + GList *l; + + for (l = parse->priv->pending_events; l != NULL; l = l->next) { + gst_pad_push_event (parse->srcpad, GST_EVENT (l->data)); + } + g_list_free (parse->priv->pending_events); + parse->priv->pending_events = NULL; + } + + if (klass->pre_push_buffer) + ret = klass->pre_push_buffer (parse, buffer); + else + ret = GST_BASE_PARSE_FLOW_CLIP; + + parse->priv->seen_keyframe |= parse->priv->is_video && + !GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT); + + if (ret == GST_BASE_PARSE_FLOW_CLIP) { + if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) && + GST_CLOCK_TIME_IS_VALID (parse->segment.stop) && + GST_BUFFER_TIMESTAMP (buffer) > + parse->segment.stop + parse->priv->lead_out_ts) { + GST_LOG_OBJECT (parse, "Dropped frame, after segment"); + ret = GST_FLOW_UNEXPECTED; + } else if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) && + GST_BUFFER_DURATION_IS_VALID (buffer) && + GST_CLOCK_TIME_IS_VALID (parse->segment.start) && + GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer) + + parse->priv->lead_in_ts < parse->segment.start) { + if (parse->priv->seen_keyframe) { + GST_LOG_OBJECT (parse, "Frame before segment, after keyframe"); + ret = GST_FLOW_OK; + } else { + GST_LOG_OBJECT (parse, "Dropped frame, before segment"); + ret = GST_BASE_PARSE_FLOW_DROPPED; + } + } else { + ret = GST_FLOW_OK; + } + } + + if (ret == GST_BASE_PARSE_FLOW_DROPPED) { + GST_LOG_OBJECT (parse, "frame (%d bytes) dropped", + GST_BUFFER_SIZE (buffer)); + gst_buffer_unref (buffer); + ret = GST_FLOW_OK; + } else if (ret == GST_FLOW_OK) { + if (parse->segment.rate > 0.0) { + ret = gst_pad_push (parse->srcpad, buffer); + GST_LOG_OBJECT (parse, "frame (%d bytes) pushed: %s", + GST_BUFFER_SIZE (buffer), gst_flow_get_name (ret)); + } else { + GST_LOG_OBJECT (parse, "frame (%d bytes) queued for now", + GST_BUFFER_SIZE (buffer)); + parse->priv->buffers_queued = + g_slist_prepend (parse->priv->buffers_queued, buffer); + ret = GST_FLOW_OK; + } + } else { + gst_buffer_unref (buffer); + GST_LOG_OBJECT (parse, "frame (%d bytes) not pushed: %s", + GST_BUFFER_SIZE (buffer), gst_flow_get_name (ret)); + /* if we are not sufficiently in control, let upstream decide on EOS */ + if (ret == GST_FLOW_UNEXPECTED && + (parse->priv->passthrough || + (parse->priv->pad_mode == GST_ACTIVATE_PUSH && + !parse->priv->upstream_seekable))) + ret = GST_FLOW_OK; + } + + /* Update current running segment position */ + if (ret == GST_FLOW_OK && last_stop != GST_CLOCK_TIME_NONE && + parse->segment.last_stop < last_stop) + gst_segment_set_last_stop (&parse->segment, GST_FORMAT_TIME, last_stop); + + return ret; +} + + +/** + * gst_base_parse_drain: + * @parse: #GstBaseParse. + * + * Drains the adapter until it is empty. It decreases the min_frame_size to + * match the current adapter size and calls chain method until the adapter + * is emptied or chain returns with error. + */ +static void +gst_base_parse_drain (GstBaseParse * parse) +{ + guint avail; + + GST_DEBUG_OBJECT (parse, "draining"); + parse->priv->drain = TRUE; + + for (;;) { + avail = gst_adapter_available (parse->adapter); + if (!avail) + break; + + if (gst_base_parse_chain (parse->sinkpad, NULL) != GST_FLOW_OK) { + break; + } + + /* nothing changed, maybe due to truncated frame; break infinite loop */ + if (avail == gst_adapter_available (parse->adapter)) { + GST_DEBUG_OBJECT (parse, "no change during draining; flushing"); + gst_adapter_clear (parse->adapter); + } + } + + parse->priv->drain = FALSE; +} + +/** + * gst_base_parse_process_fragment: + * @parse: #GstBaseParse. + * + * Processes a reverse playback (forward) fragment: + * - append head of last fragment that was skipped to current fragment data + * - drain the resulting current fragment data (i.e. repeated chain) + * - add time/duration (if needed) to frames queued by chain + * - push queued data + */ +static GstFlowReturn +gst_base_parse_process_fragment (GstBaseParse * parse, gboolean push_only) +{ + GstBuffer *buf; + GstFlowReturn ret = GST_FLOW_OK; + GSList *send = NULL; + + if (push_only) + goto push; + + /* restore order */ + parse->priv->buffers_pending = g_slist_reverse (parse->priv->buffers_pending); + while (parse->priv->buffers_pending) { + buf = GST_BUFFER_CAST (parse->priv->buffers_pending->data); + GST_LOG_OBJECT (parse, "adding pending buffer (size %d)", + GST_BUFFER_SIZE (buf)); + gst_adapter_push (parse->adapter, buf); + parse->priv->buffers_pending = + g_slist_delete_link (parse->priv->buffers_pending, + parse->priv->buffers_pending); + } + + /* invalidate so no fall-back timestamping is performed; + * ok if taken from subclass or upstream */ + parse->priv->next_ts = GST_CLOCK_TIME_NONE; + /* prevent it hanging around stop all the time */ + parse->segment.last_stop = GST_CLOCK_TIME_NONE; + /* mark next run */ + parse->priv->discont = TRUE; + + /* chain looks for frames and queues resulting ones (in stead of pushing) */ + /* initial skipped data is added to buffers_pending */ + gst_base_parse_drain (parse); + +push: + /* add metadata (if needed to queued buffers */ + GST_LOG_OBJECT (parse, "last timestamp: %" GST_TIME_FORMAT, + GST_TIME_ARGS (parse->priv->last_ts)); + while (parse->priv->buffers_queued) { + buf = GST_BUFFER_CAST (parse->priv->buffers_queued->data); + + /* no touching if upstream or parsing provided time */ + if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) { + GST_LOG_OBJECT (parse, "buffer has time %" GST_TIME_FORMAT, + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf))); + } else if (GST_CLOCK_TIME_IS_VALID (parse->priv->last_ts) && + GST_BUFFER_DURATION_IS_VALID (buf)) { + if (G_LIKELY (GST_BUFFER_DURATION (buf) <= parse->priv->last_ts)) + parse->priv->last_ts -= GST_BUFFER_DURATION (buf); + else + parse->priv->last_ts = 0; + GST_BUFFER_TIMESTAMP (buf) = parse->priv->last_ts; + GST_LOG_OBJECT (parse, "applied time %" GST_TIME_FORMAT, + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf))); + } else { + /* no idea, very bad */ + GST_WARNING_OBJECT (parse, "could not determine time for buffer"); + } + + /* reverse order for ascending sending */ + send = g_slist_prepend (send, buf); + parse->priv->buffers_queued = + g_slist_delete_link (parse->priv->buffers_queued, + parse->priv->buffers_queued); + } + + /* send buffers */ + while (send) { + buf = GST_BUFFER_CAST (send->data); + GST_LOG_OBJECT (parse, "pushing buffer %p, timestamp %" + GST_TIME_FORMAT ", duration %" GST_TIME_FORMAT + ", offset %" G_GINT64_FORMAT, buf, + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)), + GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_BUFFER_OFFSET (buf)); + + if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (parse->priv->last_ts))) + parse->priv->last_ts = GST_BUFFER_TIMESTAMP (buf); + + /* iterate output queue an push downstream */ + ret = gst_pad_push (parse->srcpad, buf); + send = g_slist_delete_link (send, send); + + /* clear any leftover if error */ + if (G_UNLIKELY (ret != GST_FLOW_OK)) { + while (send) { + buf = GST_BUFFER_CAST (send->data); + gst_buffer_unref (buf); + send = g_slist_delete_link (send, send); + } + } + } + + /* any trailing unused no longer usable (ideally none) */ + if (G_UNLIKELY (gst_adapter_available (parse->adapter))) { + GST_DEBUG_OBJECT (parse, "discarding %d trailing bytes", + gst_adapter_available (parse->adapter)); + gst_adapter_clear (parse->adapter); + } + + return ret; +} + +/* small helper that checks whether we have been trying to resync too long */ +static inline GstFlowReturn +gst_base_parse_check_sync (GstBaseParse * parse) +{ + if (G_UNLIKELY (parse->priv->discont && + parse->priv->offset - parse->priv->sync_offset > 2 * 1024 * 1024)) { + GST_ELEMENT_ERROR (parse, STREAM, DECODE, + ("Failed to parse stream"), (NULL)); + return GST_FLOW_ERROR; + } + + return GST_FLOW_OK; +} + + +/** + * gst_base_parse_chain: + * @pad: #GstPad. + * @buffer: #GstBuffer. + * + * Returns: #GstFlowReturn. + */ +static GstFlowReturn +gst_base_parse_chain (GstPad * pad, GstBuffer * buffer) +{ + GstBaseParseClass *bclass; + GstBaseParse *parse; + GstFlowReturn ret = GST_FLOW_OK; + GstBuffer *outbuf = NULL; + GstBuffer *tmpbuf = NULL; + guint fsize = 0; + gint skip = -1; + const guint8 *data; + guint min_size; + GstClockTime timestamp; + + parse = GST_BASE_PARSE (GST_OBJECT_PARENT (pad)); + bclass = GST_BASE_PARSE_GET_CLASS (parse); + + if (G_LIKELY (buffer)) { + GST_LOG_OBJECT (parse, "buffer size: %d, offset = %" G_GINT64_FORMAT, + GST_BUFFER_SIZE (buffer), GST_BUFFER_OFFSET (buffer)); + if (G_UNLIKELY (parse->priv->passthrough)) { + buffer = gst_buffer_make_metadata_writable (buffer); + return gst_base_parse_push_buffer (parse, buffer); + } + /* upstream feeding us in reverse playback; + * gather each fragment, then process it in single run */ + if (parse->segment.rate < 0.0) { + if (G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT))) { + GST_DEBUG_OBJECT (parse, "buffer starts new reverse playback fragment"); + ret = gst_base_parse_process_fragment (parse, FALSE); + } + gst_adapter_push (parse->adapter, buffer); + return ret; + } + gst_adapter_push (parse->adapter, buffer); + } + + /* Parse and push as many frames as possible */ + /* Stop either when adapter is empty or we are flushing */ + while (!parse->priv->flushing) { + tmpbuf = gst_buffer_new (); + + /* Synchronization loop */ + for (;;) { + min_size = parse->priv->min_frame_size; + + if (G_UNLIKELY (parse->priv->drain)) { + min_size = gst_adapter_available (parse->adapter); + GST_DEBUG_OBJECT (parse, "draining, data left: %d", min_size); + if (G_UNLIKELY (!min_size)) { + gst_buffer_unref (tmpbuf); + goto done; + } + } + + /* Collect at least min_frame_size bytes */ + if (gst_adapter_available (parse->adapter) < min_size) { + GST_DEBUG_OBJECT (parse, "not enough data available (only %d bytes)", + gst_adapter_available (parse->adapter)); + gst_buffer_unref (tmpbuf); + goto done; + } + + data = gst_adapter_peek (parse->adapter, min_size); + GST_BUFFER_DATA (tmpbuf) = (guint8 *) data; + GST_BUFFER_SIZE (tmpbuf) = min_size; + GST_BUFFER_OFFSET (tmpbuf) = parse->priv->offset; + GST_BUFFER_FLAG_SET (tmpbuf, GST_MINI_OBJECT_FLAG_READONLY); + + if (parse->priv->discont) { + GST_DEBUG_OBJECT (parse, "marking DISCONT"); + GST_BUFFER_FLAG_SET (tmpbuf, GST_BUFFER_FLAG_DISCONT); + } + + skip = -1; + if (bclass->check_valid_frame (parse, tmpbuf, &fsize, &skip)) { + if (gst_adapter_available (parse->adapter) < fsize) { + GST_DEBUG_OBJECT (parse, + "found valid frame but not enough data available (only %d bytes)", + gst_adapter_available (parse->adapter)); + gst_buffer_unref (tmpbuf); + goto done; + } + break; + } + if (skip == -1) { + /* subclass didn't touch this value. By default we skip 1 byte */ + skip = 1; + } + if (skip > 0) { + GST_LOG_OBJECT (parse, "finding sync, skipping %d bytes", skip); + if (parse->segment.rate < 0.0 && !parse->priv->buffers_queued) { + /* reverse playback, and no frames found yet, so we are skipping + * the leading part of a fragment, which may form the tail of + * fragment coming later, hopefully subclass skips efficiently ... */ + timestamp = gst_adapter_prev_timestamp (parse->adapter, NULL); + outbuf = gst_adapter_take_buffer (parse->adapter, skip); + outbuf = gst_buffer_make_metadata_writable (outbuf); + GST_BUFFER_TIMESTAMP (outbuf) = timestamp; + parse->priv->buffers_pending = + g_slist_prepend (parse->priv->buffers_pending, outbuf); + outbuf = NULL; + } else { + gst_adapter_flush (parse->adapter, skip); + } + parse->priv->offset += skip; + if (!parse->priv->discont) + parse->priv->sync_offset = parse->priv->offset; + parse->priv->discont = TRUE; + } + /* There is a possibility that subclass set the skip value to zero. + This means that it has probably found a frame but wants to ask + more data (by increasing the min_size) to be sure of this. */ + if ((ret = gst_base_parse_check_sync (parse)) != GST_FLOW_OK) { + gst_buffer_unref (tmpbuf); + goto done; + } + } + gst_buffer_unref (tmpbuf); + tmpbuf = NULL; + + if (skip > 0) { + /* Subclass found the sync, but still wants to skip some data */ + GST_LOG_OBJECT (parse, "skipping %d bytes", skip); + gst_adapter_flush (parse->adapter, skip); + parse->priv->offset += skip; + } + + /* Grab lock to prevent a race with FLUSH_START handler */ + GST_PAD_STREAM_LOCK (parse->srcpad); + + /* FLUSH_START event causes the "flushing" flag to be set. In this + * case we can leave the frame pushing loop */ + if (parse->priv->flushing) { + GST_PAD_STREAM_UNLOCK (parse->srcpad); + break; + } + + /* FIXME: Would it be more efficient to make a subbuffer instead? */ + outbuf = gst_adapter_take_buffer (parse->adapter, fsize); + outbuf = gst_buffer_make_metadata_writable (outbuf); + + /* Subclass may want to know the data offset */ + GST_BUFFER_OFFSET (outbuf) = parse->priv->offset; + parse->priv->offset += fsize; + GST_BUFFER_TIMESTAMP (outbuf) = GST_CLOCK_TIME_NONE; + + /* move along with upstream timestamp (if any), + * but interpolate in between */ + timestamp = gst_adapter_prev_timestamp (parse->adapter, NULL); + if (GST_CLOCK_TIME_IS_VALID (timestamp) && + (parse->priv->prev_ts != timestamp)) { + parse->priv->prev_ts = parse->priv->next_ts = timestamp; + } + + ret = gst_base_parse_handle_and_push_buffer (parse, bclass, outbuf); + GST_PAD_STREAM_UNLOCK (parse->srcpad); + + if (ret != GST_FLOW_OK) { + GST_LOG_OBJECT (parse, "push returned %d", ret); + break; + } + } + +done: + GST_LOG_OBJECT (parse, "chain leaving"); + return ret; +} + +/* pull @size bytes at current offset, + * i.e. at least try to and possibly return a shorter buffer if near the end */ +static GstFlowReturn +gst_base_parse_pull_range (GstBaseParse * parse, guint size, + GstBuffer ** buffer) +{ + GstFlowReturn ret = GST_FLOW_OK; + + g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR); + + /* Caching here actually makes much less difference than one would expect. + * We do it mainly to avoid pulling buffers of 1 byte all the time */ + if (parse->priv->cache) { + gint64 cache_offset = GST_BUFFER_OFFSET (parse->priv->cache); + gint cache_size = GST_BUFFER_SIZE (parse->priv->cache); + + if (cache_offset <= parse->priv->offset && + (parse->priv->offset + size) <= (cache_offset + cache_size)) { + *buffer = gst_buffer_create_sub (parse->priv->cache, + parse->priv->offset - cache_offset, size); + GST_BUFFER_OFFSET (*buffer) = parse->priv->offset; + return GST_FLOW_OK; + } + /* not enough data in the cache, free cache and get a new one */ + gst_buffer_unref (parse->priv->cache); + parse->priv->cache = NULL; + } + + /* refill the cache */ + ret = + gst_pad_pull_range (parse->sinkpad, parse->priv->offset, MAX (size, + 64 * 1024), &parse->priv->cache); + if (ret != GST_FLOW_OK) { + parse->priv->cache = NULL; + return ret; + } + + if (GST_BUFFER_SIZE (parse->priv->cache) >= size) { + *buffer = gst_buffer_create_sub (parse->priv->cache, 0, size); + GST_BUFFER_OFFSET (*buffer) = parse->priv->offset; + return GST_FLOW_OK; + } + + /* Not possible to get enough data, try a last time with + * requesting exactly the size we need */ + gst_buffer_unref (parse->priv->cache); + parse->priv->cache = NULL; + + ret = gst_pad_pull_range (parse->sinkpad, parse->priv->offset, size, + &parse->priv->cache); + + if (ret != GST_FLOW_OK) { + GST_DEBUG_OBJECT (parse, "pull_range returned %d", ret); + *buffer = NULL; + return ret; + } + + if (GST_BUFFER_SIZE (parse->priv->cache) < size) { + GST_DEBUG_OBJECT (parse, "Returning short buffer at offset %" + G_GUINT64_FORMAT ": wanted %u bytes, got %u bytes", parse->priv->offset, + size, GST_BUFFER_SIZE (parse->priv->cache)); + + *buffer = parse->priv->cache; + parse->priv->cache = NULL; + + return GST_FLOW_OK; + } + + *buffer = gst_buffer_create_sub (parse->priv->cache, 0, size); + GST_BUFFER_OFFSET (*buffer) = parse->priv->offset; + + return GST_FLOW_OK; +} + +static GstFlowReturn +gst_base_parse_handle_previous_fragment (GstBaseParse * parse) +{ + gint64 offset = 0; + GstClockTime ts = 0; + GstBuffer *buffer; + GstFlowReturn ret; + + GST_DEBUG_OBJECT (parse, "fragment ended; last_ts = %" GST_TIME_FORMAT + ", last_offset = %" G_GINT64_FORMAT, GST_TIME_ARGS (parse->priv->last_ts), + parse->priv->last_offset); + + if (!parse->priv->last_offset || parse->priv->last_ts <= parse->segment.start) { + GST_DEBUG_OBJECT (parse, "past start of segment %" GST_TIME_FORMAT, + GST_TIME_ARGS (parse->segment.start)); + ret = GST_FLOW_UNEXPECTED; + goto exit; + } + + /* last fragment started at last_offset / last_ts; + * seek back 10s capped at 1MB */ + if (parse->priv->last_ts >= 10 * GST_SECOND) + ts = parse->priv->last_ts - 10 * GST_SECOND; + /* if we are exact now, we will be more so going backwards */ + if (parse->priv->exact_position) { + offset = gst_base_parse_find_offset (parse, ts, TRUE, NULL); + } else { + GstFormat dstformat = GST_FORMAT_BYTES; + + if (!gst_pad_query_convert (parse->srcpad, GST_FORMAT_TIME, ts, + &dstformat, &offset)) { + GST_DEBUG_OBJECT (parse, "conversion failed, only BYTE based"); + } + } + offset = CLAMP (offset, parse->priv->last_offset - 1024 * 1024, + parse->priv->last_offset - 1024); + offset = MAX (0, offset); + + GST_DEBUG_OBJECT (parse, "next fragment from offset %" G_GINT64_FORMAT, + offset); + parse->priv->offset = offset; + + ret = gst_base_parse_pull_range (parse, parse->priv->last_offset - offset, + &buffer); + if (ret != GST_FLOW_OK) + goto exit; + + /* offset will increase again as fragment is processed/parsed */ + parse->priv->last_offset = offset; + + gst_adapter_push (parse->adapter, buffer); + ret = gst_base_parse_process_fragment (parse, FALSE); + if (ret != GST_FLOW_OK) + goto exit; + + /* force previous fragment */ + parse->priv->offset = -1; + +exit: + return ret; +} + +/* PULL mode: + * pull and scan for next frame starting from current offset + * ajusts sync, drain and offset going along */ +static GstFlowReturn +gst_base_parse_scan_frame (GstBaseParse * parse, GstBaseParseClass * klass, + GstBuffer ** buf, gboolean full) +{ + GstBuffer *buffer, *outbuf; + GstFlowReturn ret = GST_FLOW_OK; + guint fsize = 0, min_size; + gint skip = 0; + + g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR); + + while (TRUE) { + + min_size = parse->priv->min_frame_size; + + ret = gst_base_parse_pull_range (parse, min_size, &buffer); + if (ret != GST_FLOW_OK) + goto done; + + if (parse->priv->discont) { + GST_DEBUG_OBJECT (parse, "marking DISCONT"); + GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT); + } + + /* if we got a short read, inform subclass we are draining leftover + * and no more is to be expected */ + if (GST_BUFFER_SIZE (buffer) < min_size) + parse->priv->drain = TRUE; + + skip = -1; + if (klass->check_valid_frame (parse, buffer, &fsize, &skip)) { + parse->priv->drain = FALSE; + break; + } + parse->priv->drain = FALSE; + if (skip == -1) + skip = 1; + if (skip > 0) { + GST_LOG_OBJECT (parse, "finding sync, skipping %d bytes", skip); + if (full && parse->segment.rate < 0.0 && !parse->priv->buffers_queued) { + /* reverse playback, and no frames found yet, so we are skipping + * the leading part of a fragment, which may form the tail of + * fragment coming later, hopefully subclass skips efficiently ... */ + outbuf = gst_buffer_create_sub (buffer, 0, skip); + parse->priv->buffers_pending = + g_slist_prepend (parse->priv->buffers_pending, outbuf); + outbuf = NULL; + } + parse->priv->offset += skip; + if (!parse->priv->discont) + parse->priv->sync_offset = parse->priv->offset; + parse->priv->discont = TRUE; + } + /* skip == 0 should imply subclass set min_size to need more data ... */ + GST_DEBUG_OBJECT (parse, "finding sync..."); + gst_buffer_unref (buffer); + if ((ret = gst_base_parse_check_sync (parse)) != GST_FLOW_OK) { + goto done; + } + } + + if (fsize <= GST_BUFFER_SIZE (buffer)) { + outbuf = gst_buffer_create_sub (buffer, 0, fsize); + GST_BUFFER_OFFSET (outbuf) = GST_BUFFER_OFFSET (buffer); + GST_BUFFER_TIMESTAMP (outbuf) = GST_CLOCK_TIME_NONE; + gst_buffer_unref (buffer); + } else { + gst_buffer_unref (buffer); + ret = gst_base_parse_pull_range (parse, fsize, &outbuf); + if (ret != GST_FLOW_OK) + goto done; + if (GST_BUFFER_SIZE (outbuf) < fsize) { + gst_buffer_unref (outbuf); + ret = GST_FLOW_UNEXPECTED; + } + } + + parse->priv->offset += fsize; + + /* Does the subclass want to skip too? */ + if (skip > 0) + parse->priv->offset += skip; + + *buf = outbuf; + +done: + return ret; +} + +/** + * gst_base_parse_loop: + * @pad: GstPad + * + * Loop that is used in pull mode to retrieve data from upstream. + */ +static void +gst_base_parse_loop (GstPad * pad) +{ + GstBaseParse *parse; + GstBaseParseClass *klass; + GstBuffer *outbuf; + GstFlowReturn ret = GST_FLOW_OK; + + parse = GST_BASE_PARSE (gst_pad_get_parent (pad)); + klass = GST_BASE_PARSE_GET_CLASS (parse); + + /* reverse playback: + * first fragment (closest to stop time) is handled normally below, + * then we pull in fragments going backwards */ + if (parse->segment.rate < 0.0) { + /* check if we jumped back to a previous fragment, + * which is a post-first fragment */ + if (parse->priv->offset < 0) { + ret = gst_base_parse_handle_previous_fragment (parse); + goto done; + } + } + + ret = gst_base_parse_scan_frame (parse, klass, &outbuf, TRUE); + if (ret != GST_FLOW_OK) + goto done; + + /* This always unrefs the outbuf, even if error occurs */ + ret = gst_base_parse_handle_and_push_buffer (parse, klass, outbuf); + + /* eat expected eos signalling past segment in reverse playback */ + if (parse->segment.rate < 0.0 && ret == GST_FLOW_UNEXPECTED && + parse->segment.last_stop >= parse->segment.stop) { + GST_DEBUG_OBJECT (parse, "downstream has reached end of segment"); + /* push what was accumulated during loop run */ + gst_base_parse_process_fragment (parse, TRUE); + /* force previous fragment */ + parse->priv->offset = -1; + ret = GST_FLOW_OK; + } + +done: + if (ret == GST_FLOW_UNEXPECTED) + goto eos; + else if (ret != GST_FLOW_OK) + goto pause; + + gst_object_unref (parse); + return; + + /* ERRORS */ +eos: + { + ret = GST_FLOW_UNEXPECTED; + GST_DEBUG_OBJECT (parse, "eos"); + /* fall-through */ + } +pause: + { + gboolean push_eos = FALSE; + + GST_DEBUG_OBJECT (parse, "pausing task, reason %s", + gst_flow_get_name (ret)); + gst_pad_pause_task (parse->sinkpad); + + if (ret == GST_FLOW_UNEXPECTED) { + /* handle end-of-stream/segment */ + if (parse->segment.flags & GST_SEEK_FLAG_SEGMENT) { + gint64 stop; + + if ((stop = parse->segment.stop) == -1) + stop = parse->segment.duration; + + GST_DEBUG_OBJECT (parse, "sending segment_done"); + + gst_element_post_message + (GST_ELEMENT_CAST (parse), + gst_message_new_segment_done (GST_OBJECT_CAST (parse), + GST_FORMAT_TIME, stop)); + } else { + /* If we STILL have zero frames processed, fire an error */ + if (parse->priv->framecount == 0) { + GST_ELEMENT_ERROR (parse, STREAM, WRONG_TYPE, + ("No valid frames found before end of stream"), (NULL)); + } + push_eos = TRUE; + } + } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_UNEXPECTED) { + /* for fatal errors we post an error message, wrong-state is + * not fatal because it happens due to flushes and only means + * that we should stop now. */ + GST_ELEMENT_ERROR (parse, STREAM, FAILED, (NULL), + ("streaming stopped, reason %s", gst_flow_get_name (ret))); + push_eos = TRUE; + } + if (push_eos) { + /* newsegment before eos */ + if (parse->pending_segment) { + gst_pad_push_event (parse->srcpad, parse->pending_segment); + parse->pending_segment = NULL; + } + gst_pad_push_event (parse->srcpad, gst_event_new_eos ()); + } + gst_object_unref (parse); + } +} + + +/** + * gst_base_parse_sink_activate: + * @sinkpad: #GstPad to be activated. + * + * Returns: TRUE if activation succeeded. + */ +static gboolean +gst_base_parse_sink_activate (GstPad * sinkpad) +{ + GstBaseParse *parse; + gboolean result = TRUE; + + parse = GST_BASE_PARSE (gst_pad_get_parent (sinkpad)); + + GST_DEBUG_OBJECT (parse, "sink activate"); + + if (gst_pad_check_pull_range (sinkpad)) { + GST_DEBUG_OBJECT (parse, "trying to activate in pull mode"); + result = gst_pad_activate_pull (sinkpad, TRUE); + } else { + GST_DEBUG_OBJECT (parse, "trying to activate in push mode"); + result = gst_pad_activate_push (sinkpad, TRUE); + } + + GST_DEBUG_OBJECT (parse, "sink activate return %d", result); + gst_object_unref (parse); + return result; +} + + +/** + * gst_base_parse_activate: + * @parse: #GstBaseParse. + * @active: TRUE if element will be activated, FALSE if deactivated. + * + * Returns: TRUE if the operation succeeded. + */ +static gboolean +gst_base_parse_activate (GstBaseParse * parse, gboolean active) +{ + GstBaseParseClass *klass; + gboolean result = FALSE; + + GST_DEBUG_OBJECT (parse, "activate"); + + klass = GST_BASE_PARSE_GET_CLASS (parse); + + if (active) { + if (parse->priv->pad_mode == GST_ACTIVATE_NONE && klass->start) + result = klass->start (parse); + } else { + /* We must make sure streaming has finished before resetting things + * and calling the ::stop vfunc */ + GST_PAD_STREAM_LOCK (parse->sinkpad); + GST_PAD_STREAM_UNLOCK (parse->sinkpad); + + if (parse->priv->pad_mode != GST_ACTIVATE_NONE && klass->stop) + result = klass->stop (parse); + + parse->priv->pad_mode = GST_ACTIVATE_NONE; + } + GST_DEBUG_OBJECT (parse, "activate: %d", result); + return result; +} + + +/** + * gst_base_parse_sink_activate_push: + * @pad: #GstPad to be (de)activated. + * @active: TRUE when activating, FALSE when deactivating. + * + * Returns: TRUE if (de)activation succeeded. + */ +static gboolean +gst_base_parse_sink_activate_push (GstPad * pad, gboolean active) +{ + gboolean result = TRUE; + GstBaseParse *parse; + + parse = GST_BASE_PARSE (gst_pad_get_parent (pad)); + + GST_DEBUG_OBJECT (parse, "sink activate push"); + + result = gst_base_parse_activate (parse, active); + + if (result) + parse->priv->pad_mode = active ? GST_ACTIVATE_PUSH : GST_ACTIVATE_NONE; + + GST_DEBUG_OBJECT (parse, "sink activate push: %d", result); + + gst_object_unref (parse); + return result; +} + + +/** + * gst_base_parse_sink_activate_pull: + * @sinkpad: #GstPad to be (de)activated. + * @active: TRUE when activating, FALSE when deactivating. + * + * Returns: TRUE if (de)activation succeeded. + */ +static gboolean +gst_base_parse_sink_activate_pull (GstPad * sinkpad, gboolean active) +{ + gboolean result = FALSE; + GstBaseParse *parse; + + parse = GST_BASE_PARSE (gst_pad_get_parent (sinkpad)); + + GST_DEBUG_OBJECT (parse, "activate pull"); + + result = gst_base_parse_activate (parse, active); + + if (result) { + if (active) { + parse->pending_segment = gst_event_new_new_segment (FALSE, + parse->segment.rate, parse->segment.format, + parse->segment.start, parse->segment.stop, parse->segment.last_stop); + result &= gst_pad_start_task (sinkpad, + (GstTaskFunction) gst_base_parse_loop, sinkpad); + } else { + result &= gst_pad_stop_task (sinkpad); + } + } + + if (result) + parse->priv->pad_mode = active ? GST_ACTIVATE_PULL : GST_ACTIVATE_NONE; + + GST_DEBUG_OBJECT (parse, "sink activate pull: %d", result); + + gst_object_unref (parse); + return result; +} + + +/** + * gst_base_parse_set_duration: + * @parse: #GstBaseParse. + * @fmt: #GstFormat. + * @duration: duration value. + * + * Sets the duration of the currently playing media. Subclass can use this + * when it is able to determine duration and/or notices a change in the media + * duration. Alternatively, if @interval is non-zero (default), then stream + * duration is determined based on estimated bitrate, and updated every @interval + * frames. */ +void +gst_base_parse_set_duration (GstBaseParse * parse, + GstFormat fmt, gint64 duration, gint interval) +{ + g_return_if_fail (parse != NULL); + + if (parse->priv->upstream_has_duration) { + GST_DEBUG_OBJECT (parse, "using upstream duration; discarding update"); + goto exit; + } + + if (duration != parse->priv->duration) { + GstMessage *m; + + m = gst_message_new_duration (GST_OBJECT (parse), fmt, duration); + gst_element_post_message (GST_ELEMENT (parse), m); + + /* TODO: what about duration tag? */ + } + parse->priv->duration = duration; + parse->priv->duration_fmt = fmt; + GST_DEBUG_OBJECT (parse, "set duration: %" G_GINT64_FORMAT, duration); + if (fmt == GST_FORMAT_TIME && GST_CLOCK_TIME_IS_VALID (duration)) { + if (interval != 0) { + GST_DEBUG_OBJECT (parse, "valid duration provided, disabling estimate"); + interval = 0; + } + } + GST_DEBUG_OBJECT (parse, "set update interval: %d", interval); + parse->priv->update_interval = interval; +exit: + return; +} + +/** + * gst_base_parse_set_seek: + * @parse: #GstBaseParse. + * @seek: #GstBaseParseSeekable. + * @abitrate: average bitrate. + * + * Sets whether and how the media is seekable (in time). + * Also optionally provides average bitrate detected in media (if non-zero), + * e.g. based on metadata, as it will be posted to the application. + * + * By default, announced average bitrate is estimated, and seekability is assumed + * possible based on estimated bitrate. + */ +void +gst_base_parse_set_seek (GstBaseParse * parse, + GstBaseParseSeekable seek, guint bitrate) +{ + parse->priv->seekable = seek; + parse->priv->bitrate = bitrate; + GST_DEBUG_OBJECT (parse, "seek %d, bitrate %d", seek, bitrate); +} + + +/** + * gst_base_parse_set_min_frame_size: + * @parse: #GstBaseParse. + * @min_size: Minimum size of the data that this base class should give to + * subclass. + * + * Subclass can use this function to tell the base class that it needs to + * give at least #min_size buffers. + */ +void +gst_base_parse_set_min_frame_size (GstBaseParse * parse, guint min_size) +{ + g_return_if_fail (parse != NULL); + + parse->priv->min_frame_size = min_size; + GST_LOG_OBJECT (parse, "set frame_min_size: %d", min_size); +} + +/** + * gst_base_transform_set_passthrough: + * @trans: the #GstBaseParse to set + * @passthrough: boolean indicating passthrough mode. + * + * Set passthrough mode for this parser. If operating in passthrough, + * incoming buffers are pushed through unmodified. + */ +void +gst_base_parse_set_passthrough (GstBaseParse * parse, gboolean passthrough) +{ + g_return_if_fail (parse != NULL); + + parse->priv->passthrough = passthrough; + GST_LOG_OBJECT (parse, "set passthrough: %d", passthrough); +} + +/** + * gst_base_transform_set_frame_props: + * @parse: the #GstBaseParse to set + * @fps_num: frames per second (numerator). + * @fps_den: frames per second (denominator). + * @lead_in: frames needed before a segment for subsequent decode + * @lead_out: frames needed after a segment + * + * If frames per second is configured, parser can take care of buffer duration + * and timestamping. When performing segment clipping, or seeking to a specific + * location, a corresponding decoder might need an initial @lead_in and a + * following @lead_out number of frames to ensure the desired segment is + * entirely filled upon decoding. + */ +void +gst_base_parse_set_frame_props (GstBaseParse * parse, guint fps_num, + guint fps_den, guint lead_in, guint lead_out) +{ + g_return_if_fail (parse != NULL); + + parse->priv->fps_num = fps_num; + parse->priv->fps_den = fps_den; + if (!fps_num || !fps_den) { + GST_DEBUG_OBJECT (parse, "invalid fps (%d/%d), ignoring parameters", + fps_num, fps_den); + fps_num = fps_den = 0; + parse->priv->frame_duration = GST_CLOCK_TIME_NONE; + parse->priv->lead_in = parse->priv->lead_out = 0; + parse->priv->lead_in_ts = parse->priv->lead_out_ts = 0; + } else { + parse->priv->frame_duration = + gst_util_uint64_scale (GST_SECOND, fps_den, fps_num); + parse->priv->lead_in = lead_in; + parse->priv->lead_out = lead_out; + parse->priv->lead_in_ts = + gst_util_uint64_scale (GST_SECOND, fps_den * lead_in, fps_num); + parse->priv->lead_out_ts = + gst_util_uint64_scale (GST_SECOND, fps_den * lead_out, fps_num); + } + GST_LOG_OBJECT (parse, "set fps: %d/%d => duration: %" G_GINT64_FORMAT " ms", + fps_num, fps_den, parse->priv->frame_duration / GST_MSECOND); + GST_LOG_OBJECT (parse, "set lead in: %d frames = %" G_GUINT64_FORMAT " ms, " + "lead out: %d frames = %" G_GUINT64_FORMAT " ms", + lead_in, parse->priv->lead_in_ts / GST_MSECOND, + lead_out, parse->priv->lead_out_ts / GST_MSECOND); +} + +/** + * gst_base_transform_get_sync: + * @parse: the #GstBaseParse to query + * + * Returns: TRUE if parser is considered 'in sync'. That is, frames have been + * continuously successfully parsed and pushed. + */ +gboolean +gst_base_parse_get_sync (GstBaseParse * parse) +{ + gboolean ret; + + g_return_val_if_fail (parse != NULL, FALSE); + + /* losing sync is pretty much a discont (and vice versa), no ? */ + ret = !parse->priv->discont; + + GST_DEBUG_OBJECT (parse, "sync: %d", ret); + return ret; +} + +/** + * gst_base_transform_get_drain: + * @parse: the #GstBaseParse to query + * + * Returns: TRUE if parser is currently 'draining'. That is, leftover data + * (e.g. in FLUSH or EOS situation) is being parsed. + */ +gboolean +gst_base_parse_get_drain (GstBaseParse * parse) +{ + gboolean ret; + + g_return_val_if_fail (parse != NULL, FALSE); + + /* losing sync is pretty much a discont (and vice versa), no ? */ + ret = parse->priv->drain; + + GST_DEBUG_OBJECT (parse, "drain: %d", ret); + return ret; +} + +static gboolean +gst_base_parse_get_duration (GstBaseParse * parse, GstFormat format, + GstClockTime * duration) +{ + gboolean res = FALSE; + + g_return_val_if_fail (duration != NULL, FALSE); + + *duration = GST_CLOCK_TIME_NONE; + if (parse->priv->duration != -1 && format == parse->priv->duration_fmt) { + GST_LOG_OBJECT (parse, "using provided duration"); + *duration = parse->priv->duration; + res = TRUE; + } else if (parse->priv->duration != -1) { + GST_LOG_OBJECT (parse, "converting provided duration"); + res = gst_base_parse_convert (parse, parse->priv->duration_fmt, + parse->priv->duration, format, (gint64 *) duration); + } else if (format == GST_FORMAT_TIME && parse->priv->estimated_duration != -1) { + GST_LOG_OBJECT (parse, "using estimated duration"); + *duration = parse->priv->estimated_duration; + res = TRUE; + } + + GST_LOG_OBJECT (parse, "res: %d, duration %" GST_TIME_FORMAT, res, + GST_TIME_ARGS (*duration)); + return res; +} + +/** + * gst_base_parse_get_querytypes: + * @pad: GstPad + * + * Returns: A table of #GstQueryType items describing supported query types. + */ +static const GstQueryType * +gst_base_parse_get_querytypes (GstPad * pad) +{ + static const GstQueryType list[] = { + GST_QUERY_POSITION, + GST_QUERY_DURATION, + GST_QUERY_FORMATS, + GST_QUERY_SEEKING, + GST_QUERY_CONVERT, + 0 + }; + + return list; +} + + +/** + * gst_base_parse_query: + * @pad: #GstPad. + * @query: #GstQuery. + * + * Returns: TRUE on success. + */ +static gboolean +gst_base_parse_query (GstPad * pad, GstQuery * query) +{ + GstBaseParse *parse; + gboolean res = FALSE; + + parse = GST_BASE_PARSE (GST_PAD_PARENT (pad)); + + GST_LOG_OBJECT (parse, "handling query: %" GST_PTR_FORMAT, query); + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_POSITION: + { + gint64 dest_value; + GstFormat format; + + GST_DEBUG_OBJECT (parse, "position query"); + gst_query_parse_position (query, &format, NULL); + + GST_OBJECT_LOCK (parse); + if (format == GST_FORMAT_BYTES) { + dest_value = parse->priv->offset; + res = TRUE; + } else if (format == parse->segment.format && + GST_CLOCK_TIME_IS_VALID (parse->segment.last_stop)) { + dest_value = parse->segment.last_stop; + res = TRUE; + } + GST_OBJECT_UNLOCK (parse); + + if (res) + gst_query_set_position (query, format, dest_value); + else { + res = gst_pad_query_default (pad, query); + if (!res) { + /* no precise result, upstream no idea either, then best estimate */ + /* priv->offset is updated in both PUSH/PULL modes */ + res = gst_base_parse_convert (parse, + GST_FORMAT_BYTES, parse->priv->offset, format, &dest_value); + } + } + break; + } + case GST_QUERY_DURATION: + { + GstFormat format; + GstClockTime duration; + + GST_DEBUG_OBJECT (parse, "duration query"); + gst_query_parse_duration (query, &format, NULL); + + /* consult upstream */ + res = gst_pad_query_default (pad, query); + + /* otherwise best estimate from us */ + if (!res) { + res = gst_base_parse_get_duration (parse, format, &duration); + if (res) + gst_query_set_duration (query, format, duration); + } + break; + } + case GST_QUERY_SEEKING: + { + GstFormat fmt; + GstClockTime duration = GST_CLOCK_TIME_NONE; + gboolean seekable = FALSE; + + GST_DEBUG_OBJECT (parse, "seeking query"); + gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL); + + /* consult upstream */ + res = gst_pad_query_default (pad, query); + + /* we may be able to help if in TIME */ + if (fmt == GST_FORMAT_TIME && + parse->priv->seekable > GST_BASE_PARSE_SEEK_NONE) { + gst_query_parse_seeking (query, &fmt, &seekable, NULL, NULL); + /* already OK if upstream takes care */ + GST_LOG_OBJECT (parse, "upstream handled %d, seekable %d", + res, seekable); + if (!(res && seekable)) { + if (!gst_base_parse_get_duration (parse, GST_FORMAT_TIME, &duration) + || duration == -1) { + seekable = FALSE; + } else { + seekable = parse->priv->upstream_seekable; + GST_LOG_OBJECT (parse, "already determine upstream seekabled: %d", + seekable); + } + gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0, duration); + res = TRUE; + } + } + break; + } + case GST_QUERY_FORMATS: + gst_query_set_formatsv (query, 3, fmtlist); + res = TRUE; + break; + case GST_QUERY_CONVERT: + { + GstFormat src_format, dest_format; + gint64 src_value, dest_value; + + gst_query_parse_convert (query, &src_format, &src_value, + &dest_format, &dest_value); + + res = gst_base_parse_convert (parse, src_format, src_value, + dest_format, &dest_value); + if (res) { + gst_query_set_convert (query, src_format, src_value, + dest_format, dest_value); + } + break; + } + default: + res = gst_pad_query_default (pad, query); + break; + } + return res; +} + +/* scans for a cluster start from @pos, + * return GST_FLOW_OK and frame position/time in @pos/@time if found */ +static GstFlowReturn +gst_base_parse_find_frame (GstBaseParse * parse, gint64 * pos, + GstClockTime * time, GstClockTime * duration) +{ + GstBaseParseClass *klass; + gint64 orig_offset; + gboolean orig_drain, orig_discont; + GstFlowReturn ret = GST_FLOW_OK; + GstBuffer *buf = NULL; + + g_return_val_if_fail (GST_FLOW_ERROR, pos != NULL); + g_return_val_if_fail (GST_FLOW_ERROR, time != NULL); + g_return_val_if_fail (GST_FLOW_ERROR, duration != NULL); + + klass = GST_BASE_PARSE_GET_CLASS (parse); + + *time = GST_CLOCK_TIME_NONE; + *duration = GST_CLOCK_TIME_NONE; + + /* save state */ + orig_offset = parse->priv->offset; + orig_discont = parse->priv->discont; + orig_drain = parse->priv->drain; + + GST_DEBUG_OBJECT (parse, "scanning for frame starting at %" G_GINT64_FORMAT + " (%#" G_GINT64_MODIFIER "x)", *pos, *pos); + + /* jump elsewhere and locate next frame */ + parse->priv->offset = *pos; + ret = gst_base_parse_scan_frame (parse, klass, &buf, FALSE); + if (ret != GST_FLOW_OK) + goto done; + + GST_LOG_OBJECT (parse, + "peek parsing frame at offset %" G_GUINT64_FORMAT + " (%#" G_GINT64_MODIFIER "x) of size %d", + GST_BUFFER_OFFSET (buf), GST_BUFFER_OFFSET (buf), GST_BUFFER_SIZE (buf)); + + /* get offset first, subclass parsing might dump other stuff in there */ + *pos = GST_BUFFER_OFFSET (buf); + ret = klass->parse_frame (parse, buf); + + /* but it should provide proper time */ + *time = GST_BUFFER_TIMESTAMP (buf); + *duration = GST_BUFFER_DURATION (buf); + gst_buffer_unref (buf); + + GST_LOG_OBJECT (parse, + "frame with time %" GST_TIME_FORMAT " at offset %" G_GINT64_FORMAT, + GST_TIME_ARGS (*time), *pos); + +done: + /* restore state */ + parse->priv->offset = orig_offset; + parse->priv->discont = orig_discont; + parse->priv->drain = orig_drain; + + return ret; +} + +/* bisect and scan through file for frame starting before @time, + * returns OK and @time/@offset if found, NONE and/or error otherwise + * If @time == G_MAXINT64, scan for duration ( == last frame) */ +static GstFlowReturn +gst_base_parse_locate_time (GstBaseParse * parse, GstClockTime * _time, + gint64 * _offset) +{ + GstFlowReturn ret = GST_FLOW_OK; + gint64 lpos, hpos, newpos; + GstClockTime time, ltime, htime, newtime, dur; + gboolean cont = TRUE; + const GstClockTime tolerance = TARGET_DIFFERENCE; + const guint chunk = 4 * 1024; + + g_return_val_if_fail (_time != NULL, GST_FLOW_ERROR); + g_return_val_if_fail (_offset != NULL, GST_FLOW_ERROR); + + /* TODO also make keyframe aware if useful some day */ + + time = *_time; + + /* basic cases */ + if (time == 0) { + *_offset = 0; + return GST_FLOW_OK; + } + + if (time == -1) { + *_offset = -1; + return GST_FLOW_OK; + } + + /* do not know at first */ + *_offset = -1; + *_time = GST_CLOCK_TIME_NONE; + + /* need initial positions; start and end */ + lpos = parse->priv->first_frame_offset; + ltime = parse->priv->first_frame_ts; + htime = parse->priv->duration; + hpos = parse->priv->upstream_size; + + /* check preconditions are satisfied; + * start and end are needed, except for special case where we scan for + * last frame to determine duration */ + if (parse->priv->pad_mode != GST_ACTIVATE_PULL || !hpos || + !GST_CLOCK_TIME_IS_VALID (ltime) || + (!GST_CLOCK_TIME_IS_VALID (htime) && time != G_MAXINT64)) { + return GST_FLOW_OK; + } + + /* shortcut cases */ + if (time < ltime) { + goto exit; + } else if (time < ltime + tolerance) { + *_offset = lpos; + *_time = ltime; + goto exit; + } else if (time >= htime) { + *_offset = hpos; + *_time = htime; + goto exit; + } + + while (htime > ltime && cont) { + GST_LOG_OBJECT (parse, + "lpos: %" G_GUINT64_FORMAT ", ltime: %" GST_TIME_FORMAT, lpos, + GST_TIME_ARGS (ltime)); + GST_LOG_OBJECT (parse, + "hpos: %" G_GUINT64_FORMAT ", htime: %" GST_TIME_FORMAT, hpos, + GST_TIME_ARGS (htime)); + if (G_UNLIKELY (time == G_MAXINT64)) { + newpos = hpos; + } else if (G_LIKELY (hpos > lpos)) { + newpos = + gst_util_uint64_scale (hpos - lpos, time - ltime, htime - ltime) + + lpos - chunk; + } else { + newpos = lpos; + /* we check this case once, but not forever, so break loop */ + cont = FALSE; + } + + /* ensure */ + newpos = CLAMP (newpos, lpos, hpos); + GST_LOG_OBJECT (parse, + "estimated _offset for %" GST_TIME_FORMAT ": %" G_GINT64_FORMAT, + GST_TIME_ARGS (time), newpos); + + ret = gst_base_parse_find_frame (parse, &newpos, &newtime, &dur); + if (ret == GST_FLOW_UNEXPECTED) { + /* heuristic HACK */ + hpos = MAX (lpos, hpos - chunk); + continue; + } else if (ret != GST_FLOW_OK) { + goto exit; + } + + if (newtime == -1 || newpos == -1) { + GST_DEBUG_OBJECT (parse, "subclass did not provide metadata; aborting"); + break; + } + + if (G_UNLIKELY (time == G_MAXINT64)) { + *_offset = newpos; + *_time = newtime; + if (GST_CLOCK_TIME_IS_VALID (dur)) + *_time += dur; + break; + } else if (newtime > time) { + /* overshoot */ + newpos -= newpos == hpos ? chunk : 0; + hpos = CLAMP (newpos, lpos, hpos); + htime = newtime; + } else if (newtime + tolerance > time) { + /* close enough undershoot */ + *_offset = newpos; + *_time = newtime; + break; + } else if (newtime < ltime) { + /* so a position beyond lpos resulted in earlier time than ltime ... */ + GST_DEBUG_OBJECT (parse, "non-ascending time; aborting"); + } else { + /* undershoot too far */ + newpos += newpos == hpos ? chunk : 0; + lpos = CLAMP (newpos, lpos, hpos); + ltime = newtime; + } + } + +exit: + GST_LOG_OBJECT (parse, "return offset %" G_GINT64_FORMAT ", time %" + GST_TIME_FORMAT, *_offset, GST_TIME_ARGS (*_time)); + return ret; +} + +static gint64 +gst_base_parse_find_offset (GstBaseParse * parse, GstClockTime time, + gboolean before, GstClockTime * _ts) +{ + gint64 bytes = 0, ts = 0; + GstIndexEntry *entry = NULL; + + if (time == GST_CLOCK_TIME_NONE) { + ts = time; + bytes = -1; + goto exit; + } + + GST_OBJECT_LOCK (parse); + if (parse->priv->index) { + /* Let's check if we have an index entry for that time */ + entry = gst_index_get_assoc_entry (parse->priv->index, + parse->priv->index_id, + before ? GST_INDEX_LOOKUP_BEFORE : GST_INDEX_LOOKUP_AFTER, + GST_ASSOCIATION_FLAG_KEY_UNIT, GST_FORMAT_TIME, time); + } + + if (entry) { + gst_index_entry_assoc_map (entry, GST_FORMAT_BYTES, &bytes); + gst_index_entry_assoc_map (entry, GST_FORMAT_TIME, &ts); + + GST_DEBUG_OBJECT (parse, "found index entry for %" GST_TIME_FORMAT + " at %" GST_TIME_FORMAT ", offset %" G_GINT64_FORMAT, + GST_TIME_ARGS (time), GST_TIME_ARGS (ts), bytes); + } else { + GST_DEBUG_OBJECT (parse, "no index entry found for %" GST_TIME_FORMAT, + GST_TIME_ARGS (time)); + if (!before) { + bytes = -1; + ts = GST_CLOCK_TIME_NONE; + } + } + GST_OBJECT_UNLOCK (parse); + +exit: + if (_ts) + *_ts = ts; + + return bytes; +} + + +/** + * gst_base_parse_handle_seek: + * @parse: #GstBaseParse. + * @event: #GstEvent. + * + * Returns: TRUE if seek succeeded. + */ +static gboolean +gst_base_parse_handle_seek (GstBaseParse * parse, GstEvent * event) +{ + gdouble rate; + GstFormat format; + GstSeekFlags flags; + GstSeekType cur_type = GST_SEEK_TYPE_NONE, stop_type; + gboolean flush, update, res = TRUE, accurate; + gint64 cur, stop, seekpos, seekstop; + GstSegment seeksegment = { 0, }; + GstFormat dstformat; + GstClockTime start_ts; + + gst_event_parse_seek (event, &rate, &format, &flags, + &cur_type, &cur, &stop_type, &stop); + + GST_DEBUG_OBJECT (parse, "seek to format %s, rate %f, " + "start type %d at %" GST_TIME_FORMAT ", end type %d at %" + GST_TIME_FORMAT, gst_format_get_name (format), rate, + cur_type, GST_TIME_ARGS (cur), stop_type, GST_TIME_ARGS (stop)); + + /* no negative rates in push mode */ + if (rate < 0.0 && parse->priv->pad_mode == GST_ACTIVATE_PUSH) + goto negative_rate; + + if (cur_type != GST_SEEK_TYPE_SET || + (stop_type != GST_SEEK_TYPE_SET && stop_type != GST_SEEK_TYPE_NONE)) + goto wrong_type; + + /* For any format other than TIME, see if upstream handles + * it directly or fail. For TIME, try upstream, but do it ourselves if + * it fails upstream */ + if (format != GST_FORMAT_TIME) { + /* default action delegates to upstream */ + return FALSE; + } else { + gst_event_ref (event); + if (gst_pad_push_event (parse->sinkpad, event)) { + return TRUE; + } + } + + /* get flush flag */ + flush = flags & GST_SEEK_FLAG_FLUSH; + + /* copy segment, we need this because we still need the old + * segment when we close the current segment. */ + memcpy (&seeksegment, &parse->segment, sizeof (GstSegment)); + + GST_DEBUG_OBJECT (parse, "configuring seek"); + gst_segment_set_seek (&seeksegment, rate, format, flags, + cur_type, cur, stop_type, stop, &update); + + /* accurate seeking implies seek tables are used to obtain position, + * and the requested segment is maintained exactly, not adjusted any way */ + accurate = flags & GST_SEEK_FLAG_ACCURATE; + + /* maybe we can be accurate for (almost) free */ + gst_base_parse_find_offset (parse, seeksegment.last_stop, TRUE, &start_ts); + if (seeksegment.last_stop <= start_ts + TARGET_DIFFERENCE) { + GST_DEBUG_OBJECT (parse, "accurate seek possible"); + accurate = TRUE; + } + if (accurate) { + GstClockTime startpos = seeksegment.last_stop; + + /* accurate requested, so ... seek a bit before target */ + if (startpos < parse->priv->lead_in_ts) + startpos = 0; + else + startpos -= parse->priv->lead_in_ts; + seekpos = gst_base_parse_find_offset (parse, startpos, TRUE, &start_ts); + seekstop = gst_base_parse_find_offset (parse, seeksegment.stop, FALSE, + NULL); + } else { + start_ts = seeksegment.last_stop; + dstformat = GST_FORMAT_BYTES; + if (!gst_pad_query_convert (parse->srcpad, format, seeksegment.last_stop, + &dstformat, &seekpos)) + goto convert_failed; + if (!gst_pad_query_convert (parse->srcpad, format, seeksegment.stop, + &dstformat, &seekstop)) + goto convert_failed; + } + + GST_DEBUG_OBJECT (parse, + "seek position %" G_GINT64_FORMAT " in bytes: %" G_GINT64_FORMAT, + start_ts, seekpos); + GST_DEBUG_OBJECT (parse, + "seek stop %" G_GINT64_FORMAT " in bytes: %" G_GINT64_FORMAT, + seeksegment.stop, seekstop); + + if (parse->priv->pad_mode == GST_ACTIVATE_PULL) { + gint64 last_stop; + + GST_DEBUG_OBJECT (parse, "seek in PULL mode"); + + if (flush) { + if (parse->srcpad) { + GST_DEBUG_OBJECT (parse, "sending flush start"); + gst_pad_push_event (parse->srcpad, gst_event_new_flush_start ()); + /* unlock upstream pull_range */ + gst_pad_push_event (parse->sinkpad, gst_event_new_flush_start ()); + } + } else { + gst_pad_pause_task (parse->sinkpad); + } + + /* we should now be able to grab the streaming thread because we stopped it + * with the above flush/pause code */ + GST_PAD_STREAM_LOCK (parse->sinkpad); + + /* save current position */ + last_stop = parse->segment.last_stop; + GST_DEBUG_OBJECT (parse, "stopped streaming at %" G_GINT64_FORMAT, + last_stop); + + /* now commit to new position */ + + /* prepare for streaming again */ + if (flush) { + GST_DEBUG_OBJECT (parse, "sending flush stop"); + gst_pad_push_event (parse->srcpad, gst_event_new_flush_stop ()); + gst_pad_push_event (parse->sinkpad, gst_event_new_flush_stop ()); + gst_base_parse_clear_queues (parse); + } else { + if (parse->close_segment) + gst_event_unref (parse->close_segment); + + parse->close_segment = gst_event_new_new_segment (TRUE, + parse->segment.rate, parse->segment.format, + parse->segment.accum, parse->segment.last_stop, parse->segment.accum); + + /* keep track of our last_stop */ + seeksegment.accum = parse->segment.last_stop; + + GST_DEBUG_OBJECT (parse, "Created close seg format %d, " + "start = %" GST_TIME_FORMAT ", stop = %" GST_TIME_FORMAT + ", pos = %" GST_TIME_FORMAT, format, + GST_TIME_ARGS (parse->segment.accum), + GST_TIME_ARGS (parse->segment.last_stop), + GST_TIME_ARGS (parse->segment.accum)); + } + + memcpy (&parse->segment, &seeksegment, sizeof (GstSegment)); + + /* store the newsegment event so it can be sent from the streaming thread. */ + if (parse->pending_segment) + gst_event_unref (parse->pending_segment); + + /* This will be sent later in _loop() */ + parse->pending_segment = + gst_event_new_new_segment (FALSE, parse->segment.rate, + parse->segment.format, parse->segment.start, parse->segment.stop, + parse->segment.start); + + GST_DEBUG_OBJECT (parse, "Created newseg format %d, " + "start = %" GST_TIME_FORMAT ", stop = %" GST_TIME_FORMAT + ", pos = %" GST_TIME_FORMAT, format, + GST_TIME_ARGS (parse->segment.start), + GST_TIME_ARGS (parse->segment.stop), + GST_TIME_ARGS (parse->segment.start)); + + /* one last chance in pull mode to stay accurate; + * maybe scan and subclass can find where to go */ + if (!accurate) { + gint64 scanpos; + GstClockTime ts = seeksegment.last_stop; + + gst_base_parse_locate_time (parse, &ts, &scanpos); + if (scanpos >= 0) { + accurate = TRUE; + seekpos = scanpos; + /* running collected index now consists of several intervals, + * so optimized check no longer possible */ + parse->priv->index_last_valid = FALSE; + parse->priv->index_last_offset = 0; + parse->priv->index_last_ts = 0; + } + } + + /* mark discont if we are going to stream from another position. */ + if (seekpos != parse->priv->offset) { + GST_DEBUG_OBJECT (parse, + "mark DISCONT, we did a seek to another position"); + parse->priv->offset = seekpos; + parse->priv->last_offset = seekpos; + parse->priv->seen_keyframe = FALSE; + parse->priv->discont = TRUE; + parse->priv->next_ts = start_ts; + parse->priv->last_ts = GST_CLOCK_TIME_NONE; + parse->priv->sync_offset = seekpos; + parse->priv->exact_position = accurate; + } + + /* Start streaming thread if paused */ + gst_pad_start_task (parse->sinkpad, + (GstTaskFunction) gst_base_parse_loop, parse->sinkpad); + + GST_PAD_STREAM_UNLOCK (parse->sinkpad); + } else { + GstEvent *new_event; + GstBaseParseSeek *seek; + + /* The only thing we need to do in PUSH-mode is to send the + seek event (in bytes) to upstream. Segment / flush handling happens + in corresponding src event handlers */ + GST_DEBUG_OBJECT (parse, "seek in PUSH mode"); + if (seekstop >= 0 && seekpos <= seekpos) + seekstop = seekpos; + new_event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flush, + GST_SEEK_TYPE_SET, seekpos, stop_type, seekstop); + + /* store segment info so its precise details can be reconstructed when + * receiving newsegment; + * this matters for all details when accurate seeking, + * is most useful to preserve NONE stop time otherwise */ + seek = g_new0 (GstBaseParseSeek, 1); + seek->segment = seeksegment; + seek->accurate = accurate; + seek->offset = seekpos; + seek->start_ts = start_ts; + GST_OBJECT_LOCK (parse); + /* less optimal, but preserves order */ + parse->priv->pending_seeks = + g_slist_append (parse->priv->pending_seeks, seek); + GST_OBJECT_UNLOCK (parse); + + res = gst_pad_push_event (parse->sinkpad, new_event); + + if (!res) { + GST_OBJECT_LOCK (parse); + parse->priv->pending_seeks = + g_slist_remove (parse->priv->pending_seeks, seek); + GST_OBJECT_UNLOCK (parse); + g_free (seek); + } + } + +done: + return res; + + /* ERRORS */ +negative_rate: + { + GST_DEBUG_OBJECT (parse, "negative playback rates are not supported yet."); + res = FALSE; + goto done; + } +wrong_type: + { + GST_DEBUG_OBJECT (parse, "unsupported seek type."); + res = FALSE; + goto done; + } +convert_failed: + { + GST_DEBUG_OBJECT (parse, "conversion TIME to BYTES failed."); + res = FALSE; + goto done; + } +} + +/** + * gst_base_parse_handle_tag: + * @parse: #GstBaseParse. + * @event: #GstEvent. + * + * Checks if bitrates are available from upstream tags so that we don't + * override them later + */ +static void +gst_base_parse_handle_tag (GstBaseParse * parse, GstEvent * event) +{ + GstTagList *taglist = NULL; + guint tmp; + + gst_event_parse_tag (event, &taglist); + + if (gst_tag_list_get_uint (taglist, GST_TAG_MINIMUM_BITRATE, &tmp)) { + GST_DEBUG_OBJECT (parse, "upstream min bitrate %d", tmp); + parse->priv->post_min_bitrate = FALSE; + } + if (gst_tag_list_get_uint (taglist, GST_TAG_BITRATE, &tmp)) { + GST_DEBUG_OBJECT (parse, "upstream avg bitrate %d", tmp); + parse->priv->post_avg_bitrate = FALSE; + } + if (gst_tag_list_get_uint (taglist, GST_TAG_MAXIMUM_BITRATE, &tmp)) { + GST_DEBUG_OBJECT (parse, "upstream max bitrate %d", tmp); + parse->priv->post_max_bitrate = FALSE; + } +} + +/** + * gst_base_parse_sink_setcaps: + * @pad: #GstPad. + * @caps: #GstCaps. + * + * Returns: TRUE if caps were accepted. + */ +static gboolean +gst_base_parse_sink_setcaps (GstPad * pad, GstCaps * caps) +{ + GstBaseParse *parse; + GstBaseParseClass *klass; + gboolean res = TRUE; + + parse = GST_BASE_PARSE (GST_PAD_PARENT (pad)); + klass = GST_BASE_PARSE_GET_CLASS (parse); + + GST_DEBUG_OBJECT (parse, "caps: %" GST_PTR_FORMAT, caps); + + if (klass->set_sink_caps) + res = klass->set_sink_caps (parse, caps); + + return res && gst_pad_set_caps (pad, caps); +} + +static void +gst_base_parse_set_index (GstElement * element, GstIndex * index) +{ + GstBaseParse *parse = GST_BASE_PARSE (element); + + GST_OBJECT_LOCK (parse); + if (parse->priv->index) + gst_object_unref (parse->priv->index); + if (index) { + parse->priv->index = gst_object_ref (index); + gst_index_get_writer_id (index, GST_OBJECT (element), + &parse->priv->index_id); + parse->priv->own_index = FALSE; + } else + parse->priv->index = NULL; + GST_OBJECT_UNLOCK (parse); +} + +static GstIndex * +gst_base_parse_get_index (GstElement * element) +{ + GstBaseParse *parse = GST_BASE_PARSE (element); + GstIndex *result = NULL; + + GST_OBJECT_LOCK (parse); + if (parse->priv->index) + result = gst_object_ref (parse->priv->index); + GST_OBJECT_UNLOCK (parse); + + return result; +} + +static GstStateChangeReturn +gst_base_parse_change_state (GstElement * element, GstStateChange transition) +{ + GstBaseParse *parse; + GstStateChangeReturn result; + + parse = GST_BASE_PARSE (element); + + switch (transition) { + case GST_STATE_CHANGE_READY_TO_PAUSED: + /* If this is our own index destroy it as the + * old entries might be wrong for the new stream */ + if (parse->priv->own_index) { + gst_object_unref (parse->priv->index); + parse->priv->index = NULL; + parse->priv->own_index = FALSE; + } + + /* If no index was created, generate one */ + if (G_UNLIKELY (!parse->priv->index)) { + GST_DEBUG_OBJECT (parse, "no index provided creating our own"); + + parse->priv->index = gst_index_factory_make ("memindex"); + gst_index_get_writer_id (parse->priv->index, GST_OBJECT (parse), + &parse->priv->index_id); + parse->priv->own_index = TRUE; + } + break; + default: + break; + } + + result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + + switch (transition) { + case GST_STATE_CHANGE_PAUSED_TO_READY: + gst_base_parse_reset (parse); + break; + default: + break; + } + + return result; +} diff --git a/gst/h263parse/gstbaseparse.h b/gst/h263parse/gstbaseparse.h new file mode 100644 index 0000000000..605bf843a1 --- /dev/null +++ b/gst/h263parse/gstbaseparse.h @@ -0,0 +1,290 @@ +/* GStreamer + * Copyright (C) 2008 Nokia Corporation. All rights reserved. + * + * Contact: Stefan Kost + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_BASE_PARSE_H__ +#define __GST_BASE_PARSE_H__ + +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_BASE_PARSE (gst_base_parse_get_type()) +#define GST_BASE_PARSE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_BASE_PARSE,GstBaseParse)) +#define GST_BASE_PARSE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_BASE_PARSE,GstBaseParseClass)) +#define GST_BASE_PARSE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_BASE_PARSE,GstBaseParseClass)) +#define GST_IS_BASE_PARSE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_BASE_PARSE)) +#define GST_IS_BASE_PARSE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_BASE_PARSE)) +#define GST_BASE_PARSE_CAST(obj) ((GstBaseParse *)(obj)) + +/** + * GST_BASE_PARSE_SINK_NAME: + * + * the name of the templates for the sink pad + */ +#define GST_BASE_PARSE_SINK_NAME "sink" +/** + * GST_BASE_PARSE_SRC_NAME: + * + * the name of the templates for the source pad + */ +#define GST_BASE_PARSE_SRC_NAME "src" + +/** + * GST_BASE_PARSE_SRC_PAD: + * @obj: base parse instance + * + * Gives the pointer to the source #GstPad object of the element. + * + * Since: 0.10.x + */ +#define GST_BASE_PARSE_SRC_PAD(obj) (GST_BASE_PARSE_CAST (obj)->srcpad) + +/** + * GST_BASE_PARSE_SINK_PAD: + * @obj: base parse instance + * + * Gives the pointer to the sink #GstPad object of the element. + * + * Since: 0.10.x + */ +#define GST_BASE_PARSE_SINK_PAD(obj) (GST_BASE_PARSE_CAST (obj)->sinkpad) + +/** + * GST_BASE_PARSE_SEGMENT: + * @obj: base parse instance + * + * Gives the segment of the element. + * + * Since: 0.10.x + */ +#define GST_BASE_PARSE_SEGMENT(obj) (GST_BASE_PARSE_CAST (obj)->segment) + +/** + * GST_BASE_PARSE_FLOW_DROPPED: + * + * A #GstFlowReturn that can be returned from parse_frame to + * indicate that no output buffer was generated, or from pre_push_buffer to + * to forego pushing buffer. + * + * Since: 0.10.x + */ +#define GST_BASE_PARSE_FLOW_DROPPED GST_FLOW_CUSTOM_SUCCESS + +/** + * GST_BASE_PARSE_FLOW_CLIP: + * + * A #GstFlowReturn that can be returned from pre_push_buffer to + * indicate that regular segment clipping should be performed. + * + * Since: 0.10.x + */ +#define GST_BASE_PARSE_FLOW_CLIP GST_FLOW_CUSTOM_SUCCESS_1 + +/** + * GST_BASE_PARSE_BUFFER_FLAG_NO_FRAME: + * + * A #GstBufferFlag that can be set to have this buffer not counted as frame, + * e.g. if this frame is dependent on a previous one. As it is not counted as + * a frame, bitrate increases but frame to time conversions are maintained. + * + * Since: 0.10.x + */ +#define GST_BASE_PARSE_BUFFER_FLAG_NO_FRAME GST_BUFFER_FLAG_LAST + + +/** + * GstBaseParseSeekable: + * @GST_BASE_PARSE_SEEK_NONE: No seeking possible. + * GST_BASE_PARSE_SEEK_DEFAULT: Default seeking possible using estimated bitrate. + * GST_BASE_PARSE_SEEK_TABLE: Additional metadata provides more accurate seeking. + * + * Indicates what level (of quality) of seeking is possible. + */ +typedef enum _GstBaseParseSeekable { + GST_BASE_PARSE_SEEK_NONE, + GST_BASE_PARSE_SEEK_DEFAULT, + GST_BASE_PARSE_SEEK_TABLE +} GstBaseParseSeekable; + +typedef struct _GstBaseParse GstBaseParse; +typedef struct _GstBaseParseClass GstBaseParseClass; +typedef struct _GstBaseParsePrivate GstBaseParsePrivate; + +/** + * GstBaseParse: + * @element: the parent element. + * + * The opaque #GstBaseParse data structure. + */ +struct _GstBaseParse { + GstElement element; + GstAdapter *adapter; + + /*< protected >*/ + /* source and sink pads */ + GstPad *sinkpad; + GstPad *srcpad; + + /* MT-protected (with STREAM_LOCK) */ + GstSegment segment; + + /* Newsegment event to be sent after SEEK */ + GstEvent *pending_segment; + + /* Segment event that closes the running segment prior to SEEK */ + GstEvent *close_segment; + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING_LARGE]; + GstBaseParsePrivate *priv; +}; + +/** + * GstBaseParseClass: + * @start: Optional. + * Called when the element starts processing. + * Allows opening external resources. + * @stop: Optional. + * Called when the element stops processing. + * Allows closing external resources. + * @set_sink_caps: allows the subclass to be notified of the actual caps set. + * @check_valid_frame: Check if the given piece of data contains a valid + * frame. + * @parse_frame: Parse the already checked frame. Subclass need to + * set the buffer timestamp, duration, caps and possibly + * other necessary metadata. This is called with srcpad's + * STREAM_LOCK held. + * @convert: Optional. + * Convert between formats. + * @find_frame: Optional. + * Finds a frame. Gets a position passed and should return + * TRUE and the offset in bytes where this position is. + * Will only be called in pull mode and the subclass can pull + * whatever it wants from upstream. If not implemented, + * the base class will implement it by calling + * @check_valid_frame and @parse_frame to find the wanted + * frame and build a seek table. + * @event: Optional. + * Event handler on the sink pad. This function should return + * TRUE if the event was handled and can be dropped. + * @src_event: Optional. + * Event handler on the source pad. Should return TRUE + * if the event was handled and can be dropped. + * + * @get_frame_overhead: Finds the metadata overhead for the given frame. This + * is used to enable more accurate bitrate computations. + * If NULL, the per-frame overhead is assumed to be 0. If + * this returns -1, it is assumed that this frame should + * be skipped in bitrate calculation. + * + * @pre_push_buffer: Optional. + * Called just prior to pushing a frame (after any pending + * events have been sent) to give subclass a chance to perform + * additional actions at this time (e.g. tag sending) or to + * decide whether this buffer should be dropped or no + * (e.g. custom segment clipping). + * + * Subclasses can override any of the available virtual methods or not, as + * needed. At minimum @check_valid_frame and @parse_frame needs to be + * overridden. + */ +struct _GstBaseParseClass { + GstElementClass parent_class; + + /*< public >*/ + /* virtual methods for subclasses */ + + gboolean (*start) (GstBaseParse *parse); + + gboolean (*stop) (GstBaseParse *parse); + + gboolean (*set_sink_caps) (GstBaseParse *parse, + GstCaps *caps); + + gboolean (*check_valid_frame) (GstBaseParse *parse, + GstBuffer *buffer, + guint *framesize, + gint *skipsize); + + GstFlowReturn (*parse_frame) (GstBaseParse *parse, + GstBuffer *buffer); + + gboolean (*convert) (GstBaseParse * parse, + GstFormat src_format, + gint64 src_value, + GstFormat dest_format, + gint64 * dest_value); + + gboolean (*find_frame) (GstBaseParse *parse, + GstFormat src_format, + gint64 src_value, + gint64 * dest_value); + + gboolean (*event) (GstBaseParse *parse, + GstEvent *event); + + gboolean (*src_event) (GstBaseParse *parse, + GstEvent *event); + + gint (*get_frame_overhead) (GstBaseParse *parse, + GstBuffer *buf); + + GstFlowReturn (*pre_push_buffer) (GstBaseParse *parse, + GstBuffer *buf); + + /*< private >*/ + gpointer _gst_reserved[GST_PADDING_LARGE]; +}; + +GType gst_base_parse_get_type (void); + + +GstFlowReturn gst_base_parse_push_buffer (GstBaseParse *parse, + GstBuffer *buffer); + +void gst_base_parse_set_duration (GstBaseParse *parse, + GstFormat fmt, gint64 duration, gint interval); + +void gst_base_parse_set_seek (GstBaseParse * parse, + GstBaseParseSeekable seek, guint bitrate); + +void gst_base_parse_set_min_frame_size (GstBaseParse *parse, + guint min_size); +void gst_base_parse_set_passthrough (GstBaseParse * parse, gboolean passthrough); + +void gst_base_parse_set_frame_props (GstBaseParse * parse, guint fps_num, + guint fps_den, guint lead_in, guint lead_out); + +gboolean gst_base_parse_get_sync (GstBaseParse * parse); + +gboolean gst_base_parse_get_drain (GstBaseParse * parse); + +gboolean gst_base_parse_convert_default (GstBaseParse * parse, + GstFormat src_format, gint64 src_value, + GstFormat dest_format, gint64 * dest_value); + +gboolean gst_base_parse_add_index_entry (GstBaseParse * parse, guint64 offset, + GstClockTime ts, gboolean key, gboolean force); + +G_END_DECLS + +#endif /* __GST_BASE_PARSE_H__ */ diff --git a/gst/h263parse/gsth263parse.c b/gst/h263parse/gsth263parse.c new file mode 100644 index 0000000000..f09ee65858 --- /dev/null +++ b/gst/h263parse/gsth263parse.c @@ -0,0 +1,328 @@ +/* GStreamer H.263 Parser + * Copyright (C) <2010> Arun Raghavan + * Copyright (C) <2010> Edward Hervey + * Copyright (C) <2010> Collabora Multimedia + * Copyright (C) <2010> Nokia Corporation + * + * Some bits C-c,C-v'ed and s/4/3 from h264parse: + * (C) 2005 Michal Benes + * (C) 2008 Wim Taymans + * (C) 2009 Mark Nauwelaerts + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include "gsth263parse.h" + +GST_DEBUG_CATEGORY (h263_parse_debug); + +static GstStaticPadTemplate srctemplate = +GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("video/x-h263, variant = (string) itu, " + "parsed = (boolean) true") + ); + +static GstStaticPadTemplate sinktemplate = +GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("video/x-h263, variant = (string) itu, " + "parsed = (boolean) false") + ); + +GST_BOILERPLATE (GstH263Parse, gst_h263_parse, GstElement, GST_TYPE_BASE_PARSE); + +static gboolean gst_h263_parse_start (GstBaseParse * parse); +static gboolean gst_h263_parse_stop (GstBaseParse * parse); +static gboolean gst_h263_parse_sink_event (GstBaseParse * parse, + GstEvent * event); +static gboolean gst_h263_parse_check_valid_frame (GstBaseParse * parse, + GstBuffer * buffer, guint * framesize, gint * skipsize); +static GstFlowReturn gst_h263_parse_parse_frame (GstBaseParse * parse, + GstBuffer * buffer); +static GstCaps *gst_h263_parse_src_getcaps (GstPad * pad); + +static void +gst_h263_parse_base_init (gpointer g_class) +{ + GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&srctemplate)); + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&sinktemplate)); + gst_element_class_set_details_simple (gstelement_class, "H.263 parser", + "Codec/Parser/Video", + "Parses H.263 streams", + "Arun Raghavan ," + "Edward Hervey "); + + GST_DEBUG_CATEGORY_INIT (h263_parse_debug, "h263parse", 0, "h263 parser"); +} + +static void +gst_h263_parse_class_init (GstH263ParseClass * klass) +{ + GstBaseParseClass *parse_class = GST_BASE_PARSE_CLASS (klass); + + /* Override BaseParse vfuncs */ + parse_class->start = GST_DEBUG_FUNCPTR (gst_h263_parse_start); + parse_class->stop = GST_DEBUG_FUNCPTR (gst_h263_parse_stop); + parse_class->event = GST_DEBUG_FUNCPTR (gst_h263_parse_sink_event); + parse_class->check_valid_frame = + GST_DEBUG_FUNCPTR (gst_h263_parse_check_valid_frame); + parse_class->parse_frame = GST_DEBUG_FUNCPTR (gst_h263_parse_parse_frame); +} + +static void +gst_h263_parse_init (GstH263Parse * h263parse, GstH263ParseClass * g_class) +{ + gst_pad_set_getcaps_function (GST_BASE_PARSE_SRC_PAD (GST_BASE_PARSE + (h263parse)), GST_DEBUG_FUNCPTR (gst_h263_parse_src_getcaps)); +} + +static gboolean +gst_h263_parse_start (GstBaseParse * parse) +{ + GstH263Parse *h263parse = GST_H263PARSE (parse); + + GST_DEBUG ("Start"); + + h263parse->last_pos = 0; + h263parse->psc_pos = -1; + + h263parse->bitrate = 0; + h263parse->profile = -1; + h263parse->level = -1; + + h263parse->state = PARSING; + + gst_base_parse_set_passthrough (parse, FALSE); + + return TRUE; +} + +static gboolean +gst_h263_parse_stop (GstBaseParse * parse) +{ + GST_DEBUG ("Stop"); + + return TRUE; +} + +static gboolean +gst_h263_parse_sink_event (GstBaseParse * parse, GstEvent * event) +{ + GstH263Parse *h263parse; + gboolean res = FALSE; + + h263parse = GST_H263PARSE (parse); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_TAG: + { + GstTagList *taglist; + + gst_event_parse_tag (event, &taglist); + + if (gst_tag_list_get_uint (taglist, GST_TAG_BITRATE, &h263parse->bitrate)) + GST_DEBUG ("Got bitrate tag: %u", h263parse->bitrate); + + break; + } + + default: + break; + } + + return res; +} + +static guint +find_psc (GstBuffer * buffer, guint skip) +{ + GstByteReader br; + guint psc_pos = -1, psc; + + gst_byte_reader_init_from_buffer (&br, buffer); + + if (!gst_byte_reader_set_pos (&br, skip)) + goto out; + + gst_byte_reader_peek_uint24_be (&br, &psc); + + /* Scan for the picture start code (22 bits - 0x0020) */ + while ((gst_byte_reader_get_remaining (&br) >= 3)) { + if (gst_byte_reader_peek_uint24_be (&br, &psc) && + ((psc & 0xffffc0) == 0x000080)) { + psc_pos = gst_byte_reader_get_pos (&br); + break; + } else + gst_byte_reader_skip (&br, 1); + } + +out: + return psc_pos; +} + +static gboolean +gst_h263_parse_check_valid_frame (GstBaseParse * parse, GstBuffer * buffer, + guint * framesize, gint * skipsize) +{ + GstH263Parse *h263parse; + guint psc_pos; + + h263parse = GST_H263PARSE (parse); + + psc_pos = find_psc (buffer, h263parse->last_pos); + + if (psc_pos == -1) { + /* PSC not found, need more data */ + if (GST_BUFFER_SIZE (buffer) > 3) + h263parse->last_pos = GST_BUFFER_SIZE (buffer) - 3; + goto more; + } + + if (h263parse->psc_pos == -1) { + /* Found the start of the frame, now try to find the end */ + + h263parse->psc_pos = psc_pos; + h263parse->last_pos = psc_pos + 3; + + psc_pos = find_psc (buffer, h263parse->last_pos); + + if (psc_pos == -1) { + if (gst_base_parse_get_drain (GST_BASE_PARSE (h263parse))) + /* FLUSH/EOS, it's okay if we can't find the next frame */ + psc_pos = GST_BUFFER_SIZE (buffer); + else + goto more; + } + } + + /* We should now have a complete frame */ + + /* If this is the first frame, parse and set srcpad caps */ + if (h263parse->state == PARSING) { + H263Params *params = NULL; + GstFlowReturn res = gst_h263_parse_get_params (h263parse, buffer, + ¶ms, FALSE); + + if (res != GST_FLOW_OK || h263parse->state != GOT_HEADER) { + GST_WARNING ("Couldn't parse header - setting passthrough mode"); + gst_base_parse_set_passthrough (parse, TRUE); + } else { + /* Set srcpad caps since we now have sufficient information to do so */ + gst_h263_parse_set_src_caps (h263parse, params); + } + + if (params) + g_free (params); + } + + *skipsize = h263parse->psc_pos; + *framesize = psc_pos - h263parse->psc_pos; + + h263parse->psc_pos = -1; + h263parse->last_pos = 0; + + /* XXX: After getting a keyframe, should we adjust min_frame_size to + * something smaller so we don't end up collecting too many non-keyframes? */ + + GST_DEBUG ("Found a frame of size %d at pos %d", *framesize, *skipsize); + + return TRUE; + +more: + /* Ask for 1024 bytes more - this is an arbitrary choice */ + gst_base_parse_set_min_frame_size (parse, GST_BUFFER_SIZE (buffer) + 1024); + + /* Prevent baseparse from auto-skipping one byte */ + *skipsize = 0; + + return FALSE; +} + +static GstFlowReturn +gst_h263_parse_parse_frame (GstBaseParse * parse, GstBuffer * buffer) +{ + GstH263Parse *h263parse; + GstFlowReturn res; + H263Params *params = NULL; + + h263parse = GST_H263PARSE (parse); + + res = gst_h263_parse_get_params (h263parse, buffer, ¶ms, TRUE); + if (res != GST_FLOW_OK) + goto out; + + if (h263parse->state == PASSTHROUGH || h263parse->state == PARSING) { + /* There's a feature we don't support, or we didn't have enough data to + * parse the header, which should not be possible. Either way, go into + * passthrough mode and let downstream handle it if it can. */ + GST_WARNING ("Couldn't parse header - setting passthrough mode"); + gst_base_parse_set_passthrough (parse, TRUE); + goto out; + } + + /* h263parse->state is now GOT_HEADER */ + + gst_buffer_set_caps (buffer, + GST_PAD_CAPS (GST_BASE_PARSE_SRC_PAD (GST_BASE_PARSE (h263parse)))); + + if (gst_h263_parse_is_delta_unit (params)) + GST_BUFFER_FLAG_UNSET (buffer, GST_BUFFER_FLAG_DELTA_UNIT); + else + GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT); + +out: + g_free (params); + return res; +} + +static GstCaps * +gst_h263_parse_src_getcaps (GstPad * pad) +{ + GstH263Parse *h263parse; + GstCaps *caps; + + h263parse = GST_H263PARSE (GST_PAD_PARENT (pad)); + + if (h263parse->state == PARSING) + /* Not got more specific caps from headers yet - return template caps */ + return gst_caps_copy (gst_pad_get_pad_template_caps (pad)); + + g_object_get (pad, "caps", &caps, NULL); + return caps; +} + +static gboolean +plugin_init (GstPlugin * plugin) +{ + return gst_element_register (plugin, "h263parse", + GST_RANK_NONE, GST_TYPE_H263PARSE); +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "h263parse", + "Element for parsing raw h263 streams", + plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/gst/h263parse/gsth263parse.h b/gst/h263parse/gsth263parse.h new file mode 100644 index 0000000000..11ca426096 --- /dev/null +++ b/gst/h263parse/gsth263parse.h @@ -0,0 +1,94 @@ +/* GStreamer H.263 Parser + * Copyright (C) <2010> Arun Raghavan + * Copyright (C) <2010> Edward Hervey + * Copyright (C) <2010> Collabora Multimedia + * Copyright (C) <2010> Nokia Corporation + * + * Some bits C-c,C-v'ed and s/4/3 from h264parse: + * (C) 2005 Michal Benes + * (C) 2008 Wim Taymans + * (C) 2009 Mark Nauwelaerts + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_H263_PARSE_H__ +#define __GST_H263_PARSE_H__ + +#include +#include +#include "gstbaseparse.h" + +GST_DEBUG_CATEGORY_EXTERN (h263_parse_debug); +#define GST_CAT_DEFAULT h263_parse_debug + +G_BEGIN_DECLS + +typedef enum +{ + PARSING = 0, + GOT_HEADER, + PASSTHROUGH +} H263ParseState; + +typedef struct _H263Params H263Params; + +#define GST_TYPE_H263PARSE \ + (gst_h263_parse_get_type()) +#define GST_H263PARSE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_H263PARSE,GstH263Parse)) +#define GST_H263PARSE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_H263PARSE,GstH263ParseClass)) +#define GST_IS_H263PARSE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_H263PARSE)) +#define GST_IS_H263PARSE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_H263PARSE)) +GType gst_h263_parse_get_type (void); + +typedef struct _GstH263Parse GstH263Parse; +typedef struct _GstH263ParseClass GstH263ParseClass; + +struct _GstH263Parse +{ + GstBaseParse baseparse; + + gint psc_pos; + guint last_pos; + + gint profile, level; + guint bitrate; + + H263ParseState state; +}; + +struct _GstH263ParseClass +{ + GstBaseParseClass parent_class; +}; + +gboolean gst_h263_parse_is_delta_unit (H263Params * params); +GstFlowReturn gst_h263_parse_get_params (GstH263Parse * h263parse, + GstBuffer * buffer, H263Params ** params_p, gboolean fast); +void gst_h263_parse_get_framerate (GstCaps * caps, H263Params * params, + gint * num, gint * denom); +void gst_h263_parse_set_src_caps (GstH263Parse * h263parse, + H263Params * params); +gint gst_h263_parse_get_profile (H263Params * params); +gint gst_h263_parse_get_level (H263Params * params, gint profile, + guint bitrate, gint fps_num, gint fps_denom); + +G_END_DECLS +#endif diff --git a/gst/h263parse/h263parse.c b/gst/h263parse/h263parse.c new file mode 100644 index 0000000000..b46dcdab8f --- /dev/null +++ b/gst/h263parse/h263parse.c @@ -0,0 +1,823 @@ +/* GStreamer H.263 Parser + * Copyright (C) <2010> Arun Raghavan + * Copyright (C) <2010> Edward Hervey + * Copyright (C) <2010> Collabora Multimedia + * Copyright (C) <2010> Nokia Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include "gsth263parse.h" + +/* H263 Optional Features */ +typedef enum +{ + /* Optional Unrestricted Motion Vector (UMV) mode (see Annex D) */ + H263_OPTION_UMV_MODE = 1 << 0, + /* Optional Syntax-based Arithmetic Coding (SAC) mode (see Annex E) */ + H263_OPTION_SAC_MODE = 1 << 1, + /* Optional Advanced Prediction mode (AP) (see Annex F) */ + H263_OPTION_AP_MODE = 1 << 2, + /* Optional PB-frames mode (see Annex G) */ + H263_OPTION_PB_MODE = 1 << 3, + /* Optional Advanced INTRA Coding (AIC) mode (see Annex I) */ + H263_OPTION_AIC_MODE = 1 << 4, + /* Optional Deblocking Filter (DF) mode (see Annex J) */ + H263_OPTION_DF_MODE = 1 << 5, + /* Optional Slice Structured (SS) mode (see Annex K) */ + H263_OPTION_SS_MODE = 1 << 6, + /* Optional Reference Picture Selection (RPS) mode (see Annex N) */ + H263_OPTION_RPS_MODE = 1 << 7, + /* Optional Independent Segment Decoding (ISD) mode (see Annex R) */ + H263_OPTION_ISD_MODE = 1 << 8, + /* Optional Alternative INTER VLC (AIV) mode (see Annex S) */ + H263_OPTION_AIV_MODE = 1 << 9, + /* Optional Modified Quantization (MQ) mode (see Annex T) */ + H263_OPTION_MQ_MODE = 1 << 10, + /* Optional Reference Picture Resampling (RPR) mode (see Annex P) */ + H263_OPTION_RPR_MODE = 1 << 11, + /* Optional Reduced-Resolution Update (RRU) mode (see Annex Q) */ + H263_OPTION_RRU_MODE = 1 << 12, + /* Optional Enhanced Reference Picture Selection (ERPS) mode (see Annex U) */ + H263_OPTION_ERPS_MODE = 1 << 13, + /* Optional Data Partitioned Slices (DPS) mode (see Annex V) */ + H263_OPTION_DPS_MODE = 1 << 14 +} H263OptionalFeatures; + +/* H263 Picture Types */ +typedef enum +{ + PICTURE_I = 0, /* I-picture (INTRA) Baseline */ + PICTURE_P, /* P-picture (INTER) Baseline */ + PICTURE_IMPROVED_PB, /* Improved PB-frame (Annex M) */ + PICTURE_B, /* B-picture (Annex O) */ + PICTURE_EI, /* EI-picture (Annex O) */ + PICTURE_EP, /* EP-picture (Annex O) */ + PICTURE_RESERVED1, + PICTURE_RESERVED2, + PICTURE_PB /* PB-frame (See Annex G) */ +} H263PictureType; + +/* H263 Picture Format */ +typedef enum +{ + PICTURE_FMT_FORBIDDEN_0 = 0, + PICTURE_FMT_SUB_QCIF, + PICTURE_FMT_QCIF, + PICTURE_FMT_CIF, + PICTURE_FMT_4CIF, + PICTURE_FMT_16CIF, + PICTURE_FMT_RESERVED1, + PICTURE_FMT_EXTENDEDPTYPE +} H263PictureFormat; + +typedef enum +{ + UUI_ABSENT = 0, + UUI_IS_1, + UUI_IS_01, +} H263UUI; + +struct _H263Params +{ + guint32 temporal_ref; + + H263OptionalFeatures features; + + gboolean splitscreen; + gboolean documentcamera; + gboolean fullpicturefreezerelease; + gboolean custompcfpresent; + H263UUI uui; + guint8 sss; + + H263PictureFormat format; + + H263PictureType type; + + guint32 width; + guint32 height; + guint8 parnum, pardenom; + gint32 pcfnum, pcfdenom; +}; + + +gboolean +gst_h263_parse_is_delta_unit (H263Params * params) +{ + return (params->type == PICTURE_I); +} + +/* Reads adapter and tries to populate params. 'fast' mode can be used to + * extract a subset of the data (for now, it quits once we have the picture + * type. */ +GstFlowReturn +gst_h263_parse_get_params (GstH263Parse * h263parse, GstBuffer * buffer, + H263Params ** params_p, gboolean fast) +{ + static const guint8 partable[6][2] = { + {1, 0}, + {1, 1}, + {12, 11}, + {10, 11}, + {16, 11}, + {40, 33} + }; + + static const guint16 sizetable[8][2] = { + {0, 0}, + {128, 96}, + {176, 144}, + {352, 288}, + {704, 576}, + {1408, 1152} + }; + + static const gchar *source_format_name[] = { + "Forbidden", + "sub-QCIF", + "QCIF", + "CIF", + "4CIF", + "16CIF", + "Reserved", + "Extended PType" + }; + + H263Params *params; + GstBitReader br; + guint8 tr; + guint32 psc, temp32; + guint8 temp8, pquant; + gboolean hasplusptype; + + *params_p = g_new0 (H263Params, 1); + params = *params_p; + + /* FIXME: we can optimise a little by checking the value of available + * instead of calling using the bit reader's get_bits_* functions. */ + gst_bit_reader_init_from_buffer (&br, buffer); + + /* Default PCF is CIF PCF = 30000/1001 */ + params->pcfnum = 30000; + params->pcfdenom = 1001; + + GST_DEBUG ("NEW BUFFER"); + if (!gst_bit_reader_get_bits_uint32 (&br, &psc, 22) || + !gst_bit_reader_get_bits_uint8 (&br, &tr, 8) || + !gst_bit_reader_get_bits_uint8 (&br, &temp8, 8)) + goto more; + + /* PSC : Picture Start Code 22 bits + * TR : Temporal Reference 8 bits + * PTYPE : Type Information variable + * bit 1 : Always "1" + * bit 2 : Always "0" + * bit 3 : Split Screen Indicator + * bit 4 : Document Camera Indicator + * bit 6-8 : Source Format + * if 111 : extended PTYPE is present */ + + /* 5.1.1 PSC : Picture Start Code (0x0020) 22 bits */ + /* FIXME : Scan for the PSC instead of assuming it's always present + * and at the beginning. */ + if (G_UNLIKELY (psc != 0x0020)) { + GST_WARNING ("Invalid PSC"); + goto beach; + } + + /* 5.1.2 TR : Temporal Reference 8 bits */ + GST_DEBUG (" Temporal Reference : %d", tr); + params->temporal_ref = tr; + + if ((temp8 >> 6) != 0x2) { + GST_WARNING ("Invalid PTYPE"); + goto beach; + } + + /* 5.1.3 PTYPE : Type Information variable length */ + params->splitscreen = (temp8 & 0x20) == 0x20; + params->documentcamera = (temp8 & 0x10) == 0x10; + params->fullpicturefreezerelease = (temp8 & 0x08) == 0x08; + params->format = temp8 & 0x07; + + hasplusptype = (temp8 & 0x07) == 0x07; + + GST_DEBUG (" Split Screen Indicator : %s", + params->splitscreen ? "on" : "off"); + GST_DEBUG (" Document camera indicator : %s", + params->documentcamera ? "on" : "off"); + GST_DEBUG (" Full Picture Freeze Release : %s", + params->fullpicturefreezerelease ? "on" : "off"); + GST_DEBUG (" Source format 0x%x (%s)", params->format, + source_format_name[params->format]); + + if (!hasplusptype) { + guint8 ptype2; + + /* Fill in width/height based on format */ + params->width = sizetable[params->format][0]; + params->height = sizetable[params->format][1]; + + /* Default PAR is 12/11 */ + params->parnum = 12; + params->pardenom = 11; + + /* 5.1.3 : Remainder of PTYPE 5 bits */ + if (!gst_bit_reader_get_bits_uint8 (&br, &ptype2, 5)) + goto more; + + params->type = (ptype2 & 0x10) == 0x10; + if ((ptype2 & 0x08) == 0x08) + params->features |= H263_OPTION_UMV_MODE; + if ((ptype2 & 0x04) == 0x04) + params->features |= H263_OPTION_SAC_MODE; + if ((ptype2 & 0x02) == 0x02) + params->features |= H263_OPTION_AP_MODE; + if ((ptype2 & 0x01) == 0x01) { + params->features |= H263_OPTION_PB_MODE; + params->type = PICTURE_PB; + } + + GST_DEBUG (" Picture Coding Type : %s", + (ptype2 & 0x10) == 0x10 ? "INTER (P-picture)" : "INTRA (I-picture)"); + GST_DEBUG (" Unrestricted Motion Vector mode (Annex D) : %s", + (ptype2 & 0x08) == 0x08 ? "on" : "off"); + GST_DEBUG (" Syntax-basex Arithmetic Coding mode (Annex E) : %s", + (ptype2 & 0x04) == 0x04 ? "on" : "off"); + GST_DEBUG (" Advanced Prediction mode (Annex F) : %s", + (ptype2 & 0x02) == 0x02 ? "on" : "off"); + GST_DEBUG (" PB Frames mode (Annex G) : %s", + (ptype2 & 0x01) == 0x01 ? "on" : "off"); + + if (fast) + goto done; + } + + if (hasplusptype) { + guint8 ufep; + guint8 cpm; + guint32 opptype, mpptype; + + /* 5.1.4 PLUSPTYPE */ + + /* 5.1.4.1 UFEP : Update Full Extended PTYPE (3 bits) */ + if (!gst_bit_reader_get_bits_uint8 (&br, &ufep, 3)) + goto more; + GST_DEBUG (" UFEP 0x%x", ufep); + + if (ufep == 1) { + /* 5.1.4.2 OPPTYPE : The Optional Part of PLUSPTYPE (OPPTYPE) (18 bits) */ + if (!gst_bit_reader_get_bits_uint32 (&br, &opptype, 18)) + goto more; + + /* Last 4 bits are always "1000" */ + if ((opptype & 0xf) != 0x8) { + GST_WARNING ("Corrupted OPTTYPE"); + goto beach; + } + params->format = opptype >> 15; + params->custompcfpresent = (opptype & 0x4000) == 0x4000; + if (opptype & 0x2000) + params->features |= H263_OPTION_UMV_MODE; + if (opptype & 0x1000) + params->features |= H263_OPTION_SAC_MODE; + if (opptype & 0x0800) + params->features |= H263_OPTION_AP_MODE; + if (opptype & 0x0400) + params->features |= H263_OPTION_AIC_MODE; + if (opptype & 0x0200) + params->features |= H263_OPTION_DF_MODE; + if (opptype & 0x0100) + params->features |= H263_OPTION_SS_MODE; + if (opptype & 0x0080) + params->features |= H263_OPTION_RPS_MODE; + if (opptype & 0x0040) + params->features |= H263_OPTION_ISD_MODE; + if (opptype & 0x0020) + params->features |= H263_OPTION_AIV_MODE; + if (opptype & 0x0010) + params->features |= H263_OPTION_MQ_MODE; + /* Bit 15 is set to 1 to avoid looking like a start code */ + if (opptype & 0x0004) + params->features |= H263_OPTION_ERPS_MODE; + if (opptype & 0x0002) + params->features |= H263_OPTION_DPS_MODE; + } + + /* 5.1.4.3 MPPTYPE : The mandatory part of PLUSPTYPE (9 bits) */ + if (!gst_bit_reader_get_bits_uint32 (&br, &mpptype, 9)) + goto more; + + /* Last 3 bits are always "001" */ + if ((mpptype & 0x7) != 1) { + GST_WARNING ("Corrupted MPPTYPE"); + goto beach; + } + + params->type = mpptype >> 6; + GST_DEBUG (" Picture Coding Type : %d", params->type); + + if (fast) + goto done; + + if (mpptype & 0x2000) + params->features |= H263_OPTION_RPR_MODE; + if (mpptype & 0x1000) + params->features |= H263_OPTION_RRU_MODE; + + /* 5.1.20 CPM : Continuous Presence Multipoint and Video Multiplex (1 bit) */ + if (!gst_bit_reader_get_bits_uint8 (&br, &cpm, 1)) + goto more; + GST_DEBUG (" Continuous Presence Multipoint and Video Multiplex : %d", cpm); + + if (cpm) { + /* 5.1.21 PSBI : Picture Sub-Bitstream Indicator (2 bits) */ + guint8 psbi; + if (!gst_bit_reader_get_bits_uint8 (&br, &psbi, 2)) + goto more; + GST_DEBUG (" Picture Sub-Bitstream Indicator (PSBI):%d", psbi); + } + + if (ufep == 1) { + guint32 cpfmt; + + /* 5.1.5 CPFMT : Custom Picture Format (23 bits) */ + if (!gst_bit_reader_get_bits_uint32 (&br, &cpfmt, 23)) + goto more; + if (!(cpfmt & 0x200)) { + GST_WARNING ("Corrupted CPFMT (0x%x)", cpfmt); + goto beach; + } + temp8 = cpfmt >> 19; + params->width = (((cpfmt >> 10) & 0x1f) + 1) * 4; + params->height = (cpfmt & 0x1f) * 4; + + if (temp8 == 0xf) { + guint32 epar; + /* 5.1.6 EPAR : Extended Pixel Aspect Ratio (16bits) */ + if (!gst_bit_reader_get_bits_uint32 (&br, &epar, 16)) + goto more; + params->parnum = epar >> 8; + params->pardenom = epar & 0xf; + } else { + params->parnum = partable[temp8][0]; + params->pardenom = partable[temp8][1]; + } + + if (params->custompcfpresent) { + /* 5.1.7 CPCFC : Custom Picture Clock Frequency Code (8bits) */ + /* (we store this as a frame rate) */ + if (!gst_bit_reader_get_bits_uint8 (&br, &temp8, 8)) + goto more; + GST_DEBUG (" Custom PCF is present (%d)", (int) temp8); + params->pcfnum = gst_util_uint64_scale_int (1800000, 1, temp8 & 0x7f); + params->pcfdenom = (temp8 & 0x80) ? 1001 : 1000; + /* 5.1.8 ETR : Extended Temp8oral Reference (2bits) */ + if (!gst_bit_reader_get_bits_uint8 (&br, &temp8, 2)) + goto more; + params->temporal_ref |= temp8 << 8; + } + + if (params->features & H263_OPTION_UMV_MODE) { + guint8 i; + /* 5.1.9 UUI : Unlimited Unrestricted Motion Vectors Indicator (variable length) */ + if (!gst_bit_reader_get_bits_uint8 (&br, &i, 1)) + goto more; + if (i == 0) { + if (!gst_bit_reader_get_bits_uint8 (&br, &i, 1)) + goto more; + if (i != 1) { + GST_WARNING ("Corrupted UUI (0%u)", (guint) i); + goto beach; + } + params->uui = UUI_IS_01; + } else { + params->uui = UUI_IS_1; + } + } + + if (params->features & H263_OPTION_SS_MODE) { + /* 5.1.10 SSS : Slice Structured Submode bits (2bits) */ + if (!gst_bit_reader_get_bits_uint8 (&br, ¶ms->sss, 2)) + goto more; + } + + /* WE DO NOT SUPPORT optional Temporal, SNR, and Spatial Scalability mode */ + /* 5.1.11 ELNUM : Enhancement Layer Number (4bits) */ + /* 5.1.12 RLNUM : Reference Layer Number (4bits) */ + + if (params->features & H263_OPTION_RPS_MODE) { + /* 5.1.13 RPSMF : Reference Picture Selection Mode Flags (3bits) */ + /* FIXME : We just swallow the bits */ + if (!gst_bit_reader_get_bits_uint8 (&br, &temp8, 3)) + goto more; + + /* 5.1.14 TRPI : Temporal Reference for Prediction Indication (1bit) */ + if (!gst_bit_reader_get_bits_uint8 (&br, &temp8, 1)) + goto more; + + if (temp8) { + /* 5.1.15 TRP : Temporal Reference for Prediction (10bits) */ + /* FIXME : We just swallow the bits */ + if (!gst_bit_reader_get_bits_uint32 (&br, &temp32, 10)) + goto more; + } + + /* 5.1.16 BCI Back-Channel message Indication (variable length) */ + if (!gst_bit_reader_get_bits_uint8 (&br, &temp8, 1)) + goto more; + if (temp8 == 1) { + /* 5.1.17 BCM Back-Channel Message (variable length) */ + GST_ERROR ("We won't support Back-Channel Message (BCM)"); + goto beach; + } else { + if (!gst_bit_reader_get_bits_uint8 (&br, &temp8, 1)) + goto more; + if (temp8 != 1) { + GST_WARNING ("Corrupted BCI"); + goto beach; + } + } + } /* END H263_OPTION_RPS_MODE */ + } + + GST_DEBUG (" Advanced INTRA Coding mode (Annex I) : %s", + (params->features & H263_OPTION_AIC_MODE ? "on" : "off")); + GST_DEBUG (" Deblocking Filter mode (Annex J) : %s", + (params->features & H263_OPTION_DF_MODE ? "on" : "off")); + GST_DEBUG (" Slice Structured mode (Annex K) : %s", + (params->features & H263_OPTION_SS_MODE ? "on" : "off")); + GST_DEBUG (" Reference Picture Selection mode (Annex N) : %s", + (params->features & H263_OPTION_RPS_MODE ? "on" : "off")); + GST_DEBUG (" Independent Segment Decoding mode (Annex R) : %s", + (params->features & H263_OPTION_ISD_MODE ? "on" : "off")); + GST_DEBUG (" Alternative INTER VLC mode (Annex S) : %s", + (params->features & H263_OPTION_AIV_MODE ? "on" : "off")); + GST_DEBUG (" Modified Quantization mode (Annex T) : %s", + (params->features & H263_OPTION_MQ_MODE ? "on" : "off")); + GST_DEBUG (" Enhanced Reference Picture Selection mode (Annex U) : %s", + (params->features & H263_OPTION_ERPS_MODE ? "on" : "off")); + GST_DEBUG (" Enhanced Data Partitioned Slices mode (Annex V) : %s", + (params->features & H263_OPTION_DPS_MODE ? "on" : "off")); + + /* END ufep == 1 */ + /* WE DO NOT SUPPORT optional Reference Picture Resampling mode */ + /* 5.1.18 RPRP : Reference Picture Resampling Parameters (variable length) */ + } + + /* END hasplusptype */ + /* 5.1.19 PQUANT : Quantizer Information (5 bits) */ + if (!gst_bit_reader_get_bits_uint8 (&br, &pquant, 5)) + goto more; + GST_DEBUG (" PQUANT : 0x%x", pquant); + + if (!hasplusptype) { + guint8 cpm; + /* 5.1.20 CPM : Continuous Presence Multipoint and Video Multiplex (1 bit) */ + if (!gst_bit_reader_get_bits_uint8 (&br, &cpm, 1)) + goto more; + GST_DEBUG (" Continuous Presence Multipoint and Video Multiplex : %d", cpm); + + if (cpm) { + /* 5.1.21 PSBI : Picture Sub-Bitstream Indicator (2 bits) */ + guint8 psbi; + if (!gst_bit_reader_get_bits_uint8 (&br, &psbi, 2)) + goto more; + GST_DEBUG (" Picture Sub-Bitstream Indicator (PSBI):%d", psbi); + } + } + + if (params->type & (PICTURE_PB | PICTURE_IMPROVED_PB)) { + /* 5.1.22 TRb : Temporal Reference for B-pictures in PB-frames (3/5bits) */ + /* FIXME : We just swallow the bits */ + if (!gst_bit_reader_get_bits_uint8 (&br, &temp8, + params->custompcfpresent ? 5 : 3)) + goto more; + + /* 5.1.23 DBQUANT : Quantization information for B-pictures in PB-frames (2bits) */ + if (!gst_bit_reader_get_bits_uint8 (&br, &temp8, 2)) + goto more; + } + + GST_DEBUG (" Framerate defined by the stream is %d/%d", + params->pcfnum, params->pcfdenom); + + /* We ignore the PEI and PSUPP - these may occur in any frame, and can be + * ignored by decoders that don't support them, except for bits of Annex W */ + + /* FIXME: Annex H (Forward Error Correction) requires that we poke into the + * stream data. */ + + /* FIXME: Annex P (Reference Picture Resampling) can be signaled implicitly + * as well as in the header. Should we set the field to false in caps if it + * is not specfied by the header? */ + + /* FIXME: Annex U (Enhanced Reference Picture Selection) poses a problem - we + * have no means of specifying what sub-modes, if any, are used. */ + +done: + h263parse->state = GOT_HEADER; +more: + return GST_FLOW_OK; + +beach: + h263parse->state = PASSTHROUGH; + return GST_FLOW_OK; +} + +gint +gst_h263_parse_get_profile (H263Params * params) +{ + gboolean c, d, d1, d21, d22, e, f, f2, g, h, i, j, k, k0, k1, k2, l, m, n, o, + p, q, r, s, t, u, v, w; + + /* FIXME: some parts of Annex C can be discovered, others can not */ + c = FALSE; + d = (params->features & H263_OPTION_UMV_MODE) != 0; + /* d1: Annex D.1; d21: Annex D.2 with UUI=1; d22: Annex D.2 with UUI=01 */ + d1 = (d && params->uui == UUI_ABSENT); + d21 = (d && params->uui == UUI_IS_1); + d22 = (d && params->uui == UUI_IS_01); + e = (params->features & H263_OPTION_SAC_MODE) != 0; + /* f:Annex F.2 or F.3 may be used; f2: only Annex F.2 is used (we have no + * way of detecting this right now */ + f = (params->features & H263_OPTION_AP_MODE) != 0; + f2 = FALSE; + g = (params->features & H263_OPTION_PB_MODE) != 0; + h = FALSE; + i = (params->features & H263_OPTION_AIC_MODE) != 0; + j = (params->features & H263_OPTION_DF_MODE) != 0; + k = (params->features & H263_OPTION_SS_MODE) != 0; + /* k0: Annex K without submodes; k1: Annex K with ASO; k2: Annex K with RS */ + k0 = (k && params->sss == 0x0); + k1 = (k && params->sss == 0x2); + k2 = (k && params->sss == 0x1); + l = FALSE; + m = (params->type == PICTURE_IMPROVED_PB); + n = (params->features & H263_OPTION_RPS_MODE) != 0; + o = FALSE; + p = FALSE; + q = (params->features & H263_OPTION_RRU_MODE) != 0; + r = (params->features & H263_OPTION_ISD_MODE) != 0; + s = (params->features & H263_OPTION_AIV_MODE) != 0; + t = (params->features & H263_OPTION_MQ_MODE) != 0; + u = (params->features & H263_OPTION_ERPS_MODE) != 0; + v = (params->features & H263_OPTION_DPS_MODE) != 0; + w = FALSE; + + /* FIXME: The use of UUI in Annex D seems to be in contradiction with the + * profile definition in Annex X. Afaict, D.2 with UUI not present is not a + * meaningful state. */ + + /* FIXME: We have no way to distinguish between the use of section F.2 (four + * motion vectors per macroblock) and F.3 (overlapped block motion + * compensation), so we assume that they are either both present else neither + * is. This means if a profile supports only F.2 and not F.3, but we see that + * Advanced Prediction mode (Annex F) is used, we assume this profile does + * not apply. */ + + /* FIXME: We assume there is no error correction (Annex H) to avoid having to + * parse the stream to look for its existence. */ + + /* FIXME: Profiles 1 and 5-8 need the detection of Annex L.4 which can happen + * anywhere in the stream, so we just assume it doesn't exist and hope for + * the best. */ + + /* FIXME: Annex O support is TBD. */ + + /* FIXME: see note for Annex P elsewhere in this file. */ + + /* FIXME: Annex W.6.3.{8,11} suffer the same fate as Annex L.4 above. */ + + /* FIXME: We have no way of figuring out submodes when Annex U is used. Here + * we always assume no submode is used. */ + + if (!c && !d && !e && !f && !g && !h && !i && !j && !k && !l && !m && !n && + !o && !p && !q && !r && !s && !t && !u && !v && !w) + return 0; + if (!c && (!d || d1) && !e && (!f || f2) && !g && !h && !k && !l && !m && + !n && !o && !p && !q && !r && !s && !u && !v && !w) + return 1; + if (!c && (!d || d1) && !e && !g && !h && !i && !j && !k && !l && !m && !n && + !o && !p && !q && !r && !s && !t && !u && !v && !w) + return 2; + if (!c && (!d || d1) && !e && (!f || f2) && !g && !h && (!k || k0) && !l && + !m && !n && !o && !p && !q && !r && !s && !u && !v && !w) + return 3; + if (!c && (!d || d1) && !e && (!f || f2) && !g && !h && (!k || k0) && !l && + !m && !n && !o && !p && !q && !r && !s && !u && !w) + return 4; + if (!c && (!d || d1 || d21) && !e && !g && !h && !k && !l && !m && !n && + !o && !p && !q && !r && !s && !v && !w) + return 5; + if (!c && (!d || d1 || d21) && !e && !g && !h && (!k || k0 || k1) && !l && + !m && !n && !o && !p && !q && !r && !s && !v && !w) + return 6; + if (!c && (!d || d1 || d21) && !e && !g && !h && !k && !l && !m && !n && + !o && !p && !q && !r && !s && !v && !w) + return 7; + if (!c && (!d || d1 || d21) && !e && !g && !h && (!k || k0 || k1) && !l && + !m && !n && !o && !p && !q && !r && !s && !v && !w) + /* FIXME: needs Annex O and Annex P support */ + return 8; + + return -1; +} + +#define H263_PROFILE_NOT_0_2(profile) \ + ((profile) != -1 && (profile) != 0 && (profile) != 2) + +#define H263_FMT_UPTO_QCIF(params) \ + ((params)->format == PICTURE_FMT_SUB_QCIF || \ + (params)->format == PICTURE_FMT_QCIF) +#define H263_FMT_UPTO_CIF(params) \ + ((params)->format == PICTURE_FMT_SUB_QCIF || \ + (params)->format == PICTURE_FMT_QCIF || \ + (params)->format == PICTURE_FMT_CIF) +#define H263_FMT_CUSTOM_UPTO_QCIF(params) \ + ((params)->format == PICTURE_FMT_RESERVED1 && \ + (params)->height <= 144 && \ + (params)->width <= 176) +#define H263_FMT_CUSTOM_UPTO_CIF(params) \ + ((params)->format == PICTURE_FMT_RESERVED1 && \ + (params)->height <= 288 && \ + (params)->width <= 352) + +#define GST_FRACTION_LE(f1, f2) \ + ((gst_value_compare (&(f1), &(f2)) == GST_VALUE_LESS_THAN) || \ + (gst_value_compare (&(f1), &(f2)) == GST_VALUE_EQUAL)) + +gint +gst_h263_parse_get_level (H263Params * params, gint profile, + guint bitrate, gint fps_num, gint fps_denom) +{ + GValue fps15 = { 0, }; + GValue fps30 = { 0, }; + GValue fps50 = { 0, }; + GValue fps60 = { 0, }; + GValue fps = { 0, }; + + if (bitrate == 0) { + GST_DEBUG ("Can't calculate level since bitrate is unknown"); + return -1; + } + + g_value_init (&fps15, GST_TYPE_FRACTION); + g_value_init (&fps30, GST_TYPE_FRACTION); + g_value_init (&fps50, GST_TYPE_FRACTION); + g_value_init (&fps60, GST_TYPE_FRACTION); + g_value_init (&fps, GST_TYPE_FRACTION); + + gst_value_set_fraction (&fps15, 15000, 1001); + gst_value_set_fraction (&fps30, 30000, 1001); + gst_value_set_fraction (&fps50, 50, 1); + gst_value_set_fraction (&fps60, 60000, 1001); + + gst_value_set_fraction (&fps, fps_num, fps_denom); + + /* Level 10 */ + if (H263_FMT_UPTO_QCIF (params) && GST_FRACTION_LE (fps, fps15) && + bitrate <= 64000) + return 10; + + /* Level 20 */ + if (((H263_FMT_UPTO_QCIF (params) && GST_FRACTION_LE (fps, fps30)) || + (params->format == PICTURE_FMT_CIF && GST_FRACTION_LE (fps, fps15))) + && bitrate <= 128000) + return 20; + + /* Level 30 */ + if (H263_FMT_UPTO_CIF (params) && GST_FRACTION_LE (fps, fps30) && + bitrate <= 384000) + return 30; + + /* Level 40 */ + if (H263_FMT_UPTO_CIF (params) && GST_FRACTION_LE (fps, fps30) && + bitrate <= 2048000) + return 40; + + /* Level 45 */ + if ((H263_FMT_UPTO_QCIF (params) || (H263_FMT_CUSTOM_UPTO_QCIF (params) && + H263_PROFILE_NOT_0_2 (profile))) && + GST_FRACTION_LE (fps, fps15) && + /* (!h263parse->custompcfpresent || H263_PROFILE_NOT_0_2(profile)) && */ + bitrate <= 128000) + return 45; + + /* Level 50 */ + if ((H263_FMT_UPTO_CIF (params) || H263_FMT_CUSTOM_UPTO_CIF (params)) && + (GST_FRACTION_LE (fps, fps50) || + (params->width <= 352 && params->height <= 240 && + GST_FRACTION_LE (fps, fps60))) && (bitrate <= 4096000)) + return 50; + + /* Level 60 */ + if (((params->width <= 720 && params->height <= 288 && + GST_FRACTION_LE (fps, fps50)) || + (params->width <= 720 && params->height <= 240 && + GST_FRACTION_LE (fps, fps60))) && (bitrate <= 8192000)) + return 60; + + /* Level 70 */ + if (((params->width <= 720 && params->height <= 576 && + GST_FRACTION_LE (fps, fps50)) || + (params->width <= 720 && params->height <= 480 && + GST_FRACTION_LE (fps, fps60))) && (bitrate <= 16384000)) + return 70; + + GST_DEBUG ("Weird - didn't match any profile!"); + return -1; +} + +void +gst_h263_parse_get_framerate (GstCaps * sink_caps, H263Params * params, + gint * num, gint * denom) +{ + GstStructure *st; + + st = gst_caps_get_structure (sink_caps, 0); + + if (gst_structure_get_fraction (st, "framerate", num, denom)) { + /* Got it in caps - nothing more to do */ + GST_DEBUG ("Sink caps override framerate from headers"); + return; + } + + /* Caps didn't have the framerate - get it from params */ + *num = params->pcfnum; + *denom = params->pcfdenom; +} + +void +gst_h263_parse_set_src_caps (GstH263Parse * h263parse, H263Params * params) +{ + GstCaps *caps; + gint fr_num, fr_denom; + + g_assert (h263parse->state == PASSTHROUGH || h263parse->state == GOT_HEADER); + + caps = GST_PAD_CAPS (GST_BASE_PARSE_SINK_PAD (GST_BASE_PARSE (h263parse))); + if (caps) { + caps = gst_caps_copy (caps); + } else { + caps = gst_caps_new_simple ("video/x-h263", + "variant", G_TYPE_STRING, "itu", NULL); + } + gst_caps_set_simple (caps, "parsed", G_TYPE_BOOLEAN, TRUE, NULL); + + gst_h263_parse_get_framerate (caps, params, &fr_num, &fr_denom); + gst_caps_set_simple (caps, "framerate", GST_TYPE_FRACTION, fr_num, fr_denom, + NULL); + + if (h263parse->state == GOT_HEADER) { + gst_caps_set_simple (caps, + "annex-d", G_TYPE_BOOLEAN, (params->features & H263_OPTION_UMV_MODE), + "annex-e", G_TYPE_BOOLEAN, (params->features & H263_OPTION_SAC_MODE), + "annex-f", G_TYPE_BOOLEAN, (params->features & H263_OPTION_AP_MODE), + "annex-g", G_TYPE_BOOLEAN, (params->features & H263_OPTION_PB_MODE), + "annex-i", G_TYPE_BOOLEAN, (params->features & H263_OPTION_AIC_MODE), + "annex-j", G_TYPE_BOOLEAN, (params->features & H263_OPTION_DF_MODE), + "annex-k", G_TYPE_BOOLEAN, (params->features & H263_OPTION_SS_MODE), + "annex-m", G_TYPE_BOOLEAN, (params->type == PICTURE_IMPROVED_PB), + "annex-n", G_TYPE_BOOLEAN, (params->features & H263_OPTION_RPS_MODE), + "annex-q", G_TYPE_BOOLEAN, (params->features & H263_OPTION_RRU_MODE), + "annex-r", G_TYPE_BOOLEAN, (params->features & H263_OPTION_ISD_MODE), + "annex-s", G_TYPE_BOOLEAN, (params->features & H263_OPTION_AIV_MODE), + "annex-t", G_TYPE_BOOLEAN, (params->features & H263_OPTION_MQ_MODE), + "annex-u", G_TYPE_BOOLEAN, (params->features & H263_OPTION_ERPS_MODE), + "annex-v", G_TYPE_BOOLEAN, (params->features & H263_OPTION_DPS_MODE), + NULL); + + h263parse->profile = gst_h263_parse_get_profile (params); + if (h263parse->profile != -1) + gst_caps_set_simple (caps, "profile", G_TYPE_UINT, h263parse->profile, + NULL); + + h263parse->level = gst_h263_parse_get_level (params, h263parse->profile, + h263parse->bitrate, fr_num, fr_denom); + if (h263parse->level != -1) + gst_caps_set_simple (caps, "level", G_TYPE_UINT, h263parse->level, NULL); + } + + gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (GST_BASE_PARSE (h263parse)), caps); + gst_caps_unref (caps); +} From 0e6fbe2420cd971d5a9a023eaaa3352da21295e9 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Fri, 10 Dec 2010 16:26:27 +0100 Subject: [PATCH 362/448] h263parse: simplify valid_frame parsing ... considering that baseparse takes care of skipping etc --- gst/h263parse/gsth263parse.c | 44 ++++++++++++++---------------------- gst/h263parse/gsth263parse.h | 3 --- 2 files changed, 17 insertions(+), 30 deletions(-) diff --git a/gst/h263parse/gsth263parse.c b/gst/h263parse/gsth263parse.c index f09ee65858..f6dc3513f1 100644 --- a/gst/h263parse/gsth263parse.c +++ b/gst/h263parse/gsth263parse.c @@ -106,9 +106,6 @@ gst_h263_parse_start (GstBaseParse * parse) GST_DEBUG ("Start"); - h263parse->last_pos = 0; - h263parse->psc_pos = -1; - h263parse->bitrate = 0; h263parse->profile = -1; h263parse->level = -1; @@ -188,34 +185,31 @@ gst_h263_parse_check_valid_frame (GstBaseParse * parse, GstBuffer * buffer, guint * framesize, gint * skipsize) { GstH263Parse *h263parse; - guint psc_pos; + guint psc_pos, next_psc_pos; h263parse = GST_H263PARSE (parse); - psc_pos = find_psc (buffer, h263parse->last_pos); + psc_pos = find_psc (buffer, 0); if (psc_pos == -1) { /* PSC not found, need more data */ if (GST_BUFFER_SIZE (buffer) > 3) - h263parse->last_pos = GST_BUFFER_SIZE (buffer) - 3; + psc_pos = GST_BUFFER_SIZE (buffer) - 3; + else + psc_pos = 0; goto more; } - if (h263parse->psc_pos == -1) { - /* Found the start of the frame, now try to find the end */ + /* Found the start of the frame, now try to find the end */ + next_psc_pos = psc_pos + 3; + next_psc_pos = find_psc (buffer, next_psc_pos); - h263parse->psc_pos = psc_pos; - h263parse->last_pos = psc_pos + 3; - - psc_pos = find_psc (buffer, h263parse->last_pos); - - if (psc_pos == -1) { - if (gst_base_parse_get_drain (GST_BASE_PARSE (h263parse))) - /* FLUSH/EOS, it's okay if we can't find the next frame */ - psc_pos = GST_BUFFER_SIZE (buffer); - else - goto more; - } + if (next_psc_pos == -1) { + if (gst_base_parse_get_drain (GST_BASE_PARSE (h263parse))) + /* FLUSH/EOS, it's okay if we can't find the next frame */ + next_psc_pos = GST_BUFFER_SIZE (buffer); + else + goto more; } /* We should now have a complete frame */ @@ -238,11 +232,8 @@ gst_h263_parse_check_valid_frame (GstBaseParse * parse, GstBuffer * buffer, g_free (params); } - *skipsize = h263parse->psc_pos; - *framesize = psc_pos - h263parse->psc_pos; - - h263parse->psc_pos = -1; - h263parse->last_pos = 0; + *skipsize = psc_pos; + *framesize = next_psc_pos - psc_pos; /* XXX: After getting a keyframe, should we adjust min_frame_size to * something smaller so we don't end up collecting too many non-keyframes? */ @@ -255,8 +246,7 @@ more: /* Ask for 1024 bytes more - this is an arbitrary choice */ gst_base_parse_set_min_frame_size (parse, GST_BUFFER_SIZE (buffer) + 1024); - /* Prevent baseparse from auto-skipping one byte */ - *skipsize = 0; + *skipsize = psc_pos; return FALSE; } diff --git a/gst/h263parse/gsth263parse.h b/gst/h263parse/gsth263parse.h index 11ca426096..ea9f9286cf 100644 --- a/gst/h263parse/gsth263parse.h +++ b/gst/h263parse/gsth263parse.h @@ -65,9 +65,6 @@ struct _GstH263Parse { GstBaseParse baseparse; - gint psc_pos; - guint last_pos; - gint profile, level; guint bitrate; From 5ad0a3c641e2cae811dd372522ab5f2874c5af65 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Fri, 10 Dec 2010 16:40:44 +0100 Subject: [PATCH 363/448] h263parse: remove redundant get_caps .. as src pad already set to use fixed_caps --- gst/h263parse/gsth263parse.c | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/gst/h263parse/gsth263parse.c b/gst/h263parse/gsth263parse.c index f6dc3513f1..14f5a5c987 100644 --- a/gst/h263parse/gsth263parse.c +++ b/gst/h263parse/gsth263parse.c @@ -58,7 +58,6 @@ static gboolean gst_h263_parse_check_valid_frame (GstBaseParse * parse, GstBuffer * buffer, guint * framesize, gint * skipsize); static GstFlowReturn gst_h263_parse_parse_frame (GstBaseParse * parse, GstBuffer * buffer); -static GstCaps *gst_h263_parse_src_getcaps (GstPad * pad); static void gst_h263_parse_base_init (gpointer g_class) @@ -95,8 +94,6 @@ gst_h263_parse_class_init (GstH263ParseClass * klass) static void gst_h263_parse_init (GstH263Parse * h263parse, GstH263ParseClass * g_class) { - gst_pad_set_getcaps_function (GST_BASE_PARSE_SRC_PAD (GST_BASE_PARSE - (h263parse)), GST_DEBUG_FUNCPTR (gst_h263_parse_src_getcaps)); } static gboolean @@ -288,22 +285,6 @@ out: return res; } -static GstCaps * -gst_h263_parse_src_getcaps (GstPad * pad) -{ - GstH263Parse *h263parse; - GstCaps *caps; - - h263parse = GST_H263PARSE (GST_PAD_PARENT (pad)); - - if (h263parse->state == PARSING) - /* Not got more specific caps from headers yet - return template caps */ - return gst_caps_copy (gst_pad_get_pad_template_caps (pad)); - - g_object_get (pad, "caps", &caps, NULL); - return caps; -} - static gboolean plugin_init (GstPlugin * plugin) { From daed6713dbb4c5deceab5f7df4b4e63b004df664 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Thu, 6 Jan 2011 12:34:12 +0100 Subject: [PATCH 364/448] h263parse: provide for proper debug category, min frame size and code style --- gst/h263parse/gsth263parse.c | 13 +++++++++---- gst/h263parse/gsth263parse.h | 24 +++++++++++------------- gst/h263parse/h263parse.c | 3 +++ 3 files changed, 23 insertions(+), 17 deletions(-) diff --git a/gst/h263parse/gsth263parse.c b/gst/h263parse/gsth263parse.c index 14f5a5c987..b150751d2d 100644 --- a/gst/h263parse/gsth263parse.c +++ b/gst/h263parse/gsth263parse.c @@ -33,6 +33,7 @@ #include "gsth263parse.h" GST_DEBUG_CATEGORY (h263_parse_debug); +#define GST_CAT_DEFAULT h263_parse_debug static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, @@ -99,7 +100,7 @@ gst_h263_parse_init (GstH263Parse * h263parse, GstH263ParseClass * g_class) static gboolean gst_h263_parse_start (GstBaseParse * parse) { - GstH263Parse *h263parse = GST_H263PARSE (parse); + GstH263Parse *h263parse = GST_H263_PARSE (parse); GST_DEBUG ("Start"); @@ -109,6 +110,7 @@ gst_h263_parse_start (GstBaseParse * parse) h263parse->state = PARSING; + gst_base_parse_set_min_frame_size (parse, 512); gst_base_parse_set_passthrough (parse, FALSE); return TRUE; @@ -128,7 +130,7 @@ gst_h263_parse_sink_event (GstBaseParse * parse, GstEvent * event) GstH263Parse *h263parse; gboolean res = FALSE; - h263parse = GST_H263PARSE (parse); + h263parse = GST_H263_PARSE (parse); switch (GST_EVENT_TYPE (event)) { case GST_EVENT_TAG: @@ -184,7 +186,10 @@ gst_h263_parse_check_valid_frame (GstBaseParse * parse, GstBuffer * buffer, GstH263Parse *h263parse; guint psc_pos, next_psc_pos; - h263parse = GST_H263PARSE (parse); + h263parse = GST_H263_PARSE (parse); + + if (GST_BUFFER_SIZE (buffer) < 3) + return FALSE; psc_pos = find_psc (buffer, 0); @@ -255,7 +260,7 @@ gst_h263_parse_parse_frame (GstBaseParse * parse, GstBuffer * buffer) GstFlowReturn res; H263Params *params = NULL; - h263parse = GST_H263PARSE (parse); + h263parse = GST_H263_PARSE (parse); res = gst_h263_parse_get_params (h263parse, buffer, ¶ms, TRUE); if (res != GST_FLOW_OK) diff --git a/gst/h263parse/gsth263parse.h b/gst/h263parse/gsth263parse.h index ea9f9286cf..c7c8fdb19e 100644 --- a/gst/h263parse/gsth263parse.h +++ b/gst/h263parse/gsth263parse.h @@ -30,10 +30,7 @@ #include #include -#include "gstbaseparse.h" - -GST_DEBUG_CATEGORY_EXTERN (h263_parse_debug); -#define GST_CAT_DEFAULT h263_parse_debug +#include G_BEGIN_DECLS @@ -46,16 +43,17 @@ typedef enum typedef struct _H263Params H263Params; -#define GST_TYPE_H263PARSE \ +#define GST_TYPE_H263_PARSE \ (gst_h263_parse_get_type()) -#define GST_H263PARSE(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_H263PARSE,GstH263Parse)) -#define GST_H263PARSE_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_H263PARSE,GstH263ParseClass)) -#define GST_IS_H263PARSE(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_H263PARSE)) -#define GST_IS_H263PARSE_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_H263PARSE)) +#define GST_H263_PARSE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_H263_PARSE,GstH263Parse)) +#define GST_H263_PARSE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_H263_PARSE,GstH263ParseClass)) +#define GST_IS_H263_PARSE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_H263_PARSE)) +#define GST_IS_H263_PARSE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_H263_PARSE)) + GType gst_h263_parse_get_type (void); typedef struct _GstH263Parse GstH263Parse; diff --git a/gst/h263parse/h263parse.c b/gst/h263parse/h263parse.c index b46dcdab8f..0ed681ba90 100644 --- a/gst/h263parse/h263parse.c +++ b/gst/h263parse/h263parse.c @@ -27,6 +27,9 @@ #include #include "gsth263parse.h" +GST_DEBUG_CATEGORY_EXTERN (h263_parse_debug); +#define GST_CAT_DEFAULT h263_parse_debug + /* H263 Optional Features */ typedef enum { From 46308f8c535efd5499ddb9401b73ee189929f775 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Thu, 6 Jan 2011 12:29:34 +0100 Subject: [PATCH 365/448] h263parse: shuffle code to untangle h263parse and parameter parsing --- gst/h263parse/Makefile.am | 2 +- gst/h263parse/gsth263parse.c | 70 ++++++++++++++- gst/h263parse/gsth263parse.h | 22 +---- gst/h263parse/h263parse.c | 170 ++--------------------------------- gst/h263parse/h263parse.h | 144 +++++++++++++++++++++++++++++ 5 files changed, 219 insertions(+), 189 deletions(-) create mode 100644 gst/h263parse/h263parse.h diff --git a/gst/h263parse/Makefile.am b/gst/h263parse/Makefile.am index 3ea9c20020..eda4c3840a 100644 --- a/gst/h263parse/Makefile.am +++ b/gst/h263parse/Makefile.am @@ -6,4 +6,4 @@ libgsth263parse_la_LIBADD = $(GST_BASE_LIBS) $(GST_LIBS) libgsth263parse_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) libgsth263parse_la_LIBTOOLFLAGS = --tag=disable-static -noinst_HEADERS = gsth263parse.h gstbaseparse.h +noinst_HEADERS = gsth263parse.h h263parse.h gstbaseparse.h diff --git a/gst/h263parse/gsth263parse.c b/gst/h263parse/gsth263parse.c index b150751d2d..b17851aa7e 100644 --- a/gst/h263parse/gsth263parse.c +++ b/gst/h263parse/gsth263parse.c @@ -179,6 +179,70 @@ out: return psc_pos; } +static void +gst_h263_parse_set_src_caps (GstH263Parse * h263parse, H263Params * params) +{ + GstStructure *st; + GstCaps *caps, *sink_caps; + gint fr_num, fr_denom; + + g_assert (h263parse->state == PASSTHROUGH || h263parse->state == GOT_HEADER); + + caps = GST_PAD_CAPS (GST_BASE_PARSE_SINK_PAD (h263parse)); + if (caps) { + caps = gst_caps_copy (caps); + } else { + caps = gst_caps_new_simple ("video/x-h263", + "variant", G_TYPE_STRING, "itu", NULL); + } + gst_caps_set_simple (caps, "parsed", G_TYPE_BOOLEAN, TRUE, NULL); + + sink_caps = GST_PAD_CAPS (GST_BASE_PARSE_SINK_PAD (h263parse)); + if (sink_caps && (st = gst_caps_get_structure (sink_caps, 0)) && + gst_structure_get_fraction (st, "framerate", &fr_num, &fr_denom)) { + /* Got it in caps - nothing more to do */ + GST_DEBUG ("Sink caps override framerate from headers"); + } else { + /* Caps didn't have the framerate - get it from params */ + gst_h263_parse_get_framerate (params, &fr_num, &fr_denom); + } + gst_caps_set_simple (caps, "framerate", GST_TYPE_FRACTION, fr_num, fr_denom, + NULL); + + if (h263parse->state == GOT_HEADER) { + gst_caps_set_simple (caps, + "annex-d", G_TYPE_BOOLEAN, (params->features & H263_OPTION_UMV_MODE), + "annex-e", G_TYPE_BOOLEAN, (params->features & H263_OPTION_SAC_MODE), + "annex-f", G_TYPE_BOOLEAN, (params->features & H263_OPTION_AP_MODE), + "annex-g", G_TYPE_BOOLEAN, (params->features & H263_OPTION_PB_MODE), + "annex-i", G_TYPE_BOOLEAN, (params->features & H263_OPTION_AIC_MODE), + "annex-j", G_TYPE_BOOLEAN, (params->features & H263_OPTION_DF_MODE), + "annex-k", G_TYPE_BOOLEAN, (params->features & H263_OPTION_SS_MODE), + "annex-m", G_TYPE_BOOLEAN, (params->type == PICTURE_IMPROVED_PB), + "annex-n", G_TYPE_BOOLEAN, (params->features & H263_OPTION_RPS_MODE), + "annex-q", G_TYPE_BOOLEAN, (params->features & H263_OPTION_RRU_MODE), + "annex-r", G_TYPE_BOOLEAN, (params->features & H263_OPTION_ISD_MODE), + "annex-s", G_TYPE_BOOLEAN, (params->features & H263_OPTION_AIV_MODE), + "annex-t", G_TYPE_BOOLEAN, (params->features & H263_OPTION_MQ_MODE), + "annex-u", G_TYPE_BOOLEAN, (params->features & H263_OPTION_ERPS_MODE), + "annex-v", G_TYPE_BOOLEAN, (params->features & H263_OPTION_DPS_MODE), + NULL); + + h263parse->profile = gst_h263_parse_get_profile (params); + if (h263parse->profile != -1) + gst_caps_set_simple (caps, "profile", G_TYPE_UINT, h263parse->profile, + NULL); + + h263parse->level = gst_h263_parse_get_level (params, h263parse->profile, + h263parse->bitrate, fr_num, fr_denom); + if (h263parse->level != -1) + gst_caps_set_simple (caps, "level", G_TYPE_UINT, h263parse->level, NULL); + } + + gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (GST_BASE_PARSE (h263parse)), caps); + gst_caps_unref (caps); +} + static gboolean gst_h263_parse_check_valid_frame (GstBaseParse * parse, GstBuffer * buffer, guint * framesize, gint * skipsize) @@ -219,9 +283,9 @@ gst_h263_parse_check_valid_frame (GstBaseParse * parse, GstBuffer * buffer, /* If this is the first frame, parse and set srcpad caps */ if (h263parse->state == PARSING) { H263Params *params = NULL; - GstFlowReturn res = gst_h263_parse_get_params (h263parse, buffer, - ¶ms, FALSE); + GstFlowReturn res; + res = gst_h263_parse_get_params (¶ms, buffer, FALSE, &h263parse->state); if (res != GST_FLOW_OK || h263parse->state != GOT_HEADER) { GST_WARNING ("Couldn't parse header - setting passthrough mode"); gst_base_parse_set_passthrough (parse, TRUE); @@ -262,7 +326,7 @@ gst_h263_parse_parse_frame (GstBaseParse * parse, GstBuffer * buffer) h263parse = GST_H263_PARSE (parse); - res = gst_h263_parse_get_params (h263parse, buffer, ¶ms, TRUE); + res = gst_h263_parse_get_params (¶ms, buffer, TRUE, &h263parse->state); if (res != GST_FLOW_OK) goto out; diff --git a/gst/h263parse/gsth263parse.h b/gst/h263parse/gsth263parse.h index c7c8fdb19e..86ebb6b69c 100644 --- a/gst/h263parse/gsth263parse.h +++ b/gst/h263parse/gsth263parse.h @@ -32,17 +32,10 @@ #include #include +#include "h263parse.h" + G_BEGIN_DECLS -typedef enum -{ - PARSING = 0, - GOT_HEADER, - PASSTHROUGH -} H263ParseState; - -typedef struct _H263Params H263Params; - #define GST_TYPE_H263_PARSE \ (gst_h263_parse_get_type()) #define GST_H263_PARSE(obj) \ @@ -74,16 +67,5 @@ struct _GstH263ParseClass GstBaseParseClass parent_class; }; -gboolean gst_h263_parse_is_delta_unit (H263Params * params); -GstFlowReturn gst_h263_parse_get_params (GstH263Parse * h263parse, - GstBuffer * buffer, H263Params ** params_p, gboolean fast); -void gst_h263_parse_get_framerate (GstCaps * caps, H263Params * params, - gint * num, gint * denom); -void gst_h263_parse_set_src_caps (GstH263Parse * h263parse, - H263Params * params); -gint gst_h263_parse_get_profile (H263Params * params); -gint gst_h263_parse_get_level (H263Params * params, gint profile, - guint bitrate, gint fps_num, gint fps_denom); - G_END_DECLS #endif diff --git a/gst/h263parse/h263parse.c b/gst/h263parse/h263parse.c index 0ed681ba90..ace1e18a2f 100644 --- a/gst/h263parse/h263parse.c +++ b/gst/h263parse/h263parse.c @@ -30,99 +30,6 @@ GST_DEBUG_CATEGORY_EXTERN (h263_parse_debug); #define GST_CAT_DEFAULT h263_parse_debug -/* H263 Optional Features */ -typedef enum -{ - /* Optional Unrestricted Motion Vector (UMV) mode (see Annex D) */ - H263_OPTION_UMV_MODE = 1 << 0, - /* Optional Syntax-based Arithmetic Coding (SAC) mode (see Annex E) */ - H263_OPTION_SAC_MODE = 1 << 1, - /* Optional Advanced Prediction mode (AP) (see Annex F) */ - H263_OPTION_AP_MODE = 1 << 2, - /* Optional PB-frames mode (see Annex G) */ - H263_OPTION_PB_MODE = 1 << 3, - /* Optional Advanced INTRA Coding (AIC) mode (see Annex I) */ - H263_OPTION_AIC_MODE = 1 << 4, - /* Optional Deblocking Filter (DF) mode (see Annex J) */ - H263_OPTION_DF_MODE = 1 << 5, - /* Optional Slice Structured (SS) mode (see Annex K) */ - H263_OPTION_SS_MODE = 1 << 6, - /* Optional Reference Picture Selection (RPS) mode (see Annex N) */ - H263_OPTION_RPS_MODE = 1 << 7, - /* Optional Independent Segment Decoding (ISD) mode (see Annex R) */ - H263_OPTION_ISD_MODE = 1 << 8, - /* Optional Alternative INTER VLC (AIV) mode (see Annex S) */ - H263_OPTION_AIV_MODE = 1 << 9, - /* Optional Modified Quantization (MQ) mode (see Annex T) */ - H263_OPTION_MQ_MODE = 1 << 10, - /* Optional Reference Picture Resampling (RPR) mode (see Annex P) */ - H263_OPTION_RPR_MODE = 1 << 11, - /* Optional Reduced-Resolution Update (RRU) mode (see Annex Q) */ - H263_OPTION_RRU_MODE = 1 << 12, - /* Optional Enhanced Reference Picture Selection (ERPS) mode (see Annex U) */ - H263_OPTION_ERPS_MODE = 1 << 13, - /* Optional Data Partitioned Slices (DPS) mode (see Annex V) */ - H263_OPTION_DPS_MODE = 1 << 14 -} H263OptionalFeatures; - -/* H263 Picture Types */ -typedef enum -{ - PICTURE_I = 0, /* I-picture (INTRA) Baseline */ - PICTURE_P, /* P-picture (INTER) Baseline */ - PICTURE_IMPROVED_PB, /* Improved PB-frame (Annex M) */ - PICTURE_B, /* B-picture (Annex O) */ - PICTURE_EI, /* EI-picture (Annex O) */ - PICTURE_EP, /* EP-picture (Annex O) */ - PICTURE_RESERVED1, - PICTURE_RESERVED2, - PICTURE_PB /* PB-frame (See Annex G) */ -} H263PictureType; - -/* H263 Picture Format */ -typedef enum -{ - PICTURE_FMT_FORBIDDEN_0 = 0, - PICTURE_FMT_SUB_QCIF, - PICTURE_FMT_QCIF, - PICTURE_FMT_CIF, - PICTURE_FMT_4CIF, - PICTURE_FMT_16CIF, - PICTURE_FMT_RESERVED1, - PICTURE_FMT_EXTENDEDPTYPE -} H263PictureFormat; - -typedef enum -{ - UUI_ABSENT = 0, - UUI_IS_1, - UUI_IS_01, -} H263UUI; - -struct _H263Params -{ - guint32 temporal_ref; - - H263OptionalFeatures features; - - gboolean splitscreen; - gboolean documentcamera; - gboolean fullpicturefreezerelease; - gboolean custompcfpresent; - H263UUI uui; - guint8 sss; - - H263PictureFormat format; - - H263PictureType type; - - guint32 width; - guint32 height; - guint8 parnum, pardenom; - gint32 pcfnum, pcfdenom; -}; - - gboolean gst_h263_parse_is_delta_unit (H263Params * params) { @@ -133,8 +40,8 @@ gst_h263_parse_is_delta_unit (H263Params * params) * extract a subset of the data (for now, it quits once we have the picture * type. */ GstFlowReturn -gst_h263_parse_get_params (GstH263Parse * h263parse, GstBuffer * buffer, - H263Params ** params_p, gboolean fast) +gst_h263_parse_get_params (H263Params ** params_p, GstBuffer * buffer, + gboolean fast, H263ParseState * state) { static const guint8 partable[6][2] = { {1, 0}, @@ -538,12 +445,12 @@ gst_h263_parse_get_params (GstH263Parse * h263parse, GstBuffer * buffer, * have no means of specifying what sub-modes, if any, are used. */ done: - h263parse->state = GOT_HEADER; + *state = GOT_HEADER; more: return GST_FLOW_OK; beach: - h263parse->state = PASSTHROUGH; + *state = PASSTHROUGH; return GST_FLOW_OK; } @@ -752,75 +659,8 @@ gst_h263_parse_get_level (H263Params * params, gint profile, } void -gst_h263_parse_get_framerate (GstCaps * sink_caps, H263Params * params, - gint * num, gint * denom) +gst_h263_parse_get_framerate (H263Params * params, gint * num, gint * denom) { - GstStructure *st; - - st = gst_caps_get_structure (sink_caps, 0); - - if (gst_structure_get_fraction (st, "framerate", num, denom)) { - /* Got it in caps - nothing more to do */ - GST_DEBUG ("Sink caps override framerate from headers"); - return; - } - - /* Caps didn't have the framerate - get it from params */ *num = params->pcfnum; *denom = params->pcfdenom; } - -void -gst_h263_parse_set_src_caps (GstH263Parse * h263parse, H263Params * params) -{ - GstCaps *caps; - gint fr_num, fr_denom; - - g_assert (h263parse->state == PASSTHROUGH || h263parse->state == GOT_HEADER); - - caps = GST_PAD_CAPS (GST_BASE_PARSE_SINK_PAD (GST_BASE_PARSE (h263parse))); - if (caps) { - caps = gst_caps_copy (caps); - } else { - caps = gst_caps_new_simple ("video/x-h263", - "variant", G_TYPE_STRING, "itu", NULL); - } - gst_caps_set_simple (caps, "parsed", G_TYPE_BOOLEAN, TRUE, NULL); - - gst_h263_parse_get_framerate (caps, params, &fr_num, &fr_denom); - gst_caps_set_simple (caps, "framerate", GST_TYPE_FRACTION, fr_num, fr_denom, - NULL); - - if (h263parse->state == GOT_HEADER) { - gst_caps_set_simple (caps, - "annex-d", G_TYPE_BOOLEAN, (params->features & H263_OPTION_UMV_MODE), - "annex-e", G_TYPE_BOOLEAN, (params->features & H263_OPTION_SAC_MODE), - "annex-f", G_TYPE_BOOLEAN, (params->features & H263_OPTION_AP_MODE), - "annex-g", G_TYPE_BOOLEAN, (params->features & H263_OPTION_PB_MODE), - "annex-i", G_TYPE_BOOLEAN, (params->features & H263_OPTION_AIC_MODE), - "annex-j", G_TYPE_BOOLEAN, (params->features & H263_OPTION_DF_MODE), - "annex-k", G_TYPE_BOOLEAN, (params->features & H263_OPTION_SS_MODE), - "annex-m", G_TYPE_BOOLEAN, (params->type == PICTURE_IMPROVED_PB), - "annex-n", G_TYPE_BOOLEAN, (params->features & H263_OPTION_RPS_MODE), - "annex-q", G_TYPE_BOOLEAN, (params->features & H263_OPTION_RRU_MODE), - "annex-r", G_TYPE_BOOLEAN, (params->features & H263_OPTION_ISD_MODE), - "annex-s", G_TYPE_BOOLEAN, (params->features & H263_OPTION_AIV_MODE), - "annex-t", G_TYPE_BOOLEAN, (params->features & H263_OPTION_MQ_MODE), - "annex-u", G_TYPE_BOOLEAN, (params->features & H263_OPTION_ERPS_MODE), - "annex-v", G_TYPE_BOOLEAN, (params->features & H263_OPTION_DPS_MODE), - NULL); - - h263parse->profile = gst_h263_parse_get_profile (params); - if (h263parse->profile != -1) - gst_caps_set_simple (caps, "profile", G_TYPE_UINT, h263parse->profile, - NULL); - - h263parse->level = gst_h263_parse_get_level (params, h263parse->profile, - h263parse->bitrate, fr_num, fr_denom); - if (h263parse->level != -1) - gst_caps_set_simple (caps, "level", G_TYPE_UINT, h263parse->level, NULL); - } - - gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (GST_BASE_PARSE (h263parse)), caps); - gst_caps_unref (caps); -} diff --git a/gst/h263parse/h263parse.h b/gst/h263parse/h263parse.h new file mode 100644 index 0000000000..81dbed3299 --- /dev/null +++ b/gst/h263parse/h263parse.h @@ -0,0 +1,144 @@ +/* GStreamer H.263 Parser + * Copyright (C) <2010> Arun Raghavan + * Copyright (C) <2010> Edward Hervey + * Copyright (C) <2010> Collabora Multimedia + * Copyright (C) <2010> Nokia Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_H263_PARAMS_H__ +#define __GST_H263_PARAMS_H__ + +#include +#include +#include + +G_BEGIN_DECLS + +typedef enum +{ + PARSING = 0, + GOT_HEADER, + PASSTHROUGH +} H263ParseState; + +/* H263 Optional Features */ +typedef enum +{ + /* Optional Unrestricted Motion Vector (UMV) mode (see Annex D) */ + H263_OPTION_UMV_MODE = 1 << 0, + /* Optional Syntax-based Arithmetic Coding (SAC) mode (see Annex E) */ + H263_OPTION_SAC_MODE = 1 << 1, + /* Optional Advanced Prediction mode (AP) (see Annex F) */ + H263_OPTION_AP_MODE = 1 << 2, + /* Optional PB-frames mode (see Annex G) */ + H263_OPTION_PB_MODE = 1 << 3, + /* Optional Advanced INTRA Coding (AIC) mode (see Annex I) */ + H263_OPTION_AIC_MODE = 1 << 4, + /* Optional Deblocking Filter (DF) mode (see Annex J) */ + H263_OPTION_DF_MODE = 1 << 5, + /* Optional Slice Structured (SS) mode (see Annex K) */ + H263_OPTION_SS_MODE = 1 << 6, + /* Optional Reference Picture Selection (RPS) mode (see Annex N) */ + H263_OPTION_RPS_MODE = 1 << 7, + /* Optional Independent Segment Decoding (ISD) mode (see Annex R) */ + H263_OPTION_ISD_MODE = 1 << 8, + /* Optional Alternative INTER VLC (AIV) mode (see Annex S) */ + H263_OPTION_AIV_MODE = 1 << 9, + /* Optional Modified Quantization (MQ) mode (see Annex T) */ + H263_OPTION_MQ_MODE = 1 << 10, + /* Optional Reference Picture Resampling (RPR) mode (see Annex P) */ + H263_OPTION_RPR_MODE = 1 << 11, + /* Optional Reduced-Resolution Update (RRU) mode (see Annex Q) */ + H263_OPTION_RRU_MODE = 1 << 12, + /* Optional Enhanced Reference Picture Selection (ERPS) mode (see Annex U) */ + H263_OPTION_ERPS_MODE = 1 << 13, + /* Optional Data Partitioned Slices (DPS) mode (see Annex V) */ + H263_OPTION_DPS_MODE = 1 << 14 +} H263OptionalFeatures; + +/* H263 Picture Types */ +typedef enum +{ + PICTURE_I = 0, /* I-picture (INTRA) Baseline */ + PICTURE_P, /* P-picture (INTER) Baseline */ + PICTURE_IMPROVED_PB, /* Improved PB-frame (Annex M) */ + PICTURE_B, /* B-picture (Annex O) */ + PICTURE_EI, /* EI-picture (Annex O) */ + PICTURE_EP, /* EP-picture (Annex O) */ + PICTURE_RESERVED1, + PICTURE_RESERVED2, + PICTURE_PB /* PB-frame (See Annex G) */ +} H263PictureType; + +/* H263 Picture Format */ +typedef enum +{ + PICTURE_FMT_FORBIDDEN_0 = 0, + PICTURE_FMT_SUB_QCIF, + PICTURE_FMT_QCIF, + PICTURE_FMT_CIF, + PICTURE_FMT_4CIF, + PICTURE_FMT_16CIF, + PICTURE_FMT_RESERVED1, + PICTURE_FMT_EXTENDEDPTYPE +} H263PictureFormat; + +typedef enum +{ + UUI_ABSENT = 0, + UUI_IS_1, + UUI_IS_01, +} H263UUI; + + +typedef struct _H263Params H263Params; + +struct _H263Params +{ + guint32 temporal_ref; + + H263OptionalFeatures features; + + gboolean splitscreen; + gboolean documentcamera; + gboolean fullpicturefreezerelease; + gboolean custompcfpresent; + H263UUI uui; + guint8 sss; + + H263PictureFormat format; + + H263PictureType type; + + guint32 width; + guint32 height; + guint8 parnum, pardenom; + gint32 pcfnum, pcfdenom; +}; + +gboolean gst_h263_parse_is_delta_unit (H263Params * params); +GstFlowReturn gst_h263_parse_get_params (H263Params ** params_p, + GstBuffer * buffer, gboolean fast, H263ParseState * state); +void gst_h263_parse_get_framerate (H263Params * params, + gint * num, gint * denom); +gint gst_h263_parse_get_profile (H263Params * params); +gint gst_h263_parse_get_level (H263Params * params, gint profile, + guint bitrate, gint fps_num, gint fps_denom); + +G_END_DECLS +#endif From 1664b3000fdfce5bf0a716391cd38817d3bb21ab Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Thu, 27 Jan 2011 18:03:50 +0100 Subject: [PATCH 366/448] h263parse: update to latest baseparse --- gst/h263parse/gstbaseparse.c | 581 +++++++++++++++++++++++------------ gst/h263parse/gstbaseparse.h | 174 +++++++---- gst/h263parse/gsth263parse.c | 22 +- 3 files changed, 518 insertions(+), 259 deletions(-) diff --git a/gst/h263parse/gstbaseparse.c b/gst/h263parse/gstbaseparse.c index 734119493a..ccb11fb3d8 100644 --- a/gst/h263parse/gstbaseparse.c +++ b/gst/h263parse/gstbaseparse.c @@ -76,22 +76,27 @@ * #GstAdapter. * * - * A buffer of min_frame_size bytes is passed to subclass with + * A buffer of (at least) min_frame_size bytes is passed to subclass with * @check_valid_frame. Subclass checks the contents and returns TRUE * if the buffer contains a valid frame. It also needs to set the * @framesize according to the detected frame size. If buffer didn't * contain a valid frame, this call must return FALSE and optionally * set the @skipsize value to inform base class that how many bytes - * it needs to skip in order to find a valid frame. The passed buffer + * it needs to skip in order to find a valid frame. @framesize can always + * indicate a new minimum for current frame parsing. The passed buffer * is read-only. Note that @check_valid_frame might receive any small * amount of input data when leftover data is being drained (e.g. at EOS). * * * After valid frame is found, it will be passed again to subclass with * @parse_frame call. Now subclass is responsible for parsing the - * frame contents and setting the caps, buffer timestamp and duration + * frame contents and setting the caps, and buffer metadata (e.g. + * buffer timestamp and duration, or keyframe if applicable). * (although the latter can also be done by GstBaseParse if it is - * appropriately configured, see below). + * appropriately configured, see below). Frame is provided with + * timestamp derived from upstream (as much as generally possible), + * duration obtained form configuration (see below), and offset + * if meaningful (in pull mode). * * * Finally the buffer can be pushed downstream and parsing loop starts @@ -156,7 +161,7 @@ * Update the duration information with @gst_base_parse_set_duration * * - * Optionally passthrough using @gst_base_parse_set_passthrough + * Optionally passthrough using @gst_base_parse_set_format * * * Configure various baseparse parameters using @gst_base_parse_set_seek and @@ -218,9 +223,9 @@ struct _GstBaseParsePrivate gint64 estimated_duration; guint min_frame_size; - gboolean passthrough; + guint format; guint fps_num, fps_den; - guint update_interval; + gint update_interval; guint bitrate; guint lead_in, lead_out; GstClockTime lead_in_ts, lead_out_ts; @@ -269,7 +274,7 @@ struct _GstBaseParsePrivate GstClockTimeDiff idx_interval; /* ts and offset of last entry added */ GstClockTime index_last_ts; - guint64 index_last_offset; + gint64 index_last_offset; gboolean index_last_valid; /* timestamps currently produced are accurate, e.g. started from 0 onwards */ @@ -280,6 +285,7 @@ struct _GstBaseParsePrivate /* reverse playback */ GSList *buffers_pending; GSList *buffers_queued; + GSList *buffers_send; GstClockTime last_ts; gint64 last_offset; }; @@ -292,6 +298,12 @@ typedef struct _GstBaseParseSeek GstClockTime start_ts; } GstBaseParseSeek; +#define GST_BASE_PARSE_PASSTHROUGH(parse) \ + (parse->priv->format & GST_BASE_PARSE_FORMAT_PASSTHROUGH) +#define GST_BASE_PARSE_HAS_TIME(parse) \ + (parse->priv->format & GST_BASE_PARSE_FORMAT_HAS_TIME) + + static GstElementClass *parent_class = NULL; static void gst_base_parse_class_init (GstBaseParseClass * klass); @@ -350,10 +362,9 @@ static GstFlowReturn gst_base_parse_chain (GstPad * pad, GstBuffer * buffer); static void gst_base_parse_loop (GstPad * pad); static gboolean gst_base_parse_check_frame (GstBaseParse * parse, - GstBuffer * buffer, guint * framesize, gint * skipsize); - + GstBaseParseFrame * frame, guint * framesize, gint * skipsize); static GstFlowReturn gst_base_parse_parse_frame (GstBaseParse * parse, - GstBuffer * buffer); + GstBaseParseFrame * frame); static gboolean gst_base_parse_sink_eventfunc (GstBaseParse * parse, GstEvent * event); @@ -384,6 +395,9 @@ gst_base_parse_clear_queues (GstBaseParse * parse) NULL); g_slist_free (parse->priv->buffers_pending); parse->priv->buffers_pending = NULL; + g_slist_foreach (parse->priv->buffers_send, (GFunc) gst_buffer_unref, NULL); + g_slist_free (parse->priv->buffers_send); + parse->priv->buffers_send = NULL; } static void @@ -502,6 +516,49 @@ gst_base_parse_init (GstBaseParse * parse, GstBaseParseClass * bclass) GST_DEBUG_OBJECT (parse, "init ok"); } +/** + * gst_base_parse_frame_init: + * @parse: #GstBaseParse. + * @fmt: #GstBaseParseFrame. + * + * Sets a #GstBaseParseFrame to initial state. Currently this means + * all fields are zero-ed. + */ +void +gst_base_parse_frame_init (GstBaseParse * parse, GstBaseParseFrame * frame) +{ + memset (frame, 0, sizeof (*frame)); +} + +/* clear == frame no longer to be used following this */ +static void +gst_base_parse_frame_clear (GstBaseParse * parse, GstBaseParseFrame * frame) +{ + /* limited for now */ + if (frame->buffer) { + gst_buffer_unref (frame->buffer); + frame->buffer = NULL; + } +} + +static inline void +gst_base_parse_frame_update (GstBaseParse * parse, GstBaseParseFrame * frame, + GstBuffer * buf) +{ + gst_buffer_replace (&frame->buffer, buf); + if (parse->priv->drain) { + frame->flags |= GST_BASE_PARSE_FRAME_FLAG_DRAIN; + } else { + frame->flags &= ~(GST_BASE_PARSE_FRAME_FLAG_DRAIN); + } + /* losing sync is pretty much a discont (and vice versa), no ? */ + if (!parse->priv->discont) { + frame->flags |= GST_BASE_PARSE_FRAME_FLAG_SYNC; + } else { + frame->flags &= ~(GST_BASE_PARSE_FRAME_FLAG_SYNC); + } +} + static void gst_base_parse_reset (GstBaseParse * parse) { @@ -513,7 +570,7 @@ gst_base_parse_reset (GstBaseParse * parse) parse->priv->flushing = FALSE; parse->priv->offset = 0; parse->priv->sync_offset = 0; - parse->priv->update_interval = 50; + parse->priv->update_interval = -1; parse->priv->fps_num = parse->priv->fps_den = 0; parse->priv->frame_duration = GST_CLOCK_TIME_NONE; parse->priv->lead_in = parse->priv->lead_out = 0; @@ -527,7 +584,7 @@ gst_base_parse_reset (GstBaseParse * parse) parse->priv->first_frame_offset = -1; parse->priv->estimated_duration = -1; parse->priv->next_ts = 0; - parse->priv->passthrough = FALSE; + parse->priv->format = 0; parse->priv->post_min_bitrate = TRUE; parse->priv->post_avg_bitrate = TRUE; parse->priv->post_max_bitrate = TRUE; @@ -536,8 +593,8 @@ gst_base_parse_reset (GstBaseParse * parse) parse->priv->avg_bitrate = 0; parse->priv->posted_avg_bitrate = 0; - parse->priv->index_last_ts = 0; - parse->priv->index_last_offset = 0; + parse->priv->index_last_ts = GST_CLOCK_TIME_NONE; + parse->priv->index_last_offset = -1; parse->priv->index_last_valid = TRUE; parse->priv->upstream_seekable = FALSE; parse->priv->upstream_size = 0; @@ -585,9 +642,9 @@ gst_base_parse_reset (GstBaseParse * parse) */ static gboolean gst_base_parse_check_frame (GstBaseParse * parse, - GstBuffer * buffer, guint * framesize, gint * skipsize) + GstBaseParseFrame * frame, guint * framesize, gint * skipsize) { - *framesize = GST_BUFFER_SIZE (buffer); + *framesize = GST_BUFFER_SIZE (frame->buffer); *skipsize = 0; return TRUE; } @@ -601,8 +658,10 @@ gst_base_parse_check_frame (GstBaseParse * parse, * Default callback for parse_frame. */ static GstFlowReturn -gst_base_parse_parse_frame (GstBaseParse * parse, GstBuffer * buffer) +gst_base_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame) { + GstBuffer *buffer = frame->buffer; + if (!GST_BUFFER_TIMESTAMP_IS_VALID (buffer) && GST_CLOCK_TIME_IS_VALID (parse->priv->next_ts)) { GST_BUFFER_TIMESTAMP (buffer) = parse->priv->next_ts; @@ -736,7 +795,10 @@ gst_base_parse_sink_event (GstPad * pad, GstEvent * event) * * Element-level event handler function. * - * Returns: TRUE if the event was handled and not need forwarding. + * The event will be unreffed only if it has been handled and this + * function returns %TRUE + * + * Returns: %TRUE if the event was handled and not need forwarding. */ static gboolean gst_base_parse_sink_eventfunc (GstBaseParse * parse, GstEvent * event) @@ -856,7 +918,9 @@ gst_base_parse_sink_eventfunc (GstBaseParse * parse, GstEvent * event) case GST_EVENT_FLUSH_START: parse->priv->flushing = TRUE; - handled = gst_pad_push_event (parse->srcpad, event); + handled = gst_pad_push_event (parse->srcpad, gst_event_ref (event)); + if (handled) + gst_event_unref (event); /* Wait for _chain() to exit by taking the srcpad STREAM_LOCK */ GST_PAD_STREAM_LOCK (parse->srcpad); GST_PAD_STREAM_UNLOCK (parse->srcpad); @@ -925,8 +989,6 @@ gst_base_parse_src_event (GstPad * pad, GstEvent * event) if (!handled) ret = gst_pad_event_default (pad, event); - else - gst_event_unref (event); gst_object_unref (parse); return ret; @@ -1065,8 +1127,12 @@ gst_base_parse_update_duration (GstBaseParse * aacparse) gst_object_unref (GST_OBJECT (peer)); if (qres) { if (gst_base_parse_convert (parse, pformat, ptot, - GST_FORMAT_TIME, &dest_value)) + GST_FORMAT_TIME, &dest_value)) { parse->priv->estimated_duration = dest_value; + GST_LOG_OBJECT (parse, + "updated estimated duration to %" GST_TIME_FORMAT, + GST_TIME_ARGS (dest_value)); + } } } } @@ -1107,23 +1173,22 @@ gst_base_parse_post_bitrates (GstBaseParse * parse, gboolean post_min, * running average bitrate of the stream so far. */ static void -gst_base_parse_update_bitrates (GstBaseParse * parse, GstBuffer * buffer) +gst_base_parse_update_bitrates (GstBaseParse * parse, GstBaseParseFrame * frame) { /* Only update the tag on a 10 kbps delta */ static const gint update_threshold = 10000; GstBaseParseClass *klass; guint64 data_len, frame_dur; - gint overhead = 0, frame_bitrate, old_avg_bitrate; + gint overhead, frame_bitrate, old_avg_bitrate; gboolean update_min = FALSE, update_avg = FALSE, update_max = FALSE; + GstBuffer *buffer = frame->buffer; klass = GST_BASE_PARSE_GET_CLASS (parse); - if (klass->get_frame_overhead) { - overhead = klass->get_frame_overhead (parse, buffer); - if (overhead == -1) - return; - } + overhead = frame->overhead; + if (overhead == -1) + return; data_len = GST_BUFFER_SIZE (buffer) - overhead; parse->priv->data_bytecount += data_len; @@ -1149,7 +1214,10 @@ gst_base_parse_update_bitrates (GstBaseParse * parse, GstBuffer * buffer) gst_base_parse_post_bitrates (parse, FALSE, TRUE, FALSE); } - frame_bitrate = (8 * data_len * GST_SECOND) / frame_dur; + if (frame_dur) + frame_bitrate = (8 * data_len * GST_SECOND) / frame_dur; + else + return; GST_LOG_OBJECT (parse, "frame bitrate %u, avg bitrate %u", frame_bitrate, parse->priv->avg_bitrate); @@ -1226,13 +1294,14 @@ gst_base_parse_add_index_entry (GstBaseParse * parse, guint64 offset, /* FIXME need better helper data structure that handles these issues * related to ongoing collecting of index entries */ - if (parse->priv->index_last_offset >= offset) { + if (parse->priv->index_last_offset >= (gint64) offset) { GST_DEBUG_OBJECT (parse, "already have entries up to offset " "0x%08" G_GINT64_MODIFIER "x", parse->priv->index_last_offset); goto exit; } - if (GST_CLOCK_DIFF (parse->priv->index_last_ts, ts) < + if (GST_CLOCK_TIME_IS_VALID (parse->priv->index_last_ts) && + GST_CLOCK_DIFF (parse->priv->index_last_ts, ts) < parse->priv->idx_interval) { GST_DEBUG_OBJECT (parse, "entry too close to last time %" GST_TIME_FORMAT, GST_TIME_ARGS (parse->priv->index_last_ts)); @@ -1384,11 +1453,16 @@ gst_base_parse_check_media (GstBaseParse * parse) * Returns: #GstFlowReturn */ static GstFlowReturn -gst_base_parse_handle_and_push_buffer (GstBaseParse * parse, - GstBaseParseClass * klass, GstBuffer * buffer) +gst_base_parse_handle_and_push_frame (GstBaseParse * parse, + GstBaseParseClass * klass, GstBaseParseFrame * frame) { GstFlowReturn ret; gint64 offset; + GstBuffer *buffer; + + g_return_val_if_fail (frame != NULL, GST_FLOW_ERROR); + + buffer = frame->buffer; if (parse->priv->discont) { GST_DEBUG_OBJECT (parse, "marking DISCONT"); @@ -1408,14 +1482,23 @@ gst_base_parse_handle_and_push_buffer (GstBaseParse * parse, GST_BUFFER_OFFSET (buffer), GST_BUFFER_OFFSET (buffer), GST_BUFFER_SIZE (buffer)); + /* use default handler to provide initial (upstream) metadata */ + gst_base_parse_parse_frame (parse, frame); + /* store offset as it might get overwritten */ offset = GST_BUFFER_OFFSET (buffer); - ret = klass->parse_frame (parse, buffer); + ret = klass->parse_frame (parse, frame); + /* sync */ + buffer = frame->buffer; + /* subclass must play nice */ + g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR); - /* check initial frame to determine if subclass/format can provide ts. + /* check if subclass/format can provide ts. * If so, that allows and enables extra seek and duration determining options */ if (G_UNLIKELY (parse->priv->first_frame_offset < 0 && ret == GST_FLOW_OK)) { - if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer)) { + if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) && + GST_BASE_PARSE_HAS_TIME (parse) && + parse->priv->pad_mode == GST_ACTIVATE_PULL) { parse->priv->first_frame_offset = offset; parse->priv->first_frame_ts = GST_BUFFER_TIMESTAMP (buffer); GST_DEBUG_OBJECT (parse, "subclass provided ts %" GST_TIME_FORMAT @@ -1437,8 +1520,9 @@ gst_base_parse_handle_and_push_buffer (GstBaseParse * parse, } } - /* re-use default handler to add missing metadata as-much-as-possible */ - gst_base_parse_parse_frame (parse, buffer); + /* again use default handler to add missing metadata; + * we may have new information on frame properties */ + gst_base_parse_parse_frame (parse, frame); if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) && GST_BUFFER_DURATION_IS_VALID (buffer)) { parse->priv->next_ts = @@ -1460,34 +1544,40 @@ gst_base_parse_handle_and_push_buffer (GstBaseParse * parse, * frames to decide on the format and queues them internally */ /* convert internal flow to OK and mark discont for the next buffer. */ if (ret == GST_BASE_PARSE_FLOW_DROPPED) { - gst_buffer_unref (buffer); + gst_base_parse_frame_clear (parse, frame); return GST_FLOW_OK; } else if (ret != GST_FLOW_OK) { return ret; } - return gst_base_parse_push_buffer (parse, buffer); + return gst_base_parse_push_frame (parse, frame); } /** - * gst_base_parse_push_buffer: + * gst_base_parse_push_frame: * @parse: #GstBaseParse. - * @buffer: #GstBuffer. + * @frame: #GstBaseParseFrame. * - * Pushes the buffer downstream, sends any pending events and + * Pushes the frame downstream, sends any pending events and * does some timestamp and segment handling. * - * This must be called with srcpad STREAM_LOCK held. + * This must be called with sinkpad STREAM_LOCK held. * * Returns: #GstFlowReturn */ GstFlowReturn -gst_base_parse_push_buffer (GstBaseParse * parse, GstBuffer * buffer) +gst_base_parse_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame) { GstFlowReturn ret = GST_FLOW_OK; GstClockTime last_start = GST_CLOCK_TIME_NONE; GstClockTime last_stop = GST_CLOCK_TIME_NONE; GstBaseParseClass *klass = GST_BASE_PARSE_GET_CLASS (parse); + GstBuffer *buffer; + + g_return_val_if_fail (frame != NULL, GST_FLOW_ERROR); + g_return_val_if_fail (frame->buffer != NULL, GST_FLOW_ERROR); + + buffer = frame->buffer; GST_LOG_OBJECT (parse, "processing buffer of size %d with ts %" GST_TIME_FORMAT @@ -1497,14 +1587,16 @@ gst_base_parse_push_buffer (GstBaseParse * parse, GstBuffer * buffer) /* update stats */ parse->priv->bytecount += GST_BUFFER_SIZE (buffer); - if (!GST_BUFFER_FLAG_IS_SET (buffer, GST_BASE_PARSE_BUFFER_FLAG_NO_FRAME)) { + if (G_LIKELY (!(frame->flags & GST_BASE_PARSE_FRAME_FLAG_NO_FRAME))) { parse->priv->framecount++; if (GST_BUFFER_DURATION_IS_VALID (buffer)) { parse->priv->acc_duration += GST_BUFFER_DURATION (buffer); } } - GST_BUFFER_FLAG_UNSET (buffer, GST_BASE_PARSE_BUFFER_FLAG_NO_FRAME); - if (parse->priv->update_interval && + /* 0 means disabled */ + if (parse->priv->update_interval < 0) + parse->priv->update_interval = 50; + else if (parse->priv->update_interval > 0 && (parse->priv->framecount % parse->priv->update_interval) == 0) gst_base_parse_update_duration (parse); @@ -1517,10 +1609,8 @@ gst_base_parse_push_buffer (GstBaseParse * parse, GstBuffer * buffer) /* should have caps by now */ g_return_val_if_fail (GST_PAD_CAPS (parse->srcpad), GST_FLOW_ERROR); - gst_buffer_set_caps (buffer, GST_PAD_CAPS (parse->srcpad)); - /* segment adjustment magic; only if we are running the whole show */ - if (!parse->priv->passthrough && parse->segment.rate > 0.0 && + if (!GST_BASE_PARSE_PASSTHROUGH (parse) && parse->segment.rate > 0.0 && (parse->priv->pad_mode == GST_ACTIVATE_PULL || parse->priv->upstream_seekable)) { /* segment times are typically estimates, @@ -1607,7 +1697,7 @@ gst_base_parse_push_buffer (GstBaseParse * parse, GstBuffer * buffer) /* update bitrates and optionally post corresponding tags * (following newsegment) */ - gst_base_parse_update_bitrates (parse, buffer); + gst_base_parse_update_bitrates (parse, frame); if (G_UNLIKELY (parse->priv->pending_events)) { GList *l; @@ -1619,15 +1709,26 @@ gst_base_parse_push_buffer (GstBaseParse * parse, GstBuffer * buffer) parse->priv->pending_events = NULL; } - if (klass->pre_push_buffer) - ret = klass->pre_push_buffer (parse, buffer); - else - ret = GST_BASE_PARSE_FLOW_CLIP; + if (klass->pre_push_frame) { + ret = klass->pre_push_frame (parse, frame); + } else { + frame->flags |= GST_BASE_PARSE_FRAME_FLAG_CLIP; + } + + /* take final ownership of frame buffer */ + buffer = frame->buffer; + frame->buffer = NULL; + + /* subclass must play nice */ + g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR); + + /* decorate */ + gst_buffer_set_caps (buffer, GST_PAD_CAPS (parse->srcpad)); parse->priv->seen_keyframe |= parse->priv->is_video && !GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT); - if (ret == GST_BASE_PARSE_FLOW_CLIP) { + if (frame->flags & GST_BASE_PARSE_FRAME_FLAG_CLIP) { if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) && GST_CLOCK_TIME_IS_VALID (parse->segment.stop) && GST_BUFFER_TIMESTAMP (buffer) > @@ -1674,7 +1775,7 @@ gst_base_parse_push_buffer (GstBaseParse * parse, GstBuffer * buffer) GST_BUFFER_SIZE (buffer), gst_flow_get_name (ret)); /* if we are not sufficiently in control, let upstream decide on EOS */ if (ret == GST_FLOW_UNEXPECTED && - (parse->priv->passthrough || + (GST_BASE_PARSE_PASSTHROUGH (parse) || (parse->priv->pad_mode == GST_ACTIVATE_PUSH && !parse->priv->upstream_seekable))) ret = GST_FLOW_OK; @@ -1685,6 +1786,8 @@ gst_base_parse_push_buffer (GstBaseParse * parse, GstBuffer * buffer) parse->segment.last_stop < last_stop) gst_segment_set_last_stop (&parse->segment, GST_FORMAT_TIME, last_stop); + gst_base_parse_frame_clear (parse, frame); + return ret; } @@ -1724,6 +1827,50 @@ gst_base_parse_drain (GstBaseParse * parse) parse->priv->drain = FALSE; } +/** + * gst_base_parse_process_fragment: + * @parse: #GstBaseParse. + * + * Sends buffers collected in send_buffers downstream, and ensures that list + * is empty at the end (errors or not). + */ +static GstFlowReturn +gst_base_parse_send_buffers (GstBaseParse * parse) +{ + GSList *send = NULL; + GstBuffer *buf; + GstFlowReturn ret = GST_FLOW_OK; + + send = parse->priv->buffers_send; + + /* send buffers */ + while (send) { + buf = GST_BUFFER_CAST (send->data); + GST_LOG_OBJECT (parse, "pushing buffer %p, timestamp %" + GST_TIME_FORMAT ", duration %" GST_TIME_FORMAT + ", offset %" G_GINT64_FORMAT, buf, + GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)), + GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_BUFFER_OFFSET (buf)); + + /* iterate output queue an push downstream */ + ret = gst_pad_push (parse->srcpad, buf); + send = g_slist_delete_link (send, send); + + /* clear any leftover if error */ + if (G_UNLIKELY (ret != GST_FLOW_OK)) { + while (send) { + buf = GST_BUFFER_CAST (send->data); + gst_buffer_unref (buf); + send = g_slist_delete_link (send, send); + } + } + } + + parse->priv->buffers_send = send; + + return ret; +} + /** * gst_base_parse_process_fragment: * @parse: #GstBaseParse. @@ -1739,7 +1886,7 @@ gst_base_parse_process_fragment (GstBaseParse * parse, gboolean push_only) { GstBuffer *buf; GstFlowReturn ret = GST_FLOW_OK; - GSList *send = NULL; + gboolean seen_key = FALSE, seen_delta = FALSE; if (push_only) goto push; @@ -1769,6 +1916,11 @@ gst_base_parse_process_fragment (GstBaseParse * parse, gboolean push_only) gst_base_parse_drain (parse); push: + if (parse->priv->buffers_send) { + buf = GST_BUFFER_CAST (parse->priv->buffers_send->data); + seen_key |= !GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT); + } + /* add metadata (if needed to queued buffers */ GST_LOG_OBJECT (parse, "last timestamp: %" GST_TIME_FORMAT, GST_TIME_ARGS (parse->priv->last_ts)); @@ -1793,38 +1945,39 @@ push: GST_WARNING_OBJECT (parse, "could not determine time for buffer"); } + parse->priv->last_ts = GST_BUFFER_TIMESTAMP (buf); + /* reverse order for ascending sending */ - send = g_slist_prepend (send, buf); + /* send downstream at keyframe not preceded by a keyframe + * (e.g. that should identify start of collection of IDR nals) */ + if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT)) { + if (seen_key) { + ret = gst_base_parse_send_buffers (parse); + /* if a problem, throw all to sending */ + if (ret != GST_FLOW_OK) { + parse->priv->buffers_send = + g_slist_reverse (parse->priv->buffers_queued); + parse->priv->buffers_queued = NULL; + break; + } + seen_key = FALSE; + } + } else { + seen_delta = TRUE; + } + + seen_key |= !GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT); + + parse->priv->buffers_send = + g_slist_prepend (parse->priv->buffers_send, buf); parse->priv->buffers_queued = g_slist_delete_link (parse->priv->buffers_queued, parse->priv->buffers_queued); } - /* send buffers */ - while (send) { - buf = GST_BUFFER_CAST (send->data); - GST_LOG_OBJECT (parse, "pushing buffer %p, timestamp %" - GST_TIME_FORMAT ", duration %" GST_TIME_FORMAT - ", offset %" G_GINT64_FORMAT, buf, - GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)), - GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_BUFFER_OFFSET (buf)); - - if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (parse->priv->last_ts))) - parse->priv->last_ts = GST_BUFFER_TIMESTAMP (buf); - - /* iterate output queue an push downstream */ - ret = gst_pad_push (parse->srcpad, buf); - send = g_slist_delete_link (send, send); - - /* clear any leftover if error */ - if (G_UNLIKELY (ret != GST_FLOW_OK)) { - while (send) { - buf = GST_BUFFER_CAST (send->data); - gst_buffer_unref (buf); - send = g_slist_delete_link (send, send); - } - } - } + /* audio may have all marked as keyframe, so arrange to send here */ + if (!seen_delta) + ret = gst_base_parse_send_buffers (parse); /* any trailing unused no longer usable (ideally none) */ if (G_UNLIKELY (gst_adapter_available (parse->adapter))) { @@ -1866,21 +2019,24 @@ gst_base_parse_chain (GstPad * pad, GstBuffer * buffer) GstFlowReturn ret = GST_FLOW_OK; GstBuffer *outbuf = NULL; GstBuffer *tmpbuf = NULL; - guint fsize = 0; + guint fsize = 1; gint skip = -1; const guint8 *data; - guint min_size; + guint old_min_size = 0, min_size, av; GstClockTime timestamp; + GstBaseParseFrame _frame = { 0, }; + GstBaseParseFrame *frame; parse = GST_BASE_PARSE (GST_OBJECT_PARENT (pad)); bclass = GST_BASE_PARSE_GET_CLASS (parse); + frame = &_frame; if (G_LIKELY (buffer)) { GST_LOG_OBJECT (parse, "buffer size: %d, offset = %" G_GINT64_FORMAT, GST_BUFFER_SIZE (buffer), GST_BUFFER_OFFSET (buffer)); - if (G_UNLIKELY (parse->priv->passthrough)) { - buffer = gst_buffer_make_metadata_writable (buffer); - return gst_base_parse_push_buffer (parse, buffer); + if (G_UNLIKELY (GST_BASE_PARSE_PASSTHROUGH (parse))) { + frame->buffer = gst_buffer_make_metadata_writable (buffer); + return gst_base_parse_push_frame (parse, frame); } /* upstream feeding us in reverse playback; * gather each fragment, then process it in single run */ @@ -1898,14 +2054,23 @@ gst_base_parse_chain (GstPad * pad, GstBuffer * buffer) /* Parse and push as many frames as possible */ /* Stop either when adapter is empty or we are flushing */ while (!parse->priv->flushing) { + gboolean res; + tmpbuf = gst_buffer_new (); + old_min_size = 0; /* Synchronization loop */ for (;;) { - min_size = parse->priv->min_frame_size; + min_size = MAX (parse->priv->min_frame_size, fsize); + av = gst_adapter_available (parse->adapter); + + /* loop safety check */ + if (G_UNLIKELY (old_min_size >= min_size)) + goto invalid_min; + old_min_size = min_size; if (G_UNLIKELY (parse->priv->drain)) { - min_size = gst_adapter_available (parse->adapter); + min_size = av; GST_DEBUG_OBJECT (parse, "draining, data left: %d", min_size); if (G_UNLIKELY (!min_size)) { gst_buffer_unref (tmpbuf); @@ -1914,14 +2079,15 @@ gst_base_parse_chain (GstPad * pad, GstBuffer * buffer) } /* Collect at least min_frame_size bytes */ - if (gst_adapter_available (parse->adapter) < min_size) { + if (av < min_size) { GST_DEBUG_OBJECT (parse, "not enough data available (only %d bytes)", - gst_adapter_available (parse->adapter)); + av); gst_buffer_unref (tmpbuf); goto done; } - data = gst_adapter_peek (parse->adapter, min_size); + /* always pass all available data */ + data = gst_adapter_peek (parse->adapter, av); GST_BUFFER_DATA (tmpbuf) = (guint8 *) data; GST_BUFFER_SIZE (tmpbuf) = min_size; GST_BUFFER_OFFSET (tmpbuf) = parse->priv->offset; @@ -1933,7 +2099,10 @@ gst_base_parse_chain (GstPad * pad, GstBuffer * buffer) } skip = -1; - if (bclass->check_valid_frame (parse, tmpbuf, &fsize, &skip)) { + gst_base_parse_frame_update (parse, frame, tmpbuf); + res = bclass->check_valid_frame (parse, frame, &fsize, &skip); + gst_buffer_replace (&frame->buffer, NULL); + if (res) { if (gst_adapter_available (parse->adapter) < fsize) { GST_DEBUG_OBJECT (parse, "found valid frame but not enough data available (only %d bytes)", @@ -1941,6 +2110,7 @@ gst_base_parse_chain (GstPad * pad, GstBuffer * buffer) gst_buffer_unref (tmpbuf); goto done; } + GST_LOG_OBJECT (parse, "valid frame of size %d at pos %d", fsize, skip); break; } if (skip == -1) { @@ -1967,10 +2137,11 @@ gst_base_parse_chain (GstPad * pad, GstBuffer * buffer) if (!parse->priv->discont) parse->priv->sync_offset = parse->priv->offset; parse->priv->discont = TRUE; + /* something changed least; nullify loop check */ + old_min_size = 0; } - /* There is a possibility that subclass set the skip value to zero. - This means that it has probably found a frame but wants to ask - more data (by increasing the min_size) to be sure of this. */ + /* skip == 0 should imply subclass set min_size to need more data; + * we check this shortly */ if ((ret = gst_base_parse_check_sync (parse)) != GST_FLOW_OK) { gst_buffer_unref (tmpbuf); goto done; @@ -1996,15 +2167,6 @@ gst_base_parse_chain (GstPad * pad, GstBuffer * buffer) break; } - /* FIXME: Would it be more efficient to make a subbuffer instead? */ - outbuf = gst_adapter_take_buffer (parse->adapter, fsize); - outbuf = gst_buffer_make_metadata_writable (outbuf); - - /* Subclass may want to know the data offset */ - GST_BUFFER_OFFSET (outbuf) = parse->priv->offset; - parse->priv->offset += fsize; - GST_BUFFER_TIMESTAMP (outbuf) = GST_CLOCK_TIME_NONE; - /* move along with upstream timestamp (if any), * but interpolate in between */ timestamp = gst_adapter_prev_timestamp (parse->adapter, NULL); @@ -2013,7 +2175,18 @@ gst_base_parse_chain (GstPad * pad, GstBuffer * buffer) parse->priv->prev_ts = parse->priv->next_ts = timestamp; } - ret = gst_base_parse_handle_and_push_buffer (parse, bclass, outbuf); + /* FIXME: Would it be more efficient to make a subbuffer instead? */ + outbuf = gst_adapter_take_buffer (parse->adapter, fsize); + outbuf = gst_buffer_make_metadata_writable (outbuf); + + /* Subclass may want to know the data offset */ + GST_BUFFER_OFFSET (outbuf) = parse->priv->offset; + parse->priv->offset += fsize; + GST_BUFFER_TIMESTAMP (outbuf) = GST_CLOCK_TIME_NONE; + GST_BUFFER_DURATION (outbuf) = GST_CLOCK_TIME_NONE; + + frame->buffer = outbuf; + ret = gst_base_parse_handle_and_push_frame (parse, bclass, frame); GST_PAD_STREAM_UNLOCK (parse->srcpad); if (ret != GST_FLOW_OK) { @@ -2025,6 +2198,15 @@ gst_base_parse_chain (GstPad * pad, GstBuffer * buffer) done: GST_LOG_OBJECT (parse, "chain leaving"); return ret; + + /* ERRORS */ +invalid_min: + { + GST_ELEMENT_ERROR (parse, STREAM, FAILED, (NULL), + ("min_size evolution %d -> %d; breaking to avoid looping", + old_min_size, min_size)); + return GST_FLOW_ERROR; + } } /* pull @size bytes at current offset, @@ -2168,18 +2350,26 @@ exit: * ajusts sync, drain and offset going along */ static GstFlowReturn gst_base_parse_scan_frame (GstBaseParse * parse, GstBaseParseClass * klass, - GstBuffer ** buf, gboolean full) + GstBaseParseFrame * frame, gboolean full) { GstBuffer *buffer, *outbuf; GstFlowReturn ret = GST_FLOW_OK; - guint fsize = 0, min_size; + guint fsize = 1, min_size, old_min_size = 0; gint skip = 0; - g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR); + g_return_val_if_fail (frame != NULL, GST_FLOW_ERROR); + + GST_LOG_OBJECT (parse, "scanning for frame at offset %" G_GUINT64_FORMAT + " (%#" G_GINT64_MODIFIER "x)", parse->priv->offset, parse->priv->offset); while (TRUE) { + gboolean res; - min_size = parse->priv->min_frame_size; + min_size = MAX (parse->priv->min_frame_size, fsize); + /* loop safety check */ + if (G_UNLIKELY (old_min_size >= min_size)) + goto invalid_min; + old_min_size = min_size; ret = gst_base_parse_pull_range (parse, min_size, &buffer); if (ret != GST_FLOW_OK) @@ -2196,8 +2386,12 @@ gst_base_parse_scan_frame (GstBaseParse * parse, GstBaseParseClass * klass, parse->priv->drain = TRUE; skip = -1; - if (klass->check_valid_frame (parse, buffer, &fsize, &skip)) { + gst_base_parse_frame_update (parse, frame, buffer); + res = klass->check_valid_frame (parse, frame, &fsize, &skip); + gst_buffer_replace (&frame->buffer, NULL); + if (res) { parse->priv->drain = FALSE; + GST_LOG_OBJECT (parse, "valid frame of size %d at pos %d", fsize, skip); break; } parse->priv->drain = FALSE; @@ -2218,8 +2412,11 @@ gst_base_parse_scan_frame (GstBaseParse * parse, GstBaseParseClass * klass, if (!parse->priv->discont) parse->priv->sync_offset = parse->priv->offset; parse->priv->discont = TRUE; + /* something changed least; nullify loop check */ + old_min_size = 0; } - /* skip == 0 should imply subclass set min_size to need more data ... */ + /* skip == 0 should imply subclass set min_size to need more data; + * we check this shortly */ GST_DEBUG_OBJECT (parse, "finding sync..."); gst_buffer_unref (buffer); if ((ret = gst_base_parse_check_sync (parse)) != GST_FLOW_OK) { @@ -2227,9 +2424,15 @@ gst_base_parse_scan_frame (GstBaseParse * parse, GstBaseParseClass * klass, } } - if (fsize <= GST_BUFFER_SIZE (buffer)) { - outbuf = gst_buffer_create_sub (buffer, 0, fsize); - GST_BUFFER_OFFSET (outbuf) = GST_BUFFER_OFFSET (buffer); + /* Does the subclass want to skip too? */ + if (skip > 0) + parse->priv->offset += skip; + else if (skip < 0) + skip = 0; + + if (fsize + skip <= GST_BUFFER_SIZE (buffer)) { + outbuf = gst_buffer_create_sub (buffer, skip, fsize); + GST_BUFFER_OFFSET (outbuf) = GST_BUFFER_OFFSET (buffer) + skip; GST_BUFFER_TIMESTAMP (outbuf) = GST_CLOCK_TIME_NONE; gst_buffer_unref (buffer); } else { @@ -2245,14 +2448,19 @@ gst_base_parse_scan_frame (GstBaseParse * parse, GstBaseParseClass * klass, parse->priv->offset += fsize; - /* Does the subclass want to skip too? */ - if (skip > 0) - parse->priv->offset += skip; - - *buf = outbuf; + frame->buffer = outbuf; done: return ret; + + /* ERRORS */ +invalid_min: + { + GST_ELEMENT_ERROR (parse, STREAM, FAILED, (NULL), + ("min_size evolution %d -> %d; breaking to avoid looping", + old_min_size, min_size)); + return GST_FLOW_ERROR; + } } /** @@ -2266,8 +2474,8 @@ gst_base_parse_loop (GstPad * pad) { GstBaseParse *parse; GstBaseParseClass *klass; - GstBuffer *outbuf; GstFlowReturn ret = GST_FLOW_OK; + GstBaseParseFrame frame = { 0, }; parse = GST_BASE_PARSE (gst_pad_get_parent (pad)); klass = GST_BASE_PARSE_GET_CLASS (parse); @@ -2284,12 +2492,12 @@ gst_base_parse_loop (GstPad * pad) } } - ret = gst_base_parse_scan_frame (parse, klass, &outbuf, TRUE); + ret = gst_base_parse_scan_frame (parse, klass, &frame, TRUE); if (ret != GST_FLOW_OK) goto done; - /* This always unrefs the outbuf, even if error occurs */ - ret = gst_base_parse_handle_and_push_buffer (parse, klass, outbuf); + /* This always cleans up frame, even if error occurs */ + ret = gst_base_parse_handle_and_push_frame (parse, klass, &frame); /* eat expected eos signalling past segment in reverse playback */ if (parse->segment.rate < 0.0 && ret == GST_FLOW_UNEXPECTED && @@ -2412,7 +2620,7 @@ gst_base_parse_activate (GstBaseParse * parse, gboolean active) GstBaseParseClass *klass; gboolean result = FALSE; - GST_DEBUG_OBJECT (parse, "activate"); + GST_DEBUG_OBJECT (parse, "activate %d", active); klass = GST_BASE_PARSE_GET_CLASS (parse); @@ -2430,7 +2638,7 @@ gst_base_parse_activate (GstBaseParse * parse, gboolean active) parse->priv->pad_mode = GST_ACTIVATE_NONE; } - GST_DEBUG_OBJECT (parse, "activate: %d", result); + GST_DEBUG_OBJECT (parse, "activate return: %d", result); return result; } @@ -2450,14 +2658,14 @@ gst_base_parse_sink_activate_push (GstPad * pad, gboolean active) parse = GST_BASE_PARSE (gst_pad_get_parent (pad)); - GST_DEBUG_OBJECT (parse, "sink activate push"); + GST_DEBUG_OBJECT (parse, "sink activate push %d", active); result = gst_base_parse_activate (parse, active); if (result) parse->priv->pad_mode = active ? GST_ACTIVATE_PUSH : GST_ACTIVATE_NONE; - GST_DEBUG_OBJECT (parse, "sink activate push: %d", result); + GST_DEBUG_OBJECT (parse, "sink activate push return: %d", result); gst_object_unref (parse); return result; @@ -2479,7 +2687,7 @@ gst_base_parse_sink_activate_pull (GstPad * sinkpad, gboolean active) parse = GST_BASE_PARSE (gst_pad_get_parent (sinkpad)); - GST_DEBUG_OBJECT (parse, "activate pull"); + GST_DEBUG_OBJECT (parse, "activate pull %d", active); result = gst_base_parse_activate (parse, active); @@ -2498,7 +2706,7 @@ gst_base_parse_sink_activate_pull (GstPad * sinkpad, gboolean active) if (result) parse->priv->pad_mode = active ? GST_ACTIVATE_PULL : GST_ACTIVATE_NONE; - GST_DEBUG_OBJECT (parse, "sink activate pull: %d", result); + GST_DEBUG_OBJECT (parse, "sink activate pull return: %d", result); gst_object_unref (parse); return result; @@ -2592,24 +2800,28 @@ gst_base_parse_set_min_frame_size (GstBaseParse * parse, guint min_size) } /** - * gst_base_transform_set_passthrough: - * @trans: the #GstBaseParse to set - * @passthrough: boolean indicating passthrough mode. + * gst_base_parse_set_format: + * @parse: the #GstBaseParseFormat to set or unset + * @flags: format flag to enable or disable + * @on: whether or not to enable * - * Set passthrough mode for this parser. If operating in passthrough, - * incoming buffers are pushed through unmodified. + * Set flags describing characteristics of parsed format. */ void -gst_base_parse_set_passthrough (GstBaseParse * parse, gboolean passthrough) +gst_base_parse_set_format (GstBaseParse * parse, GstBaseParseFormat flag, + gboolean on) { g_return_if_fail (parse != NULL); - parse->priv->passthrough = passthrough; - GST_LOG_OBJECT (parse, "set passthrough: %d", passthrough); + GST_LOG_OBJECT (parse, "set flag %d to %d", flag, on); + if (on) + parse->priv->format |= flag; + else + parse->priv->format &= ~flag; } /** - * gst_base_transform_set_frame_props: + * gst_base_parse_set_frame_props: * @parse: the #GstBaseParse to set * @fps_num: frames per second (numerator). * @fps_den: frames per second (denominator). @@ -2646,6 +2858,12 @@ gst_base_parse_set_frame_props (GstBaseParse * parse, guint fps_num, gst_util_uint64_scale (GST_SECOND, fps_den * lead_in, fps_num); parse->priv->lead_out_ts = gst_util_uint64_scale (GST_SECOND, fps_den * lead_out, fps_num); + /* aim for about 1.5s to estimate duration */ + if (parse->priv->update_interval < 0) { + parse->priv->update_interval = fps_num * 3 / (fps_den * 2); + GST_LOG_OBJECT (parse, "estimated update interval to %d frames", + parse->priv->update_interval); + } } GST_LOG_OBJECT (parse, "set fps: %d/%d => duration: %" G_GINT64_FORMAT " ms", fps_num, fps_den, parse->priv->frame_duration / GST_MSECOND); @@ -2655,48 +2873,6 @@ gst_base_parse_set_frame_props (GstBaseParse * parse, guint fps_num, lead_out, parse->priv->lead_out_ts / GST_MSECOND); } -/** - * gst_base_transform_get_sync: - * @parse: the #GstBaseParse to query - * - * Returns: TRUE if parser is considered 'in sync'. That is, frames have been - * continuously successfully parsed and pushed. - */ -gboolean -gst_base_parse_get_sync (GstBaseParse * parse) -{ - gboolean ret; - - g_return_val_if_fail (parse != NULL, FALSE); - - /* losing sync is pretty much a discont (and vice versa), no ? */ - ret = !parse->priv->discont; - - GST_DEBUG_OBJECT (parse, "sync: %d", ret); - return ret; -} - -/** - * gst_base_transform_get_drain: - * @parse: the #GstBaseParse to query - * - * Returns: TRUE if parser is currently 'draining'. That is, leftover data - * (e.g. in FLUSH or EOS situation) is being parsed. - */ -gboolean -gst_base_parse_get_drain (GstBaseParse * parse) -{ - gboolean ret; - - g_return_val_if_fail (parse != NULL, FALSE); - - /* losing sync is pretty much a discont (and vice versa), no ? */ - ret = parse->priv->drain; - - GST_DEBUG_OBJECT (parse, "drain: %d", ret); - return ret; -} - static gboolean gst_base_parse_get_duration (GstBaseParse * parse, GstFormat format, GstClockTime * duration) @@ -2888,6 +3064,7 @@ gst_base_parse_find_frame (GstBaseParse * parse, gint64 * pos, gboolean orig_drain, orig_discont; GstFlowReturn ret = GST_FLOW_OK; GstBuffer *buf = NULL; + GstBaseParseFrame frame = { 0, }; g_return_val_if_fail (GST_FLOW_ERROR, pos != NULL); g_return_val_if_fail (GST_FLOW_ERROR, time != NULL); @@ -2908,10 +3085,11 @@ gst_base_parse_find_frame (GstBaseParse * parse, gint64 * pos, /* jump elsewhere and locate next frame */ parse->priv->offset = *pos; - ret = gst_base_parse_scan_frame (parse, klass, &buf, FALSE); + ret = gst_base_parse_scan_frame (parse, klass, &frame, FALSE); if (ret != GST_FLOW_OK) goto done; + buf = frame.buffer; GST_LOG_OBJECT (parse, "peek parsing frame at offset %" G_GUINT64_FORMAT " (%#" G_GINT64_MODIFIER "x) of size %d", @@ -2919,12 +3097,13 @@ gst_base_parse_find_frame (GstBaseParse * parse, gint64 * pos, /* get offset first, subclass parsing might dump other stuff in there */ *pos = GST_BUFFER_OFFSET (buf); - ret = klass->parse_frame (parse, buf); + ret = klass->parse_frame (parse, &frame); + buf = frame.buffer; /* but it should provide proper time */ *time = GST_BUFFER_TIMESTAMP (buf); *duration = GST_BUFFER_DURATION (buf); - gst_buffer_unref (buf); + gst_base_parse_frame_clear (parse, &frame); GST_LOG_OBJECT (parse, "frame with time %" GST_TIME_FORMAT " at offset %" G_GINT64_FORMAT, @@ -3017,6 +3196,7 @@ gst_base_parse_locate_time (GstBaseParse * parse, GstClockTime * _time, gst_util_uint64_scale (hpos - lpos, time - ltime, htime - ltime) + lpos - chunk; } else { + /* should mean lpos == hpos, since lpos <= hpos is invariant */ newpos = lpos; /* we check this case once, but not forever, so break loop */ cont = FALSE; @@ -3050,8 +3230,7 @@ gst_base_parse_locate_time (GstBaseParse * parse, GstClockTime * _time, break; } else if (newtime > time) { /* overshoot */ - newpos -= newpos == hpos ? chunk : 0; - hpos = CLAMP (newpos, lpos, hpos); + hpos = (newpos >= hpos) ? MAX (lpos, hpos - chunk) : MAX (lpos, newpos); htime = newtime; } else if (newtime + tolerance > time) { /* close enough undershoot */ @@ -3061,9 +3240,10 @@ gst_base_parse_locate_time (GstBaseParse * parse, GstClockTime * _time, } else if (newtime < ltime) { /* so a position beyond lpos resulted in earlier time than ltime ... */ GST_DEBUG_OBJECT (parse, "non-ascending time; aborting"); + break; } else { /* undershoot too far */ - newpos += newpos == hpos ? chunk : 0; + newpos += newpos == lpos ? chunk : 0; lpos = CLAMP (newpos, lpos, hpos); ltime = newtime; } @@ -3163,11 +3343,12 @@ gst_base_parse_handle_seek (GstBaseParse * parse, GstEvent * event) * it fails upstream */ if (format != GST_FORMAT_TIME) { /* default action delegates to upstream */ - return FALSE; + res = FALSE; + goto done; } else { gst_event_ref (event); - if (gst_pad_push_event (parse->sinkpad, event)) { - return TRUE; + if ((res = gst_pad_push_event (parse->sinkpad, event))) { + goto done; } } @@ -3329,6 +3510,9 @@ gst_base_parse_handle_seek (GstBaseParse * parse, GstEvent * event) (GstTaskFunction) gst_base_parse_loop, parse->sinkpad); GST_PAD_STREAM_UNLOCK (parse->sinkpad); + + /* handled seek */ + res = TRUE; } else { GstEvent *new_event; GstBaseParseSeek *seek; @@ -3369,12 +3553,15 @@ gst_base_parse_handle_seek (GstBaseParse * parse, GstEvent * event) } done: + /* handled event is ours to free */ + if (res) + gst_event_unref (event); return res; /* ERRORS */ negative_rate: { - GST_DEBUG_OBJECT (parse, "negative playback rates are not supported yet."); + GST_DEBUG_OBJECT (parse, "negative playback rates delegated upstream."); res = FALSE; goto done; } @@ -3444,7 +3631,7 @@ gst_base_parse_sink_setcaps (GstPad * pad, GstCaps * caps) if (klass->set_sink_caps) res = klass->set_sink_caps (parse, caps); - return res && gst_pad_set_caps (pad, caps); + return res; } static void diff --git a/gst/h263parse/gstbaseparse.h b/gst/h263parse/gstbaseparse.h index 605bf843a1..82ec5f6fb8 100644 --- a/gst/h263parse/gstbaseparse.h +++ b/gst/h263parse/gstbaseparse.h @@ -46,7 +46,7 @@ G_BEGIN_DECLS * * the name of the templates for the source pad */ -#define GST_BASE_PARSE_SRC_NAME "src" +#define GST_BASE_PARSE_SRC_NAME "src" /** * GST_BASE_PARSE_SRC_PAD: @@ -56,7 +56,7 @@ G_BEGIN_DECLS * * Since: 0.10.x */ -#define GST_BASE_PARSE_SRC_PAD(obj) (GST_BASE_PARSE_CAST (obj)->srcpad) +#define GST_BASE_PARSE_SRC_PAD(obj) (GST_BASE_PARSE_CAST (obj)->srcpad) /** * GST_BASE_PARSE_SINK_PAD: @@ -87,37 +87,113 @@ G_BEGIN_DECLS * * Since: 0.10.x */ -#define GST_BASE_PARSE_FLOW_DROPPED GST_FLOW_CUSTOM_SUCCESS +#define GST_BASE_PARSE_FLOW_DROPPED GST_FLOW_CUSTOM_SUCCESS /** - * GST_BASE_PARSE_FLOW_CLIP: + * GstBaseParseFrameFlags: + * @GST_BASE_PARSE_FRAME_FLAG_NONE: no flag + * @GST_BASE_PARSE_FRAME_FLAG_SYNC: indicates if parsing is 'in sync' + * @GST_BASE_PARSE_FRAME_FLAG_DRAIN: indicates if parser is 'draining'. + * That is, leftover data (e.g. in FLUSH or EOS situation) is being parsed. + * @GST_BASE_PARSE_FRAME_FLAG_NO_FRAME: set to indicate this buffer should not be + * counted as frame, e.g. if this frame is dependent on a previous one. + * As it is not counted as a frame, bitrate increases but frame to time + * conversions are maintained. + * @GST_BASE_PARSE_FRAME_FLAG_CLIP: @pre_push_buffer can set this to indicate + * that regular segment clipping can still be performed (as opposed to + * any custom one having been done). * - * A #GstFlowReturn that can be returned from pre_push_buffer to - * indicate that regular segment clipping should be performed. + * Flags to be used in a #GstBaseParseFrame. * * Since: 0.10.x */ -#define GST_BASE_PARSE_FLOW_CLIP GST_FLOW_CUSTOM_SUCCESS_1 +typedef enum { + GST_BASE_PARSE_FRAME_FLAG_NONE = 0, + GST_BASE_PARSE_FRAME_FLAG_SYNC = (1 << 0), + GST_BASE_PARSE_FRAME_FLAG_DRAIN = (1 << 1), + GST_BASE_PARSE_FRAME_FLAG_NO_FRAME = (1 << 2), + GST_BASE_PARSE_FRAME_FLAG_CLIP = (1 << 3) +} GstBaseParseFrameFlags; /** - * GST_BASE_PARSE_BUFFER_FLAG_NO_FRAME: + * GstBaseParseFrame: + * @buffer: data to check for valid frame or parsed frame. + * Subclass is allowed to replace this buffer. + * @overhead: subclass can set this to indicates the metadata overhead + * for the given frame, which is then used to enable more accurate bitrate + * computations. If this is -1, it is assumed that this frame should be + * skipped in bitrate calculation. + * @flags: a combination of input and output #GstBaseParseFrameFlags that + * convey additional context to subclass or allow subclass to tune + * subsequent #GstBaseParse actions. * - * A #GstBufferFlag that can be set to have this buffer not counted as frame, - * e.g. if this frame is dependent on a previous one. As it is not counted as - * a frame, bitrate increases but frame to time conversions are maintained. + * Frame (context) data passed to each frame parsing virtual methods. In + * addition to providing the data to be checked for a valid frame or an already + * identified frame, it conveys additional metadata or control information + * from and to the subclass w.r.t. the particular frame in question (rather + * than global parameters). Some of these may apply to each parsing stage, others + * only to some a particular one. These parameters are effectively zeroed at start + * of each frame's processing, i.e. parsing virtual method invocation sequence. * * Since: 0.10.x */ -#define GST_BASE_PARSE_BUFFER_FLAG_NO_FRAME GST_BUFFER_FLAG_LAST +typedef struct { + GstBuffer *buffer; + guint flags; + gint overhead; +} GstBaseParseFrame; +/** + * GST_BASE_PARSE_FRAME_SYNC: + * @frame: base parse frame instance + * + * Obtains current sync status indicated in frame. + * + * Since: 0.10.x + */ +#define GST_BASE_PARSE_FRAME_SYNC(frame) (!!(frame->flags & GST_BASE_PARSE_FRAME_FLAG_SYNC)) + +/** + * GST_BASE_PARSE_FRAME_DRAIN: + * @frame: base parse frame instance + * + * Obtains current drain status indicated in frame. + * + * Since: 0.10.x + */ +#define GST_BASE_PARSE_FRAME_DRAIN(frame) (!!(frame->flags & GST_BASE_PARSE_FRAME_FLAG_DRAIN)) + +/** + * GstBaseParseFormat: + * @GST_BASE_PARSE_FORMAT_NONE: default setting + * @GST_BASE_PARSE_FORMAT_PASSTHROUGH: nature of format or configuration + * does not allow (much) parsing, so parser should operate in passthrough mode + * (which only applies operating in pull mode). That is, incoming buffers + * are pushed through unmodified, i.e. no @check_valid_frame or @parse_frame + * callbacks will be invoked. On the other hand, @pre_push_buffer is still invoked, + * where subclass can perform as much or as little is appropriate for + * "passthrough" semantics. + * @GST_BASE_PARSE_FORMAT_HAS_TIME: frames carry timing info which subclass + * can (generally) parse and provide. In particular, intrinsic time + * (rather than estimated) can be obtained following seek. + * + * Since: 0.10.x + */ +typedef enum _GstBaseParseFormat { + GST_BASE_PARSE_FORMAT_NONE = 0, + GST_BASE_PARSE_FORMAT_PASSTHROUGH = (1 << 0), + GST_BASE_PARSE_FORMAT_HAS_TIME = (1 << 1), +} GstBaseParseFormat; /** * GstBaseParseSeekable: * @GST_BASE_PARSE_SEEK_NONE: No seeking possible. - * GST_BASE_PARSE_SEEK_DEFAULT: Default seeking possible using estimated bitrate. - * GST_BASE_PARSE_SEEK_TABLE: Additional metadata provides more accurate seeking. + * @GST_BASE_PARSE_SEEK_DEFAULT: Default seeking possible using estimated bitrate. + * @GST_BASE_PARSE_SEEK_TABLE: Additional metadata provides more accurate seeking. * * Indicates what level (of quality) of seeking is possible. + * + * Since: 0.10.x */ typedef enum _GstBaseParseSeekable { GST_BASE_PARSE_SEEK_NONE, @@ -200,7 +276,7 @@ struct _GstBaseParse { * Called just prior to pushing a frame (after any pending * events have been sent) to give subclass a chance to perform * additional actions at this time (e.g. tag sending) or to - * decide whether this buffer should be dropped or no + * decide whether this buffer should be dropped or not * (e.g. custom segment clipping). * * Subclasses can override any of the available virtual methods or not, as @@ -221,12 +297,15 @@ struct _GstBaseParseClass { GstCaps *caps); gboolean (*check_valid_frame) (GstBaseParse *parse, - GstBuffer *buffer, + GstBaseParseFrame *frame, guint *framesize, gint *skipsize); GstFlowReturn (*parse_frame) (GstBaseParse *parse, - GstBuffer *buffer); + GstBaseParseFrame *frame); + + GstFlowReturn (*pre_push_frame) (GstBaseParse *parse, + GstBaseParseFrame *frame); gboolean (*convert) (GstBaseParse * parse, GstFormat src_format, @@ -234,56 +313,45 @@ struct _GstBaseParseClass { GstFormat dest_format, gint64 * dest_value); - gboolean (*find_frame) (GstBaseParse *parse, - GstFormat src_format, - gint64 src_value, - gint64 * dest_value); - gboolean (*event) (GstBaseParse *parse, GstEvent *event); gboolean (*src_event) (GstBaseParse *parse, GstEvent *event); - gint (*get_frame_overhead) (GstBaseParse *parse, - GstBuffer *buf); - - GstFlowReturn (*pre_push_buffer) (GstBaseParse *parse, - GstBuffer *buf); - /*< private >*/ - gpointer _gst_reserved[GST_PADDING_LARGE]; + gpointer _gst_reserved[GST_PADDING_LARGE]; }; GType gst_base_parse_get_type (void); +void gst_base_parse_frame_init (GstBaseParse * parse, + GstBaseParseFrame * frame); +GstFlowReturn gst_base_parse_push_frame (GstBaseParse *parse, + GstBaseParseFrame *frame); -GstFlowReturn gst_base_parse_push_buffer (GstBaseParse *parse, - GstBuffer *buffer); +void gst_base_parse_set_duration (GstBaseParse *parse, + GstFormat fmt, gint64 duration, + gint interval); +void gst_base_parse_set_seek (GstBaseParse * parse, + GstBaseParseSeekable seek, + guint bitrate); +void gst_base_parse_set_min_frame_size (GstBaseParse *parse, + guint min_size); +void gst_base_parse_set_format (GstBaseParse * parse, + GstBaseParseFormat flag, + gboolean on); +void gst_base_parse_set_frame_props (GstBaseParse * parse, + guint fps_num, guint fps_den, + guint lead_in, guint lead_out); -void gst_base_parse_set_duration (GstBaseParse *parse, - GstFormat fmt, gint64 duration, gint interval); +gboolean gst_base_parse_convert_default (GstBaseParse * parse, + GstFormat src_format, gint64 src_value, + GstFormat dest_format, gint64 * dest_value); -void gst_base_parse_set_seek (GstBaseParse * parse, - GstBaseParseSeekable seek, guint bitrate); - -void gst_base_parse_set_min_frame_size (GstBaseParse *parse, - guint min_size); -void gst_base_parse_set_passthrough (GstBaseParse * parse, gboolean passthrough); - -void gst_base_parse_set_frame_props (GstBaseParse * parse, guint fps_num, - guint fps_den, guint lead_in, guint lead_out); - -gboolean gst_base_parse_get_sync (GstBaseParse * parse); - -gboolean gst_base_parse_get_drain (GstBaseParse * parse); - -gboolean gst_base_parse_convert_default (GstBaseParse * parse, - GstFormat src_format, gint64 src_value, - GstFormat dest_format, gint64 * dest_value); - -gboolean gst_base_parse_add_index_entry (GstBaseParse * parse, guint64 offset, - GstClockTime ts, gboolean key, gboolean force); +gboolean gst_base_parse_add_index_entry (GstBaseParse * parse, + guint64 offset, GstClockTime ts, + gboolean key, gboolean force); G_END_DECLS diff --git a/gst/h263parse/gsth263parse.c b/gst/h263parse/gsth263parse.c index b17851aa7e..6e4b701b3e 100644 --- a/gst/h263parse/gsth263parse.c +++ b/gst/h263parse/gsth263parse.c @@ -56,9 +56,9 @@ static gboolean gst_h263_parse_stop (GstBaseParse * parse); static gboolean gst_h263_parse_sink_event (GstBaseParse * parse, GstEvent * event); static gboolean gst_h263_parse_check_valid_frame (GstBaseParse * parse, - GstBuffer * buffer, guint * framesize, gint * skipsize); + GstBaseParseFrame * frame, guint * framesize, gint * skipsize); static GstFlowReturn gst_h263_parse_parse_frame (GstBaseParse * parse, - GstBuffer * buffer); + GstBaseParseFrame * frame); static void gst_h263_parse_base_init (gpointer g_class) @@ -111,7 +111,6 @@ gst_h263_parse_start (GstBaseParse * parse) h263parse->state = PARSING; gst_base_parse_set_min_frame_size (parse, 512); - gst_base_parse_set_passthrough (parse, FALSE); return TRUE; } @@ -244,13 +243,15 @@ gst_h263_parse_set_src_caps (GstH263Parse * h263parse, H263Params * params) } static gboolean -gst_h263_parse_check_valid_frame (GstBaseParse * parse, GstBuffer * buffer, - guint * framesize, gint * skipsize) +gst_h263_parse_check_valid_frame (GstBaseParse * parse, + GstBaseParseFrame * frame, guint * framesize, gint * skipsize) { GstH263Parse *h263parse; + GstBuffer *buffer; guint psc_pos, next_psc_pos; h263parse = GST_H263_PARSE (parse); + buffer = frame->buffer; if (GST_BUFFER_SIZE (buffer) < 3) return FALSE; @@ -271,7 +272,7 @@ gst_h263_parse_check_valid_frame (GstBaseParse * parse, GstBuffer * buffer, next_psc_pos = find_psc (buffer, next_psc_pos); if (next_psc_pos == -1) { - if (gst_base_parse_get_drain (GST_BASE_PARSE (h263parse))) + if (GST_BASE_PARSE_FRAME_DRAIN (frame)) /* FLUSH/EOS, it's okay if we can't find the next frame */ next_psc_pos = GST_BUFFER_SIZE (buffer); else @@ -288,7 +289,8 @@ gst_h263_parse_check_valid_frame (GstBaseParse * parse, GstBuffer * buffer, res = gst_h263_parse_get_params (¶ms, buffer, FALSE, &h263parse->state); if (res != GST_FLOW_OK || h263parse->state != GOT_HEADER) { GST_WARNING ("Couldn't parse header - setting passthrough mode"); - gst_base_parse_set_passthrough (parse, TRUE); + gst_base_parse_set_format (parse, + GST_BASE_PARSE_FORMAT_PASSTHROUGH, TRUE); } else { /* Set srcpad caps since we now have sufficient information to do so */ gst_h263_parse_set_src_caps (h263parse, params); @@ -318,13 +320,15 @@ more: } static GstFlowReturn -gst_h263_parse_parse_frame (GstBaseParse * parse, GstBuffer * buffer) +gst_h263_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame) { GstH263Parse *h263parse; + GstBuffer *buffer; GstFlowReturn res; H263Params *params = NULL; h263parse = GST_H263_PARSE (parse); + buffer = frame->buffer; res = gst_h263_parse_get_params (¶ms, buffer, TRUE, &h263parse->state); if (res != GST_FLOW_OK) @@ -335,7 +339,7 @@ gst_h263_parse_parse_frame (GstBaseParse * parse, GstBuffer * buffer) * parse the header, which should not be possible. Either way, go into * passthrough mode and let downstream handle it if it can. */ GST_WARNING ("Couldn't parse header - setting passthrough mode"); - gst_base_parse_set_passthrough (parse, TRUE); + gst_base_parse_set_format (parse, GST_BASE_PARSE_FORMAT_PASSTHROUGH, TRUE); goto out; } From 0c5d139ba77f8c94c50fcae047cfd2e5079dacba Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Thu, 27 Jan 2011 18:16:14 +0100 Subject: [PATCH 367/448] h263parse: move to videoparsers and separate plugin registration --- configure.ac | 4 +- gst/{h263parse => videoparsers}/Makefile.am | 2 +- .../gstbaseparse.c | 4 +- .../gstbaseparse.h | 0 .../gsth263parse.c | 13 ------ .../gsth263parse.h | 0 gst/{h263parse => videoparsers}/h263parse.c | 0 gst/{h263parse => videoparsers}/h263parse.h | 0 gst/videoparsers/plugin.c | 42 +++++++++++++++++++ 9 files changed, 47 insertions(+), 18 deletions(-) rename gst/{h263parse => videoparsers}/Makefile.am (79%) rename gst/{h263parse => videoparsers}/gstbaseparse.c (99%) rename gst/{h263parse => videoparsers}/gstbaseparse.h (100%) rename gst/{h263parse => videoparsers}/gsth263parse.c (97%) rename gst/{h263parse => videoparsers}/gsth263parse.h (100%) rename gst/{h263parse => videoparsers}/h263parse.c (100%) rename gst/{h263parse => videoparsers}/h263parse.h (100%) create mode 100644 gst/videoparsers/plugin.c diff --git a/configure.ac b/configure.ac index e8ac029012..52038b00e5 100644 --- a/configure.ac +++ b/configure.ac @@ -308,7 +308,6 @@ AG_GST_CHECK_PLUGIN(freeze) AG_GST_CHECK_PLUGIN(frei0r) AG_GST_CHECK_PLUGIN(gaudieffects) AG_GST_CHECK_PLUGIN(geometrictransform) -AG_GST_CHECK_PLUGIN(h263parse) AG_GST_CHECK_PLUGIN(h264parse) AG_GST_CHECK_PLUGIN(hdvparse) AG_GST_CHECK_PLUGIN(id3tag) @@ -345,6 +344,7 @@ AG_GST_CHECK_PLUGIN(stereo) AG_GST_CHECK_PLUGIN(tta) AG_GST_CHECK_PLUGIN(videomaxrate) AG_GST_CHECK_PLUGIN(videomeasure) +AG_GST_CHECK_PLUGIN(videoparsers) AG_GST_CHECK_PLUGIN(videosignal) AG_GST_CHECK_PLUGIN(vmnc) AG_GST_CHECK_PLUGIN(y4m) @@ -1728,7 +1728,6 @@ gst/freeze/Makefile gst/frei0r/Makefile gst/gaudieffects/Makefile gst/geometrictransform/Makefile -gst/h263parse/Makefile gst/h264parse/Makefile gst/hdvparse/Makefile gst/id3tag/Makefile @@ -1766,6 +1765,7 @@ gst/stereo/Makefile gst/tta/Makefile gst/videomaxrate/Makefile gst/videomeasure/Makefile +gst/videoparsers/Makefile gst/videosignal/Makefile gst/vmnc/Makefile gst/y4m/Makefile diff --git a/gst/h263parse/Makefile.am b/gst/videoparsers/Makefile.am similarity index 79% rename from gst/h263parse/Makefile.am rename to gst/videoparsers/Makefile.am index eda4c3840a..072e001524 100644 --- a/gst/h263parse/Makefile.am +++ b/gst/videoparsers/Makefile.am @@ -1,6 +1,6 @@ plugin_LTLIBRARIES = libgsth263parse.la -libgsth263parse_la_SOURCES = h263parse.c gsth263parse.c gstbaseparse.c +libgsth263parse_la_SOURCES = plugin.c h263parse.c gsth263parse.c gstbaseparse.c libgsth263parse_la_CFLAGS = $(GST_CFLAGS) libgsth263parse_la_LIBADD = $(GST_BASE_LIBS) $(GST_LIBS) libgsth263parse_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) diff --git a/gst/h263parse/gstbaseparse.c b/gst/videoparsers/gstbaseparse.c similarity index 99% rename from gst/h263parse/gstbaseparse.c rename to gst/videoparsers/gstbaseparse.c index ccb11fb3d8..8aa3f14fe6 100644 --- a/gst/h263parse/gstbaseparse.c +++ b/gst/videoparsers/gstbaseparse.c @@ -329,7 +329,7 @@ gst_base_parse_get_type (void) }; base_parse_type = g_type_register_static (GST_TYPE_ELEMENT, - "GstH263BaseParseBad", &base_parse_info, G_TYPE_FLAG_ABSTRACT); + "GstBaseVideoParseBad", &base_parse_info, G_TYPE_FLAG_ABSTRACT); } return base_parse_type; } @@ -460,7 +460,7 @@ gst_base_parse_class_init (GstBaseParseClass * klass) klass->src_event = gst_base_parse_src_eventfunc; klass->convert = gst_base_parse_convert_default; - GST_DEBUG_CATEGORY_INIT (gst_base_parse_debug, "h263baseparse", 0, + GST_DEBUG_CATEGORY_INIT (gst_base_parse_debug, "basevideoparse", 0, "baseparse element"); } diff --git a/gst/h263parse/gstbaseparse.h b/gst/videoparsers/gstbaseparse.h similarity index 100% rename from gst/h263parse/gstbaseparse.h rename to gst/videoparsers/gstbaseparse.h diff --git a/gst/h263parse/gsth263parse.c b/gst/videoparsers/gsth263parse.c similarity index 97% rename from gst/h263parse/gsth263parse.c rename to gst/videoparsers/gsth263parse.c index 6e4b701b3e..b727f6212e 100644 --- a/gst/h263parse/gsth263parse.c +++ b/gst/videoparsers/gsth263parse.c @@ -357,16 +357,3 @@ out: g_free (params); return res; } - -static gboolean -plugin_init (GstPlugin * plugin) -{ - return gst_element_register (plugin, "h263parse", - GST_RANK_NONE, GST_TYPE_H263PARSE); -} - -GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, - GST_VERSION_MINOR, - "h263parse", - "Element for parsing raw h263 streams", - plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/gst/h263parse/gsth263parse.h b/gst/videoparsers/gsth263parse.h similarity index 100% rename from gst/h263parse/gsth263parse.h rename to gst/videoparsers/gsth263parse.h diff --git a/gst/h263parse/h263parse.c b/gst/videoparsers/h263parse.c similarity index 100% rename from gst/h263parse/h263parse.c rename to gst/videoparsers/h263parse.c diff --git a/gst/h263parse/h263parse.h b/gst/videoparsers/h263parse.h similarity index 100% rename from gst/h263parse/h263parse.h rename to gst/videoparsers/h263parse.h diff --git a/gst/videoparsers/plugin.c b/gst/videoparsers/plugin.c new file mode 100644 index 0000000000..b6d29c459b --- /dev/null +++ b/gst/videoparsers/plugin.c @@ -0,0 +1,42 @@ +/* GStreamer video parsers + * Copyright (C) 2011 Mark Nauwelaerts + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gsth263parse.h" + +static gboolean +plugin_init (GstPlugin * plugin) +{ + gboolean ret; + + ret = gst_element_register (plugin, "h263parse", + GST_RANK_NONE, GST_TYPE_H263_PARSE); + + return ret; +} + + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "videoparsersbad", + "videoparsers", + plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN); From 0df8bb33a6c219fbe4098c411ae0249c20aae9c0 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Thu, 27 Jan 2011 18:20:13 +0100 Subject: [PATCH 368/448] h264parse: rename to legacyh264parse --- gst/h264parse/gsth264parse.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/gst/h264parse/gsth264parse.c b/gst/h264parse/gsth264parse.c index 9c35d3b2b6..5ad43f2fcc 100644 --- a/gst/h264parse/gsth264parse.c +++ b/gst/h264parse/gsth264parse.c @@ -869,7 +869,10 @@ gst_nal_decode_slice_header (GstH264Parse * h, GstNalBs * bs) return TRUE; } -GST_BOILERPLATE (GstH264Parse, gst_h264_parse, GstElement, GST_TYPE_ELEMENT); +typedef GstH264Parse GstLegacyH264Parse; +typedef GstH264ParseClass GstLegacyH264ParseClass; +GST_BOILERPLATE (GstLegacyH264Parse, gst_h264_parse, GstElement, + GST_TYPE_ELEMENT); static void gst_h264_parse_reset (GstH264Parse * h264parse); static void gst_h264_parse_finalize (GObject * object); @@ -900,7 +903,8 @@ gst_h264_parse_base_init (gpointer g_class) "Michal Benes ," "Wim Taymans "); - GST_DEBUG_CATEGORY_INIT (h264_parse_debug, "h264parse", 0, "h264 parser"); + GST_DEBUG_CATEGORY_INIT (h264_parse_debug, "legacy h264parse", 0, + "legacy h264 parser"); } static void @@ -2695,7 +2699,7 @@ gst_h264_parse_change_state (GstElement * element, GstStateChange transition) static gboolean plugin_init (GstPlugin * plugin) { - return gst_element_register (plugin, "h264parse", + return gst_element_register (plugin, "legacyh264parse", GST_RANK_NONE, GST_TYPE_H264PARSE); } From d0b942980ed9d9e9e2d0d47314ae1b863c596fda Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Fri, 28 Jan 2011 12:38:19 +0100 Subject: [PATCH 369/448] videoparsers: add h264parse Functionally equivalent to (legacy)h264parse and re-uses the latter's low level NAL parsing, but otherwise based on GstBaseParse, and replacing some property configuration with caps negotiation. --- gst/videoparsers/Makefile.am | 7 +- gst/videoparsers/gsth264parse.c | 1150 +++++++++++++++++++++++++++++++ gst/videoparsers/gsth264parse.h | 93 +++ gst/videoparsers/h264parse.c | 1042 ++++++++++++++++++++++++++++ gst/videoparsers/h264parse.h | 186 +++++ gst/videoparsers/plugin.c | 3 + 6 files changed, 2479 insertions(+), 2 deletions(-) create mode 100644 gst/videoparsers/gsth264parse.c create mode 100644 gst/videoparsers/gsth264parse.h create mode 100644 gst/videoparsers/h264parse.c create mode 100644 gst/videoparsers/h264parse.h diff --git a/gst/videoparsers/Makefile.am b/gst/videoparsers/Makefile.am index 072e001524..0ff15e7d42 100644 --- a/gst/videoparsers/Makefile.am +++ b/gst/videoparsers/Makefile.am @@ -1,9 +1,12 @@ plugin_LTLIBRARIES = libgsth263parse.la -libgsth263parse_la_SOURCES = plugin.c h263parse.c gsth263parse.c gstbaseparse.c +libgsth263parse_la_SOURCES = plugin.c \ + h263parse.c gsth263parse.c gsth264parse.c h264parse.c gstbaseparse.c libgsth263parse_la_CFLAGS = $(GST_CFLAGS) libgsth263parse_la_LIBADD = $(GST_BASE_LIBS) $(GST_LIBS) libgsth263parse_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) libgsth263parse_la_LIBTOOLFLAGS = --tag=disable-static -noinst_HEADERS = gsth263parse.h h263parse.h gstbaseparse.h +noinst_HEADERS = gsth263parse.h h263parse.h \ + gsth264parse.h gsth264parse.h \ + gstbaseparse.h diff --git a/gst/videoparsers/gsth264parse.c b/gst/videoparsers/gsth264parse.c new file mode 100644 index 0000000000..799303ea35 --- /dev/null +++ b/gst/videoparsers/gsth264parse.c @@ -0,0 +1,1150 @@ +/* GStreamer H.264 Parser + * Copyright (C) <2010> Mark Nauwelaerts + * Copyright (C) <2010> Collabora Multimedia + * Copyright (C) <2010> Nokia Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include "gsth264parse.h" + +#include + +GST_DEBUG_CATEGORY (h264_parse_debug); +#define GST_CAT_DEFAULT h264_parse_debug + +#define DEFAULT_SPLIT_PACKETIZED FALSE +#define DEFAULT_CONFIG_INTERVAL (0) + +enum +{ + PROP_0, + PROP_SPLIT_PACKETIZED, + PROP_CONFIG_INTERVAL, + PROP_LAST +}; + +enum +{ + GST_H264_PARSE_FORMAT_NONE, + GST_H264_PARSE_FORMAT_AVC, + GST_H264_PARSE_FORMAT_BYTE +}; + +enum +{ + GST_H264_PARSE_ALIGN_NONE = 0, + GST_H264_PARSE_ALIGN_NAL, + GST_H264_PARSE_ALIGN_AU +}; + +static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("video/x-h264, parsed = (boolean) false")); + +static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("video/x-h264, parsed = (boolean) true")); + +GST_BOILERPLATE (GstH264Parse, gst_h264_parse, GstElement, GST_TYPE_BASE_PARSE); + +static void gst_h264_parse_finalize (GObject * object); + +static gboolean gst_h264_parse_start (GstBaseParse * parse); +static gboolean gst_h264_parse_stop (GstBaseParse * parse); +static gboolean gst_h264_parse_check_valid_frame (GstBaseParse * parse, + GstBaseParseFrame * frame, guint * framesize, gint * skipsize); +static GstFlowReturn gst_h264_parse_parse_frame (GstBaseParse * parse, + GstBaseParseFrame * frame); +static GstFlowReturn gst_h264_parse_pre_push_frame (GstBaseParse * parse, + GstBaseParseFrame * frame); + +static void gst_h264_parse_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_h264_parse_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); + +static gboolean gst_h264_parse_set_caps (GstBaseParse * parse, GstCaps * caps); +static GstFlowReturn gst_h264_parse_chain (GstPad * pad, GstBuffer * buffer); + +static void +gst_h264_parse_base_init (gpointer g_class) +{ + GstElementClass *gstelement_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&srctemplate)); + gst_element_class_add_pad_template (gstelement_class, + gst_static_pad_template_get (&sinktemplate)); + + gst_element_class_set_details_simple (gstelement_class, "H.264 parser", + "Codec/Parser/Video", + "Parses H.264 streams", + "Mark Nauwelaerts "); + + GST_DEBUG_CATEGORY_INIT (h264_parse_debug, "h264parse", 0, "h264 parser"); +} + +static void +gst_h264_parse_class_init (GstH264ParseClass * klass) +{ + GObjectClass *gobject_class = (GObjectClass *) klass; + GstBaseParseClass *parse_class = GST_BASE_PARSE_CLASS (klass); + + gobject_class->finalize = gst_h264_parse_finalize; + gobject_class->set_property = gst_h264_parse_set_property; + gobject_class->get_property = gst_h264_parse_get_property; + + g_object_class_install_property (gobject_class, PROP_SPLIT_PACKETIZED, + g_param_spec_boolean ("split-packetized", "Split packetized", + "Split NAL units of packetized streams", DEFAULT_SPLIT_PACKETIZED, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_CONFIG_INTERVAL, + g_param_spec_uint ("config-interval", + "SPS PPS Send Interval", + "Send SPS and PPS Insertion Interval in seconds (sprop parameter sets " + "will be multiplexed in the data stream when detected.) (0 = disabled)", + 0, 3600, DEFAULT_CONFIG_INTERVAL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS)); + + /* Override BaseParse vfuncs */ + parse_class->start = GST_DEBUG_FUNCPTR (gst_h264_parse_start); + parse_class->stop = GST_DEBUG_FUNCPTR (gst_h264_parse_stop); + parse_class->check_valid_frame = + GST_DEBUG_FUNCPTR (gst_h264_parse_check_valid_frame); + parse_class->parse_frame = GST_DEBUG_FUNCPTR (gst_h264_parse_parse_frame); + parse_class->pre_push_frame = + GST_DEBUG_FUNCPTR (gst_h264_parse_pre_push_frame); + parse_class->set_sink_caps = GST_DEBUG_FUNCPTR (gst_h264_parse_set_caps); +} + +static void +gst_h264_parse_init (GstH264Parse * h264parse, GstH264ParseClass * g_class) +{ + h264parse->frame_out = gst_adapter_new (); + + /* retrieve and intercept baseparse. + * Quite HACKish, but fairly OK since it is needed to perform avc packet + * splitting, which is the penultimate de-parsing */ + h264parse->parse_chain = + GST_PAD_CHAINFUNC (GST_BASE_PARSE_SINK_PAD (h264parse)); + gst_pad_set_chain_function (GST_BASE_PARSE_SINK_PAD (h264parse), + gst_h264_parse_chain); +} + + +static void +gst_h264_parse_finalize (GObject * object) +{ + GstH264Parse *h264parse = GST_H264_PARSE (object); + + g_object_unref (h264parse->frame_out); +} + +static void +gst_h264_parse_reset_frame (GstH264Parse * h264parse) +{ + /* done parsing; reset state */ + h264parse->last_nal_pos = 0; + h264parse->next_sc_pos = 0; + h264parse->picture_start = FALSE; + h264parse->update_caps = FALSE; + h264parse->idr_pos = -1; + h264parse->keyframe = FALSE; + h264parse->frame_start = FALSE; +} + +static void +gst_h264_parse_reset (GstH264Parse * h264parse) +{ + h264parse->width = 0; + h264parse->height = 0; + h264parse->fps_num = 0; + h264parse->fps_den = 0; + gst_buffer_replace (&h264parse->codec_data, NULL); + h264parse->nal_length_size = 4; + h264parse->packetized = FALSE; + + h264parse->align = GST_H264_PARSE_ALIGN_NONE; + h264parse->format = GST_H264_PARSE_FORMAT_NONE; + + h264parse->last_report = GST_CLOCK_TIME_NONE; + h264parse->push_codec = FALSE; + + gst_h264_parse_reset_frame (h264parse); +} + +static gboolean +gst_h264_parse_start (GstBaseParse * parse) +{ + GstH264Parse *h264parse = GST_H264_PARSE (parse); + + GST_DEBUG ("Start"); + gst_h264_parse_reset (h264parse); + + gst_h264_params_create (&h264parse->params, GST_ELEMENT (h264parse)); + + gst_base_parse_set_min_frame_size (parse, 512); + + return TRUE; +} + +static gboolean +gst_h264_parse_stop (GstBaseParse * parse) +{ + GstH264Parse *h264parse = GST_H264_PARSE (parse); + + GST_DEBUG ("Stop"); + gst_h264_parse_reset (h264parse); + + gst_h264_params_free (h264parse->params); + h264parse->params = NULL; + + return TRUE; +} + +static const gchar * +gst_h264_parse_get_string (GstH264Parse * parse, gboolean format, gint code) +{ + if (format) { + switch (code) { + case GST_H264_PARSE_FORMAT_AVC: + return "avc"; + case GST_H264_PARSE_FORMAT_BYTE: + return "byte-stream"; + default: + return "none"; + } + } else { + switch (code) { + case GST_H264_PARSE_ALIGN_NAL: + return "nal"; + case GST_H264_PARSE_ALIGN_AU: + return "au"; + default: + return "none"; + } + } +} + +/* check downstream caps to configure format and alignment */ +static void +gst_h264_parse_negotiate (GstH264Parse * h264parse) +{ + GstCaps *caps; + guint format = GST_H264_PARSE_FORMAT_NONE; + guint align = GST_H264_PARSE_ALIGN_NONE; + + caps = gst_pad_get_allowed_caps (GST_BASE_PARSE_SRC_PAD (h264parse)); + GST_DEBUG_OBJECT (h264parse, "allowed caps: %" GST_PTR_FORMAT, caps); + + if (caps && gst_caps_get_size (caps) > 0) { + GstStructure *s = gst_caps_get_structure (caps, 0); + const gchar *str = NULL; + + if ((str = gst_structure_get_string (s, "stream-format"))) { + if (strcmp (str, "avc") == 0) { + format = GST_H264_PARSE_FORMAT_AVC; + } else if (strcmp (str, "byte-stream") == 0) { + format = GST_H264_PARSE_FORMAT_BYTE; + } else { + GST_DEBUG_OBJECT (h264parse, "unknown stream-format: %s", str); + } + } + + if ((str = gst_structure_get_string (s, "alignment"))) { + if (strcmp (str, "au") == 0) { + align = GST_H264_PARSE_ALIGN_AU; + } else if (strcmp (str, "nal") == 0) { + align = GST_H264_PARSE_ALIGN_NAL; + } else { + GST_DEBUG_OBJECT (h264parse, "unknown alignment: %s", str); + } + } + } + + if (caps) + gst_caps_unref (caps); + + /* default */ + if (!format) + format = GST_H264_PARSE_FORMAT_BYTE; + if (!align) + align = GST_H264_PARSE_ALIGN_AU; + + GST_DEBUG_OBJECT (h264parse, "selected format %s, alignment %s", + gst_h264_parse_get_string (h264parse, TRUE, format), + gst_h264_parse_get_string (h264parse, FALSE, align)); + + h264parse->format = format; + h264parse->align = align; +} + +static GstBuffer * +gst_h264_parse_wrap_nal (GstH264Parse * h264parse, guint format, guint8 * data, + guint size) +{ + GstBuffer *buf; + const guint nl = h264parse->nal_length_size; + + buf = gst_buffer_new_and_alloc (size + nl + 4); + if (format == GST_H264_PARSE_FORMAT_AVC) { + GST_WRITE_UINT32_BE (GST_BUFFER_DATA (buf), size << (32 - 8 * nl)); + } else { + g_assert (nl == 4); + GST_WRITE_UINT32_BE (GST_BUFFER_DATA (buf), 1); + } + + GST_BUFFER_SIZE (buf) = size + nl; + memcpy (GST_BUFFER_DATA (buf) + nl, data, size); + + return buf; +} + +/* SPS/PPS/IDR considered key, all others DELTA; + * so downstream waiting for keyframe can pick up at SPS/PPS/IDR */ +#define NAL_TYPE_IS_KEY(nt) (((nt) == 5) || ((nt) == 7) || ((nt) == 8)) + +/* caller guarantees 2 bytes of nal payload */ +static void +gst_h264_parse_process_nal (GstH264Parse * h264parse, guint8 * data, + gint sc_pos, gint nal_pos, guint nal_size) +{ + guint nal_type; + + g_return_if_fail (nal_size >= 2); + g_return_if_fail (nal_pos - sc_pos > 0 && nal_pos - sc_pos <= 4); + + /* lower layer collects params */ + gst_h264_params_parse_nal (h264parse->params, data + nal_pos, nal_size); + + /* we have a peek as well */ + nal_type = data[nal_pos] & 0x1f; + h264parse->keyframe |= NAL_TYPE_IS_KEY (nal_type); + + switch (nal_type) { + case NAL_SPS: + case NAL_PPS: + /* parameters might have changed, force caps check */ + GST_DEBUG_OBJECT (h264parse, "triggering src caps check"); + h264parse->update_caps = TRUE; + /* found in stream, no need to forcibly push at start */ + h264parse->push_codec = FALSE; + break; + case NAL_SLICE: + case NAL_SLICE_DPA: + case NAL_SLICE_DPB: + case NAL_SLICE_DPC: + /* real frame data */ + h264parse->frame_start |= (h264parse->params->first_mb_in_slice == 0); + /* if we need to sneak codec NALs into the stream, + * this is a good place, so fake it as IDR + * (which should be at start anyway) */ + if (G_LIKELY (!h264parse->push_codec)) + break; + /* fall-through */ + case NAL_SLICE_IDR: + /* real frame data */ + h264parse->frame_start |= (h264parse->params->first_mb_in_slice == 0); + /* mark where config needs to go if interval expired */ + /* mind replacement buffer if applicable */ + if (h264parse->format == GST_H264_PARSE_FORMAT_AVC) + h264parse->idr_pos = gst_adapter_available (h264parse->frame_out); + else + h264parse->idr_pos = sc_pos; + GST_DEBUG_OBJECT (h264parse, "marking IDR in frame at offset %d", + h264parse->idr_pos); + break; + } + + /* if AVC output needed, collect properly prefixed nal in adapter, + * and use that to replace outgoing buffer data later on */ + if (h264parse->format == GST_H264_PARSE_FORMAT_AVC) { + GstBuffer *buf; + + GST_LOG_OBJECT (h264parse, "collecting NAL in AVC frame"); + buf = gst_h264_parse_wrap_nal (h264parse, h264parse->format, + data + nal_pos, nal_size); + gst_adapter_push (h264parse->frame_out, buf); + } +} + +/* caller guarantees at least 2 bytes of nal payload for each nal + * returns TRUE if next_nal indicates that nal terminates an AU */ +static inline gboolean +gst_h264_parse_collect_nal (GstH264Parse * h264parse, guint8 * nal, + guint8 * next_nal) +{ + gint nal_type; + gboolean complete; + + if (h264parse->align == GST_H264_PARSE_ALIGN_NAL) + return TRUE; + + /* determine if AU complete */ + nal_type = nal[0] & 0x1f; + GST_LOG_OBJECT (h264parse, "nal type: %d", nal_type); + /* coded slice NAL starts a picture, + * i.e. other types become aggregated in front of it */ + h264parse->picture_start |= (nal_type == 1 || nal_type == 2 || nal_type == 5); + + /* consider a coded slices (IDR or not) to start a picture, + * (so ending the previous one) if first_mb_in_slice == 0 + * (non-0 is part of previous one) */ + /* NOTE this is not entirely according to Access Unit specs in 7.4.1.2.4, + * but in practice it works in sane cases, needs not much parsing, + * and also works with broken frame_num in NAL + * (where spec-wise would fail) */ + nal_type = next_nal[0] & 0x1f; + GST_LOG_OBJECT (h264parse, "next nal type: %d", nal_type); + complete = h264parse->picture_start && (nal_type >= 6 && nal_type <= 9); + complete |= h264parse->picture_start && + (nal_type == 1 || nal_type == 2 || nal_type == 5) && + /* first_mb_in_slice == 0 considered start of frame */ + (next_nal[1] & 0x80); + + GST_LOG_OBJECT (h264parse, "au complete: %d", complete); + + return complete; +} + +/* finds next startcode == 00 00 01, along with a subsequent byte */ +static guint +gst_h264_parse_find_sc (GstBuffer * buffer, guint skip) +{ + GstByteReader br; + guint sc_pos = -1; + + gst_byte_reader_init_from_buffer (&br, buffer); + + /* NALU not empty, so we can at least expect 1 (even 2) bytes following sc */ + sc_pos = gst_byte_reader_masked_scan_uint32 (&br, 0xffffff00, 0x00000100, + skip, gst_byte_reader_get_remaining (&br) - skip); + + return sc_pos; +} + +static gboolean +gst_h264_parse_check_valid_frame (GstBaseParse * parse, + GstBaseParseFrame * frame, guint * framesize, gint * skipsize) +{ + GstH264Parse *h264parse = GST_H264_PARSE (parse); + GstBuffer *buffer = frame->buffer; + gint sc_pos, nal_pos, next_sc_pos, next_nal_pos; + guint8 *data; + guint size; + gboolean drain; + + /* expect at least 3 bytes startcode == sc, and 2 bytes NALU payload */ + if (G_UNLIKELY (GST_BUFFER_SIZE (buffer) < 5)) + return FALSE; + + /* need to configure aggregation */ + if (G_UNLIKELY (h264parse->format == GST_H264_PARSE_FORMAT_NONE)) + gst_h264_parse_negotiate (h264parse); + + data = GST_BUFFER_DATA (buffer); + size = GST_BUFFER_SIZE (buffer); + + GST_LOG_OBJECT (h264parse, "last_nal_pos: %d, last_scan_pos %d", + h264parse->last_nal_pos, h264parse->next_sc_pos); + + nal_pos = h264parse->last_nal_pos; + next_sc_pos = h264parse->next_sc_pos; + + if (!next_sc_pos) { + sc_pos = gst_h264_parse_find_sc (buffer, 0); + + if (sc_pos == -1) { + /* SC not found, need more data */ + sc_pos = GST_BUFFER_SIZE (buffer) - 3; + goto more; + } + + nal_pos = sc_pos + 3; + next_sc_pos = nal_pos; + /* sc might have 2 or 3 0-bytes */ + if (sc_pos > 0 && data[sc_pos - 1] == 00) + sc_pos--; + GST_LOG_OBJECT (h264parse, "found sc at offset %d", sc_pos); + } else { + /* previous checks already arrange sc at start */ + sc_pos = 0; + } + + drain = GST_BASE_PARSE_FRAME_DRAIN (frame); + while (TRUE) { + gint prev_sc_pos; + + next_sc_pos = gst_h264_parse_find_sc (buffer, next_sc_pos); + if (next_sc_pos == -1) { + GST_LOG_OBJECT (h264parse, "no next sc"); + if (drain) { + /* FLUSH/EOS, it's okay if we can't find the next frame */ + next_sc_pos = size; + next_nal_pos = size; + } else { + next_sc_pos = size - 3; + goto more; + } + } else { + next_nal_pos = next_sc_pos + 3; + if (data[next_sc_pos - 1] == 00) + next_sc_pos--; + GST_LOG_OBJECT (h264parse, "found next sc at offset %d", next_sc_pos); + /* need at least 1 more byte of next NAL */ + if (!drain && (next_nal_pos == size - 1)) + goto more; + } + + /* determine nal's sc position */ + prev_sc_pos = nal_pos - 3; + g_assert (prev_sc_pos >= 0); + if (prev_sc_pos > 0 && data[prev_sc_pos - 1] == 0) + prev_sc_pos--; + + /* already consume and gather info from NAL */ + gst_h264_parse_process_nal (h264parse, data, prev_sc_pos, nal_pos, + next_sc_pos - nal_pos); + if (next_nal_pos >= size - 1 || + gst_h264_parse_collect_nal (h264parse, data + nal_pos, + data + next_nal_pos)) + break; + + /* move along */ + next_sc_pos = nal_pos = next_nal_pos; + } + + *skipsize = sc_pos; + *framesize = next_sc_pos - sc_pos; + + return TRUE; + +more: + /* Ask for 1024 bytes more - this is an arbitrary choice */ + gst_base_parse_set_min_frame_size (parse, GST_BUFFER_SIZE (buffer) + 1024); + + /* skip up to initial startcode */ + *skipsize = sc_pos; + /* resume scanning here next time */ + h264parse->last_nal_pos = nal_pos; + h264parse->next_sc_pos = next_sc_pos; + + return FALSE; +} + +/* byte together avc codec data based on collected pps and sps so far */ +static GstBuffer * +gst_h264_parse_make_codec_data (GstH264Parse * h264parse) +{ + GstBuffer *buf, *nal; + gint i, sps_size = 0, pps_size = 0, num_sps = 0, num_pps = 0; + guint8 profile_idc = 0, profile_comp = 0, level_idc = 0; + gboolean found = FALSE; + guint8 *data; + + /* only nal payload in stored nals */ + + for (i = 0; i < MAX_SPS_COUNT; i++) { + if ((nal = h264parse->params->sps_nals[i])) { + num_sps++; + /* size bytes also count */ + sps_size += GST_BUFFER_SIZE (nal) + 2; + if (GST_BUFFER_SIZE (nal) >= 4) { + found = TRUE; + profile_idc = (GST_BUFFER_DATA (nal))[1]; + profile_comp = (GST_BUFFER_DATA (nal))[2]; + level_idc = (GST_BUFFER_DATA (nal))[3]; + } + } + } + for (i = 0; i < MAX_PPS_COUNT; i++) { + if ((nal = h264parse->params->pps_nals[i])) { + num_pps++; + /* size bytes also count */ + pps_size += GST_BUFFER_SIZE (nal) + 2; + } + } + + GST_DEBUG_OBJECT (h264parse, + "constructing codec_data: num_sps=%d, num_pps=%d", num_sps, num_pps); + + if (!found || !num_pps) + return NULL; + + buf = gst_buffer_new_and_alloc (5 + 1 + sps_size + 1 + pps_size); + data = GST_BUFFER_DATA (buf); + + data[0] = 1; /* AVC Decoder Configuration Record ver. 1 */ + data[1] = profile_idc; /* profile_idc */ + data[2] = profile_comp; /* profile_compability */ + data[3] = level_idc; /* level_idc */ + data[4] = 0xfc | (4 - 1); /* nal_length_size_minus1 */ + data[5] = 0xe0 | num_sps; /* number of SPSs */ + + data += 6; + for (i = 0; i < MAX_SPS_COUNT; i++) { + if ((nal = h264parse->params->sps_nals[i])) { + GST_WRITE_UINT16_BE (data, GST_BUFFER_SIZE (nal)); + memcpy (data + 2, GST_BUFFER_DATA (nal), GST_BUFFER_SIZE (nal)); + data += 2 + GST_BUFFER_SIZE (nal); + } + } + + data[0] = num_pps; + data++; + for (i = 0; i < MAX_PPS_COUNT; i++) { + if ((nal = h264parse->params->pps_nals[i])) { + GST_WRITE_UINT16_BE (data, GST_BUFFER_SIZE (nal)); + memcpy (data + 2, GST_BUFFER_DATA (nal), GST_BUFFER_SIZE (nal)); + data += 2 + GST_BUFFER_SIZE (nal); + } + } + + return buf; +} + +static void +gst_h264_parse_update_src_caps (GstH264Parse * h264parse) +{ + GstH264ParamsSPS *sps; + GstCaps *caps = NULL, *sink_caps; + gboolean modified = FALSE; + GstBuffer *buf = NULL; + + if (G_UNLIKELY (!GST_PAD_CAPS (GST_BASE_PARSE_SRC_PAD (h264parse)))) + modified = TRUE; + else if (G_UNLIKELY (!h264parse->update_caps)) + return; + + /* carry over input caps as much as possible; override with our own stuff */ + sink_caps = GST_PAD_CAPS (GST_BASE_PARSE_SINK_PAD (h264parse)); + if (sink_caps) + gst_caps_ref (sink_caps); + else + sink_caps = gst_caps_new_simple ("video/x-h264", NULL); + + sps = h264parse->params->sps; + GST_DEBUG_OBJECT (h264parse, "sps: %p", sps); + + /* only codec-data for nice-and-clean au aligned packetized avc format */ + if (h264parse->format == GST_H264_PARSE_FORMAT_AVC && + h264parse->align == GST_H264_PARSE_ALIGN_AU) { + buf = gst_h264_parse_make_codec_data (h264parse); + if (buf && h264parse->codec_data) { + if (GST_BUFFER_SIZE (buf) != GST_BUFFER_SIZE (h264parse->codec_data) || + memcmp (GST_BUFFER_DATA (buf), + GST_BUFFER_DATA (h264parse->codec_data), GST_BUFFER_SIZE (buf))) + modified = TRUE; + } else { + if (h264parse->codec_data) + buf = gst_buffer_ref (h264parse->codec_data); + modified = TRUE; + } + } + + if (G_UNLIKELY (!sps)) { + caps = gst_caps_copy (sink_caps); + } else if (G_UNLIKELY (h264parse->width != sps->width || + h264parse->height != sps->height || h264parse->fps_num != sps->fps_num + || h264parse->fps_den != sps->fps_den || modified)) { + caps = gst_caps_copy (sink_caps); + /* sps should give this */ + gst_caps_set_simple (caps, "width", G_TYPE_INT, sps->width, + "height", G_TYPE_INT, sps->height, NULL); + h264parse->height = sps->height; + h264parse->width = sps->width; + /* but not necessarily or reliably this */ + if ((!h264parse->fps_num || !h264parse->fps_den) && + sps->fps_num > 0 && sps->fps_den > 0) { + gst_caps_set_simple (caps, "framerate", + GST_TYPE_FRACTION, sps->fps_num, sps->fps_den, NULL); + h264parse->fps_num = sps->fps_num; + h264parse->fps_den = sps->fps_den; + gst_base_parse_set_frame_props (GST_BASE_PARSE (h264parse), + h264parse->fps_num, h264parse->fps_den, 0, 0); + } + } + + if (caps) { + gst_caps_set_simple (caps, "stream-format", G_TYPE_STRING, + gst_h264_parse_get_string (h264parse, TRUE, h264parse->format), + "alignment", G_TYPE_STRING, + gst_h264_parse_get_string (h264parse, FALSE, h264parse->align), NULL); + if (buf) { + gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER, buf, NULL); + gst_buffer_replace (&h264parse->codec_data, buf); + gst_buffer_unref (buf); + buf = NULL; + } else { + GstStructure *s; + /* remove any left-over codec-data hanging around */ + s = gst_caps_get_structure (caps, 0); + gst_structure_remove_field (s, "codec_data"); + } + gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (h264parse), caps); + gst_caps_unref (caps); + } + + gst_caps_unref (sink_caps); + if (buf) + gst_buffer_unref (buf); +} + +static GstFlowReturn +gst_h264_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame) +{ + GstH264Parse *h264parse; + GstBuffer *buffer; + guint av; + + h264parse = GST_H264_PARSE (parse); + buffer = frame->buffer; + + gst_h264_parse_update_src_caps (h264parse); + + gst_h264_params_get_timestamp (h264parse->params, + &GST_BUFFER_TIMESTAMP (buffer), &GST_BUFFER_DURATION (buffer), + h264parse->frame_start); + + if (h264parse->keyframe) + GST_BUFFER_FLAG_UNSET (buffer, GST_BUFFER_FLAG_DELTA_UNIT); + else + GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT); + + /* replace with transformed AVC output if applicable */ + av = gst_adapter_available (h264parse->frame_out); + if (av) { + GstBuffer *buf; + + buf = gst_adapter_take_buffer (h264parse->frame_out, av); + gst_buffer_copy_metadata (buf, buffer, GST_BUFFER_COPY_ALL); + gst_buffer_replace (&frame->buffer, buf); + } + + return GST_FLOW_OK; +} + +/* sends a codec NAL downstream, decorating and transforming as needed. + * No ownership is taken of @nal */ +static GstFlowReturn +gst_h264_parse_push_codec_buffer (GstH264Parse * h264parse, GstBuffer * nal, + GstClockTime ts) +{ + nal = gst_h264_parse_wrap_nal (h264parse, h264parse->format, + GST_BUFFER_DATA (nal), GST_BUFFER_SIZE (nal)); + + GST_BUFFER_TIMESTAMP (nal) = ts; + GST_BUFFER_DURATION (nal) = 0; + + gst_buffer_set_caps (nal, GST_PAD_CAPS (GST_BASE_PARSE_SRC_PAD (h264parse))); + + return gst_pad_push (GST_BASE_PARSE_SRC_PAD (h264parse), nal); +} + +static GstFlowReturn +gst_h264_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame) +{ + GstH264Parse *h264parse; + GstBuffer *buffer; + + h264parse = GST_H264_PARSE (parse); + buffer = frame->buffer; + + /* periodic SPS/PPS sending */ + if (h264parse->interval > 0 || h264parse->push_codec) { + GstClockTime timestamp = GST_BUFFER_TIMESTAMP (buffer); + guint64 diff; + + /* init */ + if (!GST_CLOCK_TIME_IS_VALID (h264parse->last_report)) { + h264parse->last_report = timestamp; + } + + if (h264parse->idr_pos >= 0) { + GST_LOG_OBJECT (h264parse, "IDR nal at offset %d", h264parse->idr_pos); + + if (timestamp > h264parse->last_report) + diff = timestamp - h264parse->last_report; + else + diff = 0; + + GST_LOG_OBJECT (h264parse, + "now %" GST_TIME_FORMAT ", last SPS/PPS %" GST_TIME_FORMAT, + GST_TIME_ARGS (timestamp), GST_TIME_ARGS (h264parse->last_report)); + + GST_DEBUG_OBJECT (h264parse, + "interval since last SPS/PPS %" GST_TIME_FORMAT, + GST_TIME_ARGS (diff)); + + if (GST_TIME_AS_SECONDS (diff) >= h264parse->interval || + h264parse->push_codec) { + GstBuffer *codec_nal; + gint i; + GstClockTime new_ts; + + /* avoid overwriting a perfectly fine timestamp */ + new_ts = GST_CLOCK_TIME_IS_VALID (timestamp) ? timestamp : + h264parse->last_report; + + if (h264parse->align == GST_H264_PARSE_ALIGN_NAL) { + /* send separate config NAL buffers */ + GST_DEBUG_OBJECT (h264parse, "- sending SPS/PPS"); + for (i = 0; i < MAX_SPS_COUNT; i++) { + if ((codec_nal = h264parse->params->sps_nals[i])) { + GST_DEBUG_OBJECT (h264parse, "sending SPS nal"); + gst_h264_parse_push_codec_buffer (h264parse, codec_nal, + timestamp); + h264parse->last_report = new_ts; + } + } + for (i = 0; i < MAX_PPS_COUNT; i++) { + if ((codec_nal = h264parse->params->pps_nals[i])) { + GST_DEBUG_OBJECT (h264parse, "sending PPS nal"); + gst_h264_parse_push_codec_buffer (h264parse, codec_nal, + timestamp); + h264parse->last_report = new_ts; + } + } + } else { + /* insert config NALs into AU */ + GstByteWriter bw; + GstBuffer *new_buf; + const gboolean bs = h264parse->format == GST_H264_PARSE_FORMAT_BYTE; + + gst_byte_writer_init_with_size (&bw, GST_BUFFER_SIZE (buffer), FALSE); + gst_byte_writer_put_data (&bw, GST_BUFFER_DATA (buffer), + h264parse->idr_pos); + GST_DEBUG_OBJECT (h264parse, "- inserting SPS/PPS"); + for (i = 0; i < MAX_SPS_COUNT; i++) { + if ((codec_nal = h264parse->params->sps_nals[i])) { + GST_DEBUG_OBJECT (h264parse, "inserting SPS nal"); + gst_byte_writer_put_uint32_be (&bw, + bs ? 1 : GST_BUFFER_SIZE (codec_nal)); + gst_byte_writer_put_data (&bw, GST_BUFFER_DATA (codec_nal), + GST_BUFFER_SIZE (codec_nal)); + h264parse->last_report = new_ts; + } + } + for (i = 0; i < MAX_PPS_COUNT; i++) { + if ((codec_nal = h264parse->params->pps_nals[i])) { + GST_DEBUG_OBJECT (h264parse, "inserting PPS nal"); + gst_byte_writer_put_uint32_be (&bw, + bs ? 1 : GST_BUFFER_SIZE (codec_nal)); + gst_byte_writer_put_data (&bw, GST_BUFFER_DATA (codec_nal), + GST_BUFFER_SIZE (codec_nal)); + h264parse->last_report = new_ts; + } + } + gst_byte_writer_put_data (&bw, + GST_BUFFER_DATA (buffer) + h264parse->idr_pos, + GST_BUFFER_SIZE (buffer) - h264parse->idr_pos); + /* collect result and push */ + new_buf = gst_byte_writer_reset_and_get_buffer (&bw); + gst_buffer_copy_metadata (new_buf, buffer, GST_BUFFER_COPY_ALL); + gst_buffer_replace (&frame->buffer, new_buf); + } + } + /* we pushed whatever we had */ + h264parse->push_codec = FALSE; + } + } + + gst_h264_parse_reset_frame (h264parse); + + return GST_FLOW_OK; +} + +static gboolean +gst_h264_parse_set_caps (GstBaseParse * parse, GstCaps * caps) +{ + GstH264Parse *h264parse; + GstStructure *str; + const GValue *value; + GstBuffer *buffer = NULL; + guint size; + + h264parse = GST_H264_PARSE (parse); + + /* reset */ + h264parse->push_codec = FALSE; + + str = gst_caps_get_structure (caps, 0); + + /* accept upstream info if provided */ + gst_structure_get_int (str, "width", &h264parse->width); + gst_structure_get_int (str, "height", &h264parse->height); + gst_structure_get_fraction (str, "framerate", &h264parse->fps_num, + &h264parse->fps_den); + + /* packetized video has a codec_data */ + if ((value = gst_structure_get_value (str, "codec_data"))) { + guint8 *data; + guint num_sps, num_pps, profile, len; + gint i; + + GST_DEBUG_OBJECT (h264parse, "have packetized h264"); + /* make note for optional split processing */ + h264parse->packetized = TRUE; + + buffer = gst_value_get_buffer (value); + if (!buffer) + goto wrong_type; + data = GST_BUFFER_DATA (buffer); + size = GST_BUFFER_SIZE (buffer); + + /* parse the avcC data */ + if (size < 7) + goto avcc_too_small; + /* parse the version, this must be 1 */ + if (data[0] != 1) + goto wrong_version; + + /* AVCProfileIndication */ + /* profile_compat */ + /* AVCLevelIndication */ + profile = (data[1] << 16) | (data[2] << 8) | data[3]; + GST_DEBUG_OBJECT (h264parse, "profile %06x", profile); + + /* 6 bits reserved | 2 bits lengthSizeMinusOne */ + /* this is the number of bytes in front of the NAL units to mark their + * length */ + h264parse->nal_length_size = (data[4] & 0x03) + 1; + GST_DEBUG_OBJECT (h264parse, "nal length %u", h264parse->nal_length_size); + + num_sps = data[5] & 0x1f; + data += 6; + size -= 6; + for (i = 0; i < num_sps; i++) { + len = GST_READ_UINT16_BE (data); + if (size < len + 2 || len < 2) + goto avcc_too_small; + /* digest for later reference */ + gst_h264_parse_process_nal (h264parse, data, 0, 2, len); + data += len + 2; + size -= len + 2; + } + num_pps = data[0]; + data++; + size++; + for (i = 0; i < num_pps; i++) { + len = GST_READ_UINT16_BE (data); + if (size < len + 2 || len < 2) + goto avcc_too_small; + /* digest for later reference */ + gst_h264_parse_process_nal (h264parse, data, 0, 2, len); + data += len + 2; + size -= len + 2; + } + } else { + GST_DEBUG_OBJECT (h264parse, "have bytestream h264"); + /* nothing to pre-process */ + h264parse->packetized = FALSE; + /* we have 4 sync bytes */ + h264parse->nal_length_size = 4; + } + + if (h264parse->packetized) { + if (h264parse->split_packetized) { + GST_DEBUG_OBJECT (h264parse, + "converting AVC to nal bytestream prior to parsing"); + /* negotiate behaviour with upstream */ + gst_h264_parse_negotiate (h264parse); + if (h264parse->format == GST_H264_PARSE_FORMAT_BYTE) { + /* arrange to insert codec-data in-stream if needed */ + h264parse->push_codec = h264parse->packetized; + } + } else { + GST_DEBUG_OBJECT (h264parse, "passing on packetized AVC"); + /* no choice to negotiate */ + h264parse->format = GST_H264_PARSE_FORMAT_AVC; + h264parse->align = GST_H264_PARSE_ALIGN_AU; + /* fallback codec-data */ + h264parse->codec_data = gst_buffer_ref (buffer); + /* pass through unharmed, though _chain will parse a bit */ + gst_base_parse_set_format (parse, + GST_BASE_PARSE_FORMAT_PASSTHROUGH, TRUE); + /* we did parse codec-data and might supplement src caps */ + gst_h264_parse_update_src_caps (h264parse); + } + } + + /* src caps are only arranged for later on */ + return TRUE; + + /* ERRORS */ +avcc_too_small: + { + GST_DEBUG_OBJECT (h264parse, "avcC size %u < 7", size); + goto refuse_caps; + } +wrong_version: + { + GST_DEBUG_OBJECT (h264parse, "wrong avcC version"); + goto refuse_caps; + } +wrong_type: + { + GST_DEBUG_OBJECT (h264parse, "wrong codec-data type"); + goto refuse_caps; + } +refuse_caps: + { + GST_WARNING_OBJECT (h264parse, "refused caps %" GST_PTR_FORMAT, caps); + return FALSE; + } +} + +static GstFlowReturn +gst_h264_parse_chain (GstPad * pad, GstBuffer * buffer) +{ + GstH264Parse *h264parse = GST_H264_PARSE (GST_PAD_PARENT (pad)); + + if (h264parse->packetized && buffer) { + GstByteReader br; + GstBuffer *sub; + GstFlowReturn ret = GST_FLOW_OK; + guint32 len; + const guint nl = h264parse->nal_length_size; + + GST_LOG_OBJECT (h264parse, "processing packet buffer of size %d", + GST_BUFFER_SIZE (buffer)); + gst_byte_reader_init_from_buffer (&br, buffer); + while (ret == GST_FLOW_OK && gst_byte_reader_get_remaining (&br)) { + GST_DEBUG_OBJECT (h264parse, "AVC nal offset %d", + gst_byte_reader_get_pos (&br)); + if (gst_byte_reader_get_remaining (&br) < nl) + goto parse_failed; + switch (nl) { + case 4: + len = gst_byte_reader_get_uint32_be_unchecked (&br); + break; + case 3: + len = gst_byte_reader_get_uint24_be_unchecked (&br); + break; + case 2: + len = gst_byte_reader_get_uint16_be_unchecked (&br); + break; + case 1: + len = gst_byte_reader_get_uint8_unchecked (&br); + break; + default: + goto not_negotiated; + break; + } + GST_DEBUG_OBJECT (h264parse, "AVC nal size %d", len); + if (gst_byte_reader_get_remaining (&br) < len) + goto parse_failed; + if (h264parse->split_packetized) { + /* convert to NAL aligned byte stream input */ + sub = gst_h264_parse_wrap_nal (h264parse, GST_H264_PARSE_FORMAT_BYTE, + (guint8 *) gst_byte_reader_get_data_unchecked (&br, len), len); + /* at least this should make sense */ + GST_BUFFER_TIMESTAMP (sub) = GST_BUFFER_TIMESTAMP (buffer); + GST_LOG_OBJECT (h264parse, "pushing NAL of size %d", len); + ret = h264parse->parse_chain (pad, sub); + } else { + /* pass-through: no looking for frames (and nal processing), + * so need to parse to collect data here */ + /* NOTE: so if it is really configured to do so, + * pre_push can/will still insert codec-data at intervals, + * which is not really pure pass-through, but anyway ... */ + gst_h264_parse_process_nal (h264parse, + GST_BUFFER_DATA (buffer), gst_byte_reader_get_pos (&br) - nl, + gst_byte_reader_get_pos (&br), len); + gst_byte_reader_skip_unchecked (&br, len); + } + } + if (h264parse->split_packetized) + return ret; + } + +exit: + /* nal processing in pass-through might have collected stuff; + * ensure nothing happens with this later on */ + gst_adapter_clear (h264parse->frame_out); + + return h264parse->parse_chain (pad, buffer); + + /* ERRORS */ +not_negotiated: + { + GST_DEBUG_OBJECT (h264parse, "insufficient data to split input"); + return GST_FLOW_NOT_NEGOTIATED; + } +parse_failed: + { + if (h264parse->split_packetized) { + GST_ELEMENT_ERROR (h264parse, STREAM, FAILED, (NULL), + ("invalid AVC input data")); + return GST_FLOW_ERROR; + } else { + /* do not meddle to much in this case */ + GST_DEBUG_OBJECT (h264parse, "parsing packet failed"); + goto exit; + } + } +} + +static void +gst_h264_parse_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstH264Parse *parse; + + parse = GST_H264_PARSE (object); + + switch (prop_id) { + case PROP_SPLIT_PACKETIZED: + parse->split_packetized = g_value_get_boolean (value); + break; + case PROP_CONFIG_INTERVAL: + parse->interval = g_value_get_uint (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +gst_h264_parse_get_property (GObject * object, guint prop_id, GValue * value, + GParamSpec * pspec) +{ + GstH264Parse *parse; + + parse = GST_H264_PARSE (object); + + switch (prop_id) { + case PROP_SPLIT_PACKETIZED: + g_value_set_boolean (value, parse->split_packetized); + break; + case PROP_CONFIG_INTERVAL: + g_value_set_uint (value, parse->interval); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} diff --git a/gst/videoparsers/gsth264parse.h b/gst/videoparsers/gsth264parse.h new file mode 100644 index 0000000000..50f4cf2364 --- /dev/null +++ b/gst/videoparsers/gsth264parse.h @@ -0,0 +1,93 @@ +/* GStreamer H.264 Parser + * Copyright (C) <2010> Mark Nauwelaerts + * Copyright (C) <2010> Collabora Multimedia + * Copyright (C) <2010> Nokia Corporation + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_H264_PARSE_H__ +#define __GST_H264_PARSE_H__ + +#include +#include "gstbaseparse.h" + +#include "h264parse.h" + +G_BEGIN_DECLS + +typedef struct _H264Params H264Params; + +#define GST_TYPE_H264_PARSE \ + (gst_h264_parse_get_type()) +#define GST_H264_PARSE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_H264_PARSE,GstH264Parse)) +#define GST_H264_PARSE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_H264_PARSE,GstH264ParseClass)) +#define GST_IS_H264_PARSE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_H264_PARSE)) +#define GST_IS_H264_PARSE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_H264_PARSE)) + +GType gst_h264_parse_get_type (void); + +typedef struct _GstH264Parse GstH264Parse; +typedef struct _GstH264ParseClass GstH264ParseClass; + +struct _GstH264Parse +{ + GstBaseParse baseparse; + + GstPadChainFunction parse_chain; + + /* stream */ + gint width, height; + gint fps_num, fps_den; + GstBuffer *codec_data; + guint nal_length_size; + gboolean packetized; + + /* state */ + GstH264Params *params; + guint align; + guint format; + + GstClockTime last_report; + gboolean push_codec; + + /* frame parsing */ + guint last_nal_pos; + guint next_sc_pos; + gint idr_pos; + gboolean update_caps; + GstAdapter *frame_out; + gboolean keyframe; + gboolean frame_start; + /* AU state */ + gboolean picture_start; + + /* props */ + gboolean split_packetized; + guint interval; +}; + +struct _GstH264ParseClass +{ + GstBaseParseClass parent_class; +}; + +G_END_DECLS +#endif diff --git a/gst/videoparsers/h264parse.c b/gst/videoparsers/h264parse.c new file mode 100644 index 0000000000..f0ec757f87 --- /dev/null +++ b/gst/videoparsers/h264parse.c @@ -0,0 +1,1042 @@ +/* GStreamer H.264 Parser + * Copyright (C) <2010> Mark Nauwelaerts + * Copyright (C) <2010> Collabora Multimedia + * Copyright (C) <2010> Nokia Corporation + * + * Some bits C-c,C-v'ed and s/4/3 from h264parse: + * (C) 2005 Michal Benes + * (C) 2008 Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "h264parse.h" + +#include + +GST_DEBUG_CATEGORY_EXTERN (h264_parse_debug); +#define GST_CAT_DEFAULT h264_parse_debug + +/* simple bitstream parser, automatically skips over + * emulation_prevention_three_bytes. */ +typedef struct +{ + const guint8 *orig_data; + const guint8 *data; + const guint8 *end; + /* bitpos in the cache of next bit */ + gint head; + /* cached bytes */ + guint64 cache; +} GstNalBs; + +static void +gst_nal_bs_init (GstNalBs * bs, const guint8 * data, guint size) +{ + bs->orig_data = data; + bs->data = data; + bs->end = data + size; + bs->head = 0; + /* fill with something other than 0 to detect emulation prevention bytes */ + bs->cache = 0xffffffff; +} + +static inline void +gst_nal_bs_get_data (GstNalBs * bs, const guint8 ** data, guint * size) +{ + *data = bs->orig_data; + *size = bs->end - bs->orig_data; +} + +static guint32 +gst_nal_bs_read (GstNalBs * bs, guint n) +{ + guint32 res = 0; + gint shift; + + if (n == 0) + return res; + + /* fill up the cache if we need to */ + while (bs->head < n) { + guint8 byte; + gboolean check_three_byte; + + check_three_byte = TRUE; + next_byte: + if (bs->data >= bs->end) { + /* we're at the end, can't produce more than head number of bits */ + n = bs->head; + break; + } + /* get the byte, this can be an emulation_prevention_three_byte that we need + * to ignore. */ + byte = *bs->data++; + if (check_three_byte && byte == 0x03 && ((bs->cache & 0xffff) == 0)) { + /* next byte goes unconditionally to the cache, even if it's 0x03 */ + check_three_byte = FALSE; + goto next_byte; + } + /* shift bytes in cache, moving the head bits of the cache left */ + bs->cache = (bs->cache << 8) | byte; + bs->head += 8; + } + + /* bring the required bits down and truncate */ + if ((shift = bs->head - n) > 0) + res = bs->cache >> shift; + else + res = bs->cache; + + /* mask out required bits */ + if (n < 32) + res &= (1 << n) - 1; + + bs->head = shift; + + return res; +} + +static gboolean +gst_nal_bs_eos (GstNalBs * bs) +{ + return (bs->data >= bs->end) && (bs->head == 0); +} + +/* read unsigned Exp-Golomb code */ +static gint +gst_nal_bs_read_ue (GstNalBs * bs) +{ + gint i = 0; + + while (gst_nal_bs_read (bs, 1) == 0 && !gst_nal_bs_eos (bs) && i < 32) + i++; + + return ((1 << i) - 1 + gst_nal_bs_read (bs, i)); +} + +/* read signed Exp-Golomb code */ +static gint +gst_nal_bs_read_se (GstNalBs * bs) +{ + gint i = 0; + + i = gst_nal_bs_read_ue (bs); + /* (-1)^(i+1) Ceil (i / 2) */ + i = (i + 1) / 2 * (i & 1 ? 1 : -1); + + return i; +} + +/* end parser helper */ + +static void +gst_h264_params_store_nal (GstH264Params * params, GstBuffer ** store, gint id, + GstNalBs * bs) +{ + const guint8 *data; + GstBuffer *buf; + guint size; + + g_return_if_fail (MAX_SPS_COUNT == MAX_PPS_COUNT); + + if (id >= MAX_SPS_COUNT) { + GST_DEBUG_OBJECT (params->el, + "unable to store nal, id out-of-range %d", id); + return; + } + + gst_nal_bs_get_data (bs, &data, &size); + buf = gst_buffer_new_and_alloc (size); + memcpy (GST_BUFFER_DATA (buf), data, size); + gst_buffer_replace (store + id, buf); +} + +static GstH264ParamsSPS * +gst_h264_params_get_sps (GstH264Params * params, guint8 sps_id, gboolean set) +{ + GstH264ParamsSPS *sps; + + g_return_val_if_fail (params != NULL, NULL); + + if (G_UNLIKELY (sps_id >= MAX_SPS_COUNT)) { + GST_WARNING_OBJECT (params->el, + "requested sps_id=%04x out of range", sps_id); + return NULL; + } + + sps = ¶ms->sps_buffers[sps_id]; + if (set) { + if (sps->valid) { + params->sps = sps; + } else { + GST_WARNING_OBJECT (params->el, "invalid sps not selected"); + params->sps = NULL; + sps = NULL; + } + } + + return sps; +} + +static GstH264ParamsPPS * +gst_h264_params_get_pps (GstH264Params * params, guint8 pps_id, gboolean set) +{ + GstH264ParamsPPS *pps; + + g_return_val_if_fail (params != NULL, NULL); + + if (G_UNLIKELY (pps_id >= MAX_PPS_COUNT)) { + GST_WARNING_OBJECT (params->el, + "requested pps_id=%04x out of range", pps_id); + return NULL; + } + + pps = ¶ms->pps_buffers[pps_id]; + if (set) { + if (pps->valid) { + params->pps = pps; + } else { + GST_WARNING_OBJECT (params->el, "invalid pps not selected"); + params->pps = NULL; + pps = NULL; + } + } + + return pps; +} + +static gboolean +gst_h264_params_decode_sps_vui_hrd (GstH264Params * params, + GstH264ParamsSPS * sps, GstNalBs * bs) +{ + gint sched_sel_idx; + + sps->cpb_cnt_minus1 = gst_nal_bs_read_ue (bs); + if (sps->cpb_cnt_minus1 > 31U) { + GST_WARNING_OBJECT (params->el, "cpb_cnt_minus1 = %d out of range", + sps->cpb_cnt_minus1); + return FALSE; + } + + /* bit_rate_scale */ + gst_nal_bs_read (bs, 4); + /* cpb_size_scale */ + gst_nal_bs_read (bs, 4); + + for (sched_sel_idx = 0; sched_sel_idx <= sps->cpb_cnt_minus1; sched_sel_idx++) { + /* bit_rate_value_minus1 */ + gst_nal_bs_read_ue (bs); + /* cpb_size_value_minus1 */ + gst_nal_bs_read_ue (bs); + /* cbr_flag */ + gst_nal_bs_read (bs, 1); + } + + sps->initial_cpb_removal_delay_length_minus1 = gst_nal_bs_read (bs, 5); + sps->cpb_removal_delay_length_minus1 = gst_nal_bs_read (bs, 5); + sps->dpb_output_delay_length_minus1 = gst_nal_bs_read (bs, 5); + sps->time_offset_length_minus1 = gst_nal_bs_read (bs, 5); + + return TRUE; +} + +static gboolean +gst_h264_params_decode_sps_vui (GstH264Params * params, GstH264ParamsSPS * sps, + GstNalBs * bs) +{ + if (G_UNLIKELY (!sps)) + return FALSE; + + /* aspect_ratio_info_present_flag */ + if (gst_nal_bs_read (bs, 1)) { + /* aspect_ratio_idc */ + if (gst_nal_bs_read (bs, 8) == 255) { + /* Extended_SAR */ + /* sar_width */ + gst_nal_bs_read (bs, 16); + /* sar_height */ + gst_nal_bs_read (bs, 16); + } + } + + /* overscan_info_present_flag */ + if (gst_nal_bs_read (bs, 1)) { + /* overscan_appropriate_flag */ + gst_nal_bs_read (bs, 1); + } + + /* video_signal_type_present_flag */ + if (gst_nal_bs_read (bs, 1)) { + /* video_format */ + gst_nal_bs_read (bs, 3); + /* video_full_range_flag */ + gst_nal_bs_read (bs, 1); + + /* colour_description_present_flag */ + if (gst_nal_bs_read (bs, 1)) { + /* colour_primaries */ + gst_nal_bs_read (bs, 8); + /* transfer_characteristics */ + gst_nal_bs_read (bs, 8); + /* matrix_coefficients */ + gst_nal_bs_read (bs, 8); + } + } + + /* chroma_loc_info_present_flag */ + if (gst_nal_bs_read (bs, 1)) { + /* chroma_sample_loc_type_top_field */ + gst_nal_bs_read_ue (bs); + /* chroma_sample_loc_type_bottom_field */ + gst_nal_bs_read_ue (bs); + } + + sps->timing_info_present_flag = gst_nal_bs_read (bs, 1); + if (sps->timing_info_present_flag) { + guint32 num_units_in_tick = gst_nal_bs_read (bs, 32); + guint32 time_scale = gst_nal_bs_read (bs, 32); + + /* If any of these parameters = 0, discard all timing_info */ + if (time_scale == 0) { + GST_WARNING_OBJECT (params->el, + "time_scale = 0 detected in stream (incompliant to H.264 E.2.1)." + " Discarding related info."); + } else if (num_units_in_tick == 0) { + GST_WARNING_OBJECT (params->el, + "num_units_in_tick = 0 detected in stream (incompliant to H.264 E.2.1)." + " Discarding related info."); + } else { + sps->num_units_in_tick = num_units_in_tick; + sps->time_scale = time_scale; + sps->fixed_frame_rate_flag = gst_nal_bs_read (bs, 1); + GST_LOG_OBJECT (params->el, "timing info: dur=%d/%d fixed=%d", + num_units_in_tick, time_scale, sps->fixed_frame_rate_flag); + } + } + + sps->nal_hrd_parameters_present_flag = gst_nal_bs_read (bs, 1); + if (sps->nal_hrd_parameters_present_flag) { + gst_h264_params_decode_sps_vui_hrd (params, sps, bs); + } + sps->vcl_hrd_parameters_present_flag = gst_nal_bs_read (bs, 1); + if (sps->vcl_hrd_parameters_present_flag) { + gst_h264_params_decode_sps_vui_hrd (params, sps, bs); + } + if (sps->nal_hrd_parameters_present_flag + || sps->vcl_hrd_parameters_present_flag) { + gst_nal_bs_read (bs, 1); /* low_delay_hrd_flag */ + } + + sps->pic_struct_present_flag = gst_nal_bs_read (bs, 1); + + /* derive framerate */ + /* FIXME verify / also handle other cases */ + if (sps->fixed_frame_rate_flag && sps->frame_mbs_only_flag && + !sps->pic_struct_present_flag) { + sps->fps_num = sps->time_scale; + sps->fps_den = sps->num_units_in_tick; + /* picture is a frame = 2 fields */ + sps->fps_den *= 2; + GST_LOG_OBJECT (params->el, "framerate %d/%d", sps->fps_num, sps->fps_den); + } + + return TRUE; +} + +static gboolean +gst_h264_params_decode_sps (GstH264Params * params, GstNalBs * bs) +{ + guint8 profile_idc, level_idc; + guint8 sps_id; + GstH264ParamsSPS *sps = NULL; + guint subwc[] = { 1, 2, 2, 1 }; + guint subhc[] = { 1, 2, 1, 1 }; + guint chroma; + guint fc_top, fc_bottom, fc_left, fc_right; + gint width, height; + + profile_idc = gst_nal_bs_read (bs, 8); + /* constraint_set0_flag */ + gst_nal_bs_read (bs, 1); + /* constraint_set1_flag */ + gst_nal_bs_read (bs, 1); + /* constraint_set1_flag */ + gst_nal_bs_read (bs, 1); + /* constraint_set1_flag */ + gst_nal_bs_read (bs, 1); + /* reserved */ + gst_nal_bs_read (bs, 4); + level_idc = gst_nal_bs_read (bs, 8); + + sps_id = gst_nal_bs_read_ue (bs); + sps = gst_h264_params_get_sps (params, sps_id, FALSE); + if (G_UNLIKELY (sps == NULL)) + return FALSE; + + gst_h264_params_store_nal (params, params->sps_nals, sps_id, bs); + + /* could be redefined mid stream, arrange for clear state */ + memset (sps, 0, sizeof (*sps)); + + GST_LOG_OBJECT (params->el, "sps id %d", sps_id); + sps->valid = TRUE; + /* validate and force activate this one if it is the first SPS we see */ + if (params->sps == NULL) + params->sps = sps; + + sps->profile_idc = profile_idc; + sps->level_idc = level_idc; + + if (profile_idc == 100 || profile_idc == 110 || profile_idc == 122 + || profile_idc == 244 || profile_idc == 44 || + profile_idc == 83 || profile_idc == 86) { + gint scp_flag = 0; + + /* chroma_format_idc */ + if ((chroma = gst_nal_bs_read_ue (bs)) == 3) { + /* separate_colour_plane_flag */ + sps->scp_flag = gst_nal_bs_read (bs, 1); + } + /* bit_depth_luma_minus8 */ + gst_nal_bs_read_ue (bs); + /* bit_depth_chroma_minus8 */ + gst_nal_bs_read_ue (bs); + /* qpprime_y_zero_transform_bypass_flag */ + gst_nal_bs_read (bs, 1); + /* seq_scaling_matrix_present_flag */ + if (gst_nal_bs_read (bs, 1)) { + gint i, j, m, d; + + m = (chroma != 3) ? 8 : 12; + for (i = 0; i < m; i++) { + /* seq_scaling_list_present_flag[i] */ + d = gst_nal_bs_read (bs, 1); + if (d) { + gint lastScale = 8, nextScale = 8, deltaScale; + + j = (i < 6) ? 16 : 64; + for (; j > 0; j--) { + if (nextScale != 0) { + deltaScale = gst_nal_bs_read_se (bs); + nextScale = (lastScale + deltaScale + 256) % 256; + } + if (nextScale != 0) + lastScale = nextScale; + } + } + } + } + if (scp_flag) + chroma = 0; + } else { + /* inferred value */ + chroma = 1; + } + + /* between 0 and 12 */ + sps->log2_max_frame_num_minus4 = gst_nal_bs_read_ue (bs); + if (sps->log2_max_frame_num_minus4 > 12) { + GST_WARNING_OBJECT (params->el, + "log2_max_frame_num_minus4 = %d out of range" " [0,12]", + sps->log2_max_frame_num_minus4); + return FALSE; + } + + sps->pic_order_cnt_type = gst_nal_bs_read_ue (bs); + if (sps->pic_order_cnt_type == 0) { + sps->log2_max_pic_order_cnt_lsb_minus4 = gst_nal_bs_read_ue (bs); + } else if (sps->pic_order_cnt_type == 1) { + gint d; + + /* delta_pic_order_always_zero_flag */ + gst_nal_bs_read (bs, 1); + /* offset_for_non_ref_pic */ + gst_nal_bs_read_ue (bs); + /* offset_for_top_to_bottom_field */ + gst_nal_bs_read_ue (bs); + /* num_ref_frames_in_pic_order_cnt_cycle */ + d = gst_nal_bs_read_ue (bs); + for (; d > 0; d--) { + /* offset_for_ref_frame[i] */ + gst_nal_bs_read_ue (bs); + } + } + + /* max_num_ref_frames */ + gst_nal_bs_read_ue (bs); + /* gaps_in_frame_num_value_allowed_flag */ + gst_nal_bs_read (bs, 1); + /* pic_width_in_mbs_minus1 */ + width = gst_nal_bs_read_ue (bs); + /* pic_height_in_map_units_minus1 */ + height = gst_nal_bs_read_ue (bs); + + sps->frame_mbs_only_flag = gst_nal_bs_read (bs, 1); + if (!sps->frame_mbs_only_flag) { + /* mb_adaptive_frame_field_flag */ + gst_nal_bs_read (bs, 1); + } + + width++; + width *= 16; + height++; + height *= 16 * (2 - sps->frame_mbs_only_flag); + + /* direct_8x8_inference_flag */ + gst_nal_bs_read (bs, 1); + /* frame_cropping_flag */ + if (gst_nal_bs_read (bs, 1)) { + /* frame_crop_left_offset */ + fc_left = gst_nal_bs_read_ue (bs); + /* frame_crop_right_offset */ + fc_right = gst_nal_bs_read_ue (bs); + /* frame_crop_top_offset */ + fc_top = gst_nal_bs_read_ue (bs); + /* frame_crop_bottom_offset */ + fc_bottom = gst_nal_bs_read_ue (bs); + } else { + fc_left = fc_right = fc_top = fc_bottom = 0; + } + + GST_LOG_OBJECT (params->el, "decoding SPS: profile_idc = %d, " + "level_idc = %d, sps_id = %d, pic_order_cnt_type = %d, " + "frame_mbs_only_flag = %d", + sps->profile_idc, sps->level_idc, sps_id, sps->pic_order_cnt_type, + sps->frame_mbs_only_flag); + + /* calculate width and height */ + GST_LOG_OBJECT (params->el, "initial width=%d, height=%d", width, height); + GST_LOG_OBJECT (params->el, "crop (%d,%d)(%d,%d)", + fc_left, fc_top, fc_right, fc_bottom); + if (chroma > 3) { + GST_LOG_OBJECT (params->el, "chroma=%d in SPS is out of range", chroma); + return FALSE; + } + width -= (fc_left + fc_right) * subwc[chroma]; + height -= + (fc_top + fc_bottom) * subhc[chroma] * (2 - sps->frame_mbs_only_flag); + if (width < 0 || height < 0) { + GST_WARNING_OBJECT (params->el, "invalid width/height in SPS"); + return FALSE; + } + GST_LOG_OBJECT (params->el, "final width=%u, height=%u", width, height); + sps->width = width; + sps->height = height; + + sps->vui_parameters_present_flag = gst_nal_bs_read (bs, 1); + if (sps->vui_parameters_present_flag) { + /* discard parsing problem */ + gst_h264_params_decode_sps_vui (params, sps, bs); + } + + return TRUE; +} + +static gboolean +gst_h264_params_decode_pps (GstH264Params * params, GstNalBs * bs) +{ + guint8 pps_id; + GstH264ParamsPPS *pps = NULL; + + pps_id = gst_nal_bs_read_ue (bs); + + pps = gst_h264_params_get_pps (params, pps_id, FALSE); + if (G_UNLIKELY (pps == NULL)) + return FALSE; + + /* validate and set */ + pps->valid = TRUE; + params->pps = pps; + + gst_h264_params_store_nal (params, params->pps_nals, pps_id, bs); + + pps->sps_id = gst_nal_bs_read_ue (bs); + GST_LOG_OBJECT (params->el, "pps %d referencing sps %d", pps_id, pps->sps_id); + + /* activate referenced sps */ + if (!gst_h264_params_get_sps (params, pps->sps_id, TRUE)) + return FALSE; + + /* not parsing the rest for the time being */ + return TRUE; +} + +static gboolean +gst_h264_params_decode_sei_buffering_period (GstH264Params * params, + GstNalBs * bs) +{ +#ifdef EXTRA_PARSE + guint8 sps_id; + gint sched_sel_idx; + GstH264ParamsSPS *sps; + + sps_id = gst_nal_bs_read_ue (bs); + sps = gst_h264_params_get_sps (params, sps_id, TRUE); + if (G_UNLIKELY (sps == NULL)) + return FALSE; + + if (sps->nal_hrd_parameters_present_flag) { + for (sched_sel_idx = 0; sched_sel_idx <= sps->cpb_cnt_minus1; + sched_sel_idx++) { + params->initial_cpb_removal_delay[sched_sel_idx] + = gst_nal_bs_read (bs, + sps->initial_cpb_removal_delay_length_minus1 + 1); + /* initial_cpb_removal_delay_offset */ + gst_nal_bs_read (bs, sps->initial_cpb_removal_delay_length_minus1 + 1); + } + } + + if (sps->vcl_hrd_parameters_present_flag) { + for (sched_sel_idx = 0; sched_sel_idx <= sps->cpb_cnt_minus1; + sched_sel_idx++) { + params->initial_cpb_removal_delay[sched_sel_idx] + = gst_nal_bs_read (bs, + sps->initial_cpb_removal_delay_length_minus1 + 1); + /* initial_cpb_removal_delay_offset */ + gst_nal_bs_read (bs, sps->initial_cpb_removal_delay_length_minus1 + 1); + } + } +#endif + + if (params->ts_trn_nb == GST_CLOCK_TIME_NONE || + params->dts == GST_CLOCK_TIME_NONE) + params->ts_trn_nb = 0; + else + params->ts_trn_nb = params->dts; + + GST_LOG_OBJECT (params->el, + "new buffering period; ts_trn_nb updated: %" GST_TIME_FORMAT, + GST_TIME_ARGS (params->ts_trn_nb)); + + return 0; +} + +static gboolean +gst_h264_params_decode_sei_picture_timing (GstH264Params * params, + GstNalBs * bs) +{ + GstH264ParamsSPS *sps = params->sps; + + if (sps == NULL) { + GST_WARNING_OBJECT (params->el, + "SPS == NULL; delayed decoding of picture timing info not implemented "); + return FALSE; + } + + if (sps->nal_hrd_parameters_present_flag + || sps->vcl_hrd_parameters_present_flag) { + params->sei_cpb_removal_delay = + gst_nal_bs_read (bs, sps->cpb_removal_delay_length_minus1 + 1); + /* sei_dpb_output_delay */ + gst_nal_bs_read (bs, sps->dpb_output_delay_length_minus1 + 1); + } + + if (sps->pic_struct_present_flag) { +#ifdef EXTRA_PARSE + /* pic_struct to NumClockTS lookup table */ + static const guint8 sei_num_clock_ts_table[9] = + { 1, 1, 1, 2, 2, 3, 3, 2, 3 }; + guint i, num_clock_ts; + guint sei_ct_type = 0; +#endif + + params->sei_pic_struct = gst_nal_bs_read (bs, 4); + GST_LOG_OBJECT (params, "pic_struct:%d", params->sei_pic_struct); + if (params->sei_pic_struct > SEI_PIC_STRUCT_FRAME_TRIPLING) + return FALSE; + +#ifdef EXTRA_PARSE + num_clock_ts = sei_num_clock_ts_table[params->sei_pic_struct]; + + for (i = 0; i < num_clock_ts; i++) { + /* clock_timestamp_flag */ + if (gst_nal_bs_read (bs, 1)) { + guint full_timestamp_flag; + + sei_ct_type |= 1 << gst_nal_bs_read (bs, 2); + /* nuit_field_based_flag */ + gst_nal_bs_read (bs, 1); + /* counting_type */ + gst_nal_bs_read (bs, 5); + full_timestamp_flag = gst_nal_bs_read (bs, 1); + /* discontinuity_flag */ + gst_nal_bs_read (bs, 1); + /* cnt_dropped_flag */ + gst_nal_bs_read (bs, 1); + /* n_frames */ + gst_nal_bs_read (bs, 8); + if (full_timestamp_flag) { + /* seconds_value 0..59 */ + gst_nal_bs_read (bs, 6); + /* minutes_value 0..59 */ + gst_nal_bs_read (bs, 6); + /* hours_value 0..23 */ + gst_nal_bs_read (bs, 5); + } else { + /* seconds_flag */ + if (gst_nal_bs_read (bs, 1)) { + /* seconds_value range 0..59 */ + gst_nal_bs_read (bs, 6); + /* minutes_flag */ + if (gst_nal_bs_read (bs, 1)) { + /* minutes_value 0..59 */ + gst_nal_bs_read (bs, 6); + /* hours_flag */ + if (gst_nal_bs_read (bs, 1)) + /* hours_value 0..23 */ + gst_nal_bs_read (bs, 5); + } + } + } + if (sps->time_offset_length_minus1 >= 0) { + /* time_offset */ + gst_nal_bs_read (bs, sps->time_offset_length_minus1 + 1); + } + } + } + + GST_LOG_OBJECT (params, "ct_type:%X", sei_ct_type); +#endif + } + + return TRUE; +} + +static gboolean +gst_h264_params_decode_sei (GstH264Params * params, GstNalBs * bs) +{ + guint8 tmp; + GstH264ParamsSEIPayloadType payloadType = 0; + gint8 payloadSize = 0; + + do { + tmp = gst_nal_bs_read (bs, 8); + payloadType += tmp; + } while (tmp == 255); + do { + tmp = gst_nal_bs_read (bs, 8); + payloadSize += tmp; + } while (tmp == 255); + + GST_LOG_OBJECT (params->el, + "SEI message received: payloadType = %d, payloadSize = %d bytes", + payloadType, payloadSize); + + switch (payloadType) { + case SEI_BUF_PERIOD: + if (!gst_h264_params_decode_sei_buffering_period (params, bs)) + return FALSE; + break; + case SEI_PIC_TIMING: + /* TODO: According to H264 D2.2 Note1, it might be the case that the + * picture timing SEI message is encountered before the corresponding SPS + * is specified. Need to hold down the message and decode it later. */ + if (!gst_h264_params_decode_sei_picture_timing (params, bs)) + return FALSE; + break; + default: + GST_LOG_OBJECT (params->el, + "SEI message of payloadType = %d is received but not parsed", + payloadType); + break; + } + + return TRUE; +} + +static gboolean +gst_h264_params_decode_slice_header (GstH264Params * params, GstNalBs * bs) +{ + GstH264ParamsSPS *sps; + GstH264ParamsPPS *pps; + guint8 pps_id; + + params->first_mb_in_slice = gst_nal_bs_read_ue (bs); + params->slice_type = gst_nal_bs_read_ue (bs); + + pps_id = gst_nal_bs_read_ue (bs); + GST_LOG_OBJECT (params->el, "slice header references pps id %d", pps_id); + pps = gst_h264_params_get_pps (params, pps_id, TRUE); + if (G_UNLIKELY (pps == NULL)) + return FALSE; + sps = gst_h264_params_get_sps (params, pps->sps_id, TRUE); + if (G_UNLIKELY (sps == NULL)) + return FALSE; + + if (sps->scp_flag) { + /* colour_plane_id */ + gst_nal_bs_read (bs, 2); + } + + /* frame num */ + gst_nal_bs_read (bs, sps->log2_max_pic_order_cnt_lsb_minus4 + 4); + + if (!sps->frame_mbs_only_flag) { + params->field_pic_flag = gst_nal_bs_read (bs, 1); + if (params->field_pic_flag) + params->bottom_field_flag = gst_nal_bs_read (bs, 1); + } + + /* not parsing the rest for the time being */ + return TRUE; +} + +/* only payload in @data */ +gboolean +gst_h264_params_parse_nal (GstH264Params * params, guint8 * data, gint size) +{ + GstH264ParamsNalUnitType nal_type; + GstNalBs bs; + gint nal_ref_idc; + gboolean res = TRUE; + + g_return_val_if_fail (params != NULL, FALSE); + g_return_val_if_fail (data != NULL, FALSE); + g_return_val_if_fail (size != 0, FALSE); + + nal_type = (data[0] & 0x1f); + nal_ref_idc = (data[0] & 0x60) >> 5; + + GST_LOG_OBJECT (params->el, "NAL type: %d, ref_idc: %d", nal_type, + nal_ref_idc); + + gst_nal_bs_init (&bs, data + 1, size - 1); + /* optimality HACK */ + bs.orig_data = data; + + /* first parse some things needed to get to the frame type */ + switch (nal_type) { + case NAL_SLICE: + case NAL_SLICE_DPA: + case NAL_SLICE_DPB: + case NAL_SLICE_DPC: + case NAL_SLICE_IDR: + { + gint first_mb_in_slice, slice_type; + + gst_h264_params_decode_slice_header (params, &bs); + first_mb_in_slice = params->first_mb_in_slice; + slice_type = params->slice_type; + + GST_LOG_OBJECT (params->el, "first MB: %d, slice type: %d", + first_mb_in_slice, slice_type); + + switch (slice_type) { + case 0: + case 5: + case 3: + case 8: /* SP */ + /* P frames */ + GST_LOG_OBJECT (params->el, "we have a P slice"); + break; + case 1: + case 6: + /* B frames */ + GST_LOG_OBJECT (params->el, "we have a B slice"); + break; + case 2: + case 7: + case 4: + case 9: + /* I frames */ + GST_LOG_OBJECT (params->el, "we have an I slice"); + break; + } + break; + } + case NAL_SEI: + GST_LOG_OBJECT (params->el, "SEI NAL"); + res = gst_h264_params_decode_sei (params, &bs); + break; + case NAL_SPS: + GST_LOG_OBJECT (params->el, "SPS NAL"); + res = gst_h264_params_decode_sps (params, &bs); + break; + case NAL_PPS: + GST_LOG_OBJECT (params->el, "PPS NAL"); + res = gst_h264_params_decode_pps (params, &bs); + break; + case NAL_AU_DELIMITER: + GST_LOG_OBJECT (params->el, "AU delimiter NAL"); + break; + default: + GST_LOG_OBJECT (params->el, "unparsed NAL"); + break; + } + + return res; +} + +void +gst_h264_params_get_timestamp (GstH264Params * params, + GstClockTime * out_ts, GstClockTime * out_dur, gboolean frame) +{ + GstH264ParamsSPS *sps = params->sps; + GstClockTime upstream; + gint duration = 1; + + g_return_if_fail (out_dur != NULL); + g_return_if_fail (out_ts != NULL); + + upstream = *out_ts; + + if (!frame) { + GST_LOG_OBJECT (params->el, "no frame data -> 0 duration"); + *out_dur = 0; + goto exit; + } else { + *out_ts = upstream; + } + + if (!sps) { + GST_DEBUG_OBJECT (params->el, "referred SPS invalid"); + goto exit; + } else if (!sps->timing_info_present_flag) { + GST_DEBUG_OBJECT (params->el, + "unable to compute timestamp: timing info not present"); + goto exit; + } else if (sps->time_scale == 0) { + GST_DEBUG_OBJECT (params->el, + "unable to compute timestamp: time_scale = 0 " + "(this is forbidden in spec; bitstream probably contains error)"); + goto exit; + } + + if (sps->pic_struct_present_flag && params->sei_pic_struct != (guint8) - 1) { + /* Note that when h264parse->sei_pic_struct == -1 (unspecified), there + * are ways to infer its value. This is related to computing the + * TopFieldOrderCnt and BottomFieldOrderCnt, which looks + * complicated and thus not implemented for the time being. Yet + * the value we have here is correct for many applications + */ + switch (params->sei_pic_struct) { + case SEI_PIC_STRUCT_TOP_FIELD: + case SEI_PIC_STRUCT_BOTTOM_FIELD: + duration = 1; + break; + case SEI_PIC_STRUCT_FRAME: + case SEI_PIC_STRUCT_TOP_BOTTOM: + case SEI_PIC_STRUCT_BOTTOM_TOP: + duration = 2; + break; + case SEI_PIC_STRUCT_TOP_BOTTOM_TOP: + case SEI_PIC_STRUCT_BOTTOM_TOP_BOTTOM: + duration = 3; + break; + case SEI_PIC_STRUCT_FRAME_DOUBLING: + duration = 4; + break; + case SEI_PIC_STRUCT_FRAME_TRIPLING: + duration = 6; + break; + default: + GST_DEBUG_OBJECT (params, + "h264parse->sei_pic_struct of unknown value %d. Not parsed", + params->sei_pic_struct); + break; + } + } else { + duration = params->field_pic_flag ? 1 : 2; + } + + GST_LOG_OBJECT (params->el, "frame tick duration %d", duration); + + /* + * h264parse.264 C.1.2 Timing of coded picture removal (equivalent to DTS): + * Tr,n(0) = initial_cpb_removal_delay[ SchedSelIdx ] / 90000 + * Tr,n(n) = Tr,n(nb) + Tc * cpb_removal_delay(n) + * where + * Tc = num_units_in_tick / time_scale + */ + + if (params->ts_trn_nb != GST_CLOCK_TIME_NONE) { + GST_LOG_OBJECT (params->el, "buffering based ts"); + /* buffering period is present */ + if (upstream != GST_CLOCK_TIME_NONE) { + /* If upstream timestamp is valid, we respect it and adjust current + * reference point */ + params->ts_trn_nb = upstream - + (GstClockTime) gst_util_uint64_scale_int + (params->sei_cpb_removal_delay * GST_SECOND, + sps->num_units_in_tick, sps->time_scale); + } else { + /* If no upstream timestamp is given, we write in new timestamp */ + upstream = params->dts = params->ts_trn_nb + + (GstClockTime) gst_util_uint64_scale_int + (params->sei_cpb_removal_delay * GST_SECOND, + sps->num_units_in_tick, sps->time_scale); + } + } else { + GstClockTime dur; + + GST_LOG_OBJECT (params->el, "duration based ts"); + /* naive method: no removal delay specified + * track upstream timestamp and provide best guess frame duration */ + dur = gst_util_uint64_scale_int (duration * GST_SECOND, + sps->num_units_in_tick, sps->time_scale); + /* sanity check */ + if (dur < GST_MSECOND) { + GST_DEBUG_OBJECT (params->el, "discarding dur %" GST_TIME_FORMAT, + GST_TIME_ARGS (dur)); + } else { + *out_dur = dur; + } + } + +exit: + if (GST_CLOCK_TIME_IS_VALID (upstream)) + *out_ts = params->dts = upstream; + + if (GST_CLOCK_TIME_IS_VALID (*out_dur) && + GST_CLOCK_TIME_IS_VALID (params->dts)) + params->dts += *out_dur; +} + +void +gst_h264_params_create (GstH264Params ** _params, GstElement * element) +{ + GstH264Params *params; + + g_return_if_fail (_params != NULL); + + params = g_new0 (GstH264Params, 1); + params->el = element; + + params->dts = GST_CLOCK_TIME_NONE; + params->ts_trn_nb = GST_CLOCK_TIME_NONE; + + *_params = params; +} + +void +gst_h264_params_free (GstH264Params * params) +{ + gint i; + + g_return_if_fail (params != NULL); + + for (i = 0; i < MAX_SPS_COUNT; i++) + gst_buffer_replace (¶ms->sps_nals[i], NULL); + for (i = 0; i < MAX_PPS_COUNT; i++) + gst_buffer_replace (¶ms->sps_nals[i], NULL); + + g_free (params); +} diff --git a/gst/videoparsers/h264parse.h b/gst/videoparsers/h264parse.h new file mode 100644 index 0000000000..141564bcef --- /dev/null +++ b/gst/videoparsers/h264parse.h @@ -0,0 +1,186 @@ +/* GStreamer H.264 Parser + * Copyright (C) <2010> Mark Nauwelaerts + * Copyright (C) <2010> Collabora Multimedia + * Copyright (C) <2010> Nokia Corporation + * + * Some bits C-c,C-v'ed and s/4/3 from h264parse: + * (C) 2005 Michal Benes + * (C) 2008 Wim Taymans + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef __GST_H264_PARAMS_H__ +#define __GST_H264_PARAMS_H__ + +#include + +G_BEGIN_DECLS + +typedef enum +{ + NAL_UNKNOWN = 0, + NAL_SLICE = 1, + NAL_SLICE_DPA = 2, + NAL_SLICE_DPB = 3, + NAL_SLICE_DPC = 4, + NAL_SLICE_IDR = 5, + NAL_SEI = 6, + NAL_SPS = 7, + NAL_PPS = 8, + NAL_AU_DELIMITER = 9, + NAL_SEQ_END = 10, + NAL_STREAM_END = 11, + NAL_FILTER_DATA = 12 +} GstH264ParamsNalUnitType; + +/* SEI type */ +typedef enum +{ + SEI_BUF_PERIOD = 0, + SEI_PIC_TIMING = 1 + /* and more... */ +} GstH264ParamsSEIPayloadType; + +/* SEI pic_struct type */ +typedef enum +{ + SEI_PIC_STRUCT_FRAME = 0, + SEI_PIC_STRUCT_TOP_FIELD = 1, + SEI_PIC_STRUCT_BOTTOM_FIELD = 2, + SEI_PIC_STRUCT_TOP_BOTTOM = 3, + SEI_PIC_STRUCT_BOTTOM_TOP = 4, + SEI_PIC_STRUCT_TOP_BOTTOM_TOP = 5, + SEI_PIC_STRUCT_BOTTOM_TOP_BOTTOM = 6, + SEI_PIC_STRUCT_FRAME_DOUBLING = 7, + SEI_PIC_STRUCT_FRAME_TRIPLING = 8 +} GstH264ParamsSEIPicStructType; + +typedef struct _GstH264Params GstH264Params; +typedef struct _GstH264ParamsSPS GstH264ParamsSPS; +typedef struct _GstH264ParamsPPS GstH264ParamsPPS; + +#define MAX_SPS_COUNT 32 +#define MAX_PPS_COUNT 32 + +/* SPS: sequential parameter sets */ +struct _GstH264ParamsSPS +{ + gboolean valid; + + /* raw values */ + guint8 profile_idc; + guint8 level_idc; + + guint8 sps_id; + + guint8 pic_order_cnt_type; + + guint8 log2_max_frame_num_minus4; + gboolean frame_mbs_only_flag; + guint8 log2_max_pic_order_cnt_lsb_minus4; + + gboolean frame_cropping_flag; + gboolean scp_flag; + + /* VUI parameters */ + gboolean vui_parameters_present_flag; + + gboolean timing_info_present_flag; + guint32 num_units_in_tick; + guint32 time_scale; + gboolean fixed_frame_rate_flag; + + gboolean nal_hrd_parameters_present_flag; + gboolean vcl_hrd_parameters_present_flag; + + /* hrd parameters */ + guint8 cpb_cnt_minus1; + gint initial_cpb_removal_delay_length_minus1; + gint cpb_removal_delay_length_minus1; + gint dpb_output_delay_length_minus1; + gboolean time_offset_length_minus1; + + gboolean pic_struct_present_flag; + + /* ... and probably more ... */ + + /* derived values */ + gint width, height; + gint fps_num, fps_den; +}; + +/* PPS: pic parameter sets */ +struct _GstH264ParamsPPS +{ + gboolean valid; + + /* raw values */ + guint8 pps_id; + guint8 sps_id; +}; + +struct _GstH264Params +{ + /* debug purposes */ + GstElement *el; + + /* SPS: sequential parameter set */ + GstH264ParamsSPS sps_buffers[MAX_SPS_COUNT]; + /* current SPS; most recent one in stream or referenced by PPS */ + GstH264ParamsSPS *sps; + /* PPS: sequential parameter set */ + GstH264ParamsPPS pps_buffers[MAX_PPS_COUNT]; + /* current PPS; most recent one in stream */ + GstH264ParamsPPS *pps; + + /* extracted from slice header or otherwise relevant nal */ + guint8 first_mb_in_slice; + guint8 slice_type; + gboolean field_pic_flag; + gboolean bottom_field_flag; + + /* SEI: supplemental enhancement messages */ +#ifdef EXTRA_PARSE + /* buffering period */ + guint32 initial_cpb_removal_delay[32]; +#endif + /* picture timing */ + guint32 sei_cpb_removal_delay; + guint8 sei_pic_struct; + /* And more... */ + + /* cached timestamps */ + /* (trying to) track upstream dts and interpolate */ + GstClockTime dts; + /* dts at start of last buffering period */ + GstClockTime ts_trn_nb; + + /* collected SPS and PPS NALUs */ + GstBuffer *sps_nals[MAX_SPS_COUNT]; + GstBuffer *pps_nals[MAX_PPS_COUNT]; +}; + +gboolean gst_h264_params_parse_nal (GstH264Params * params, guint8 * nal, gint size); +void gst_h264_params_get_timestamp (GstH264Params * params, + GstClockTime * out_ts, GstClockTime * out_dur, + gboolean frame); +void gst_h264_params_create (GstH264Params ** _params, GstElement * element); +void gst_h264_params_free (GstH264Params * params); + + +G_END_DECLS +#endif diff --git a/gst/videoparsers/plugin.c b/gst/videoparsers/plugin.c index b6d29c459b..463e417cb6 100644 --- a/gst/videoparsers/plugin.c +++ b/gst/videoparsers/plugin.c @@ -22,6 +22,7 @@ #endif #include "gsth263parse.h" +#include "gsth264parse.h" static gboolean plugin_init (GstPlugin * plugin) @@ -30,6 +31,8 @@ plugin_init (GstPlugin * plugin) ret = gst_element_register (plugin, "h263parse", GST_RANK_NONE, GST_TYPE_H263_PARSE); + ret = gst_element_register (plugin, "h264parse", + GST_RANK_NONE, GST_TYPE_H264_PARSE); return ret; } From 39a16a3233b8ef5e8454ea176f458efc800a7ea6 Mon Sep 17 00:00:00 2001 From: Sjoerd Simons Date: Sun, 16 May 2010 17:23:17 +0100 Subject: [PATCH 370/448] rtpvp8: Add simple payloaders and depayloaders for VP8 Minimal implementation of http://www.webmproject.org/code/specs/rtp/, version 0.3.2 --- configure.ac | 2 + gst/rtpvp8/Makefile.am | 14 ++ gst/rtpvp8/gstrtpvp8.c | 21 ++ gst/rtpvp8/gstrtpvp8depay.c | 193 +++++++++++++++ gst/rtpvp8/gstrtpvp8depay.h | 63 +++++ gst/rtpvp8/gstrtpvp8pay.c | 473 ++++++++++++++++++++++++++++++++++++ gst/rtpvp8/gstrtpvp8pay.h | 65 +++++ 7 files changed, 831 insertions(+) create mode 100644 gst/rtpvp8/Makefile.am create mode 100644 gst/rtpvp8/gstrtpvp8.c create mode 100644 gst/rtpvp8/gstrtpvp8depay.c create mode 100644 gst/rtpvp8/gstrtpvp8depay.h create mode 100644 gst/rtpvp8/gstrtpvp8pay.c create mode 100644 gst/rtpvp8/gstrtpvp8pay.h diff --git a/configure.ac b/configure.ac index 52038b00e5..618aef90bd 100644 --- a/configure.ac +++ b/configure.ac @@ -334,6 +334,7 @@ AG_GST_CHECK_PLUGIN(qtmux) AG_GST_CHECK_PLUGIN(rawparse) AG_GST_CHECK_PLUGIN(real) AG_GST_CHECK_PLUGIN(rtpmux) +AG_GST_CHECK_PLUGIN(rtpvp8) AG_GST_CHECK_PLUGIN(scaletempo) AG_GST_CHECK_PLUGIN(sdp) AG_GST_CHECK_PLUGIN(segmentclip) @@ -1755,6 +1756,7 @@ gst/qtmux/Makefile gst/rawparse/Makefile gst/real/Makefile gst/rtpmux/Makefile +gst/rtpvp8/Makefile gst/scaletempo/Makefile gst/sdp/Makefile gst/segmentclip/Makefile diff --git a/gst/rtpvp8/Makefile.am b/gst/rtpvp8/Makefile.am new file mode 100644 index 0000000000..4f5ab1fc31 --- /dev/null +++ b/gst/rtpvp8/Makefile.am @@ -0,0 +1,14 @@ +plugin_LTLIBRARIES = libgstrtpvp8.la + +libgstrtpvp8_la_SOURCES = gstrtpvp8.c \ + gstrtpvp8depay.c \ + gstrtpvp8pay.c + +noinst_HEADERS = gstrtpvp8depay.h \ + gstrtpvp8pay.h + +libgstrtpvp8_la_CFLAGS = $(GST_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) +libgstrtpvp8_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) $(GST_LIBS) \ + -lgstrtp-@GST_MAJORMINOR@ +libgstrtpvp8_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) +libgstrtpvp8_la_LIBTOOLFLAGS = --tag=disable-static diff --git a/gst/rtpvp8/gstrtpvp8.c b/gst/rtpvp8/gstrtpvp8.c new file mode 100644 index 0000000000..baafd1fd35 --- /dev/null +++ b/gst/rtpvp8/gstrtpvp8.c @@ -0,0 +1,21 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "gstrtpvp8pay.h" +#include "gstrtpvp8depay.h" + +static gboolean +plugin_init (GstPlugin *plugin) +{ + gst_rtp_vp8_depay_plugin_init (plugin); + gst_rtp_vp8_pay_plugin_init (plugin); + + return TRUE; +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "rtpvp8", + "rtpvp8", + plugin_init, VERSION, GST_LICENSE, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) diff --git a/gst/rtpvp8/gstrtpvp8depay.c b/gst/rtpvp8/gstrtpvp8depay.c new file mode 100644 index 0000000000..79eee53279 --- /dev/null +++ b/gst/rtpvp8/gstrtpvp8depay.c @@ -0,0 +1,193 @@ +/* + * gst-rtp-vp8-depay.c - Source for GstRtpVP8Depay + * Copyright (C) 2011 Sjoerd Simons + * + * 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; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * 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 St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "gstrtpvp8depay.h" + +GST_DEBUG_CATEGORY_STATIC (gst_rtp_vp8_depay_debug); +#define GST_CAT_DEFAULT gst_rtp_vp8_depay_debug + +GST_BOILERPLATE (GstRtpVP8Depay, gst_rtp_vp8_depay, GstBaseRTPDepayload, + GST_TYPE_BASE_RTP_DEPAYLOAD); + +static GstStaticPadTemplate gst_rtp_vp8_depay_src_template = +GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("video/x-vp8")); + +static GstStaticPadTemplate gst_rtp_vp8_depay_sink_template = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("application/x-rtp, " + "payload = (int) " GST_RTP_PAYLOAD_DYNAMIC_STRING "," + "clock-rate = (int) 90000," + "media = (string) \"video\"," + "encoding-name = (string) \"VP8-DRAFT-0-3-2\"")); + +static void +gst_rtp_vp8_depay_init (GstRtpVP8Depay * self, GstRtpVP8DepayClass * klass) +{ + self->adapter = gst_adapter_new (); + self->started = FALSE; +} + +static void gst_rtp_vp8_depay_dispose (GObject * object); +static GstBuffer *gst_rtp_vp8_depay_process (GstBaseRTPDepayload * depayload, + GstBuffer * buf); +static gboolean gst_rtp_vp8_depay_set_caps (GstBaseRTPDepayload * depayload, + GstCaps * caps); + +static void +gst_rtp_vp8_depay_base_init (gpointer klass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_rtp_vp8_depay_sink_template)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_rtp_vp8_depay_src_template)); + + gst_element_class_set_details_simple (element_class, "RTP VP8 depayloader", + "Codec/Depayloader/Network/RTP", + "Extracts VP8 video from RTP packets)", + "Sjoerd Simons "); +} + +static void +gst_rtp_vp8_depay_class_init (GstRtpVP8DepayClass * gst_rtp_vp8_depay_class) +{ + GObjectClass *object_class = G_OBJECT_CLASS (gst_rtp_vp8_depay_class); + GstBaseRTPDepayloadClass *depay_class = + (GstBaseRTPDepayloadClass *) (gst_rtp_vp8_depay_class); + + object_class->dispose = gst_rtp_vp8_depay_dispose; + + depay_class->process = gst_rtp_vp8_depay_process; + depay_class->set_caps = gst_rtp_vp8_depay_set_caps; + + GST_DEBUG_CATEGORY_INIT (gst_rtp_vp8_depay_debug, "rtpvp8depay", 0, + "VP8 Video RTP Depayloader"); +} + +static void +gst_rtp_vp8_depay_dispose (GObject * object) +{ + GstRtpVP8Depay *self = GST_RTP_VP8_DEPAY (object); + + if (self->adapter != NULL) + g_object_unref (self->adapter); + self->adapter = NULL; + + /* release any references held by the object here */ + + if (G_OBJECT_CLASS (parent_class)->dispose) + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static GstBuffer * +gst_rtp_vp8_depay_process (GstBaseRTPDepayload * depay, GstBuffer * buf) +{ + GstRtpVP8Depay *self = GST_RTP_VP8_DEPAY (depay); + GstBuffer *payload; + guint8 *data; + guint offset; + guint size = gst_rtp_buffer_get_payload_len (buf); + + if (G_UNLIKELY (GST_BUFFER_IS_DISCONT (buf))) { + GST_LOG_OBJECT (self, "Discontinuity, flushing adapter"); + gst_adapter_clear (self->adapter); + self->started = FALSE; + } + + if (G_UNLIKELY (size < 2)) + goto too_small; + + data = gst_rtp_buffer_get_payload (buf); + + if (G_UNLIKELY (!self->started)) { + /* Check if this is the start of a VP8 frame, otherwise bail */ + if ((data[0] & 0x1) == 0) + return NULL; + + self->started = TRUE; + } + + offset = 1; + if ((data[0] & 0x10) != 0) { + /* Skip Picture identifier bytes */ + for (; (data[offset] & 0x80) != 0; offset++) { + /* should be at least one more pictureID byte and at least one byte in + * the vp8 payload */ + if (offset + 2 >= size) + goto too_small; + } + offset++; + } + + if (offset + 1 >= size) + goto too_small; + + payload = gst_rtp_buffer_get_payload_subbuffer (buf, offset, -1); + gst_adapter_push (self->adapter, payload); + + /* Marker indicates that it was the last rtp packet for this frame */ + if (gst_rtp_buffer_get_marker (buf)) { + GstBuffer *out; + + out = gst_adapter_take_buffer (self->adapter, + gst_adapter_available (self->adapter)); + + self->started = FALSE; + return out; + } + + return NULL; + +too_small: + GST_LOG_OBJECT (self, "Invalid rtp packet (too small), ignoring"); + gst_adapter_clear (self->adapter); + self->started = FALSE; + return NULL; +} + +static gboolean +gst_rtp_vp8_depay_set_caps (GstBaseRTPDepayload * depayload, GstCaps * caps) +{ + GstCaps *srccaps = gst_caps_new_simple ("video/x-vp8", + "framerate", GST_TYPE_FRACTION, 0, 1, + NULL); + + gst_pad_set_caps (GST_BASE_RTP_DEPAYLOAD_SRCPAD (depayload), srccaps); + gst_caps_unref (srccaps); + + return TRUE; +} + +gboolean +gst_rtp_vp8_depay_plugin_init (GstPlugin * plugin) +{ + return gst_element_register (plugin, "rtpvp8depay", + GST_RANK_MARGINAL, GST_TYPE_RTP_VP8_DEPAY); +} diff --git a/gst/rtpvp8/gstrtpvp8depay.h b/gst/rtpvp8/gstrtpvp8depay.h new file mode 100644 index 0000000000..8726156027 --- /dev/null +++ b/gst/rtpvp8/gstrtpvp8depay.h @@ -0,0 +1,63 @@ +/* + * gst-rtp-vp8-depay.h - Header for GstRtpVP8Depay + * Copyright (C) 2011 Sjoerd Simons + * + * 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; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * 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 St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __GST_RTP_VP8_DEPAY_H__ +#define __GST_RTP_VP8_DEPAY_H__ + +#include +#include +#include + +G_BEGIN_DECLS typedef struct _GstRtpVP8Depay GstRtpVP8Depay; +typedef struct _GstRtpVP8DepayClass GstRtpVP8DepayClass; + +struct _GstRtpVP8DepayClass +{ + GstBaseRTPDepayloadClass parent_class; +}; + +struct _GstRtpVP8Depay +{ + GstBaseRTPDepayload parent; + GstAdapter *adapter; + gboolean started; +}; + +GType gst_rtp_vp8_depay_get_type (void); + +/* TYPE MACROS */ +#define GST_TYPE_RTP_VP8_DEPAY \ + (gst_rtp_vp8_depay_get_type()) +#define GST_RTP_VP8_DEPAY(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_RTP_VP8_DEPAY, GstRtpVP8Depay)) +#define GST_RTP_VP8_DEPAY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_RTP_VP8_DEPAY, \ + GstRtpVP8DepayClass)) +#define GST_IS_RTP_VP8_DEPAY(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_RTP_VP8_DEPAY)) +#define GST_IS_RTP_VP8_DEPAY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_RTP_VP8_DEPAY)) +#define GST_RTP_VP8_DEPAY_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_RTP_VP8_DEPAY, \ + GstRtpVP8DepayClass)) + +gboolean gst_rtp_vp8_depay_plugin_init (GstPlugin * plugin); + +G_END_DECLS +#endif /* #ifndef __GST_RTP_VP8_DEPAY_H__ */ diff --git a/gst/rtpvp8/gstrtpvp8pay.c b/gst/rtpvp8/gstrtpvp8pay.c new file mode 100644 index 0000000000..8a552705e2 --- /dev/null +++ b/gst/rtpvp8/gstrtpvp8pay.c @@ -0,0 +1,473 @@ +/* + * gst-rtp-vp8-pay.c - Source for GstRtpVP8Pay + * Copyright (C) 2011 Sjoerd Simons + * + * 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; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * 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 St, Fifth Floor, Boston, MA 02110-1301 USA + */ + + +#include +#include +#include + +#include +#include +#include +#include "gstrtpvp8pay.h" + +#define FI_FRAG_UNFRAGMENTED 0x0 +#define FI_FRAG_START 0x1 +#define FI_FRAG_MIDDLE 0x2 +#define FI_FRAG_END 0x3 + +GST_DEBUG_CATEGORY_STATIC (gst_rtp_vp8_pay_debug); +#define GST_CAT_DEFAULT gst_rtp_vp8_pay_debug + +GST_BOILERPLATE (GstRtpVP8Pay, gst_rtp_vp8_pay, GstBaseRTPPayload, + GST_TYPE_BASE_RTP_PAYLOAD); + +static GstStaticPadTemplate gst_rtp_vp8_pay_src_template = +GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("application/x-rtp, " + "payload = (int) " GST_RTP_PAYLOAD_DYNAMIC_STRING "," + "clock-rate = (int) 90000, encoding-name = (string) \"VP8-DRAFT-0-3-2\"")); + +static GstStaticPadTemplate gst_rtp_vp8_pay_sink_template = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("video/x-vp8")); + +static void +gst_rtp_vp8_pay_init (GstRtpVP8Pay * obj, GstRtpVP8PayClass * klass) +{ +} + +static GstFlowReturn gst_rtp_vp8_pay_handle_buffer (GstBaseRTPPayload * payload, + GstBuffer * buffer); +static gboolean gst_rtp_vp8_pay_set_caps (GstBaseRTPPayload * payload, + GstCaps * caps); + +static void +gst_rtp_vp8_pay_base_init (gpointer klass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_rtp_vp8_pay_sink_template)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_rtp_vp8_pay_src_template)); + + gst_element_class_set_details_simple (element_class, "RTP VP8 payloader", + "Codec/Payloader/Network/RTP", + "Puts VP8 video in RTP packets)", "Sjoerd Simons "); +} + +static void +gst_rtp_vp8_pay_class_init (GstRtpVP8PayClass * gst_rtp_vp8_pay_class) +{ + GstBaseRTPPayloadClass *pay_class = + GST_BASE_RTP_PAYLOAD_CLASS (gst_rtp_vp8_pay_class); + + pay_class->handle_buffer = gst_rtp_vp8_pay_handle_buffer; + pay_class->set_caps = gst_rtp_vp8_pay_set_caps; + + GST_DEBUG_CATEGORY_INIT (gst_rtp_vp8_pay_debug, "rtpvp8pay", 0, + "VP8 Video RTP Payloader"); +} + +static gsize +gst_rtp_vp8_calc_payload_len (GstBaseRTPPayload * payload) +{ + return gst_rtp_buffer_calc_payload_len (GST_BASE_RTP_PAYLOAD_MTU (payload) - + 1, 0, 0); +} + +/* When growing the vp8 header keep gst_rtp_vp8_calc_payload_len in sync */ +static GstBuffer * +gst_rtp_vp8_create_header_buffer (gboolean start, gboolean mark, guint fi, + GstBuffer * in) +{ + GstBuffer *out; + guint8 *p; + + out = gst_rtp_buffer_new_allocate (1, 0, 0); + p = gst_rtp_buffer_get_payload (out); + /* Hardcode I = 0 and N = 0, only set FI and B */ + p[0] = (fi & 0x3) << 1 | (start ? 1 : 0); + + gst_rtp_buffer_set_marker (out, mark); + + GST_BUFFER_DURATION (out) = GST_BUFFER_DURATION (in); + GST_BUFFER_TIMESTAMP (out) = GST_BUFFER_TIMESTAMP (in); + + return out; +} + + +static gboolean +gst_rtp_vp8_pay_parse_frame (GstRtpVP8Pay * self, GstBuffer * buffer) +{ + GstBitReader *reader; + int i; + gboolean keyframe; + guint32 header_size; + guint8 version; + guint8 tmp8; + guint8 *data; + guint8 partitions; + + reader = gst_bit_reader_new_from_buffer (buffer); + + if (G_UNLIKELY (GST_BUFFER_SIZE (buffer) < 3)) + goto error; + + data = GST_BUFFER_DATA (buffer); + + self->is_keyframe = keyframe = ((data[0] & 0x1) == 0); + version = (data[0] >> 1) & 0x7; + + /* keyframe, version and show_frame use 5 bits */ + header_size = data[2] << 11 | data[1] << 3 | (data[0] >> 5); + + /* Include the uncompressed data blob in the header */ + header_size += keyframe ? 10 : 3; + + if (!gst_bit_reader_skip (reader, 24)) + goto error; + + if (keyframe) { + /* check start tag: 0x9d 0x01 0x2a */ + if (!gst_bit_reader_get_bits_uint8 (reader, &tmp8, 8) || tmp8 != 0x9d) + goto error; + + if (!gst_bit_reader_get_bits_uint8 (reader, &tmp8, 8) || tmp8 != 0x01) + goto error; + + if (!gst_bit_reader_get_bits_uint8 (reader, &tmp8, 8) || tmp8 != 0x2a) + goto error; + + /* Skip horizontal size code (16 bits) vertical size code (16 bits), + * color space (1 bit) and clamping type (1 bit) */ + if (!gst_bit_reader_skip (reader, 34)) + goto error; + } + + /* segmentation_enabled */ + if (!gst_bit_reader_get_bits_uint8 (reader, &tmp8, 1)) + goto error; + + if (tmp8 != 0) { + gboolean update_mb_segmentation_map; + gboolean update_segment_feature_data; + + if (!gst_bit_reader_get_bits_uint8 (reader, &tmp8, 2)) + goto error; + + update_mb_segmentation_map = (tmp8 & 0x2) != 0; + update_segment_feature_data = (tmp8 & 0x1) != 0; + + if (update_segment_feature_data) { + /* skip segment feature mode */ + if (!gst_bit_reader_skip (reader, 1)) + goto error; + + for (i = 0; i < 4; i++) { + /* quantizer update */ + if (!gst_bit_reader_get_bits_uint8 (reader, &tmp8, 1)) + goto error; + + if (tmp8 != 0) { + /* skip quantizer value (7 bits) and sign (1 bit) */ + if (!gst_bit_reader_skip (reader, 8)) + goto error; + } + } + + for (i = 0; i < 4; i++) { + /* loop filter update */ + if (!gst_bit_reader_get_bits_uint8 (reader, &tmp8, 1)) + goto error; + + if (tmp8 != 0) { + /* skip lf update value (6 bits) and sign (1 bit) */ + if (!gst_bit_reader_skip (reader, 7)) + goto error; + } + } + } + + if (update_mb_segmentation_map) { + for (i = 0; i < 3; i++) { + /* segment prob update */ + if (!gst_bit_reader_get_bits_uint8 (reader, &tmp8, 1)) + goto error; + + if (tmp8 != 0) { + /* skip segment prob */ + if (!gst_bit_reader_skip (reader, 8)) + goto error; + } + } + } + } + + /* skip filter type (1 bit), loop filter level (6 bits) and + * sharpness level (3 bits) */ + if (!gst_bit_reader_skip (reader, 10)) + goto error; + + /* loop_filter_adj_enabled */ + if (!gst_bit_reader_get_bits_uint8 (reader, &tmp8, 1)) + goto error; + + if (tmp8 != 0) { + /* loop filter adj enabled */ + + /* mode_ref_lf_delta_update */ + if (!gst_bit_reader_get_bits_uint8 (reader, &tmp8, 1)) + goto error; + + if (tmp8 != 0) { + /* mode_ref_lf_data_update */ + int i; + + for (i = 0; i < 8; i++) { + /* 8 updates, 1 bit indicate whether there is one and if follow by a + * 7 bit update */ + if (!gst_bit_reader_get_bits_uint8 (reader, &tmp8, 1)) + goto error; + + if (tmp8 != 0) { + /* skip delta magnitude (6 bits) and sign (1 bit) */ + if (!gst_bit_reader_skip (reader, 7)) + goto error; + } + } + } + } + + if (!gst_bit_reader_get_bits_uint8 (reader, &tmp8, 2)) + goto error; + + self->n_partitions = partitions = 1 << tmp8; + + /* Check if things are still sensible */ + if (header_size + (partitions - 1) * 3 >= GST_BUFFER_SIZE (buffer)) + goto error; + + /* partition data is right after the frame header */ + data = GST_BUFFER_DATA (buffer) + header_size; + + self->partition_offset[0] = header_size + (partitions - 1) * 3; + + /* Include partition data in the header for RTP purposes */ + self->header_size = self->partition_offset[0]; + + for (i = 0; i < (partitions - 1); i++) { + guint size = (data[2] << 16 | data[1] << 8 | data[0]); + + data += 3; + self->partition_size[i] = size; + self->partition_offset[i + 1] = self->partition_offset[i] + size; + } + + /* Check that our partition offsets and sizes don't go outsize the buffer + * size. */ + if (self->partition_offset[i] >= GST_BUFFER_SIZE (buffer)) + goto error; + + self->partition_size[i] = GST_BUFFER_SIZE (buffer) + - self->partition_offset[i]; + + self->partition_offset[i + 1] = GST_BUFFER_SIZE (buffer); + + gst_bit_reader_free (reader); + return TRUE; + +error: + GST_DEBUG ("Failed to parse frame"); + gst_bit_reader_free (reader); + return FALSE; +} + +static guint +gst_rtp_vp8_fit_partitions (GstRtpVP8Pay * self, gint first, gsize available) +{ + guint num = 0; + int i; + + g_assert (first < self->n_partitions); + + if (first < 0) { + if (self->header_size > available) + return 0; + + available -= self->header_size; + num++; + first = 0; + } + + for (i = first; + i < self->n_partitions && self->partition_size[i] < available; i++) { + num++; + available -= self->partition_size[i]; + } + + return num; +} + +static GstBuffer * +gst_rtp_vp8_create_sub (GstRtpVP8Pay * self, + GstBuffer * buffer, gint current, guint num) +{ + guint offset = 0; + guint size; + + if (current >= 0) { + offset = self->partition_offset[current]; + } + + size = self->partition_offset[current + num] - offset; + + return gst_buffer_create_sub (buffer, offset, size); +} + + +static guint +gst_rtp_vp8_payload_next (GstRtpVP8Pay * self, + GstBufferListIterator * it, gint first, GstBuffer * buffer) +{ + guint num; + GstBuffer *header; + GstBuffer *sub; + gboolean mark; + gsize available = gst_rtp_vp8_calc_payload_len (GST_BASE_RTP_PAYLOAD (self)); + + g_assert (first < 8); + + /* How many partitions can we fit */ + num = gst_rtp_vp8_fit_partitions (self, first, available); + + if (num > 0) { + mark = (first + num == self->n_partitions); + /* whole set of partitions, payload them and done */ + header = gst_rtp_vp8_create_header_buffer (first == -1, mark, + FI_FRAG_UNFRAGMENTED, buffer); + sub = gst_rtp_vp8_create_sub (self, buffer, first, num); + + gst_buffer_list_iterator_add_group (it); + gst_buffer_list_iterator_add (it, header); + gst_buffer_list_iterator_add (it, sub); + } else { + /* Fragmented packets */ + guint left; + guint offset; + + if (first >= 0) { + offset = self->partition_offset[first]; + left = self->partition_size[first]; + } else { + offset = 0; + left = self->header_size; + } + + header = gst_rtp_vp8_create_header_buffer (first == -1, FALSE, + FI_FRAG_START, buffer); + sub = gst_buffer_create_sub (buffer, offset, available); + offset += available; + + gst_buffer_list_iterator_add_group (it); + gst_buffer_list_iterator_add (it, header); + gst_buffer_list_iterator_add (it, sub); + + left -= available; + + for (; left > available; left -= available) { + header = gst_rtp_vp8_create_header_buffer (first == -1, FALSE, + FI_FRAG_MIDDLE, buffer); + + sub = gst_buffer_create_sub (buffer, offset, available); + offset += available; + + gst_buffer_list_iterator_add_group (it); + gst_buffer_list_iterator_add (it, header); + gst_buffer_list_iterator_add (it, sub); + } + + mark = (first + 1 == self->n_partitions); + + header = gst_rtp_vp8_create_header_buffer (first == -1, mark, + FI_FRAG_END, buffer); + sub = gst_buffer_create_sub (buffer, offset, left); + + gst_buffer_list_iterator_add_group (it); + gst_buffer_list_iterator_add (it, header); + gst_buffer_list_iterator_add (it, sub); + + return 1; + } + + return num; +} + + +static GstFlowReturn +gst_rtp_vp8_pay_handle_buffer (GstBaseRTPPayload * payload, GstBuffer * buffer) +{ + GstRtpVP8Pay *self = GST_RTP_VP8_PAY (payload); + GstFlowReturn ret; + GstBufferList *list; + GstBufferListIterator *it; + gint current; + + if (G_UNLIKELY (!gst_rtp_vp8_pay_parse_frame (self, buffer))) { + /* FIXME throw flow error */ + g_message ("Failed to parse frame"); + return GST_FLOW_ERROR; + } + + list = gst_buffer_list_new (); + it = gst_buffer_list_iterate (list); + + for (current = -1; current < self->n_partitions;) { + guint n; + + n = gst_rtp_vp8_payload_next (self, it, current, buffer); + current += n; + } + + ret = gst_basertppayload_push_list (payload, list); + gst_buffer_list_iterator_free (it); + + return ret; +} + +static gboolean +gst_rtp_vp8_pay_set_caps (GstBaseRTPPayload * payload, GstCaps * caps) +{ + gst_basertppayload_set_options (payload, "video", TRUE, + "VP8-DRAFT-0-3-2", 90000); + return gst_basertppayload_set_outcaps (payload, NULL); +} + +gboolean +gst_rtp_vp8_pay_plugin_init (GstPlugin * plugin) +{ + return gst_element_register (plugin, "rtpvp8pay", + GST_RANK_MARGINAL, GST_TYPE_RTP_VP8_PAY); +} diff --git a/gst/rtpvp8/gstrtpvp8pay.h b/gst/rtpvp8/gstrtpvp8pay.h new file mode 100644 index 0000000000..ea76534bcb --- /dev/null +++ b/gst/rtpvp8/gstrtpvp8pay.h @@ -0,0 +1,65 @@ +/* + * gst-rtp-vp8-pay.h - Header for GstRtpVP8Pay + * Copyright (C) 2011 Sjoerd Simons + * + * 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; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * 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 St, Fifth Floor, Boston, MA 02110-1301 USA + */ + +#ifndef __GST_RTP_VP8_PAY_H__ +#define __GST_RTP_VP8_PAY_H__ + +#include +#include +#include + +G_BEGIN_DECLS typedef struct _GstRtpVP8Pay GstRtpVP8Pay; +typedef struct _GstRtpVP8PayClass GstRtpVP8PayClass; + +struct _GstRtpVP8PayClass +{ + GstBaseRTPPayloadClass parent_class; +}; + +struct _GstRtpVP8Pay +{ + GstBaseRTPPayload parent; + gboolean is_keyframe; + gint n_partitions; + guint header_size; + /* Add the end offset for easier implementation */ + guint partition_offset[9]; + guint partition_size[8]; +}; + +GType gst_rtp_vp8_pay_get_type (void); + +/* TYPE MACROS */ +#define GST_TYPE_RTP_VP8_PAY \ + (gst_rtp_vp8_pay_get_type()) +#define GST_RTP_VP8_PAY(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_RTP_VP8_PAY, GstRtpVP8Pay)) +#define GST_RTP_VP8_PAY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_RTP_VP8_PAY, GstRtpVP8PayClass)) +#define GST_IS_RTP_VP8_PAY(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_RTP_VP8_PAY)) +#define GST_IS_RTP_VP8_PAY_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_RTP_VP8_PAY)) +#define GST_RTP_VP8_PAY_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_RTP_VP8_PAY, GstRtpVP8PayClass)) + +gboolean gst_rtp_vp8_pay_plugin_init (GstPlugin * plugin); + +G_END_DECLS +#endif /* #ifndef __GST_RTP_VP8_PAY_H__ */ From 0bee149c74a22ad9a08f46eebe25b5a88b7fb204 Mon Sep 17 00:00:00 2001 From: Sjoerd Simons Date: Sun, 23 Jan 2011 16:42:17 +0000 Subject: [PATCH 371/448] rtpvp8pay: Treat the frame header just like any other partition When setting up the initial mapping just act as if the global frame information is another partition. This saves special-casing it later in the actual packetizing code. --- gst/rtpvp8/gstrtpvp8pay.c | 64 ++++++++++++++------------------------- gst/rtpvp8/gstrtpvp8pay.h | 8 ++--- 2 files changed, 26 insertions(+), 46 deletions(-) diff --git a/gst/rtpvp8/gstrtpvp8pay.c b/gst/rtpvp8/gstrtpvp8pay.c index 8a552705e2..0ea5777134 100644 --- a/gst/rtpvp8/gstrtpvp8pay.c +++ b/gst/rtpvp8/gstrtpvp8pay.c @@ -264,7 +264,7 @@ gst_rtp_vp8_pay_parse_frame (GstRtpVP8Pay * self, GstBuffer * buffer) if (!gst_bit_reader_get_bits_uint8 (reader, &tmp8, 2)) goto error; - self->n_partitions = partitions = 1 << tmp8; + partitions = 1 << tmp8; /* Check if things are still sensible */ if (header_size + (partitions - 1) * 3 >= GST_BUFFER_SIZE (buffer)) @@ -273,12 +273,14 @@ gst_rtp_vp8_pay_parse_frame (GstRtpVP8Pay * self, GstBuffer * buffer) /* partition data is right after the frame header */ data = GST_BUFFER_DATA (buffer) + header_size; - self->partition_offset[0] = header_size + (partitions - 1) * 3; + /* Set up mapping, count the initial header as a partition to make other + * sections of the code easier */ + self->n_partitions = partitions + 1; + self->partition_offset[0] = 0; + self->partition_size[0] = header_size + (partitions - 1) * 3; - /* Include partition data in the header for RTP purposes */ - self->header_size = self->partition_offset[0]; - - for (i = 0; i < (partitions - 1); i++) { + self->partition_offset[1] = self->partition_size[0]; + for (i = 1; i < partitions; i++) { guint size = (data[2] << 16 | data[1] << 8 | data[0]); data += 3; @@ -313,15 +315,6 @@ gst_rtp_vp8_fit_partitions (GstRtpVP8Pay * self, gint first, gsize available) g_assert (first < self->n_partitions); - if (first < 0) { - if (self->header_size > available) - return 0; - - available -= self->header_size; - num++; - first = 0; - } - for (i = first; i < self->n_partitions && self->partition_size[i] < available; i++) { num++; @@ -333,16 +326,10 @@ gst_rtp_vp8_fit_partitions (GstRtpVP8Pay * self, gint first, gsize available) static GstBuffer * gst_rtp_vp8_create_sub (GstRtpVP8Pay * self, - GstBuffer * buffer, gint current, guint num) + GstBuffer * buffer, guint current, guint num) { - guint offset = 0; - guint size; - - if (current >= 0) { - offset = self->partition_offset[current]; - } - - size = self->partition_offset[current + num] - offset; + guint offset = self->partition_offset[current]; + guint size = self->partition_offset[current + num] - offset; return gst_buffer_create_sub (buffer, offset, size); } @@ -350,7 +337,7 @@ gst_rtp_vp8_create_sub (GstRtpVP8Pay * self, static guint gst_rtp_vp8_payload_next (GstRtpVP8Pay * self, - GstBufferListIterator * it, gint first, GstBuffer * buffer) + GstBufferListIterator * it, guint first, GstBuffer * buffer) { guint num; GstBuffer *header; @@ -358,7 +345,7 @@ gst_rtp_vp8_payload_next (GstRtpVP8Pay * self, gboolean mark; gsize available = gst_rtp_vp8_calc_payload_len (GST_BASE_RTP_PAYLOAD (self)); - g_assert (first < 8); + g_assert (first < 9); /* How many partitions can we fit */ num = gst_rtp_vp8_fit_partitions (self, first, available); @@ -366,7 +353,7 @@ gst_rtp_vp8_payload_next (GstRtpVP8Pay * self, if (num > 0) { mark = (first + num == self->n_partitions); /* whole set of partitions, payload them and done */ - header = gst_rtp_vp8_create_header_buffer (first == -1, mark, + header = gst_rtp_vp8_create_header_buffer (first == 0, mark, FI_FRAG_UNFRAGMENTED, buffer); sub = gst_rtp_vp8_create_sub (self, buffer, first, num); @@ -375,18 +362,11 @@ gst_rtp_vp8_payload_next (GstRtpVP8Pay * self, gst_buffer_list_iterator_add (it, sub); } else { /* Fragmented packets */ - guint left; - guint offset; + guint offset = self->partition_offset[first]; + guint left = self->partition_size[first]; + gboolean start = (first == 0); - if (first >= 0) { - offset = self->partition_offset[first]; - left = self->partition_size[first]; - } else { - offset = 0; - left = self->header_size; - } - - header = gst_rtp_vp8_create_header_buffer (first == -1, FALSE, + header = gst_rtp_vp8_create_header_buffer (start, FALSE, FI_FRAG_START, buffer); sub = gst_buffer_create_sub (buffer, offset, available); offset += available; @@ -398,7 +378,7 @@ gst_rtp_vp8_payload_next (GstRtpVP8Pay * self, left -= available; for (; left > available; left -= available) { - header = gst_rtp_vp8_create_header_buffer (first == -1, FALSE, + header = gst_rtp_vp8_create_header_buffer (start, FALSE, FI_FRAG_MIDDLE, buffer); sub = gst_buffer_create_sub (buffer, offset, available); @@ -411,7 +391,7 @@ gst_rtp_vp8_payload_next (GstRtpVP8Pay * self, mark = (first + 1 == self->n_partitions); - header = gst_rtp_vp8_create_header_buffer (first == -1, mark, + header = gst_rtp_vp8_create_header_buffer (start, mark, FI_FRAG_END, buffer); sub = gst_buffer_create_sub (buffer, offset, left); @@ -433,7 +413,7 @@ gst_rtp_vp8_pay_handle_buffer (GstBaseRTPPayload * payload, GstBuffer * buffer) GstFlowReturn ret; GstBufferList *list; GstBufferListIterator *it; - gint current; + guint current; if (G_UNLIKELY (!gst_rtp_vp8_pay_parse_frame (self, buffer))) { /* FIXME throw flow error */ @@ -444,7 +424,7 @@ gst_rtp_vp8_pay_handle_buffer (GstBaseRTPPayload * payload, GstBuffer * buffer) list = gst_buffer_list_new (); it = gst_buffer_list_iterate (list); - for (current = -1; current < self->n_partitions;) { + for (current = 0; current < self->n_partitions;) { guint n; n = gst_rtp_vp8_payload_next (self, it, current, buffer); diff --git a/gst/rtpvp8/gstrtpvp8pay.h b/gst/rtpvp8/gstrtpvp8pay.h index ea76534bcb..19a2e0147b 100644 --- a/gst/rtpvp8/gstrtpvp8pay.h +++ b/gst/rtpvp8/gstrtpvp8pay.h @@ -37,10 +37,10 @@ struct _GstRtpVP8Pay GstBaseRTPPayload parent; gboolean is_keyframe; gint n_partitions; - guint header_size; - /* Add the end offset for easier implementation */ - guint partition_offset[9]; - guint partition_size[8]; + /* Treat frame header & tag & partition size block as the first partition, + * folowed by max. 8 data partitions. last offset is the end of the buffer */ + guint partition_offset[10]; + guint partition_size[9]; }; GType gst_rtp_vp8_pay_get_type (void); From 216189ea36d0c477ed771d229eb548e93acb0cc3 Mon Sep 17 00:00:00 2001 From: Sjoerd Simons Date: Sun, 23 Jan 2011 17:02:38 +0000 Subject: [PATCH 372/448] rtpvp8depay: Accept packets with only one byte of data When fragmenting partions it can happen that an RTP packet only caries 1 byte of RTP data. --- gst/rtpvp8/gstrtpvp8depay.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/gst/rtpvp8/gstrtpvp8depay.c b/gst/rtpvp8/gstrtpvp8depay.c index 79eee53279..d9d222654c 100644 --- a/gst/rtpvp8/gstrtpvp8depay.c +++ b/gst/rtpvp8/gstrtpvp8depay.c @@ -121,6 +121,7 @@ gst_rtp_vp8_depay_process (GstBaseRTPDepayload * depay, GstBuffer * buf) self->started = FALSE; } + /* At least one header and one vp8 byte */ if (G_UNLIKELY (size < 2)) goto too_small; @@ -140,13 +141,13 @@ gst_rtp_vp8_depay_process (GstBaseRTPDepayload * depay, GstBuffer * buf) for (; (data[offset] & 0x80) != 0; offset++) { /* should be at least one more pictureID byte and at least one byte in * the vp8 payload */ - if (offset + 2 >= size) + if (G_UNLIKELY (offset + 2 >= size)) goto too_small; } offset++; } - if (offset + 1 >= size) + if (G_UNLIKELY (offset >= size)) goto too_small; payload = gst_rtp_buffer_get_payload_subbuffer (buf, offset, -1); From 9ae14406e83750c3ab75fde1d487723101027184 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Sun, 30 Jan 2011 17:08:11 +0000 Subject: [PATCH 373/448] rtpvp8: fix LIBS and CFLAGS order in Makefile.am --- gst/rtpvp8/Makefile.am | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gst/rtpvp8/Makefile.am b/gst/rtpvp8/Makefile.am index 4f5ab1fc31..8a722ebc0a 100644 --- a/gst/rtpvp8/Makefile.am +++ b/gst/rtpvp8/Makefile.am @@ -7,8 +7,8 @@ libgstrtpvp8_la_SOURCES = gstrtpvp8.c \ noinst_HEADERS = gstrtpvp8depay.h \ gstrtpvp8pay.h -libgstrtpvp8_la_CFLAGS = $(GST_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) -libgstrtpvp8_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) $(GST_LIBS) \ - -lgstrtp-@GST_MAJORMINOR@ +libgstrtpvp8_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) +libgstrtpvp8_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) -lgstrtp-@GST_MAJORMINOR@ \ + $(GST_LIBS) libgstrtpvp8_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) libgstrtpvp8_la_LIBTOOLFLAGS = --tag=disable-static From ad019102e5d3b354c48eba7fac0591810d7776c6 Mon Sep 17 00:00:00 2001 From: Teemu Katajisto Date: Fri, 14 Jan 2011 10:19:28 +0200 Subject: [PATCH 374/448] camerabin: optimize setting new caps for preview image pipeline Avoid re-creating and linking of preview image pipeline when setting new preview image caps. Backported from camerabin2. https://bugzilla.gnome.org/show_bug.cgi?id=639502 --- gst/camerabin/camerabinpreview.c | 192 ++++++++++++++++++------------- gst/camerabin/camerabinpreview.h | 35 ++++-- gst/camerabin/gstcamerabin.c | 43 ++++--- gst/camerabin/gstcamerabin.h | 7 +- 4 files changed, 166 insertions(+), 111 deletions(-) diff --git a/gst/camerabin/camerabinpreview.c b/gst/camerabin/camerabinpreview.c index 028297eaf6..434a92f7a5 100644 --- a/gst/camerabin/camerabinpreview.c +++ b/gst/camerabin/camerabinpreview.c @@ -60,124 +60,133 @@ create_element (const gchar * factory_name, const gchar * elem_name, /** * gst_camerabin_preview_create_pipeline: + * @element: #GstCameraBin element * @caps: pointer to the caps used in pipeline + * @src_filter: source filter element * * Create a preview converter pipeline that outputs the format defined in * @caps parameter. * - * Returns: New pipeline, or NULL if error occured. + * Returns: New pipeline data structure, or NULL if error occured. */ -GstElement * -gst_camerabin_preview_create_pipeline (GstCameraBin * camera, GstCaps * caps, +GstCameraBinPreviewPipelineData * +gst_camerabin_preview_create_pipeline (GstElement * element, GstCaps * caps, GstElement * src_filter) { - GstElement *pipe, *src, *csp, *filter, *vscale, *sink; + GstElement *csp, *vscale; GError *error = NULL; + GstCameraBinPreviewPipelineData *data; - g_return_val_if_fail (caps != NULL, FALSE); + g_return_val_if_fail (caps != NULL, NULL); GST_DEBUG ("creating elements"); - if (!create_element ("appsrc", "prev_src", &src, &error) || - !create_element ("videoscale", NULL, &vscale, &error) || - !create_element ("ffmpegcolorspace", NULL, &csp, &error) || - !create_element ("capsfilter", NULL, &filter, &error) || - !create_element ("fakesink", "prev_sink", &sink, &error)) - goto no_elements; + data = g_new (GstCameraBinPreviewPipelineData, 1); /* We have multiple pipelines created by using this function, so we can't * give a name to them. Another way would to ensure the uniqueness of the * name here*/ - pipe = gst_pipeline_new (NULL); - if (pipe == NULL) - goto no_pipeline; + data->pipeline = gst_pipeline_new (NULL); + if (!data->pipeline) + goto create_error; + + if (!create_element ("appsrc", "prev_src", &data->appsrc, &error) || + !create_element ("videoscale", NULL, &vscale, &error) || + !create_element ("ffmpegcolorspace", NULL, &csp, &error) || + !create_element ("capsfilter", NULL, &data->capsfilter, &error) || + !create_element ("fakesink", "prev_sink", &data->appsink, &error)) + goto create_error; GST_DEBUG ("adding elements"); - gst_bin_add_many (GST_BIN (pipe), src, csp, filter, vscale, sink, NULL); + gst_bin_add_many (GST_BIN (data->pipeline), data->appsrc, csp, + data->capsfilter, vscale, data->appsink, NULL); if (src_filter) { - gst_bin_add (GST_BIN (pipe), src_filter); + gst_bin_add (GST_BIN (data->pipeline), src_filter); } + data->element = element; + GST_DEBUG ("preview format is: %" GST_PTR_FORMAT, caps); - g_object_set (filter, "caps", caps, NULL); - g_object_set (sink, "preroll-queue-len", 1, "signal-handoffs", TRUE, NULL); + g_object_set (data->capsfilter, "caps", caps, NULL); + g_object_set (data->appsink, "preroll-queue-len", 1, "signal-handoffs", TRUE, + NULL); g_object_set (vscale, "method", 0, NULL); - /* FIXME: linking is still way too expensive, profile this properly */ GST_DEBUG ("linking src->vscale"); - if (!gst_element_link_pads_full (src, "src", vscale, "sink", - GST_PAD_LINK_CHECK_CAPS)) - return FALSE; + if (!gst_element_link_pads (data->appsrc, "src", vscale, "sink")) + goto link_error; if (src_filter) { - GST_DEBUG ("linking vscale->filter"); - if (!gst_element_link_pads_full (vscale, "src", src_filter, "sink", - GST_PAD_LINK_CHECK_CAPS)) { - return FALSE; + GST_DEBUG ("linking vscale->src_filter"); + if (!gst_element_link_pads (vscale, "src", src_filter, "sink")) { + goto link_error; } GST_DEBUG ("linking filter->csp"); - if (!gst_element_link_pads_full (src_filter, "src", csp, "sink", - GST_PAD_LINK_CHECK_CAPS)) { - return FALSE; + if (!gst_element_link_pads (src_filter, "src", csp, "sink")) { + goto link_error; } } else { GST_DEBUG ("linking vscale->csp"); - if (!gst_element_link_pads_full (vscale, "src", csp, "sink", - GST_PAD_LINK_CHECK_CAPS)) - return FALSE; + if (!gst_element_link_pads (vscale, "src", csp, "sink")) + goto link_error; } GST_DEBUG ("linking csp->capsfilter"); - if (!gst_element_link_pads_full (csp, "src", filter, "sink", - GST_PAD_LINK_CHECK_CAPS)) - return FALSE; + if (!gst_element_link_pads (csp, "src", data->capsfilter, "sink")) + goto link_error; GST_DEBUG ("linking capsfilter->sink"); - if (!gst_element_link_pads_full (filter, "src", sink, "sink", - GST_PAD_LINK_CHECK_CAPS)) - return FALSE; + if (!gst_element_link_pads (data->capsfilter, "src", data->appsink, "sink")) + goto link_error; - return pipe; + return data; - /* ERRORS */ -no_elements: - { - g_warning ("Could not make preview pipeline: %s", error->message); +create_error: + if (error) { + GST_WARNING ("Preview pipeline element creation failed: %s", + error->message); g_error_free (error); - return NULL; - } -no_pipeline: - { - g_warning ("Could not make preview pipeline: %s", - "no pipeline (unknown error)"); - return NULL; } + if (csp) + gst_object_unref (csp); + if (vscale) + gst_object_unref (vscale); + if (data->appsrc) + gst_object_unref (data->appsrc); + if (data->capsfilter) + gst_object_unref (data->capsfilter); + if (data->appsink) + gst_object_unref (data->appsink); + +link_error: + GST_WARNING ("Could not create preview pipeline"); + gst_camerabin_preview_destroy_pipeline (data); + + return NULL; } /** * gst_camerabin_preview_destroy_pipeline: - * @camera: camerabin object - * @pipeline: the pipeline to be destroyed + * @data: the pipeline data to be destroyed * * Destroy preview converter pipeline. */ void -gst_camerabin_preview_destroy_pipeline (GstCameraBin * camera, - GstElement * pipeline) +gst_camerabin_preview_destroy_pipeline (GstCameraBinPreviewPipelineData * data) { - g_return_if_fail (pipeline != NULL); - - gst_element_set_state (pipeline, GST_STATE_NULL); - gst_object_unref (pipeline); + if (data->pipeline) { + gst_element_set_state (data->pipeline, GST_STATE_NULL); + gst_object_unref (data->pipeline); + } + g_free (data); } /** * gst_camerabin_preview_convert: - * @camera: camerabin object - * @pipeline: preview pipeline to use + * @data: preview pipeline data to use * @buf: #GstBuffer that contains the frame to be converted * * Create a preview image of the given frame. @@ -185,8 +194,8 @@ gst_camerabin_preview_destroy_pipeline (GstCameraBin * camera, * Returns: converted preview image, or NULL if operation failed. */ GstBuffer * -gst_camerabin_preview_convert (GstCameraBin * camera, - GstElement * pipeline, GstBuffer * buf) +gst_camerabin_preview_convert (GstCameraBinPreviewPipelineData * data, + GstBuffer * buf) { GstMessage *msg; GstBuffer *result = NULL; @@ -198,13 +207,13 @@ gst_camerabin_preview_convert (GstCameraBin * camera, g_return_val_if_fail (GST_BUFFER_CAPS (buf) != NULL, NULL); - if (pipeline == NULL) { + if (data->pipeline == NULL) { GST_WARNING ("pipeline is NULL"); goto no_pipeline; } - src = gst_bin_get_by_name (GST_BIN (pipeline), "prev_src"); - sink = gst_bin_get_by_name (GST_BIN (pipeline), "prev_sink"); + src = gst_bin_get_by_name (GST_BIN (data->pipeline), "prev_src"); + sink = gst_bin_get_by_name (GST_BIN (data->pipeline), "prev_sink"); if (!src || !sink) { GST_WARNING ("pipeline doesn't have src / sink elements"); @@ -222,11 +231,11 @@ gst_camerabin_preview_convert (GstCameraBin * camera, GST_DEBUG ("running conversion pipeline, source is: %" GST_PTR_FORMAT, GST_BUFFER_CAPS (buf)); - gst_element_set_state (pipeline, GST_STATE_PLAYING); + gst_element_set_state (data->pipeline, GST_STATE_PLAYING); g_signal_emit_by_name (src, "push-buffer", buf, &fret); - bus = gst_element_get_bus (pipeline); + bus = gst_element_get_bus (data->pipeline); msg = gst_bus_timed_pop_filtered (bus, (25 * GST_SECOND), GST_MESSAGE_ERROR | GST_MESSAGE_EOS); gst_object_unref (bus); @@ -268,7 +277,7 @@ gst_camerabin_preview_convert (GstCameraBin * camera, g_signal_handlers_disconnect_by_func (sink, G_CALLBACK (save_result), &result); - gst_element_set_state (pipeline, GST_STATE_READY); + gst_element_set_state (data->pipeline, GST_STATE_READY); GST_BUFFER_FLAGS (buf) = bflags; @@ -297,7 +306,7 @@ no_pipeline: /** * gst_camerabin_preview_send_event: - * @camera: the #GstCameraBin + * @data: preview pipeline data to use * @evt: The #GstEvent to be pushed, takes ownership * * Pushes an event to the preview pipeline. @@ -305,21 +314,50 @@ no_pipeline: * Returns: True if the event was handled */ gboolean -gst_camerabin_preview_send_event (GstCameraBin * camera, GstElement * pipeline, +gst_camerabin_preview_send_event (GstCameraBinPreviewPipelineData * data, GstEvent * evt) { GstElement *src; - gboolean ret = FALSE; - src = gst_bin_get_by_name (GST_BIN (pipeline), "prev_src"); + src = gst_bin_get_by_name (GST_BIN (data->pipeline), "prev_src"); if (!src) { GST_WARNING ("Preview pipeline doesn't have src element, can't push event"); gst_event_unref (evt); - } else { - GST_DEBUG_OBJECT (camera, "Pushing event %p to preview pipeline", evt); - ret = gst_element_send_event (src, evt); - gst_object_unref (src); + return FALSE; } - return ret; + GST_DEBUG_OBJECT (data->element, "Pushing event %p to preview pipeline", evt); + + return gst_element_send_event (src, evt); +} + +/** + * gst_camerabin_preview_set_caps: + * @data: preview pipeline data to use + * @caps: New #GstCaps to be set for the pipeline + * + * Sets new caps for the preview pipeline + */ +void +gst_camerabin_preview_set_caps (GstCameraBinPreviewPipelineData * data, + GstCaps * caps) +{ + GstState state, pending; + GstStateChangeReturn ret; + + g_return_if_fail (data->pipeline != NULL); + g_return_if_fail (caps != NULL); + + ret = gst_element_get_state (data->pipeline, &state, &pending, 0); + if (ret == GST_STATE_CHANGE_FAILURE) { + /* make it try again */ + state = GST_STATE_PLAYING; + pending = GST_STATE_VOID_PENDING; + } + + gst_element_set_state (data->pipeline, GST_STATE_NULL); + g_object_set (data->capsfilter, "caps", caps, NULL); + if (pending != GST_STATE_VOID_PENDING) + state = pending; + gst_element_set_state (data->pipeline, state); } diff --git a/gst/camerabin/camerabinpreview.h b/gst/camerabin/camerabinpreview.h index cde9f7b883..3da9a05b3a 100644 --- a/gst/camerabin/camerabinpreview.h +++ b/gst/camerabin/camerabinpreview.h @@ -23,20 +23,35 @@ #include -#include "gstcamerabin.h" - G_BEGIN_DECLS - GstElement * gst_camerabin_preview_create_pipeline (GstCameraBin * camera, - GstCaps * caps, GstElement * src_filter); -void gst_camerabin_preview_destroy_pipeline (GstCameraBin * camera, - GstElement * pipeline); +typedef struct +{ + GstElement *pipeline; -GstBuffer *gst_camerabin_preview_convert (GstCameraBin * camera, - GstElement * pipeline, GstBuffer * buf); + GstElement *appsrc; + GstElement *capsfilter; + GstElement *appsink; -gboolean gst_camerabin_preview_send_event (GstCameraBin * camera, - GstElement * pipeline, GstEvent * event); + GstElement *element; +} GstCameraBinPreviewPipelineData; + + +GstCameraBinPreviewPipelineData * gst_camerabin_preview_create_pipeline ( + GstElement *element, GstCaps *caps, GstElement *src_filter); + +void gst_camerabin_preview_destroy_pipeline ( + GstCameraBinPreviewPipelineData *data); + +GstBuffer *gst_camerabin_preview_convert ( + GstCameraBinPreviewPipelineData *data, GstBuffer *buf); + +gboolean gst_camerabin_preview_send_event ( + GstCameraBinPreviewPipelineData *pipeline, GstEvent *event); + +void gst_camerabin_preview_set_caps ( + GstCameraBinPreviewPipelineData *pipeline, GstCaps *caps); G_END_DECLS + #endif /* __CAMERABINPREVIEW_H__ */ diff --git a/gst/camerabin/gstcamerabin.c b/gst/camerabin/gstcamerabin.c index 0cc6444ae6..8267500e58 100644 --- a/gst/camerabin/gstcamerabin.c +++ b/gst/camerabin/gstcamerabin.c @@ -1760,7 +1760,7 @@ camerabin_pad_blocked (GstPad * pad, gboolean blocked, gpointer user_data) static gboolean gst_camerabin_send_preview (GstCameraBin * camera, GstBuffer * buffer) { - GstElement *pipeline; + GstCameraBinPreviewPipelineData *data; GstBuffer *prev = NULL; GstStructure *s; GstMessage *msg; @@ -1768,9 +1768,9 @@ gst_camerabin_send_preview (GstCameraBin * camera, GstBuffer * buffer) GST_DEBUG_OBJECT (camera, "creating preview"); - pipeline = (camera->mode == MODE_IMAGE) ? + data = (camera->mode == MODE_IMAGE) ? camera->preview_pipeline : camera->video_preview_pipeline; - prev = gst_camerabin_preview_convert (camera, pipeline, buffer); + prev = gst_camerabin_preview_convert (data, buffer); GST_DEBUG_OBJECT (camera, "preview created: %p", prev); @@ -1865,12 +1865,11 @@ gst_camerabin_have_img_buffer (GstPad * pad, GstMiniObject * obj, /* forward tag events to preview pipeline */ if (camera->preview_caps && GST_EVENT_TYPE (event) == GST_EVENT_TAG) { - GstElement *pipeline; + GstCameraBinPreviewPipelineData *data; - pipeline = (camera->mode == MODE_IMAGE) ? + data = (camera->mode == MODE_IMAGE) ? camera->preview_pipeline : camera->video_preview_pipeline; - gst_camerabin_preview_send_event (camera, pipeline, - gst_event_ref (event)); + gst_camerabin_preview_send_event (data, gst_event_ref (event)); } } @@ -3373,12 +3372,11 @@ gst_camerabin_dispose (GObject * object) gst_object_unref (camera->vidbin); if (camera->preview_pipeline) { - gst_camerabin_preview_destroy_pipeline (camera, camera->preview_pipeline); + gst_camerabin_preview_destroy_pipeline (camera->preview_pipeline); camera->preview_pipeline = NULL; } if (camera->video_preview_pipeline) { - gst_camerabin_preview_destroy_pipeline (camera, - camera->video_preview_pipeline); + gst_camerabin_preview_destroy_pipeline (camera->video_preview_pipeline); camera->video_preview_pipeline = NULL; } @@ -3525,7 +3523,7 @@ gst_camerabin_set_property (GObject * object, guint prop_id, break; case ARG_PREVIEW_CAPS: { - GstElement **prev_pipe = NULL; + GstCameraBinPreviewPipelineData **prev_pipe = NULL; GstElement **preview_source_filter = NULL; GstCaps **prev_caps = NULL; GstCaps *new_caps = NULL; @@ -3545,19 +3543,20 @@ gst_camerabin_set_property (GObject * object, guint prop_id, if (prev_caps && !gst_caps_is_equal (*prev_caps, new_caps)) { GST_DEBUG_OBJECT (camera, "setting preview caps: %" GST_PTR_FORMAT, new_caps); - if (*prev_pipe) { - gst_camerabin_preview_destroy_pipeline (camera, *prev_pipe); - *prev_pipe = NULL; - } + GST_OBJECT_LOCK (camera); gst_caps_replace (prev_caps, new_caps); GST_OBJECT_UNLOCK (camera); if (new_caps && !gst_caps_is_any (new_caps) && !gst_caps_is_empty (new_caps)) { - *prev_pipe = - gst_camerabin_preview_create_pipeline (camera, new_caps, - *preview_source_filter); + if (!*prev_pipe) { + *prev_pipe = + gst_camerabin_preview_create_pipeline (GST_ELEMENT (camera), + new_caps, *preview_source_filter); + } else { + gst_camerabin_preview_set_caps (*prev_pipe, new_caps); + } } } break; @@ -3568,7 +3567,7 @@ gst_camerabin_set_property (GObject * object, guint prop_id, ("camerabin must be in NULL state when setting the preview source filter element"), (NULL)); } else { - GstElement **preview_pipe = NULL; + GstCameraBinPreviewPipelineData **preview_pipe = NULL; GstElement **preview_source_filter = NULL; GstCaps *preview_caps = NULL; @@ -3587,10 +3586,10 @@ gst_camerabin_set_property (GObject * object, guint prop_id, *preview_source_filter = g_value_dup_object (value); if (*preview_pipe) { - gst_camerabin_preview_destroy_pipeline (camera, *preview_pipe); + gst_camerabin_preview_destroy_pipeline (*preview_pipe); *preview_pipe = - gst_camerabin_preview_create_pipeline (camera, preview_caps, - *preview_source_filter); + gst_camerabin_preview_create_pipeline (GST_ELEMENT (camera), + preview_caps, *preview_source_filter); } } break; diff --git a/gst/camerabin/gstcamerabin.h b/gst/camerabin/gstcamerabin.h index d53af1e1bc..066545c94c 100644 --- a/gst/camerabin/gstcamerabin.h +++ b/gst/camerabin/gstcamerabin.h @@ -31,6 +31,7 @@ #include "gstcamerabin-enum.h" #include "camerabinimage.h" #include "camerabinvideo.h" +#include "camerabinpreview.h" G_BEGIN_DECLS /* #defines don't like whitespacey bits */ @@ -147,8 +148,10 @@ struct _GstCameraBin GstElement *imgbin; /* bin that holds image capturing elements */ GstElement *vidbin; /* bin that holds video capturing elements */ GstElement *active_bin; /* image or video bin that is currently in use */ - GstElement *preview_pipeline; /* pipeline for creating preview images */ - GstElement *video_preview_pipeline; /* pipeline for creating video preview image */ + /* pipeline for creating preview images */ + GstCameraBinPreviewPipelineData *preview_pipeline; + /* pipeline for creating video preview image */ + GstCameraBinPreviewPipelineData *video_preview_pipeline; GstBuffer *video_preview_buffer; /* buffer for storing video preview */ From c57a9e4ba9e267b9b370d4f6c61675504a69184d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Mon, 31 Jan 2011 17:45:19 +0000 Subject: [PATCH 375/448] videoparsers: dist h264parse.h, fixing make distcheck Spotted by Nathanael D. Noblet --- gst/videoparsers/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst/videoparsers/Makefile.am b/gst/videoparsers/Makefile.am index 0ff15e7d42..171c7ce1f5 100644 --- a/gst/videoparsers/Makefile.am +++ b/gst/videoparsers/Makefile.am @@ -8,5 +8,5 @@ libgsth263parse_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) libgsth263parse_la_LIBTOOLFLAGS = --tag=disable-static noinst_HEADERS = gsth263parse.h h263parse.h \ - gsth264parse.h gsth264parse.h \ + gsth264parse.h gsth264parse.h h264parse.h \ gstbaseparse.h From 149cca83d05a486bad3cb87553d3554940305b5f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Tue, 1 Feb 2011 14:40:54 +0000 Subject: [PATCH 376/448] id3mux: map new GST_TAG_ENCODED_BY to ID3v2 TENC frame https://bugzilla.gnome.org/show_bug.cgi?id=627268 --- configure.ac | 2 +- gst/id3tag/id3tag.c | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/configure.ac b/configure.ac index 618aef90bd..3da824432f 100644 --- a/configure.ac +++ b/configure.ac @@ -50,7 +50,7 @@ AC_LIBTOOL_WIN32_DLL AM_PROG_LIBTOOL dnl *** required versions of GStreamer stuff *** -GST_REQ=0.10.32 +GST_REQ=0.10.32.1 GSTPB_REQ=0.10.32 dnl *** autotools stuff **** diff --git a/gst/id3tag/id3tag.c b/gst/id3tag/id3tag.c index 272301bd1e..2f3bebf848 100644 --- a/gst/id3tag/id3tag.c +++ b/gst/id3tag/id3tag.c @@ -1047,6 +1047,7 @@ static const struct GST_TAG_COPYRIGHT, add_text_tag, "TCOP"}, { GST_TAG_COMPOSER, add_text_tag, "TCOM"}, { GST_TAG_GENRE, add_text_tag, "TCON"}, { + GST_TAG_ENCODED_BY, add_text_tag, "TENC"}, { /* Private frames */ GST_ID3_DEMUX_TAG_ID3V2_FRAME, add_id3v2frame_tag, NULL}, { From 17c2b30e9ba502a1a7b6b7e14c63ebc6f43ec908 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Tue, 1 Feb 2011 20:01:13 +0000 Subject: [PATCH 377/448] rtpvp8: also link against libgstbase-0.10 for adapter and bit reader API https://bugzilla.gnome.org/show_bug.cgi?id=641178 --- gst/rtpvp8/Makefile.am | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/gst/rtpvp8/Makefile.am b/gst/rtpvp8/Makefile.am index 8a722ebc0a..05bf5d7c4c 100644 --- a/gst/rtpvp8/Makefile.am +++ b/gst/rtpvp8/Makefile.am @@ -7,8 +7,9 @@ libgstrtpvp8_la_SOURCES = gstrtpvp8.c \ noinst_HEADERS = gstrtpvp8depay.h \ gstrtpvp8pay.h -libgstrtpvp8_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_CFLAGS) +libgstrtpvp8_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) \ + $(GST_BASE_CFLAGS) $(GST_CFLAGS) libgstrtpvp8_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) -lgstrtp-@GST_MAJORMINOR@ \ - $(GST_LIBS) + $(GST_BASE_LIBS) $(GST_LIBS) libgstrtpvp8_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) libgstrtpvp8_la_LIBTOOLFLAGS = --tag=disable-static From c32a99559d2826668cb891cc7aff83af587e39b0 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Mon, 31 Jan 2011 17:24:24 +0100 Subject: [PATCH 378/448] dccp: use socklen_t where appropriate rather than specific type In particular, fixes Cygwin build where socklen_t is defined as int in line with native win32 api definition. --- gst/dccp/gstdccp.c | 6 +----- gst/dccp/gstdccp_common.h | 3 +++ 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/gst/dccp/gstdccp.c b/gst/dccp/gstdccp.c index 470c217ac0..af652f2de6 100644 --- a/gst/dccp/gstdccp.c +++ b/gst/dccp/gstdccp.c @@ -241,18 +241,14 @@ gst_dccp_server_wait_connections (GstElement * element, int server_sock_fd) /* new client */ int client_sock_fd; struct sockaddr_in client_address; - unsigned int client_address_len; + socklen_t client_address_len; memset (&client_address, 0, sizeof (client_address)); client_address_len = 0; if ((client_sock_fd = accept (server_sock_fd, (struct sockaddr *) &client_address, -#ifndef G_OS_WIN32 &client_address_len)) == -1) { -#else - (int *) &client_address_len)) == -1) { -#endif GST_ELEMENT_ERROR (element, RESOURCE, OPEN_WRITE, (NULL), ("Could not accept client on server socket %d: %s (%d)", server_sock_fd, g_strerror (errno), errno)); diff --git a/gst/dccp/gstdccp_common.h b/gst/dccp/gstdccp_common.h index 9657806183..a2c2ca2a36 100644 --- a/gst/dccp/gstdccp_common.h +++ b/gst/dccp/gstdccp_common.h @@ -32,6 +32,9 @@ # define WINVER 0x0501 # include # include +#ifndef socklen_t +#define socklen_t int +#endif #endif #include #include From 14375582fa8ae44a356eb4a3aabb267b47fd7327 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Wed, 2 Feb 2011 18:41:39 +0000 Subject: [PATCH 379/448] dvbsrc: fix up enum nick names https://bugzilla.gnome.org/show_bug.cgi?id=591651 --- sys/dvb/gstdvbsrc.c | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/sys/dvb/gstdvbsrc.c b/sys/dvb/gstdvbsrc.c index a136027d4e..2f18431ada 100644 --- a/sys/dvb/gstdvbsrc.c +++ b/sys/dvb/gstdvbsrc.c @@ -117,7 +117,7 @@ gst_dvbsrc_code_rate_get_type (void) { static GType dvbsrc_code_rate_type = 0; static GEnumValue code_rate_types[] = { - {FEC_NONE, "NONE", "NONE"}, + {FEC_NONE, "NONE", "none"}, {FEC_1_2, "1/2", "1/2"}, {FEC_2_3, "2/3", "2/3"}, {FEC_3_4, "3/4", "3/4"}, @@ -126,7 +126,7 @@ gst_dvbsrc_code_rate_get_type (void) {FEC_6_7, "6/7", "6/7"}, {FEC_7_8, "7/8", "7/8"}, {FEC_8_9, "8/9", "8/9"}, - {FEC_AUTO, "AUTO", ""}, + {FEC_AUTO, "AUTO", "auto"}, {0, NULL, NULL}, }; @@ -143,15 +143,15 @@ gst_dvbsrc_modulation_get_type (void) { static GType dvbsrc_modulation_type = 0; static GEnumValue modulation_types[] = { - {QPSK, "QPSK", "QPSK"}, - {QAM_16, "QAM 16", "QAM 16"}, - {QAM_32, "QAM 32", "QAM 32"}, - {QAM_64, "QAM 64", "QAM 64"}, - {QAM_128, "QAM 128", "QAM 128"}, - {QAM_256, "QAM 256", "QAM 256"}, - {QAM_AUTO, "AUTO", "AUTO"}, - {VSB_8, "8VSB", "8VSB"}, - {VSB_16, "16VSB", "16VSB"}, + {QPSK, "QPSK", "qpsk"}, + {QAM_16, "QAM 16", "qam-16"}, + {QAM_32, "QAM 32", "qam-32"}, + {QAM_64, "QAM 64", "qam-64"}, + {QAM_128, "QAM 128", "qam-128"}, + {QAM_256, "QAM 256", "qam-256"}, + {QAM_AUTO, "AUTO", "auto"}, + {VSB_8, "8VSB", "8vsb"}, + {VSB_16, "16VSB", "16vsb"}, {0, NULL, NULL}, }; @@ -168,9 +168,9 @@ gst_dvbsrc_transmission_mode_get_type (void) { static GType dvbsrc_transmission_mode_type = 0; static GEnumValue transmission_mode_types[] = { - {TRANSMISSION_MODE_2K, "2k", "2k"}, - {TRANSMISSION_MODE_8K, "8k", "8k"}, - {TRANSMISSION_MODE_AUTO, "AUTO", "AUTO"}, + {TRANSMISSION_MODE_2K, "2K", "2k"}, + {TRANSMISSION_MODE_8K, "8K", "8k"}, + {TRANSMISSION_MODE_AUTO, "AUTO", "auto"}, {0, NULL, NULL}, }; @@ -212,7 +212,7 @@ gst_dvbsrc_guard_get_type (void) {GUARD_INTERVAL_1_16, "16", "16"}, {GUARD_INTERVAL_1_8, "8", "8"}, {GUARD_INTERVAL_1_4, "4", "4"}, - {GUARD_INTERVAL_AUTO, "AUTO", "AUTO"}, + {GUARD_INTERVAL_AUTO, "AUTO", "auto"}, {0, NULL, NULL}, }; @@ -228,11 +228,11 @@ gst_dvbsrc_hierarchy_get_type (void) { static GType dvbsrc_hierarchy_type = 0; static GEnumValue hierarchy_types[] = { - {HIERARCHY_NONE, "NONE", "NONE"}, + {HIERARCHY_NONE, "NONE", "none"}, {HIERARCHY_1, "1", "1"}, {HIERARCHY_2, "2", "2"}, {HIERARCHY_4, "4", "4"}, - {HIERARCHY_AUTO, "AUTO", "AUTO"}, + {HIERARCHY_AUTO, "AUTO", "auto"}, {0, NULL, NULL}, }; @@ -249,9 +249,9 @@ gst_dvbsrc_inversion_get_type (void) { static GType dvbsrc_inversion_type = 0; static GEnumValue inversion_types[] = { - {INVERSION_OFF, "OFF", "OFF"}, - {INVERSION_ON, "ON", "ON"}, - {INVERSION_AUTO, "AUTO", "AUTO"}, + {INVERSION_OFF, "OFF", "off"}, + {INVERSION_ON, "ON", "on"}, + {INVERSION_AUTO, "AUTO", "auto"}, {0, NULL, NULL}, }; From 4724ecfd0671b1b3e4affda52a86ee5658a35a85 Mon Sep 17 00:00:00 2001 From: Edward Hervey Date: Thu, 3 Feb 2011 16:24:24 +0100 Subject: [PATCH 380/448] camerabin: Initialize variables Makes compilers happy --- gst/camerabin/camerabinpreview.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst/camerabin/camerabinpreview.c b/gst/camerabin/camerabinpreview.c index 434a92f7a5..5f46d0628a 100644 --- a/gst/camerabin/camerabinpreview.c +++ b/gst/camerabin/camerabinpreview.c @@ -73,7 +73,7 @@ GstCameraBinPreviewPipelineData * gst_camerabin_preview_create_pipeline (GstElement * element, GstCaps * caps, GstElement * src_filter) { - GstElement *csp, *vscale; + GstElement *csp = NULL, *vscale = NULL; GError *error = NULL; GstCameraBinPreviewPipelineData *data; From 675632b38237549dc68effd1caeaa836aa4e933c Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Wed, 26 Jan 2011 15:27:19 -0300 Subject: [PATCH 381/448] camerabin2: Add custom filter properties Adds custom filter properties for camerabin2. Custom filters can be added to video/image/preview branches. --- gst/camerabin2/gstcamerabin2.c | 123 ++++++++++++++++++++++++++++++++- gst/camerabin2/gstcamerabin2.h | 7 ++ 2 files changed, 129 insertions(+), 1 deletion(-) diff --git a/gst/camerabin2/gstcamerabin2.c b/gst/camerabin2/gstcamerabin2.c index 456a7ea261..85a56967a6 100644 --- a/gst/camerabin2/gstcamerabin2.c +++ b/gst/camerabin2/gstcamerabin2.c @@ -40,7 +40,10 @@ * have room to set the destination filename). * There is no problem to leave it on playing after an EOS, so * no action is taken on stop-capture. + * * - TODO: What happens when an error pops? + * - TODO: Should we split properties in image/video variants? We already do so + * for some of them * * */ @@ -69,7 +72,10 @@ enum PROP_VIDEO_CAPTURE_CAPS, PROP_POST_PREVIEWS, PROP_PREVIEW_CAPS, - PROP_VIDEO_ENCODING_PROFILE + PROP_VIDEO_ENCODING_PROFILE, + PROP_IMAGE_FILTER, + PROP_VIDEO_FILTER, + PROP_VIEWFINDER_FILTER }; enum @@ -278,6 +284,20 @@ gst_camera_bin_dispose (GObject * object) if (camerabin->imagebin_capsfilter) gst_object_unref (camerabin->imagebin_capsfilter); + if (camerabin->video_filter) + gst_object_unref (camerabin->video_filter); + if (camerabin->image_filter) + gst_object_unref (camerabin->image_filter); + if (camerabin->viewfinder_filter) + gst_object_unref (camerabin->viewfinder_filter); + + if (camerabin->user_video_filter) + gst_object_unref (camerabin->user_video_filter); + if (camerabin->user_image_filter) + gst_object_unref (camerabin->user_image_filter); + if (camerabin->user_viewfinder_filter) + gst_object_unref (camerabin->user_viewfinder_filter); + if (camerabin->video_profile) gst_encoding_profile_unref (camerabin->video_profile); @@ -394,6 +414,25 @@ gst_camera_bin_class_init (GstCameraBinClass * klass) GST_TYPE_ENCODING_PROFILE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (object_class, PROP_IMAGE_FILTER, + g_param_spec_object ("image-filter", "Image filter", + "The element that will process captured image frames. (Should be" + " set on NULL state)", + GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (object_class, PROP_VIDEO_FILTER, + g_param_spec_object ("video-filter", "Video filter", + "The element that will process captured video frames. (Should be" + " set on NULL state)", + GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (object_class, PROP_VIEWFINDER_FILTER, + g_param_spec_object ("viewfinder-filter", "Viewfinder filter", + "The element that will process frames going to the viewfinder." + " (Should be set on NULL state)", + GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + /** * GstCameraBin::capture-start: * @camera: the camera bin element @@ -479,6 +518,48 @@ gst_camera_bin_handle_message (GstBin * bin, GstMessage * message) GST_BIN_CLASS (parent_class)->handle_message (bin, message); } +/* + * Transforms: + * ... ! previous_element [ ! current_filter ] ! next_element ! ... + * + * into: + * ... ! previous_element [ ! new_filter ] ! next_element ! ... + * + * Where current_filter and new_filter might or might not be NULL + */ +static void +gst_camera_bin_check_and_replace_filter (GstCameraBin * camera, + GstElement ** current_filter, GstElement * new_filter, + GstElement * previous_element, GstElement * next_element) +{ + if (*current_filter == new_filter) { + GST_DEBUG_OBJECT (camera, "Current filter is the same as the previous, " + "no switch needed."); + return; + } + + GST_DEBUG_OBJECT (camera, "Replacing current filter (%s) with new filter " + "(%s)", *current_filter ? GST_ELEMENT_NAME (*current_filter) : "null", + new_filter ? GST_ELEMENT_NAME (new_filter) : "null"); + + if (*current_filter) { + gst_bin_remove (GST_BIN_CAST (camera), *current_filter); + gst_object_unref (*current_filter); + *current_filter = NULL; + } else { + /* unlink the pads */ + gst_element_unlink (previous_element, next_element); + } + + if (new_filter) { + *current_filter = gst_object_ref (new_filter); + gst_bin_add (GST_BIN_CAST (camera), gst_object_ref (new_filter)); + gst_element_link_many (previous_element, new_filter, next_element, NULL); + } else { + gst_element_link (previous_element, next_element); + } +} + /** * gst_camera_bin_create_elements: * @param camera: the #GstCameraBin @@ -612,6 +693,16 @@ gst_camera_bin_create_elements (GstCameraBin * camera) "sink"); } + gst_camera_bin_check_and_replace_filter (camera, &camera->image_filter, + camera->user_image_filter, camera->imagebin_queue, + camera->imagebin_capsfilter); + gst_camera_bin_check_and_replace_filter (camera, &camera->video_filter, + camera->user_video_filter, camera->videobin_queue, + camera->videobin_capsfilter); + gst_camera_bin_check_and_replace_filter (camera, &camera->viewfinder_filter, + camera->user_viewfinder_filter, camera->viewfinderbin_queue, + camera->viewfinderbin_capsfilter); + camera->elements_created = TRUE; return TRUE; } @@ -763,6 +854,24 @@ gst_camera_bin_set_property (GObject * object, guint prop_id, camera->video_profile = (GstEncodingProfile *) gst_value_dup_mini_object (value); break; + case PROP_IMAGE_FILTER: + if (camera->user_image_filter) + g_object_unref (camera->user_image_filter); + + camera->user_image_filter = g_value_dup_object (value); + break; + case PROP_VIDEO_FILTER: + if (camera->user_video_filter) + g_object_unref (camera->user_video_filter); + + camera->user_video_filter = g_value_dup_object (value); + break; + case PROP_VIEWFINDER_FILTER: + if (camera->user_viewfinder_filter) + g_object_unref (camera->user_viewfinder_filter); + + camera->user_viewfinder_filter = g_value_dup_object (value); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -851,6 +960,18 @@ gst_camera_bin_get_property (GObject * object, guint prop_id, (GstMiniObject *) camera->video_profile); } break; + case PROP_VIDEO_FILTER: + if (camera->video_filter) + g_value_set_object (value, camera->video_filter); + break; + case PROP_IMAGE_FILTER: + if (camera->image_filter) + g_value_set_object (value, camera->image_filter); + break; + case PROP_VIEWFINDER_FILTER: + if (camera->viewfinder_filter) + g_value_set_object (value, camera->viewfinder_filter); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; diff --git a/gst/camerabin2/gstcamerabin2.h b/gst/camerabin2/gstcamerabin2.h index 8534674aa4..f24417f1eb 100644 --- a/gst/camerabin2/gstcamerabin2.h +++ b/gst/camerabin2/gstcamerabin2.h @@ -55,6 +55,13 @@ struct _GstCameraBin GstElement *imagebin_queue; GstElement *imagebin_capsfilter; + GstElement *video_filter; + GstElement *image_filter; + GstElement *viewfinder_filter; + GstElement *user_video_filter; + GstElement *user_image_filter; + GstElement *user_viewfinder_filter; + /* Index of the auto incrementing file index for video recordings */ gint video_index; From b2a45f6f21f44ca0d0c127c6a7f1fe25a206dea0 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Thu, 27 Jan 2011 10:19:42 -0300 Subject: [PATCH 382/448] tests: camerabin2: Add tests for custom filters Adds tests to check that custom filters elements receive buffers --- tests/check/elements/camerabin2.c | 127 ++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) diff --git a/tests/check/elements/camerabin2.c b/tests/check/elements/camerabin2.c index 23c9379944..1b0ddf4556 100644 --- a/tests/check/elements/camerabin2.c +++ b/tests/check/elements/camerabin2.c @@ -505,6 +505,16 @@ check_file_validity (const gchar * filename, gint num, GstTagList * taglist, return TRUE; } +static gboolean +filter_buffer_count (GstPad * pad, GstMiniObject * obj, gpointer data) +{ + gint *counter = data; + + (*counter)++; + + return TRUE; +} + GST_START_TEST (test_single_image_capture) { if (!camera) @@ -974,6 +984,120 @@ GST_START_TEST (test_supported_caps) GST_END_TEST; +GST_START_TEST (test_image_custom_filter) +{ + GstElement *vf_filter; + GstElement *image_filter; + GstPad *pad; + gint vf_probe_counter = 0; + gint image_probe_counter = 0; + + if (!camera) + return; + + vf_filter = gst_element_factory_make ("identity", "vf-filter"); + image_filter = gst_element_factory_make ("identity", "img-filter"); + + pad = gst_element_get_static_pad (vf_filter, "src"); + gst_pad_add_buffer_probe (pad, (GCallback) filter_buffer_count, + &vf_probe_counter); + gst_object_unref (pad); + + pad = gst_element_get_static_pad (image_filter, "src"); + gst_pad_add_buffer_probe (pad, (GCallback) filter_buffer_count, + &image_probe_counter); + gst_object_unref (pad); + + /* set still image mode and filters */ + g_object_set (camera, "mode", 1, + "location", make_test_file_name (IMAGE_FILENAME, -1), + "viewfinder-filter", vf_filter, "image-filter", image_filter, NULL); + + if (gst_element_set_state (GST_ELEMENT (camera), GST_STATE_PLAYING) == + GST_STATE_CHANGE_FAILURE) { + GST_WARNING ("setting camerabin to PLAYING failed"); + gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL); + gst_object_unref (camera); + camera = NULL; + } + GST_INFO ("starting capture"); + fail_unless (camera != NULL); + g_signal_emit_by_name (camera, "start-capture", NULL); + + g_timeout_add_seconds (3, (GSourceFunc) g_main_loop_quit, main_loop); + g_main_loop_run (main_loop); + + /* check that we got a preview image */ + check_preview_image (); + + gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL); + check_file_validity (IMAGE_FILENAME, 0, NULL, 0, 0); + + fail_unless (vf_probe_counter > 0); + fail_unless (image_probe_counter == 1); +} + +GST_END_TEST; + + +GST_START_TEST (test_video_custom_filter) +{ + GstElement *vf_filter; + GstElement *video_filter; + GstPad *pad; + gint vf_probe_counter = 0; + gint video_probe_counter = 0; + + if (!camera) + return; + + vf_filter = gst_element_factory_make ("identity", "vf-filter"); + video_filter = gst_element_factory_make ("identity", "video-filter"); + + pad = gst_element_get_static_pad (vf_filter, "src"); + gst_pad_add_buffer_probe (pad, (GCallback) filter_buffer_count, + &vf_probe_counter); + gst_object_unref (pad); + + pad = gst_element_get_static_pad (video_filter, "src"); + gst_pad_add_buffer_probe (pad, (GCallback) filter_buffer_count, + &video_probe_counter); + gst_object_unref (pad); + + /* set still image mode and filters */ + g_object_set (camera, "mode", 2, + "location", make_test_file_name (VIDEO_FILENAME, -1), + "viewfinder-filter", vf_filter, "video-filter", video_filter, NULL); + + if (gst_element_set_state (GST_ELEMENT (camera), GST_STATE_PLAYING) == + GST_STATE_CHANGE_FAILURE) { + GST_WARNING ("setting camerabin to PLAYING failed"); + gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL); + gst_object_unref (camera); + camera = NULL; + } + GST_INFO ("starting capture"); + fail_unless (camera != NULL); + g_signal_emit_by_name (camera, "start-capture", NULL); + + g_timeout_add_seconds (VIDEO_DURATION, (GSourceFunc) g_main_loop_quit, + main_loop); + g_main_loop_run (main_loop); + g_signal_emit_by_name (camera, "stop-capture", NULL); + + /* check that we got a preview image */ + check_preview_image (); + + gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL); + check_file_validity (VIDEO_FILENAME, 0, NULL, 0, 0); + + fail_unless (vf_probe_counter > 0); + fail_unless (video_probe_counter > 0); +} + +GST_END_TEST; + + typedef struct _TestCaseDef { const gchar *name; @@ -1026,6 +1150,9 @@ camerabin_suite (void) tcase_add_test (tc_basic, test_image_capture_with_tags); tcase_add_test (tc_basic, test_video_capture_with_tags); + + tcase_add_test (tc_basic, test_image_custom_filter); + tcase_add_test (tc_basic, test_video_custom_filter); } end: From 869a61343c415cee12fef7dd43d4c1a0114acf4c Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Thu, 27 Jan 2011 14:39:19 -0300 Subject: [PATCH 383/448] camerabin2: Add preview-filter property Adds a property to select a custom element for preview pipeline buffers processing --- gst/camerabin2/camerabingeneral.c | 19 +- gst/camerabin2/camerabingeneral.h | 3 +- gst/camerabin2/gstcamerabin2.c | 31 ++- gst/camerabin2/gstcamerabin2.h | 1 + gst/camerabin2/gstwrappercamerabinsrc.c | 260 +++++++++++++----------- gst/camerabin2/gstwrappercamerabinsrc.h | 2 + 6 files changed, 195 insertions(+), 121 deletions(-) diff --git a/gst/camerabin2/camerabingeneral.c b/gst/camerabin2/camerabingeneral.c index d6c1c86744..26edc12d0f 100644 --- a/gst/camerabin2/camerabingeneral.c +++ b/gst/camerabin2/camerabingeneral.c @@ -320,6 +320,7 @@ gst_camerabin_preview_pipeline_new_buffer (GstAppSink * appsink, /** * gst_camerabin_create_preview_pipeline: * @element: Owner of this pipeline + * @filter: Custom filter to process preview data (an extra ref is taken) * * Creates a new previewing pipeline that can receive buffers * to be posted as camerabin preview messages for @element @@ -327,7 +328,8 @@ gst_camerabin_preview_pipeline_new_buffer (GstAppSink * appsink, * Returns: The newly created #GstCameraBinPreviewPipelineData */ GstCameraBinPreviewPipelineData * -gst_camerabin_create_preview_pipeline (GstElement * element) +gst_camerabin_create_preview_pipeline (GstElement * element, + GstElement * filter) { GstCameraBinPreviewPipelineData *data; GstElement *csp; @@ -354,11 +356,19 @@ gst_camerabin_create_preview_pipeline (GstElement * element) gst_bin_add_many (GST_BIN (data->pipeline), data->appsrc, data->capsfilter, data->appsink, csp, csp2, vscale, NULL); + if (filter) + gst_bin_add (GST_BIN (data->pipeline), gst_object_ref (filter)); added = TRUE; - if (!gst_element_link_many (data->appsrc, csp, vscale, csp2, data->capsfilter, - data->appsink, NULL)) - goto error; + if (filter) { + if (!gst_element_link_many (data->appsrc, filter, csp, vscale, csp2, + data->capsfilter, data->appsink, NULL)) + goto error; + } else { + if (!gst_element_link_many (data->appsrc, csp, vscale, csp2, + data->capsfilter, data->appsink, NULL)) + goto error; + } callbacks.new_preroll = gst_camerabin_preview_pipeline_new_preroll; callbacks.new_buffer = gst_camerabin_preview_pipeline_new_buffer; @@ -366,6 +376,7 @@ gst_camerabin_create_preview_pipeline (GstElement * element) NULL); data->element = element; + data->filter = filter; return data; error: diff --git a/gst/camerabin2/camerabingeneral.h b/gst/camerabin2/camerabingeneral.h index 4e0812a994..f39cbd77ef 100644 --- a/gst/camerabin2/camerabingeneral.h +++ b/gst/camerabin2/camerabingeneral.h @@ -28,13 +28,14 @@ typedef struct GstElement *pipeline; GstElement *appsrc; + GstElement *filter; GstElement *capsfilter; GstElement *appsink; GstElement *element; } GstCameraBinPreviewPipelineData; -GstCameraBinPreviewPipelineData *gst_camerabin_create_preview_pipeline (GstElement * element); +GstCameraBinPreviewPipelineData *gst_camerabin_create_preview_pipeline (GstElement * element, GstElement * filter); void gst_camerabin_destroy_preview_pipeline (GstCameraBinPreviewPipelineData * preview); gboolean gst_camerabin_preview_pipeline_post (GstCameraBinPreviewPipelineData * preview, GstBuffer * buffer); void gst_camerabin_preview_set_caps (GstCameraBinPreviewPipelineData * preview, GstCaps * caps); diff --git a/gst/camerabin2/gstcamerabin2.c b/gst/camerabin2/gstcamerabin2.c index 85a56967a6..d7139a4ab6 100644 --- a/gst/camerabin2/gstcamerabin2.c +++ b/gst/camerabin2/gstcamerabin2.c @@ -75,7 +75,8 @@ enum PROP_VIDEO_ENCODING_PROFILE, PROP_IMAGE_FILTER, PROP_VIDEO_FILTER, - PROP_VIEWFINDER_FILTER + PROP_VIEWFINDER_FILTER, + PROP_PREVIEW_FILTER }; enum @@ -303,6 +304,10 @@ gst_camera_bin_dispose (GObject * object) if (camerabin->preview_caps) gst_caps_replace (&camerabin->preview_caps, NULL); + if (camerabin->preview_filter) { + gst_object_unref (camerabin->preview_filter); + camerabin->preview_filter = NULL; + } G_OBJECT_CLASS (parent_class)->dispose (object); } @@ -432,6 +437,12 @@ gst_camera_bin_class_init (GstCameraBinClass * klass) " (Should be set on NULL state)", GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (object_class, PROP_PREVIEW_FILTER, + g_param_spec_object ("preview-filter", "Preview filter", + "The element that will process preview buffers." + " (Should be set on NULL state)", + GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + /** * GstCameraBin::capture-start: @@ -678,7 +689,8 @@ gst_camera_bin_create_elements (GstCameraBin * camera) && g_object_class_find_property (G_OBJECT_GET_CLASS (camera->src), "preview-caps")) { g_object_set (camera->src, "post-previews", camera->post_previews, - "preview-caps", camera->preview_caps, NULL); + "preview-caps", camera->preview_caps, "preview-filter", + camera->preview_filter, NULL); } if (new_src) { gst_bin_add (GST_BIN_CAST (camera), gst_object_ref (camera->src)); @@ -872,6 +884,17 @@ gst_camera_bin_set_property (GObject * object, guint prop_id, camera->user_viewfinder_filter = g_value_dup_object (value); break; + case PROP_PREVIEW_FILTER: + if (camera->preview_filter) + g_object_unref (camera->preview_filter); + + camera->preview_filter = g_value_dup_object (value); + if (camera->src + && g_object_class_find_property (G_OBJECT_GET_CLASS (camera->src), + "preview-filter")) + g_object_set (camera->src, "preview-filter", camera->preview_filter, + NULL); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -972,6 +995,10 @@ gst_camera_bin_get_property (GObject * object, guint prop_id, if (camera->viewfinder_filter) g_value_set_object (value, camera->viewfinder_filter); break; + case PROP_PREVIEW_FILTER: + if (camera->preview_filter) + g_value_set_object (value, camera->preview_filter); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; diff --git a/gst/camerabin2/gstcamerabin2.h b/gst/camerabin2/gstcamerabin2.h index f24417f1eb..64828b49e0 100644 --- a/gst/camerabin2/gstcamerabin2.h +++ b/gst/camerabin2/gstcamerabin2.h @@ -71,6 +71,7 @@ struct _GstCameraBin gchar *image_location; gboolean post_previews; GstCaps *preview_caps; + GstElement *preview_filter; GstEncodingProfile *video_profile; gboolean elements_created; diff --git a/gst/camerabin2/gstwrappercamerabinsrc.c b/gst/camerabin2/gstwrappercamerabinsrc.c index 864373bdc3..c35fe8d77c 100644 --- a/gst/camerabin2/gstwrappercamerabinsrc.c +++ b/gst/camerabin2/gstwrappercamerabinsrc.c @@ -39,7 +39,8 @@ enum PROP_0, PROP_VIDEO_SRC, PROP_POST_PREVIEWS, - PROP_PREVIEW_CAPS + PROP_PREVIEW_CAPS, + PROP_PREVIEW_FILTER }; #define DEFAULT_POST_PREVIEWS TRUE @@ -74,6 +75,11 @@ gst_wrapper_camera_bin_src_dispose (GObject * object) if (self->preview_caps) gst_caps_replace (&self->preview_caps, NULL); + if (self->preview_filter) { + gst_object_unref (self->preview_filter); + self->preview_filter = NULL; + } + G_OBJECT_CLASS (parent_class)->dispose (object); } @@ -113,6 +119,12 @@ gst_wrapper_camera_bin_src_set_property (GObject * object, gst_camerabin_preview_set_caps (self->preview_pipeline, (GstCaps *) gst_value_get_caps (value)); break; + case PROP_PREVIEW_FILTER: + if (self->preview_filter) + gst_object_unref (self->preview_filter); + self->preview_filter = g_value_dup_object (value); + self->preview_filter_changed = TRUE; + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec); break; @@ -139,6 +151,10 @@ gst_wrapper_camera_bin_src_get_property (GObject * object, if (self->preview_caps) gst_value_set_caps (value, self->preview_caps); break; + case PROP_PREVIEW_FILTER: + if (self->preview_filter) + g_value_set_object (value, self->preview_filter); + break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (self, prop_id, pspec); break; @@ -294,127 +310,138 @@ gst_wrapper_camera_bin_src_construct_pipeline (GstBaseCameraSrc * bcamsrc) GstPad *vf_pad; GstPad *tee_capture_pad; - if (self->elements_created) - return TRUE; + if (!self->elements_created) { - GST_DEBUG_OBJECT (self, "constructing pipeline"); + GST_DEBUG_OBJECT (self, "constructing pipeline"); - /* Add application set or default video src element */ - if (!(self->src_vid_src = gst_camerabin_setup_default_element (cbin, - self->app_vid_src, "autovideosrc", DEFAULT_VIDEOSRC, - "camerasrc-real-src"))) { - self->src_vid_src = NULL; - goto done; - } else { - if (!gst_camerabin_add_element (cbin, self->src_vid_src)) { + /* Add application set or default video src element */ + if (!(self->src_vid_src = gst_camerabin_setup_default_element (cbin, + self->app_vid_src, "autovideosrc", DEFAULT_VIDEOSRC, + "camerasrc-real-src"))) { + self->src_vid_src = NULL; goto done; + } else { + if (!gst_camerabin_add_element (cbin, self->src_vid_src)) { + goto done; + } } + /* we lost the reference */ + self->app_vid_src = NULL; + + /* add a buffer probe to the src elemento to drop EOS from READY->NULL */ + { + GstPad *pad; + pad = gst_element_get_static_pad (self->src_vid_src, "src"); + + self->src_event_probe_id = gst_pad_add_event_probe (pad, + (GCallback) gst_camerabin_drop_eos_probe, NULL); + gst_object_unref (pad); + } + + if (!gst_camerabin_create_and_add_element (cbin, "ffmpegcolorspace", + "src-colorspace")) + goto done; + + if (!(self->src_filter = + gst_camerabin_create_and_add_element (cbin, "capsfilter", + "src-capsfilter"))) + goto done; + + if (!(self->src_zoom_crop = + gst_camerabin_create_and_add_element (cbin, "videocrop", + "zoom-crop"))) + goto done; + if (!(self->src_zoom_scale = + gst_camerabin_create_and_add_element (cbin, "videoscale", + "zoom-scale"))) + goto done; + if (!(self->src_zoom_filter = + gst_camerabin_create_and_add_element (cbin, "capsfilter", + "zoom-capsfilter"))) + goto done; + + if (!(tee = + gst_camerabin_create_and_add_element (cbin, "tee", + "camerasrc-tee"))) + goto done; + + /* viewfinder pad */ + vf_pad = gst_element_get_request_pad (tee, "src%d"); + g_object_set (tee, "alloc-pad", vf_pad, NULL); + gst_object_unref (vf_pad); + + /* the viewfinder should always work, so we add some converters to it */ + if (!gst_camerabin_create_and_add_element (cbin, "ffmpegcolorspace", + "viewfinder-colorspace")) + goto done; + if (!(videoscale = + gst_camerabin_create_and_add_element (cbin, "videoscale", + "viewfinder-scale"))) + goto done; + + /* image/video pad from tee */ + tee_capture_pad = gst_element_get_request_pad (tee, "src%d"); + + self->output_selector = + gst_element_factory_make ("output-selector", "outsel"); + g_object_set (self->output_selector, "pad-negotiation-mode", 0, NULL); + gst_bin_add (GST_BIN (self), self->output_selector); + { + GstPad *pad = gst_element_get_static_pad (self->output_selector, "sink"); + + /* check return TODO */ + gst_pad_link (tee_capture_pad, pad); + gst_object_unref (pad); + } + gst_object_unref (tee_capture_pad); + + /* Create the 2 output pads for video and image */ + self->outsel_vidpad = + gst_element_get_request_pad (self->output_selector, "src%d"); + self->outsel_imgpad = + gst_element_get_request_pad (self->output_selector, "src%d"); + + g_assert (self->outsel_vidpad != NULL); + g_assert (self->outsel_imgpad != NULL); + + gst_pad_add_buffer_probe (self->outsel_imgpad, + G_CALLBACK (gst_wrapper_camera_bin_src_imgsrc_probe), self); + gst_pad_add_buffer_probe (self->outsel_vidpad, + G_CALLBACK (gst_wrapper_camera_bin_src_vidsrc_probe), self); + gst_ghost_pad_set_target (GST_GHOST_PAD (self->imgsrc), + self->outsel_imgpad); + gst_ghost_pad_set_target (GST_GHOST_PAD (self->vidsrc), + self->outsel_vidpad); + + if (bcamsrc->mode == MODE_IMAGE) { + g_object_set (self->output_selector, "active-pad", self->outsel_imgpad, + NULL); + } else { + g_object_set (self->output_selector, "active-pad", self->outsel_vidpad, + NULL); + } + + /* hook-up the vf ghostpad */ + vf_pad = gst_element_get_static_pad (videoscale, "src"); + gst_ghost_pad_set_target (GST_GHOST_PAD (self->vfsrc), vf_pad); + gst_object_unref (vf_pad); + + gst_pad_set_active (self->vfsrc, TRUE); + gst_pad_set_active (self->imgsrc, TRUE); /* XXX ??? */ + gst_pad_set_active (self->vidsrc, TRUE); /* XXX ??? */ } - /* we lost the reference */ - self->app_vid_src = NULL; - - /* add a buffer probe to the src elemento to drop EOS from READY->NULL */ - { - GstPad *pad; - pad = gst_element_get_static_pad (self->src_vid_src, "src"); - - self->src_event_probe_id = gst_pad_add_event_probe (pad, - (GCallback) gst_camerabin_drop_eos_probe, NULL); - gst_object_unref (pad); + /* recreate the preview pipeline */ + if (self->preview_pipeline && self->preview_filter_changed) { + gst_camerabin_destroy_preview_pipeline (self->preview_pipeline); } - if (!gst_camerabin_create_and_add_element (cbin, "ffmpegcolorspace", - "src-colorspace")) - goto done; + if (self->preview_pipeline == NULL) + self->preview_pipeline = + gst_camerabin_create_preview_pipeline (GST_ELEMENT_CAST (self), + self->preview_filter); - if (!(self->src_filter = - gst_camerabin_create_and_add_element (cbin, "capsfilter", - "src-capsfilter"))) - goto done; - - if (!(self->src_zoom_crop = - gst_camerabin_create_and_add_element (cbin, "videocrop", - "zoom-crop"))) - goto done; - if (!(self->src_zoom_scale = - gst_camerabin_create_and_add_element (cbin, "videoscale", - "zoom-scale"))) - goto done; - if (!(self->src_zoom_filter = - gst_camerabin_create_and_add_element (cbin, "capsfilter", - "zoom-capsfilter"))) - goto done; - - if (!(tee = - gst_camerabin_create_and_add_element (cbin, "tee", "camerasrc-tee"))) - goto done; - - /* viewfinder pad */ - vf_pad = gst_element_get_request_pad (tee, "src%d"); - g_object_set (tee, "alloc-pad", vf_pad, NULL); - gst_object_unref (vf_pad); - - /* the viewfinder should always work, so we add some converters to it */ - if (!gst_camerabin_create_and_add_element (cbin, "ffmpegcolorspace", - "viewfinder-colorspace")) - goto done; - if (!(videoscale = - gst_camerabin_create_and_add_element (cbin, "videoscale", - "viewfinder-scale"))) - goto done; - - /* image/video pad from tee */ - tee_capture_pad = gst_element_get_request_pad (tee, "src%d"); - - self->output_selector = - gst_element_factory_make ("output-selector", "outsel"); - g_object_set (self->output_selector, "pad-negotiation-mode", 0, NULL); - gst_bin_add (GST_BIN (self), self->output_selector); - { - GstPad *pad = gst_element_get_static_pad (self->output_selector, "sink"); - - /* check return TODO */ - gst_pad_link (tee_capture_pad, pad); - gst_object_unref (pad); - } - gst_object_unref (tee_capture_pad); - - /* Create the 2 output pads for video and image */ - self->outsel_vidpad = - gst_element_get_request_pad (self->output_selector, "src%d"); - self->outsel_imgpad = - gst_element_get_request_pad (self->output_selector, "src%d"); - - g_assert (self->outsel_vidpad != NULL); - g_assert (self->outsel_imgpad != NULL); - - gst_pad_add_buffer_probe (self->outsel_imgpad, - G_CALLBACK (gst_wrapper_camera_bin_src_imgsrc_probe), self); - gst_pad_add_buffer_probe (self->outsel_vidpad, - G_CALLBACK (gst_wrapper_camera_bin_src_vidsrc_probe), self); - gst_ghost_pad_set_target (GST_GHOST_PAD (self->imgsrc), self->outsel_imgpad); - gst_ghost_pad_set_target (GST_GHOST_PAD (self->vidsrc), self->outsel_vidpad); - - if (bcamsrc->mode == MODE_IMAGE) { - g_object_set (self->output_selector, "active-pad", self->outsel_imgpad, - NULL); - } else { - g_object_set (self->output_selector, "active-pad", self->outsel_vidpad, - NULL); - } - - /* hook-up the vf ghostpad */ - vf_pad = gst_element_get_static_pad (videoscale, "src"); - gst_ghost_pad_set_target (GST_GHOST_PAD (self->vfsrc), vf_pad); - gst_object_unref (vf_pad); - - gst_pad_set_active (self->vfsrc, TRUE); - gst_pad_set_active (self->imgsrc, TRUE); /* XXX ??? */ - gst_pad_set_active (self->vidsrc, TRUE); /* XXX ??? */ - - /* create the preview pipeline */ - self->preview_pipeline = - gst_camerabin_create_preview_pipeline (GST_ELEMENT_CAST (self)); + g_assert (self->preview_pipeline != NULL); + self->preview_filter_changed = FALSE; if (self->preview_caps) gst_camerabin_preview_set_caps (self->preview_pipeline, self->preview_caps); @@ -1025,6 +1052,11 @@ gst_wrapper_camera_bin_src_class_init (GstWrapperCameraBinSrcClass * klass) "The caps of the preview image to be posted", GST_TYPE_CAPS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (gobject_class, PROP_PREVIEW_FILTER, + g_param_spec_object ("preview-filter", "Preview filter", + "A custom preview filter to process preview image data", + GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + gstelement_class->change_state = gst_wrapper_camera_bin_src_change_state; gstbasecamerasrc_class->construct_pipeline = diff --git a/gst/camerabin2/gstwrappercamerabinsrc.h b/gst/camerabin2/gstwrappercamerabinsrc.h index c74be279c9..b2f4c7ae6f 100644 --- a/gst/camerabin2/gstwrappercamerabinsrc.h +++ b/gst/camerabin2/gstwrappercamerabinsrc.h @@ -113,6 +113,8 @@ struct _GstWrapperCameraBinSrc GstCameraBinPreviewPipelineData *preview_pipeline; gboolean post_previews; GstCaps *preview_caps; + GstElement *preview_filter; + gboolean preview_filter_changed; }; From 4a7dc8178207b00ee43f7071fa43ff1581a6199d Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Thu, 27 Jan 2011 15:35:14 -0300 Subject: [PATCH 384/448] tests: camerabin2: preview filter tests Adds tests to the preview-filter property of camerabin2 --- tests/check/elements/camerabin2.c | 32 +++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/tests/check/elements/camerabin2.c b/tests/check/elements/camerabin2.c index 1b0ddf4556..df630d4218 100644 --- a/tests/check/elements/camerabin2.c +++ b/tests/check/elements/camerabin2.c @@ -988,15 +988,18 @@ GST_START_TEST (test_image_custom_filter) { GstElement *vf_filter; GstElement *image_filter; + GstElement *preview_filter; GstPad *pad; gint vf_probe_counter = 0; gint image_probe_counter = 0; + gint preview_probe_counter = 0; if (!camera) return; vf_filter = gst_element_factory_make ("identity", "vf-filter"); image_filter = gst_element_factory_make ("identity", "img-filter"); + preview_filter = gst_element_factory_make ("identity", "preview-filter"); pad = gst_element_get_static_pad (vf_filter, "src"); gst_pad_add_buffer_probe (pad, (GCallback) filter_buffer_count, @@ -1008,10 +1011,20 @@ GST_START_TEST (test_image_custom_filter) &image_probe_counter); gst_object_unref (pad); + pad = gst_element_get_static_pad (preview_filter, "src"); + gst_pad_add_buffer_probe (pad, (GCallback) filter_buffer_count, + &preview_probe_counter); + gst_object_unref (pad); + /* set still image mode and filters */ g_object_set (camera, "mode", 1, "location", make_test_file_name (IMAGE_FILENAME, -1), - "viewfinder-filter", vf_filter, "image-filter", image_filter, NULL); + "viewfinder-filter", vf_filter, "image-filter", image_filter, + "preview-filter", preview_filter, NULL); + + gst_object_unref (vf_filter); + gst_object_unref (preview_filter); + gst_object_unref (image_filter); if (gst_element_set_state (GST_ELEMENT (camera), GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) { @@ -1035,6 +1048,7 @@ GST_START_TEST (test_image_custom_filter) fail_unless (vf_probe_counter > 0); fail_unless (image_probe_counter == 1); + fail_unless (preview_probe_counter == 1); } GST_END_TEST; @@ -1044,15 +1058,18 @@ GST_START_TEST (test_video_custom_filter) { GstElement *vf_filter; GstElement *video_filter; + GstElement *preview_filter; GstPad *pad; gint vf_probe_counter = 0; gint video_probe_counter = 0; + gint preview_probe_counter = 0; if (!camera) return; vf_filter = gst_element_factory_make ("identity", "vf-filter"); video_filter = gst_element_factory_make ("identity", "video-filter"); + preview_filter = gst_element_factory_make ("identity", "preview-filter"); pad = gst_element_get_static_pad (vf_filter, "src"); gst_pad_add_buffer_probe (pad, (GCallback) filter_buffer_count, @@ -1064,10 +1081,20 @@ GST_START_TEST (test_video_custom_filter) &video_probe_counter); gst_object_unref (pad); + pad = gst_element_get_static_pad (preview_filter, "src"); + gst_pad_add_buffer_probe (pad, (GCallback) filter_buffer_count, + &preview_probe_counter); + gst_object_unref (pad); + /* set still image mode and filters */ g_object_set (camera, "mode", 2, "location", make_test_file_name (VIDEO_FILENAME, -1), - "viewfinder-filter", vf_filter, "video-filter", video_filter, NULL); + "viewfinder-filter", vf_filter, "video-filter", video_filter, + "preview-filter", preview_filter, NULL); + + gst_object_unref (vf_filter); + gst_object_unref (preview_filter); + gst_object_unref (video_filter); if (gst_element_set_state (GST_ELEMENT (camera), GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE) { @@ -1093,6 +1120,7 @@ GST_START_TEST (test_video_custom_filter) fail_unless (vf_probe_counter > 0); fail_unless (video_probe_counter > 0); + fail_unless (preview_probe_counter == 1); } GST_END_TEST; From 1a62d9374b228dc5bd3fb8c7da2212ceb5506430 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Tue, 1 Feb 2011 11:19:29 -0300 Subject: [PATCH 385/448] wrappercamerabinsrc: Handle src state change to avoid losing timestamps Camerabin2 uses state changes to force the source to renegotiate its caps to the capture formats. The state changes makes the source lose its clock and base_time, causing it to stop timestamping the buffers. We still need a proper way to make sources renegotiate its caps, so this patch is a hack to make the source continue timestamping buffers even after changing state. The patch works by getting the clock and base time before doing the state change to NULL and setting them back after putting it to PLAYING again. It also cares to drop the first new segment after this state change. --- gst/camerabin2/gstwrappercamerabinsrc.c | 67 ++++++++++++++++++++++++- gst/camerabin2/gstwrappercamerabinsrc.h | 3 ++ 2 files changed, 69 insertions(+), 1 deletion(-) diff --git a/gst/camerabin2/gstwrappercamerabinsrc.c b/gst/camerabin2/gstwrappercamerabinsrc.c index c35fe8d77c..0f2e6090ab 100644 --- a/gst/camerabin2/gstwrappercamerabinsrc.c +++ b/gst/camerabin2/gstwrappercamerabinsrc.c @@ -165,12 +165,50 @@ static void gst_wrapper_camera_bin_reset_video_src_caps (GstWrapperCameraBinSrc * self, GstCaps * caps) { + GstClock *clock; + gint64 base_time; + GST_DEBUG_OBJECT (self, "Resetting src caps to %" GST_PTR_FORMAT, caps); if (self->src_vid_src) { + clock = gst_element_get_clock (self->src_vid_src); + base_time = gst_element_get_base_time (self->src_vid_src); + gst_element_set_state (self->src_vid_src, GST_STATE_NULL); set_capsfilter_caps (self, caps); + + self->drop_newseg = TRUE; + GST_DEBUG_OBJECT (self, "Bringing source up"); gst_element_sync_state_with_parent (self->src_vid_src); + + gst_element_set_clock (self->src_vid_src, clock); + gst_element_set_base_time (self->src_vid_src, base_time); + + if (GST_IS_BIN (self->src_vid_src)) { + GstIterator *it = gst_bin_iterate_elements (GST_BIN (self->src_vid_src)); + gpointer item = NULL; + gboolean done = FALSE; + while (!done) { + switch (gst_iterator_next (it, &item)) { + case GST_ITERATOR_OK: + gst_element_set_base_time (GST_ELEMENT (item), base_time); + gst_object_unref (item); + break; + case GST_ITERATOR_RESYNC: + gst_iterator_resync (it); + break; + case GST_ITERATOR_ERROR: + done = TRUE; + break; + case GST_ITERATOR_DONE: + done = TRUE; + break; + } + } + gst_iterator_free (it); + } + + gst_object_unref (clock); } } @@ -286,6 +324,30 @@ gst_wrapper_camera_bin_src_event (GstPad * pad, GstEvent * event) return src->srcpad_event_func (pad, event); } +static gboolean +gst_wrapper_camera_src_src_event_probe (GstPad * pad, GstEvent * evt, + gpointer udata) +{ + gboolean ret = TRUE; + GstWrapperCameraBinSrc *self = udata; + + switch (GST_EVENT_TYPE (evt)) { + case GST_EVENT_EOS: + /* drop */ + ret = FALSE; + break; + case GST_EVENT_NEWSEGMENT: + if (self->drop_newseg) { + ret = FALSE; + self->drop_newseg = FALSE; + } + break; + default: + break; + } + return ret; +} + /** * gst_wrapper_camera_bin_src_construct_pipeline: * @bcamsrc: camerasrc object @@ -334,7 +396,7 @@ gst_wrapper_camera_bin_src_construct_pipeline (GstBaseCameraSrc * bcamsrc) pad = gst_element_get_static_pad (self->src_vid_src, "src"); self->src_event_probe_id = gst_pad_add_event_probe (pad, - (GCallback) gst_camerabin_drop_eos_probe, NULL); + (GCallback) gst_wrapper_camera_src_src_event_probe, self); gst_object_unref (pad); } @@ -991,6 +1053,9 @@ gst_wrapper_camera_bin_src_change_state (GstElement * element, goto end; switch (trans) { + case GST_STATE_CHANGE_PAUSED_TO_READY: + self->drop_newseg = FALSE; + break; case GST_STATE_CHANGE_READY_TO_NULL: gst_element_set_state (self->preview_pipeline->pipeline, GST_STATE_NULL); break; diff --git a/gst/camerabin2/gstwrappercamerabinsrc.h b/gst/camerabin2/gstwrappercamerabinsrc.h index b2f4c7ae6f..d937321a88 100644 --- a/gst/camerabin2/gstwrappercamerabinsrc.h +++ b/gst/camerabin2/gstwrappercamerabinsrc.h @@ -88,6 +88,9 @@ struct _GstWrapperCameraBinSrc GstPadEventFunction srcpad_event_func; + /* For changing caps without losing timestamps */ + gboolean drop_newseg; + /* Application configurable elements */ GstElement *app_vid_src; From 48b05a3002f48faffdaabfbf3997b2bdda273aaf Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Tue, 1 Feb 2011 11:19:53 -0300 Subject: [PATCH 386/448] wrappercamerabinsrc: Fix preview messages Image previews where being posted in sync with the buffers timestamps, this makes no sense as previews should be posted ASAP. Also adds some debugging messages. --- gst/camerabin2/camerabingeneral.c | 2 ++ gst/camerabin2/gstwrappercamerabinsrc.c | 19 +++++++++++++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/gst/camerabin2/camerabingeneral.c b/gst/camerabin2/camerabingeneral.c index 26edc12d0f..2f5bd05b1a 100644 --- a/gst/camerabin2/camerabingeneral.c +++ b/gst/camerabin2/camerabingeneral.c @@ -375,6 +375,8 @@ gst_camerabin_create_preview_pipeline (GstElement * element, gst_app_sink_set_callbacks ((GstAppSink *) data->appsink, &callbacks, data, NULL); + g_object_set (data->appsink, "sync", FALSE, NULL); + data->element = element; data->filter = filter; diff --git a/gst/camerabin2/gstwrappercamerabinsrc.c b/gst/camerabin2/gstwrappercamerabinsrc.c index 0f2e6090ab..bfe8c47dae 100644 --- a/gst/camerabin2/gstwrappercamerabinsrc.c +++ b/gst/camerabin2/gstwrappercamerabinsrc.c @@ -115,9 +115,13 @@ gst_wrapper_camera_bin_src_set_property (GObject * object, case PROP_PREVIEW_CAPS: gst_caps_replace (&self->preview_caps, (GstCaps *) gst_value_get_caps (value)); - if (self->preview_pipeline) + if (self->preview_pipeline) { + GST_DEBUG_OBJECT (self, + "Setting preview pipeline caps %" GST_PTR_FORMAT, + self->preview_caps); gst_camerabin_preview_set_caps (self->preview_pipeline, (GstCaps *) gst_value_get_caps (value)); + } break; case PROP_PREVIEW_FILTER: if (self->preview_filter) @@ -236,8 +240,10 @@ gst_wrapper_camera_bin_src_imgsrc_probe (GstPad * pad, GstBuffer * buffer, /* post preview */ /* TODO This can likely be optimized if the viewfinder caps is the same as * the preview caps, avoiding another scaling of the same buffer. */ - if (self->post_previews) + if (self->post_previews) { + GST_DEBUG_OBJECT (self, "Posting preview for image"); gst_camerabin_preview_pipeline_post (self->preview_pipeline, buffer); + } if (self->image_capture_count == 0) { gst_base_camera_src_finish_capture (camerasrc); @@ -285,8 +291,10 @@ gst_wrapper_camera_bin_src_vidsrc_probe (GstPad * pad, GstBuffer * buffer, self->video_rec_status = GST_VIDEO_RECORDING_STATUS_RUNNING; /* post preview */ - if (self->post_previews) + if (self->post_previews) { + GST_DEBUG_OBJECT (self, "Posting preview for video"); gst_camerabin_preview_pipeline_post (self->preview_pipeline, buffer); + } ret = TRUE; } else if (self->video_rec_status == GST_VIDEO_RECORDING_STATUS_FINISHING) { @@ -504,8 +512,11 @@ gst_wrapper_camera_bin_src_construct_pipeline (GstBaseCameraSrc * bcamsrc) g_assert (self->preview_pipeline != NULL); self->preview_filter_changed = FALSE; - if (self->preview_caps) + if (self->preview_caps) { + GST_DEBUG_OBJECT (self, "Setting preview pipeline caps %" GST_PTR_FORMAT, + self->preview_caps); gst_camerabin_preview_set_caps (self->preview_pipeline, self->preview_caps); + } ret = TRUE; self->elements_created = TRUE; From bb0cdda4870d46e525adcfa91abc95e62a85d2f4 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Tue, 1 Feb 2011 11:20:25 -0300 Subject: [PATCH 387/448] tests: camerabin2: Improve preview checking --- tests/check/elements/camerabin2.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/check/elements/camerabin2.c b/tests/check/elements/camerabin2.c index df630d4218..53e6ccc17a 100644 --- a/tests/check/elements/camerabin2.c +++ b/tests/check/elements/camerabin2.c @@ -287,6 +287,7 @@ check_preview_image (void) { fail_unless (preview_buffer != NULL); if (preview_caps) { + fail_unless (GST_BUFFER_CAPS (preview_buffer) != NULL); fail_unless (gst_caps_can_intersect (GST_BUFFER_CAPS (preview_buffer), preview_caps)); } @@ -786,6 +787,11 @@ GST_START_TEST (test_image_capture_previews) g_main_loop_run (main_loop); check_preview_image (); + + if (preview_buffer) + gst_buffer_unref (preview_buffer); + preview_buffer = NULL; + gst_caps_replace (&preview_caps, NULL); } gst_element_set_state (GST_ELEMENT (camera), GST_STATE_NULL); From 186d317a2faca0dc23aa5a1be96609bcd766b3a6 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Thu, 3 Feb 2011 15:22:51 -0300 Subject: [PATCH 388/448] imagecapturebin: Fix property setting Set the property on the child and not on itself causing infinite looping --- gst/camerabin2/gstimagecapturebin.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gst/camerabin2/gstimagecapturebin.c b/gst/camerabin2/gstimagecapturebin.c index 2a5bcdba8e..b4aba2aa08 100644 --- a/gst/camerabin2/gstimagecapturebin.c +++ b/gst/camerabin2/gstimagecapturebin.c @@ -117,8 +117,9 @@ gst_image_capture_bin_set_property (GObject * object, guint prop_id, case PROP_LOCATION: g_free (imagebin->location); imagebin->location = g_value_dup_string (value); + GST_DEBUG_OBJECT (imagebin, "setting location to %s", imagebin->location); if (imagebin->sink) { - g_object_set (imagebin, "location", imagebin->location, NULL); + g_object_set (imagebin->sink, "location", imagebin->location, NULL); } break; case PROP_ENCODER: From 2b4c85414632fd4538ab135414fb227be46f80bd Mon Sep 17 00:00:00 2001 From: Alexey Fisher Date: Fri, 4 Feb 2011 09:08:26 +0100 Subject: [PATCH 389/448] vp8enc: Add description for bitrate units. --- ext/vp8/gstvp8enc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/vp8/gstvp8enc.c b/ext/vp8/gstvp8enc.c index b70510243b..17b316a5bd 100644 --- a/ext/vp8/gstvp8enc.c +++ b/ext/vp8/gstvp8enc.c @@ -229,7 +229,7 @@ gst_vp8_enc_class_init (GstVP8EncClass * klass) g_object_class_install_property (gobject_class, PROP_BITRATE, g_param_spec_int ("bitrate", "Bit rate", - "Bit rate", + "Bit rate (in bits/sec)", 0, 1000000000, DEFAULT_BITRATE, (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS))); From 4915493932ef5b4767c0772f180fd48413288950 Mon Sep 17 00:00:00 2001 From: Stefan Kost Date: Wed, 12 Jan 2011 17:13:07 +0200 Subject: [PATCH 390/448] camerabin-tests: fix lookup of UI files These are uninstalled examples. Pass $srcdir to cpp to build the correct location for the UI file. --- tests/examples/camerabin/Makefile.am | 4 ++-- tests/examples/camerabin/gst-camera.c | 12 +++--------- tests/examples/camerabin2/Makefile.am | 2 +- tests/examples/camerabin2/gst-camera2.c | 2 +- 4 files changed, 7 insertions(+), 13 deletions(-) diff --git a/tests/examples/camerabin/Makefile.am b/tests/examples/camerabin/Makefile.am index 5898a0ce51..9d74d91d72 100644 --- a/tests/examples/camerabin/Makefile.am +++ b/tests/examples/camerabin/Makefile.am @@ -21,7 +21,7 @@ gst_camera_LDADD = \ noinst_DATA = $(GST_CAMERABIN_UI_FILES) -INCLUDES = -DCAMERA_APPS_UIDIR=\""$(uidir)"\" +INCLUDES = -DCAMERA_APPS_UIDIR=\""$(srcdir)"\" else GST_CAMERABIN_GTK_EXAMPLES = @@ -29,7 +29,7 @@ endif gst_camera_perf_SOURCES = gst-camera-perf.c gst_camera_perf_CFLAGS = $(GST_CFLAGS) -gst_camera_perf_LDADD = $(GST_LIBS) +gst_camera_perf_LDADD = $(GST_LIBS) if HAVE_X11 diff --git a/tests/examples/camerabin/gst-camera.c b/tests/examples/camerabin/gst-camera.c index eded8bb881..57ff706e14 100644 --- a/tests/examples/camerabin/gst-camera.c +++ b/tests/examples/camerabin/gst-camera.c @@ -65,8 +65,7 @@ gtk_widget_get_allocation (GtkWidget * w, GtkAllocation * a) #define PREVIEW_TIME_MS (2 * 1000) #define N_BURST_IMAGES 10 -#define DEFAULT_UI_FILE "gst-camera.ui" -#define SHARED_UI_FILE CAMERA_APPS_UIDIR"/"DEFAULT_UI_FILE +#define UI_FILE CAMERA_APPS_UIDIR G_DIR_SEPARATOR_S "gst-camera.ui" /* Names of default elements */ #define CAMERA_APP_VIDEOSRC "v4l2src" @@ -762,7 +761,7 @@ set_metadata (void) /* for more information about image metadata tags, see: * http://webcvs.freedesktop.org/gstreamer/gst-plugins-bad/tests/icles/metadata_editor.c * and for the mapping: - * http://webcvs.freedesktop.org/gstreamer/gst-plugins-bad/ext/metadata/metadata_mapping.htm?view=co + * http://webcvs.freedesktop.org/gstreamer/gst-plugins-bad/ext/metadata/metadata_mapping.htm?view=co */ GstTagSetter *setter = GST_TAG_SETTER (gst_camera_bin); @@ -1622,14 +1621,9 @@ static gboolean ui_create (void) { GError *error = NULL; - const gchar *uifile = DEFAULT_UI_FILE; - - if (!g_file_test (uifile, G_FILE_TEST_EXISTS)) { - uifile = SHARED_UI_FILE; - } builder = gtk_builder_new (); - if (!gtk_builder_add_from_file (builder, uifile, &error)) { + if (!gtk_builder_add_from_file (builder, UI_FILE, &error)) { g_warning ("Couldn't load builder file: %s", error->message); g_error_free (error); goto done; diff --git a/tests/examples/camerabin2/Makefile.am b/tests/examples/camerabin2/Makefile.am index 781f201639..5fa7534712 100644 --- a/tests/examples/camerabin2/Makefile.am +++ b/tests/examples/camerabin2/Makefile.am @@ -21,7 +21,7 @@ gst_camera2_LDADD = \ noinst_DATA = $(GST_CAMERABIN_UI_FILES) -INCLUDES = -DCAMERA_APPS_UIDIR=\""$(uidir)"\" +INCLUDES = -DCAMERA_APPS_UIDIR=\""$(srcdir)"\" else GST_CAMERABIN_GTK_EXAMPLES = diff --git a/tests/examples/camerabin2/gst-camera2.c b/tests/examples/camerabin2/gst-camera2.c index 42b6e07a06..14e3be10f4 100644 --- a/tests/examples/camerabin2/gst-camera2.c +++ b/tests/examples/camerabin2/gst-camera2.c @@ -37,7 +37,7 @@ #include #include -#define UI_FILE "gst-camera2.ui" +#define UI_FILE CAMERA_APPS_UIDIR G_DIR_SEPARATOR_S "gst-camera2.ui" static GstElement *camera; static GtkBuilder *builder; From d6d48cfb7091b2bcfd8e4dba3a7eaafce668b1f0 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Mon, 7 Feb 2011 14:05:34 +0100 Subject: [PATCH 391/448] configure.ac: set GST_LIB_LDFLAGS Aligns GST_LIB_LDFLAGS with e.g. -base to arrange for proper exports in libs. --- configure.ac | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/configure.ac b/configure.ac index 3da824432f..5819cb3c15 100644 --- a/configure.ac +++ b/configure.ac @@ -1691,6 +1691,13 @@ dnl whatevertarget_LIBS and -L flags here affect the rest of the linking GST_ALL_LDFLAGS="-no-undefined" AC_SUBST(GST_ALL_LDFLAGS) +dnl GST_LIB_LDFLAGS +dnl linker flags shared by all libraries +dnl LDFLAGS modifier defining exported symbols from built libraries +dnl (export _gst_foo but not __gst_foo) +GST_LIB_LDFLAGS="-export-symbols-regex ^_?\(gst_\|Gst\|GST_\).*" +AC_SUBST(GST_LIB_LDFLAGS) + dnl this really should only contain flags, not libs - they get added before dnl whatevertarget_LIBS and -L flags here affect the rest of the linking GST_PLUGIN_LDFLAGS="-module -avoid-version -export-symbols-regex '^[_]*gst_plugin_desc\$\$' $GST_ALL_LDFLAGS" From c85e8e8015b7239df7819fc2eaa0a21158f1e250 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Mon, 6 Sep 2010 14:10:11 +0200 Subject: [PATCH 392/448] amrparse: a valid amr-wb frame should not have reserved frame type index See #639715. --- gst/audioparsers/gstamrparse.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/gst/audioparsers/gstamrparse.c b/gst/audioparsers/gstamrparse.c index a668817ae5..42481a2b29 100644 --- a/gst/audioparsers/gstamrparse.c +++ b/gst/audioparsers/gstamrparse.c @@ -64,7 +64,7 @@ static const gint block_size_nb[16] = { 12, 13, 15, 17, 19, 20, 26, 31, 5, 0, 0, 0, 0, 0, 0, 0 }; static const gint block_size_wb[16] = - { 17, 23, 32, 36, 40, 46, 50, 58, 60, 5, 5, 0, 0, 0, 0, 0 }; + { 17, 23, 32, 36, 40, 46, 50, 58, 60, 5, -1, -1, -1, -1, 0, 0 }; /* AMR has a "hardcoded" framerate of 50fps */ #define AMR_FRAMES_PER_SECOND 50 @@ -307,8 +307,9 @@ gst_amrparse_check_valid_frame (GstBaseParse * parse, * to contain a valid header as well (and there is enough data to * perform this check) */ - if (GST_BASE_PARSE_FRAME_SYNC (frame) || GST_BASE_PARSE_FRAME_DRAIN (frame) - || (dsize > fsize && (data[fsize] & 0x83) == 0)) { + if (fsize && + (GST_BASE_PARSE_FRAME_SYNC (frame) || GST_BASE_PARSE_FRAME_DRAIN (frame) + || (dsize > fsize && (data[fsize] & 0x83) == 0))) { *framesize = fsize; return TRUE; } From ab2b9079f0dc99daa9c1648504ccf7cab0aa1f1a Mon Sep 17 00:00:00 2001 From: Teemu Katajisto Date: Mon, 7 Feb 2011 09:50:22 +0200 Subject: [PATCH 393/448] examples: camerabin: fix --no-xwindow option handling in gst-camerabin-test --no-window flag is false by default and selection based on the option whether to create XWindow is done before options are parsed. Therefore XWindow is never created. https://bugzilla.gnome.org/show_bug.cgi?id=641712 --- tests/examples/camerabin/gst-camerabin-test.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/examples/camerabin/gst-camerabin-test.c b/tests/examples/camerabin/gst-camerabin-test.c index 6286b25ef7..73399e5953 100644 --- a/tests/examples/camerabin/gst-camerabin-test.c +++ b/tests/examples/camerabin/gst-camerabin-test.c @@ -781,10 +781,6 @@ main (int argc, char *argv[]) GOptionContext *ctx; GError *err = NULL; - /* if we fail to create xwindow should we care? */ - if (!no_xwindow) - create_host_window (); - if (!g_thread_supported ()) g_thread_init (NULL); @@ -797,6 +793,10 @@ main (int argc, char *argv[]) } g_option_context_free (ctx); + /* if we fail to create xwindow should we care? */ + if (!no_xwindow) + create_host_window (); + GST_DEBUG_CATEGORY_INIT (camerabin_test, "camerabin-test", 0, "camerabin test"); From 15366355a4caa34481cab7bdfd0385b44dfad866 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Tue, 8 Feb 2011 11:24:59 -0300 Subject: [PATCH 394/448] wrappercamerabinsrc: Do not re-set the clock if it is null Avoids not needed work and doesn't assert when trying to unref the null reference --- gst/camerabin2/gstwrappercamerabinsrc.c | 51 +++++++++++++------------ 1 file changed, 27 insertions(+), 24 deletions(-) diff --git a/gst/camerabin2/gstwrappercamerabinsrc.c b/gst/camerabin2/gstwrappercamerabinsrc.c index bfe8c47dae..811479493c 100644 --- a/gst/camerabin2/gstwrappercamerabinsrc.c +++ b/gst/camerabin2/gstwrappercamerabinsrc.c @@ -185,34 +185,37 @@ gst_wrapper_camera_bin_reset_video_src_caps (GstWrapperCameraBinSrc * self, GST_DEBUG_OBJECT (self, "Bringing source up"); gst_element_sync_state_with_parent (self->src_vid_src); - gst_element_set_clock (self->src_vid_src, clock); - gst_element_set_base_time (self->src_vid_src, base_time); + if (clock) { + gst_element_set_clock (self->src_vid_src, clock); + gst_element_set_base_time (self->src_vid_src, base_time); - if (GST_IS_BIN (self->src_vid_src)) { - GstIterator *it = gst_bin_iterate_elements (GST_BIN (self->src_vid_src)); - gpointer item = NULL; - gboolean done = FALSE; - while (!done) { - switch (gst_iterator_next (it, &item)) { - case GST_ITERATOR_OK: - gst_element_set_base_time (GST_ELEMENT (item), base_time); - gst_object_unref (item); - break; - case GST_ITERATOR_RESYNC: - gst_iterator_resync (it); - break; - case GST_ITERATOR_ERROR: - done = TRUE; - break; - case GST_ITERATOR_DONE: - done = TRUE; - break; + if (GST_IS_BIN (self->src_vid_src)) { + GstIterator *it = + gst_bin_iterate_elements (GST_BIN (self->src_vid_src)); + gpointer item = NULL; + gboolean done = FALSE; + while (!done) { + switch (gst_iterator_next (it, &item)) { + case GST_ITERATOR_OK: + gst_element_set_base_time (GST_ELEMENT (item), base_time); + gst_object_unref (item); + break; + case GST_ITERATOR_RESYNC: + gst_iterator_resync (it); + break; + case GST_ITERATOR_ERROR: + done = TRUE; + break; + case GST_ITERATOR_DONE: + done = TRUE; + break; + } } + gst_iterator_free (it); } - gst_iterator_free (it); - } - gst_object_unref (clock); + gst_object_unref (clock); + } } } From edb15598ed566f37d90129492a86341badee0672 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Mon, 7 Feb 2011 22:47:34 +0100 Subject: [PATCH 395/448] directdrawsink: avoid rendering to invalid area Based on patch by Havard Graff Fixes #594280. --- sys/directdraw/gstdirectdrawsink.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/sys/directdraw/gstdirectdrawsink.c b/sys/directdraw/gstdirectdrawsink.c index 15f79d12a7..3b8967f6ce 100644 --- a/sys/directdraw/gstdirectdrawsink.c +++ b/sys/directdraw/gstdirectdrawsink.c @@ -904,6 +904,19 @@ gst_directdraw_sink_show_frame (GstBaseSink * bsink, GstBuffer * buf) GetClientRect (ddrawsink->video_window, &destsurf_rect); OffsetRect (&destsurf_rect, dest_surf_point.x, dest_surf_point.y); + /* Check to see if we have an area to draw to. + * When the window is minimized, it will trigger the + * "IDirectDrawSurface7_Blt (object's offscreen surface)" warning, + * with a msg that the rectangle is invalid */ + if (destsurf_rect.right <= destsurf_rect.left || + destsurf_rect.bottom <= destsurf_rect.top) { + GST_OBJECT_UNLOCK (ddrawsink); + GST_DEBUG_OBJECT (ddrawsink, "invalid rendering window rectangle " + "(%ld, %ld), (%ld, %ld)", destsurf_rect.left, destsurf_rect.top, + destsurf_rect.right, destsurf_rect.bottom); + goto beach; + } + if (ddrawsink->keep_aspect_ratio) { /* center image to dest image keeping aspect ratio */ src_rect.top = 0; @@ -1004,6 +1017,7 @@ gst_directdraw_sink_show_frame (GstBaseSink * bsink, GstBuffer * buf) "returned %s", DDErrorString (hRes)); } +beach: return GST_FLOW_OK; } From f96dab44cf2391c30abf76f5598e0f8557c7d549 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Mon, 7 Feb 2011 23:17:55 +0100 Subject: [PATCH 396/448] directdrawsink: avoid aspect-ratio borders overlying other windows Fixes #632056. --- sys/directdraw/gstdirectdrawsink.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sys/directdraw/gstdirectdrawsink.c b/sys/directdraw/gstdirectdrawsink.c index 3b8967f6ce..05c81367ad 100644 --- a/sys/directdraw/gstdirectdrawsink.c +++ b/sys/directdraw/gstdirectdrawsink.c @@ -821,9 +821,11 @@ gst_directdraw_sink_draw_borders (GstDirectDrawSink * ddrawsink, RECT dst_rect) OffsetRect (&win_rect, win_point.x, win_point.y); /* We acquire a drawing context */ - if (IDirectDrawSurface7_GetDC (ddrawsink->primary_surface, &hdc) == DD_OK) { + if ((hdc = GetDC (ddrawsink->video_window))) { HBRUSH brush = CreateSolidBrush (RGB (0, 0, 0)); + /* arrange for logical coordinates that match screen coordinates */ + SetWindowOrgEx (hdc, win_point.x, win_point.y, NULL); /* Left border */ if (dst_rect.left > win_rect.left) { fill_rect.left = win_rect.left; @@ -857,7 +859,7 @@ gst_directdraw_sink_draw_borders (GstDirectDrawSink * ddrawsink, RECT dst_rect) FillRect (hdc, &fill_rect, brush); } DeleteObject (brush); - IDirectDrawSurface7_ReleaseDC (ddrawsink->primary_surface, hdc); + ReleaseDC (ddrawsink->video_window, hdc); } } From 2522a672a9a841a44ff4e0b20c7372092fd61010 Mon Sep 17 00:00:00 2001 From: Luciana Fujii Pontello Date: Wed, 26 Jan 2011 11:49:48 -0200 Subject: [PATCH 397/448] camerabin: Events with select-all in input-selector When select-all was set, input-selector wasn't handling upstream events. Now input-selector forwards the event to all of its sink pads. This changes the input-selector internal to camerabin until it is replaced with a better solution. --- gst/camerabin/gstinputselector.c | 39 ++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/gst/camerabin/gstinputselector.c b/gst/camerabin/gstinputselector.c index 75ecab1d21..ef4e23637d 100644 --- a/gst/camerabin/gstinputselector.c +++ b/gst/camerabin/gstinputselector.c @@ -1076,15 +1076,54 @@ gst_input_selector_event (GstPad * pad, GstEvent * event) { gboolean res = FALSE; GstPad *otherpad; + GstInputSelector *sel; + GstIterator *iter; + gboolean done; + gpointer nextpad; + sel = GST_INPUT_SELECTOR (gst_pad_get_parent (pad)); otherpad = gst_input_selector_get_linked_pad (pad, TRUE); if (otherpad) { res = gst_pad_push_event (otherpad, event); gst_object_unref (otherpad); + } else if (sel->select_all) { + + /* If select-all is set, we should push the event to all pads. + * The result will be TRUE if the push works for any of the pads, even if a + * push fails. This is coherent with the way camerabin uses input-selector, + * but might not be for other uses of it. */ + + iter = gst_element_iterate_sink_pads (GST_ELEMENT (sel)); + + done = FALSE; + while (!done) { + switch (gst_iterator_next (iter, &nextpad)) { + case GST_ITERATOR_OK: + res |= gst_pad_push_event (nextpad, gst_event_ref (event)); + gst_object_unref (nextpad); + break; + case GST_ITERATOR_RESYNC: + gst_iterator_resync (iter); + break; + case GST_ITERATOR_ERROR: + GST_WARNING_OBJECT (sel, + "Wrong parameters when retrieving sink pads"); + done = TRUE; + break; + case GST_ITERATOR_DONE: + done = TRUE; + break; + } + } + gst_event_unref (event); + gst_iterator_free (iter); } else gst_event_unref (event); + + gst_object_unref (sel); + return res; } From fa45b1fe2d6a2613a3972b10d9595558cd521607 Mon Sep 17 00:00:00 2001 From: Luciana Fujii Pontello Date: Fri, 4 Feb 2011 01:00:55 -0200 Subject: [PATCH 398/448] camerabin: Always take photo when preview-caps is set When filename is not set, but preview-caps is set, take the photo and send its preview. --- gst/camerabin/gstcamerabin.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/gst/camerabin/gstcamerabin.c b/gst/camerabin/gstcamerabin.c index 8267500e58..5704513c6b 100644 --- a/gst/camerabin/gstcamerabin.c +++ b/gst/camerabin/gstcamerabin.c @@ -1816,6 +1816,10 @@ gst_camerabin_have_img_buffer (GstPad * pad, GstMiniObject * obj, GST_LOG ("got buffer %p with size %d", buffer, GST_BUFFER_SIZE (buffer)); + if (camera->preview_caps) { + gst_camerabin_send_preview (camera, buffer); + } + /* Image filename should be set by now */ if (g_str_equal (camera->filename->str, "")) { GST_DEBUG_OBJECT (camera, "filename not set, dropping buffer"); @@ -1824,10 +1828,6 @@ gst_camerabin_have_img_buffer (GstPad * pad, GstMiniObject * obj, goto done; } - if (camera->preview_caps) { - gst_camerabin_send_preview (camera, buffer); - } - gst_camerabin_rewrite_tags (camera); /* Send a custom event which tells the filename to image queue */ @@ -4045,11 +4045,14 @@ gst_camerabin_capture_start (GstCameraBin * camera) } } - if (g_str_equal (camera->filename->str, "")) { - GST_ELEMENT_ERROR (camera, CORE, FAILED, - ("set filename before starting capture"), (NULL)); - return; - } + /* We need a filename unless it's a photo and preview_caps is set */ + + if (g_str_equal (camera->filename->str, "")) + if (camera->active_bin == camera->vidbin || !camera->preview_caps) { + GST_ELEMENT_ERROR (camera, CORE, FAILED, + ("set filename before starting capture"), (NULL)); + return; + } g_mutex_lock (camera->capture_mutex); if (camera->capturing) { From cfc3f5e43bbcc5a9c6437ad83f12e834e7307908 Mon Sep 17 00:00:00 2001 From: Arun Raghavan Date: Tue, 8 Feb 2011 23:50:13 +0530 Subject: [PATCH 399/448] mpegaudioparse: Post CBR bitrate as nominal bitrate Even if VBR headers are missing, we can't guarantee that a stream is in fact a CBR stream, so it's safer to let baseparse calculate the average bitrate rather than assume a CBR stream. However, in order to make /some/ metadata available before the requisite number of frames have been parsed, this posts the bitrate from the non-VBR headers as the nominal bitrate. https://bugzilla.gnome.org/show_bug.cgi?id=641858 --- gst/audioparsers/gstmpegaudioparse.c | 11 +++++++++++ gst/audioparsers/gstmpegaudioparse.h | 3 +++ 2 files changed, 14 insertions(+) diff --git a/gst/audioparsers/gstmpegaudioparse.c b/gst/audioparsers/gstmpegaudioparse.c index d95f8aeaad..b9ad66a43e 100644 --- a/gst/audioparsers/gstmpegaudioparse.c +++ b/gst/audioparsers/gstmpegaudioparse.c @@ -189,6 +189,8 @@ gst_mpeg_audio_parse_reset (GstMpegAudioParse * mp3parse) mp3parse->last_posted_crc = CRC_UNKNOWN; mp3parse->last_posted_channel_mode = MPEG_AUDIO_CHANNEL_MODE_UNKNOWN; + mp3parse->hdr_bitrate = 0; + mp3parse->xing_flags = 0; mp3parse->xing_bitrate = 0; mp3parse->xing_frames = 0; @@ -958,6 +960,8 @@ gst_mpeg_audio_parse_parse_frame (GstBaseParse * parse, (version == 1) ? 10 : 30, 2); } + mp3parse->hdr_bitrate = bitrate; + /* For first frame; check for seek tables and output a codec tag */ gst_mpeg_audio_parse_handle_first_frame (mp3parse, buf); @@ -1148,6 +1152,13 @@ gst_mpeg_audio_parse_pre_push_frame (GstBaseParse * parse, taglist = gst_tag_list_new (); gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, GST_TAG_AUDIO_CODEC, codec, NULL); + if (mp3parse->hdr_bitrate > 0 && mp3parse->xing_bitrate == 0 && + mp3parse->vbri_bitrate == 0) { + /* We don't have a VBR bitrate, so post the available bitrate as + * nominal and let baseparse calculate the real bitrate */ + gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, + GST_TAG_NOMINAL_BITRATE, mp3parse->hdr_bitrate, NULL); + } gst_element_found_tags_for_pad (GST_ELEMENT (mp3parse), GST_BASE_PARSE_SRC_PAD (mp3parse), taglist); g_free (codec); diff --git a/gst/audioparsers/gstmpegaudioparse.h b/gst/audioparsers/gstmpegaudioparse.h index 0b4dad7751..cf5fd37b11 100644 --- a/gst/audioparsers/gstmpegaudioparse.h +++ b/gst/audioparsers/gstmpegaudioparse.h @@ -65,6 +65,9 @@ struct _GstMpegAudioParse { gint last_posted_crc, last_crc; guint last_posted_channel_mode, last_mode; + /* Bitrate from non-vbr headers */ + guint32 hdr_bitrate; + /* Xing info */ guint32 xing_flags; guint32 xing_frames; From 3f683e02887f39675c814c1e418dd4e3beb9bc1d Mon Sep 17 00:00:00 2001 From: Arun Raghavan Date: Tue, 8 Feb 2011 23:39:24 +0530 Subject: [PATCH 400/448] baseparse: Update min/max bitrate before first posting them This avoids posting an initial min-bitrate of G_UINTMAX and max-bitrate of 0. https://bugzilla.gnome.org/show_bug.cgi?id=641857 --- gst/audioparsers/gstbaseparse.c | 4 +++- gst/videoparsers/gstbaseparse.c | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/gst/audioparsers/gstbaseparse.c b/gst/audioparsers/gstbaseparse.c index 5be6363384..75c945c2ee 100644 --- a/gst/audioparsers/gstbaseparse.c +++ b/gst/audioparsers/gstbaseparse.c @@ -1227,7 +1227,9 @@ gst_base_parse_update_bitrates (GstBaseParse * parse, GstBaseParseFrame * frame) } else if (parse->priv->framecount == MIN_FRAMES_TO_POST_BITRATE) { /* always post all at threshold time */ update_min = update_max = update_avg = TRUE; - } else { + } + + if (G_LIKELY (parse->priv->framecount >= MIN_FRAMES_TO_POST_BITRATE)) { if (frame_bitrate < parse->priv->min_bitrate) { parse->priv->min_bitrate = frame_bitrate; update_min = TRUE; diff --git a/gst/videoparsers/gstbaseparse.c b/gst/videoparsers/gstbaseparse.c index 8aa3f14fe6..4ab5dbb367 100644 --- a/gst/videoparsers/gstbaseparse.c +++ b/gst/videoparsers/gstbaseparse.c @@ -1227,7 +1227,9 @@ gst_base_parse_update_bitrates (GstBaseParse * parse, GstBaseParseFrame * frame) } else if (parse->priv->framecount == MIN_FRAMES_TO_POST_BITRATE) { /* always post all at threshold time */ update_min = update_max = update_avg = TRUE; - } else { + } + + if (G_LIKELY (parse->priv->framecount >= MIN_FRAMES_TO_POST_BITRATE)) { if (frame_bitrate < parse->priv->min_bitrate) { parse->priv->min_bitrate = frame_bitrate; update_min = TRUE; From a11b314b1ecceb7311162962c2f6b4e7fb21ede7 Mon Sep 17 00:00:00 2001 From: Hu Gang Date: Thu, 10 Feb 2011 10:35:18 +0800 Subject: [PATCH 401/448] photography interface: update the noise_reduction type from guint to GstPhotographyNoiseReduction https://bugzilla.gnome.org/show_bug.cgi?id=616814 --- gst-libs/gst/interfaces/photography.c | 2 +- gst-libs/gst/interfaces/photography.h | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/gst-libs/gst/interfaces/photography.c b/gst-libs/gst/interfaces/photography.c index 95e0f307a7..878b185ebe 100644 --- a/gst-libs/gst/interfaces/photography.c +++ b/gst-libs/gst/interfaces/photography.c @@ -313,7 +313,7 @@ GST_PHOTOGRAPHY_FUNC_TEMPLATE (flash_mode, GstFlashMode); * * Since: 0.10.21 */ -GST_PHOTOGRAPHY_FUNC_TEMPLATE (noise_reduction, guint); +GST_PHOTOGRAPHY_FUNC_TEMPLATE (noise_reduction, GstPhotographyNoiseReduction); /** * gst_photography_set_zoom: diff --git a/gst-libs/gst/interfaces/photography.h b/gst-libs/gst/interfaces/photography.h index 1ab652ca73..ce8fea9231 100644 --- a/gst-libs/gst/interfaces/photography.h +++ b/gst-libs/gst/interfaces/photography.h @@ -217,7 +217,7 @@ typedef struct gfloat zoom; GstFlickerReductionMode flicker_mode; GstFocusMode focus_mode; - guint noise_reduction; + GstPhotographyNoiseReduction noise_reduction; } GstPhotoSettings; /** @@ -341,7 +341,7 @@ gboolean gst_photography_get_scene_mode (GstPhotography * photo, gboolean gst_photography_get_flash_mode (GstPhotography * photo, GstFlashMode * flash_mode); gboolean gst_photography_get_noise_reduction (GstPhotography * photo, - guint * noise_reduction); + GstPhotographyNoiseReduction * noise_reduction); gboolean gst_photography_get_zoom (GstPhotography * photo, gfloat * zoom); gboolean gst_photography_get_flicker_mode (GstPhotography * photo, GstFlickerReductionMode *mode); @@ -363,7 +363,7 @@ gboolean gst_photography_set_scene_mode (GstPhotography * photo, gboolean gst_photography_set_flash_mode (GstPhotography * photo, GstFlashMode flash_mode); gboolean gst_photography_set_noise_reduction (GstPhotography * photo, - guint noise_reduction); + GstPhotographyNoiseReduction noise_reduction); gboolean gst_photography_set_zoom (GstPhotography * photo, gfloat zoom); gboolean gst_photography_set_flicker_mode (GstPhotography * photo, GstFlickerReductionMode mode); From 7e9fb16c4858d7384641075949d5642c3beaa8fc Mon Sep 17 00:00:00 2001 From: Teemu Katajisto Date: Thu, 10 Feb 2011 16:00:03 +0200 Subject: [PATCH 402/448] camerabin: application element memory leak fixes If videobin/imagebin was never set to READY state the ownership of elements created and set by application were never taken by bin and therefore gst_object_sink is called for these elements before unreffing (they may still be in floating state and not unreffed properly without sinking first) --- gst/camerabin/camerabinimage.c | 8 ++++++++ gst/camerabin/camerabinvideo.c | 11 +++++++++++ 2 files changed, 19 insertions(+) diff --git a/gst/camerabin/camerabinimage.c b/gst/camerabin/camerabinimage.c index 8b94d7d22a..2aa858d883 100644 --- a/gst/camerabin/camerabinimage.c +++ b/gst/camerabin/camerabinimage.c @@ -196,7 +196,14 @@ gst_camerabin_image_dispose (GstCameraBinImage * img) } + /* Note: if imagebin was never set to READY state the + ownership of elements created by application were never + taken by bin and therefore gst_object_sink is called for + these elements (they may still be in floating state + and not unreffed properly without sinking first) + */ if (img->app_enc) { + gst_object_sink (img->app_enc); GST_LOG_OBJECT (img, "disposing %s with refcount %d", GST_ELEMENT_NAME (img->app_enc), GST_OBJECT_REFCOUNT_VALUE (img->app_enc)); @@ -205,6 +212,7 @@ gst_camerabin_image_dispose (GstCameraBinImage * img) } if (img->post) { + gst_object_sink (img->post); GST_LOG_OBJECT (img, "disposing %s with refcount %d", GST_ELEMENT_NAME (img->post), GST_OBJECT_REFCOUNT_VALUE (img->post)); gst_object_unref (img->post); diff --git a/gst/camerabin/camerabinvideo.c b/gst/camerabin/camerabinvideo.c index 9100518767..257eed31f2 100644 --- a/gst/camerabin/camerabinvideo.c +++ b/gst/camerabin/camerabinvideo.c @@ -215,27 +215,38 @@ gst_camerabin_video_dispose (GstCameraBinVideo * vid) vid->vid_sink_probe_id = 0; } + /* Note: if videobin was never set to READY state the + ownership of elements created by application were never + taken by bin and therefore gst_object_sink is called for + these elements (they may still be in floating state + and not unreffed properly without sinking first) + */ if (vid->app_post) { + gst_object_sink (vid->app_post); gst_object_unref (vid->app_post); vid->app_post = NULL; } if (vid->app_vid_enc) { + gst_object_sink (vid->app_vid_enc); gst_object_unref (vid->app_vid_enc); vid->app_vid_enc = NULL; } if (vid->app_aud_enc) { + gst_object_sink (vid->app_aud_enc); gst_object_unref (vid->app_aud_enc); vid->app_aud_enc = NULL; } if (vid->app_aud_src) { + gst_object_sink (vid->app_aud_src); gst_object_unref (vid->app_aud_src); vid->app_aud_src = NULL; } if (vid->app_mux) { + gst_object_sink (vid->app_mux); gst_object_unref (vid->app_mux); vid->app_mux = NULL; } From a96fb3b4722cbb441d56a2a29adc2915f7e39daa Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Fri, 11 Feb 2011 17:59:31 +0100 Subject: [PATCH 403/448] rsvgoverlay: implement x/y/width/height (absolute and relative) positioning and dimensioning Signed-off-by: Olivier Aubert --- ext/rsvg/gstrsvgoverlay.c | 178 ++++++++++++++++++++++++++++++++++---- ext/rsvg/gstrsvgoverlay.h | 13 ++- 2 files changed, 171 insertions(+), 20 deletions(-) diff --git a/ext/rsvg/gstrsvgoverlay.c b/ext/rsvg/gstrsvgoverlay.c index 2a5bdc10d4..6875c9d4eb 100644 --- a/ext/rsvg/gstrsvgoverlay.c +++ b/ext/rsvg/gstrsvgoverlay.c @@ -24,19 +24,34 @@ * either be specified through properties, or fed through the * data-sink pad. * - * Note: setting the x or y parameter to a non-zero value will implicitly disable the fit-to-frame behaviour. + * Position and dimension of the SVG graphics can be achieved by + * specifying appropriate dimensions in the SVG file itself, but + * shortcuts are provided by the element to specify x/y position and + * width/height dimension, both in absolute form (pixels) and in + * relative form (percentage of video dimension). + * + * For any measure (x/y/width/height), the absolute value (in pixels) + * takes precedence over the relative one if both are + * specified. Absolute values must be set to 0 to disable them. + * + * If all parameters are 0, the image is displayed without rescaling + * at (0, 0) position. + * + * The fit-to-frame property is a shortcut for displaying the SVG + * overlay at (0, 0) position filling the whole screen. It modifies + * the values of the x/y/width/height attributes, by setting + * height-/width-relative to 1.0. and all other attributes to 0. * * - * * Example launch lines * |[ * gst-launch -v videotestsrc ! ffmpegcolorspace ! rsvgoverlay location=foo.svg ! ffmpegcolorspace ! autovideosink - * ]| specifies the SVG location through the filename property. + * ]| specifies the SVG location through the filename property. * |[ * gst-launch -v videotestsrc ! ffmpegcolorspace ! rsvgoverlay name=overlay ! ffmpegcolorspace ! autovideosink filesrc location=foo.svg ! image/svg ! overlay.data_sink * ]| does the same by feeding data through the data_sink pad. You can also specify the SVG data itself as parameter: * |[ - * gst-launch -v videotestsrc ! ffmpegcolorspace ! rsvgoverlay data='' ! ffmpegcolorspace ! autovideosink + * gst-launch -v videotestsrc ! ffmpegcolorspace ! rsvgoverlay data='<svg viewBox="0 0 800 600"><image x="80%" y="80%" width="10%" height="10%" xlink:href="foo.jpg" /></svg>' ! ffmpegcolorspace ! autovideosink * ]| * */ @@ -61,6 +76,12 @@ enum PROP_FIT_TO_FRAME, PROP_X, PROP_Y, + PROP_X_RELATIVE, + PROP_Y_RELATIVE, + PROP_WIDTH, + PROP_HEIGHT, + PROP_WIDTH_RELATIVE, + PROP_HEIGHT_RELATIVE }; #define GST_RSVG_LOCK(overlay) G_STMT_START { \ @@ -138,8 +159,8 @@ gst_rsvg_overlay_set_svg_data (GstRsvgOverlay * overlay, const gchar * data, /* Get SVG dimension. */ RsvgDimensionData svg_dimension; rsvg_handle_get_dimensions (overlay->handle, &svg_dimension); - overlay->width = svg_dimension.width; - overlay->height = svg_dimension.height; + overlay->svg_width = svg_dimension.width; + overlay->svg_height = svg_dimension.height; gst_base_transform_set_passthrough (btrans, FALSE); } } @@ -168,7 +189,19 @@ gst_rsvg_overlay_set_property (GObject * object, guint prop_id, } case PROP_FIT_TO_FRAME: { - overlay->fit_to_frame = g_value_get_boolean (value); + if (g_value_get_boolean (value)) { + overlay->x_offset = 0; + overlay->y_offset = 0; + overlay->x_relative = 0.0; + overlay->y_relative = 0.0; + overlay->width = 0; + overlay->height = 0; + overlay->width_relative = 1.0; + overlay->height_relative = 1.0; + } else { + overlay->width_relative = 0; + overlay->height_relative = 0; + } break; } case PROP_X: @@ -181,6 +214,37 @@ gst_rsvg_overlay_set_property (GObject * object, guint prop_id, overlay->y_offset = g_value_get_int (value); break; } + case PROP_X_RELATIVE: + { + overlay->x_relative = g_value_get_float (value); + break; + } + case PROP_Y_RELATIVE: + { + overlay->y_relative = g_value_get_float (value); + break; + } + + case PROP_WIDTH: + { + overlay->width = g_value_get_int (value); + break; + } + case PROP_HEIGHT: + { + overlay->height = g_value_get_int (value); + break; + } + case PROP_WIDTH_RELATIVE: + { + overlay->width_relative = g_value_get_float (value); + break; + } + case PROP_HEIGHT_RELATIVE: + { + overlay->height_relative = g_value_get_float (value); + break; + } default: { @@ -205,8 +269,29 @@ gst_rsvg_overlay_get_property (GObject * object, guint prop_id, GValue * value, case PROP_Y: g_value_set_int (value, overlay->y_offset); break; + case PROP_X_RELATIVE: + g_value_set_float (value, overlay->x_relative); + break; + case PROP_Y_RELATIVE: + g_value_set_float (value, overlay->y_relative); + break; + + case PROP_WIDTH: + g_value_set_int (value, overlay->width); + break; + case PROP_HEIGHT: + g_value_set_int (value, overlay->height); + break; + case PROP_WIDTH_RELATIVE: + g_value_set_float (value, overlay->width_relative); + break; + case PROP_HEIGHT_RELATIVE: + g_value_set_float (value, overlay->height_relative); + break; + case PROP_FIT_TO_FRAME: - g_value_set_boolean (value, overlay->fit_to_frame); + g_value_set_boolean (value, (overlay->width_relative == 1.0 + && overlay->height_relative == 1.0)); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -278,6 +363,10 @@ gst_rsvg_overlay_transform_ip (GstBaseTransform * btrans, GstBuffer * buf) GstRsvgOverlay *overlay = GST_RSVG_OVERLAY (btrans); cairo_surface_t *surface; cairo_t *cr; + double applied_x_offset = (double) overlay->x_offset; + double applied_y_offset = (double) overlay->y_offset; + int applied_width = overlay->width; + int applied_height = overlay->height; GST_RSVG_LOCK (overlay); if (!overlay->handle) { @@ -298,14 +387,37 @@ gst_rsvg_overlay_transform_ip (GstBaseTransform * btrans, GstBuffer * buf) return GST_FLOW_ERROR; } - /* If x or y offset is specified, do not fit-to-frame. */ - if (overlay->x_offset || overlay->y_offset) - cairo_translate (cr, (double) overlay->x_offset, - (double) overlay->y_offset); - else if (overlay->fit_to_frame && overlay->width && overlay->height) - cairo_scale (cr, (float) overlay->caps_width / overlay->width, - (float) overlay->caps_height / overlay->height); + /* Compute relative dimensions if absolute dimensions are not set */ + if (!applied_x_offset && overlay->x_relative) { + applied_x_offset = overlay->x_relative * overlay->caps_width; + } + if (!applied_y_offset && overlay->y_relative) { + applied_y_offset = overlay->y_relative * overlay->caps_height; + } + if (!applied_width && overlay->width_relative) { + applied_width = (int) (overlay->width_relative * overlay->caps_width); + } + if (!applied_height && overlay->height_relative) { + applied_height = (int) (overlay->height_relative * overlay->caps_height); + } + if (applied_x_offset || applied_y_offset) { + cairo_translate (cr, applied_x_offset, applied_y_offset); + } + + /* Scale when necessary, i.e. an absolute or relative dimension has been specified. */ + if ((applied_width || applied_height) && overlay->svg_width + && overlay->svg_height) { + /* If may happen that only one of the dimension is specified. Use + the original SVG size for the other dimension. */ + if (!applied_width) + applied_width = overlay->svg_width; + if (!applied_height) + applied_height = overlay->svg_height; + + cairo_scale (cr, (double) applied_width / overlay->svg_width, + (double) applied_height / overlay->svg_height); + } rsvg_handle_render_cairo (overlay->handle, cr); GST_RSVG_UNLOCK (overlay); @@ -366,6 +478,7 @@ gst_rsvg_overlay_class_init (GstRsvgOverlayClass * klass) g_param_spec_boolean ("fit-to-frame", "fit to frame", "Fit the SVG to fill the whole frame.", TRUE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_X, g_param_spec_int ("x", "x offset", "Specify an x offset.", 0, G_MAXINT, 0, @@ -374,6 +487,31 @@ gst_rsvg_overlay_class_init (GstRsvgOverlayClass * klass) g_param_spec_int ("y", "y offset", "Specify a y offset.", 0, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_X_RELATIVE, + g_param_spec_float ("x-relative", "x relative offset", + "Specify an x offset relative to the display size.", 0, G_MAXFLOAT, 0, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_Y_RELATIVE, + g_param_spec_float ("y-relative", "y relative offset", + "Specify a y offset relative to the display size.", 0, G_MAXFLOAT, 0, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_WIDTH, + g_param_spec_int ("width", "width", + "Specify a width in pixels.", 0, G_MAXINT, 0, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_HEIGHT, + g_param_spec_int ("height", "height", + "Specify a height in pixels.", 0, G_MAXINT, 0, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_WIDTH_RELATIVE, + g_param_spec_float ("width-relative", "relative width", + "Specify a width relative to the display size.", 0, G_MAXFLOAT, 0, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_HEIGHT_RELATIVE, + g_param_spec_float ("height-relative", "relative height", + "Specify a height relative to the display size.", 0, G_MAXFLOAT, 0, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); basetransform_class->set_caps = gst_rsvg_overlay_set_caps; basetransform_class->transform_ip = gst_rsvg_overlay_transform_ip; @@ -384,7 +522,15 @@ gst_rsvg_overlay_class_init (GstRsvgOverlayClass * klass) static void gst_rsvg_overlay_init (GstRsvgOverlay * overlay, GstRsvgOverlayClass * klass) { - overlay->fit_to_frame = 1; + overlay->x_offset = 0; + overlay->y_offset = 0; + overlay->x_relative = 0.0; + overlay->y_relative = 0.0; + overlay->width = 0; + overlay->height = 0; + overlay->width_relative = 0.0; + overlay->height_relative = 0.0; + overlay->adapter = gst_adapter_new (); /* data sink */ diff --git a/ext/rsvg/gstrsvgoverlay.h b/ext/rsvg/gstrsvgoverlay.h index a0125444cc..371bc35bec 100644 --- a/ext/rsvg/gstrsvgoverlay.h +++ b/ext/rsvg/gstrsvgoverlay.h @@ -50,13 +50,18 @@ struct _GstRsvgOverlay RsvgHandle *handle; /* width and height of the SVG data */ - int width; - int height; - /* Should we fit the SVG to the dimension ? */ - gboolean fit_to_frame; + int svg_width; + int svg_height; int x_offset; int y_offset; + float x_relative; + float y_relative; + + int width; + int height; + float width_relative; + float height_relative; GstVideoFormat caps_format; int caps_width; From 07f797bf39d9c1869a522c9f75e18b42ac0211a9 Mon Sep 17 00:00:00 2001 From: Stefan Kost Date: Mon, 14 Feb 2011 11:42:52 +0200 Subject: [PATCH 404/448] rsvgdec: add basic doc-blob --- ext/rsvg/gstrsvgdec.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/ext/rsvg/gstrsvgdec.c b/ext/rsvg/gstrsvgdec.c index b885d15b8f..c0a636216d 100644 --- a/ext/rsvg/gstrsvgdec.c +++ b/ext/rsvg/gstrsvgdec.c @@ -16,6 +16,18 @@ * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ +/** + * SECTION:element-rsvgdec + * + * This elements renders SVG graphics. + * + * + * Example launch lines + * |[ + * gst-launch filesrc location=image.svg ! rsvgdec ! imagefreeze ! ffmpegcolorspace ! autovideosink + * ]| render and show a svg image. + * + */ #ifdef HAVE_CONFIG_H #include "config.h" From eb0d4f2b3f373044e979d4fc354a88b4e5445e3b Mon Sep 17 00:00:00 2001 From: Stefan Kost Date: Mon, 14 Feb 2011 11:48:34 +0200 Subject: [PATCH 405/448] docs: add rsvg plugin to the docs --- docs/plugins/Makefile.am | 6 ++-- .../plugins/gst-plugins-bad-plugins-docs.sgml | 5 +++- .../gst-plugins-bad-plugins-sections.txt | 28 +++++++++++++++++++ 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/docs/plugins/Makefile.am b/docs/plugins/Makefile.am index 63719918fa..f148177629 100644 --- a/docs/plugins/Makefile.am +++ b/docs/plugins/Makefile.am @@ -69,7 +69,7 @@ SCANOBJ_DEPS = \ $(top_builddir)/gst-libs/gst/interfaces/libgstphotography-@GST_MAJORMINOR@.la # Header files to ignore when scanning. -IGNORE_HFILES = +IGNORE_HFILES = IGNORE_CFILES = # we add all .h files of elements that have signals/args we want @@ -83,7 +83,7 @@ IGNORE_CFILES = # -> it just works (TM) (ensonic) # FIXME: not ported yet -# $(top_srcdir)/ext/gnomevfs/gstgnomevfssink.c +# $(top_srcdir)/ext/gnomevfs/gstgnomevfssink.c # example code that needs to be converted to xml and placed in xml/ EXAMPLE_CFILES = \ @@ -124,6 +124,8 @@ EXTRA_HFILES = \ $(top_srcdir)/ext/opencv/gstpyramidsegment.h \ $(top_srcdir)/ext/opencv/gsttemplatematch.h \ $(top_srcdir)/ext/opencv/gsttextwrite.h \ + $(top_srcdir)/ext/rsvg/gstrsvgdec.h \ + $(top_srcdir)/ext/rsvg/gstrsvgoverlay.h \ $(top_srcdir)/ext/sdl/sdlaudiosink.h \ $(top_srcdir)/ext/sdl/sdlvideosink.h \ $(top_srcdir)/ext/theora/theoradec.h \ diff --git a/docs/plugins/gst-plugins-bad-plugins-docs.sgml b/docs/plugins/gst-plugins-bad-plugins-docs.sgml index d102a0691d..5551d5c600 100644 --- a/docs/plugins/gst-plugins-bad-plugins-docs.sgml +++ b/docs/plugins/gst-plugins-bad-plugins-docs.sgml @@ -1,5 +1,5 @@ - %version-entities; @@ -94,6 +94,8 @@ + + @@ -195,6 +197,7 @@ + diff --git a/docs/plugins/gst-plugins-bad-plugins-sections.txt b/docs/plugins/gst-plugins-bad-plugins-sections.txt index fe5104ad51..f85d0754d8 100644 --- a/docs/plugins/gst-plugins-bad-plugins-sections.txt +++ b/docs/plugins/gst-plugins-bad-plugins-sections.txt @@ -1188,6 +1188,34 @@ GST_TYPE_QT_MUX gst_qt_mux_get_type
+
+element-rsvgoverlay +rsvgoverlay +GstRsvgOverlay + +GstRsvgOverlayClass +GST_RSVG_OVERLAY +GST_RSVG_OVERLAY_CLASS +GST_IS_RSVG_OVERLAY +GST_IS_RSVG_OVERLAY_CLASS +GST_TYPE_RSVG_OVERLAY +gst_rsvg_overlay_get_type +
+ +
+element-rsvgdec +rsvgdec +GstRsvgDec + +GstRsvgDecClass +GST_RSVG_DEC +GST_RSVG_DEC_CLASS +GST_IS_RSVG_DEC +GST_IS_RSVG_DEC_CLASS +GST_TYPE_RSVG_DEC +gst_rsvg_dec_get_type +
+
element-rtpdtmfdepay rtpdtmfdepay From 7deaade2600a8366676c07d6b8b66acd2269a877 Mon Sep 17 00:00:00 2001 From: Stefan Kost Date: Mon, 14 Feb 2011 12:14:12 +0200 Subject: [PATCH 406/448] docs: remove duplicated rule from Makefile.am This causes a make warning and might even cause dist-failure. Other modules don't need to override the target either and if we can fi it in common/gtk-doc-plugins.mak. --- docs/plugins/Makefile.am | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/docs/plugins/Makefile.am b/docs/plugins/Makefile.am index f148177629..c9820cfd79 100644 --- a/docs/plugins/Makefile.am +++ b/docs/plugins/Makefile.am @@ -231,25 +231,6 @@ DOC_OVERRIDES = include $(top_srcdir)/common/gtk-doc-plugins.mak -# some additional clean rules from gtk-doc.mak -distclean-local: - rm -f $(REPORT_FILES) \ - $(DOC_MODULE)-decl-list.txt $(DOC_MODULE)-decl.txt - rm -rf tmpl/*.sgml.bak - rm -f $(DOC_MODULE).hierarchy - rm -f *.stamp || true - if test x"$(srcdir)" != x. ; then \ - rm -f $(DOC_MODULE)-docs.sgml ; \ - rm -f $(DOC_MODULE).types ; \ - rm -f $(DOC_MODULE).interfaces ; \ - rm -f $(DOC_MODULE)-overrides.txt ; \ - rm -f $(DOC_MODULE).prerequisites ; \ - rm -f $(DOC_MODULE)-sections.txt ; \ - rm -rf tmpl/*.sgml ; \ - fi - rm -rf *.o - - SUBDIRS = FIGURES_SOURCEFILES = camerabin.dot From b80b6d642667fe5e06587860120c2ca5459a5f1f Mon Sep 17 00:00:00 2001 From: Stefan Kost Date: Mon, 14 Feb 2011 12:53:49 +0200 Subject: [PATCH 407/448] Automatic update of common submodule From f94d739 to 1de7f6a --- common | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common b/common index f94d739915..1de7f6ab2d 160000 --- a/common +++ b/common @@ -1 +1 @@ -Subproject commit f94d73991563ea2dcae2218b4847e32998f06816 +Subproject commit 1de7f6ab2d4bc1af69f06079cf0f4e2cbbfdc178 From 451bbc4e1b12a8a64c9b5cddc4eddc4a4a53a8cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Wed, 16 Feb 2011 15:23:50 +0100 Subject: [PATCH 408/448] equalizer-test: Initialize debug category after gst_init() to fix segfault --- tests/icles/equalizer-test.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/icles/equalizer-test.c b/tests/icles/equalizer-test.c index d8fd8dda39..e8126fad3a 100644 --- a/tests/icles/equalizer-test.c +++ b/tests/icles/equalizer-test.c @@ -182,8 +182,6 @@ main (int argc, char **argv) if (!g_thread_supported ()) g_thread_init (NULL); - GST_DEBUG_CATEGORY_INIT (equalizer_test_debug, "equalizertest", 0, "eqtest"); - /* command line option parsing */ ctx = g_option_context_new ("FILENAME"); g_option_context_add_group (ctx, gst_init_get_option_group ()); @@ -194,6 +192,8 @@ main (int argc, char **argv) return -1; } + GST_DEBUG_CATEGORY_INIT (equalizer_test_debug, "equalizertest", 0, "eqtest"); + if (filenames == NULL || *filenames == NULL) { g_printerr ("Please specify a file to play back\n"); return -1; From 861e06cab8368caceb48eaa7370a8f07fdde3f02 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Wed, 16 Feb 2011 15:29:29 +0100 Subject: [PATCH 409/448] icles: Completely remove equalizer-test from -bad, it's in -good now --- Makefile.am | 3 +- tests/icles/Makefile.am | 8 +- tests/icles/equalizer-test.c | 289 ----------------------------------- 3 files changed, 3 insertions(+), 297 deletions(-) delete mode 100644 tests/icles/equalizer-test.c diff --git a/Makefile.am b/Makefile.am index a8ac17d49b..46fbdf5c9e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -64,7 +64,8 @@ CRUFT_FILES = \ $(top_builddir)/tests/examples/jack/jack_client \ $(top_builddir)/tests/examples/switch/switcher \ $(top_builddir)/tests/icles/output-selector-test \ - $(top_builddir)/tests/icles/test-oss4 + $(top_builddir)/tests/icles/test-oss4 \ + $(top_builddir)/tests/icles/equalizer-test CRUFT_DIRS = \ $(top_srcdir)/gst/aacparse \ diff --git a/tests/icles/Makefile.am b/tests/icles/Makefile.am index c175aec7f2..996c5cc5cc 100644 --- a/tests/icles/Makefile.am +++ b/tests/icles/Makefile.am @@ -25,11 +25,5 @@ endif GST_METADATA_TESTS = #endif -equalizer_test_SOURCES = equalizer-test.c -equalizer_test_CFLAGS = $(GST_CFLAGS) -equalizer_test_LDADD = $(GST_LIBS) -equalizer_test_LDFLAGS = $(GST_PLUGIN_LDFLAGS) - -noinst_PROGRAMS = $(GST_SOUNDTOUCH_TESTS) $(GST_METADATA_TESTS) \ - equalizer-test +noinst_PROGRAMS = $(GST_SOUNDTOUCH_TESTS) $(GST_METADATA_TESTS) diff --git a/tests/icles/equalizer-test.c b/tests/icles/equalizer-test.c deleted file mode 100644 index e8126fad3a..0000000000 --- a/tests/icles/equalizer-test.c +++ /dev/null @@ -1,289 +0,0 @@ -/* GStreamer test for the equalizer element - * Copyright (C) 2007 Tim-Philipp Müller - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -/* - * Will tests the equalizer by fading all bands in and out one by one and - * finaly all together. - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include - -#include -#include - -GST_DEBUG_CATEGORY_STATIC (equalizer_test_debug); -#define GST_CAT_DEFAULT equalizer_test_debug - -static GstBus *pipeline_bus; - -static gboolean -check_bus (GstClockTime max_wait_time) -{ - GstMessage *msg; - - msg = gst_bus_poll (pipeline_bus, GST_MESSAGE_ERROR | GST_MESSAGE_EOS, - max_wait_time); - - if (msg == NULL) - return FALSE; - - if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR) { - GError *err = NULL; - gchar *debug = NULL; - - g_assert (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR); - gst_message_parse_error (msg, &err, &debug); - GST_ERROR ("ERROR: %s [%s]", err->message, debug); - g_print ("\n===========> ERROR: %s\n%s\n\n", err->message, debug); - g_error_free (err); - g_free (debug); - } - - if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_EOS) { - g_print ("\n === EOS ===\n\n"); - } - - gst_message_unref (msg); - return TRUE; -} - -// fix below - -static void -equalizer_set_band_value (GstElement * eq, guint band, gdouble val) -{ - GstObject *child; - - child = gst_child_proxy_get_child_by_index (GST_CHILD_PROXY (eq), band); - g_object_set (child, "gain", val, NULL); - gst_object_unref (child); - g_print ("Band %2d: %.2f\n", band, val); -} - -static void -equalizer_set_all_band_values (GstElement * eq, guint num, gdouble val) -{ - gint i; - GstObject *child; - - for (i = 0; i < num; i++) { - child = gst_child_proxy_get_child_by_index (GST_CHILD_PROXY (eq), i); - g_object_set (child, "gain", val, NULL); - gst_object_unref (child); - } - g_print ("All bands: %.2f\n", val); -} - -// fix above - -static gboolean -equalizer_set_band_value_and_wait (GstElement * eq, guint band, gdouble val) -{ - equalizer_set_band_value (eq, band, val); - return check_bus (100 * GST_MSECOND); -} - -static gboolean -equalizer_set_all_band_values_and_wait (GstElement * eq, guint num, gdouble val) -{ - equalizer_set_all_band_values (eq, num, val); - return check_bus (100 * GST_MSECOND); -} - -static void -do_slider_fiddling (GstElement * playbin, GstElement * eq) -{ - gboolean stop; - guint num_bands, i; - gdouble d, step = 0.5; - - stop = FALSE; - - g_object_get (eq, "num-bands", &num_bands, NULL); - - g_print ("%u bands.\n", num_bands); - - while (!stop) { - for (i = 0; !stop && i < num_bands; ++i) { - d = -24.0; - while (!stop && d <= 12.0) { - stop = equalizer_set_band_value_and_wait (eq, i, d); - d += step; - } - d = 12.0; - while (!stop && d >= -24.0) { - stop = equalizer_set_band_value_and_wait (eq, i, d); - d -= step; - } - d = -24.0; - while (!stop && d <= 12.0) { - stop = equalizer_set_band_value_and_wait (eq, i, d); - d += step; - } - } - - d = 0.0; - while (!stop && d <= 12.0) { - stop = equalizer_set_all_band_values_and_wait (eq, num_bands, d); - d += step; - } - d = 12.0; - while (!stop && d >= -24.0) { - stop = equalizer_set_all_band_values_and_wait (eq, num_bands, d); - d -= step; - } - d = -24.0; - while (!stop && d <= 0.0) { - stop = equalizer_set_all_band_values_and_wait (eq, num_bands, d); - d += step; - } - } -} - -int -main (int argc, char **argv) -{ - gchar *opt_audiosink_str = NULL; - gchar **filenames = NULL; - const GOptionEntry test_goptions[] = { - {"audiosink", '\0', 0, G_OPTION_ARG_STRING, &opt_audiosink_str, - "audiosink to use (default: autoaudiosink)", NULL}, - {G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &filenames, NULL}, - {NULL, '\0', 0, 0, NULL, NULL, NULL} - }; - GOptionContext *ctx; - GError *opt_err = NULL; - - GstStateChangeReturn ret; - GstElement *playbin, *sink, *bin, *eq, *auconv; - GstPad *eq_sinkpad; - gchar *uri; - - if (!g_thread_supported ()) - g_thread_init (NULL); - - /* command line option parsing */ - ctx = g_option_context_new ("FILENAME"); - g_option_context_add_group (ctx, gst_init_get_option_group ()); - g_option_context_add_main_entries (ctx, test_goptions, NULL); - - if (!g_option_context_parse (ctx, &argc, &argv, &opt_err)) { - g_error ("Error parsing command line options: %s", opt_err->message); - return -1; - } - - GST_DEBUG_CATEGORY_INIT (equalizer_test_debug, "equalizertest", 0, "eqtest"); - - if (filenames == NULL || *filenames == NULL) { - g_printerr ("Please specify a file to play back\n"); - return -1; - } - - playbin = gst_element_factory_make ("playbin", "playbin"); - if (playbin == NULL) { - g_error ("Couldn't create 'playbin' element"); - return -1; - } - - if (opt_audiosink_str) { - g_print ("Trying audiosink '%s' ...", opt_audiosink_str); - sink = gst_element_factory_make (opt_audiosink_str, "sink"); - g_print ("%s\n", (sink) ? "ok" : "element couldn't be created"); - } else { - sink = NULL; - } - if (sink == NULL) { - g_print ("Trying audiosink '%s' ...", "autoaudiosink"); - sink = gst_element_factory_make ("autoaudiosink", "sink"); - g_print ("%s\n", (sink) ? "ok" : "element couldn't be created"); - } - if (sink == NULL) { - g_print ("Trying audiosink '%s' ...", "alsasink"); - sink = gst_element_factory_make ("alsasink", "sink"); - g_print ("%s\n", (sink) ? "ok" : "element couldn't be created"); - } - if (sink == NULL) { - g_print ("Trying audiosink '%s' ...", "osssink"); - sink = gst_element_factory_make ("osssink", "sink"); - g_print ("%s\n", (sink) ? "ok" : "element couldn't be created"); - } - - g_assert (sink != NULL); - - bin = gst_bin_new ("ausinkbin"); - g_assert (bin != NULL); - - eq = gst_element_factory_make ("equalizer-nbands", "equalizer"); - g_assert (eq != NULL); - - auconv = gst_element_factory_make ("audioconvert", "eqauconv"); - g_assert (auconv != NULL); - - gst_bin_add_many (GST_BIN (bin), eq, auconv, sink, NULL); - - if (!gst_element_link (eq, auconv)) - g_error ("Failed to link equalizer to audioconvert"); - - if (!gst_element_link (auconv, sink)) - g_error ("Failed to link audioconvert to audio sink"); - - eq_sinkpad = gst_element_get_static_pad (eq, "sink"); - g_assert (eq_sinkpad != NULL); - - gst_element_add_pad (bin, gst_ghost_pad_new (NULL, eq_sinkpad)); - gst_object_unref (eq_sinkpad); - - g_object_set (playbin, "audio-sink", bin, NULL); - - /* won't work: uri = gst_uri_construct ("file", filenames[0]); */ - uri = g_strdup_printf ("file://%s", filenames[0]); - g_object_set (playbin, "uri", uri, NULL); - g_free (uri); - - pipeline_bus = GST_ELEMENT_BUS (playbin); - - ret = gst_element_set_state (playbin, GST_STATE_PLAYING); - if (ret == GST_STATE_CHANGE_FAILURE) { - g_printerr ("Failed to set playbin to PLAYING\n"); - check_bus (1 * GST_SECOND); - return -1; - } - - ret = gst_element_get_state (playbin, NULL, NULL, 5 * GST_SECOND); - if (ret == GST_STATE_CHANGE_ASYNC) { - g_printerr ("Failed to go to PLAYING in 5 seconds, bailing out\n"); - return -1; - } else if (ret != GST_STATE_CHANGE_SUCCESS) { - g_printerr ("State change to PLAYING failed\n"); - check_bus (1 * GST_SECOND); - return -1; - } - - g_print ("Playing ...\n"); - do_slider_fiddling (playbin, eq); - - gst_element_set_state (playbin, GST_STATE_NULL); - gst_object_unref (playbin); - - return 0; -} From a887fc157ec4cfe2fbb0ea591e2f1e5670f74ce9 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Thu, 17 Feb 2011 12:28:56 +0100 Subject: [PATCH 410/448] faac: remove extraneous buffer unref --- ext/faac/gstfaac.c | 1 - 1 file changed, 1 deletion(-) diff --git a/ext/faac/gstfaac.c b/ext/faac/gstfaac.c index d26da1043c..f3086036fe 100644 --- a/ext/faac/gstfaac.c +++ b/ext/faac/gstfaac.c @@ -764,7 +764,6 @@ gst_faac_push_buffers (GstFaac * faac, gboolean force) encode_failed: { GST_ELEMENT_ERROR (faac, LIBRARY, ENCODE, (NULL), (NULL)); - gst_buffer_unref (outbuf); return GST_FLOW_ERROR; } } From 99baf8ae17f48cb34280374bcf1baaa3e68729ee Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Mon, 7 Feb 2011 14:46:57 +0100 Subject: [PATCH 411/448] baseparse: tune QUERY_SEEKING response Even if we currently do not have a duration yet, assume seekable if it looks like we'll likely be able to determine it later on (which coincides with needed information to perform seeking). Fixes #641047. --- gst/audioparsers/gstbaseparse.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gst/audioparsers/gstbaseparse.c b/gst/audioparsers/gstbaseparse.c index 75c945c2ee..16a6a081c9 100644 --- a/gst/audioparsers/gstbaseparse.c +++ b/gst/audioparsers/gstbaseparse.c @@ -3016,7 +3016,9 @@ gst_base_parse_query (GstPad * pad, GstQuery * query) if (!(res && seekable)) { if (!gst_base_parse_get_duration (parse, GST_FORMAT_TIME, &duration) || duration == -1) { - seekable = FALSE; + /* seekable if we still have a chance to get duration later on */ + seekable = + parse->priv->upstream_seekable && parse->priv->update_interval; } else { seekable = parse->priv->upstream_seekable; GST_LOG_OBJECT (parse, "already determine upstream seekabled: %d", From 2bb835f69af69c98d31f857456211fd05d5e5251 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Thu, 17 Feb 2011 14:12:43 +0100 Subject: [PATCH 412/448] baseparse: tune QUERY_SEEKING response Even if we currently do not have a duration yet, assume seekable if it looks like we'll likely be able to determine it later on (which coincides with needed information to perform seeking). --- gst/videoparsers/gstbaseparse.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/gst/videoparsers/gstbaseparse.c b/gst/videoparsers/gstbaseparse.c index 4ab5dbb367..db2691fe2e 100644 --- a/gst/videoparsers/gstbaseparse.c +++ b/gst/videoparsers/gstbaseparse.c @@ -3016,7 +3016,9 @@ gst_base_parse_query (GstPad * pad, GstQuery * query) if (!(res && seekable)) { if (!gst_base_parse_get_duration (parse, GST_FORMAT_TIME, &duration) || duration == -1) { - seekable = FALSE; + /* seekable if we still have a chance to get duration later on */ + seekable = + parse->priv->upstream_seekable && parse->priv->update_interval; } else { seekable = parse->priv->upstream_seekable; GST_LOG_OBJECT (parse, "already determine upstream seekabled: %d", From 22ecf13e428d05ca55b76a930c62e8cf91a075d4 Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Wed, 16 Feb 2011 17:57:42 +0100 Subject: [PATCH 413/448] mpegtsdemux: add MPEG TS demuxer rewrite from Edward Hervey with contributions from Miquel Angel Farre Guiu and Zaheer Abbas Merali --- configure.ac | 2 + gst-plugins-bad.spec.in | 1 + gst/mpegtsdemux/Makefile.am | 27 + gst/mpegtsdemux/TODO | 117 ++ gst/mpegtsdemux/gstmpegdefs.h | 234 +++ gst/mpegtsdemux/gstmpegdesc.c | 209 +++ gst/mpegtsdemux/gstmpegdesc.h | 342 ++++ gst/mpegtsdemux/gsttsdemux.c | 47 + gst/mpegtsdemux/mpegtsbase.c | 1257 +++++++++++++ gst/mpegtsdemux/mpegtsbase.h | 169 ++ gst/mpegtsdemux/mpegtspacketizer.c | 2714 ++++++++++++++++++++++++++++ gst/mpegtsdemux/mpegtspacketizer.h | 167 ++ gst/mpegtsdemux/mpegtsparse.c | 718 ++++++++ gst/mpegtsdemux/mpegtsparse.h | 71 + gst/mpegtsdemux/tsdemux.c | 1491 +++++++++++++++ gst/mpegtsdemux/tsdemux.h | 78 + 16 files changed, 7644 insertions(+) create mode 100644 gst/mpegtsdemux/Makefile.am create mode 100644 gst/mpegtsdemux/TODO create mode 100644 gst/mpegtsdemux/gstmpegdefs.h create mode 100644 gst/mpegtsdemux/gstmpegdesc.c create mode 100644 gst/mpegtsdemux/gstmpegdesc.h create mode 100644 gst/mpegtsdemux/gsttsdemux.c create mode 100644 gst/mpegtsdemux/mpegtsbase.c create mode 100644 gst/mpegtsdemux/mpegtsbase.h create mode 100644 gst/mpegtsdemux/mpegtspacketizer.c create mode 100644 gst/mpegtsdemux/mpegtspacketizer.h create mode 100644 gst/mpegtsdemux/mpegtsparse.c create mode 100644 gst/mpegtsdemux/mpegtsparse.h create mode 100644 gst/mpegtsdemux/tsdemux.c create mode 100644 gst/mpegtsdemux/tsdemux.h diff --git a/configure.ac b/configure.ac index 5819cb3c15..3e594baf76 100644 --- a/configure.ac +++ b/configure.ac @@ -320,6 +320,7 @@ AG_GST_CHECK_PLUGIN(legacyresample) AG_GST_CHECK_PLUGIN(librfb) AG_GST_CHECK_PLUGIN(liveadder) AG_GST_CHECK_PLUGIN(mpegdemux) +AG_GST_CHECK_PLUGIN(mpegtsdemux) AG_GST_CHECK_PLUGIN(mpegtsmux) AG_GST_CHECK_PLUGIN(mpegpsmux) AG_GST_CHECK_PLUGIN(mpeg4videoparse) @@ -1748,6 +1749,7 @@ gst/legacyresample/Makefile gst/librfb/Makefile gst/liveadder/Makefile gst/mpegdemux/Makefile +gst/mpegtsdemux/Makefile gst/mpegtsmux/Makefile gst/mpegtsmux/tsmux/Makefile gst/mpegpsmux/Makefile diff --git a/gst-plugins-bad.spec.in b/gst-plugins-bad.spec.in index 33c8bd887d..3b4fa9e27b 100644 --- a/gst-plugins-bad.spec.in +++ b/gst-plugins-bad.spec.in @@ -103,6 +103,7 @@ rm -rf $RPM_BUILD_ROOT %{_libdir}/gstreamer-%{majorminor}/libgstmpegtsmux.so %{_libdir}/gstreamer-%{majorminor}/libgstscaletempoplugin.so %{_libdir}/gstreamer-%{majorminor}/libgstmpegdemux.so +%{_libdir}/gstreamer-%{majorminor}/libgstmpegtsdemux.so %{_libdir}/gstreamer-%{majorminor}/libgstjp2k.so %{_libdir}/gstreamer-%{majorminor}/libgstapexsink.so %{_libdir}/gstreamer-%{majorminor}/libgstqtmux.so diff --git a/gst/mpegtsdemux/Makefile.am b/gst/mpegtsdemux/Makefile.am new file mode 100644 index 0000000000..bb88bbdd85 --- /dev/null +++ b/gst/mpegtsdemux/Makefile.am @@ -0,0 +1,27 @@ +plugin_LTLIBRARIES = libgstmpegtsdemux.la + +libgstmpegtsdemux_la_SOURCES = \ + gsttsdemux.c \ + gstmpegdesc.c \ + mpegtsbase.c \ + mpegtspacketizer.c \ + mpegtsparse.c \ + tsdemux.c + +libgstmpegtsdemux_la_CFLAGS = \ + $(GST_PLUGINS_BAD_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) \ + $(GST_BASE_CFLAGS) $(GST_CFLAGS) +libgstmpegtsdemux_la_LIBADD = \ + $(GST_PLUGINS_BASE_LIBS) -lgsttag-$(GST_MAJORMINOR) \ + $(GST_BASE_LIBS) $(GST_LIBS) +libgstmpegtsdemux_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) +libgstmpegtsdemux_la_LIBTOOLFLAGS = --tag=disable-static + +noinst_HEADERS = \ + gstmpegdefs.h \ + gstmpegdesc.h \ + mpegtsbase.h \ + mpegtspacketizer.h \ + mpegtsparse.c \ + tsdemux.h + diff --git a/gst/mpegtsdemux/TODO b/gst/mpegtsdemux/TODO new file mode 100644 index 0000000000..b8f636687a --- /dev/null +++ b/gst/mpegtsdemux/TODO @@ -0,0 +1,117 @@ +mpegtsparse rebasing +-------------------- + +Rationale : +----------- + + mpegtsparse code is more sane to handle and work with. + + We need a modular demuxer + + We need to avoid duplicating code regarding mpeg-ts in a gazillion + elements and allow easy creatiof new elements. + + +Battleplan : +------------ +* Figure out code from mpegtsparse which would be also needed for a +mpeg-ts demuxer (ex: packet/psi/pcr parsing). +* Extract common code into a base mpegtsbase class. +* Refactor mpegtsparse to subclass that base class. +* Create a minimalistic demuxer that creates pads (based on PSI info) +and outputs ES packets (let's say mpeg audio and video to start with) + +Potential subclasses : +---------------------- +* MpegTSParse : Program splitter. Given an incoming multi-program + mpeg-ts stream, it can provide request pads for each program. Each + of those pads will contain the ts packets specific to that program. + +* TSDemux : Program demuxer. Given an incoming single or multi-program + mpeg-ts stream, it will reconstruct the original Program Streams of + the selected program and output them on dynamically created pads. + +* HDVSplitter : Given an incoming HDV mpeg-ts stream, it will locate + the beginning of new scenes and output a mpeg-ts stream with the + PAT/PMT/AUX packets properly ordered and marked with DISCONT, so + that the following pipeline will automatically cut up a tape dump + into individual scenes: + filesrc ! hdvsplit ! multifilesink next-file=discont + +Code/Design common to a program-spliter and a demuxer : +------------------------------------------------------- +* Parsing TS packets +* Establishing PAT/PMT mapping +* Handling the notions of Programs/Streams +* Seeking ? + + One proposal... would be to have the base class automatically create + all the structures (and relationships) for the following objects: + + * Programs (from PAT/PMT, dunno if it could come from something + else) + * Program id + * Streams contained in that program (with links to them) + * Which stream contains the PCR + * Metadata ? + * Streams (ideally... in a table for fast access) + * We want to be able to have stream-type specific information + easily accessible also (like mpeg video specific data) + * Maybe some other info ??? + + The subclasses would then be able to make their own decision based + on those objects. + Maybe we could have some virtual methods that will be called when a + new program is detected, a new stream is added, etc... + + It is the subclass who decides what's to do with a given packet once + it's been parsed. + tsparse : forward it as-is to the pad corresponding to the program + tsdemux : forward it to the proper PS parser + hdvsplit : ? + + +Ideas to be taken into account for a proper demuxer : +----------------------------------------------------- +* Push-based (with inacurrate seeking) +* Pull-based (with fast *AND* accurate seeking) +* Modular system to add stream-type specific helper parsing + * Doesn't have to be fully fledged, just enough to help any kind of + seeking and scanning code. +* ... + +Problems to figure out : +------------------------ +* clock + Needed for proper dvb playback. mpegtsdemux currently does internal + clock estimation... to provide a clock with PCR estimations. + A proper way to solve that would be to timestamp the buffers at the + source element using the system clock, and then adjusting the PCR + against those values. (i.e. doing the opposite of what's done in + mpegtsdemux, but it will be more accurate since the timestamping is + done at the source). + + +Bugs that need fixing : +----------------------- +* Perfomance : Creation/Destruction of buffers is slow + * => This is due to g_type_instance_create using a dogslow rwlock + which take up to 50% of gst_adapter_take_buffer() + => Bugzilla #585375 (performance and contention problems) + +Code structure: + + MpegTSBase + +--- MpegTSParse + +--- TSDemux + + +Known limitations and problems : +-------------------------------- +* mpegtspacketizer + * Assumes 188 bytes packets. It should support all modes. + * offset/timestamp of incoming buffers need to be carried on to the + sub-buffers in order for several demuxer features to work correctly. +* mpegtsparser + * SERIOUS room for improvement performance-wise (see callgrind) + diff --git a/gst/mpegtsdemux/gstmpegdefs.h b/gst/mpegtsdemux/gstmpegdefs.h new file mode 100644 index 0000000000..947dc4d55e --- /dev/null +++ b/gst/mpegtsdemux/gstmpegdefs.h @@ -0,0 +1,234 @@ +/* + * This library is licensed under 2 different licenses and you + * can choose to use it under the terms of either one of them. The + * two licenses are the MPL 1.1 and the LGPL. + * + * MPL: + * + * The contents of this file are subject to the Mozilla Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the + * License for the specific language governing rights and limitations + * under the License. + * + * LGPL: + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + * The Original Code is Fluendo MPEG Demuxer plugin. + * + * The Initial Developer of the Original Code is Fluendo, S.L. + * Portions created by Fluendo, S.L. are Copyright (C) 2005 + * Fluendo, S.L. All Rights Reserved. + * + * Contributor(s): Wim Taymans + */ + +#ifndef __GST_MPEG_DEFS_H__ +#define __GST_MPEG_DEFS_H__ + +/* + * 1011 1100 program_stream_map + * 1011 1101 private_stream_1 + * 1011 1110 padding_stream + * 1011 1111 private_stream_2 + * 110x xxxx ISO/IEC 13818-3 or ISO/IEC 11172-3 audio stream number x xxxx + * 1110 xxxx ITU-T Rec. H.262 | ISO/IEC 13818-2 or ISO/IEC 11172-2 video stream number xxxx + * 1111 0000 ECM_stream + * 1111 0001 EMM_stream + * 1111 0010 ITU-T Rec. H.222.0 | ISO/IEC 13818-1 Annex A or ISO/IEC 13818-6_DSMCC_stream + * 1111 0011 ISO/IEC_13522_stream + * 1111 0100 ITU-T Rec. H.222.1 type A + * 1111 0101 ITU-T Rec. H.222.1 type B + * 1111 0110 ITU-T Rec. H.222.1 type C + * 1111 0111 ITU-T Rec. H.222.1 type D + * 1111 1000 ITU-T Rec. H.222.1 type E + * 1111 1001 ancillary_stream + * 1111 1010 E 1111 1110 reserved data stream + * 1111 1111 program_stream_directory + */ + +#define ID_PS_END_CODE 0x000001B9 +#define ID_PS_PACK_START_CODE 0x000001BA +#define ID_PS_SYSTEM_HEADER_START_CODE 0x000001BB +#define ID_PS_PROGRAM_STREAM_MAP 0x000001BC +#define ID_PRIVATE_STREAM_1 0x000001BD +#define ID_PADDING_STREAM 0x000001BE +#define ID_PRIVATE_STREAM_2 0x000001BF +#define ID_ISO_IEC_MPEG12_AUDIO_STREAM_0 0x000001C0 +#define ID_ISO_IEC_MPEG12_AUDIO_STREAM_32 0x000001DF +#define ID_ISO_IEC_MPEG12_VIDEO_STREAM_0 0x000001E0 +#define ID_ISO_IEC_MPEG12_VIDEO_STREAM_16 0x000001EF +#define ID_ECM_STREAM 0x000001F0 +#define ID_EMM_STREAM 0x000001F1 +#define ID_DSMCC_STREAM 0x000001F2 +#define ID_ISO_IEC_13522_STREAM 0x000001F3 +#define ID_ITU_TREC_H222_TYPE_A_STREAM 0x000001F4 +#define ID_ITU_TREC_H222_TYPE_B_STREAM 0x000001F5 +#define ID_ITU_TREC_H222_TYPE_C_STREAM 0x000001F6 +#define ID_ITU_TREC_H222_TYPE_D_STREAM 0x000001F7 +#define ID_ITU_TREC_H222_TYPE_E_STREAM 0x000001F8 +#define ID_ANCILLARY_STREAM 0x000001F9 +#define ID_RESERVED_STREAM_1 0x000001FA +#define ID_RESERVED_STREAM_2 0x000001FB +#define ID_EXTENDED_METADATA 0x000001FC +#define ID_EXTENDED_STREAM_ID 0x000001FD +#define ID_RESERVED_STREAM_3 0x000001FE +#define ID_PROGRAM_STREAM_DIRECTORY 0x000001FF + +#define PACKET_VIDEO_START_CODE 0x000001E0 +#define PACKET_AUDIO_START_CODE 0x000001C0 +#define PICTURE_START_CODE 0x00000100 +#define USER_DATA_START_CODE 0x000001B2 +#define SEQUENCE_HEADER_CODE 0x000001B3 +#define SEQUENCE_ERROR_CODE 0x000001B4 +#define EXTENSION_START_CODE 0x000001B5 +#define SEQUENCE_END_CODE 0x000001B7 +#define GROUP_START_CODE 0x000001B8 + +#define AC3_SYNC_WORD 0x0b770000 + +#define MPEG_TS_SYNC_BYTE 0x00000047 + +#define PID_PROGRAM_ASSOCIATION_TABLE 0x0000 +#define PID_CONDITIONAL_ACCESS_TABLE 0x0001 +#define PID_RESERVED_FIRST 0x0002 +#define PID_RESERVED_LAST 0x0010 +#define PID_NULL_PACKET 0x1FFF + +#define PID_TYPE_UNKNOWN 0 +#define PID_TYPE_RESERVED 1 +#define PID_TYPE_PROGRAM_ASSOCIATION 2 +#define PID_TYPE_CONDITIONAL_ACCESS 3 +#define PID_TYPE_PROGRAM_MAP 4 +#define PID_TYPE_ELEMENTARY 5 +#define PID_TYPE_NULL_PACKET 6 +#define PID_TYPE_PRIVATE_SECTION 7 + +/* Stream type assignments + * + * 0x00 ITU-T | ISO/IEC Reserved + * 0x01 ISO/IEC 11172 Video + * 0x02 ITU-T Rec. H.262 | ISO/IEC 13818-2 Video or + * ISO/IEC 11172-2 constrained parameter video + * stream + * 0x03 ISO/IEC 11172 Audio + * 0x04 ISO/IEC 13818-3 Audio + * 0x05 ITU-T Rec. H.222.0 | ISO/IEC 13818-1 + * private_sections + * 0x06 ITU-T Rec. H.222.0 | ISO/IEC 13818-1 PES + * packets containing private data + * 0x07 ISO/IEC 13522 MHEG + * 0x08 ITU-T Rec. H.222.0 | ISO/IEC 13818-1 Annex A + * DSM CC + * 0x09 ITU-T Rec. H.222.1 + * 0x0A ISO/IEC 13818-6 type A + * 0x0B ISO/IEC 13818-6 type B + * 0x0C ISO/IEC 13818-6 type C + * 0x0D ISO/IEC 13818-6 type D + * 0x0E ISO/IEC 13818-1 auxiliary + * 0x0F-0x7F ITU-T Rec. H.222.0 | ISO/IEC 13818-1 Reserved + * 0x80-0xFF User Private + */ +#define ST_RESERVED 0x00 +#define ST_VIDEO_MPEG1 0x01 +#define ST_VIDEO_MPEG2 0x02 +#define ST_AUDIO_MPEG1 0x03 +#define ST_AUDIO_MPEG2 0x04 +#define ST_PRIVATE_SECTIONS 0x05 +#define ST_PRIVATE_DATA 0x06 +#define ST_MHEG 0x07 +#define ST_DSMCC 0x08 +#define ST_H222_1 0x09 + +/* later extensions */ +#define ST_AUDIO_AAC 0x0f +#define ST_VIDEO_MPEG4 0x10 +#define ST_VIDEO_H264 0x1b + +/* Un-official Dirac extension */ +#define ST_VIDEO_DIRAC 0xd1 + +/* private stream types */ +#define ST_PS_AUDIO_AC3 0x81 +#define ST_PS_AUDIO_DTS 0x8a +#define ST_PS_AUDIO_LPCM 0x8b +#define ST_PS_DVD_SUBPICTURE 0xff +/* Blu-ray related */ +#define ST_BD_AUDIO_LPCM 0x80 +#define ST_BD_AUDIO_AC3 0x81 +#define ST_BD_AUDIO_DTS 0x82 +#define ST_BD_AUDIO_AC3_TRUE_HD 0x83 +#define ST_BD_AUDIO_AC3_PLUS 0x84 +#define ST_BD_AUDIO_DTS_HD 0x85 +#define ST_BD_AUDIO_DTS_HD_MASTER_AUDIO 0x86 +#define ST_BD_AUDIO_EAC3 0x87 +#define ST_BD_PGS_SUBPICTURE 0x90 +#define ST_BD_IGS 0x91 +#define ST_BD_SUBTITLE 0x92 +#define ST_BD_SECONDARY_AC3_PLUS 0xa1 +#define ST_BD_SECONDARY_DTS_HD 0xa2 + +/* defined for VC1 extension in RP227 */ +#define ST_PRIVATE_EA 0xea + +/* HDV AUX stream mapping + * 0xA0 ISO/IEC 61834-11 + * 0xA1 ISO/IEC 61834-11 + */ +#define ST_HDV_AUX_A 0xa0 +#define ST_HDV_AUX_V 0xa1 + +/* Un-official time-code stream */ +#define ST_PS_TIMECODE 0xd2 + +/* Internal stream types >= 0x100 */ +#define ST_GST_AUDIO_RAWA52 0x181 + /* Used when we don't yet know which stream type it will be in a PS stream */ +#define ST_GST_VIDEO_MPEG1_OR_2 0x102 + +#define CLOCK_BASE 9LL +#define CLOCK_FREQ (CLOCK_BASE * 10000) + +#define PCRTIME_TO_GSTTIME(time) (gst_util_uint64_scale ((time), \ + GST_MSECOND/10, 300 * CLOCK_BASE)) +#define MPEGTIME_TO_GSTTIME(time) (gst_util_uint64_scale ((time), \ + GST_MSECOND/10, CLOCK_BASE)) +#define GSTTIME_TO_MPEGTIME(time) (gst_util_uint64_scale ((time), \ + CLOCK_BASE, GST_MSECOND/10)) + +#define MPEG_MUX_RATE_MULT 50 + +/* sync:4 == 00xx ! pts:3 ! 1 ! pts:15 ! 1 | pts:15 ! 1 */ +#define READ_TS(data, target, lost_sync_label) \ + if ((*data & 0x01) != 0x01) goto lost_sync_label; \ + target = ((guint64) (*data++ & 0x0E)) << 29; \ + target |= ((guint64) (*data++ )) << 22; \ + if ((*data & 0x01) != 0x01) goto lost_sync_label; \ + target |= ((guint64) (*data++ & 0xFE)) << 14; \ + target |= ((guint64) (*data++ )) << 7; \ + if ((*data & 0x01) != 0x01) goto lost_sync_label; \ + target |= ((guint64) (*data++ & 0xFE)) >> 1; + +/* some extra GstFlowReturn values used internally */ +#define GST_FLOW_NEED_MORE_DATA GST_FLOW_CUSTOM_SUCCESS +#define GST_FLOW_LOST_SYNC GST_FLOW_CUSTOM_SUCCESS_1 + +#endif /* __GST_MPEG_DEFS_H__ */ diff --git a/gst/mpegtsdemux/gstmpegdesc.c b/gst/mpegtsdemux/gstmpegdesc.c new file mode 100644 index 0000000000..7e80483975 --- /dev/null +++ b/gst/mpegtsdemux/gstmpegdesc.c @@ -0,0 +1,209 @@ +/* + * The contents of this file are subject to the Mozilla Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the + * License for the specific language governing rights and limitations + * under the License. + * + * The Original Code is Fluendo MPEG Demuxer plugin. + * + * The Initial Developer of the Original Code is Fluendo, S.L. + * Portions created by Fluendo, S.L. are Copyright (C) 2005 + * Fluendo, S.L. All Rights Reserved. + * + * Contributor(s): Wim Taymans + * + * Alternatively, the contents of this file may be used under the terms of + * the GNU Lesser General Public License Version 2 or later (the "LGPL"), + * in which case the provisions of the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of the MPL or the LGPL. + */ + +#include + +#include + +#include "gstmpegdesc.h" + +GST_DEBUG_CATEGORY (gstmpegtsdesc_debug); +#define GST_CAT_DEFAULT (gstmpegtsdesc_debug) + +void +gst_mpeg_descriptor_free (GstMPEGDescriptor * desc) +{ + g_return_if_fail (desc != NULL); + + g_free (desc); +} + +static guint +gst_mpeg_descriptor_parse_1 (guint8 * data, guint size) +{ + guint8 tag; + guint8 length; + + /* need at least 2 bytes for tag and length */ + if (size < 2) + return 0; + + tag = *data++; + length = *data++; + size -= 2; + + GST_DEBUG ("tag: 0x%02x, length: %d", tag, length); + + if (length > size) + return 0; + + GST_MEMDUMP ("tag contents:", data, length); + + return length + 2; +} + +GstMPEGDescriptor * +gst_mpeg_descriptor_parse (guint8 * data, guint size) +{ + guint8 *current; + guint consumed, total, n_desc; + GstMPEGDescriptor *result; + + g_return_val_if_fail (data != NULL, NULL); + + current = data; + total = 0; + n_desc = 0; + + do { + consumed = gst_mpeg_descriptor_parse_1 (current, size); + + if (consumed > 0) { + current += consumed; + total += consumed; + size -= consumed; + n_desc++; + } + } + while (consumed > 0); + + GST_DEBUG ("parsed %d descriptors", n_desc); + + if (total == 0) + return NULL; + + result = g_malloc (sizeof (GstMPEGDescriptor) + total); + result->n_desc = n_desc; + result->data_length = total; + result->data = ((guint8 *) result) + sizeof (GstMPEGDescriptor); + + memcpy (result->data, data, total); + + return result; +} + +guint +gst_mpeg_descriptor_n_desc (GstMPEGDescriptor * desc) +{ + g_return_val_if_fail (desc != NULL, 0); + + return desc->n_desc; +} + +guint8 * +gst_mpeg_descriptor_find (GstMPEGDescriptor * desc, gint tag) +{ + guint8 length; + guint8 *current; + guint size; + + g_return_val_if_fail (desc != NULL, NULL); + + current = desc->data; + length = desc->data_length; + + while (length > 0) { + if (DESC_TAG (current) == tag) + return current; + + size = DESC_LENGTH (current) + 2; + + current += size; + length -= size; + } + return NULL; +} + +/* array needs freeing afterwards */ +GArray * +gst_mpeg_descriptor_find_all (GstMPEGDescriptor * desc, gint tag) +{ + GArray *all; + + guint8 length; + guint8 *current; + guint size; + + g_return_val_if_fail (desc != NULL, NULL); + all = g_array_new (TRUE, TRUE, sizeof (guint8 *)); + + current = desc->data; + length = desc->data_length; + + while (length > 0) { + if (DESC_TAG (current) == tag) + g_array_append_val (all, current); + size = DESC_LENGTH (current) + 2; + + current += size; + length -= size; + } + + GST_DEBUG ("found tag 0x%02x %d times", tag, all->len); + + return all; +} + +guint8 * +gst_mpeg_descriptor_nth (GstMPEGDescriptor * desc, guint i) +{ + guint8 length; + guint8 *current; + guint size; + + g_return_val_if_fail (desc != NULL, NULL); + + if (i > desc->n_desc) + return NULL; + + current = desc->data; + length = desc->data_length; + + while (length > 0) { + if (i == 0) + return current; + + size = DESC_LENGTH (current) + 2; + + current += size; + length -= size; + i--; + + } + return NULL; +} + +void +gst_mpegtsdesc_init_debug (void) +{ + GST_DEBUG_CATEGORY_INIT (gstmpegtsdesc_debug, "mpegtsdesc", 0, + "MPEG transport stream parser (descriptor)"); +} diff --git a/gst/mpegtsdemux/gstmpegdesc.h b/gst/mpegtsdemux/gstmpegdesc.h new file mode 100644 index 0000000000..9e1ae75c8e --- /dev/null +++ b/gst/mpegtsdemux/gstmpegdesc.h @@ -0,0 +1,342 @@ +/* + * The contents of this file are subject to the Mozilla Public License + * Version 1.1 (the "License"); you may not use this file except in + * compliance with the License. You may obtain a copy of the License at + * http://www.mozilla.org/MPL/. + * + * Software distributed under the License is distributed on an "AS IS" + * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the + * License for the specific language governing rights and limitations + * under the License. + * + * The Original Code is Fluendo MPEG Demuxer plugin. + * + * The Initial Developer of the Original Code is Fluendo, S.L. + * Portions created by Fluendo, S.L. are Copyright (C) 2005 + * Fluendo, S.L. All Rights Reserved. + * + * Contributor(s): Wim Taymans + * + * Alternatively, the contents of this file may be used under the terms of + * the GNU Lesser General Public License Version 2 or later (the "LGPL"), + * in which case the provisions of the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of the MPL or the LGPL. + */ + +#ifndef __GST_MPEG_DESC_H__ +#define __GST_MPEG_DESC_H__ + +#include +/* + * descriptor_tag TS PS Identification + * 0 n/a n/a Reserved + * 1 n/a n/a Reserved + * 2 X X video_stream_descriptor + * 3 X X audio_stream_descriptor + * 4 X X hierarchy_descriptor + * 5 X X registration_descriptor + * 6 X X data_stream_alignment_descriptor + * 7 X X target_background_grid_descriptor + * 8 X X video_window_descriptor + * 9 X X CA_descriptor + * 10 X X ISO_639_language_descriptor + * 11 X X system_clock_descriptor + * 12 X X multiplex_buffer_utilization_descriptor + * 13 X X copyright_descriptor + * 14 X maximum bitrate descriptor + * 15 X X private data indicator descriptor + * 16 X X smoothing buffer descriptor + * 17 X STD_descriptor + * 18 X X IBP descriptor + * 19-63 n/a n/a ITU-T Rec. H.222.0 | ISO/IEC 13818-1 Reserved + * 64-255 n/a n/a User Private + */ +#define DESC_VIDEO_STREAM 2 +#define DESC_AUDIO_STREAM 3 +#define DESC_HIERARCHY 4 +#define DESC_REGISTRATION 5 +#define DESC_DATA_STREAM_ALIGNMENT 6 +#define DESC_TARGET_BACKGROUND_GRID 7 +#define DESC_VIDEO_WINDOW 8 +#define DESC_CA 9 +#define DESC_ISO_639_LANGUAGE 10 +#define DESC_SYSTEM_CLOCK 11 +#define DESC_MULTIPLEX_BUFFER_UTILISATION 12 +#define DESC_COPYRIGHT 13 +#define DESC_MAXIMUM_BITRATE 14 +#define DESC_PRIVATE_DATA_INDICATOR 15 +#define DESC_SMOOTHING_BUFFER 16 +#define DESC_STD 17 +#define DESC_IBP 18 + +#define DESC_DIRAC_TC_PRIVATE 0xAC + +/* DVB tags */ +#define DESC_DVB_CAROUSEL_IDENTIFIER 0x13 +#define DESC_DVB_NETWORK_NAME 0x40 +#define DESC_DVB_SERVICE_LIST 0x41 +#define DESC_DVB_STUFFING 0x42 +#define DESC_DVB_SATELLITE_DELIVERY_SYSTEM 0x43 +#define DESC_DVB_CABLE_DELIVERY_SYSTEM 0x44 +#define DESC_DVB_VBI_DATA 0x45 +#define DESC_DVB_VBI_TELETEXT 0x46 +#define DESC_DVB_BOUQUET_NAME 0x47 +#define DESC_DVB_SERVICE 0x48 +#define DESC_DVB_COUNTRY_AVAILABILITY 0x49 +#define DESC_DVB_LINKAGE 0x4A +#define DESC_DVB_NVOD_REFERENCE 0x4B +#define DESC_DVB_TIME_SHIFTED_SERVICE 0x4C +#define DESC_DVB_SHORT_EVENT 0x4D +#define DESC_DVB_EXTENDED_EVENT 0x4E +#define DESC_DVB_TIME_SHIFTED_EVENT 0x4F +#define DESC_DVB_COMPONENT 0x50 +#define DESC_DVB_MOSAIC 0x51 +#define DESC_DVB_STREAM_IDENTIFIER 0x52 +#define DESC_DVB_CA_IDENTIFIER 0x53 +#define DESC_DVB_CONTENT 0x54 +#define DESC_DVB_PARENTAL_RATING 0x55 +#define DESC_DVB_TELETEXT 0x56 +#define DESC_DVB_TELEPHONE 0x57 +#define DESC_DVB_LOCAL_TIME_OFFSET 0x58 +#define DESC_DVB_SUBTITLING 0x59 +#define DESC_DVB_TERRESTRIAL_DELIVERY_SYSTEM 0x5A +#define DESC_DVB_MULTILINGUAL_NETWORK_NAME 0x5B +#define DESC_DVB_MULTILINGUAL_BOUQUET_NAME 0x5C +#define DESC_DVB_MULTILINGUAL_SERVICE_NAME 0x5D +#define DESC_DVB_MULTILINGUAL_COMPONENT 0x5E +#define DESC_DVB_PRIVATE_DATA 0x5F +#define DESC_DVB_SERVICE_MOVE 0x60 +#define DESC_DVB_SHORT_SMOOTHING_BUFFER 0x61 +#define DESC_DVB_FREQUENCY_LIST 0x62 +#define DESC_DVB_PARTIAL_TRANSPORT_STREAM 0x63 +#define DESC_DVB_DATA_BROADCAST 0x64 +#define DESC_DVB_SCRAMBLING 0x65 +#define DESC_DVB_DATA_BROADCAST_ID 0x66 +#define DESC_DVB_TRANSPORT_STREAM 0x67 +#define DESC_DVB_DSNG 0x68 +#define DESC_DVB_PDC 0x69 +#define DESC_DVB_AC3 0x6A +#define DESC_DVB_ANCILLARY_DATA 0x6B +#define DESC_DVB_CELL_LIST 0x6C +#define DESC_DVB_CELL_FREQUENCY_LINK 0x6D +#define DESC_DVB_ANNOUNCEMENT_SUPPORT 0x6E +#define DESC_DVB_APPLICATION_SIGNALLING 0x6F +#define DESC_DVB_ADAPTATION_FIELD_DATA 0x70 +#define DESC_DVB_SERVICE_IDENTIFIER 0x71 +#define DESC_DVB_SERVICE_AVAILABILITY 0x72 +#define DESC_DVB_DEFAULT_AUTHORITY 0x73 +#define DESC_DVB_RELATED_CONTENT 0x74 +#define DESC_DVB_TVA_ID 0x75 +#define DESC_DVB_CONTENT_IDENTIFIER 0x76 +#define DESC_DVB_TIMESLICE_FEC_IDENTIFIER 0x77 +#define DESC_DVB_ECM_REPETITION_RATE 0x78 +#define DESC_DVB_S2_SATELLITE_DELIVERY_SYSTEM 0x79 +#define DESC_DVB_ENHANCED_AC3 0x7A +#define DESC_DVB_DTS 0x7B +#define DESC_DVB_AAC 0x7C +/* 0x7D and 0x7E are reserved for future use */ +#define DESC_DVB_EXTENSION 0x7F +/* 0x80 - 0xFE are user defined */ +#define DESC_DTG_LOGICAL_CHANNEL 0x83 /* from DTG D-Book */ +/* 0xFF is forbidden */ + +/* common for all descriptors */ +#define DESC_TAG(desc) (desc[0]) +#define DESC_LENGTH(desc) (desc[1]) + +/* video_stream_descriptor */ +#define DESC_VIDEO_STREAM_multiple_framerate_flag(desc) (((desc)[2] & 0x80) == 0x80) +#define DESC_VIDEO_STREAM_frame_rate_code(desc) (((desc)[2] & 0x38) >> 3) +#define DESC_VIDEO_STREAM_MPEG_1_only_flag(desc) (((desc)[2] & 0x04) == 0x04) +#define DESC_VIDEO_STREAM_constrained_parameter_flag(desc) (((desc)[2] & 0x02) == 0x02) +#define DESC_VIDEO_STREAM_still_picture_flag(desc) (((desc)[2] & 0x01) == 0x01) +/* if (MPEG_1_only_flag == 1) */ +#define DESC_VIDEO_STREAM_profile_and_level_indication(desc) ((desc)[3]) +#define DESC_VIDEO_STREAM_chroma_format(desc) (((desc)[4] & 0xc0) >> 6) +#define DESC_VIDEO_STREAM_frame_rate_extension_flag(desc) (((desc)[4] & 0x20) == 0x20) + +/* audio_stream_descriptor */ +#define DESC_AUDIO_STREAM_free_format_flag(desc) (((desc)[2] & 0x80) == 0x80) +#define DESC_AUDIO_STREAM_ID(desc) (((desc)[2] & 0x40) == 0x40) +#define DESC_AUDIO_STREAM_layer(desc) (((desc)[2] & 0x30) >> 4) +#define DESC_AUDIO_STREAM_variable_rate_audio_indicator(desc) (((desc)[2] & 0x08) == 0x08) + +/* hierarchy_descriptor */ +#define DESC_HIERARCHY_hierarchy_type(desc) (((desc)[2] & 0x0f)) +#define DESC_HIERARCHY_hierarchy_layer_index(desc) (((desc)[3] & 0x3f)) +#define DESC_HIERARCHY_hierarchy_embedded_layer_index(desc) (((desc)[4] & 0x3f)) +#define DESC_HIERARCHY_hierarchy_channel(desc) (((desc)[5] & 0x3f)) + +/* registration_descriptor */ +#define DESC_REGISTRATION_format_identifier(desc) (GST_READ_UINT32_BE ((desc)+2)) +#define DESC_REGISTRATION_additional_ident_info_len(desc) ((desc)[1] - 4) +#define DESC_REGISTRATION_additional_ident_info(desc) (&(desc)[6]) + +/* data_stream_alignment_descriptor */ +#define DESC_DATA_STREAM_ALIGNMENT_alignment_type(desc) ((desc)[2]) + +/* target_background_grid_descriptor */ +#define DESC_TARGET_BACKGROUND_GRID_horizontal_size(desc) (GST_READ_UINT16_BE ((desc)+2) >> 2) +#define DESC_TARGET_BACKGROUND_GRID_vertical_size(desc) ((GST_READ_UINT32_BE ((desc)+2) & 0x0003fff0) >> 4) +#define DESC_TARGET_BACKGROUND_GRID_aspect_ratio_information(desc) ((desc)[5] & 0x0f) + +/* video_window_descriptor */ +#define DESC_VIDEO_WINDOW_horizontal_offset(desc) (GST_READ_UINT16_BE ((desc)+2) >> 2) +#define DESC_VIDEO_WINDOW_vertical_offset(desc) ((GST_READ_UINT32_BE ((desc)+2) & 0x0003fff0) >> 4) +#define DESC_VIDEO_WINDOW_window_priority(desc) ((desc)[5] & 0x0f) + +/* CA_descriptor */ +#define DESC_CA_system_ID(desc) (GST_READ_UINT16_BE ((desc)+2)) +#define DESC_CA_PID(desc) (GST_READ_UINT16_BE ((desc)+2) & 0x1fff) + +/* ISO_639_language_descriptor */ +#define DESC_ISO_639_LANGUAGE_codes_n(desc) ((desc[1]) >> 2) +#define DESC_ISO_639_LANGUAGE_language_code_nth(desc,i) (&(desc[2 + (4*i)])) +#define DESC_ISO_639_LANGUAGE_audio_type_nth(desc,i) ((desc)[5 + (4*i)]) + +/* system_clock_descriptor */ +#define DESC_SYSTEM_CLOCK_external_clock_reference_indicator(desc) (((desc)[2] & 0x80) == 0x80) +#define DESC_SYSTEM_CLOCK_clock_accuracy_integer(desc) ((desc)[2] & 0x3f) +#define DESC_SYSTEM_CLOCK_clock_accuracy_exponent(desc) (((desc)[3] & 0xe0) >> 5) + +/* multiplex_buffer_utilization_descriptor */ +#define DESC_MULTIPLEX_BUFFER_UTILISATION_bound_valid_flag(desc) (((desc)[2] & 0x80) == 0x80) +#define DESC_MULTIPLEX_BUFFER_UTILISATION_LTW_offset_lower_bound(desc) (GST_READ_UINT16_BE ((desc)+2) & 0x7fff) +#define DESC_MULTIPLEX_BUFFER_UTILISATION_LTW_offset_upper_bound(desc) (GST_READ_UINT16_BE ((desc)+4) & 0x7fff) + +/* copyright_descriptor */ +#define DESC_COPYRIGHT_copyright_identifier(desc) (GST_READ_UINT32_BE ((desc)+2)) +#define DESC_COPYRIGHT_additional_copyright_info_len(desc) ((desc)[1] - 4) +#define DESC_COPYRIGHT_additional_copyright_info(desc) (&(desc)[6]) + +/* maximum_bitrate_descriptor */ +#define DESC_MAXIMUM_BITRAT_maximum_bitrate(desc) (((((guint32)desc[2]) & 0x3f) << 16) | \ + GST_READ_UINT16_BE ((desc)+3)) + +/* private_data_indicator_descriptor */ +#define DESC_PRIVATE_DATA_INDICATOR_indicator(desc) (GST_READ_UINT32_BE(&desc[2])) + +/* smoothing_buffer_descriptor */ +#define DESC_SMOOTHING_BUFFER_sb_leak_rate(desc) (((((guint32)desc[2]) & 0x3f) << 16) | \ + GST_READ_UINT16_BE ((desc)+3)) +#define DESC_SMOOTHING_BUFFER_sb_size(desc) (((((guint32)desc[5]) & 0x3f) << 16) | \ + GST_READ_UINT16_BE ((desc)+6)) +/* STD_descriptor */ +#define DESC_STD_leak_valid_flag(desc) (((desc)[2] & 0x01) == 0x01) + +/* ibp_descriptor */ +#define DESC_IBP_closed_gop_flag(desc) (((desc)[2] & 0x80) == 0x80) +#define DESC_IBP_identical_gop_flag(desc) (((desc)[2] & 0x40) == 0x40) +#define DESC_IBP_max_gop_length(desc) (GST_READ_UINT16_BE ((desc)+6) & 0x3fff) + +/* time_code descriptor */ +#define DESC_TIMECODE_video_pid(desc) (GST_READ_UINT16_BE ((desc) + 2) & 0x1fff) + +/* Stream identifier descriptor */ +#define DESC_DVB_STREAM_IDENTIFIER_component_tag(desc) (desc[2]) + +/* DVB Network Name descriptor */ +#define DESC_DVB_NETWORK_NAME_length(desc) (GST_READ_UINT8((desc)+1)) +#define DESC_DVB_NETWORK_NAME_text(desc) (desc+2) + +/* DVB Service Descriptor */ +#define DESC_DVB_SERVICE_type(desc) (desc[2]) +#define DESC_DVB_SERVICE_provider_name_length(desc) (desc[3]) +#define DESC_DVB_SERVICE_provider_name_text(desc) (desc+4) +#define DESC_DVB_SERVICE_name_length(desc) (desc[4 + DESC_DVB_SERVICE_provider_name_length(desc)]) +#define DESC_DVB_SERVICE_name_text(desc) (desc + 5 + DESC_DVB_SERVICE_provider_name_length(desc)) + +/* DVB Component Descriptor */ +#define DESC_DVB_COMPONENT_stream_content(desc) (desc[2] & 0x0F) +#define DESC_DVB_COMPONENT_type(desc) (desc[3]) +#define DESC_DVB_COMPONENT_tag(desc) (desc[4]) +#define DESC_DVB_COMPONENT_language(desc) (desc + 5) + +/* DVB Bouquet Name Descriptor */ +#define DESC_DVB_BOUQUET_NAME_text(desc) (desc + 2) + +/* DVB Short Event Descriptor */ +#define DESC_DVB_SHORT_EVENT_name_text(desc) (desc + 6) +#define DESC_DVB_SHORT_EVENT_name_length(desc) (desc[5]) +#define DESC_DVB_SHORT_EVENT_description_text(desc) (desc + 6 + DESC_DVB_SHORT_EVENT_name_length(desc) + 1) +#define DESC_DVB_SHORT_EVENT_description_length(desc) (desc[6 + DESC_DVB_SHORT_EVENT_name_length(desc)]) + +/* DVB Extended Event Descriptor */ +#define DESC_DVB_EXTENDED_EVENT_descriptor_number(desc) ((desc[2] & 0xF0) >> 4) +#define DESC_DVB_EXTENDED_EVENT_last_descriptor_number(desc) (desc[2] & 0x0F) +#define DESC_DVB_EXTENDED_EVENT_iso639_language_code(desc) (desc + 3) +#define DESC_DVB_EXTENDED_EVENT_items_length(desc) (desc[6]) +#define DESC_DVB_EXTENDED_EVENT_items(desc) (desc + 7) +#define DESC_DVB_EXTENDED_EVENT_text_length(desc) (desc[7 + DESC_DVB_EXTENDED_EVENT_items_length(desc)]) +#define DESC_DVB_EXTENDED_EVENT_text(desc) (desc + 7 + DESC_DVB_EXTENDED_EVENT_items_length(desc) + 1) + +/* DVB Satellite Delivery System Descriptor */ +#define DESC_DVB_SATELLITE_DELIVERY_SYSTEM_frequency(desc) (desc + 2) +#define DESC_DVB_SATELLITE_DELIVERY_SYSTEM_orbital_position(desc) (desc + 6) +#define DESC_DVB_SATELLITE_DELIVERY_SYSTEM_west_east_flag(desc) ((desc[8] & 0x80) == 0x80) +#define DESC_DVB_SATELLITE_DELIVERY_SYSTEM_polarization(desc) ((desc[8] >> 5) & 0x3) +#define DESC_DVB_SATELLITE_DELIVERY_SYSTEM_modulation(desc) (desc[8] & 0x1F) +#define DESC_DVB_SATELLITE_DELIVERY_SYSTEM_symbol_rate(desc) (desc + 9) +#define DESC_DVB_SATELLITE_DELIVERY_SYSTEM_fec_inner(desc) (desc[12] & 0x0F) + +/* DVB Terrestrial Delivery System Descriptor */ +#define DESC_DVB_TERRESTRIAL_DELIVERY_SYSTEM_frequency(desc) (GST_READ_UINT32_BE((desc) + 2)) +#define DESC_DVB_TERRESTRIAL_DELIVERY_SYSTEM_bandwidth(desc) ((desc[6] >> 5) & 0x7) +#define DESC_DVB_TERRESTRIAL_DELIVERY_SYSTEM_constellation(desc) ((desc[7] >> 6) & 0x3) +#define DESC_DVB_TERRESTRIAL_DELIVERY_SYSTEM_hierarchy(desc) ((desc[7] >> 3) & 0x7) +#define DESC_DVB_TERRESTRIAL_DELIVERY_SYSTEM_code_rate_hp(desc) (desc[7] & 0x7) +#define DESC_DVB_TERRESTRIAL_DELIVERY_SYSTEM_code_rate_lp(desc) ((desc[8] >> 5) & 0x7) +#define DESC_DVB_TERRESTRIAL_DELIVERY_SYSTEM_guard_interval(desc) ((desc[8] >> 3) & 0x3) +#define DESC_DVB_TERRESTRIAL_DELIVERY_SYSTEM_transmission_mode(desc) ((desc[8] >> 1) & 0x3) +#define DESC_DVB_TERRESTRIAL_DELIVERY_SYSTEM_other_frequency(desc) ((desc[8] & 0x01) == 0x01) + +/* DVB Cable Delivery System Descriptor */ +#define DESC_DVB_CABLE_DELIVERY_SYSTEM_frequency(desc) (desc + 2) +#define DESC_DVB_CABLE_DELIVERY_SYSTEM_fec_outer(desc) (desc[7] & 0x0F) +#define DESC_DVB_CABLE_DELIVERY_SYSTEM_modulation(desc) (desc[8]) +#define DESC_DVB_CABLE_DELIVERY_SYSTEM_symbol_rate(desc) (desc + 9) +#define DESC_DVB_CABLE_DELIVERY_SYSTEM_fec_inner(desc) (desc[12] & 0x0F) + +/* DVB Data Broadcast Descriptor */ +#define DESC_DVB_DATA_BROADCAST_data_broadcast_id(desc) (GST_READ_UINT16_BE((desc) + 2)) +#define DESC_DVB_DATA_BROADCAST_component_tag(desc) (desc[4]) +#define DESC_DVB_DATA_BROADCAST_selector_length(desc) (desc[5]) +#define DESC_DVB_DATA_BROADCAST_selector(desc) (desc + 6) +#define DESC_DVB_DATA_BROADCAST_iso639_language_code(desc) (desc + 6 + DESC_DVB_DATA_BROADCAST_selector_length(desc)) +#define DESC_DVB_DATA_BROADCAST_text_length(desc) (desc + 9 + DESC_DVB_DATA_BROADCAST_selector_length(desc)) +#define DESC_DVB_DATA_BROADCAST_text(desc) (desc + 10 + DESC_DVB_DATA_BROADCAST_selector_length(desc)) + +/* DVB Data Broadcast Id Descriptor */ +#define DESC_DVB_DATA_BROADCAST_ID_data_broadcast_id(desc) (GST_READ_UINT16_BE((desc) + 2)) +#define DESC_DVB_DATA_BROADCAST_ID_id_selector_byte(desc) (desc + 4) + +/* DVB Carousel Identifier Descriptor */ +#define DESC_DVB_CAROUSEL_IDENTIFIER_carousel_id(desc) (GST_READ_UINT32_BE((desc) + 2)) + +/* registration_descriptor format IDs */ +#define DRF_ID_HDMV 0x48444d56 +#define DRF_ID_VC1 0x56432D31 /* defined in RP227 */ + +typedef struct { + guint n_desc; + guint8 data_length; + guint8 *data; +} GstMPEGDescriptor; + +void gst_mpegtsdesc_init_debug (void); +GstMPEGDescriptor* gst_mpeg_descriptor_parse (guint8 *data, guint size); +void gst_mpeg_descriptor_free (GstMPEGDescriptor *desc); + +guint gst_mpeg_descriptor_n_desc (GstMPEGDescriptor *desc); +guint8* gst_mpeg_descriptor_find (GstMPEGDescriptor *desc, gint tag); +GArray* gst_mpeg_descriptor_find_all (GstMPEGDescriptor * desc, gint tag); + +guint8* gst_mpeg_descriptor_nth (GstMPEGDescriptor *desc, guint i); + +#endif /* __GST_MPEG_DESC_H__ */ diff --git a/gst/mpegtsdemux/gsttsdemux.c b/gst/mpegtsdemux/gsttsdemux.c new file mode 100644 index 0000000000..fc9aa8ddd1 --- /dev/null +++ b/gst/mpegtsdemux/gsttsdemux.c @@ -0,0 +1,47 @@ +/* + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "mpegtsbase.h" +#include "mpegtspacketizer.h" +#include "mpegtsparse.h" +#include "tsdemux.h" + + +static gboolean +plugin_init (GstPlugin * plugin) +{ + if (!gst_mpegtsbase_plugin_init (plugin)) + return FALSE; + if (!gst_mpegtsparse_plugin_init (plugin)) + return FALSE; + if (!gst_ts_demux_plugin_init (plugin)) + return FALSE; + return TRUE; +} + +GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, + GST_VERSION_MINOR, + "mpegtsdemux", + "MPEG TS demuxer", + plugin_init, VERSION, + GST_LICENSE_UNKNOWN, GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN); diff --git a/gst/mpegtsdemux/mpegtsbase.c b/gst/mpegtsdemux/mpegtsbase.c new file mode 100644 index 0000000000..7151ef7a91 --- /dev/null +++ b/gst/mpegtsdemux/mpegtsbase.c @@ -0,0 +1,1257 @@ +/* + * mpegtsbase.c - + * Copyright (C) 2007 Alessandro Decina + * 2010 Edward Hervey + * + * Authors: + * Alessandro Decina + * Zaheer Abbas Merali + * Edward Hervey + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include +#include "mpegtsbase.h" +#include "gstmpegdesc.h" + +/* latency in mseconds */ +#define TS_LATENCY 700 + +#define TABLE_ID_UNSET 0xFF +#define RUNNING_STATUS_RUNNING 4 + +GST_DEBUG_CATEGORY_STATIC (mpegts_base_debug); +#define GST_CAT_DEFAULT mpegts_base_debug + +static GQuark QUARK_PROGRAMS; +static GQuark QUARK_PROGRAM_NUMBER; +static GQuark QUARK_PID; +static GQuark QUARK_PCR_PID; +static GQuark QUARK_STREAMS; +static GQuark QUARK_STREAM_TYPE; + +static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("video/mpegts, " "systemstream = (boolean) true ") + ); + +enum +{ + ARG_0, + /* FILL ME */ +}; + +static void mpegts_base_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void mpegts_base_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); +static void mpegts_base_dispose (GObject * object); +static void mpegts_base_finalize (GObject * object); +static void mpegts_base_free_program (MpegTSBaseProgram * program); +static void mpegts_base_free_stream (MpegTSBaseStream * ptream); +static gboolean mpegts_base_sink_activate (GstPad * pad); +static gboolean mpegts_base_sink_activate_pull (GstPad * pad, gboolean active); +static gboolean mpegts_base_sink_activate_push (GstPad * pad, gboolean active); +static GstFlowReturn mpegts_base_chain (GstPad * pad, GstBuffer * buf); +static gboolean mpegts_base_sink_event (GstPad * pad, GstEvent * event); +static GstStateChangeReturn mpegts_base_change_state (GstElement * element, + GstStateChange transition); +static void _extra_init (GType type); +static void mpegts_base_get_tags_from_sdt (MpegTSBase * base, + GstStructure * sdt_info); +static void mpegts_base_get_tags_from_eit (MpegTSBase * base, + GstStructure * eit_info); + +GST_BOILERPLATE_FULL (MpegTSBase, mpegts_base, GstElement, GST_TYPE_ELEMENT, + _extra_init); + + +static const guint32 crc_tab[256] = { + 0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, + 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, + 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7, + 0x4593e01e, 0x4152fda9, 0x5f15adac, 0x5bd4b01b, 0x569796c2, 0x52568b75, + 0x6a1936c8, 0x6ed82b7f, 0x639b0da6, 0x675a1011, 0x791d4014, 0x7ddc5da3, + 0x709f7b7a, 0x745e66cd, 0x9823b6e0, 0x9ce2ab57, 0x91a18d8e, 0x95609039, + 0x8b27c03c, 0x8fe6dd8b, 0x82a5fb52, 0x8664e6e5, 0xbe2b5b58, 0xbaea46ef, + 0xb7a96036, 0xb3687d81, 0xad2f2d84, 0xa9ee3033, 0xa4ad16ea, 0xa06c0b5d, + 0xd4326d90, 0xd0f37027, 0xddb056fe, 0xd9714b49, 0xc7361b4c, 0xc3f706fb, + 0xceb42022, 0xca753d95, 0xf23a8028, 0xf6fb9d9f, 0xfbb8bb46, 0xff79a6f1, + 0xe13ef6f4, 0xe5ffeb43, 0xe8bccd9a, 0xec7dd02d, 0x34867077, 0x30476dc0, + 0x3d044b19, 0x39c556ae, 0x278206ab, 0x23431b1c, 0x2e003dc5, 0x2ac12072, + 0x128e9dcf, 0x164f8078, 0x1b0ca6a1, 0x1fcdbb16, 0x018aeb13, 0x054bf6a4, + 0x0808d07d, 0x0cc9cdca, 0x7897ab07, 0x7c56b6b0, 0x71159069, 0x75d48dde, + 0x6b93dddb, 0x6f52c06c, 0x6211e6b5, 0x66d0fb02, 0x5e9f46bf, 0x5a5e5b08, + 0x571d7dd1, 0x53dc6066, 0x4d9b3063, 0x495a2dd4, 0x44190b0d, 0x40d816ba, + 0xaca5c697, 0xa864db20, 0xa527fdf9, 0xa1e6e04e, 0xbfa1b04b, 0xbb60adfc, + 0xb6238b25, 0xb2e29692, 0x8aad2b2f, 0x8e6c3698, 0x832f1041, 0x87ee0df6, + 0x99a95df3, 0x9d684044, 0x902b669d, 0x94ea7b2a, 0xe0b41de7, 0xe4750050, + 0xe9362689, 0xedf73b3e, 0xf3b06b3b, 0xf771768c, 0xfa325055, 0xfef34de2, + 0xc6bcf05f, 0xc27dede8, 0xcf3ecb31, 0xcbffd686, 0xd5b88683, 0xd1799b34, + 0xdc3abded, 0xd8fba05a, 0x690ce0ee, 0x6dcdfd59, 0x608edb80, 0x644fc637, + 0x7a089632, 0x7ec98b85, 0x738aad5c, 0x774bb0eb, 0x4f040d56, 0x4bc510e1, + 0x46863638, 0x42472b8f, 0x5c007b8a, 0x58c1663d, 0x558240e4, 0x51435d53, + 0x251d3b9e, 0x21dc2629, 0x2c9f00f0, 0x285e1d47, 0x36194d42, 0x32d850f5, + 0x3f9b762c, 0x3b5a6b9b, 0x0315d626, 0x07d4cb91, 0x0a97ed48, 0x0e56f0ff, + 0x1011a0fa, 0x14d0bd4d, 0x19939b94, 0x1d528623, 0xf12f560e, 0xf5ee4bb9, + 0xf8ad6d60, 0xfc6c70d7, 0xe22b20d2, 0xe6ea3d65, 0xeba91bbc, 0xef68060b, + 0xd727bbb6, 0xd3e6a601, 0xdea580d8, 0xda649d6f, 0xc423cd6a, 0xc0e2d0dd, + 0xcda1f604, 0xc960ebb3, 0xbd3e8d7e, 0xb9ff90c9, 0xb4bcb610, 0xb07daba7, + 0xae3afba2, 0xaafbe615, 0xa7b8c0cc, 0xa379dd7b, 0x9b3660c6, 0x9ff77d71, + 0x92b45ba8, 0x9675461f, 0x8832161a, 0x8cf30bad, 0x81b02d74, 0x857130c3, + 0x5d8a9099, 0x594b8d2e, 0x5408abf7, 0x50c9b640, 0x4e8ee645, 0x4a4ffbf2, + 0x470cdd2b, 0x43cdc09c, 0x7b827d21, 0x7f436096, 0x7200464f, 0x76c15bf8, + 0x68860bfd, 0x6c47164a, 0x61043093, 0x65c52d24, 0x119b4be9, 0x155a565e, + 0x18197087, 0x1cd86d30, 0x029f3d35, 0x065e2082, 0x0b1d065b, 0x0fdc1bec, + 0x3793a651, 0x3352bbe6, 0x3e119d3f, 0x3ad08088, 0x2497d08d, 0x2056cd3a, + 0x2d15ebe3, 0x29d4f654, 0xc5a92679, 0xc1683bce, 0xcc2b1d17, 0xc8ea00a0, + 0xd6ad50a5, 0xd26c4d12, 0xdf2f6bcb, 0xdbee767c, 0xe3a1cbc1, 0xe760d676, + 0xea23f0af, 0xeee2ed18, 0xf0a5bd1d, 0xf464a0aa, 0xf9278673, 0xfde69bc4, + 0x89b8fd09, 0x8d79e0be, 0x803ac667, 0x84fbdbd0, 0x9abc8bd5, 0x9e7d9662, + 0x933eb0bb, 0x97ffad0c, 0xafb010b1, 0xab710d06, 0xa6322bdf, 0xa2f33668, + 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4 +}; + +/* relicenced to LGPL from fluendo ts demuxer */ +static guint32 +mpegts_base_calc_crc32 (guint8 * data, guint datalen) +{ + gint i; + guint32 crc = 0xffffffff; + + for (i = 0; i < datalen; i++) { + crc = (crc << 8) ^ crc_tab[((crc >> 24) ^ *data++) & 0xff]; + } + return crc; +} + +static void +_extra_init (GType type) +{ + QUARK_PROGRAMS = g_quark_from_string ("programs"); + QUARK_PROGRAM_NUMBER = g_quark_from_string ("program-number"); + QUARK_PID = g_quark_from_string ("pid"); + QUARK_PCR_PID = g_quark_from_string ("pcr-pid"); + QUARK_STREAMS = g_quark_from_string ("streams"); + QUARK_STREAM_TYPE = g_quark_from_string ("stream-type"); +} + +static void +mpegts_base_base_init (gpointer klass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&sink_template)); +} + +static void +mpegts_base_class_init (MpegTSBaseClass * klass) +{ + GObjectClass *gobject_class; + GstElementClass *element_class; + + element_class = GST_ELEMENT_CLASS (klass); + element_class->change_state = mpegts_base_change_state; + + gobject_class = G_OBJECT_CLASS (klass); + gobject_class->set_property = mpegts_base_set_property; + gobject_class->get_property = mpegts_base_get_property; + gobject_class->dispose = mpegts_base_dispose; + gobject_class->finalize = mpegts_base_finalize; + +} + +static void +mpegts_base_reset (MpegTSBase * base) +{ + mpegts_packetizer_clear (base->packetizer); + memset (base->is_pes, 0, 8192); + memset (base->known_psi, 0, 8192); + + /* PAT */ + base->known_psi[0] = TRUE; + + /* FIXME : Commenting the Following lines is to be in sync with the following + * commit + * + * 61a885613316ce7657c36a6cd215b43f9dc67b79 + * mpegtsparse: don't free PAT structure which may still be needed later + */ + + /* if (base->pat != NULL) */ + /* gst_structure_free (base->pat); */ + /* base->pat = NULL; */ + /* pmt pids will be added and removed dynamically */ + +} + +static void +mpegts_base_init (MpegTSBase * base, MpegTSBaseClass * klass) +{ + base->sinkpad = gst_pad_new_from_static_template (&sink_template, "sink"); + gst_pad_set_activate_function (base->sinkpad, mpegts_base_sink_activate); + gst_pad_set_activatepull_function (base->sinkpad, + mpegts_base_sink_activate_pull); + gst_pad_set_activatepush_function (base->sinkpad, + mpegts_base_sink_activate_push); + gst_pad_set_chain_function (base->sinkpad, mpegts_base_chain); + gst_pad_set_event_function (base->sinkpad, mpegts_base_sink_event); + gst_element_add_pad (GST_ELEMENT (base), base->sinkpad); + + base->disposed = FALSE; + base->packetizer = mpegts_packetizer_new (); + base->programs = g_hash_table_new_full (g_direct_hash, g_direct_equal, + NULL, (GDestroyNotify) mpegts_base_free_program); + + base->is_pes = g_new0 (gboolean, 8192); + base->known_psi = g_new0 (gboolean, 8192); + mpegts_base_reset (base); + base->program_size = sizeof (MpegTSBaseProgram); + base->stream_size = sizeof (MpegTSBaseStream); + + base->mode = BASE_MODE_STREAMING; + base->first_pat_offset = -1; +} + +static void +mpegts_base_dispose (GObject * object) +{ + MpegTSBase *base = GST_MPEGTS_BASE (object); + + if (!base->disposed) { + g_object_unref (base->packetizer); + base->disposed = TRUE; + g_free (base->known_psi); + g_free (base->is_pes); + } + + if (G_OBJECT_CLASS (parent_class)->dispose) + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +static void +mpegts_base_finalize (GObject * object) +{ + MpegTSBase *base = GST_MPEGTS_BASE (object); + + if (base->pat) { + gst_structure_free (base->pat); + base->pat = NULL; + } + g_hash_table_destroy (base->programs); + + if (G_OBJECT_CLASS (parent_class)->finalize) + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +mpegts_base_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + /* MpegTSBase *base = GST_MPEGTS_BASE (object); */ + + switch (prop_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +mpegts_base_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + /* MpegTSBase *base = GST_MPEGTS_BASE (object); */ + + switch (prop_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +/* returns NULL if no matching descriptor found * + * otherwise returns a descriptor that needs to * + * be freed */ +guint8 * +mpegts_get_descriptor_from_stream (MpegTSBaseStream * stream, guint8 tag) +{ + GValueArray *descriptors = NULL; + GstStructure *stream_info = stream->stream_info; + guint8 *retval = NULL; + int i; + + gst_structure_get (stream_info, "descriptors", G_TYPE_VALUE_ARRAY, + &descriptors, NULL); + if (descriptors) { + for (i = 0; i < descriptors->n_values; i++) { + GValue *value = g_value_array_get_nth (descriptors, i); + guint8 *desc = g_value_dup_boxed (value); + if (DESC_TAG (desc) == tag) { + retval = desc; + break; + } + } + g_value_array_free (descriptors); + } + return retval; +} + +/* returns NULL if no matching descriptor found * + * otherwise returns a descriptor that needs to * + * be freed */ +guint8 * +mpegts_get_descriptor_from_program (MpegTSBaseProgram * program, guint8 tag) +{ + GValueArray *descriptors = NULL; + GstStructure *program_info; + guint8 *retval = NULL; + int i; + + if (G_UNLIKELY (program == NULL)) + return NULL; + program_info = program->pmt_info; + gst_structure_get (program_info, "descriptors", G_TYPE_VALUE_ARRAY, + &descriptors, NULL); + if (descriptors) { + for (i = 0; i < descriptors->n_values; i++) { + GValue *value = g_value_array_get_nth (descriptors, i); + GString *desc = g_value_dup_boxed (value); + if (DESC_TAG (desc->str) == tag) { + retval = (guint8 *) desc->str; + g_string_free (desc, FALSE); + break; + } else + g_string_free (desc, FALSE); + } + g_value_array_free (descriptors); + } + return retval; +} + +MpegTSBaseProgram * +mpegts_base_add_program (MpegTSBase * base, + gint program_number, guint16 pmt_pid) +{ + MpegTSBaseProgram *program; + + program = g_malloc0 (base->program_size); + program->program_number = program_number; + program->pmt_pid = pmt_pid; + program->pcr_pid = G_MAXUINT16; + program->streams = g_new0 (MpegTSBaseStream *, 0x2000); + program->patcount = 0; + + g_hash_table_insert (base->programs, + GINT_TO_POINTER (program_number), program); + + return program; +} + +MpegTSBaseProgram * +mpegts_base_get_program (MpegTSBase * base, gint program_number) +{ + MpegTSBaseProgram *program; + + program = (MpegTSBaseProgram *) g_hash_table_lookup (base->programs, + GINT_TO_POINTER ((gint) program_number)); + + return program; +} + +#if 0 +static GstPad * +mpegts_base_activate_program (MpegTSBase * base, MpegTSBaseProgram * program) +{ + MpegTSBasePad *tspad; + gchar *pad_name; + + pad_name = g_strdup_printf ("program_%d", program->program_number); + + tspad = mpegts_base_create_tspad (base, pad_name); + tspad->program_number = program->program_number; + tspad->program = program; + program->tspad = tspad; + g_free (pad_name); + gst_pad_set_active (tspad->pad, TRUE); + program->active = TRUE; + + return tspad->pad; +} + +static GstPad * +mpegts_base_deactivate_program (MpegTSBase * base, MpegTSBaseProgram * program) +{ + MpegTSBasePad *tspad; + + tspad = program->tspad; + gst_pad_set_active (tspad->pad, FALSE); + program->active = FALSE; + + /* tspad will be destroyed in GstElementClass::pad_removed */ + + return tspad->pad; +} +#endif + + +static void +mpegts_base_free_program (MpegTSBaseProgram * program) +{ + guint i; + + if (program->pmt_info) + gst_structure_free (program->pmt_info); + + for (i = 0; i < 0x2000; i++) + if (program->streams[i]) + mpegts_base_free_stream (program->streams[i]); + + if (program->tags) + gst_tag_list_free (program->tags); + + g_free (program); +} + +void +mpegts_base_remove_program (MpegTSBase * base, gint program_number) +{ + MpegTSBaseProgram *program; + MpegTSBaseClass *klass = GST_MPEGTS_BASE_GET_CLASS (base); + + if (klass->program_stopped) { + program = + (MpegTSBaseProgram *) g_hash_table_lookup (base->programs, + GINT_TO_POINTER (program_number)); + klass->program_stopped (base, program); + } + g_hash_table_remove (base->programs, GINT_TO_POINTER (program_number)); + +} + +static MpegTSBaseStream * +mpegts_base_program_add_stream (MpegTSBase * base, + MpegTSBaseProgram * program, guint16 pid, guint8 stream_type, + GstStructure * stream_info) +{ + MpegTSBaseClass *klass = GST_MPEGTS_BASE_GET_CLASS (base); + MpegTSBaseStream *stream; + + GST_DEBUG ("pid:0x%04x, stream_type:0x%03x, stream_info:%" GST_PTR_FORMAT, + pid, stream_type, stream_info); + + stream = g_malloc0 (base->stream_size); + stream->pid = pid; + stream->stream_type = stream_type; + stream->stream_info = stream_info; + + program->streams[pid] = stream; + + if (klass->stream_added) + klass->stream_added (base, stream, program); + + return stream; +} + +static void +mpegts_base_free_stream (MpegTSBaseStream * stream) +{ + g_free (stream); +} + +void +mpegts_base_program_remove_stream (MpegTSBase * base, + MpegTSBaseProgram * program, guint16 pid) +{ + MpegTSBaseClass *klass = GST_MPEGTS_BASE_GET_CLASS (base); + + /* If subclass needs it, inform it of the stream we are about to remove */ + if (klass->stream_removed) + klass->stream_removed (base, program->streams[pid]); + + mpegts_base_free_stream (program->streams[pid]); + program->streams[pid] = NULL; +} + +static void +mpegts_base_deactivate_pmt (MpegTSBase * base, MpegTSBaseProgram * program) +{ + gint i; + guint pid; + guint stream_type; + GstStructure *stream; + const GValue *streams; + const GValue *value; + MpegTSBaseClass *klass = GST_MPEGTS_BASE_GET_CLASS (base); + + if (program->pmt_info) { + /* Inform subclasses we're deactivating this program */ + if (klass->program_stopped) + klass->program_stopped (base, program); + + streams = gst_structure_id_get_value (program->pmt_info, QUARK_STREAMS); + + for (i = 0; i < gst_value_list_get_size (streams); ++i) { + value = gst_value_list_get_value (streams, i); + stream = g_value_get_boxed (value); + gst_structure_id_get (stream, QUARK_PID, G_TYPE_UINT, &pid, + QUARK_STREAM_TYPE, G_TYPE_UINT, &stream_type, NULL); + mpegts_base_program_remove_stream (base, program, (guint16) pid); + base->is_pes[pid] = FALSE; + } + /* remove pcr stream */ + mpegts_base_program_remove_stream (base, program, program->pcr_pid); + base->is_pes[program->pcr_pid] = FALSE; + } +} + + +gboolean +mpegts_base_is_psi (MpegTSBase * base, MpegTSPacketizerPacket * packet) +{ + gboolean retval = FALSE; + guint8 table_id; + int i; + static const guint8 si_tables[] = + { 0x00, 0x01, 0x02, 0x03, 0x40, 0x41, 0x42, 0x46, 0x4A, + 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, + 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F, 0x60, 0x61, 0x62, 0x63, 0x64, 0x65, + 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, + 0x72, 0x73, 0x7E, 0x7F, TABLE_ID_UNSET + }; + + if (base->known_psi[packet->pid]) + retval = TRUE; + + /* check is it is a pes pid */ + if (base->is_pes[packet->pid]) + return FALSE; + + if (!retval) { + if (packet->payload_unit_start_indicator) { + table_id = *(packet->data); + i = 0; + while (si_tables[i] != TABLE_ID_UNSET) { + if (G_UNLIKELY (si_tables[i] == table_id)) { + GST_DEBUG_OBJECT (base, "Packet has table id 0x%x", table_id); + retval = TRUE; + break; + } + i++; + } + } else { + MpegTSPacketizerStream *stream = (MpegTSPacketizerStream *) + base->packetizer->streams[packet->pid]; + + if (stream) { + i = 0; + GST_DEBUG_OBJECT (base, "section table id: 0x%x", + stream->section_table_id); + while (si_tables[i] != TABLE_ID_UNSET) { + if (G_UNLIKELY (si_tables[i] == stream->section_table_id)) { + retval = TRUE; + break; + } + i++; + } + } + } + } + + GST_LOG_OBJECT (base, "Packet of pid 0x%x is psi: %d", packet->pid, retval); + return retval; +} + +static void +mpegts_base_apply_pat (MpegTSBase * base, GstStructure * pat_info) +{ + const GValue *value; + GstStructure *old_pat; + GstStructure *program_info; + guint program_number; + guint pid; + MpegTSBaseProgram *program; + gint i; + const GValue *programs; + MpegTSBaseClass *klass = GST_MPEGTS_BASE_GET_CLASS (base); + + old_pat = base->pat; + base->pat = gst_structure_copy (pat_info); + + GST_INFO_OBJECT (base, "PAT %" GST_PTR_FORMAT, pat_info); + + gst_element_post_message (GST_ELEMENT_CAST (base), + gst_message_new_element (GST_OBJECT (base), + gst_structure_copy (pat_info))); + + programs = gst_structure_id_get_value (pat_info, QUARK_PROGRAMS); + /* activate the new table */ + for (i = 0; i < gst_value_list_get_size (programs); ++i) { + value = gst_value_list_get_value (programs, i); + + program_info = g_value_get_boxed (value); + gst_structure_id_get (program_info, QUARK_PROGRAM_NUMBER, G_TYPE_UINT, + &program_number, QUARK_PID, G_TYPE_UINT, &pid, NULL); + + program = mpegts_base_get_program (base, program_number); + if (program) { + if (program->pmt_pid != pid) { + if (program->pmt_pid != G_MAXUINT16) { + /* pmt pid changed */ + /* FIXME: when this happens it may still be pmt pid of another + * program, so setting to False may make it go through expensive + * path in is_psi unnecessarily */ + base->known_psi[program->pmt_pid] = FALSE; + } + + program->pmt_pid = pid; + base->known_psi[pid] = TRUE; + } + } else { + base->known_psi[pid] = TRUE; + program = mpegts_base_add_program (base, program_number, pid); + } + program->patcount += 1; + } + + if (old_pat) { + /* deactivate the old table */ + + programs = gst_structure_id_get_value (old_pat, QUARK_PROGRAMS); + for (i = 0; i < gst_value_list_get_size (programs); ++i) { + value = gst_value_list_get_value (programs, i); + + program_info = g_value_get_boxed (value); + gst_structure_id_get (program_info, + QUARK_PROGRAM_NUMBER, G_TYPE_UINT, &program_number, + QUARK_PID, G_TYPE_UINT, &pid, NULL); + + program = mpegts_base_get_program (base, program_number); + if (program == NULL) { + GST_DEBUG_OBJECT (base, "broken PAT, duplicated entry for program %d", + program_number); + continue; + } + + if (--program->patcount > 0) + /* the program has been referenced by the new pat, keep it */ + continue; + + GST_INFO_OBJECT (base, "PAT removing program %" GST_PTR_FORMAT, + program_info); + + if (klass->program_stopped) { + klass->program_stopped (base, program); + } + mpegts_base_deactivate_pmt (base, program); + mpegts_base_remove_program (base, program_number); + /* FIXME: when this happens it may still be pmt pid of another + * program, so setting to False may make it go through expensive + * path in is_psi unnecessarily */ + base->known_psi[pid] = TRUE; + mpegts_packetizer_remove_stream (base->packetizer, pid); + } + + gst_structure_free (old_pat); + } +#if 0 + mpegts_base_sync_program_pads (base); +#endif +} + +static void +mpegts_base_apply_pmt (MpegTSBase * base, + guint16 pmt_pid, GstStructure * pmt_info) +{ + MpegTSBaseProgram *program; + guint program_number; + guint pcr_pid; + guint pid; + guint stream_type; + GstStructure *stream; + gint i; + const GValue *new_streams; + const GValue *value; + MpegTSBaseClass *klass = GST_MPEGTS_BASE_GET_CLASS (base); + + if (G_UNLIKELY (base->first_pat_offset == -1)) { + GST_WARNING ("Got pmt without pat first. Returning"); + return; + } + + gst_structure_id_get (pmt_info, + QUARK_PROGRAM_NUMBER, G_TYPE_UINT, &program_number, + QUARK_PCR_PID, G_TYPE_UINT, &pcr_pid, NULL); + new_streams = gst_structure_id_get_value (pmt_info, QUARK_STREAMS); + + program = mpegts_base_get_program (base, program_number); + if (program) { + /* deactivate old pmt */ ; + mpegts_base_deactivate_pmt (base, program); + if (program->pmt_info) + gst_structure_free (program->pmt_info); + program->pmt_info = NULL; + } else { + /* no PAT?? */ + base->known_psi[pmt_pid] = TRUE; + program = mpegts_base_add_program (base, program_number, pid); + } + + /* activate new pmt */ + program->pmt_info = gst_structure_copy (pmt_info); + program->pmt_pid = pmt_pid; + program->pcr_pid = pcr_pid; + mpegts_base_program_add_stream (base, program, (guint16) pcr_pid, -1, NULL); + base->is_pes[pcr_pid] = TRUE; + + for (i = 0; i < gst_value_list_get_size (new_streams); ++i) { + value = gst_value_list_get_value (new_streams, i); + stream = g_value_get_boxed (value); + + gst_structure_id_get (stream, QUARK_PID, G_TYPE_UINT, &pid, + QUARK_STREAM_TYPE, G_TYPE_UINT, &stream_type, NULL); + mpegts_base_program_add_stream (base, program, + (guint16) pid, (guint8) stream_type, stream); + base->is_pes[pid] = TRUE; + + } + + if (klass->program_started != NULL) { + klass->program_started (base, program); + } + + GST_DEBUG_OBJECT (base, "new pmt %" GST_PTR_FORMAT, pmt_info); + + gst_element_post_message (GST_ELEMENT_CAST (base), + gst_message_new_element (GST_OBJECT (base), + gst_structure_copy (pmt_info))); +} + +static void +mpegts_base_apply_nit (MpegTSBase * base, + guint16 pmt_pid, GstStructure * nit_info) +{ + GST_DEBUG_OBJECT (base, "NIT %" GST_PTR_FORMAT, nit_info); + + gst_element_post_message (GST_ELEMENT_CAST (base), + gst_message_new_element (GST_OBJECT (base), + gst_structure_copy (nit_info))); +} + +static void +mpegts_base_apply_sdt (MpegTSBase * base, + guint16 pmt_pid, GstStructure * sdt_info) +{ + GST_DEBUG_OBJECT (base, "SDT %" GST_PTR_FORMAT, sdt_info); + + mpegts_base_get_tags_from_sdt (base, sdt_info); + + gst_element_post_message (GST_ELEMENT_CAST (base), + gst_message_new_element (GST_OBJECT (base), + gst_structure_copy (sdt_info))); +} + +static void +mpegts_base_apply_eit (MpegTSBase * base, + guint16 pmt_pid, GstStructure * eit_info) +{ + GST_DEBUG_OBJECT (base, "EIT %" GST_PTR_FORMAT, eit_info); + + mpegts_base_get_tags_from_eit (base, eit_info); + + gst_element_post_message (GST_ELEMENT_CAST (base), + gst_message_new_element (GST_OBJECT (base), + gst_structure_copy (eit_info))); +} + +static void +mpegts_base_apply_tdt (MpegTSBase * base, + guint16 tdt_pid, GstStructure * tdt_info) +{ + gst_element_post_message (GST_ELEMENT_CAST (base), + gst_message_new_element (GST_OBJECT (base), + gst_structure_copy (tdt_info))); + + GST_MPEGTS_BASE_GET_CLASS (base)->push_event (base, + gst_event_new_custom (GST_EVENT_CUSTOM_DOWNSTREAM, + gst_structure_copy (tdt_info))); +} + + +gboolean +mpegts_base_handle_psi (MpegTSBase * base, MpegTSPacketizerSection * section) +{ + gboolean res = TRUE; + GstStructure *structure = NULL; + + /* table ids 0x70 - 0x73 do not have a crc */ + if (G_LIKELY (section->table_id < 0x70 || section->table_id > 0x73)) { + if (G_UNLIKELY (mpegts_base_calc_crc32 (GST_BUFFER_DATA (section->buffer), + GST_BUFFER_SIZE (section->buffer)) != 0)) { + GST_WARNING_OBJECT (base, "bad crc in psi pid 0x%x", section->pid); + return FALSE; + } + } + + switch (section->table_id) { + case 0x00: + /* PAT */ + structure = mpegts_packetizer_parse_pat (base->packetizer, section); + if (G_LIKELY (structure)) { + mpegts_base_apply_pat (base, structure); + if (base->first_pat_offset == -1) { + + base->first_pat_offset = GST_BUFFER_OFFSET (section->buffer); + GST_DEBUG ("First PAT offset: %d", base->first_pat_offset); + } + + } else + res = FALSE; + + break; + case 0x02: + structure = mpegts_packetizer_parse_pmt (base->packetizer, section); + if (G_LIKELY (structure)) + mpegts_base_apply_pmt (base, section->pid, structure); + else + res = FALSE; + + break; + case 0x40: + /* NIT, actual network */ + case 0x41: + /* NIT, other network */ + structure = mpegts_packetizer_parse_nit (base->packetizer, section); + if (G_LIKELY (structure)) + mpegts_base_apply_nit (base, section->pid, structure); + else + res = FALSE; + + break; + case 0x42: + case 0x46: + structure = mpegts_packetizer_parse_sdt (base->packetizer, section); + if (G_LIKELY (structure)) + mpegts_base_apply_sdt (base, section->pid, structure); + else + res = FALSE; + break; + case 0x4E: + case 0x4F: + /* EIT, present/following */ + case 0x50: + case 0x51: + case 0x52: + case 0x53: + case 0x54: + case 0x55: + case 0x56: + case 0x57: + case 0x58: + case 0x59: + case 0x5A: + case 0x5B: + case 0x5C: + case 0x5D: + case 0x5E: + case 0x5F: + case 0x60: + case 0x61: + case 0x62: + case 0x63: + case 0x64: + case 0x65: + case 0x66: + case 0x67: + case 0x68: + case 0x69: + case 0x6A: + case 0x6B: + case 0x6C: + case 0x6D: + case 0x6E: + case 0x6F: + /* EIT, schedule */ + structure = mpegts_packetizer_parse_eit (base->packetizer, section); + if (G_LIKELY (structure)) + mpegts_base_apply_eit (base, section->pid, structure); + else + res = FALSE; + break; + case 0x70: + /* TDT (Time and Date table) */ + structure = mpegts_packetizer_parse_tdt (base->packetizer, section); + if (G_LIKELY (structure)) + mpegts_base_apply_tdt (base, section->pid, structure); + else + res = FALSE; + break; + default: + break; + } + + if (structure) + gst_structure_free (structure); + + return res; +} + +static void +mpegts_base_get_tags_from_sdt (MpegTSBase * base, GstStructure * sdt_info) +{ + const GValue *services; + guint i; + + services = gst_structure_get_value (sdt_info, "services"); + + for (i = 0; i < gst_value_list_get_size (services); i++) { + const GstStructure *service; + const gchar *sid_str; + gchar *tmp; + gint program_number; + MpegTSBaseProgram *program; + + service = gst_value_get_structure (gst_value_list_get_value (services, i)); + + /* get program_number from structure name + * which looks like service-%d */ + sid_str = gst_structure_get_name (service); + tmp = g_strstr_len (sid_str, -1, "-"); + program_number = atoi (++tmp); + + program = mpegts_base_get_program (base, program_number); + if (program && !program->tags) { + program->tags = gst_tag_list_new_full (GST_TAG_ARTIST, + gst_structure_get_string (service, "name"), NULL); + } + } +} + +static void +mpegts_base_get_tags_from_eit (MpegTSBase * base, GstStructure * eit_info) +{ + const GValue *events; + guint i; + guint program_number; + MpegTSBaseProgram *program; + gboolean present_following; + + gst_structure_get_uint (eit_info, "service-id", &program_number); + program = mpegts_base_get_program (base, program_number); + + gst_structure_get_boolean (eit_info, "present-following", &present_following); + + if (program && present_following) { + events = gst_structure_get_value (eit_info, "events"); + + for (i = 0; i < gst_value_list_get_size (events); i++) { + const GstStructure *event; + const gchar *title; + guint status; + guint event_id; + guint duration; + + event = gst_value_get_structure (gst_value_list_get_value (events, i)); + + title = gst_structure_get_string (event, "name"); + gst_structure_get_uint (event, "event-id", &event_id); + gst_structure_get_uint (event, "running-status", &status); + + if (title && event_id != program->event_id + && status == RUNNING_STATUS_RUNNING) { + gst_structure_get_uint (event, "duration", &duration); + + program->event_id = event_id; + program->tags = gst_tag_list_new_full (GST_TAG_TITLE, + title, GST_TAG_DURATION, duration * GST_SECOND, NULL); + } + } + } +} + + +static gboolean +mpegts_base_sink_event (GstPad * pad, GstEvent * event) +{ + gboolean res; + MpegTSBase *base = GST_MPEGTS_BASE (gst_object_get_parent (GST_OBJECT (pad))); + + GST_WARNING_OBJECT (base, "Got event %s", + gst_event_type_get_name (GST_EVENT_TYPE (event))); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_NEWSEGMENT: + /* FIXME : STORE NEW SEGMENT ! */ + gst_event_unref (event); + res = FALSE; + break; + case GST_EVENT_FLUSH_STOP: + mpegts_packetizer_clear (base->packetizer); + /* Passthrough */ + default: + res = GST_MPEGTS_BASE_GET_CLASS (base)->push_event (base, event); + gst_event_unref (event); + } + + gst_object_unref (base); + return res; +} + +static inline GstFlowReturn +mpegts_base_push (MpegTSBase * base, MpegTSPacketizerPacket * packet, + MpegTSPacketizerSection * section) +{ + MpegTSBaseClass *klass = GST_MPEGTS_BASE_GET_CLASS (base); + + /* Call implementation */ + if (G_UNLIKELY (klass->push == NULL)) { + GST_ERROR_OBJECT (base, "Class doesn't have a 'push' implementation !"); + return GST_FLOW_ERROR; + } + + return klass->push (base, packet, section); +} + +static GstFlowReturn +mpegts_base_chain (GstPad * pad, GstBuffer * buf) +{ + GstFlowReturn res = GST_FLOW_OK; + MpegTSBase *base; + gboolean based; + MpegTSPacketizerPacketReturn pret; + MpegTSPacketizer2 *packetizer; + MpegTSPacketizerPacket packet; + MpegTSBaseClass *klass; + + base = GST_MPEGTS_BASE (gst_object_get_parent (GST_OBJECT (pad))); + klass = GST_MPEGTS_BASE_GET_CLASS (base); + packetizer = base->packetizer; + + mpegts_packetizer_push (base->packetizer, buf); + while (((pret = + mpegts_packetizer_next_packet (base->packetizer, + &packet)) != PACKET_NEED_MORE) && res == GST_FLOW_OK) { + if (G_UNLIKELY (pret == PACKET_BAD)) + /* bad header, skip the packet */ + goto next; + + /* base PSI data */ + if (packet.payload != NULL && mpegts_base_is_psi (base, &packet)) { + MpegTSPacketizerSection section; + based = mpegts_packetizer_push_section (packetizer, &packet, §ion); + if (G_UNLIKELY (!based)) + /* bad section data */ + goto next; + + if (G_LIKELY (section.complete)) { + /* section complete */ + based = mpegts_base_handle_psi (base, §ion); + gst_buffer_unref (section.buffer); + + if (G_UNLIKELY (!based)) + /* bad PSI table */ + goto next; + } + /* we need to push section packet downstream */ + res = mpegts_base_push (base, &packet, §ion); + + } else { + /* push the packet downstream */ + res = mpegts_base_push (base, &packet, NULL); + } + + next: + mpegts_packetizer_clear_packet (base->packetizer, &packet); + } + + gst_object_unref (base); + return res; +} + +static GstFlowReturn +mpegts_base_scan (MpegTSBase * base) +{ + GstFlowReturn ret; + GstBuffer *buf; + guint i; + MpegTSBaseClass *klass = GST_MPEGTS_BASE_GET_CLASS (base); + + GST_DEBUG ("Scanning for initial sync point"); + + /* Find initial sync point */ + for (i = 0; i < 10; i++) { + GST_DEBUG ("Grabbing %d => %d", + i * 50 * MPEGTS_MAX_PACKETSIZE, 50 * MPEGTS_MAX_PACKETSIZE); + ret = gst_pad_pull_range (base->sinkpad, i * 50 * MPEGTS_MAX_PACKETSIZE, + 50 * MPEGTS_MAX_PACKETSIZE, &buf); + if (G_UNLIKELY (ret != GST_FLOW_OK)) + goto beach; + + /* Push to packetizer */ + mpegts_packetizer_push (base->packetizer, buf); + + if (mpegts_packetizer_has_packets (base->packetizer)) { + /* Mark the initial sync point and remember the packetsize */ + base->initial_sync_point = base->seek_offset = base->packetizer->offset; + GST_DEBUG ("Sync point is now %" G_GUINT64_FORMAT, base->seek_offset); + base->packetsize = base->packetizer->packet_size; + + /* If the subclass can seek for timestamps, do that */ + if (klass->find_timestamps) { + guint64 offset; + mpegts_packetizer_clear (base->packetizer); + + ret = klass->find_timestamps (base, 0, &offset); + + base->initial_sync_point = base->seek_offset = + base->packetizer->offset = base->first_pat_offset; + GST_DEBUG ("Sync point is now %" G_GUINT64_FORMAT, base->seek_offset); + } + goto beach; + } + } + + GST_WARNING ("Didn't find initial sync point"); + ret = GST_FLOW_ERROR; + +beach: + mpegts_packetizer_clear (base->packetizer); + return ret; + +} + + +static void +mpegts_base_loop (MpegTSBase * base) +{ + GstFlowReturn ret = GST_FLOW_ERROR; + switch (base->mode) { + case BASE_MODE_SCANNING: + /* Find first sync point */ + ret = mpegts_base_scan (base); + if (G_UNLIKELY (ret != GST_FLOW_OK)) + goto error; + base->mode = BASE_MODE_STREAMING; + GST_DEBUG ("Changing to Streaming"); + break; + case BASE_MODE_SEEKING: + /* FIXME : yes, we should do something here */ + base->mode = BASE_MODE_STREAMING; + break; + case BASE_MODE_STREAMING: + { + GstBuffer *buf; + + GST_DEBUG ("Pulling data from %" G_GUINT64_FORMAT, base->seek_offset); + + ret = gst_pad_pull_range (base->sinkpad, base->seek_offset, + 100 * base->packetsize, &buf); + if (G_UNLIKELY (ret != GST_FLOW_OK)) + goto error; + base->seek_offset += GST_BUFFER_SIZE (buf); + ret = mpegts_base_chain (base->sinkpad, buf); + if (G_UNLIKELY (ret != GST_FLOW_OK)) + goto error; + } + break; + } + + return; + +error: + { + const gchar *reason = gst_flow_get_name (ret); + GST_DEBUG_OBJECT (base, "Pausing task, reason %s", reason); + if (ret == GST_FLOW_UNEXPECTED) + GST_MPEGTS_BASE_GET_CLASS (base)->push_event (base, gst_event_new_eos ()); + else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_UNEXPECTED) { + GST_ELEMENT_ERROR (base, STREAM, FAILED, + (_("Internal data stream error.")), + ("stream stopped, reason %s", reason)); + GST_MPEGTS_BASE_GET_CLASS (base)->push_event (base, gst_event_new_eos ()); + } + gst_pad_pause_task (base->sinkpad); + } +} + +static gboolean +mpegts_base_sink_activate (GstPad * pad) +{ + if (gst_pad_check_pull_range (pad)) { + GST_DEBUG_OBJECT (pad, "activating pull"); + return gst_pad_activate_pull (pad, TRUE); + } else { + GST_DEBUG_OBJECT (pad, "activating push"); + return gst_pad_activate_push (pad, TRUE); + } +} + +static gboolean +mpegts_base_sink_activate_pull (GstPad * pad, gboolean active) +{ + MpegTSBase *base = GST_MPEGTS_BASE (GST_OBJECT_PARENT (pad)); + if (active) { + base->mode = BASE_MODE_SCANNING; + return gst_pad_start_task (pad, (GstTaskFunction) mpegts_base_loop, base); + } else + return gst_pad_stop_task (pad); +} + +static gboolean +mpegts_base_sink_activate_push (GstPad * pad, gboolean active) +{ + return TRUE; +} + + +static GstStateChangeReturn +mpegts_base_change_state (GstElement * element, GstStateChange transition) +{ + MpegTSBase *base; + GstStateChangeReturn ret; + + base = GST_MPEGTS_BASE (element); + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + + switch (transition) { + case GST_STATE_CHANGE_PAUSED_TO_READY: + mpegts_base_reset (base); + break; + default: + break; + } + + return ret; +} + +gboolean +gst_mpegtsbase_plugin_init (GstPlugin * plugin) +{ + GST_DEBUG_CATEGORY_INIT (mpegts_base_debug, "mpegtsbase", 0, + "MPEG transport stream base class"); + + gst_mpegtsdesc_init_debug (); + + return TRUE; +} diff --git a/gst/mpegtsdemux/mpegtsbase.h b/gst/mpegtsdemux/mpegtsbase.h new file mode 100644 index 0000000000..168f2ff1c4 --- /dev/null +++ b/gst/mpegtsdemux/mpegtsbase.h @@ -0,0 +1,169 @@ +/* + * mpegtsbase.h - GStreamer MPEG transport stream base class + * Copyright (C) 2009 Edward Hervey + * 2007 Alessandro Decina + * + * Authors: + * Alessandro Decina + * Edward Hervey + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef GST_MPEG_TS_BASE_H +#define GST_MPEG_TS_BASE_H + +#include +#include "mpegtspacketizer.h" + +G_BEGIN_DECLS + +#define GST_TYPE_MPEGTS_BASE \ + (mpegts_base_get_type()) +#define GST_MPEGTS_BASE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_MPEGTS_BASE,MpegTSBase)) +#define GST_MPEGTS_BASE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_MPEGTS_BASE,MpegTSBaseClass)) +#define GST_IS_MPEGTS_BASE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_MPEGTS_BASE)) +#define GST_IS_MPEGTS_BASE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_MPEGTS_BASE)) +#define GST_MPEGTS_BASE_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_MPEGTS_BASE, MpegTSBaseClass)) + +typedef struct _MpegTSBase MpegTSBase; +typedef struct _MpegTSBaseClass MpegTSBaseClass; +typedef struct _MpegTSBaseStream MpegTSBaseStream; +typedef struct _MpegTSBaseProgram MpegTSBaseProgram; + +struct _MpegTSBaseStream +{ + guint16 pid; + guint8 stream_type; + GstStructure* stream_info; +}; + +struct _MpegTSBaseProgram +{ + gint program_number; + guint16 pmt_pid; + guint16 pcr_pid; + GstStructure *pmt_info; + MpegTSBaseStream **streams; + gint patcount; + + /* Pending Tags for the program */ + GstTagList *tags; + guint event_id; +}; + +typedef enum { + BASE_MODE_SCANNING, + BASE_MODE_SEEKING, + BASE_MODE_STREAMING +} MpegTSBaseMode; + +struct _MpegTSBase { + GstElement element; + + GstPad *sinkpad; + + /* pull-based behaviour */ + MpegTSBaseMode mode; + + /* location of first sync point */ + guint64 initial_sync_point; + + /* Current pull offset (also set by seek handler) */ + guint64 seek_offset; + + /* Cached packetsize */ + guint16 packetsize; + + /* the following vars must be protected with the OBJECT_LOCK as they can be + * accessed from the application thread and the streaming thread */ + GHashTable *programs; + + GstStructure *pat; + MpegTSPacketizer2 *packetizer; + + /* arrays that say whether a pid is a known psi pid or a pes pid + * FIXME: Make these bit arrays so we can make them 8 times smaller */ + gboolean *known_psi; + gboolean *is_pes; + + gboolean disposed; + + /* size of the MpegTSBaseProgram structure, can be overridden + * by subclasses if they have their own MpegTSBaseProgram subclasses. */ + gsize program_size; + + /* size of the MpegTSBaseStream structure, can be overridden + * by subclasses if they have their own MpegTSBaseStream subclasses */ + gsize stream_size; + + /*Offset from the origin to the first PAT (pullmode) */ + guint64 first_pat_offset; +}; + +struct _MpegTSBaseClass { + GstElementClass parent_class; + + /* Virtual methods */ + GstFlowReturn (*push) (MpegTSBase *base, MpegTSPacketizerPacket *packet, MpegTSPacketizerSection * section); + gboolean (*push_event) (MpegTSBase *base, GstEvent * event); + /* program_started gets called when program's pmt arrives for first time */ + void (*program_started) (MpegTSBase *base, MpegTSBaseProgram *program); + /* program_stopped gets called when pat no longer has program's pmt */ + void (*program_stopped) (MpegTSBase *base, MpegTSBaseProgram *program); + + /* stream_added is called whenever a new stream has been identified */ + void (*stream_added) (MpegTSBase *base, MpegTSBaseStream *stream, MpegTSBaseProgram *program); + /* stream_removed is called whenever a stream is no longer referenced */ + void (*stream_removed) (MpegTSBase *base, MpegTSBaseStream *stream); + + /* find_timestamps is called to find PCR */ + GstFlowReturn (*find_timestamps) (MpegTSBase * base, guint64 initoff, guint64 *offset); + + /* signals */ + void (*pat_info) (GstStructure *pat); + void (*pmt_info) (GstStructure *pmt); + void (*nit_info) (GstStructure *nit); + void (*sdt_info) (GstStructure *sdt); + void (*eit_info) (GstStructure *eit); +}; + +GType mpegts_base_get_type(void); + +MpegTSBaseProgram *mpegts_base_get_program (MpegTSBase * base, gint program_number); +MpegTSBaseProgram *mpegts_base_add_program (MpegTSBase * base, gint program_number, guint16 pmt_pid); + +guint8 *mpegts_get_descriptor_from_stream (MpegTSBaseStream * stream, guint8 tag); +guint8 *mpegts_get_descriptor_from_program (MpegTSBaseProgram * program, guint8 tag); + + +gboolean gst_mpegtsbase_plugin_init (GstPlugin * plugin); + +gboolean mpegts_base_is_psi (MpegTSBase * base, MpegTSPacketizerPacket * packet); +gboolean mpegts_base_handle_psi (MpegTSBase * base, MpegTSPacketizerSection * section); + +void mpegts_base_program_remove_stream (MpegTSBase * base, MpegTSBaseProgram * program, guint16 pid); + +void mpegts_base_remove_program(MpegTSBase *base, gint program_number); +G_END_DECLS + +#endif /* GST_MPEG_TS_BASE_H */ diff --git a/gst/mpegtsdemux/mpegtspacketizer.c b/gst/mpegtsdemux/mpegtspacketizer.c new file mode 100644 index 0000000000..34ecc2ac14 --- /dev/null +++ b/gst/mpegtsdemux/mpegtspacketizer.c @@ -0,0 +1,2714 @@ +/* + * mpegtspacketizer.c - + * Copyright (C) 2007, 2008 Alessandro Decina, Zaheer Merali + * + * Authors: + * Zaheer Merali + * Alessandro Decina + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#include + +#include "mpegtspacketizer.h" +#include "gstmpegdesc.h" + +GST_DEBUG_CATEGORY_STATIC (mpegts_packetizer_debug); +#define GST_CAT_DEFAULT mpegts_packetizer_debug + +static GQuark QUARK_PAT; +static GQuark QUARK_TRANSPORT_STREAM_ID; +static GQuark QUARK_PROGRAM_NUMBER; +static GQuark QUARK_PID; +static GQuark QUARK_PROGRAMS; + +static GQuark QUARK_PMT; +static GQuark QUARK_PCR_PID; +static GQuark QUARK_VERSION_NUMBER; +static GQuark QUARK_DESCRIPTORS; +static GQuark QUARK_STREAM_TYPE; +static GQuark QUARK_STREAMS; + +static GQuark QUARK_NIT; +static GQuark QUARK_NETWORK_ID; +static GQuark QUARK_CURRENT_NEXT_INDICATOR; +static GQuark QUARK_ACTUAL_NETWORK; +static GQuark QUARK_NETWORK_NAME; +static GQuark QUARK_ORIGINAL_NETWORK_ID; +static GQuark QUARK_TRANSPORTS; + +static GQuark QUARK_SDT; +static GQuark QUARK_ACTUAL_TRANSPORT_STREAM; +static GQuark QUARK_SERVICES; + +static GQuark QUARK_EIT; +static GQuark QUARK_SERVICE_ID; +static GQuark QUARK_PRESENT_FOLLOWING; +static GQuark QUARK_SEGMENT_LAST_SECTION_NUMBER; +static GQuark QUARK_LAST_TABLE_ID; +static GQuark QUARK_EVENTS; + +static void _init_local (void); +G_DEFINE_TYPE_EXTENDED (MpegTSPacketizer2, mpegts_packetizer, G_TYPE_OBJECT, 0, + _init_local ()); + +static void mpegts_packetizer_dispose (GObject * object); +static void mpegts_packetizer_finalize (GObject * object); +static gchar *convert_to_utf8 (const gchar * text, gint length, guint start, + const gchar * encoding, gboolean is_multibyte, GError ** error); +static gchar *get_encoding (const gchar * text, guint * start_text, + gboolean * is_multibyte); +static gchar *get_encoding_and_convert (const gchar * text, guint length); + +#define CONTINUITY_UNSET 255 +#define MAX_CONTINUITY 15 +#define VERSION_NUMBER_UNSET 255 +#define TABLE_ID_UNSET 0xFF + +static gint +mpegts_packetizer_stream_subtable_compare (gconstpointer a, gconstpointer b) +{ + MpegTSPacketizerStreamSubtable *asub, *bsub; + + asub = (MpegTSPacketizerStreamSubtable *) a; + bsub = (MpegTSPacketizerStreamSubtable *) b; + + if (asub->table_id == bsub->table_id && + asub->subtable_extension == bsub->subtable_extension) + return 0; + return -1; +} + +static MpegTSPacketizerStreamSubtable * +mpegts_packetizer_stream_subtable_new (guint8 table_id, + guint16 subtable_extension) +{ + MpegTSPacketizerStreamSubtable *subtable; + + subtable = g_new0 (MpegTSPacketizerStreamSubtable, 1); + subtable->version_number = VERSION_NUMBER_UNSET; + subtable->table_id = table_id; + subtable->subtable_extension = subtable_extension; + subtable->crc = 0; + return subtable; +} + +static MpegTSPacketizerStream * +mpegts_packetizer_stream_new (void) +{ + MpegTSPacketizerStream *stream; + + stream = (MpegTSPacketizerStream *) g_new0 (MpegTSPacketizerStream, 1); + stream->section_adapter = gst_adapter_new (); + stream->continuity_counter = CONTINUITY_UNSET; + stream->subtables = NULL; + stream->section_table_id = TABLE_ID_UNSET; + return stream; +} + +static void +mpegts_packetizer_stream_free (MpegTSPacketizerStream * stream) +{ + gst_adapter_clear (stream->section_adapter); + g_object_unref (stream->section_adapter); + g_slist_foreach (stream->subtables, (GFunc) g_free, NULL); + g_slist_free (stream->subtables); + g_free (stream); +} + +static void +mpegts_packetizer_clear_section (MpegTSPacketizer2 * packetizer, + MpegTSPacketizerStream * stream) +{ + gst_adapter_clear (stream->section_adapter); + stream->continuity_counter = CONTINUITY_UNSET; + stream->section_length = 0; + stream->section_table_id = TABLE_ID_UNSET; +} + +static void +mpegts_packetizer_class_init (MpegTSPacketizer2Class * klass) +{ + GObjectClass *gobject_class; + + gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->dispose = mpegts_packetizer_dispose; + gobject_class->finalize = mpegts_packetizer_finalize; +} + +static void +mpegts_packetizer_init (MpegTSPacketizer2 * packetizer) +{ + packetizer->adapter = gst_adapter_new (); + packetizer->offset = 0; + packetizer->empty = TRUE; + packetizer->streams = g_new0 (MpegTSPacketizerStream *, 8192); + packetizer->know_packet_size = FALSE; +} + +static void +mpegts_packetizer_dispose (GObject * object) +{ + MpegTSPacketizer2 *packetizer = GST_MPEGTS_PACKETIZER (object); + + if (!packetizer->disposed) { + if (packetizer->know_packet_size && packetizer->caps != NULL) { + gst_caps_unref (packetizer->caps); + packetizer->caps = NULL; + packetizer->know_packet_size = FALSE; + } + if (packetizer->streams) { + int i; + for (i = 0; i < 8192; i++) { + if (packetizer->streams[i]) + mpegts_packetizer_stream_free (packetizer->streams[i]); + } + g_free (packetizer->streams); + } + + gst_adapter_clear (packetizer->adapter); + g_object_unref (packetizer->adapter); + packetizer->disposed = TRUE; + packetizer->offset = 0; + packetizer->empty = TRUE; + } + + if (G_OBJECT_CLASS (mpegts_packetizer_parent_class)->dispose) + G_OBJECT_CLASS (mpegts_packetizer_parent_class)->dispose (object); +} + +static void +mpegts_packetizer_finalize (GObject * object) +{ + if (G_OBJECT_CLASS (mpegts_packetizer_parent_class)->finalize) + G_OBJECT_CLASS (mpegts_packetizer_parent_class)->finalize (object); +} + +static gboolean +mpegts_packetizer_parse_adaptation_field_control (MpegTSPacketizer2 * + packetizer, MpegTSPacketizerPacket * packet) +{ + guint8 length, afcflags; + guint8 *data; + + length = *packet->data++; + + if (packet->adaptation_field_control == 0x02) { + /* no payload, adaptation field of 183 bytes */ + if (length != 183) { + GST_DEBUG ("PID %d afc == 0x%x and length %d != 183", + packet->pid, packet->adaptation_field_control, length); + } + } else if (length > 182) { + GST_DEBUG ("PID %d afc == 0x%01x and length %d > 182", + packet->pid, packet->adaptation_field_control, length); + } + + if (packet->data + length > packet->data_end) { + GST_DEBUG ("PID %d afc length %d overflows the buffer current %d max %d", + packet->pid, length, (gint) (packet->data - packet->data_start), + (gint) (packet->data_end - packet->data_start)); + return FALSE; + } + + data = packet->data; + packet->data += length; + + afcflags = packet->afc_flags = *data++; + + /* PCR */ + if (afcflags & MPEGTS_AFC_PCR_FLAG) { + guint32 pcr1; + guint16 pcr2; + guint64 pcr, pcr_ext; + + pcr1 = GST_READ_UINT32_BE (data); + pcr2 = GST_READ_UINT16_BE (data + 4); + pcr = ((guint64) pcr1) << 1; + pcr |= (pcr2 & 0x8000) >> 15; + pcr_ext = (pcr2 & 0x01ff); + packet->pcr = pcr * 300 + pcr_ext % 300;; + *data += 6; + } + + /* OPCR */ + if (afcflags & MPEGTS_AFC_OPCR_FLAG) { + guint32 pcr1; + guint16 pcr2; + guint64 pcr, pcr_ext; + + pcr1 = GST_READ_UINT32_BE (data); + pcr2 = GST_READ_UINT16_BE (data + 4); + pcr = ((guint64) pcr1) << 1; + pcr |= (pcr2 & 0x8000) >> 15; + pcr_ext = (pcr2 & 0x01ff); + packet->opcr = pcr * 300 + pcr_ext % 300;; + *data += 6; + } + + return TRUE; +} + +static gboolean +mpegts_packetizer_parse_packet (MpegTSPacketizer2 * packetizer, + MpegTSPacketizerPacket * packet) +{ + guint8 *data; + + data = packet->data_start; + data++; + + packet->payload_unit_start_indicator = (*data >> 6) & 0x01; + packet->pid = GST_READ_UINT16_BE (data) & 0x1FFF; + data += 2; + + packet->adaptation_field_control = (*data >> 4) & 0x03; + packet->continuity_counter = *data & 0x0F; + data += 1; + + packet->data = data; + + if (packet->adaptation_field_control & 0x02) + if (!mpegts_packetizer_parse_adaptation_field_control (packetizer, packet)) + return FALSE; + + if (packet->adaptation_field_control & 0x01) + packet->payload = packet->data; + else + packet->payload = NULL; + + return TRUE; +} + +static gboolean +mpegts_packetizer_parse_section_header (MpegTSPacketizer2 * packetizer, + MpegTSPacketizerStream * stream, MpegTSPacketizerSection * section) +{ + guint8 tmp; + guint8 *data, *crc_data; + MpegTSPacketizerStreamSubtable *subtable; + GSList *subtable_list = NULL; + + section->complete = TRUE; + /* get the section buffer, pass the ownership to the caller */ + section->buffer = gst_adapter_take_buffer (stream->section_adapter, + 3 + stream->section_length); + data = GST_BUFFER_DATA (section->buffer); + GST_BUFFER_OFFSET (section->buffer) = stream->offset; + + section->table_id = *data++; + /* if table_id is 0 (pat) then ignore the subtable extension */ + if ((data[0] & 0x80) == 0 || section->table_id == 0) + section->subtable_extension = 0; + else + section->subtable_extension = GST_READ_UINT16_BE (data + 2); + + subtable = mpegts_packetizer_stream_subtable_new (section->table_id, + section->subtable_extension); + + subtable_list = g_slist_find_custom (stream->subtables, subtable, + mpegts_packetizer_stream_subtable_compare); + if (subtable_list) { + g_free (subtable); + subtable = (MpegTSPacketizerStreamSubtable *) (subtable_list->data); + } else { + stream->subtables = g_slist_prepend (stream->subtables, subtable); + } + + section->section_length = GST_READ_UINT16_BE (data) & 0x0FFF; + data += 2; + + /* skip to the version byte */ + data += 2; + + tmp = *data++; + section->version_number = (tmp >> 1) & 0x1F; + section->current_next_indicator = tmp & 0x01; + + if (!section->current_next_indicator) + goto not_applicable; + + /* CRC is at the end of the section */ + crc_data = + GST_BUFFER_DATA (section->buffer) + GST_BUFFER_SIZE (section->buffer) - 4; + section->crc = GST_READ_UINT32_BE (crc_data); + + if (section->version_number == subtable->version_number && + section->crc == subtable->crc) + goto not_applicable; + + subtable->version_number = section->version_number; + subtable->crc = section->crc; + stream->section_table_id = section->table_id; + + return TRUE; + +not_applicable: + GST_LOG + ("not applicable pid %d table_id %d subtable_extension %d, current_next %d version %d, crc 0x%x", + section->pid, section->table_id, section->subtable_extension, + section->current_next_indicator, section->version_number, section->crc); + section->complete = FALSE; + gst_buffer_unref (section->buffer); + return TRUE; +} + +static gboolean +mpegts_packetizer_parse_descriptors (MpegTSPacketizer2 * packetizer, + guint8 ** buffer, guint8 * buffer_end, GValueArray * descriptors) +{ + guint8 tag, length; + guint8 *data; + GValue value = { 0 }; + GString *desc; + + data = *buffer; + + while (data < buffer_end) { + tag = *data++; + length = *data++; + + if (data + length > buffer_end) { + GST_WARNING ("invalid descriptor length %d now at %d max %d", length, + (gint) (data - *buffer), (gint) (buffer_end - *buffer)); + goto error; + } + + /* include tag and length */ + desc = g_string_new_len ((gchar *) data - 2, length + 2); + data += length; + /* G_TYPE_GSTING is a GBoxed type and is used so properly marshalled from python */ + g_value_init (&value, G_TYPE_GSTRING); + g_value_take_boxed (&value, desc); + g_value_array_append (descriptors, &value); + g_value_unset (&value); + } + + if (data != buffer_end) { + GST_WARNING ("descriptors size %d expected %d", (gint) (data - *buffer), + (gint) (buffer_end - *buffer)); + goto error; + } + + *buffer = data; + + return TRUE; +error: + return FALSE; +} + +GstStructure * +mpegts_packetizer_parse_pat (MpegTSPacketizer2 * packetizer, + MpegTSPacketizerSection * section) +{ + GstStructure *pat_info = NULL; + guint8 *data, *end; + guint transport_stream_id; + guint8 tmp; + guint program_number; + guint pmt_pid; + GValue entries = { 0 }; + GValue value = { 0 }; + GstStructure *entry = NULL; + gchar *struct_name; + + data = GST_BUFFER_DATA (section->buffer); + + section->table_id = *data++; + section->section_length = GST_READ_UINT16_BE (data) & 0x0FFF; + data += 2; + + transport_stream_id = GST_READ_UINT16_BE (data); + data += 2; + + tmp = *data++; + section->version_number = (tmp >> 1) & 0x1F; + section->current_next_indicator = tmp & 0x01; + + /* skip section_number and last_section_number */ + data += 2; + + pat_info = gst_structure_id_new (QUARK_PAT, + QUARK_TRANSPORT_STREAM_ID, G_TYPE_UINT, transport_stream_id, NULL); + g_value_init (&entries, GST_TYPE_LIST); + /* stop at the CRC */ + end = GST_BUFFER_DATA (section->buffer) + GST_BUFFER_SIZE (section->buffer); + while (data < end - 4) { + program_number = GST_READ_UINT16_BE (data); + data += 2; + + pmt_pid = GST_READ_UINT16_BE (data) & 0x1FFF; + data += 2; + + struct_name = g_strdup_printf ("program-%d", program_number); + entry = gst_structure_new (struct_name, NULL); + g_free (struct_name); + gst_structure_id_set (entry, QUARK_PROGRAM_NUMBER, G_TYPE_UINT, + program_number, QUARK_PID, G_TYPE_UINT, pmt_pid, NULL); + + g_value_init (&value, GST_TYPE_STRUCTURE); + g_value_take_boxed (&value, entry); + gst_value_list_append_value (&entries, &value); + g_value_unset (&value); + } + + gst_structure_id_set_value (pat_info, QUARK_PROGRAMS, &entries); + g_value_unset (&entries); + + if (data != end - 4) { + /* FIXME: check the CRC before parsing the packet */ + GST_ERROR ("at the end of PAT data != end - 4"); + gst_structure_free (pat_info); + + return NULL; + } + + return pat_info; +} + +GstStructure * +mpegts_packetizer_parse_pmt (MpegTSPacketizer2 * packetizer, + MpegTSPacketizerSection * section) +{ + GstStructure *pmt = NULL; + guint8 *data, *end; + guint16 program_number; + guint8 tmp; + guint pcr_pid; + guint program_info_length; + guint8 stream_type; + guint16 pid; + guint stream_info_length; + GValueArray *descriptors; + GValue stream_value = { 0 }; + GValue programs = { 0 }; + GstStructure *stream_info = NULL; + gchar *struct_name; + + /* fixed header + CRC == 16 */ + if (GST_BUFFER_SIZE (section->buffer) < 16) { + GST_WARNING ("PID %d invalid PMT size %d", + section->pid, section->section_length); + goto error; + } + + data = GST_BUFFER_DATA (section->buffer); + end = data + GST_BUFFER_SIZE (section->buffer); + + section->table_id = *data++; + section->section_length = GST_READ_UINT16_BE (data) & 0x0FFF; + data += 2; + + program_number = GST_READ_UINT16_BE (data); + data += 2; + + tmp = *data++; + section->version_number = (tmp >> 1) & 0x1F; + section->current_next_indicator = tmp & 0x01; + + /* skip section_number and last_section_number */ + data += 2; + + pcr_pid = GST_READ_UINT16_BE (data) & 0x1FFF; + data += 2; + + program_info_length = GST_READ_UINT16_BE (data) & 0x0FFF; + data += 2; + + pmt = gst_structure_id_new (QUARK_PMT, + QUARK_PROGRAM_NUMBER, G_TYPE_UINT, program_number, + QUARK_PCR_PID, G_TYPE_UINT, pcr_pid, + QUARK_VERSION_NUMBER, G_TYPE_UINT, section->version_number, NULL); + + if (program_info_length) { + /* check that the buffer is large enough to contain at least + * program_info_length bytes + CRC */ + if (data + program_info_length + 4 > end) { + GST_WARNING ("PID %d invalid program info length %d left %d", + section->pid, program_info_length, (gint) (end - data)); + goto error; + } + + descriptors = g_value_array_new (0); + if (!mpegts_packetizer_parse_descriptors (packetizer, + &data, data + program_info_length, descriptors)) { + g_value_array_free (descriptors); + goto error; + } + + gst_structure_id_set (pmt, QUARK_DESCRIPTORS, G_TYPE_VALUE_ARRAY, + descriptors, NULL); + g_value_array_free (descriptors); + } + + g_value_init (&programs, GST_TYPE_LIST); + /* parse entries, cycle until there's space for another entry (at least 5 + * bytes) plus the CRC */ + while (data <= end - 4 - 5) { + stream_type = *data++; + + pid = GST_READ_UINT16_BE (data) & 0x1FFF; + data += 2; + + stream_info_length = GST_READ_UINT16_BE (data) & 0x0FFF; + data += 2; + + if (data + stream_info_length + 4 > end) { + GST_WARNING ("PID %d invalid stream info length %d left %d", section->pid, + stream_info_length, (gint) (end - data)); + g_value_unset (&programs); + goto error; + } + + struct_name = g_strdup_printf ("pid-%d", pid); + stream_info = gst_structure_new (struct_name, NULL); + g_free (struct_name); + gst_structure_id_set (stream_info, + QUARK_PID, G_TYPE_UINT, pid, QUARK_STREAM_TYPE, G_TYPE_UINT, + stream_type, NULL); + + if (stream_info_length) { + /* check for AC3 descriptor */ + GstMPEGDescriptor *desc = + gst_mpeg_descriptor_parse (data, stream_info_length); + if (desc != NULL) { + /* DVB AC3 */ + guint8 *desc_data; + if (gst_mpeg_descriptor_find (desc, DESC_DVB_AC3)) { + gst_structure_set (stream_info, "has-ac3", G_TYPE_BOOLEAN, TRUE, + NULL); + } + + /* DATA BROADCAST ID */ + desc_data = gst_mpeg_descriptor_find (desc, DESC_DVB_DATA_BROADCAST_ID); + if (desc_data) { + guint16 data_broadcast_id; + data_broadcast_id = + DESC_DVB_DATA_BROADCAST_ID_data_broadcast_id (desc_data); + gst_structure_set (stream_info, "data-broadcast-id", G_TYPE_UINT, + data_broadcast_id, NULL); + } + + /* DATA BROADCAST */ + desc_data = gst_mpeg_descriptor_find (desc, DESC_DVB_DATA_BROADCAST); + if (desc_data) { + GstStructure *databroadcast_info; + guint16 data_broadcast_id; + guint8 component_tag; + data_broadcast_id = + DESC_DVB_DATA_BROADCAST_data_broadcast_id (desc_data); + component_tag = DESC_DVB_DATA_BROADCAST_component_tag (desc_data); + databroadcast_info = gst_structure_new ("data-broadcast", "id", + G_TYPE_UINT, data_broadcast_id, "component-tag", component_tag, + NULL); + gst_structure_set (stream_info, "data-broadcast", GST_TYPE_STRUCTURE, + databroadcast_info, NULL); + } + + /* DVB CAROUSEL IDENTIFIER */ + desc_data = + gst_mpeg_descriptor_find (desc, DESC_DVB_CAROUSEL_IDENTIFIER); + if (desc_data) { + guint32 carousel_id; + carousel_id = DESC_DVB_CAROUSEL_IDENTIFIER_carousel_id (desc_data); + gst_structure_set (stream_info, "carousel-id", G_TYPE_UINT, + carousel_id, NULL); + } + + /* DVB STREAM IDENTIFIER */ + desc_data = gst_mpeg_descriptor_find (desc, DESC_DVB_STREAM_IDENTIFIER); + if (desc_data) { + guint8 component_tag; + component_tag = DESC_DVB_STREAM_IDENTIFIER_component_tag (desc_data); + gst_structure_set (stream_info, "component-tag", G_TYPE_UINT, + component_tag, NULL); + } + + /* ISO 639 LANGUAGE */ + desc_data = gst_mpeg_descriptor_find (desc, DESC_ISO_639_LANGUAGE); + if (desc_data && DESC_ISO_639_LANGUAGE_codes_n (desc_data)) { + gchar *lang_code; + gchar *language_n = (gchar *) + DESC_ISO_639_LANGUAGE_language_code_nth (desc_data, 0); + lang_code = g_strndup (language_n, 3); + gst_structure_set (stream_info, "lang-code", G_TYPE_STRING, + lang_code, NULL); + g_free (lang_code); + } + + gst_mpeg_descriptor_free (desc); + } + + descriptors = g_value_array_new (0); + if (!mpegts_packetizer_parse_descriptors (packetizer, + &data, data + stream_info_length, descriptors)) { + g_value_unset (&programs); + gst_structure_free (stream_info); + g_value_array_free (descriptors); + goto error; + } + + gst_structure_id_set (stream_info, + QUARK_DESCRIPTORS, G_TYPE_VALUE_ARRAY, descriptors, NULL); + g_value_array_free (descriptors); + + } + + g_value_init (&stream_value, GST_TYPE_STRUCTURE); + g_value_take_boxed (&stream_value, stream_info); + gst_value_list_append_value (&programs, &stream_value); + g_value_unset (&stream_value); + } + + gst_structure_id_set_value (pmt, QUARK_STREAMS, &programs); + g_value_unset (&programs); + + g_assert (data == end - 4); + + return pmt; + +error: + if (pmt) + gst_structure_free (pmt); + + return NULL; +} + +GstStructure * +mpegts_packetizer_parse_nit (MpegTSPacketizer2 * packetizer, + MpegTSPacketizerSection * section) +{ + GstStructure *nit = NULL, *transport = NULL, *delivery_structure = NULL; + guint8 *data, *end, *entry_begin; + guint16 network_id, transport_stream_id, original_network_id; + guint tmp; + guint16 descriptors_loop_length, transport_stream_loop_length; + GValue transports = { 0 }; + GValue transport_value = { 0 }; + GValueArray *descriptors = NULL; + + GST_DEBUG ("NIT"); + /* fixed header + CRC == 16 */ + if (GST_BUFFER_SIZE (section->buffer) < 23) { + GST_WARNING ("PID %d invalid NIT size %d", + section->pid, section->section_length); + goto error; + } + + data = GST_BUFFER_DATA (section->buffer); + end = data + GST_BUFFER_SIZE (section->buffer); + + section->table_id = *data++; + section->section_length = GST_READ_UINT16_BE (data) & 0x0FFF; + data += 2; + + if (data + section->section_length != end) { + GST_WARNING ("PID %d invalid NIT section length %d expected %d", + section->pid, section->section_length, (gint) (end - data)); + goto error; + } + + network_id = GST_READ_UINT16_BE (data); + data += 2; + + tmp = *data++; + section->version_number = (tmp >> 1) & 0x1F; + section->current_next_indicator = tmp & 0x01; + + /* skip section_number and last_section_number */ + data += 2; + + descriptors_loop_length = GST_READ_UINT16_BE (data) & 0x0FFF; + data += 2; + + nit = gst_structure_id_new (QUARK_NIT, + QUARK_NETWORK_ID, G_TYPE_UINT, network_id, + QUARK_VERSION_NUMBER, G_TYPE_UINT, section->version_number, + QUARK_CURRENT_NEXT_INDICATOR, G_TYPE_UINT, + section->current_next_indicator, QUARK_ACTUAL_NETWORK, G_TYPE_BOOLEAN, + section->table_id == 0x40, NULL); + + /* see if the buffer is large enough */ + if (descriptors_loop_length) { + guint8 *networkname_descriptor; + GstMPEGDescriptor *mpegdescriptor; + + if (data + descriptors_loop_length > end - 4) { + GST_WARNING ("PID %d invalid NIT descriptors loop length %d", + section->pid, descriptors_loop_length); + gst_structure_free (nit); + goto error; + } + mpegdescriptor = gst_mpeg_descriptor_parse (data, descriptors_loop_length); + networkname_descriptor = + gst_mpeg_descriptor_find (mpegdescriptor, DESC_DVB_NETWORK_NAME); + if (networkname_descriptor != NULL) { + gchar *networkname_tmp; + + /* No need to bounds check this value as it comes from the descriptor length itself */ + guint8 networkname_length = + DESC_DVB_NETWORK_NAME_length (networkname_descriptor); + gchar *networkname = + (gchar *) DESC_DVB_NETWORK_NAME_text (networkname_descriptor); + + networkname_tmp = + get_encoding_and_convert (networkname, networkname_length); + gst_structure_id_set (nit, QUARK_NETWORK_NAME, G_TYPE_STRING, + networkname_tmp, NULL); + g_free (networkname_tmp); + } + gst_mpeg_descriptor_free (mpegdescriptor); + + descriptors = g_value_array_new (0); + if (!mpegts_packetizer_parse_descriptors (packetizer, + &data, data + descriptors_loop_length, descriptors)) { + gst_structure_free (nit); + g_value_array_free (descriptors); + goto error; + } + + gst_structure_id_set (nit, QUARK_DESCRIPTORS, G_TYPE_VALUE_ARRAY, + descriptors, NULL); + g_value_array_free (descriptors); + } + + transport_stream_loop_length = GST_READ_UINT16_BE (data) & 0x0FFF; + data += 2; + + g_value_init (&transports, GST_TYPE_LIST); + /* read up to the CRC */ + while (transport_stream_loop_length - 4 > 0) { + gchar *transport_name; + + entry_begin = data; + + if (transport_stream_loop_length < 10) { + /* each entry must be at least 6 bytes (+ 4bytes CRC) */ + GST_WARNING ("PID %d invalid NIT entry size %d", + section->pid, transport_stream_loop_length); + goto error; + } + + transport_stream_id = GST_READ_UINT16_BE (data); + data += 2; + + original_network_id = GST_READ_UINT16_BE (data); + data += 2; + + descriptors_loop_length = GST_READ_UINT16_BE (data) & 0x0FFF; + data += 2; + + transport_name = g_strdup_printf ("transport-%d", transport_stream_id); + transport = gst_structure_new (transport_name, NULL); + g_free (transport_name); + gst_structure_id_set (transport, + QUARK_TRANSPORT_STREAM_ID, G_TYPE_UINT, transport_stream_id, + QUARK_ORIGINAL_NETWORK_ID, G_TYPE_UINT, original_network_id, NULL); + + if (descriptors_loop_length) { + GstMPEGDescriptor *mpegdescriptor; + guint8 *delivery; + + if (data + descriptors_loop_length > end - 4) { + GST_WARNING ("PID %d invalid NIT entry %d descriptors loop length %d", + section->pid, transport_stream_id, descriptors_loop_length); + gst_structure_free (transport); + goto error; + } + mpegdescriptor = + gst_mpeg_descriptor_parse (data, descriptors_loop_length); + + if ((delivery = + gst_mpeg_descriptor_find (mpegdescriptor, + DESC_DVB_SATELLITE_DELIVERY_SYSTEM))) { + + guint8 *frequency_bcd = + DESC_DVB_SATELLITE_DELIVERY_SYSTEM_frequency (delivery); + guint32 frequency = + 10 * ((frequency_bcd[3] & 0x0F) + + 10 * ((frequency_bcd[3] & 0xF0) >> 4) + + 100 * (frequency_bcd[2] & 0x0F) + + 1000 * ((frequency_bcd[2] & 0xF0) >> 4) + + 10000 * (frequency_bcd[1] & 0x0F) + + 100000 * ((frequency_bcd[1] & 0xF0) >> 4) + + 1000000 * (frequency_bcd[0] & 0x0F) + + 10000000 * ((frequency_bcd[0] & 0xF0) >> 4)); + guint8 *orbital_bcd = + DESC_DVB_SATELLITE_DELIVERY_SYSTEM_orbital_position (delivery); + gfloat orbital = + (orbital_bcd[1] & 0x0F) / 10. + ((orbital_bcd[1] & 0xF0) >> 4) + + 10 * (orbital_bcd[0] & 0x0F) + 100 * ((orbital_bcd[0] & 0xF0) >> 4); + gboolean east = + DESC_DVB_SATELLITE_DELIVERY_SYSTEM_west_east_flag (delivery); + guint8 polarization = + DESC_DVB_SATELLITE_DELIVERY_SYSTEM_polarization (delivery); + const gchar *polarization_str; + guint8 modulation = + DESC_DVB_SATELLITE_DELIVERY_SYSTEM_modulation (delivery); + const gchar *modulation_str; + guint8 *symbol_rate_bcd = + DESC_DVB_SATELLITE_DELIVERY_SYSTEM_symbol_rate (delivery); + guint32 symbol_rate = + (symbol_rate_bcd[2] & 0x0F) + + 10 * ((symbol_rate_bcd[2] & 0xF0) >> 4) + + 100 * (symbol_rate_bcd[1] & 0x0F) + + 1000 * ((symbol_rate_bcd[1] & 0xF0) >> 4) + + 10000 * (symbol_rate_bcd[0] & 0x0F) + + 100000 * ((symbol_rate_bcd[0] & 0xF0) >> 4); + guint8 fec_inner = + DESC_DVB_SATELLITE_DELIVERY_SYSTEM_fec_inner (delivery); + const gchar *fec_inner_str; + + switch (polarization) { + case 0: + polarization_str = "horizontal"; + break; + case 1: + polarization_str = "vertical"; + break; + case 2: + polarization_str = "left"; + break; + case 3: + polarization_str = "right"; + break; + default: + polarization_str = ""; + } + switch (fec_inner) { + case 0: + fec_inner_str = "undefined"; + break; + case 1: + fec_inner_str = "1/2"; + break; + case 2: + fec_inner_str = "2/3"; + break; + case 3: + fec_inner_str = "3/4"; + break; + case 4: + fec_inner_str = "5/6"; + break; + case 5: + fec_inner_str = "7/8"; + break; + case 6: + fec_inner_str = "8/9"; + break; + case 0xF: + fec_inner_str = "none"; + break; + default: + fec_inner_str = "reserved"; + } + switch (modulation) { + case 0x00: + modulation_str = "undefined"; + break; + case 0x01: + modulation_str = "QAM16"; + break; + case 0x02: + modulation_str = "QAM32"; + break; + case 0x03: + modulation_str = "QAM64"; + break; + case 0x04: + modulation_str = "QAM128"; + break; + case 0x05: + modulation_str = "QAM256"; + break; + default: + modulation_str = "reserved"; + } + delivery_structure = gst_structure_new ("satellite", + "orbital", G_TYPE_FLOAT, orbital, + "east-or-west", G_TYPE_STRING, east ? "east" : "west", + "modulation", G_TYPE_STRING, modulation_str, + "frequency", G_TYPE_UINT, frequency, + "polarization", G_TYPE_STRING, polarization_str, + "symbol-rate", G_TYPE_UINT, symbol_rate, + "inner-fec", G_TYPE_STRING, fec_inner_str, NULL); + gst_structure_set (transport, "delivery", GST_TYPE_STRUCTURE, + delivery_structure, NULL); + } else if ((delivery = + gst_mpeg_descriptor_find (mpegdescriptor, + DESC_DVB_TERRESTRIAL_DELIVERY_SYSTEM))) { + + guint32 frequency = + DESC_DVB_TERRESTRIAL_DELIVERY_SYSTEM_frequency (delivery) * 10; + guint8 bandwidth = + DESC_DVB_TERRESTRIAL_DELIVERY_SYSTEM_bandwidth (delivery); + guint8 constellation = + DESC_DVB_TERRESTRIAL_DELIVERY_SYSTEM_constellation (delivery); + guint8 hierarchy = + DESC_DVB_TERRESTRIAL_DELIVERY_SYSTEM_hierarchy (delivery); + guint8 code_rate_hp = + DESC_DVB_TERRESTRIAL_DELIVERY_SYSTEM_code_rate_hp (delivery); + guint8 code_rate_lp = + DESC_DVB_TERRESTRIAL_DELIVERY_SYSTEM_code_rate_lp (delivery); + guint8 guard_interval = + DESC_DVB_TERRESTRIAL_DELIVERY_SYSTEM_guard_interval (delivery); + guint8 transmission_mode = + DESC_DVB_TERRESTRIAL_DELIVERY_SYSTEM_transmission_mode (delivery); + gboolean other_frequency = + DESC_DVB_TERRESTRIAL_DELIVERY_SYSTEM_other_frequency (delivery); + const gchar *constellation_str, *code_rate_hp_str, *code_rate_lp_str, + *transmission_mode_str; + /* do the stuff */ + /* bandwidth is 8 if 0, 7 if 1, 6 if 2, reserved otherwise */ + if (bandwidth <= 2) + bandwidth = 8 - bandwidth; + else + bandwidth = 0; + switch (constellation) { + case 0: + constellation_str = "QPSK"; + break; + case 1: + constellation_str = "QAM16"; + break; + case 2: + constellation_str = "QAM64"; + break; + default: + constellation_str = "reserved"; + } + /* hierarchy is 4 if 3, 2 if 2, 1 if 1, 0 if 0, reserved if > 3 */ + if (hierarchy <= 3) { + if (hierarchy == 3) + hierarchy = 4; + } else { + hierarchy = 0; + } + + switch (code_rate_hp) { + case 0: + code_rate_hp_str = "1/2"; + break; + case 1: + code_rate_hp_str = "2/3"; + break; + case 2: + code_rate_hp_str = "3/4"; + break; + case 3: + code_rate_hp_str = "5/6"; + break; + case 4: + code_rate_hp_str = "7/8"; + break; + default: + code_rate_hp_str = "reserved"; + } + + switch (code_rate_lp) { + case 0: + code_rate_lp_str = "1/2"; + break; + case 1: + code_rate_lp_str = "2/3"; + break; + case 2: + code_rate_lp_str = "3/4"; + break; + case 3: + code_rate_lp_str = "5/6"; + break; + case 4: + code_rate_lp_str = "7/8"; + break; + default: + code_rate_lp_str = "reserved"; + } + /* guard is 32 if 0, 16 if 1, 8 if 2, 4 if 3 */ + switch (guard_interval) { + case 0: + guard_interval = 32; + break; + case 1: + guard_interval = 16; + break; + case 2: + guard_interval = 8; + break; + case 3: + guard_interval = 4; + break; + default: /* make it default to 32 */ + guard_interval = 32; + } + switch (transmission_mode) { + case 0: + transmission_mode_str = "2k"; + break; + case 1: + transmission_mode_str = "8k"; + break; + default: + transmission_mode_str = "reserved"; + } + delivery_structure = gst_structure_new ("terrestrial", + "frequency", G_TYPE_UINT, frequency, + "bandwidth", G_TYPE_UINT, bandwidth, + "constellation", G_TYPE_STRING, constellation_str, + "hierarchy", G_TYPE_UINT, hierarchy, + "code-rate-hp", G_TYPE_STRING, code_rate_hp_str, + "code-rate-lp", G_TYPE_STRING, code_rate_lp_str, + "guard-interval", G_TYPE_UINT, guard_interval, + "transmission-mode", G_TYPE_STRING, transmission_mode_str, + "other-frequency", G_TYPE_BOOLEAN, other_frequency, NULL); + gst_structure_set (transport, "delivery", GST_TYPE_STRUCTURE, + delivery_structure, NULL); + } else if ((delivery = + gst_mpeg_descriptor_find (mpegdescriptor, + DESC_DVB_CABLE_DELIVERY_SYSTEM))) { + + guint8 *frequency_bcd = + DESC_DVB_CABLE_DELIVERY_SYSTEM_frequency (delivery); + /* see en 300 468 section 6.2.13.1 least significant bcd digit + * is measured in 100Hz units so multiplier needs to be 100 to get + * into Hz */ + guint32 frequency = 100 * + ((frequency_bcd[3] & 0x0F) + + 10 * ((frequency_bcd[3] & 0xF0) >> 4) + + 100 * (frequency_bcd[2] & 0x0F) + + 1000 * ((frequency_bcd[2] & 0xF0) >> 4) + + 10000 * (frequency_bcd[1] & 0x0F) + + 100000 * ((frequency_bcd[1] & 0xF0) >> 4) + + 1000000 * (frequency_bcd[0] & 0x0F) + + 10000000 * ((frequency_bcd[0] & 0xF0) >> 4)); + guint8 modulation = + DESC_DVB_CABLE_DELIVERY_SYSTEM_modulation (delivery); + const gchar *modulation_str; + guint8 *symbol_rate_bcd = + DESC_DVB_CABLE_DELIVERY_SYSTEM_symbol_rate (delivery); + guint32 symbol_rate = + (symbol_rate_bcd[2] & 0x0F) + + 10 * ((symbol_rate_bcd[2] & 0xF0) >> 4) + + 100 * (symbol_rate_bcd[1] & 0x0F) + + 1000 * ((symbol_rate_bcd[1] & 0xF0) >> 4) + + 10000 * (symbol_rate_bcd[0] & 0x0F) + + 100000 * ((symbol_rate_bcd[0] & 0xF0) >> 4); + guint8 fec_inner = DESC_DVB_CABLE_DELIVERY_SYSTEM_fec_inner (delivery); + const gchar *fec_inner_str; + + switch (fec_inner) { + case 0: + fec_inner_str = "undefined"; + break; + case 1: + fec_inner_str = "1/2"; + break; + case 2: + fec_inner_str = "2/3"; + break; + case 3: + fec_inner_str = "3/4"; + break; + case 4: + fec_inner_str = "5/6"; + break; + case 5: + fec_inner_str = "7/8"; + break; + case 6: + fec_inner_str = "8/9"; + break; + case 0xF: + fec_inner_str = "none"; + break; + default: + fec_inner_str = "reserved"; + } + switch (modulation) { + case 0x00: + modulation_str = "undefined"; + break; + case 0x01: + modulation_str = "QAM16"; + break; + case 0x02: + modulation_str = "QAM32"; + break; + case 0x03: + modulation_str = "QAM64"; + break; + case 0x04: + modulation_str = "QAM128"; + break; + case 0x05: + modulation_str = "QAM256"; + break; + default: + modulation_str = "reserved"; + } + delivery_structure = gst_structure_new ("cable", + "modulation", G_TYPE_STRING, modulation_str, + "frequency", G_TYPE_UINT, frequency, + "symbol-rate", G_TYPE_UINT, symbol_rate, + "inner-fec", G_TYPE_STRING, fec_inner_str, NULL); + gst_structure_set (transport, "delivery", GST_TYPE_STRUCTURE, + delivery_structure, NULL); + } + /* free the temporary delivery structure */ + if (delivery_structure != NULL) { + gst_structure_free (delivery_structure); + delivery_structure = NULL; + } + if ((delivery = + gst_mpeg_descriptor_find (mpegdescriptor, + DESC_DTG_LOGICAL_CHANNEL))) { + guint8 *current_pos = delivery + 2; + GValue channel_numbers = { 0 }; + + g_value_init (&channel_numbers, GST_TYPE_LIST); + while (current_pos < delivery + DESC_LENGTH (delivery)) { + GstStructure *channel; + GValue channel_value = { 0 }; + guint16 service_id = GST_READ_UINT16_BE (current_pos); + guint16 logical_channel_number; + + current_pos += 2; + logical_channel_number = GST_READ_UINT16_BE (current_pos) & 0x03ff; + channel = + gst_structure_new ("channels", "service-id", G_TYPE_UINT, + service_id, "logical-channel-number", G_TYPE_UINT, + logical_channel_number, NULL); + g_value_init (&channel_value, GST_TYPE_STRUCTURE); + g_value_take_boxed (&channel_value, channel); + gst_value_list_append_value (&channel_numbers, &channel_value); + g_value_unset (&channel_value); + current_pos += 2; + } + gst_structure_set_value (transport, "channels", &channel_numbers); + g_value_unset (&channel_numbers); + } + if ((delivery = + gst_mpeg_descriptor_find (mpegdescriptor, + DESC_DVB_FREQUENCY_LIST))) { + guint8 *current_pos = delivery + 2; + GValue frequencies = { 0 }; + guint8 type; + + type = *current_pos & 0x03; + current_pos++; + + if (type) { + const gchar *fieldname = NULL; + g_value_init (&frequencies, GST_TYPE_LIST); + + while (current_pos < delivery + DESC_LENGTH (delivery) - 3) { + guint32 freq = 0; + guint8 *frequency_bcd = current_pos; + GValue frequency = { 0 }; + + switch (type) { + case 0x01: + /* satellite */ + freq = + 10 * ((frequency_bcd[3] & 0x0F) + + 10 * ((frequency_bcd[3] & 0xF0) >> 4) + + 100 * (frequency_bcd[2] & 0x0F) + + 1000 * ((frequency_bcd[2] & 0xF0) >> 4) + + 10000 * (frequency_bcd[1] & 0x0F) + + 100000 * ((frequency_bcd[1] & 0xF0) >> 4) + + 1000000 * (frequency_bcd[0] & 0x0F) + + 10000000 * ((frequency_bcd[0] & 0xF0) >> 4)); + break; + case 0x02: + /* cable */ + freq = 100 * + ((frequency_bcd[3] & 0x0F) + + 10 * ((frequency_bcd[3] & 0xF0) >> 4) + + 100 * (frequency_bcd[2] & 0x0F) + + 1000 * ((frequency_bcd[2] & 0xF0) >> 4) + + 10000 * (frequency_bcd[1] & 0x0F) + + 100000 * ((frequency_bcd[1] & 0xF0) >> 4) + + 1000000 * (frequency_bcd[0] & 0x0F) + + 10000000 * ((frequency_bcd[0] & 0xF0) >> 4)); + break; + case 0x03: + /* terrestrial */ + freq = GST_READ_UINT32_BE (current_pos) * 10; + break; + } + g_value_init (&frequency, G_TYPE_UINT); + g_value_set_uint (&frequency, freq); + gst_value_list_append_value (&frequencies, &frequency); + g_value_unset (&frequency); + current_pos += 4; + } + + switch (type) { + case 0x01: + fieldname = "frequency-list-satellite"; + break; + case 0x02: + fieldname = "frequency-list-cable"; + break; + case 0x03: + fieldname = "frequency-list-terrestrial"; + break; + } + + gst_structure_set_value (transport, fieldname, &frequencies); + g_value_unset (&frequencies); + } + } + gst_mpeg_descriptor_free (mpegdescriptor); + + descriptors = g_value_array_new (0); + if (!mpegts_packetizer_parse_descriptors (packetizer, + &data, data + descriptors_loop_length, descriptors)) { + gst_structure_free (transport); + g_value_array_free (descriptors); + goto error; + } + + gst_structure_id_set (transport, QUARK_DESCRIPTORS, G_TYPE_VALUE_ARRAY, + descriptors, NULL); + g_value_array_free (descriptors); + } + + g_value_init (&transport_value, GST_TYPE_STRUCTURE); + g_value_take_boxed (&transport_value, transport); + gst_value_list_append_value (&transports, &transport_value); + g_value_unset (&transport_value); + + transport_stream_loop_length -= data - entry_begin; + } + + if (data != end - 4) { + GST_WARNING ("PID %d invalid NIT parsed %d length %d", + section->pid, (gint) (data - GST_BUFFER_DATA (section->buffer)), + GST_BUFFER_SIZE (section->buffer)); + goto error; + } + + gst_structure_id_set_value (nit, QUARK_TRANSPORTS, &transports); + g_value_unset (&transports); + + GST_DEBUG ("NIT %" GST_PTR_FORMAT, nit); + + return nit; + +error: + if (nit) + gst_structure_free (nit); + + if (GST_VALUE_HOLDS_LIST (&transports)) + g_value_unset (&transports); + + return NULL; +} + +GstStructure * +mpegts_packetizer_parse_sdt (MpegTSPacketizer2 * packetizer, + MpegTSPacketizerSection * section) +{ + GstStructure *sdt = NULL, *service = NULL; + guint8 *data, *end, *entry_begin; + guint16 transport_stream_id, original_network_id, service_id; + guint tmp; + guint sdt_info_length; + gboolean EIT_schedule, EIT_present_following; + guint8 running_status; + gboolean scrambled; + guint descriptors_loop_length; + GValue services = { 0 }; + GValueArray *descriptors = NULL; + GValue service_value = { 0 }; + + GST_DEBUG ("SDT"); + /* fixed header + CRC == 16 */ + if (GST_BUFFER_SIZE (section->buffer) < 14) { + GST_WARNING ("PID %d invalid SDT size %d", + section->pid, section->section_length); + goto error; + } + + data = GST_BUFFER_DATA (section->buffer); + end = data + GST_BUFFER_SIZE (section->buffer); + + section->table_id = *data++; + section->section_length = GST_READ_UINT16_BE (data) & 0x0FFF; + data += 2; + + if (data + section->section_length != end) { + GST_WARNING ("PID %d invalid SDT section length %d expected %d", + section->pid, section->section_length, (gint) (end - data)); + goto error; + } + + transport_stream_id = GST_READ_UINT16_BE (data); + data += 2; + + tmp = *data++; + section->version_number = (tmp >> 1) & 0x1F; + section->current_next_indicator = tmp & 0x01; + + /* skip section_number and last_section_number */ + data += 2; + + original_network_id = GST_READ_UINT16_BE (data); + data += 2; + + /* skip reserved byte */ + data += 1; + + sdt = gst_structure_id_new (QUARK_SDT, + QUARK_TRANSPORT_STREAM_ID, G_TYPE_UINT, transport_stream_id, + QUARK_VERSION_NUMBER, G_TYPE_UINT, section->version_number, + QUARK_CURRENT_NEXT_INDICATOR, G_TYPE_UINT, + section->current_next_indicator, QUARK_ORIGINAL_NETWORK_ID, G_TYPE_UINT, + original_network_id, QUARK_ACTUAL_TRANSPORT_STREAM, G_TYPE_BOOLEAN, + section->table_id == 0x42, NULL); + + sdt_info_length = section->section_length - 8; + g_value_init (&services, GST_TYPE_LIST); + /* read up to the CRC */ + while (sdt_info_length - 4 > 0) { + gchar *service_name; + + entry_begin = data; + + if (sdt_info_length < 9) { + /* each entry must be at least 5 bytes (+4 bytes for the CRC) */ + GST_WARNING ("PID %d invalid SDT entry size %d", + section->pid, sdt_info_length); + goto error; + } + + service_id = GST_READ_UINT16_BE (data); + data += 2; + + EIT_schedule = ((*data & 0x02) == 2); + EIT_present_following = (*data & 0x01) == 1; + + data += 1; + tmp = GST_READ_UINT16_BE (data); + + running_status = (*data >> 5) & 0x07; + scrambled = (*data >> 4) & 0x01; + descriptors_loop_length = tmp & 0x0FFF; + data += 2; + + /* TODO send tag event down relevant pad for channel name and provider */ + service_name = g_strdup_printf ("service-%d", service_id); + service = gst_structure_new (service_name, NULL); + g_free (service_name); + + if (descriptors_loop_length) { + guint8 *service_descriptor; + GstMPEGDescriptor *mpegdescriptor; + + if (data + descriptors_loop_length > end - 4) { + GST_WARNING ("PID %d invalid SDT entry %d descriptors loop length %d", + section->pid, service_id, descriptors_loop_length); + gst_structure_free (service); + goto error; + } + mpegdescriptor = + gst_mpeg_descriptor_parse (data, descriptors_loop_length); + service_descriptor = + gst_mpeg_descriptor_find (mpegdescriptor, DESC_DVB_SERVICE); + if (service_descriptor != NULL) { + gchar *servicename_tmp, *serviceprovider_name_tmp; + guint8 serviceprovider_name_length = + DESC_DVB_SERVICE_provider_name_length (service_descriptor); + gchar *serviceprovider_name = + (gchar *) DESC_DVB_SERVICE_provider_name_text (service_descriptor); + guint8 servicename_length = + DESC_DVB_SERVICE_name_length (service_descriptor); + gchar *servicename = + (gchar *) DESC_DVB_SERVICE_name_text (service_descriptor); + if (servicename_length + serviceprovider_name_length + 2 <= + DESC_LENGTH (service_descriptor)) { + const gchar *running_status_tmp; + switch (running_status) { + case 0: + running_status_tmp = "undefined"; + break; + case 1: + running_status_tmp = "not running"; + break; + case 2: + running_status_tmp = "starts in a few seconds"; + break; + case 3: + running_status_tmp = "pausing"; + break; + case 4: + running_status_tmp = "running"; + break; + default: + running_status_tmp = "reserved"; + } + servicename_tmp = + get_encoding_and_convert (servicename, servicename_length); + serviceprovider_name_tmp = + get_encoding_and_convert (serviceprovider_name, + serviceprovider_name_length); + + gst_structure_set (service, + "name", G_TYPE_STRING, servicename_tmp, + "provider-name", G_TYPE_STRING, serviceprovider_name_tmp, + "scrambled", G_TYPE_BOOLEAN, scrambled, + "running-status", G_TYPE_STRING, running_status_tmp, NULL); + + g_free (servicename_tmp); + g_free (serviceprovider_name_tmp); + } + } + gst_mpeg_descriptor_free (mpegdescriptor); + + descriptors = g_value_array_new (0); + if (!mpegts_packetizer_parse_descriptors (packetizer, + &data, data + descriptors_loop_length, descriptors)) { + gst_structure_free (service); + g_value_array_free (descriptors); + goto error; + } + + gst_structure_id_set (service, QUARK_DESCRIPTORS, G_TYPE_VALUE_ARRAY, + descriptors, NULL); + + g_value_array_free (descriptors); + } + + g_value_init (&service_value, GST_TYPE_STRUCTURE); + g_value_take_boxed (&service_value, service); + gst_value_list_append_value (&services, &service_value); + g_value_unset (&service_value); + + sdt_info_length -= data - entry_begin; + } + + if (data != end - 4) { + GST_WARNING ("PID %d invalid SDT parsed %d length %d", + section->pid, (gint) (data - GST_BUFFER_DATA (section->buffer)), + GST_BUFFER_SIZE (section->buffer)); + goto error; + } + + gst_structure_id_set_value (sdt, QUARK_SERVICES, &services); + g_value_unset (&services); + + return sdt; + +error: + if (sdt) + gst_structure_free (sdt); + + if (GST_VALUE_HOLDS_LIST (&services)) + g_value_unset (&services); + + return NULL; +} + +GstStructure * +mpegts_packetizer_parse_eit (MpegTSPacketizer2 * packetizer, + MpegTSPacketizerSection * section) +{ + GstStructure *eit = NULL, *event = NULL; + guint service_id, last_table_id, segment_last_section_number; + guint transport_stream_id, original_network_id; + gboolean free_ca_mode; + guint event_id, running_status; + guint64 start_and_duration; + guint16 mjd; + guint year, month, day, hour, minute, second; + guint duration; + guint8 *data, *end, *duration_ptr, *utc_ptr; + guint16 descriptors_loop_length; + GValue events = { 0 }; + GValue event_value = { 0 }; + GValueArray *descriptors = NULL; + gchar *event_name; + guint tmp; + + /* fixed header + CRC == 16 */ + if (GST_BUFFER_SIZE (section->buffer) < 18) { + GST_WARNING ("PID %d invalid EIT size %d", + section->pid, section->section_length); + goto error; + } + + data = GST_BUFFER_DATA (section->buffer); + end = data + GST_BUFFER_SIZE (section->buffer); + + section->table_id = *data++; + section->section_length = GST_READ_UINT16_BE (data) & 0x0FFF; + data += 2; + + if (data + section->section_length != end) { + GST_WARNING ("PID %d invalid EIT section length %d expected %d", + section->pid, section->section_length, (gint) (end - data)); + goto error; + } + + service_id = GST_READ_UINT16_BE (data); + data += 2; + + tmp = *data++; + section->version_number = (tmp >> 1) & 0x1F; + section->current_next_indicator = tmp & 0x01; + + /* skip section_number and last_section_number */ + data += 2; + + transport_stream_id = GST_READ_UINT16_BE (data); + data += 2; + original_network_id = GST_READ_UINT16_BE (data); + data += 2; + segment_last_section_number = *data; + data += 1; + last_table_id = *data; + data += 1; + + eit = gst_structure_id_new (QUARK_EIT, + QUARK_VERSION_NUMBER, G_TYPE_UINT, section->version_number, + QUARK_CURRENT_NEXT_INDICATOR, G_TYPE_UINT, + section->current_next_indicator, QUARK_SERVICE_ID, G_TYPE_UINT, + service_id, QUARK_ACTUAL_TRANSPORT_STREAM, G_TYPE_BOOLEAN, + (section->table_id == 0x4E || (section->table_id >= 0x50 + && section->table_id <= 0x5F)), QUARK_PRESENT_FOLLOWING, + G_TYPE_BOOLEAN, (section->table_id == 0x4E + || section->table_id == 0x4F), QUARK_TRANSPORT_STREAM_ID, G_TYPE_UINT, + transport_stream_id, QUARK_ORIGINAL_NETWORK_ID, G_TYPE_UINT, + original_network_id, QUARK_SEGMENT_LAST_SECTION_NUMBER, G_TYPE_UINT, + segment_last_section_number, QUARK_LAST_TABLE_ID, G_TYPE_UINT, + last_table_id, NULL); + + g_value_init (&events, GST_TYPE_LIST); + while (data < end - 4) { + /* 12 is the minimum entry size + CRC */ + if (end - data < 12 + 4) { + GST_WARNING ("PID %d invalid EIT entry length %d", + section->pid, (gint) (end - 4 - data)); + gst_structure_free (eit); + goto error; + } + + event_id = GST_READ_UINT16_BE (data); + data += 2; + start_and_duration = GST_READ_UINT64_BE (data); + duration_ptr = data + 5; + utc_ptr = data + 2; + mjd = GST_READ_UINT16_BE (data); + if (mjd == G_MAXUINT16) { + year = 1900; + month = day = hour = minute = second = 0; + } else { + /* See EN 300 468 Annex C */ + year = (guint32) (((mjd - 15078.2) / 365.25)); + month = (guint8) ((mjd - 14956.1 - (guint) (year * 365.25)) / 30.6001); + day = mjd - 14956 - (guint) (year * 365.25) - (guint) (month * 30.6001); + if (month == 14 || month == 15) { + year++; + month = month - 1 - 12; + } else { + month--; + } + year += 1900; + hour = ((utc_ptr[0] & 0xF0) >> 4) * 10 + (utc_ptr[0] & 0x0F); + minute = ((utc_ptr[1] & 0xF0) >> 4) * 10 + (utc_ptr[1] & 0x0F); + second = ((utc_ptr[2] & 0xF0) >> 4) * 10 + (utc_ptr[2] & 0x0F); + } + + duration = (((duration_ptr[0] & 0xF0) >> 4) * 10 + + (duration_ptr[0] & 0x0F)) * 60 * 60 + + (((duration_ptr[1] & 0xF0) >> 4) * 10 + + (duration_ptr[1] & 0x0F)) * 60 + + ((duration_ptr[2] & 0xF0) >> 4) * 10 + (duration_ptr[2] & 0x0F); + + data += 8; + running_status = *data >> 5; + free_ca_mode = (*data >> 4) & 0x01; + descriptors_loop_length = GST_READ_UINT16_BE (data) & 0x0FFF; + data += 2; + + /* TODO: send tag event down relevant pad saying what is currently playing */ + event_name = g_strdup_printf ("event-%d", event_id); + event = gst_structure_new (event_name, + "event-id", G_TYPE_UINT, event_id, + "year", G_TYPE_UINT, year, + "month", G_TYPE_UINT, month, + "day", G_TYPE_UINT, day, + "hour", G_TYPE_UINT, hour, + "minute", G_TYPE_UINT, minute, + "second", G_TYPE_UINT, second, + "duration", G_TYPE_UINT, duration, + "running-status", G_TYPE_UINT, running_status, + "free-ca-mode", G_TYPE_BOOLEAN, free_ca_mode, NULL); + g_free (event_name); + + if (descriptors_loop_length) { + guint8 *event_descriptor; + GArray *component_descriptors; + GArray *extended_event_descriptors; + GstMPEGDescriptor *mpegdescriptor; + + if (data + descriptors_loop_length > end - 4) { + GST_WARNING ("PID %d invalid EIT descriptors loop length %d", + section->pid, descriptors_loop_length); + gst_structure_free (event); + goto error; + } + mpegdescriptor = + gst_mpeg_descriptor_parse (data, descriptors_loop_length); + event_descriptor = + gst_mpeg_descriptor_find (mpegdescriptor, DESC_DVB_SHORT_EVENT); + if (event_descriptor != NULL) { + gchar *eventname_tmp, *eventdescription_tmp; + guint8 eventname_length = + DESC_DVB_SHORT_EVENT_name_length (event_descriptor); + gchar *eventname = + (gchar *) DESC_DVB_SHORT_EVENT_name_text (event_descriptor); + guint8 eventdescription_length = + DESC_DVB_SHORT_EVENT_description_length (event_descriptor); + gchar *eventdescription = + (gchar *) DESC_DVB_SHORT_EVENT_description_text (event_descriptor); + if (eventname_length + eventdescription_length + 2 <= + DESC_LENGTH (event_descriptor)) { + + eventname_tmp = + get_encoding_and_convert (eventname, eventname_length), + eventdescription_tmp = + get_encoding_and_convert (eventdescription, + eventdescription_length); + + gst_structure_set (event, "name", G_TYPE_STRING, eventname_tmp, NULL); + gst_structure_set (event, "description", G_TYPE_STRING, + eventdescription_tmp, NULL); + g_free (eventname_tmp); + g_free (eventdescription_tmp); + } + } + extended_event_descriptors = gst_mpeg_descriptor_find_all (mpegdescriptor, + DESC_DVB_EXTENDED_EVENT); + if (extended_event_descriptors) { + int i; + guint8 *extended_descriptor; + /*GValue extended_items = { 0 }; */ + gchar *extended_text = NULL; + /*g_value_init (&extended_items, GST_TYPE_LIST); */ + for (i = 0; i < extended_event_descriptors->len; i++) { + extended_descriptor = g_array_index (extended_event_descriptors, + guint8 *, i); + if (DESC_DVB_EXTENDED_EVENT_descriptor_number (extended_descriptor) == + i) { + if (extended_text) { + gchar *tmp; + gchar *old_extended_text = extended_text; + tmp = get_encoding_and_convert ((gchar *) + DESC_DVB_EXTENDED_EVENT_text (extended_descriptor), + DESC_DVB_EXTENDED_EVENT_text_length (extended_descriptor)); + extended_text = g_strdup_printf ("%s%s", extended_text, tmp); + g_free (old_extended_text); + g_free (tmp); + } else { + extended_text = get_encoding_and_convert ((gchar *) + DESC_DVB_EXTENDED_EVENT_text (extended_descriptor), + DESC_DVB_EXTENDED_EVENT_text_length (extended_descriptor)); + } + } + } + if (extended_text) { + gst_structure_set (event, "extended-text", G_TYPE_STRING, + extended_text, NULL); + g_free (extended_text); + } + g_array_free (extended_event_descriptors, TRUE); + } + + component_descriptors = gst_mpeg_descriptor_find_all (mpegdescriptor, + DESC_DVB_COMPONENT); + if (component_descriptors) { + int i; + guint8 *comp_descriptor; + GValue components = { 0 }; + g_value_init (&components, GST_TYPE_LIST); + /* FIXME: do the component descriptor parsing less verbosely + * and better...a task for 0.10.6 */ + for (i = 0; i < component_descriptors->len; i++) { + GstStructure *component = NULL; + GValue component_value = { 0 }; + gint widescreen = 0; /* 0 for 4:3, 1 for 16:9, 2 for > 16:9 */ + gint freq = 25; /* 25 or 30 measured in Hertz */ + gboolean highdef = FALSE; + gboolean panvectors = FALSE; + const gchar *comptype = ""; + + comp_descriptor = g_array_index (component_descriptors, guint8 *, i); + switch (DESC_DVB_COMPONENT_stream_content (comp_descriptor)) { + case 0x01: + /* video */ + switch (DESC_DVB_COMPONENT_type (comp_descriptor)) { + case 0x01: + widescreen = 0; + freq = 25; + break; + case 0x02: + widescreen = 1; + panvectors = TRUE; + freq = 25; + break; + case 0x03: + widescreen = 1; + panvectors = FALSE; + freq = 25; + break; + case 0x04: + widescreen = 2; + freq = 25; + break; + case 0x05: + widescreen = 0; + freq = 30; + break; + case 0x06: + widescreen = 1; + panvectors = TRUE; + freq = 30; + break; + case 0x07: + widescreen = 1; + panvectors = FALSE; + freq = 30; + break; + case 0x08: + widescreen = 2; + freq = 30; + break; + case 0x09: + widescreen = 0; + highdef = TRUE; + freq = 25; + break; + case 0x0A: + widescreen = 1; + highdef = TRUE; + panvectors = TRUE; + freq = 25; + break; + case 0x0B: + widescreen = 1; + highdef = TRUE; + panvectors = FALSE; + freq = 25; + break; + case 0x0C: + widescreen = 2; + highdef = TRUE; + freq = 25; + break; + case 0x0D: + widescreen = 0; + highdef = TRUE; + freq = 30; + break; + case 0x0E: + widescreen = 1; + highdef = TRUE; + panvectors = TRUE; + freq = 30; + break; + case 0x0F: + widescreen = 1; + highdef = TRUE; + panvectors = FALSE; + freq = 30; + break; + case 0x10: + widescreen = 2; + highdef = TRUE; + freq = 30; + break; + } + component = gst_structure_new ("video", "high-definition", + G_TYPE_BOOLEAN, TRUE, "frequency", G_TYPE_INT, freq, + "tag", G_TYPE_INT, DESC_DVB_COMPONENT_tag (comp_descriptor), + NULL); + if (widescreen == 0) { + gst_structure_set (component, "aspect-ratio", + G_TYPE_STRING, "4:3", NULL); + } else if (widescreen == 2) { + gst_structure_set (component, "aspect-ratio", G_TYPE_STRING, + "> 16:9", NULL); + } else { + gst_structure_set (component, "aspect-ratio", G_TYPE_STRING, + "16:9", "pan-vectors", G_TYPE_BOOLEAN, panvectors, NULL); + } + break; + case 0x02: /* audio */ + comptype = "undefined"; + switch (DESC_DVB_COMPONENT_type (comp_descriptor)) { + case 0x01: + comptype = "single channel mono"; + break; + case 0x02: + comptype = "dual channel mono"; + break; + case 0x03: + comptype = "stereo"; + break; + case 0x04: + comptype = "multi-channel multi-lingual"; + break; + case 0x05: + comptype = "surround"; + break; + case 0x40: + comptype = "audio description for the visually impaired"; + break; + case 0x41: + comptype = "audio for the hard of hearing"; + break; + } + component = gst_structure_new ("audio", "type", G_TYPE_STRING, + comptype, "tag", G_TYPE_INT, + DESC_DVB_COMPONENT_tag (comp_descriptor), NULL); + break; + case 0x03: /* subtitles/teletext/vbi */ + comptype = "reserved"; + switch (DESC_DVB_COMPONENT_type (comp_descriptor)) { + case 0x01: + comptype = "EBU Teletext subtitles"; + break; + case 0x02: + comptype = "associated EBU Teletext"; + break; + case 0x03: + comptype = "VBI data"; + break; + case 0x10: + comptype = "Normal DVB subtitles"; + break; + case 0x11: + comptype = "Normal DVB subtitles for 4:3"; + break; + case 0x12: + comptype = "Normal DVB subtitles for 16:9"; + break; + case 0x13: + comptype = "Normal DVB subtitles for 2.21:1"; + break; + case 0x20: + comptype = "Hard of hearing DVB subtitles"; + break; + case 0x21: + comptype = "Hard of hearing DVB subtitles for 4:3"; + break; + case 0x22: + comptype = "Hard of hearing DVB subtitles for 16:9"; + break; + case 0x23: + comptype = "Hard of hearing DVB subtitles for 2.21:1"; + break; + } + component = gst_structure_new ("teletext", "type", G_TYPE_STRING, + comptype, "tag", G_TYPE_INT, + DESC_DVB_COMPONENT_tag (comp_descriptor), NULL); + break; + } + if (component) { + g_value_init (&component_value, GST_TYPE_STRUCTURE); + g_value_take_boxed (&component_value, component); + gst_value_list_append_value (&components, &component_value); + g_value_unset (&component_value); + component = NULL; + } + } + gst_structure_set_value (event, "components", &components); + g_value_unset (&components); + g_array_free (component_descriptors, TRUE); + } + gst_mpeg_descriptor_free (mpegdescriptor); + + descriptors = g_value_array_new (0); + if (!mpegts_packetizer_parse_descriptors (packetizer, + &data, data + descriptors_loop_length, descriptors)) { + gst_structure_free (event); + g_value_array_free (descriptors); + goto error; + } + gst_structure_id_set (event, QUARK_DESCRIPTORS, G_TYPE_VALUE_ARRAY, + descriptors, NULL); + g_value_array_free (descriptors); + } + + g_value_init (&event_value, GST_TYPE_STRUCTURE); + g_value_take_boxed (&event_value, event); + gst_value_list_append_value (&events, &event_value); + g_value_unset (&event_value); + } + + if (data != end - 4) { + GST_WARNING ("PID %d invalid EIT parsed %d length %d", + section->pid, (gint) (data - GST_BUFFER_DATA (section->buffer)), + GST_BUFFER_SIZE (section->buffer)); + goto error; + } + + gst_structure_id_set_value (eit, QUARK_EVENTS, &events); + g_value_unset (&events); + + GST_DEBUG ("EIT %" GST_PTR_FORMAT, eit); + + return eit; + +error: + if (eit) + gst_structure_free (eit); + + if (GST_VALUE_HOLDS_LIST (&events)) + g_value_unset (&events); + + return NULL; +} + +GstStructure * +mpegts_packetizer_parse_tdt (MpegTSPacketizer2 * packetizer, + MpegTSPacketizerSection * section) +{ + GstStructure *tdt = NULL; + guint16 mjd; + guint year, month, day, hour, minute, second; + guint8 *data, *end, *utc_ptr; + + GST_DEBUG ("TDT"); + /* length always 8 */ + if (G_UNLIKELY (GST_BUFFER_SIZE (section->buffer) != 8)) { + GST_WARNING ("PID %d invalid TDT size %d", + section->pid, section->section_length); + goto error; + } + + data = GST_BUFFER_DATA (section->buffer); + end = data + GST_BUFFER_SIZE (section->buffer); + + section->table_id = *data++; + section->section_length = GST_READ_UINT16_BE (data) & 0x0FFF; + data += 2; + + if (data + section->section_length != end) { + GST_WARNING ("PID %d invalid TDT section length %d expected %d", + section->pid, section->section_length, (gint) (end - data)); + goto error; + } + + mjd = GST_READ_UINT16_BE (data); + data += 2; + utc_ptr = data; + if (mjd == G_MAXUINT16) { + year = 1900; + month = day = hour = minute = second = 0; + } else { + /* See EN 300 468 Annex C */ + year = (guint32) (((mjd - 15078.2) / 365.25)); + month = (guint8) ((mjd - 14956.1 - (guint) (year * 365.25)) / 30.6001); + day = mjd - 14956 - (guint) (year * 365.25) - (guint) (month * 30.6001); + if (month == 14 || month == 15) { + year++; + month = month - 1 - 12; + } else { + month--; + } + year += 1900; + hour = ((utc_ptr[0] & 0xF0) >> 4) * 10 + (utc_ptr[0] & 0x0F); + minute = ((utc_ptr[1] & 0xF0) >> 4) * 10 + (utc_ptr[1] & 0x0F); + second = ((utc_ptr[2] & 0xF0) >> 4) * 10 + (utc_ptr[2] & 0x0F); + } + tdt = gst_structure_new ("tdt", + "year", G_TYPE_UINT, year, + "month", G_TYPE_UINT, month, + "day", G_TYPE_UINT, day, + "hour", G_TYPE_UINT, hour, + "minute", G_TYPE_UINT, minute, "second", G_TYPE_UINT, second, NULL); + + return tdt; + +error: + if (tdt) + gst_structure_free (tdt); + + return NULL; +} + +void +mpegts_packetizer_clear (MpegTSPacketizer2 * packetizer) +{ + if (packetizer->know_packet_size) { + packetizer->know_packet_size = FALSE; + packetizer->packet_size = 0; + if (packetizer->caps != NULL) { + gst_caps_unref (packetizer->caps); + packetizer->caps = NULL; + } + } + if (packetizer->streams) { + int i; + for (i = 0; i < 8192; i++) { + if (packetizer->streams[i]) { + mpegts_packetizer_stream_free (packetizer->streams[i]); + } + } + memset (packetizer->streams, 0, 8192 * sizeof (MpegTSPacketizerStream *)); + } + + gst_adapter_clear (packetizer->adapter); + packetizer->offset = 0; + packetizer->empty = TRUE; +} + +void +mpegts_packetizer_remove_stream (MpegTSPacketizer2 * packetizer, gint16 pid) +{ + MpegTSPacketizerStream *stream = packetizer->streams[pid]; + if (stream) { + GST_INFO ("Removing stream for PID %d", pid); + mpegts_packetizer_stream_free (stream); + packetizer->streams[pid] = NULL; + } +} + +MpegTSPacketizer2 * +mpegts_packetizer_new (void) +{ + MpegTSPacketizer2 *packetizer; + + packetizer = + GST_MPEGTS_PACKETIZER (g_object_new (GST_TYPE_MPEGTS_PACKETIZER, NULL)); + + return packetizer; +} + +void +mpegts_packetizer_push (MpegTSPacketizer2 * packetizer, GstBuffer * buffer) +{ + if (G_UNLIKELY (packetizer->empty)) { + packetizer->empty = FALSE; + packetizer->offset = GST_BUFFER_OFFSET (buffer); + } + + GST_DEBUG ("Pushing %u byte from offset %" G_GUINT64_FORMAT, + GST_BUFFER_SIZE (buffer), GST_BUFFER_OFFSET (buffer)); + gst_adapter_push (packetizer->adapter, buffer); +} + +static gboolean +mpegts_try_discover_packet_size (MpegTSPacketizer2 * packetizer) +{ + guint8 *dest; + int i, pos = -1, j; + static const guint psizes[] = { + MPEGTS_NORMAL_PACKETSIZE, + MPEGTS_M2TS_PACKETSIZE, + MPEGTS_DVB_ASI_PACKETSIZE, + MPEGTS_ATSC_PACKETSIZE + }; + + + dest = g_malloc (MPEGTS_MAX_PACKETSIZE * 4); + /* wait for 3 sync bytes */ + while (packetizer->adapter->size >= MPEGTS_MAX_PACKETSIZE * 4) { + + /* check for sync bytes */ + gst_adapter_copy (packetizer->adapter, dest, 0, MPEGTS_MAX_PACKETSIZE * 4); + /* find first sync byte */ + pos = -1; + for (i = 0; i < MPEGTS_MAX_PACKETSIZE; i++) { + if (dest[i] == 0x47) { + for (j = 0; j < 4; j++) { + guint packetsize = psizes[j]; + /* check each of the packet size possibilities in turn */ + if (dest[i] == 0x47 && dest[i + packetsize] == 0x47 && + dest[i + packetsize * 2] == 0x47 && + dest[i + packetsize * 3] == 0x47) { + packetizer->know_packet_size = TRUE; + packetizer->packet_size = packetsize; + packetizer->caps = gst_caps_new_simple ("video/mpegts", + "systemstream", G_TYPE_BOOLEAN, TRUE, + "packetsize", G_TYPE_INT, packetsize, NULL); + if (packetsize == MPEGTS_M2TS_PACKETSIZE) + pos = i - 4; + else + pos = i; + break; + } + } + break; + } + } + + if (packetizer->know_packet_size) + break; + + /* Skip MPEGTS_MAX_PACKETSIZE */ + gst_adapter_flush (packetizer->adapter, MPEGTS_MAX_PACKETSIZE); + packetizer->offset += MPEGTS_MAX_PACKETSIZE; + } + + g_free (dest); + + if (packetizer->know_packet_size) { + GST_DEBUG ("have packetsize detected: %d of %u bytes", + packetizer->know_packet_size, packetizer->packet_size); + /* flush to sync byte */ + if (pos > 0) { + GST_DEBUG ("Flushing out %d bytes"); + gst_adapter_flush (packetizer->adapter, pos); + packetizer->offset += pos; + } else if (!packetizer->know_packet_size) { + /* drop invalid data and move to the next possible packets */ + gst_adapter_flush (packetizer->adapter, MPEGTS_MAX_PACKETSIZE); + } + } + + return packetizer->know_packet_size; +} + +gboolean +mpegts_packetizer_has_packets (MpegTSPacketizer2 * packetizer) +{ + if (G_UNLIKELY (packetizer->know_packet_size == FALSE)) { + if (!mpegts_try_discover_packet_size (packetizer)) + return FALSE; + } + return packetizer->adapter->size >= packetizer->packet_size; +} + +MpegTSPacketizerPacketReturn +mpegts_packetizer_next_packet (MpegTSPacketizer2 * packetizer, + MpegTSPacketizerPacket * packet) +{ + guint avail; + + packet->buffer = NULL; + + if (G_UNLIKELY (!packetizer->know_packet_size)) { + if (!mpegts_try_discover_packet_size (packetizer)) + return PACKET_NEED_MORE; + } + + while ((avail = packetizer->adapter->size) >= packetizer->packet_size) { + packet->buffer = gst_adapter_take_buffer (packetizer->adapter, + packetizer->packet_size); + /* M2TS packets don't start with the sync byte, all other variants do */ + if (packetizer->packet_size == MPEGTS_M2TS_PACKETSIZE) { + packet->data_start = GST_BUFFER_DATA (packet->buffer) + 4; + } else { + packet->data_start = GST_BUFFER_DATA (packet->buffer); + } + /* ALL mpeg-ts variants contain 188 bytes of data. Those with bigger packet + * sizes contain either extra data (timesync, FEC, ..) either before or after + * the data */ + packet->data_end = packet->data_start + 188; + GST_BUFFER_OFFSET (packet->buffer) = packet->offset = packetizer->offset; + GST_DEBUG ("offset %" G_GUINT64_FORMAT, packet->offset); + packetizer->offset += packetizer->packet_size; + GST_MEMDUMP ("buffer", GST_BUFFER_DATA (packet->buffer), 16); + GST_MEMDUMP ("data_start", packet->data_start, 16); + + /* Check sync byte */ + if (G_UNLIKELY (packet->data_start[0] != 0x47)) { + guint i; + GstBuffer *tmpbuf; + + GST_LOG ("Lost sync %d", packetizer->packet_size); + /* Find the 0x47 in the buffer */ + for (i = 0; i < packetizer->packet_size; i++) + if (GST_BUFFER_DATA (packet->buffer)[i] == 0x47) + break; + if (G_UNLIKELY (i == packetizer->packet_size)) { + GST_ERROR ("REALLY lost the sync"); + gst_buffer_unref (packet->buffer); + goto done; + } + /* Pop out the remaining data... */ + GST_BUFFER_DATA (packet->buffer) += i; + GST_BUFFER_SIZE (packet->buffer) -= i; + GST_BUFFER_OFFSET (packet->buffer) += i; + tmpbuf = + gst_adapter_take_buffer (packetizer->adapter, + packetizer->adapter->size); + /* ... and push everything back in */ + gst_adapter_push (packetizer->adapter, packet->buffer); + gst_adapter_push (packetizer->adapter, tmpbuf); + continue; + } + + return mpegts_packetizer_parse_packet (packetizer, packet); + } + +done: + return PACKET_NEED_MORE; +} + +void +mpegts_packetizer_clear_packet (MpegTSPacketizer2 * packetizer, + MpegTSPacketizerPacket * packet) +{ + memset (packet, 0, sizeof (MpegTSPacketizerPacket)); +} + +gboolean +mpegts_packetizer_push_section (MpegTSPacketizer2 * packetizer, + MpegTSPacketizerPacket * packet, MpegTSPacketizerSection * section) +{ + gboolean res = FALSE; + MpegTSPacketizerStream *stream; + guint8 pointer, table_id; + guint16 subtable_extension; + guint section_length; + GstBuffer *sub_buf; + guint8 *data; + + data = packet->data; + section->pid = packet->pid; + + if (packet->payload_unit_start_indicator == 1) { + pointer = *data++; + if (data + pointer > packet->data_end) { + GST_WARNING ("PID %d PSI section pointer points past the end " + "of the buffer", packet->pid); + goto out; + } + + data += pointer; + } + /* TDT and TOT sections (see ETSI EN 300 468 5.2.5) + * these sections do not extend to several packets so we don't need to use the + * sections filter. */ + if (packet->pid == 0x14) { + table_id = data[0]; + section->section_length = GST_READ_UINT24_BE (data) & 0x000FFF; + section->buffer = gst_buffer_create_sub (packet->buffer, + data - GST_BUFFER_DATA (packet->buffer), section->section_length + 3); + section->table_id = table_id; + section->complete = TRUE; + res = TRUE; + GST_DEBUG ("TDT section pid:%d table_id:%d section_length: %d\n", + packet->pid, table_id, section->section_length); + goto out; + } + + /* create a sub buffer from the start of the section (table_id and + * section_length included) to the end */ + sub_buf = gst_buffer_create_sub (packet->buffer, + data - GST_BUFFER_DATA (packet->buffer), packet->data_end - data); + + + stream = packetizer->streams[packet->pid]; + if (stream == NULL) { + stream = mpegts_packetizer_stream_new (); + packetizer->streams[packet->pid] = stream; + } + + if (packet->payload_unit_start_indicator) { + table_id = *data++; + /* subtable_extension should be read from 4th and 5th bytes only if + * section_syntax_indicator is 1 */ + if ((data[0] & 0x80) == 0) + subtable_extension = 0; + else + subtable_extension = GST_READ_UINT16_BE (data + 2); + GST_DEBUG ("pid: %d table_id %d sub_table_extension %d", + packet->pid, table_id, subtable_extension); + + section_length = GST_READ_UINT16_BE (data) & 0x0FFF; + + if (stream->continuity_counter != CONTINUITY_UNSET) { + GST_DEBUG + ("PID %d table_id %d sub_table_extension %d payload_unit_start_indicator set but section " + "not complete (last_continuity: %d continuity: %d sec len %d buffer %d avail %d", + packet->pid, table_id, subtable_extension, stream->continuity_counter, + packet->continuity_counter, section_length, GST_BUFFER_SIZE (sub_buf), + stream->section_adapter->size); + mpegts_packetizer_clear_section (packetizer, stream); + } else { + GST_DEBUG + ("pusi set and new stream section is %d long and data we have is: %d", + section_length, (gint) (packet->data_end - packet->data)); + } + stream->continuity_counter = packet->continuity_counter; + stream->section_length = section_length; + stream->section_table_id = table_id; + stream->offset = packet->offset; + gst_adapter_push (stream->section_adapter, sub_buf); + + res = TRUE; + } else if (stream->continuity_counter != CONTINUITY_UNSET && + (packet->continuity_counter == stream->continuity_counter + 1 || + (stream->continuity_counter == MAX_CONTINUITY && + packet->continuity_counter == 0))) { + stream->continuity_counter = packet->continuity_counter; + gst_adapter_push (stream->section_adapter, sub_buf); + + res = TRUE; + } else { + if (stream->continuity_counter == CONTINUITY_UNSET) + GST_DEBUG ("PID %d waiting for pusi", packet->pid); + else + GST_DEBUG ("PID %d section discontinuity " + "(last_continuity: %d continuity: %d", packet->pid, + stream->continuity_counter, packet->continuity_counter); + mpegts_packetizer_clear_section (packetizer, stream); + gst_buffer_unref (sub_buf); + } + + if (res) { + /* we pushed some data in the section adapter, see if the section is + * complete now */ + + /* >= as sections can be padded and padding is not included in + * section_length */ + if (stream->section_adapter->size >= stream->section_length + 3) { + res = mpegts_packetizer_parse_section_header (packetizer, + stream, section); + + /* flush stuffing bytes */ + mpegts_packetizer_clear_section (packetizer, stream); + } else { + GST_DEBUG ("section not complete"); + /* section not complete yet */ + section->complete = FALSE; + } + } else { + GST_WARNING ("section not complete"); + section->complete = FALSE; + } + +out: + packet->data = data; + GST_DEBUG ("result: %d complete: %d", res, section->complete); + return res; +} + +static void +_init_local (void) +{ + GST_DEBUG_CATEGORY_INIT (mpegts_packetizer_debug, "mpegtspacketizer", 0, + "MPEG transport stream parser"); + + QUARK_PAT = g_quark_from_string ("pat"); + QUARK_TRANSPORT_STREAM_ID = g_quark_from_string ("transport-stream-id"); + QUARK_PROGRAM_NUMBER = g_quark_from_string ("program-number"); + QUARK_PID = g_quark_from_string ("pid"); + QUARK_PROGRAMS = g_quark_from_string ("programs"); + + QUARK_PMT = g_quark_from_string ("pmt"); + QUARK_PCR_PID = g_quark_from_string ("pcr-pid"); + QUARK_VERSION_NUMBER = g_quark_from_string ("version-number"); + QUARK_DESCRIPTORS = g_quark_from_string ("descriptors"); + QUARK_STREAM_TYPE = g_quark_from_string ("stream-type"); + QUARK_STREAMS = g_quark_from_string ("streams"); + + QUARK_NIT = g_quark_from_string ("nit"); + QUARK_NETWORK_ID = g_quark_from_string ("network-id"); + QUARK_CURRENT_NEXT_INDICATOR = g_quark_from_string ("current-next-indicator"); + QUARK_ACTUAL_NETWORK = g_quark_from_string ("actual-network"); + QUARK_NETWORK_NAME = g_quark_from_string ("network-name"); + QUARK_ORIGINAL_NETWORK_ID = g_quark_from_string ("original-network-id"); + QUARK_TRANSPORTS = g_quark_from_string ("transports"); + + QUARK_SDT = g_quark_from_string ("sdt"); + QUARK_ACTUAL_TRANSPORT_STREAM = + g_quark_from_string ("actual-transport-stream"); + QUARK_SERVICES = g_quark_from_string ("services"); + + QUARK_EIT = g_quark_from_string ("eit"); + QUARK_SERVICE_ID = g_quark_from_string ("service-id"); + QUARK_PRESENT_FOLLOWING = g_quark_from_string ("present-following"); + QUARK_SEGMENT_LAST_SECTION_NUMBER = + g_quark_from_string ("segment-last-section-number"); + QUARK_LAST_TABLE_ID = g_quark_from_string ("last-table-id"); + QUARK_EVENTS = g_quark_from_string ("events"); +} + +/** + * @text: The text you want to get the encoding from + * @start_text: Location where the beginning of the actual text is stored + * @is_multibyte: Location where information whether it's a multibyte encoding + * or not is stored + * @returns: Name of encoding or NULL of encoding could not be detected. + * + * The returned string should be freed with g_free () when no longer needed. + */ +static gchar * +get_encoding (const gchar * text, guint * start_text, gboolean * is_multibyte) +{ + gchar *encoding; + guint8 firstbyte; + + g_return_val_if_fail (text != NULL, NULL); + + firstbyte = (guint8) text[0]; + + if (firstbyte == 0x01) { + encoding = g_strdup ("iso8859-5"); + *start_text = 1; + *is_multibyte = FALSE; + } else if (firstbyte == 0x02) { + encoding = g_strdup ("iso8859-6"); + *start_text = 1; + *is_multibyte = FALSE; + } else if (firstbyte == 0x03) { + encoding = g_strdup ("iso8859-7"); + *start_text = 1; + *is_multibyte = FALSE; + } else if (firstbyte == 0x04) { + encoding = g_strdup ("iso8859-8"); + *start_text = 1; + *is_multibyte = FALSE; + } else if (firstbyte == 0x05) { + encoding = g_strdup ("iso8859-9"); + *start_text = 1; + *is_multibyte = FALSE; + } else if (firstbyte >= 0x20) { + encoding = g_strdup ("iso6937"); + *start_text = 0; + *is_multibyte = FALSE; + } else if (firstbyte == 0x10) { + guint16 table; + gchar table_str[6]; + + text++; + table = GST_READ_UINT16_BE (text); + g_snprintf (table_str, 6, "%d", table); + + encoding = g_strconcat ("iso8859-", table_str, NULL); + *start_text = 3; + *is_multibyte = FALSE; + } else if (firstbyte == 0x11) { + encoding = g_strdup ("ISO-10646/UCS2"); + *start_text = 1; + *is_multibyte = TRUE; + } else if (firstbyte == 0x12) { + // That's korean encoding. + // The spec says it's encoded in KSC 5601, but iconv only knows KSC 5636. + // Couldn't find any information about either of them. + encoding = NULL; + *start_text = 1; + *is_multibyte = TRUE; + } else { + // reserved + encoding = NULL; + *start_text = 0; + *is_multibyte = FALSE; + } + + GST_DEBUG + ("Found encoding %s, first byte is 0x%02x, start_text: %u, is_multibyte: %d", + encoding, firstbyte, *start_text, *is_multibyte); + + return encoding; +} + +/** + * @text: The text to convert. It may include pango markup ( and ) + * @length: The length of the string -1 if it's nul-terminated + * @start: Where to start converting in the text + * @encoding: The encoding of text + * @is_multibyte: Whether the encoding is a multibyte encoding + * @error: The location to store the error, or NULL to ignore errors + * @returns: UTF-8 encoded string + * + * Convert text to UTF-8. + */ +static gchar * +convert_to_utf8 (const gchar * text, gint length, guint start, + const gchar * encoding, gboolean is_multibyte, GError ** error) +{ + gchar *new_text; + GByteArray *sb; + gint i; + + g_return_val_if_fail (text != NULL, NULL); + g_return_val_if_fail (encoding != NULL, NULL); + + text += start; + + sb = g_byte_array_sized_new (length * 1.1); + + if (is_multibyte) { + if (length == -1) { + while (*text != '\0') { + guint16 code = GST_READ_UINT16_BE (text); + + switch (code) { + case 0xE086: /* emphasis on */ + case 0xE087: /* emphasis off */ + /* skip it */ + break; + case 0xE08A:{ + guint8 nl[] = { 0x0A, 0x00 }; // new line + g_byte_array_append (sb, nl, 2); + break; + } + default: + g_byte_array_append (sb, (guint8 *) text, 2); + break; + } + + text += 2; + } + } else { + for (i = 0; i < length; i += 2) { + guint16 code = GST_READ_UINT16_BE (text); + + switch (code) { + case 0xE086: /* emphasis on */ + case 0xE087: /* emphasis off */ + /* skip it */ + break; + case 0xE08A:{ + guint8 nl[] = { 0x0A, 0x00 }; // new line + g_byte_array_append (sb, nl, 2); + break; + } + default: + g_byte_array_append (sb, (guint8 *) text, 2); + break; + } + + text += 2; + } + } + } else { + if (length == -1) { + while (*text != '\0') { + guint8 code = (guint8) (*text); + + switch (code) { + case 0x86: /* emphasis on */ + case 0x87: /* emphasis off */ + /* skip it */ + break; + case 0x8A: + g_byte_array_append (sb, (guint8 *) "\n", 1); + break; + default: + g_byte_array_append (sb, &code, 1); + break; + } + + text++; + } + } else { + for (i = 0; i < length; i++) { + guint8 code = (guint8) (*text); + + switch (code) { + case 0x86: /* emphasis on */ + case 0x87: /* emphasis off */ + /* skip it */ + break; + case 0x8A: + g_byte_array_append (sb, (guint8 *) "\n", 1); + break; + default: + g_byte_array_append (sb, &code, 1); + break; + } + + text++; + } + } + } + + if (sb->len > 0) { + new_text = + g_convert ((gchar *) sb->data, sb->len, "utf-8", encoding, NULL, NULL, + error); + } else { + new_text = g_strdup (""); + } + + g_byte_array_free (sb, TRUE); + + return new_text; +} + +static gchar * +get_encoding_and_convert (const gchar * text, guint length) +{ + GError *error = NULL; + gchar *converted_str; + gchar *encoding; + guint start_text = 0; + gboolean is_multibyte; + + g_return_val_if_fail (text != NULL, NULL); + + if (length == 0) + return g_strdup (""); + + encoding = get_encoding (text, &start_text, &is_multibyte); + + if (encoding == NULL) { + GST_WARNING ("Could not detect encoding"); + converted_str = g_strndup (text, length); + } else { + converted_str = convert_to_utf8 (text, length - start_text, start_text, + encoding, is_multibyte, &error); + if (error != NULL) { + GST_WARNING ("Could not convert string, encoding is %s: %s", + encoding, error->message); + g_error_free (error); + error = NULL; + + /* The first part of ISO 6937 is identical to ISO 8859-9, but + * they differ in the second part. Some channels don't + * provide the first byte that indicates ISO 8859-9 encoding. + * If decoding from ISO 6937 failed, we try ISO 8859-9 here. + */ + if (strcmp (encoding, "iso6937") == 0) { + GST_INFO ("Trying encoding ISO 8859-9"); + converted_str = convert_to_utf8 (text, length, 0, + "iso8859-9", FALSE, &error); + if (error != NULL) { + GST_WARNING + ("Could not convert string while assuming encoding ISO 8859-9: %s", + error->message); + g_error_free (error); + goto failed; + } + } else { + goto failed; + } + } + + g_free (encoding); + } + + return converted_str; + +failed: + { + g_free (encoding); + text += start_text; + return g_strndup (text, length - start_text); + } +} diff --git a/gst/mpegtsdemux/mpegtspacketizer.h b/gst/mpegtsdemux/mpegtspacketizer.h new file mode 100644 index 0000000000..e0be1e09ff --- /dev/null +++ b/gst/mpegtsdemux/mpegtspacketizer.h @@ -0,0 +1,167 @@ +/* + * mpegtspacketizer.h - + * Copyright (C) 2007 Alessandro Decina + * + * Authors: + * Alessandro Decina + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef GST_MPEGTS_PACKETIZER_H +#define GST_MPEGTS_PACKETIZER_H + +#include +#include +#include + +#define MPEGTS_NORMAL_PACKETSIZE 188 +#define MPEGTS_M2TS_PACKETSIZE 192 +#define MPEGTS_DVB_ASI_PACKETSIZE 204 +#define MPEGTS_ATSC_PACKETSIZE 208 + +#define MPEGTS_MIN_PACKETSIZE MPEGTS_NORMAL_PACKETSIZE +#define MPEGTS_MAX_PACKETSIZE MPEGTS_ATSC_PACKETSIZE + +#define MPEGTS_AFC_PCR_FLAG 0x10 +#define MPEGTS_AFC_OPCR_FLAG 0x08 + +G_BEGIN_DECLS + +#define GST_TYPE_MPEGTS_PACKETIZER \ + (mpegts_packetizer_get_type()) +#define GST_MPEGTS_PACKETIZER(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_MPEGTS_PACKETIZER,MpegTSPacketizer2)) +#define GST_MPEGTS_PACKETIZER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_MPEGTS_PACKETIZER,MpegTSPacketizer2Class)) +#define GST_IS_MPEGTS_PACKETIZER(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_MPEGTS_PACKETIZER)) +#define GST_IS_MPEGTS_PACKETIZER_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_MPEGTS_PACKETIZER)) + +typedef struct _MpegTSPacketizer2 MpegTSPacketizer2; +typedef struct _MpegTSPacketizer2Class MpegTSPacketizer2Class; + +typedef struct +{ + guint continuity_counter; + GstAdapter *section_adapter; + guint8 section_table_id; + guint section_length; + GSList *subtables; + guint64 offset; +} MpegTSPacketizerStream; + +struct _MpegTSPacketizer2 { + GObject object; + + GstAdapter *adapter; + /* streams hashed by pid */ + MpegTSPacketizerStream **streams; + gboolean disposed; + gboolean know_packet_size; + guint16 packet_size; + GstCaps *caps; + + /* current offset of the tip of the adapter */ + guint64 offset; + gboolean empty; +}; + +struct _MpegTSPacketizer2Class { + GObjectClass object_class; +}; + +typedef struct +{ + GstBuffer *buffer; + gint16 pid; + guint8 payload_unit_start_indicator; + guint8 adaptation_field_control; + guint8 continuity_counter; + guint8 *payload; + + guint8 *data_start; + guint8 *data_end; + guint8 *data; + + guint8 afc_flags; + guint64 pcr; + guint64 opcr; + guint64 offset; +} MpegTSPacketizerPacket; + +typedef struct +{ + gboolean complete; + GstBuffer *buffer; + gint16 pid; + guint8 table_id; + guint16 subtable_extension; + guint section_length; + guint8 version_number; + guint8 current_next_indicator; + guint32 crc; +} MpegTSPacketizerSection; + +typedef struct +{ + guint8 table_id; + /* the spec says sub_table_extension is the fourth and fifth byte of a + * section when the section_syntax_indicator is set to a value of "1". If + * section_syntax_indicator is 0, sub_table_extension will be set to 0 */ + guint16 subtable_extension; + guint8 version_number; + guint32 crc; +} MpegTSPacketizerStreamSubtable; + +typedef enum { + PACKET_BAD = FALSE, + PACKET_OK = TRUE, + PACKET_NEED_MORE +} MpegTSPacketizerPacketReturn; + +GType mpegts_packetizer_get_type(void); + +MpegTSPacketizer2 *mpegts_packetizer_new (void); +void mpegts_packetizer_clear (MpegTSPacketizer2 *packetizer); +void mpegts_packetizer_push (MpegTSPacketizer2 *packetizer, GstBuffer *buffer); +gboolean mpegts_packetizer_has_packets (MpegTSPacketizer2 *packetizer); +MpegTSPacketizerPacketReturn mpegts_packetizer_next_packet (MpegTSPacketizer2 *packetizer, + MpegTSPacketizerPacket *packet); +void mpegts_packetizer_clear_packet (MpegTSPacketizer2 *packetizer, + MpegTSPacketizerPacket *packet); +void mpegts_packetizer_remove_stream(MpegTSPacketizer2 *packetizer, + gint16 pid); + +gboolean mpegts_packetizer_push_section (MpegTSPacketizer2 *packetzer, + MpegTSPacketizerPacket *packet, MpegTSPacketizerSection *section); +GstStructure *mpegts_packetizer_parse_pat (MpegTSPacketizer2 *packetizer, + MpegTSPacketizerSection *section); +GstStructure *mpegts_packetizer_parse_pmt (MpegTSPacketizer2 *packetizer, + MpegTSPacketizerSection *section); +GstStructure *mpegts_packetizer_parse_nit (MpegTSPacketizer2 *packetizer, + MpegTSPacketizerSection *section); +GstStructure *mpegts_packetizer_parse_sdt (MpegTSPacketizer2 *packetizer, + MpegTSPacketizerSection *section); +GstStructure *mpegts_packetizer_parse_eit (MpegTSPacketizer2 *packetizer, + MpegTSPacketizerSection *section); +GstStructure *mpegts_packetizer_parse_tdt (MpegTSPacketizer2 *packetizer, + MpegTSPacketizerSection *section); + +G_END_DECLS + +#endif /* GST_MPEGTS_PACKETIZER_H */ diff --git a/gst/mpegtsdemux/mpegtsparse.c b/gst/mpegtsdemux/mpegtsparse.c new file mode 100644 index 0000000000..ede74ae827 --- /dev/null +++ b/gst/mpegtsdemux/mpegtsparse.c @@ -0,0 +1,718 @@ +/* + * mpegtsparse.c - + * Copyright (C) 2007 Alessandro Decina + * + * Authors: + * Alessandro Decina + * Zaheer Abbas Merali + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "mpegtsbase.h" +#include "mpegtsparse.h" +#include "gstmpegdesc.h" + +/* latency in mseconds */ +#define TS_LATENCY 700 + +#define TABLE_ID_UNSET 0xFF +#define RUNNING_STATUS_RUNNING 4 + +GST_DEBUG_CATEGORY_STATIC (mpegts_parse_debug); +#define GST_CAT_DEFAULT mpegts_parse_debug + +typedef struct _MpegTSParsePad MpegTSParsePad; + +typedef struct +{ + MpegTSBaseProgram program; + gint selected; + gboolean active; + MpegTSParsePad *tspad; +} MpegTSParseProgram; + +struct _MpegTSParsePad +{ + GstPad *pad; + + /* the program number that the peer wants on this pad */ + gint program_number; + MpegTSParseProgram *program; + + /* set to FALSE before a push and TRUE after */ + gboolean pushed; + + /* the return of the latest push */ + GstFlowReturn flow_return; + + GstTagList *tags; + guint event_id; +}; + +static GstStaticPadTemplate src_template = +GST_STATIC_PAD_TEMPLATE ("src%d", GST_PAD_SRC, + GST_PAD_REQUEST, + GST_STATIC_CAPS ("video/mpegts, " "systemstream = (boolean) true ") + ); + +static GstStaticPadTemplate program_template = +GST_STATIC_PAD_TEMPLATE ("program_%d", GST_PAD_SRC, + GST_PAD_SOMETIMES, + GST_STATIC_CAPS ("video/mpegts, " "systemstream = (boolean) true ") + ); + +enum +{ + ARG_0, + PROP_PROGRAM_NUMBERS, + /* FILL ME */ +}; + +static void +mpegts_parse_program_started (MpegTSBase * base, MpegTSBaseProgram * program); +static void +mpegts_parse_program_stopped (MpegTSBase * base, MpegTSBaseProgram * program); + +static GstFlowReturn +mpegts_parse_push (MpegTSBase * base, MpegTSPacketizerPacket * packet, + MpegTSPacketizerSection * section); +static void mpegts_parse_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void mpegts_parse_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); +static void mpegts_parse_finalize (GObject * object); + +static MpegTSParsePad *mpegts_parse_create_tspad (MpegTSParse2 * parse, + const gchar * name); +static void mpegts_parse_destroy_tspad (MpegTSParse2 * parse, + MpegTSParsePad * tspad); +static GstPad *mpegts_parse_activate_program (MpegTSParse2 * parse, + MpegTSParseProgram * program); +static void mpegts_parse_reset_selected_programs (MpegTSParse2 * parse, + gchar * programs); + +static void mpegts_parse_pad_removed (GstElement * element, GstPad * pad); +static GstPad *mpegts_parse_request_new_pad (GstElement * element, + GstPadTemplate * templ, const gchar * name); +static void mpegts_parse_release_pad (GstElement * element, GstPad * pad); +static gboolean mpegts_parse_src_pad_query (GstPad * pad, GstQuery * query); +static gboolean push_event (MpegTSBase * base, GstEvent * event); + +GST_BOILERPLATE (MpegTSParse2, mpegts_parse, MpegTSBase, GST_TYPE_MPEGTS_BASE); + +static void +mpegts_parse_base_init (gpointer klass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&src_template)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&program_template)); + + gst_element_class_set_details_simple (element_class, + "MPEG transport stream parser", "Codec/Parser", + "Parses MPEG2 transport streams", + "Alessandro Decina , " + "Zaheer Abbas Merali "); +} + +static void +mpegts_parse_class_init (MpegTSParse2Class * klass) +{ + GObjectClass *gobject_class; + GstElementClass *element_class; + MpegTSBaseClass *ts_class; + + element_class = GST_ELEMENT_CLASS (klass); + element_class->pad_removed = mpegts_parse_pad_removed; + element_class->request_new_pad = mpegts_parse_request_new_pad; + element_class->release_pad = mpegts_parse_release_pad; + + gobject_class = G_OBJECT_CLASS (klass); + gobject_class->set_property = mpegts_parse_set_property; + gobject_class->get_property = mpegts_parse_get_property; + gobject_class->finalize = mpegts_parse_finalize; + + g_object_class_install_property (gobject_class, PROP_PROGRAM_NUMBERS, + g_param_spec_string ("program-numbers", + "Program Numbers", + "Colon separated list of programs", "", + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + ts_class = GST_MPEGTS_BASE_CLASS (klass); + ts_class->push = GST_DEBUG_FUNCPTR (mpegts_parse_push); + ts_class->push_event = GST_DEBUG_FUNCPTR (push_event); + ts_class->program_started = GST_DEBUG_FUNCPTR (mpegts_parse_program_started); + ts_class->program_stopped = GST_DEBUG_FUNCPTR (mpegts_parse_program_stopped); +} + +static void +mpegts_parse_init (MpegTSParse2 * parse, MpegTSParse2Class * klass) +{ + parse->need_sync_program_pads = FALSE; + parse->program_numbers = g_strdup (""); + parse->pads_to_add = NULL; + parse->pads_to_remove = NULL; + GST_MPEGTS_BASE (parse)->program_size = sizeof (MpegTSParseProgram); +} + +static void +mpegts_parse_finalize (GObject * object) +{ + MpegTSParse2 *parse = GST_MPEGTS_PARSE (object); + + g_free (parse->program_numbers); + + if (G_OBJECT_CLASS (parent_class)->finalize) + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static void +mpegts_parse_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + MpegTSParse2 *parse = GST_MPEGTS_PARSE (object); + + switch (prop_id) { + case PROP_PROGRAM_NUMBERS: + mpegts_parse_reset_selected_programs (parse, g_value_dup_string (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +mpegts_parse_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + MpegTSParse2 *parse = GST_MPEGTS_PARSE (object); + + switch (prop_id) { + case PROP_PROGRAM_NUMBERS: + g_value_set_string (value, parse->program_numbers); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static GstPad * +mpegts_parse_activate_program (MpegTSParse2 * parse, + MpegTSParseProgram * program) +{ + MpegTSParsePad *tspad; + gchar *pad_name; + + pad_name = + g_strdup_printf ("program_%d", + ((MpegTSBaseProgram *) program)->program_number); + + tspad = mpegts_parse_create_tspad (parse, pad_name); + tspad->program_number = ((MpegTSBaseProgram *) program)->program_number; + tspad->program = program; + program->tspad = tspad; + g_free (pad_name); + gst_pad_set_active (tspad->pad, TRUE); + program->active = TRUE; + + return tspad->pad; +} + +static gboolean +push_event (MpegTSBase * base, GstEvent * event) +{ + MpegTSParse2 *parse = (MpegTSParse2 *) base; + GList *tmp; + + for (tmp = GST_ELEMENT_CAST (parse)->srcpads; tmp; tmp = tmp->next) { + GstPad *pad = (GstPad *) tmp->data; + if (pad) { + gst_event_ref (event); + gst_pad_push_event (pad, event); + } + } + return TRUE; +} + +static GstPad * +mpegts_parse_deactivate_program (MpegTSParse2 * parse, + MpegTSParseProgram * program) +{ + MpegTSParsePad *tspad; + + tspad = program->tspad; + gst_pad_set_active (tspad->pad, FALSE); + program->active = FALSE; + + /* tspad will be destroyed in GstElementClass::pad_removed */ + + return tspad->pad; +} + +static void +mpegts_parse_sync_program_pads (MpegTSParse2 * parse) +{ + GList *walk; + + GST_INFO_OBJECT (parse, "begin sync pads"); + for (walk = parse->pads_to_remove; walk; walk = walk->next) + gst_element_remove_pad (GST_ELEMENT (parse), GST_PAD (walk->data)); + + for (walk = parse->pads_to_add; walk; walk = walk->next) + gst_element_add_pad (GST_ELEMENT (parse), GST_PAD (walk->data)); + + if (parse->pads_to_add) + g_list_free (parse->pads_to_add); + + if (parse->pads_to_remove) + g_list_free (parse->pads_to_remove); + + GST_OBJECT_LOCK (parse); + parse->pads_to_remove = NULL; + parse->pads_to_add = NULL; + parse->need_sync_program_pads = FALSE; + GST_OBJECT_UNLOCK (parse); + + GST_INFO_OBJECT (parse, "end sync pads"); +} + +static void +foreach_program_activate_or_deactivate (gpointer key, gpointer value, + gpointer data) +{ + MpegTSParse2 *parse = GST_MPEGTS_PARSE (data); + MpegTSParseProgram *program = (MpegTSParseProgram *) value; + + /* at this point selected programs have program->selected == 2, + * unselected programs thay may have to be deactivated have selected == 1 and + * unselected inactive programs have selected == 0 */ + + switch (--program->selected) { + case 1: + /* selected */ + if (!program->active + && ((MpegTSBaseProgram *) program)->pmt_pid != G_MAXUINT16) + parse->pads_to_add = + g_list_append (parse->pads_to_add, + mpegts_parse_activate_program (parse, program)); + else { + program->selected = 2; + } + break; + case 0: + /* unselected */ + if (program->active) + parse->pads_to_remove = g_list_append (parse->pads_to_remove, + mpegts_parse_deactivate_program (parse, program)); + break; + case -1: + /* was already unselected */ + program->selected = 0; + break; + default: + g_return_if_reached (); + } +} + +static void +mpegts_parse_reset_selected_programs (MpegTSParse2 * parse, + gchar * program_numbers) +{ + GST_OBJECT_LOCK (parse); + if (parse->program_numbers) + g_free (parse->program_numbers); + + parse->program_numbers = program_numbers; + + if (*parse->program_numbers != '\0') { + gint program_number; + MpegTSParseProgram *program; + gchar **progs, **walk; + + progs = g_strsplit (parse->program_numbers, ":", 0); + + walk = progs; + while (*walk != NULL) { + program_number = strtol (*walk, NULL, 0); + program = + (MpegTSParseProgram *) mpegts_base_get_program ((MpegTSBase *) parse, + program_number); + if (program == NULL) + /* create the program, it will get activated once we get a PMT for it */ + program = (MpegTSParseProgram *) mpegts_base_add_program ((MpegTSBase *) + parse, program_number, G_MAXUINT16); + program->selected = 2; + ++walk; + } + g_strfreev (progs); + } + + g_hash_table_foreach (((MpegTSBase *) parse)->programs, + foreach_program_activate_or_deactivate, parse); + + if (parse->pads_to_remove || parse->pads_to_add) + parse->need_sync_program_pads = TRUE; + GST_OBJECT_UNLOCK (parse); +} + + +static MpegTSParsePad * +mpegts_parse_create_tspad (MpegTSParse2 * parse, const gchar * pad_name) +{ + GstPad *pad; + MpegTSParsePad *tspad; + + pad = gst_pad_new_from_static_template (&program_template, pad_name); + gst_pad_set_query_function (pad, + GST_DEBUG_FUNCPTR (mpegts_parse_src_pad_query)); + + /* create our wrapper */ + tspad = g_new0 (MpegTSParsePad, 1); + tspad->pad = pad; + tspad->program_number = -1; + tspad->program = NULL; + tspad->pushed = FALSE; + tspad->flow_return = GST_FLOW_NOT_LINKED; + gst_pad_set_element_private (pad, tspad); + + return tspad; +} + +static void +mpegts_parse_destroy_tspad (MpegTSParse2 * parse, MpegTSParsePad * tspad) +{ + if (tspad->tags) { + gst_tag_list_free (tspad->tags); + } + + /* free the wrapper */ + g_free (tspad); +} + +static void +mpegts_parse_pad_removed (GstElement * element, GstPad * pad) +{ + MpegTSParsePad *tspad; + MpegTSParse2 *parse = GST_MPEGTS_PARSE (element); + + if (gst_pad_get_direction (pad) == GST_PAD_SINK) + return; + + tspad = (MpegTSParsePad *) gst_pad_get_element_private (pad); + mpegts_parse_destroy_tspad (parse, tspad); + + if (GST_ELEMENT_CLASS (parent_class)->pad_removed) + GST_ELEMENT_CLASS (parent_class)->pad_removed (element, pad); +} + +static GstPad * +mpegts_parse_request_new_pad (GstElement * element, GstPadTemplate * template, + const gchar * unused) +{ + MpegTSParse2 *parse; + gchar *name; + GstPad *pad; + + g_return_val_if_fail (template != NULL, NULL); + g_return_val_if_fail (GST_IS_MPEGTS_PARSE (element), NULL); + + parse = GST_MPEGTS_PARSE (element); + + GST_OBJECT_LOCK (element); + name = g_strdup_printf ("src%d", parse->req_pads++); + GST_OBJECT_UNLOCK (element); + + pad = mpegts_parse_create_tspad (parse, name)->pad; + gst_pad_set_active (pad, TRUE); + gst_element_add_pad (element, pad); + g_free (name); + + return pad; +} + +static void +mpegts_parse_release_pad (GstElement * element, GstPad * pad) +{ + g_return_if_fail (GST_IS_MPEGTS_PARSE (element)); + + gst_pad_set_active (pad, FALSE); + /* we do the cleanup in GstElement::pad-removed */ + gst_element_remove_pad (element, pad); +} + +static GstFlowReturn +mpegts_parse_tspad_push_section (MpegTSParse2 * parse, MpegTSParsePad * tspad, + MpegTSPacketizerSection * section, GstBuffer * buffer) +{ + GstFlowReturn ret = GST_FLOW_NOT_LINKED; + gboolean to_push = TRUE; + + if (tspad->program_number != -1) { + if (tspad->program) { + /* we push all sections to all pads except PMTs which we + * only push to pads meant to receive that program number */ + if (section->table_id == 0x02) { + /* PMT */ + if (section->subtable_extension != tspad->program_number) + to_push = FALSE; + } + } else { + /* there's a program filter on the pad but the PMT for the program has not + * been parsed yet, ignore the pad until we get a PMT */ + to_push = FALSE; + ret = GST_FLOW_OK; + } + } + GST_DEBUG_OBJECT (parse, + "pushing section: %d program number: %d table_id: %d", to_push, + tspad->program_number, section->table_id); + if (to_push) { + ret = gst_pad_push (tspad->pad, buffer); + } else { + gst_buffer_unref (buffer); + if (gst_pad_is_linked (tspad->pad)) + ret = GST_FLOW_OK; + } + + return ret; +} + +static GstFlowReturn +mpegts_parse_tspad_push (MpegTSParse2 * parse, MpegTSParsePad * tspad, + guint16 pid, GstBuffer * buffer) +{ + GstFlowReturn ret = GST_FLOW_NOT_LINKED; + MpegTSBaseStream **pad_pids = NULL; + + if (tspad->program_number != -1) { + if (tspad->program) { + MpegTSBaseProgram *bp = (MpegTSBaseProgram *) tspad->program; + pad_pids = bp->streams; + if (bp->tags) { + gst_element_found_tags_for_pad (GST_ELEMENT_CAST (parse), tspad->pad, + bp->tags); + bp->tags = NULL; + } + } else { + /* there's a program filter on the pad but the PMT for the program has not + * been parsed yet, ignore the pad until we get a PMT */ + gst_buffer_unref (buffer); + ret = GST_FLOW_OK; + goto out; + } + } + + if (pad_pids == NULL || pad_pids[pid]) { + /* push if there's no filter or if the pid is in the filter */ + ret = gst_pad_push (tspad->pad, buffer); + } else { + gst_buffer_unref (buffer); + if (gst_pad_is_linked (tspad->pad)) + ret = GST_FLOW_OK; + } + +out: + return ret; +} + +static void +pad_clear_for_push (GstPad * pad, MpegTSParse2 * parse) +{ + MpegTSParsePad *tspad = (MpegTSParsePad *) gst_pad_get_element_private (pad); + + tspad->flow_return = GST_FLOW_NOT_LINKED; + tspad->pushed = FALSE; +} + +static GstFlowReturn +mpegts_parse_push (MpegTSBase * base, MpegTSPacketizerPacket * packet, + MpegTSPacketizerSection * section) +{ + MpegTSParse2 *parse = (MpegTSParse2 *) base; + guint32 pads_cookie; + gboolean done = FALSE; + GstPad *pad = NULL; + MpegTSParsePad *tspad; + guint16 pid; + GstBuffer *buffer; + GstFlowReturn ret; + GList *srcpads; + + if (G_UNLIKELY (parse->need_sync_program_pads)) + mpegts_parse_sync_program_pads (parse); + + pid = packet->pid; + buffer = gst_buffer_make_metadata_writable (packet->buffer); + /* we have the same caps on all the src pads */ + gst_buffer_set_caps (buffer, base->packetizer->caps); + + GST_OBJECT_LOCK (parse); + /* clear tspad->pushed on pads */ + g_list_foreach (GST_ELEMENT_CAST (parse)->srcpads, + (GFunc) pad_clear_for_push, parse); + if (GST_ELEMENT_CAST (parse)->srcpads) + ret = GST_FLOW_NOT_LINKED; + else + ret = GST_FLOW_OK; + + /* Get cookie and source pads list */ + pads_cookie = GST_ELEMENT_CAST (parse)->pads_cookie; + srcpads = GST_ELEMENT_CAST (parse)->srcpads; + if (G_LIKELY (srcpads)) { + pad = GST_PAD_CAST (srcpads->data); + g_object_ref (pad); + } + GST_OBJECT_UNLOCK (parse); + + while (pad && !done) { + tspad = gst_pad_get_element_private (pad); + + if (G_LIKELY (!tspad->pushed)) { + /* ref the buffer as gst_pad_push takes a ref but we want to reuse the + * same buffer for next pushes */ + gst_buffer_ref (buffer); + if (section) { + tspad->flow_return = + mpegts_parse_tspad_push_section (parse, tspad, section, buffer); + } else { + tspad->flow_return = + mpegts_parse_tspad_push (parse, tspad, pid, buffer); + } + tspad->pushed = TRUE; + + if (G_UNLIKELY (tspad->flow_return != GST_FLOW_OK + && tspad->flow_return != GST_FLOW_NOT_LINKED)) { + /* return the error upstream */ + ret = tspad->flow_return; + done = TRUE; + } + + } + + if (ret == GST_FLOW_NOT_LINKED) + ret = tspad->flow_return; + + g_object_unref (pad); + + if (G_UNLIKELY (!done)) { + GST_OBJECT_LOCK (parse); + if (G_UNLIKELY (pads_cookie != GST_ELEMENT_CAST (parse)->pads_cookie)) { + /* resync */ + GST_DEBUG ("resync"); + pads_cookie = GST_ELEMENT_CAST (parse)->pads_cookie; + srcpads = GST_ELEMENT_CAST (parse)->srcpads; + } else { + GST_DEBUG ("getting next pad"); + /* Get next pad */ + srcpads = g_list_next (srcpads); + } + + if (srcpads) { + pad = GST_PAD_CAST (srcpads->data); + g_object_ref (pad); + } else + done = TRUE; + GST_OBJECT_UNLOCK (parse); + } + } + + gst_buffer_unref (buffer); + packet->buffer = NULL; + + return ret; +} + +static void +mpegts_parse_program_started (MpegTSBase * base, MpegTSBaseProgram * program) +{ + MpegTSParse2 *parse = GST_MPEGTS_PARSE (base); + MpegTSParseProgram *parseprogram = (MpegTSParseProgram *) program; + if (parseprogram->selected == 2) { + parse->pads_to_add = + g_list_append (parse->pads_to_add, + mpegts_parse_activate_program (parse, parseprogram)); + parseprogram->selected = 1; + parse->need_sync_program_pads = TRUE; + } + +} + +static void +mpegts_parse_program_stopped (MpegTSBase * base, MpegTSBaseProgram * program) +{ + MpegTSParse2 *parse = GST_MPEGTS_PARSE (base); + MpegTSParseProgram *parseprogram = (MpegTSParseProgram *) program; + + if (parseprogram->active) { + parse->pads_to_remove = + g_list_append (parse->pads_to_remove, + mpegts_parse_deactivate_program (parse, parseprogram)); + parse->need_sync_program_pads = TRUE; + } +} + +static gboolean +mpegts_parse_src_pad_query (GstPad * pad, GstQuery * query) +{ + MpegTSParse2 *parse = GST_MPEGTS_PARSE (gst_pad_get_parent (pad)); + gboolean res; + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_LATENCY: + { + if ((res = gst_pad_peer_query (((MpegTSBase *) parse)->sinkpad, query))) { + gboolean is_live; + GstClockTime min_latency, max_latency; + + gst_query_parse_latency (query, &is_live, &min_latency, &max_latency); + if (is_live) { + min_latency += TS_LATENCY * GST_MSECOND; + if (max_latency != GST_CLOCK_TIME_NONE) + max_latency += TS_LATENCY * GST_MSECOND; + } + + gst_query_set_latency (query, is_live, min_latency, max_latency); + } + + break; + } + default: + res = gst_pad_query_default (pad, query); + } + gst_object_unref (parse); + return res; +} + +gboolean +gst_mpegtsparse_plugin_init (GstPlugin * plugin) +{ + GST_DEBUG_CATEGORY_INIT (mpegts_parse_debug, "tsparse", 0, + "MPEG transport stream parser"); + + gst_mpegtsdesc_init_debug (); + + return gst_element_register (plugin, "tsparse", + GST_RANK_NONE, GST_TYPE_MPEGTS_PARSE); +} diff --git a/gst/mpegtsdemux/mpegtsparse.h b/gst/mpegtsdemux/mpegtsparse.h new file mode 100644 index 0000000000..ef722dd5e4 --- /dev/null +++ b/gst/mpegtsdemux/mpegtsparse.h @@ -0,0 +1,71 @@ +/* + * mpegts_parse.h - GStreamer MPEG transport stream parser + * Copyright (C) 2007 Alessandro Decina + * + * Authors: + * Alessandro Decina + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef GST_MPEG_TS_PARSE_H +#define GST_MPEG_TS_PARSE_H + +#include +#include "mpegtsbase.h" +#include "mpegtspacketizer.h" + +G_BEGIN_DECLS + +#define GST_TYPE_MPEGTS_PARSE \ + (mpegts_parse_get_type()) +#define GST_MPEGTS_PARSE(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_MPEGTS_PARSE,MpegTSParse2)) +#define GST_MPEGTS_PARSE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_MPEGTS_PARSE,MpegTSParse2Class)) +#define GST_IS_MPEGTS_PARSE(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_MPEGTS_PARSE)) +#define GST_IS_MPEGTS_PARSE_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_MPEGTS_PARSE)) + +typedef struct _MpegTSParse2 MpegTSParse2; +typedef struct _MpegTSParse2Class MpegTSParse2Class; + +struct _MpegTSParse2 { + MpegTSBase parent; + + /* the following vars must be protected with the OBJECT_LOCK as they can be + * accessed from the application thread and the streaming thread */ + gchar *program_numbers; + GList *pads_to_add; + GList *pads_to_remove; + guint req_pads; + + gboolean need_sync_program_pads; +}; + +struct _MpegTSParse2Class { + MpegTSBaseClass parent_class; +}; + +GType mpegts_parse_get_type(void); + +gboolean gst_mpegtsparse_plugin_init (GstPlugin * plugin); + +G_END_DECLS + +#endif /* GST_MPEG_TS_PARSE_H */ diff --git a/gst/mpegtsdemux/tsdemux.c b/gst/mpegtsdemux/tsdemux.c new file mode 100644 index 0000000000..97dd3802bf --- /dev/null +++ b/gst/mpegtsdemux/tsdemux.c @@ -0,0 +1,1491 @@ +/* + * tsdemux.c + * Copyright (C) 2009 Zaheer Abbas Merali + * 2010 Edward Hervey + * + * Authors: + * Zaheer Abbas Merali + * Edward Hervey + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include "mpegtsbase.h" +#include "tsdemux.h" +#include "gstmpegdesc.h" +#include "gstmpegdefs.h" +#include "mpegtspacketizer.h" + +/* latency in mseconds */ +#define TS_LATENCY 700 + +#define TABLE_ID_UNSET 0xFF + +/* Size of the pendingbuffers array. */ +#define TS_MAX_PENDING_BUFFERS 256 + +GST_DEBUG_CATEGORY_STATIC (ts_demux_debug); +#define GST_CAT_DEFAULT ts_demux_debug + +static GQuark QUARK_TSDEMUX; +static GQuark QUARK_PID; +static GQuark QUARK_PCR; +static GQuark QUARK_OPCR; +static GQuark QUARK_PTS; +static GQuark QUARK_DTS; +static GQuark QUARK_OFFSET; + + + +typedef enum +{ + PENDING_PACKET_EMPTY = 0, /* No pending packet/buffer + * Push incoming buffers to the array */ + PENDING_PACKET_HEADER, /* PES header needs to be parsed + * Push incoming buffers to the array */ + PENDING_PACKET_BUFFER, /* Currently filling up output buffer + * Push incoming buffers to the bufferlist */ + PENDING_PACKET_DISCONT /* Discontinuity in incoming packets + * Drop all incoming buffers */ +} PendingPacketState; + +typedef struct _TSDemuxStream TSDemuxStream; + +struct _TSDemuxStream +{ + MpegTSBaseStream stream; + + GstPad *pad; + + /* set to FALSE before a push and TRUE after */ + gboolean pushed; + + /* the return of the latest push */ + GstFlowReturn flow_return; + + /* Output data */ + PendingPacketState state; + /* Pending buffers array. */ + /* These buffers are stored in this array until the PES header (if needed) + * is succesfully parsed. */ + GstBuffer *pendingbuffers[TS_MAX_PENDING_BUFFERS]; + guint8 nbpending; + + /* Current data to be pushed out */ + GstBufferList *current; + GstBufferListIterator *currentit; + GList *currentlist; + + GstClockTime pts; +}; + +#define VIDEO_CAPS \ + GST_STATIC_CAPS (\ + "video/mpeg, " \ + "mpegversion = (int) { 1, 2, 4 }, " \ + "systemstream = (boolean) FALSE; " \ + "video/x-h264;" \ + "video/x-dirac;" \ + "video/x-wmv," \ + "wmvversion = (int) 3, " \ + "format = (fourcc) WVC1" \ + ) + +#define AUDIO_CAPS \ + GST_STATIC_CAPS ( \ + "audio/mpeg, " \ + "mpegversion = (int) { 1, 4 };" \ + "audio/x-lpcm, " \ + "width = (int) { 16, 20, 24 }, " \ + "rate = (int) { 48000, 96000 }, " \ + "channels = (int) [ 1, 8 ], " \ + "dynamic_range = (int) [ 0, 255 ], " \ + "emphasis = (boolean) { FALSE, TRUE }, " \ + "mute = (boolean) { FALSE, TRUE }; " \ + "audio/x-ac3; audio/x-eac3;" \ + "audio/x-dts;" \ + "audio/x-private-ts-lpcm" \ + ) + +/* Can also use the subpicture pads for text subtitles? */ +#define SUBPICTURE_CAPS \ + GST_STATIC_CAPS ("subpicture/x-pgs; video/x-dvd-subpicture") + +static GstStaticPadTemplate video_template = +GST_STATIC_PAD_TEMPLATE ("video_%04x", GST_PAD_SRC, + GST_PAD_SOMETIMES, + VIDEO_CAPS); + +static GstStaticPadTemplate audio_template = +GST_STATIC_PAD_TEMPLATE ("audio_%04x", + GST_PAD_SRC, + GST_PAD_SOMETIMES, + AUDIO_CAPS); + +static GstStaticPadTemplate subpicture_template = +GST_STATIC_PAD_TEMPLATE ("subpicture_%04x", + GST_PAD_SRC, + GST_PAD_SOMETIMES, + SUBPICTURE_CAPS); + +static GstStaticPadTemplate private_template = +GST_STATIC_PAD_TEMPLATE ("private_%04x", + GST_PAD_SRC, + GST_PAD_SOMETIMES, + GST_STATIC_CAPS_ANY); + +enum +{ + ARG_0, + PROP_PROGRAM_NUMBER, + PROP_EMIT_STATS, + /* FILL ME */ +}; + +/* Pad functions */ +static const GstQueryType *gst_ts_demux_srcpad_query_types (GstPad * pad); +static gboolean gst_ts_demux_srcpad_query (GstPad * pad, GstQuery * query); + + +/* mpegtsbase methods */ +static void +gst_ts_demux_program_started (MpegTSBase * base, MpegTSBaseProgram * program); +static void +gst_ts_demux_program_stopped (MpegTSBase * base, MpegTSBaseProgram * program); +static GstFlowReturn +gst_ts_demux_push (MpegTSBase * base, MpegTSPacketizerPacket * packet, + MpegTSPacketizerSection * section); +static void +gst_ts_demux_stream_added (MpegTSBase * base, MpegTSBaseStream * stream, + MpegTSBaseProgram * program); +static void +gst_ts_demux_stream_removed (MpegTSBase * base, MpegTSBaseStream * stream); +static GstFlowReturn +find_timestamps (MpegTSBase * base, guint64 initoff, guint64 * offset); +static void gst_ts_demux_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec); +static void gst_ts_demux_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec); +static void gst_ts_demux_finalize (GObject * object); +static GstFlowReturn +process_pcr (MpegTSBase * base, guint64 initoff, GstClockTime * pcr, + guint numpcr, gboolean isinitial); +static gboolean push_event (MpegTSBase * base, GstEvent * event); +static void _extra_init (GType type); + +GST_BOILERPLATE_FULL (GstTSDemux, gst_ts_demux, MpegTSBase, + GST_TYPE_MPEGTS_BASE, _extra_init); + +static void +_extra_init (GType type) +{ + QUARK_TSDEMUX = g_quark_from_string ("tsdemux"); + QUARK_PID = g_quark_from_string ("pid"); + QUARK_PCR = g_quark_from_string ("pcr"); + QUARK_OPCR = g_quark_from_string ("opcr"); + QUARK_PTS = g_quark_from_string ("pts"); + QUARK_DTS = g_quark_from_string ("dts"); + QUARK_OFFSET = g_quark_from_string ("offset"); +} + +static void +gst_ts_demux_base_init (gpointer klass) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (klass); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&video_template)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&audio_template)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&subpicture_template)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&private_template)); + + gst_element_class_set_details_simple (element_class, + "MPEG transport stream demuxer", + "Codec/Demuxer", + "Demuxes MPEG2 transport streams", + "Zaheer Abbas Merali ;" + " Edward Hervey "); +} + +static void +gst_ts_demux_class_init (GstTSDemuxClass * klass) +{ + GObjectClass *gobject_class; + MpegTSBaseClass *ts_class; + + gobject_class = G_OBJECT_CLASS (klass); + gobject_class->set_property = gst_ts_demux_set_property; + gobject_class->get_property = gst_ts_demux_get_property; + gobject_class->finalize = gst_ts_demux_finalize; + + g_object_class_install_property (gobject_class, PROP_PROGRAM_NUMBER, + g_param_spec_int ("program-number", "Program number", + "Program Number to demux for (-1 to ignore)", -1, G_MAXINT, + -1, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + g_object_class_install_property (gobject_class, PROP_EMIT_STATS, + g_param_spec_boolean ("emit-stats", "Emit statistics", + "Emit messages for every pcr/opcr/pts/dts", FALSE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + + + ts_class = GST_MPEGTS_BASE_CLASS (klass); + ts_class->push = GST_DEBUG_FUNCPTR (gst_ts_demux_push); + ts_class->push_event = GST_DEBUG_FUNCPTR (push_event); + ts_class->program_started = GST_DEBUG_FUNCPTR (gst_ts_demux_program_started); + ts_class->program_stopped = GST_DEBUG_FUNCPTR (gst_ts_demux_program_stopped); + ts_class->stream_added = gst_ts_demux_stream_added; + ts_class->stream_removed = gst_ts_demux_stream_removed; + ts_class->find_timestamps = GST_DEBUG_FUNCPTR (find_timestamps); +} + +static void +gst_ts_demux_init (GstTSDemux * demux, GstTSDemuxClass * klass) +{ + demux->need_newsegment = TRUE; + demux->program_number = -1; + demux->duration = GST_CLOCK_TIME_NONE; + GST_MPEGTS_BASE (demux)->stream_size = sizeof (TSDemuxStream); +} + +static void +gst_ts_demux_finalize (GObject * object) +{ + if (G_OBJECT_CLASS (parent_class)->finalize) + G_OBJECT_CLASS (parent_class)->finalize (object); +} + + + +static void +gst_ts_demux_set_property (GObject * object, guint prop_id, + const GValue * value, GParamSpec * pspec) +{ + GstTSDemux *demux = GST_TS_DEMUX (object); + + switch (prop_id) { + case PROP_PROGRAM_NUMBER: + /* FIXME: do something if program is switched as opposed to set at + * beginning */ + demux->program_number = g_value_get_int (value); + break; + case PROP_EMIT_STATS: + demux->emit_statistics = g_value_get_boolean (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static void +gst_ts_demux_get_property (GObject * object, guint prop_id, + GValue * value, GParamSpec * pspec) +{ + GstTSDemux *demux = GST_TS_DEMUX (object); + + switch (prop_id) { + case PROP_PROGRAM_NUMBER: + g_value_set_int (value, demux->program_number); + break; + case PROP_EMIT_STATS: + g_value_set_boolean (value, demux->emit_statistics); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + } +} + +static const GstQueryType * +gst_ts_demux_srcpad_query_types (GstPad * pad) +{ + static const GstQueryType query_types[] = { + GST_QUERY_DURATION, + 0 + }; + + return query_types; +} + +static gboolean +gst_ts_demux_srcpad_query (GstPad * pad, GstQuery * query) +{ + gboolean res = TRUE; + GstTSDemux *demux; + + demux = GST_TS_DEMUX (gst_pad_get_parent (pad)); + + switch (GST_QUERY_TYPE (query)) { + case GST_QUERY_DURATION: + { + GstFormat format; + + gst_query_parse_duration (query, &format, NULL); + /* can only get position in time */ + if (format != GST_FORMAT_TIME) + goto wrong_format; + + gst_query_set_duration (query, GST_FORMAT_TIME, demux->duration); + break; + } + default: + res = gst_pad_query_default (pad, query); + break; + } + +done: + gst_object_unref (demux); + return res; + +wrong_format: + { + GST_DEBUG_OBJECT (demux, "only query duration on TIME is supported"); + res = FALSE; + goto done; + } +} + + +static gboolean +push_event (MpegTSBase * base, GstEvent * event) +{ + GstTSDemux *demux = (GstTSDemux *) base; + guint i; + + if (G_UNLIKELY (demux->program == NULL)) + return FALSE; + + for (i = 0; i < 0x2000; i++) { + if (demux->program->streams[i]) { + if (((TSDemuxStream *) demux->program->streams[i])->pad) { + gst_event_ref (event); + gst_pad_push_event (((TSDemuxStream *) demux->program->streams[i])->pad, + event); + } + } + } + + return TRUE; +} + +static GstFlowReturn +tsdemux_combine_flows (GstTSDemux * demux, TSDemuxStream * stream, + GstFlowReturn ret) +{ + guint i; + + /* Store the value */ + stream->flow_return = ret; + + /* any other error that is not-linked can be returned right away */ + if (ret != GST_FLOW_NOT_LINKED) + goto done; + + /* Only return NOT_LINKED if all other pads returned NOT_LINKED */ + for (i = 0; i < 0x2000; i++) { + if (demux->program->streams[i]) { + stream = (TSDemuxStream *) demux->program->streams[i]; + if (stream->pad) { + ret = stream->flow_return; + /* some other return value (must be SUCCESS but we can return + * other values as well) */ + if (ret != GST_FLOW_NOT_LINKED) + goto done; + } + } + /* if we get here, all other pads were unlinked and we return + * NOT_LINKED then */ + } + +done: + return ret; +} + +static GstPad * +create_pad_for_stream (GstTSDemux * demux, MpegTSBaseStream * bstream, + MpegTSBaseProgram * program) +{ + TSDemuxStream *stream = (TSDemuxStream *) bstream; + gchar *name = NULL; + GstCaps *caps = NULL; + GstPadTemplate *template = NULL; + guint8 *desc = NULL; + GstPad *pad = NULL; + + + GST_LOG ("Attempting to create pad for stream 0x%04x with stream_type %d", + bstream->pid, bstream->stream_type); + + switch (bstream->stream_type) { + case ST_VIDEO_MPEG1: + case ST_VIDEO_MPEG2: + GST_LOG ("mpeg video"); + template = gst_static_pad_template_get (&video_template); + name = g_strdup_printf ("video_%04x", bstream->pid); + caps = gst_caps_new_simple ("video/mpeg", + "mpegversion", G_TYPE_INT, + bstream->stream_type == ST_VIDEO_MPEG1 ? 1 : 2, "systemstream", + G_TYPE_BOOLEAN, FALSE, NULL); + + break; + case ST_AUDIO_MPEG1: + case ST_AUDIO_MPEG2: + GST_LOG ("mpeg audio"); + template = gst_static_pad_template_get (&audio_template); + name = g_strdup_printf ("audio_%04x", bstream->pid); + caps = + gst_caps_new_simple ("audio/mpeg", "mpegversion", G_TYPE_INT, 1, + NULL); + break; + case ST_PRIVATE_DATA: + GST_LOG ("private data"); + desc = + mpegts_get_descriptor_from_stream ((MpegTSBaseStream *) stream, + DESC_DVB_AC3); + if (desc) { + GST_LOG ("ac3 audio"); + template = gst_static_pad_template_get (&audio_template); + name = g_strdup_printf ("audio_%04x", bstream->pid); + caps = gst_caps_new_simple ("audio/x-ac3", NULL); + g_free (desc); + break; + } + desc = + mpegts_get_descriptor_from_stream ((MpegTSBaseStream *) stream, + DESC_DVB_ENHANCED_AC3); + if (desc) { + GST_LOG ("ac3 audio"); + template = gst_static_pad_template_get (&audio_template); + name = g_strdup_printf ("audio_%04x", bstream->pid); + caps = gst_caps_new_simple ("audio/x-eac3", NULL); + g_free (desc); + break; + } + desc = + mpegts_get_descriptor_from_stream ((MpegTSBaseStream *) stream, + DESC_DVB_TELETEXT); + if (desc) { + GST_LOG ("teletext"); + template = gst_static_pad_template_get (&private_template); + name = g_strdup_printf ("private_%04x", bstream->pid); + caps = gst_caps_new_simple ("private/teletext", NULL); + g_free (desc); + break; + } + desc = + mpegts_get_descriptor_from_stream ((MpegTSBaseStream *) stream, + DESC_DVB_SUBTITLING); + if (desc) { + GST_LOG ("subtitling"); + template = gst_static_pad_template_get (&private_template); + name = g_strdup_printf ("private_%04x", bstream->pid); + caps = gst_caps_new_simple ("subpicture/x-dvb", NULL); + g_free (desc); + } + /* hack for itv hd (sid 10510, video pid 3401 */ + if (program->program_number == 10510 && bstream->pid == 3401) { + template = gst_static_pad_template_get (&video_template); + name = g_strdup_printf ("video_%04x", bstream->pid); + caps = gst_caps_new_simple ("video/x-h264", NULL); + } + break; + case ST_HDV_AUX_V: + /* We don't expose those streams since they're only helper streams */ + /* template = gst_static_pad_template_get (&private_template); */ + /* name = g_strdup_printf ("private_%04x", bstream->pid); */ + /* caps = gst_caps_new_simple ("hdv/aux-v", NULL); */ + break; + case ST_HDV_AUX_A: + /* We don't expose those streams since they're only helper streams */ + /* template = gst_static_pad_template_get (&private_template); */ + /* name = g_strdup_printf ("private_%04x", bstream->pid); */ + /* caps = gst_caps_new_simple ("hdv/aux-a", NULL); */ + break; + case ST_PRIVATE_SECTIONS: + case ST_MHEG: + case ST_DSMCC: + break; + case ST_AUDIO_AAC: + template = gst_static_pad_template_get (&audio_template); + name = g_strdup_printf ("audio_%04x", bstream->pid); + caps = gst_caps_new_simple ("audio/mpeg", + "mpegversion", G_TYPE_INT, 4, NULL); + break; + case ST_VIDEO_MPEG4: + template = gst_static_pad_template_get (&video_template); + name = g_strdup_printf ("video_%04x", bstream->pid); + caps = gst_caps_new_simple ("video/mpeg", + "mpegversion", G_TYPE_INT, 4, + "systemstream", G_TYPE_BOOLEAN, FALSE, NULL); + break; + case ST_VIDEO_H264: + template = gst_static_pad_template_get (&video_template); + name = g_strdup_printf ("video_%04x", bstream->pid); + caps = gst_caps_new_simple ("video/x-h264", NULL); + break; + case ST_VIDEO_DIRAC: + desc = + mpegts_get_descriptor_from_stream ((MpegTSBaseStream *) stream, + DESC_REGISTRATION); + if (desc) { + if (DESC_LENGTH (desc) >= 4) { + if (DESC_REGISTRATION_format_identifier (desc) == 0x64726163) { + GST_LOG ("dirac"); + /* dirac in hex */ + template = gst_static_pad_template_get (&video_template); + name = g_strdup_printf ("video_%04x", bstream->pid); + caps = gst_caps_new_simple ("video/x-dirac", NULL); + } + } + g_free (desc); + } + break; + case ST_PRIVATE_EA: /* Try to detect a VC1 stream */ + { + desc = + mpegts_get_descriptor_from_stream ((MpegTSBaseStream *) stream, + DESC_REGISTRATION); + if (desc) { + if (DESC_LENGTH (desc) >= 4) { + if (DESC_REGISTRATION_format_identifier (desc) == DRF_ID_VC1) { + GST_WARNING ("0xea private stream type found but no descriptor " + "for VC1. Assuming plain VC1."); + template = gst_static_pad_template_get (&video_template); + name = g_strdup_printf ("video_%04x", bstream->pid); + caps = gst_caps_new_simple ("video/x-wmv", + "wmvversion", G_TYPE_INT, 3, + "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('W', 'V', 'C', '1'), + NULL); + } + } + g_free (desc); + } + break; + } + case ST_BD_AUDIO_AC3: + { + /* REGISTRATION DRF_ID_HDMV */ + desc = mpegts_get_descriptor_from_program (program, DESC_REGISTRATION); + if (desc) { + if (DESC_REGISTRATION_format_identifier (desc) == DRF_ID_HDMV) { + template = gst_static_pad_template_get (&audio_template); + name = g_strdup_printf ("audio_%04x", bstream->pid); + caps = gst_caps_new_simple ("audio/x-eac3", NULL); + } + g_free (desc); + } + if (template) + break; + + /* DVB_ENHANCED_AC3 */ + desc = + mpegts_get_descriptor_from_stream ((MpegTSBaseStream *) stream, + DESC_DVB_ENHANCED_AC3); + if (desc) { + template = gst_static_pad_template_get (&audio_template); + name = g_strdup_printf ("audio_%04x", bstream->pid); + caps = gst_caps_new_simple ("audio/x-eac3", NULL); + g_free (desc); + break; + } + + /* DVB_AC3 */ + desc = + mpegts_get_descriptor_from_stream ((MpegTSBaseStream *) stream, + DESC_DVB_AC3); + if (!desc) + GST_WARNING ("AC3 stream type found but no corresponding " + "descriptor to differentiate between AC3 and EAC3. " + "Assuming plain AC3."); + else + g_free (desc); + template = gst_static_pad_template_get (&audio_template); + name = g_strdup_printf ("audio_%04x", bstream->pid); + caps = gst_caps_new_simple ("audio/x-ac3", NULL); + break; + } + case ST_BD_AUDIO_EAC3: + template = gst_static_pad_template_get (&audio_template); + name = g_strdup_printf ("audio_%04x", bstream->pid); + caps = gst_caps_new_simple ("audio/x-eac3", NULL); + break; + case ST_PS_AUDIO_DTS: + template = gst_static_pad_template_get (&audio_template); + name = g_strdup_printf ("audio_%04x", bstream->pid); + caps = gst_caps_new_simple ("audio/x-dts", NULL); + break; + case ST_PS_AUDIO_LPCM: + template = gst_static_pad_template_get (&audio_template); + name = g_strdup_printf ("audio_%04x", bstream->pid); + caps = gst_caps_new_simple ("audio/x-lpcm", NULL); + break; + case ST_BD_AUDIO_LPCM: + template = gst_static_pad_template_get (&audio_template); + name = g_strdup_printf ("audio_%04x", bstream->pid); + caps = gst_caps_new_simple ("audio/x-private-ts-lpcm", NULL); + break; + case ST_PS_DVD_SUBPICTURE: + template = gst_static_pad_template_get (&subpicture_template); + name = g_strdup_printf ("subpicture_%04x", bstream->pid); + caps = gst_caps_new_simple ("video/x-dvd-subpicture", NULL); + break; + case ST_BD_PGS_SUBPICTURE: + template = gst_static_pad_template_get (&subpicture_template); + name = g_strdup_printf ("subpicture_%04x", bstream->pid); + caps = gst_caps_new_simple ("subpicture/x-pgs", NULL); + break; + } + if (template && name && caps) { + GST_LOG ("stream:%p creating pad with name %s and caps %s", stream, name, + gst_caps_to_string (caps)); + pad = gst_pad_new_from_template (template, name); + gst_pad_use_fixed_caps (pad); + gst_pad_set_caps (pad, caps); + gst_pad_set_query_type_function (pad, gst_ts_demux_srcpad_query_types); + gst_pad_set_query_function (pad, gst_ts_demux_srcpad_query); + gst_caps_unref (caps); + } + + g_free (name); + + return pad; +} + +static void +gst_ts_demux_stream_added (MpegTSBase * base, MpegTSBaseStream * bstream, + MpegTSBaseProgram * program) +{ + GstTSDemux *tsdemux = (GstTSDemux *) base; + TSDemuxStream *stream = (TSDemuxStream *) bstream; + + if (!stream->pad) { + /* Create the pad */ + if (bstream->stream_type != 0xff) + stream->pad = create_pad_for_stream (tsdemux, bstream, program); + stream->pts = GST_CLOCK_TIME_NONE; + } + stream->flow_return = GST_FLOW_OK; +} + +static void +gst_ts_demux_stream_removed (MpegTSBase * base, MpegTSBaseStream * bstream) +{ + TSDemuxStream *stream = (TSDemuxStream *) bstream; + if (stream) { + if (stream->pad) { + /* Unref the pad, clear it */ + gst_object_unref (stream->pad); + stream->pad = NULL; + } + stream->flow_return = GST_FLOW_NOT_LINKED; + } +} + +static void +activate_pad_for_stream (GstTSDemux * tsdemux, TSDemuxStream * stream) +{ + if (stream->pad) { + GST_DEBUG_OBJECT (tsdemux, "Activating pad %s:%s for stream %p", + GST_DEBUG_PAD_NAME (stream->pad), stream); + gst_pad_set_active (stream->pad, TRUE); + gst_element_add_pad ((GstElement *) tsdemux, stream->pad); + GST_DEBUG_OBJECT (stream->pad, "done adding pad"); + } else + GST_WARNING_OBJECT (tsdemux, "stream %p has no pad", stream); +} + +static void +gst_ts_demux_program_started (MpegTSBase * base, MpegTSBaseProgram * program) +{ + GstTSDemux *demux = GST_TS_DEMUX (base); + + if (demux->program_number == -1 || + demux->program_number == program->program_number) { + guint i; + + GST_LOG ("program %d started", program->program_number); + demux->program_number = program->program_number; + demux->program = program; + + /* Activate all stream pads, the pads will already have been created */ + + /* FIXME : Actually, we don't want to activate *ALL* streams ! + * For example, we don't want to expose HDV AUX private streams, we will just + * be using them directly for seeking and metadata. */ + if (base->mode != BASE_MODE_SCANNING) + for (i = 0; i < 0x2000; i++) + if (program->streams[i]) + activate_pad_for_stream (demux, + (TSDemuxStream *) program->streams[i]); + + /* Inform scanner we have got our program */ + demux->current_program_number = program->program_number; + } +} + +static void +gst_ts_demux_program_stopped (MpegTSBase * base, MpegTSBaseProgram * program) +{ + guint i; + GstTSDemux *demux = GST_TS_DEMUX (base); + TSDemuxStream *localstream = NULL; + + GST_LOG ("program %d stopped", program->program_number); + + if (program != demux->program) + return; + + for (i = 0; i < 0x2000; i++) { + if (demux->program->streams[i]) { + localstream = (TSDemuxStream *) program->streams[i]; + if (localstream->pad) { + GST_DEBUG ("HAVE PAD %s:%s", GST_DEBUG_PAD_NAME (localstream->pad)); + if (gst_pad_is_active (localstream->pad)) + gst_element_remove_pad (GST_ELEMENT_CAST (demux), localstream->pad); + else + gst_object_unref (localstream->pad); + localstream->pad = NULL; + } + } + } + demux->program = NULL; + demux->program_number = -1; +} + +static gboolean +process_section (MpegTSBase * base) +{ + GstTSDemux *demux = GST_TS_DEMUX (base); + gboolean based; + gboolean done = FALSE; + MpegTSPacketizerPacket packet; + MpegTSPacketizerPacketReturn pret; + + while ((!done) + && ((pret = + mpegts_packetizer_next_packet (base->packetizer, + &packet)) != PACKET_NEED_MORE)) { + if (G_UNLIKELY (pret == PACKET_BAD)) + /* bad header, skip the packet */ + goto next; + + /* base PSI data */ + if (packet.payload != NULL && mpegts_base_is_psi (base, &packet)) { + MpegTSPacketizerSection section; + + based = + mpegts_packetizer_push_section (base->packetizer, &packet, §ion); + if (G_UNLIKELY (!based)) + /* bad section data */ + goto next; + + if (G_LIKELY (section.complete)) { + /* section complete */ + GST_DEBUG ("Section Complete"); + based = mpegts_base_handle_psi (base, §ion); + gst_buffer_unref (section.buffer); + if (G_UNLIKELY (!based)) + /* bad PSI table */ + goto next; + + } + + if (demux->program != NULL) { + GST_DEBUG ("Got Program"); + done = TRUE; + } + } + next: + mpegts_packetizer_clear_packet (base->packetizer, &packet); + } + return done; +} + + +static GstFlowReturn +find_timestamps (MpegTSBase * base, guint64 initoff, guint64 * offset) +{ + + GstFlowReturn ret = GST_FLOW_OK; + GstBuffer *buf; + gboolean done = FALSE; + GstFormat format = GST_FORMAT_BYTES; + gint64 total_bytes; + guint64 scan_offset; + guint i = 0; + GstClockTime initial, final; + GstTSDemux *demux = GST_TS_DEMUX (base); + + GST_DEBUG ("Scanning for timestamps"); + + /* Flush what remained from before */ + mpegts_packetizer_clear (base->packetizer); + + /* Start scanning from know PAT offset */ + while (!done) { + ret = + gst_pad_pull_range (base->sinkpad, i * 50 * MPEGTS_MAX_PACKETSIZE, + 50 * MPEGTS_MAX_PACKETSIZE, &buf); + if (ret != GST_FLOW_OK) + goto beach; + mpegts_packetizer_push (base->packetizer, buf); + done = process_section (base); + i++; + } + mpegts_packetizer_clear (base->packetizer); + done = FALSE; + i = 1; + + + *offset = base->seek_offset; + + /* Search for the first PCRs */ + ret = process_pcr (base, base->first_pat_offset, &initial, 10, TRUE); + mpegts_packetizer_clear (base->packetizer); + /* Remove current program so we ensure looking for a PAT when scanning the + * for the final PCR */ + mpegts_base_remove_program (base, demux->current_program_number); + + if (ret != GST_FLOW_OK) { + GST_WARNING ("Problem getting initial PCRs"); + goto beach; + } + + /* Find end position */ + if (G_UNLIKELY (!gst_pad_query_peer_duration (base->sinkpad, &format, + &total_bytes) || format != GST_FORMAT_BYTES)) { + GST_WARNING_OBJECT (base, "Couldn't get upstream size in bytes"); + ret = GST_FLOW_ERROR; + mpegts_packetizer_clear (base->packetizer); + return ret; + } + GST_DEBUG ("Upstream is %" G_GINT64_FORMAT " bytes", total_bytes); + + scan_offset = total_bytes - 4000 * MPEGTS_MAX_PACKETSIZE; + + GST_DEBUG ("Scanning for last sync point between:%" G_GINT64_FORMAT + " and the end:%" G_GINT64_FORMAT, scan_offset, total_bytes); + while ((!done) && (scan_offset < total_bytes)) { + ret = + gst_pad_pull_range (base->sinkpad, + scan_offset, 50 * MPEGTS_MAX_PACKETSIZE, &buf); + if (ret != GST_FLOW_OK) + goto beach; + + mpegts_packetizer_push (base->packetizer, buf); + done = process_section (base); + scan_offset += 50 * MPEGTS_MAX_PACKETSIZE; + } + + mpegts_packetizer_clear (base->packetizer); + + GST_DEBUG ("Searching PCR"); + ret = + process_pcr (base, total_bytes - 4000 * MPEGTS_MAX_PACKETSIZE, &final, 10, + FALSE); + + if (ret != GST_FLOW_OK) { + GST_DEBUG ("Problem getting last PCRs"); + goto beach; + } + + demux->duration = final - initial; + + GST_DEBUG ("Done, duration:%" GST_TIME_FORMAT, + GST_TIME_ARGS (demux->duration)); + +beach: + + mpegts_packetizer_clear (base->packetizer); + /* Remove current program */ + mpegts_base_remove_program (base, demux->current_program_number); + + return ret; +} + +static GstFlowReturn +process_pcr (MpegTSBase * base, guint64 initoff, GstClockTime * pcr, + guint numpcr, gboolean isinitial) +{ + GstTSDemux *demux = GST_TS_DEMUX (base); + GstFlowReturn ret = GST_FLOW_OK; + MpegTSBaseProgram *program; + GstBuffer *buf; + guint nbpcr, i = 0; + guint32 pcrmask, pcrpattern; + guint64 pcrs[50]; + guint64 pcroffs[50]; + GstByteReader br; + + GST_DEBUG ("initoff:%" G_GUINT64_FORMAT ", numpcr:%d, isinitial:%d", + initoff, numpcr, isinitial); + + /* Get the program */ + program = demux->program; + if (G_UNLIKELY (program == NULL)) + return GST_FLOW_ERROR; + + /* First find the first X PCR */ + nbpcr = 0; + /* Mask/pattern is PID:PCR_PID, AFC&0x02 */ + /* sync_byte (0x47) : 8bits => 0xff + * transport_error_indicator : 1bit ACTIVATE + * payload_unit_start_indicator : 1bit IGNORE + * transport_priority : 1bit IGNORE + * PID : 13bit => 0x9f 0xff + * transport_scrambling_control : 2bit + * adaptation_field_control : 2bit + * continuity_counter : 4bit => 0x30 + */ + pcrmask = 0xff9fff20; + pcrpattern = 0x47000020 | ((program->pcr_pid & 0x1fff) << 8); + + for (i = 0; (i < 20) && (nbpcr < numpcr); i++) { + guint offset, size; + + ret = + gst_pad_pull_range (base->sinkpad, + initoff + i * 500 * base->packetsize, 500 * base->packetsize, &buf); + + if (G_UNLIKELY (ret != GST_FLOW_OK)) + goto beach; + + gst_byte_reader_init_from_buffer (&br, buf); + + offset = 0; + size = GST_BUFFER_SIZE (buf); + + /* FIXME : We should jump to next packet instead of scanning everything */ + while ((size >= br.size) && (nbpcr < numpcr) + && (offset = + gst_byte_reader_masked_scan_uint32 (&br, pcrmask, pcrpattern, + offset, size)) != -1) { + /* Potential PCR */ +/* GST_DEBUG ("offset %" G_GUINT64_FORMAT, GST_BUFFER_OFFSET (buf) + offset); + GST_MEMDUMP ("something", GST_BUFFER_DATA (buf) + offset, 16);*/ + if ((*(br.data + offset + 5)) & 0x10) { + guint16 pcr2; + guint64 pcr, pcr_ext; + + pcr = ((guint64) GST_READ_UINT32_BE (br.data + offset + 6)) << 1; + pcr2 = GST_READ_UINT16_BE (br.data + offset + 10); + pcr |= (pcr2 & 0x8000) >> 15; + pcr_ext = (pcr2 & 0x01ff); + pcr = pcr * 300 + pcr_ext % 300; + + GST_DEBUG ("Found PCR %" G_GUINT64_FORMAT " %" GST_TIME_FORMAT + " at offset %" G_GUINT64_FORMAT, pcr, + GST_TIME_ARGS (PCRTIME_TO_GSTTIME (pcr)), + GST_BUFFER_OFFSET (buf) + offset); + pcrs[nbpcr] = pcr; + pcroffs[nbpcr] = GST_BUFFER_OFFSET (buf) + offset; + /* Safeguard against bogus PCR (by detecting if it's the same as the + * previous one or wheter the difference with the previous one is + * greater than 10mins */ + if (nbpcr > 1) { + if (pcrs[nbpcr] == pcrs[nbpcr - 1]) { + GST_WARNING ("Found same PCR at different offset"); + } else if ((pcrs[nbpcr] - pcrs[nbpcr - 1]) > + (guint64) 10 * 60 * 27000000) { + GST_WARNING ("PCR differs with previous PCR by more than 10 mins"); + } else + nbpcr += 1; + } else + nbpcr += 1; + } + /* Move offset forward by 1 */ + size -= offset + 1; + offset += 1; + + } + } + +beach: + GST_DEBUG ("Found %d PCR", nbpcr); + if (nbpcr) { + if (isinitial) + *pcr = PCRTIME_TO_GSTTIME (pcrs[0]); + else + *pcr = PCRTIME_TO_GSTTIME (pcrs[nbpcr - 1]); + GST_DEBUG ("pcrdiff:%" GST_TIME_FORMAT " offsetdiff %" G_GUINT64_FORMAT, + GST_TIME_ARGS (PCRTIME_TO_GSTTIME (pcrs[nbpcr - 1] - pcrs[0])), + pcroffs[nbpcr - 1] - pcroffs[0]); + GST_DEBUG ("Estimated bitrate %" G_GUINT64_FORMAT, + gst_util_uint64_scale (GST_SECOND, pcroffs[nbpcr - 1] - pcroffs[0], + PCRTIME_TO_GSTTIME (pcrs[nbpcr - 1] - pcrs[0]))); + GST_DEBUG ("Average PCR interval %" G_GUINT64_FORMAT, + (pcroffs[nbpcr - 1] - pcroffs[0]) / nbpcr); + } + /* Swallow any errors if it happened during the end scanning */ + if (!isinitial) + ret = GST_FLOW_OK; + return ret; +} + + + + +static inline void +gst_ts_demux_record_pcr (GstTSDemux * demux, TSDemuxStream * stream, + guint64 pcr, guint64 offset) +{ + MpegTSBaseStream *bs = (MpegTSBaseStream *) stream; + + GST_LOG ("pid 0x%04x pcr:%" GST_TIME_FORMAT " at offset %" + G_GUINT64_FORMAT, bs->pid, + GST_TIME_ARGS (PCRTIME_TO_GSTTIME (pcr)), offset); + + if (G_UNLIKELY (demux->emit_statistics)) { + GstStructure *st; + st = gst_structure_id_empty_new (QUARK_TSDEMUX); + gst_structure_id_set (st, + QUARK_PID, G_TYPE_UINT, bs->pid, + QUARK_OFFSET, G_TYPE_UINT64, offset, QUARK_PCR, G_TYPE_UINT64, pcr, + NULL); + gst_element_post_message (GST_ELEMENT_CAST (demux), + gst_message_new_element (GST_OBJECT (demux), st)); + } +} + +static inline void +gst_ts_demux_record_opcr (GstTSDemux * demux, TSDemuxStream * stream, + guint64 opcr, guint64 offset) +{ + MpegTSBaseStream *bs = (MpegTSBaseStream *) stream; + + GST_LOG ("pid 0x%04x opcr:%" GST_TIME_FORMAT " at offset %" + G_GUINT64_FORMAT, bs->pid, + GST_TIME_ARGS (PCRTIME_TO_GSTTIME (opcr)), offset); + + if (G_UNLIKELY (demux->emit_statistics)) { + GstStructure *st; + st = gst_structure_id_empty_new (QUARK_TSDEMUX); + gst_structure_id_set (st, + QUARK_PID, G_TYPE_UINT, bs->pid, + QUARK_OFFSET, G_TYPE_UINT64, offset, + QUARK_OPCR, G_TYPE_UINT64, opcr, NULL); + gst_element_post_message (GST_ELEMENT_CAST (demux), + gst_message_new_element (GST_OBJECT (demux), st)); + } +} + +static inline void +gst_ts_demux_record_pts (GstTSDemux * demux, TSDemuxStream * stream, + guint64 pts, guint64 offset) +{ + MpegTSBaseStream *bs = (MpegTSBaseStream *) stream; + + GST_LOG ("pid 0x%04x pts:%" GST_TIME_FORMAT " at offset %" + G_GUINT64_FORMAT, bs->pid, + GST_TIME_ARGS (MPEGTIME_TO_GSTTIME (pts)), offset); + + if (G_UNLIKELY (demux->emit_statistics)) { + GstStructure *st; + st = gst_structure_id_empty_new (QUARK_TSDEMUX); + gst_structure_id_set (st, + QUARK_PID, G_TYPE_UINT, bs->pid, + QUARK_OFFSET, G_TYPE_UINT64, offset, QUARK_PTS, G_TYPE_UINT64, pts, + NULL); + gst_element_post_message (GST_ELEMENT_CAST (demux), + gst_message_new_element (GST_OBJECT (demux), st)); + } +} + +static inline void +gst_ts_demux_record_dts (GstTSDemux * demux, TSDemuxStream * stream, + guint64 dts, guint64 offset) +{ + MpegTSBaseStream *bs = (MpegTSBaseStream *) stream; + + GST_LOG ("pid 0x%04x dts:%" GST_TIME_FORMAT " at offset %" + G_GUINT64_FORMAT, bs->pid, + GST_TIME_ARGS (MPEGTIME_TO_GSTTIME (dts)), offset); + + if (G_UNLIKELY (demux->emit_statistics)) { + GstStructure *st; + st = gst_structure_id_empty_new (QUARK_TSDEMUX); + gst_structure_id_set (st, + QUARK_PID, G_TYPE_UINT, bs->pid, + QUARK_OFFSET, G_TYPE_UINT64, offset, QUARK_DTS, G_TYPE_UINT64, dts, + NULL); + gst_element_post_message (GST_ELEMENT_CAST (demux), + gst_message_new_element (GST_OBJECT (demux), st)); + } +} + +static GstFlowReturn +gst_ts_demux_parse_pes_header (GstTSDemux * demux, TSDemuxStream * stream) +{ + GstFlowReturn res = GST_FLOW_OK; + guint8 *data; + guint32 length; + guint32 psc_stid; + guint8 stid; + guint16 pesplength; + guint8 PES_header_data_length = 0; + + data = GST_BUFFER_DATA (stream->pendingbuffers[0]); + length = GST_BUFFER_SIZE (stream->pendingbuffers[0]); + + GST_MEMDUMP ("Header buffer", data, MIN (length, 32)); + + /* packet_start_code_prefix 24 + * stream_id 8*/ + psc_stid = GST_READ_UINT32_BE (data); + data += 4; + length -= 4; + if (G_UNLIKELY ((psc_stid & 0xffffff00) != 0x00000100)) { + GST_WARNING ("WRONG PACKET START CODE !"); + goto discont; + } + stid = psc_stid & 0x000000ff; + GST_LOG ("stream_id:0x%02x", stid); + + /* PES_packet_length 16 */ + /* FIXME : store the expected pes length somewhere ? */ + pesplength = GST_READ_UINT16_BE (data); + data += 2; + length -= 2; + GST_LOG ("PES_packet_length:%d", pesplength); + + /* FIXME : Only parse header on streams which require it (see table 2-21) */ + if (stid != 0xbf) { + guint8 p1, p2; + guint64 pts, dts; + p1 = *data++; + p2 = *data++; + PES_header_data_length = *data++ + 3; + length -= 3; + + GST_LOG ("0x%02x 0x%02x 0x%02x", p1, p2, PES_header_data_length); + GST_LOG ("PES header data length:%d", PES_header_data_length); + + /* '10' 2 + * PES_scrambling_control 2 + * PES_priority 1 + * data_alignment_indicator 1 + * copyright 1 + * original_or_copy 1 */ + if (G_UNLIKELY ((p1 & 0xc0) != 0x80)) { + GST_WARNING ("p1 >> 6 != 0x2"); + goto discont; + } + + /* PTS_DTS_flags 2 + * ESCR_flag 1 + * ES_rate_flag 1 + * DSM_trick_mode_flag 1 + * additional_copy_info_flag 1 + * PES_CRC_flag 1 + * PES_extension_flag 1*/ + + /* PES_header_data_length 8 */ + if (G_UNLIKELY (length < PES_header_data_length)) { + GST_WARNING ("length < PES_header_data_length"); + goto discont; + } + + /* PTS 32 */ + if ((p2 & 0x80)) { /* PTS */ + READ_TS (data, pts, discont); + gst_ts_demux_record_pts (demux, stream, pts, + GST_BUFFER_OFFSET (stream->pendingbuffers[0])); + length -= 4; + GST_BUFFER_TIMESTAMP (stream->pendingbuffers[0]) = + MPEGTIME_TO_GSTTIME (pts); + + if (!GST_CLOCK_TIME_IS_VALID (stream->pts)) { + stream->pts = GST_BUFFER_TIMESTAMP (stream->pendingbuffers[0]); + } + + } + /* DTS 32 */ + if ((p2 & 0x40)) { /* DTS */ + READ_TS (data, dts, discont); + gst_ts_demux_record_dts (demux, stream, dts, + GST_BUFFER_OFFSET (stream->pendingbuffers[0])); + length -= 4; + } + /* ESCR 48 */ + if ((p2 & 0x20)) { + GST_LOG ("ESCR present"); + data += 6; + length -= 6; + } + /* ES_rate 24 */ + if ((p2 & 0x10)) { + GST_LOG ("ES_rate present"); + data += 3; + length -= 3; + } + /* DSM_trick_mode 8 */ + if ((p2 & 0x08)) { + GST_LOG ("DSM_trick_mode present"); + data += 1; + length -= 1; + } + } + + /* Remove PES headers */ + GST_BUFFER_DATA (stream->pendingbuffers[0]) += 6 + PES_header_data_length; + GST_BUFFER_SIZE (stream->pendingbuffers[0]) -= 6 + PES_header_data_length; + + /* FIXME : responsible for switching to PENDING_PACKET_BUFFER and + * creating the bufferlist */ + if (1) { + /* Append to the buffer list */ + if (G_UNLIKELY (stream->current == NULL)) { + guint8 i; + + /* Create a new bufferlist */ + stream->current = gst_buffer_list_new (); + stream->currentit = gst_buffer_list_iterate (stream->current); + stream->currentlist = NULL; + gst_buffer_list_iterator_add_group (stream->currentit); + + /* Push pending buffers into the list */ + for (i = stream->nbpending; i; i--) + stream->currentlist = + g_list_prepend (stream->currentlist, stream->pendingbuffers[i - 1]); + memset (stream->pendingbuffers, 0, TS_MAX_PENDING_BUFFERS); + stream->nbpending = 0; + } + stream->state = PENDING_PACKET_BUFFER; + } + + return res; + +discont: + stream->state = PENDING_PACKET_DISCONT; + return res; +} + + /* ONLY CALL THIS: + * * WITH packet->payload != NULL + * * WITH pending/current flushed out if beginning of new PES packet + */ +static inline void +gst_ts_demux_queue_data (GstTSDemux * demux, TSDemuxStream * stream, + MpegTSPacketizerPacket * packet) +{ + GstBuffer *buf; + + GST_DEBUG ("state:%d", stream->state); + + buf = packet->buffer; + /* HACK : Instead of creating a new buffer, we just modify the data/size + * of the buffer to point to the payload */ + GST_BUFFER_DATA (buf) = packet->payload; + GST_BUFFER_SIZE (buf) = packet->data_end - packet->payload; + + if (stream->state == PENDING_PACKET_EMPTY) { + if (G_UNLIKELY (!packet->payload_unit_start_indicator)) { + stream->state = PENDING_PACKET_DISCONT; + GST_WARNING ("Didn't get the first packet of this PES"); + } else { + GST_LOG ("EMPTY=>HEADER"); + stream->state = PENDING_PACKET_HEADER; + if (stream->pad) { + GST_DEBUG ("Setting pad caps on buffer %p", buf); + gst_buffer_set_caps (buf, GST_PAD_CAPS (stream->pad)); + } + } + } + + if (stream->state == PENDING_PACKET_HEADER) { + GST_LOG ("HEADER: appending data to array"); + /* Append to the array */ + stream->pendingbuffers[stream->nbpending++] = buf; + + /* parse the header */ + gst_ts_demux_parse_pes_header (demux, stream); + } else if (stream->state == PENDING_PACKET_BUFFER) { + GST_LOG ("BUFFER: appending data to bufferlist"); + stream->currentlist = g_list_prepend (stream->currentlist, buf); + } + + + return; +} + +static GstFlowReturn +gst_ts_demux_push_pending_data (GstTSDemux * demux, TSDemuxStream * stream) +{ + GstFlowReturn res = GST_FLOW_OK; + MpegTSBaseStream *bs = (MpegTSBaseStream *) stream; + + + guint i; + GstClockTime tinypts = GST_CLOCK_TIME_NONE; + GstClockTime stop = GST_CLOCK_TIME_NONE; + GstEvent *newsegmentevent; + + GST_DEBUG ("stream:%p, pid:0x%04x stream_type:%d state:%d pad:%s:%s", + stream, bs->pid, bs->stream_type, stream->state, + GST_DEBUG_PAD_NAME (stream->pad)); + + if (G_UNLIKELY (stream->current == NULL)) { + GST_LOG ("stream->current == NULL"); + goto beach; + } + + if (G_UNLIKELY (stream->state == PENDING_PACKET_EMPTY)) { + GST_LOG ("EMPTY: returning"); + goto beach; + } + + /* We have a confirmed buffer, let's push it out */ + if (stream->state == PENDING_PACKET_BUFFER) { + GST_LOG ("BUFFER: pushing out pending data"); + stream->currentlist = g_list_reverse (stream->currentlist); + gst_buffer_list_iterator_add_list (stream->currentit, stream->currentlist); + gst_buffer_list_iterator_free (stream->currentit); + + + if (stream->pad) { + + if (demux->need_newsegment) { + + for (i = 0; i < 0x2000; i++) { + + if (demux->program->streams[i]) { + if ((!GST_CLOCK_TIME_IS_VALID (tinypts)) + || (((TSDemuxStream *) demux->program->streams[i])->pts < + tinypts)) + tinypts = ((TSDemuxStream *) demux->program->streams[i])->pts; + } + + + } + + if (GST_CLOCK_TIME_IS_VALID (demux->duration)) + stop = tinypts + demux->duration; + + GST_DEBUG ("Sending newsegment event"); + newsegmentevent = + gst_event_new_new_segment (0, 1.0, GST_FORMAT_TIME, tinypts, stop, + 0); + + push_event ((MpegTSBase *) demux, newsegmentevent); + + demux->need_newsegment = FALSE; + } + + GST_DEBUG_OBJECT (stream->pad, "Pushing buffer list "); + + res = gst_pad_push_list (stream->pad, stream->current); + GST_DEBUG_OBJECT (stream->pad, "Returned %s", gst_flow_get_name (res)); + /* FIXME : combine flow returns */ + res = tsdemux_combine_flows (demux, stream, res); + GST_DEBUG_OBJECT (stream->pad, "combined %s", gst_flow_get_name (res)); + } + } + +beach: + /* Reset everything */ + GST_LOG ("Resetting to EMPTY"); + stream->state = PENDING_PACKET_EMPTY; + + /* for (i = 0; i < stream->nbpending; i++) */ + /* gst_buffer_unref (stream->pendingbuffers[i]); */ + memset (stream->pendingbuffers, 0, TS_MAX_PENDING_BUFFERS); + stream->nbpending = 0; + + stream->current = NULL; + + + + return res; +} + +static GstFlowReturn +gst_ts_demux_handle_packet (GstTSDemux * demux, TSDemuxStream * stream, + MpegTSPacketizerPacket * packet, MpegTSPacketizerSection * section) +{ + GstFlowReturn res = GST_FLOW_OK; + + GST_DEBUG ("buffer:%p, data:%p", GST_BUFFER_DATA (packet->buffer), + packet->data); + GST_LOG ("pid 0x%04x pusi:%d, afc:%d, cont:%d, payload:%p", + packet->pid, + packet->payload_unit_start_indicator, + packet->adaptation_field_control, + packet->continuity_counter, packet->payload); + + if (section) { + GST_DEBUG ("section complete:%d, buffer size %d", + section->complete, GST_BUFFER_SIZE (section->buffer)); + } + + if (G_UNLIKELY (packet->payload_unit_start_indicator)) + /* Flush previous data */ + res = gst_ts_demux_push_pending_data (demux, stream); + + if (packet->adaptation_field_control & 0x2) { + if (packet->afc_flags & MPEGTS_AFC_PCR_FLAG) + gst_ts_demux_record_pcr (demux, stream, packet->pcr, + GST_BUFFER_OFFSET (packet->buffer)); + if (packet->afc_flags & MPEGTS_AFC_OPCR_FLAG) + gst_ts_demux_record_opcr (demux, stream, packet->opcr, + GST_BUFFER_OFFSET (packet->buffer)); + } + + if (packet->payload) + gst_ts_demux_queue_data (demux, stream, packet); + + return res; +} + +static GstFlowReturn +gst_ts_demux_push (MpegTSBase * base, MpegTSPacketizerPacket * packet, + MpegTSPacketizerSection * section) +{ + GstTSDemux *demux = GST_TS_DEMUX_CAST (base); + TSDemuxStream *stream = NULL; + GstFlowReturn res = GST_FLOW_OK; + + if (G_LIKELY (demux->program)) { + stream = (TSDemuxStream *) demux->program->streams[packet->pid]; + + if (stream) { + res = gst_ts_demux_handle_packet (demux, stream, packet, section); + } else if (packet->buffer) + gst_buffer_unref (packet->buffer); + } else { + if (packet->buffer) + gst_buffer_unref (packet->buffer); + } + return res; +} + +gboolean +gst_ts_demux_plugin_init (GstPlugin * plugin) +{ + GST_DEBUG_CATEGORY_INIT (ts_demux_debug, "tsdemux", 0, + "MPEG transport stream demuxer"); + + return gst_element_register (plugin, "tsdemux", + GST_RANK_SECONDARY, GST_TYPE_TS_DEMUX); +} diff --git a/gst/mpegtsdemux/tsdemux.h b/gst/mpegtsdemux/tsdemux.h new file mode 100644 index 0000000000..bfee2df42e --- /dev/null +++ b/gst/mpegtsdemux/tsdemux.h @@ -0,0 +1,78 @@ +/* + * tsdemux - GStreamer MPEG transport stream demuxer + * Copyright (C) 2009 Zaheer Abbas Merali + * 2010 Edward Hervey + * + * Authors: + * Zaheer Abbas Merali + * Edward Hervey + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#ifndef GST_TS_DEMUX_H +#define GST_TS_DEMUX_H + +#include +#include +#include "mpegtsbase.h" +#include "mpegtspacketizer.h" + +G_BEGIN_DECLS +#define GST_TYPE_TS_DEMUX \ + (gst_ts_demux_get_type()) +#define GST_TS_DEMUX(obj) \ + (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_TS_DEMUX,GstTSDemux)) +#define GST_TS_DEMUX_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_TS_DEMUX,GstTSDemuxClass)) +#define GST_IS_TS_DEMUX(obj) \ + (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_TS_DEMUX)) +#define GST_IS_TS_DEMUX_CLASS(klass) \ + (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_TS_DEMUX)) +#define GST_TS_DEMUX_GET_CLASS(obj) \ + (G_TYPE_INSTANCE_GET_CLASS ((obj), GST_TYPE_TS_DEMUX, GstTSDemuxClass)) +#define GST_TS_DEMUX_CAST(obj) ((GstTSDemux*) obj) +typedef struct _GstTSDemux GstTSDemux; +typedef struct _GstTSDemuxClass GstTSDemuxClass; + +struct _GstTSDemux +{ + MpegTSBase parent; + + /* the following vars must be protected with the OBJECT_LOCK as they can be + * accessed from the application thread and the streaming thread */ + guint program_number; /* Required program number (ignore:-1) */ + gboolean emit_statistics; + + /*< private >*/ + MpegTSBaseProgram *program; /* Current program */ + guint current_program_number; + gboolean need_newsegment; + GstClockTime duration; /* Total duration */ +}; + +struct _GstTSDemuxClass +{ + MpegTSBaseClass parent_class; +}; + +GType gst_ts_demux_get_type (void); + +gboolean gst_ts_demux_plugin_init (GstPlugin * plugin); + +G_END_DECLS +#endif /* GST_TS_DEMUX_H */ From 535bf57d1f76fc1c73cde5af636a78b78b950733 Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Thu, 10 Feb 2011 12:35:47 +0100 Subject: [PATCH 414/448] mpegtsdemux: relicense gstmpegdefs.h, gstmpegdesc.h and gstmpegdesc.c to LGPL only with permission from the license header: """ This library is licensed under 2 different licenses and you can choose to use it under the terms of either one of them. The two licenses are the MPL 1.1 and the LGPL. """ --- gst/mpegtsdemux/gstmpegdefs.h | 17 ----------------- gst/mpegtsdemux/gstmpegdesc.c | 32 ++++++++++++++------------------ gst/mpegtsdemux/gstmpegdesc.h | 32 ++++++++++++++------------------ 3 files changed, 28 insertions(+), 53 deletions(-) diff --git a/gst/mpegtsdemux/gstmpegdefs.h b/gst/mpegtsdemux/gstmpegdefs.h index 947dc4d55e..268234f25c 100644 --- a/gst/mpegtsdemux/gstmpegdefs.h +++ b/gst/mpegtsdemux/gstmpegdefs.h @@ -1,21 +1,4 @@ /* - * This library is licensed under 2 different licenses and you - * can choose to use it under the terms of either one of them. The - * two licenses are the MPL 1.1 and the LGPL. - * - * MPL: - * - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/. - * - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the - * License for the specific language governing rights and limitations - * under the License. - * - * LGPL: * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public diff --git a/gst/mpegtsdemux/gstmpegdesc.c b/gst/mpegtsdemux/gstmpegdesc.c index 7e80483975..4abf5eb360 100644 --- a/gst/mpegtsdemux/gstmpegdesc.c +++ b/gst/mpegtsdemux/gstmpegdesc.c @@ -1,13 +1,19 @@ /* - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/. * - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the - * License for the specific language governing rights and limitations - * under the License. + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. * * The Original Code is Fluendo MPEG Demuxer plugin. * @@ -17,16 +23,6 @@ * * Contributor(s): Wim Taymans * - * Alternatively, the contents of this file may be used under the terms of - * the GNU Lesser General Public License Version 2 or later (the "LGPL"), - * in which case the provisions of the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of the MPL or the LGPL. */ #include diff --git a/gst/mpegtsdemux/gstmpegdesc.h b/gst/mpegtsdemux/gstmpegdesc.h index 9e1ae75c8e..06aa17b959 100644 --- a/gst/mpegtsdemux/gstmpegdesc.h +++ b/gst/mpegtsdemux/gstmpegdesc.h @@ -1,13 +1,19 @@ /* - * The contents of this file are subject to the Mozilla Public License - * Version 1.1 (the "License"); you may not use this file except in - * compliance with the License. You may obtain a copy of the License at - * http://www.mozilla.org/MPL/. * - * Software distributed under the License is distributed on an "AS IS" - * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the - * License for the specific language governing rights and limitations - * under the License. + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. * * The Original Code is Fluendo MPEG Demuxer plugin. * @@ -17,16 +23,6 @@ * * Contributor(s): Wim Taymans * - * Alternatively, the contents of this file may be used under the terms of - * the GNU Lesser General Public License Version 2 or later (the "LGPL"), - * in which case the provisions of the LGPL are applicable instead - * of those above. If you wish to allow use of your version of this file only - * under the terms of the LGPL, and not to allow others to - * use your version of this file under the terms of the MPL, indicate your - * decision by deleting the provisions above and replace them with the notice - * and other provisions required by the LGPL. If you do not delete - * the provisions above, a recipient may use your version of this file under - * the terms of the MPL or the LGPL. */ #ifndef __GST_MPEG_DESC_H__ From df1a470d5d25a3517e401fafcab9b06a5abe2792 Mon Sep 17 00:00:00 2001 From: David Schleef Date: Tue, 15 Feb 2011 18:12:02 -0800 Subject: [PATCH 415/448] colorspace: Fix memory leak --- gst/colorspace/gstcolorspace.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/gst/colorspace/gstcolorspace.c b/gst/colorspace/gstcolorspace.c index 2de57732dc..8a823fa0d9 100644 --- a/gst/colorspace/gstcolorspace.c +++ b/gst/colorspace/gstcolorspace.c @@ -407,7 +407,14 @@ gst_csp_base_init (gpointer klass) static void gst_csp_finalize (GObject * obj) { + GstCsp *space = GST_CSP (obj); + + if (space->convert) { + colorspace_convert_free (space->convert); + } + G_OBJECT_CLASS (parent_class)->finalize (obj); + } static void From 92d5ea292634d9133ff25e06d70ef282502c0d2f Mon Sep 17 00:00:00 2001 From: Janne Grunau Date: Thu, 17 Feb 2011 21:33:56 +0100 Subject: [PATCH 416/448] mpegtsdemux: use G_GUINT64_FORMAT as format specifier for guint64 fixes compilation on 32bit --- gst/mpegtsdemux/mpegtsbase.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gst/mpegtsdemux/mpegtsbase.c b/gst/mpegtsdemux/mpegtsbase.c index 7151ef7a91..8eb89bff2b 100644 --- a/gst/mpegtsdemux/mpegtsbase.c +++ b/gst/mpegtsdemux/mpegtsbase.c @@ -823,7 +823,8 @@ mpegts_base_handle_psi (MpegTSBase * base, MpegTSPacketizerSection * section) if (base->first_pat_offset == -1) { base->first_pat_offset = GST_BUFFER_OFFSET (section->buffer); - GST_DEBUG ("First PAT offset: %d", base->first_pat_offset); + GST_DEBUG ("First PAT offset: %" G_GUINT64_FORMAT, + base->first_pat_offset); } } else From 455aaa3fbd2ba0b994fc28c09af93c01399ce6ac Mon Sep 17 00:00:00 2001 From: David Schleef Date: Sat, 4 Dec 2010 19:55:32 -0800 Subject: [PATCH 417/448] mpegtsmux: fix release_pad Remove bogus freeing of pad element_private data that we never set (collectpads uses it, which causes confusion here). Also, check that our collectpads instance exists before using it. Partial fix for #636011. --- gst/mpegtsmux/mpegtsmux.c | 21 ++++----------------- 1 file changed, 4 insertions(+), 17 deletions(-) diff --git a/gst/mpegtsmux/mpegtsmux.c b/gst/mpegtsmux/mpegtsmux.c index 55f51f6eab..0ed2403dd1 100644 --- a/gst/mpegtsmux/mpegtsmux.c +++ b/gst/mpegtsmux/mpegtsmux.c @@ -800,28 +800,15 @@ static void mpegtsmux_release_pad (GstElement * element, GstPad * pad) { MpegTsMux *mux = GST_MPEG_TSMUX (element); - MpegTsPadData *pad_data = NULL; GST_DEBUG_OBJECT (mux, "Pad %" GST_PTR_FORMAT " being released", pad); - /* Get the MpegTsPadData out of the pad */ - GST_OBJECT_LOCK (pad); - pad_data = (MpegTsPadData *) gst_pad_get_element_private (pad); - if (G_LIKELY (pad_data)) { - /* Free codec data reference if any */ - if (pad_data->codec_data) { - GST_DEBUG_OBJECT (element, "releasing codec_data reference"); - gst_buffer_unref (pad_data->codec_data); - pad_data->codec_data = NULL; - } - if (pad_data->prepare_data && pad_data->free_func) { - pad_data->free_func (pad_data->prepare_data); - pad_data->prepare_data = pad_data->free_func = NULL; - } + if (mux->collect) { + gst_collect_pads_remove_pad (mux->collect, pad); } - GST_OBJECT_UNLOCK (pad); - gst_collect_pads_remove_pad (mux->collect, pad); + /* chain up */ + gst_element_remove_pad (element, pad); } static gboolean From 0a786810af09f974be427b9bda9799be5ec34e88 Mon Sep 17 00:00:00 2001 From: David Schleef Date: Wed, 16 Feb 2011 21:17:57 -0800 Subject: [PATCH 418/448] dvdsubdec: make up clut values if they weren't set --- gst/dvdspu/gstspu-vobsub-render.c | 34 +++++++++++++++++++++++-------- 1 file changed, 26 insertions(+), 8 deletions(-) diff --git a/gst/dvdspu/gstspu-vobsub-render.c b/gst/dvdspu/gstspu-vobsub-render.c index 06054085d1..830017d33e 100644 --- a/gst/dvdspu/gstspu-vobsub-render.c +++ b/gst/dvdspu/gstspu-vobsub-render.c @@ -37,15 +37,33 @@ gstspu_vobsub_recalc_palette (GstDVDSpu * dvdspu, SpuState *state = &dvdspu->spu_state; gint i; - for (i = 0; i < 4; i++, dest++) { - guint32 col = state->vobsub.current_clut[idx[i]]; + if (state->vobsub.current_clut[idx[0]] != 0) { + for (i = 0; i < 4; i++, dest++) { + guint32 col = state->vobsub.current_clut[idx[i]]; - /* Convert incoming 4-bit alpha to 8 bit for blending */ - dest->A = (alpha[i] << 4) | alpha[i]; - dest->Y = ((guint16) ((col >> 16) & 0xff)) * dest->A; - /* U/V are stored as V/U in the clut words, so switch them */ - dest->V = ((guint16) ((col >> 8) & 0xff)) * dest->A; - dest->U = ((guint16) (col & 0xff)) * dest->A; + /* Convert incoming 4-bit alpha to 8 bit for blending */ + dest->A = (alpha[i] << 4) | alpha[i]; + dest->Y = ((guint16) ((col >> 16) & 0xff)) * dest->A; + /* U/V are stored as V/U in the clut words, so switch them */ + dest->V = ((guint16) ((col >> 8) & 0xff)) * dest->A; + dest->U = ((guint16) (col & 0xff)) * dest->A; + } + } else { + int y = 240; + + /* The CLUT presumably hasn't been set, so we'll just guess some + * values for the non-transparent colors (white, grey, black) */ + for (i = 0; i < 4; i++, dest++) { + dest->A = (alpha[i] << 4) | alpha[i]; + if (alpha[i] != 0) { + dest[0].Y = y * dest[0].A; + y -= 112; + if (y < 0) + y = 0; + } + dest[0].U = 128 * dest[0].A; + dest[0].V = 128 * dest[0].A; + } } } From fa3ff9e5edddc9ade8b33aff33aeb81066c47c72 Mon Sep 17 00:00:00 2001 From: David Schleef Date: Wed, 13 Oct 2010 15:39:55 -0700 Subject: [PATCH 419/448] baseparse: Create baseparse library --- configure.ac | 1 + gst-libs/gst/Makefile.am | 5 +- gst-libs/gst/baseparse/Makefile.am | 20 + .../gst/baseparse}/gstbaseparse.c | 0 .../gst/baseparse}/gstbaseparse.h | 0 gst/audioparsers/Makefile.am | 10 +- gst/audioparsers/gstaacparse.h | 2 +- gst/audioparsers/gstac3parse.h | 2 +- gst/audioparsers/gstamrparse.h | 2 +- gst/audioparsers/gstdcaparse.h | 2 +- gst/audioparsers/gstflacparse.h | 2 +- gst/audioparsers/gstmpegaudioparse.h | 2 +- gst/videoparsers/Makefile.am | 5 +- gst/videoparsers/gstbaseparse.c | 3716 ----------------- gst/videoparsers/gstbaseparse.h | 358 -- gst/videoparsers/gsth263parse.h | 2 +- gst/videoparsers/gsth264parse.h | 2 +- gst/videoparsers/h263parse.h | 2 +- 18 files changed, 41 insertions(+), 4092 deletions(-) create mode 100644 gst-libs/gst/baseparse/Makefile.am rename {gst/audioparsers => gst-libs/gst/baseparse}/gstbaseparse.c (100%) rename {gst/audioparsers => gst-libs/gst/baseparse}/gstbaseparse.h (100%) delete mode 100644 gst/videoparsers/gstbaseparse.c delete mode 100644 gst/videoparsers/gstbaseparse.h diff --git a/configure.ac b/configure.ac index 3e594baf76..dd040a4e86 100644 --- a/configure.ac +++ b/configure.ac @@ -1783,6 +1783,7 @@ gst/y4m/Makefile gst-libs/Makefile gst-libs/gst/Makefile gst-libs/gst/basecamerabinsrc/Makefile +gst-libs/gst/baseparse/Makefile gst-libs/gst/interfaces/Makefile gst-libs/gst/signalprocessor/Makefile gst-libs/gst/video/Makefile diff --git a/gst-libs/gst/Makefile.am b/gst-libs/gst/Makefile.am index a760e99819..92d951cc88 100644 --- a/gst-libs/gst/Makefile.am +++ b/gst-libs/gst/Makefile.am @@ -2,7 +2,8 @@ if BUILD_EXPERIMENTAL EXPERIMENTAL_LIBS=basecamerabinsrc endif -SUBDIRS = interfaces signalprocessor video $(EXPERIMENTAL_LIBS) +SUBDIRS = baseparse interfaces signalprocessor video $(EXPERIMENTAL_LIBS) noinst_HEADERS = gst-i18n-plugin.h gettext.h -DIST_SUBDIRS = interfaces signalprocessor video basecamerabinsrc +DIST_SUBDIRS = baseparse interfaces signalprocessor video basecamerabinsrc + diff --git a/gst-libs/gst/baseparse/Makefile.am b/gst-libs/gst/baseparse/Makefile.am new file mode 100644 index 0000000000..e44a78b0aa --- /dev/null +++ b/gst-libs/gst/baseparse/Makefile.am @@ -0,0 +1,20 @@ + +lib_LTLIBRARIES = libgstbaseparse-@GST_MAJORMINOR@.la + +CLEANFILES = $(BUILT_SOURCES) + +libgstbaseparse_@GST_MAJORMINOR@_la_SOURCES = \ + gstbaseparse.c + +libgstbaseparse_@GST_MAJORMINOR@includedir = $(includedir)/gstreamer-@GST_MAJORMINOR@/gst/baseparse +libgstbaseparse_@GST_MAJORMINOR@include_HEADERS = \ + gstbaseparse.h + +libgstbaseparse_@GST_MAJORMINOR@_la_CFLAGS = \ + $(GST_PLUGINS_BAD_CFLAGS) \ + $(GST_PLUGINS_BASE_CFLAGS) \ + -DGST_USE_UNSTABLE_API \ + $(GST_CFLAGS) +libgstbaseparse_@GST_MAJORMINOR@_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) $(GST_BASE_LIBS) $(GST_LIBS) +libgstbaseparse_@GST_MAJORMINOR@_la_LDFLAGS = $(GST_LIB_LDFLAGS) $(GST_ALL_LDFLAGS) $(GST_LT_LDFLAGS) + diff --git a/gst/audioparsers/gstbaseparse.c b/gst-libs/gst/baseparse/gstbaseparse.c similarity index 100% rename from gst/audioparsers/gstbaseparse.c rename to gst-libs/gst/baseparse/gstbaseparse.c diff --git a/gst/audioparsers/gstbaseparse.h b/gst-libs/gst/baseparse/gstbaseparse.h similarity index 100% rename from gst/audioparsers/gstbaseparse.h rename to gst-libs/gst/baseparse/gstbaseparse.h diff --git a/gst/audioparsers/Makefile.am b/gst/audioparsers/Makefile.am index 8aca6d98cf..77039c7154 100644 --- a/gst/audioparsers/Makefile.am +++ b/gst/audioparsers/Makefile.am @@ -3,10 +3,13 @@ plugin_LTLIBRARIES = libgstaudioparsersbad.la libgstaudioparsersbad_la_SOURCES = \ gstaacparse.c gstamrparse.c gstac3parse.c \ gstdcaparse.c gstflacparse.c gstmpegaudioparse.c \ - gstbaseparse.c plugin.c + plugin.c -libgstaudioparsersbad_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) +libgstaudioparsersbad_la_CFLAGS = \ + -I$(top_srcdir)/gst-libs \ + $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) libgstaudioparsersbad_la_LIBADD = \ + $(top_builddir)/gst-libs/gst/baseparse/libgstbaseparse-$(GST_MAJORMINOR).la \ $(GST_PLUGINS_BASE_LIBS) -lgsttag-$(GST_MAJORMINOR) \ -lgstaudio-$(GST_MAJORMINOR) \ $(GST_BASE_LIBS) $(GST_LIBS) @@ -14,5 +17,4 @@ libgstaudioparsersbad_la_LDFLAGS = $(PACKAGE_LIBS) $(GST_PLUGIN_LDFLAGS) libgstaudioparsersbad_la_LIBTOOLFLAGS = --tag=disable-static noinst_HEADERS = gstaacparse.h gstamrparse.h gstac3parse.h \ - gstdcaparse.h gstflacparse.h gstmpegaudioparse.h \ - gstbaseparse.h + gstdcaparse.h gstflacparse.h gstmpegaudioparse.h diff --git a/gst/audioparsers/gstaacparse.h b/gst/audioparsers/gstaacparse.h index 7d71ef0dce..e62bf651f0 100644 --- a/gst/audioparsers/gstaacparse.h +++ b/gst/audioparsers/gstaacparse.h @@ -23,7 +23,7 @@ #define __GST_AACPARSE_H__ #include -#include "gstbaseparse.h" +#include G_BEGIN_DECLS diff --git a/gst/audioparsers/gstac3parse.h b/gst/audioparsers/gstac3parse.h index 724b56f599..781554be5f 100644 --- a/gst/audioparsers/gstac3parse.h +++ b/gst/audioparsers/gstac3parse.h @@ -24,7 +24,7 @@ #define __GST_AC3_PARSE_H__ #include -#include "gstbaseparse.h" +#include G_BEGIN_DECLS diff --git a/gst/audioparsers/gstamrparse.h b/gst/audioparsers/gstamrparse.h index e3fc191b83..04cd6e7639 100644 --- a/gst/audioparsers/gstamrparse.h +++ b/gst/audioparsers/gstamrparse.h @@ -24,7 +24,7 @@ #define __GST_AMRPARSE_H__ #include -#include "gstbaseparse.h" +#include G_BEGIN_DECLS diff --git a/gst/audioparsers/gstdcaparse.h b/gst/audioparsers/gstdcaparse.h index 150a191814..b0d7546416 100644 --- a/gst/audioparsers/gstdcaparse.h +++ b/gst/audioparsers/gstdcaparse.h @@ -21,7 +21,7 @@ #define __GST_DCA_PARSE_H__ #include -#include "gstbaseparse.h" +#include G_BEGIN_DECLS diff --git a/gst/audioparsers/gstflacparse.h b/gst/audioparsers/gstflacparse.h index 3394115f9f..664b2a6bc9 100644 --- a/gst/audioparsers/gstflacparse.h +++ b/gst/audioparsers/gstflacparse.h @@ -25,7 +25,7 @@ #define __GST_FLAC_PARSE_H__ #include -#include "gstbaseparse.h" +#include G_BEGIN_DECLS diff --git a/gst/audioparsers/gstmpegaudioparse.h b/gst/audioparsers/gstmpegaudioparse.h index cf5fd37b11..3f680d1e53 100644 --- a/gst/audioparsers/gstmpegaudioparse.h +++ b/gst/audioparsers/gstmpegaudioparse.h @@ -24,7 +24,7 @@ #define __GST_MPEG_AUDIO_PARSE_H__ #include -#include "gstbaseparse.h" +#include G_BEGIN_DECLS diff --git a/gst/videoparsers/Makefile.am b/gst/videoparsers/Makefile.am index 171c7ce1f5..59b5160211 100644 --- a/gst/videoparsers/Makefile.am +++ b/gst/videoparsers/Makefile.am @@ -1,12 +1,11 @@ plugin_LTLIBRARIES = libgsth263parse.la libgsth263parse_la_SOURCES = plugin.c \ - h263parse.c gsth263parse.c gsth264parse.c h264parse.c gstbaseparse.c + h263parse.c gsth263parse.c gsth264parse.c h264parse.c libgsth263parse_la_CFLAGS = $(GST_CFLAGS) libgsth263parse_la_LIBADD = $(GST_BASE_LIBS) $(GST_LIBS) libgsth263parse_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) libgsth263parse_la_LIBTOOLFLAGS = --tag=disable-static noinst_HEADERS = gsth263parse.h h263parse.h \ - gsth264parse.h gsth264parse.h h264parse.h \ - gstbaseparse.h + gsth264parse.h h264parse.h diff --git a/gst/videoparsers/gstbaseparse.c b/gst/videoparsers/gstbaseparse.c deleted file mode 100644 index db2691fe2e..0000000000 --- a/gst/videoparsers/gstbaseparse.c +++ /dev/null @@ -1,3716 +0,0 @@ -/* GStreamer - * Copyright (C) 2008 Nokia Corporation. All rights reserved. - * Contact: Stefan Kost - * Copyright (C) 2008 Sebastian Dröge . - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -/** - * SECTION:gstbaseparse - * @short_description: Base class for stream parsers - * @see_also: #GstBaseTransform - * - * This base class is for parser elements that process data and splits it - * into separate audio/video/whatever frames. - * - * It provides for: - * - * One sinkpad and one srcpad - * Handles state changes - * Does flushing - * Push mode - * Pull mode - * Handles events (NEWSEGMENT/EOS/FLUSH) - * Handles seeking in both modes - * - * Handles POSITION/DURATION/SEEKING/FORMAT/CONVERT queries - * - * - * - * The purpose of this base class is to provide a basic functionality of - * a parser and share a lot of rather complex code. - * - * Description of the parsing mechanism: - * - * - * Set-up phase - * - * GstBaseParse class calls @set_sink_caps to inform the subclass about - * incoming sinkpad caps. Subclass should set the srcpad caps accordingly. - * - * - * GstBaseParse calls @start to inform subclass that data processing is - * about to start now. - * - * - * At least in this point subclass needs to tell the GstBaseParse class - * how big data chunks it wants to receive (min_frame_size). It can do - * this with @gst_base_parse_set_min_frame_size. - * - * - * GstBaseParse class sets up appropriate data passing mode (pull/push) - * and starts to process the data. - * - * - * - * - * - * Parsing phase - * - * GstBaseParse gathers at least min_frame_size bytes of data either - * by pulling it from upstream or collecting buffers into internal - * #GstAdapter. - * - * - * A buffer of (at least) min_frame_size bytes is passed to subclass with - * @check_valid_frame. Subclass checks the contents and returns TRUE - * if the buffer contains a valid frame. It also needs to set the - * @framesize according to the detected frame size. If buffer didn't - * contain a valid frame, this call must return FALSE and optionally - * set the @skipsize value to inform base class that how many bytes - * it needs to skip in order to find a valid frame. @framesize can always - * indicate a new minimum for current frame parsing. The passed buffer - * is read-only. Note that @check_valid_frame might receive any small - * amount of input data when leftover data is being drained (e.g. at EOS). - * - * - * After valid frame is found, it will be passed again to subclass with - * @parse_frame call. Now subclass is responsible for parsing the - * frame contents and setting the caps, and buffer metadata (e.g. - * buffer timestamp and duration, or keyframe if applicable). - * (although the latter can also be done by GstBaseParse if it is - * appropriately configured, see below). Frame is provided with - * timestamp derived from upstream (as much as generally possible), - * duration obtained form configuration (see below), and offset - * if meaningful (in pull mode). - * - * - * Finally the buffer can be pushed downstream and parsing loop starts - * over again. Just prior to actually pushing the buffer in question, - * it is passed to @pre_push_buffer which gives subclass yet one - * last chance to examine buffer metadata, or to send some custom (tag) - * events, or to perform custom (segment) filtering. - * - * - * During the parsing process GstBaseParseClass will handle both srcpad and - * sinkpad events. They will be passed to subclass if @event or - * @src_event callbacks have been provided. - * - * - * - * - * Shutdown phase - * - * GstBaseParse class calls @stop to inform the subclass that data - * parsing will be stopped. - * - * - * - * - * - * Subclass is responsible for providing pad template caps for - * source and sink pads. The pads need to be named "sink" and "src". It also - * needs to set the fixed caps on srcpad, when the format is ensured (e.g. - * when base class calls subclass' @set_sink_caps function). - * - * This base class uses GST_FORMAT_DEFAULT as a meaning of frames. So, - * subclass conversion routine needs to know that conversion from - * GST_FORMAT_TIME to GST_FORMAT_DEFAULT must return the - * frame number that can be found from the given byte position. - * - * GstBaseParse uses subclasses conversion methods also for seeking (or otherwise - * uses its own default one, see also below). - * - * Subclass @start and @stop functions will be called to inform the beginning - * and end of data processing. - * - * Things that subclass need to take care of: - * - * Provide pad templates - * - * Fixate the source pad caps when appropriate - * - * - * Inform base class how big data chunks should be retrieved. This is - * done with @gst_base_parse_set_min_frame_size function. - * - * - * Examine data chunks passed to subclass with @check_valid_frame - * and tell if they contain a valid frame - * - * - * Set the caps and timestamp to frame that is passed to subclass with - * @parse_frame function. - * - * Provide conversion functions - * - * Update the duration information with @gst_base_parse_set_duration - * - * - * Optionally passthrough using @gst_base_parse_set_format - * - * - * Configure various baseparse parameters using @gst_base_parse_set_seek and - * @gst_base_parse_set_frame_props. - * - * - * In particular, if subclass is unable to determine a duration, but - * parsing (or specs) yields a frames per seconds rate, then this can be - * provided to GstBaseParse to enable it to cater for - * buffer time metadata (which will be taken from upstream as much as possible). - * Internally keeping track of frame durations and respective - * sizes that have been pushed provides GstBaseParse with an estimated bitrate. - * A default @convert (used if not overriden) will then use these - * rates to perform obvious conversions. These rates are also used to update - * (estimated) duration at regular frame intervals. - * - * - * - */ - -/* TODO: - * - In push mode provide a queue of adapter-"queued" buffers for upstream - * buffer metadata - * - Queue buffers/events until caps are set - */ - -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif - -#include -#include - -#include "gstbaseparse.h" - -#define MIN_FRAMES_TO_POST_BITRATE 10 -#define TARGET_DIFFERENCE (20 * GST_SECOND) - -GST_DEBUG_CATEGORY_STATIC (gst_base_parse_debug); -#define GST_CAT_DEFAULT gst_base_parse_debug - -/* Supported formats */ -static GstFormat fmtlist[] = { - GST_FORMAT_DEFAULT, - GST_FORMAT_BYTES, - GST_FORMAT_TIME, - 0 -}; - -#define GST_BASE_PARSE_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GST_TYPE_BASE_PARSE, GstBaseParsePrivate)) - -struct _GstBaseParsePrivate -{ - GstActivateMode pad_mode; - - gint64 duration; - GstFormat duration_fmt; - gint64 estimated_duration; - - guint min_frame_size; - guint format; - guint fps_num, fps_den; - gint update_interval; - guint bitrate; - guint lead_in, lead_out; - GstClockTime lead_in_ts, lead_out_ts; - GstBaseParseSeekable seekable; - - gboolean discont; - gboolean flushing; - gboolean drain; - - gint64 offset; - gint64 sync_offset; - GstClockTime next_ts; - GstClockTime prev_ts; - GstClockTime frame_duration; - gboolean seen_keyframe; - gboolean is_video; - - guint64 framecount; - guint64 bytecount; - guint64 data_bytecount; - guint64 acc_duration; - GstClockTime first_frame_ts; - gint64 first_frame_offset; - - gboolean post_min_bitrate; - gboolean post_avg_bitrate; - gboolean post_max_bitrate; - guint min_bitrate; - guint avg_bitrate; - guint max_bitrate; - guint posted_avg_bitrate; - - GList *pending_events; - - GstBuffer *cache; - - /* index entry storage, either ours or provided */ - GstIndex *index; - gint index_id; - gboolean own_index; - /* seek table entries only maintained if upstream is BYTE seekable */ - gboolean upstream_seekable; - gboolean upstream_has_duration; - gint64 upstream_size; - /* minimum distance between two index entries */ - GstClockTimeDiff idx_interval; - /* ts and offset of last entry added */ - GstClockTime index_last_ts; - gint64 index_last_offset; - gboolean index_last_valid; - - /* timestamps currently produced are accurate, e.g. started from 0 onwards */ - gboolean exact_position; - /* seek events are temporarily kept to match them with newsegments */ - GSList *pending_seeks; - - /* reverse playback */ - GSList *buffers_pending; - GSList *buffers_queued; - GSList *buffers_send; - GstClockTime last_ts; - gint64 last_offset; -}; - -typedef struct _GstBaseParseSeek -{ - GstSegment segment; - gboolean accurate; - gint64 offset; - GstClockTime start_ts; -} GstBaseParseSeek; - -#define GST_BASE_PARSE_PASSTHROUGH(parse) \ - (parse->priv->format & GST_BASE_PARSE_FORMAT_PASSTHROUGH) -#define GST_BASE_PARSE_HAS_TIME(parse) \ - (parse->priv->format & GST_BASE_PARSE_FORMAT_HAS_TIME) - - -static GstElementClass *parent_class = NULL; - -static void gst_base_parse_class_init (GstBaseParseClass * klass); -static void gst_base_parse_init (GstBaseParse * parse, - GstBaseParseClass * klass); - -GType -gst_base_parse_get_type (void) -{ - static GType base_parse_type = 0; - - if (!base_parse_type) { - static const GTypeInfo base_parse_info = { - sizeof (GstBaseParseClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) gst_base_parse_class_init, - NULL, - NULL, - sizeof (GstBaseParse), - 0, - (GInstanceInitFunc) gst_base_parse_init, - }; - - base_parse_type = g_type_register_static (GST_TYPE_ELEMENT, - "GstBaseVideoParseBad", &base_parse_info, G_TYPE_FLAG_ABSTRACT); - } - return base_parse_type; -} - -static void gst_base_parse_finalize (GObject * object); - -static GstStateChangeReturn gst_base_parse_change_state (GstElement * element, - GstStateChange transition); -static void gst_base_parse_reset (GstBaseParse * parse); - -static void gst_base_parse_set_index (GstElement * element, GstIndex * index); -static GstIndex *gst_base_parse_get_index (GstElement * element); - -static gboolean gst_base_parse_sink_activate (GstPad * sinkpad); -static gboolean gst_base_parse_sink_activate_push (GstPad * pad, - gboolean active); -static gboolean gst_base_parse_sink_activate_pull (GstPad * pad, - gboolean active); -static gboolean gst_base_parse_handle_seek (GstBaseParse * parse, - GstEvent * event); -static void gst_base_parse_handle_tag (GstBaseParse * parse, GstEvent * event); - -static gboolean gst_base_parse_src_event (GstPad * pad, GstEvent * event); -static gboolean gst_base_parse_sink_event (GstPad * pad, GstEvent * event); -static gboolean gst_base_parse_query (GstPad * pad, GstQuery * query); -static gboolean gst_base_parse_sink_setcaps (GstPad * pad, GstCaps * caps); -static const GstQueryType *gst_base_parse_get_querytypes (GstPad * pad); - -static GstFlowReturn gst_base_parse_chain (GstPad * pad, GstBuffer * buffer); -static void gst_base_parse_loop (GstPad * pad); - -static gboolean gst_base_parse_check_frame (GstBaseParse * parse, - GstBaseParseFrame * frame, guint * framesize, gint * skipsize); -static GstFlowReturn gst_base_parse_parse_frame (GstBaseParse * parse, - GstBaseParseFrame * frame); - -static gboolean gst_base_parse_sink_eventfunc (GstBaseParse * parse, - GstEvent * event); - -static gboolean gst_base_parse_src_eventfunc (GstBaseParse * parse, - GstEvent * event); - -static void gst_base_parse_drain (GstBaseParse * parse); - -static void gst_base_parse_post_bitrates (GstBaseParse * parse, - gboolean post_min, gboolean post_avg, gboolean post_max); - -static gint64 gst_base_parse_find_offset (GstBaseParse * parse, - GstClockTime time, gboolean before, GstClockTime * _ts); -static GstFlowReturn gst_base_parse_locate_time (GstBaseParse * parse, - GstClockTime * _time, gint64 * _offset); - -static GstFlowReturn gst_base_parse_process_fragment (GstBaseParse * parse, - gboolean push_only); - -static void -gst_base_parse_clear_queues (GstBaseParse * parse) -{ - g_slist_foreach (parse->priv->buffers_queued, (GFunc) gst_buffer_unref, NULL); - g_slist_free (parse->priv->buffers_queued); - parse->priv->buffers_queued = NULL; - g_slist_foreach (parse->priv->buffers_pending, (GFunc) gst_buffer_unref, - NULL); - g_slist_free (parse->priv->buffers_pending); - parse->priv->buffers_pending = NULL; - g_slist_foreach (parse->priv->buffers_send, (GFunc) gst_buffer_unref, NULL); - g_slist_free (parse->priv->buffers_send); - parse->priv->buffers_send = NULL; -} - -static void -gst_base_parse_finalize (GObject * object) -{ - GstBaseParse *parse = GST_BASE_PARSE (object); - GstEvent **p_ev; - - g_object_unref (parse->adapter); - - if (parse->pending_segment) { - p_ev = &parse->pending_segment; - gst_event_replace (p_ev, NULL); - } - if (parse->close_segment) { - p_ev = &parse->close_segment; - gst_event_replace (p_ev, NULL); - } - - if (parse->priv->cache) { - gst_buffer_unref (parse->priv->cache); - parse->priv->cache = NULL; - } - - g_list_foreach (parse->priv->pending_events, (GFunc) gst_mini_object_unref, - NULL); - g_list_free (parse->priv->pending_events); - parse->priv->pending_events = NULL; - - if (parse->priv->index) { - gst_object_unref (parse->priv->index); - parse->priv->index = NULL; - } - - gst_base_parse_clear_queues (parse); - - G_OBJECT_CLASS (parent_class)->finalize (object); -} - -static void -gst_base_parse_class_init (GstBaseParseClass * klass) -{ - GObjectClass *gobject_class; - GstElementClass *gstelement_class; - - gobject_class = G_OBJECT_CLASS (klass); - g_type_class_add_private (klass, sizeof (GstBaseParsePrivate)); - parent_class = g_type_class_peek_parent (klass); - gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_base_parse_finalize); - - gstelement_class = (GstElementClass *) klass; - gstelement_class->change_state = - GST_DEBUG_FUNCPTR (gst_base_parse_change_state); - gstelement_class->set_index = GST_DEBUG_FUNCPTR (gst_base_parse_set_index); - gstelement_class->get_index = GST_DEBUG_FUNCPTR (gst_base_parse_get_index); - - /* Default handlers */ - klass->check_valid_frame = gst_base_parse_check_frame; - klass->parse_frame = gst_base_parse_parse_frame; - klass->src_event = gst_base_parse_src_eventfunc; - klass->convert = gst_base_parse_convert_default; - - GST_DEBUG_CATEGORY_INIT (gst_base_parse_debug, "basevideoparse", 0, - "baseparse element"); -} - -static void -gst_base_parse_init (GstBaseParse * parse, GstBaseParseClass * bclass) -{ - GstPadTemplate *pad_template; - - GST_DEBUG_OBJECT (parse, "gst_base_parse_init"); - - parse->priv = GST_BASE_PARSE_GET_PRIVATE (parse); - - pad_template = - gst_element_class_get_pad_template (GST_ELEMENT_CLASS (bclass), "sink"); - g_return_if_fail (pad_template != NULL); - parse->sinkpad = gst_pad_new_from_template (pad_template, "sink"); - gst_pad_set_event_function (parse->sinkpad, - GST_DEBUG_FUNCPTR (gst_base_parse_sink_event)); - gst_pad_set_setcaps_function (parse->sinkpad, - GST_DEBUG_FUNCPTR (gst_base_parse_sink_setcaps)); - gst_pad_set_chain_function (parse->sinkpad, - GST_DEBUG_FUNCPTR (gst_base_parse_chain)); - gst_pad_set_activate_function (parse->sinkpad, - GST_DEBUG_FUNCPTR (gst_base_parse_sink_activate)); - gst_pad_set_activatepush_function (parse->sinkpad, - GST_DEBUG_FUNCPTR (gst_base_parse_sink_activate_push)); - gst_pad_set_activatepull_function (parse->sinkpad, - GST_DEBUG_FUNCPTR (gst_base_parse_sink_activate_pull)); - gst_element_add_pad (GST_ELEMENT (parse), parse->sinkpad); - - GST_DEBUG_OBJECT (parse, "sinkpad created"); - - pad_template = - gst_element_class_get_pad_template (GST_ELEMENT_CLASS (bclass), "src"); - g_return_if_fail (pad_template != NULL); - parse->srcpad = gst_pad_new_from_template (pad_template, "src"); - gst_pad_set_event_function (parse->srcpad, - GST_DEBUG_FUNCPTR (gst_base_parse_src_event)); - gst_pad_set_query_type_function (parse->srcpad, - GST_DEBUG_FUNCPTR (gst_base_parse_get_querytypes)); - gst_pad_set_query_function (parse->srcpad, - GST_DEBUG_FUNCPTR (gst_base_parse_query)); - gst_pad_use_fixed_caps (parse->srcpad); - gst_element_add_pad (GST_ELEMENT (parse), parse->srcpad); - GST_DEBUG_OBJECT (parse, "src created"); - - parse->adapter = gst_adapter_new (); - - parse->priv->pad_mode = GST_ACTIVATE_NONE; - - /* init state */ - gst_base_parse_reset (parse); - GST_DEBUG_OBJECT (parse, "init ok"); -} - -/** - * gst_base_parse_frame_init: - * @parse: #GstBaseParse. - * @fmt: #GstBaseParseFrame. - * - * Sets a #GstBaseParseFrame to initial state. Currently this means - * all fields are zero-ed. - */ -void -gst_base_parse_frame_init (GstBaseParse * parse, GstBaseParseFrame * frame) -{ - memset (frame, 0, sizeof (*frame)); -} - -/* clear == frame no longer to be used following this */ -static void -gst_base_parse_frame_clear (GstBaseParse * parse, GstBaseParseFrame * frame) -{ - /* limited for now */ - if (frame->buffer) { - gst_buffer_unref (frame->buffer); - frame->buffer = NULL; - } -} - -static inline void -gst_base_parse_frame_update (GstBaseParse * parse, GstBaseParseFrame * frame, - GstBuffer * buf) -{ - gst_buffer_replace (&frame->buffer, buf); - if (parse->priv->drain) { - frame->flags |= GST_BASE_PARSE_FRAME_FLAG_DRAIN; - } else { - frame->flags &= ~(GST_BASE_PARSE_FRAME_FLAG_DRAIN); - } - /* losing sync is pretty much a discont (and vice versa), no ? */ - if (!parse->priv->discont) { - frame->flags |= GST_BASE_PARSE_FRAME_FLAG_SYNC; - } else { - frame->flags &= ~(GST_BASE_PARSE_FRAME_FLAG_SYNC); - } -} - -static void -gst_base_parse_reset (GstBaseParse * parse) -{ - GST_OBJECT_LOCK (parse); - gst_segment_init (&parse->segment, GST_FORMAT_TIME); - parse->priv->duration = -1; - parse->priv->min_frame_size = 1; - parse->priv->discont = TRUE; - parse->priv->flushing = FALSE; - parse->priv->offset = 0; - parse->priv->sync_offset = 0; - parse->priv->update_interval = -1; - parse->priv->fps_num = parse->priv->fps_den = 0; - parse->priv->frame_duration = GST_CLOCK_TIME_NONE; - parse->priv->lead_in = parse->priv->lead_out = 0; - parse->priv->lead_in_ts = parse->priv->lead_out_ts = 0; - parse->priv->seekable = GST_BASE_PARSE_SEEK_DEFAULT; - parse->priv->bitrate = 0; - parse->priv->framecount = 0; - parse->priv->bytecount = 0; - parse->priv->acc_duration = 0; - parse->priv->first_frame_ts = GST_CLOCK_TIME_NONE; - parse->priv->first_frame_offset = -1; - parse->priv->estimated_duration = -1; - parse->priv->next_ts = 0; - parse->priv->format = 0; - parse->priv->post_min_bitrate = TRUE; - parse->priv->post_avg_bitrate = TRUE; - parse->priv->post_max_bitrate = TRUE; - parse->priv->min_bitrate = G_MAXUINT; - parse->priv->max_bitrate = 0; - parse->priv->avg_bitrate = 0; - parse->priv->posted_avg_bitrate = 0; - - parse->priv->index_last_ts = GST_CLOCK_TIME_NONE; - parse->priv->index_last_offset = -1; - parse->priv->index_last_valid = TRUE; - parse->priv->upstream_seekable = FALSE; - parse->priv->upstream_size = 0; - parse->priv->upstream_has_duration = FALSE; - parse->priv->idx_interval = 0; - parse->priv->exact_position = TRUE; - parse->priv->seen_keyframe = FALSE; - - parse->priv->last_ts = GST_CLOCK_TIME_NONE; - parse->priv->last_offset = 0; - - if (parse->pending_segment) { - gst_event_unref (parse->pending_segment); - parse->pending_segment = NULL; - } - - g_list_foreach (parse->priv->pending_events, (GFunc) gst_mini_object_unref, - NULL); - g_list_free (parse->priv->pending_events); - parse->priv->pending_events = NULL; - - if (parse->priv->cache) { - gst_buffer_unref (parse->priv->cache); - parse->priv->cache = NULL; - } - - g_slist_foreach (parse->priv->pending_seeks, (GFunc) g_free, NULL); - g_slist_free (parse->priv->pending_seeks); - parse->priv->pending_seeks = NULL; - - GST_OBJECT_UNLOCK (parse); -} - -/** - * gst_base_parse_check_frame: - * @parse: #GstBaseParse. - * @buffer: GstBuffer. - * @framesize: This will be set to tell the found frame size in bytes. - * @skipsize: Output parameter that tells how much data needs to be skipped - * in order to find the following frame header. - * - * Default callback for check_valid_frame. - * - * Returns: Always TRUE. - */ -static gboolean -gst_base_parse_check_frame (GstBaseParse * parse, - GstBaseParseFrame * frame, guint * framesize, gint * skipsize) -{ - *framesize = GST_BUFFER_SIZE (frame->buffer); - *skipsize = 0; - return TRUE; -} - - -/** - * gst_base_parse_parse_frame: - * @parse: #GstBaseParse. - * @buffer: #GstBuffer. - * - * Default callback for parse_frame. - */ -static GstFlowReturn -gst_base_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame) -{ - GstBuffer *buffer = frame->buffer; - - if (!GST_BUFFER_TIMESTAMP_IS_VALID (buffer) && - GST_CLOCK_TIME_IS_VALID (parse->priv->next_ts)) { - GST_BUFFER_TIMESTAMP (buffer) = parse->priv->next_ts; - } - if (!GST_BUFFER_DURATION_IS_VALID (buffer) && - GST_CLOCK_TIME_IS_VALID (parse->priv->frame_duration)) { - GST_BUFFER_DURATION (buffer) = parse->priv->frame_duration; - } - return GST_FLOW_OK; -} - -/** - * gst_base_parse_convert: - * @parse: #GstBaseParse. - * @src_format: #GstFormat describing the source format. - * @src_value: Source value to be converted. - * @dest_format: #GstFormat defining the converted format. - * @dest_value: Pointer where the conversion result will be put. - * - * Converts using configured "convert" vmethod in #GstBaseParse class. - * - * Returns: TRUE if conversion was successful. - */ -static gboolean -gst_base_parse_convert (GstBaseParse * parse, - GstFormat src_format, - gint64 src_value, GstFormat dest_format, gint64 * dest_value) -{ - GstBaseParseClass *klass = GST_BASE_PARSE_GET_CLASS (parse); - gboolean ret; - - g_return_val_if_fail (dest_value != NULL, FALSE); - - if (!klass->convert) - return FALSE; - - ret = klass->convert (parse, src_format, src_value, dest_format, dest_value); - -#ifndef GST_DISABLE_GST_DEBUG - { - if (ret) { - if (src_format == GST_FORMAT_TIME && dest_format == GST_FORMAT_BYTES) { - GST_LOG_OBJECT (parse, - "TIME -> BYTES: %" GST_TIME_FORMAT " -> %" G_GINT64_FORMAT, - GST_TIME_ARGS (src_value), *dest_value); - } else if (dest_format == GST_FORMAT_TIME && - src_format == GST_FORMAT_BYTES) { - GST_LOG_OBJECT (parse, - "BYTES -> TIME: %" G_GINT64_FORMAT " -> %" GST_TIME_FORMAT, - src_value, GST_TIME_ARGS (*dest_value)); - } else { - GST_LOG_OBJECT (parse, - "%s -> %s: %" G_GINT64_FORMAT " -> %" G_GINT64_FORMAT, - GST_STR_NULL (gst_format_get_name (src_format)), - GST_STR_NULL (gst_format_get_name (dest_format)), - src_value, *dest_value); - } - } else { - GST_DEBUG_OBJECT (parse, "conversion failed"); - } - } -#endif - - return ret; -} - -/** - * gst_base_parse_sink_event: - * @pad: #GstPad that received the event. - * @event: #GstEvent to be handled. - * - * Handler for sink pad events. - * - * Returns: TRUE if the event was handled. - */ -static gboolean -gst_base_parse_sink_event (GstPad * pad, GstEvent * event) -{ - GstBaseParse *parse; - GstBaseParseClass *bclass; - gboolean handled = FALSE; - gboolean ret = TRUE; - - parse = GST_BASE_PARSE (gst_pad_get_parent (pad)); - bclass = GST_BASE_PARSE_GET_CLASS (parse); - - GST_DEBUG_OBJECT (parse, "handling event %d, %s", GST_EVENT_TYPE (event), - GST_EVENT_TYPE_NAME (event)); - - /* Cache all events except EOS, NEWSEGMENT and FLUSH_STOP if we have a - * pending segment */ - if (parse->pending_segment && GST_EVENT_TYPE (event) != GST_EVENT_EOS - && GST_EVENT_TYPE (event) != GST_EVENT_NEWSEGMENT - && GST_EVENT_TYPE (event) != GST_EVENT_FLUSH_START - && GST_EVENT_TYPE (event) != GST_EVENT_FLUSH_STOP) { - - if (GST_EVENT_TYPE (event) == GST_EVENT_TAG) - /* See if any bitrate tags were posted */ - gst_base_parse_handle_tag (parse, event); - - parse->priv->pending_events = - g_list_append (parse->priv->pending_events, event); - ret = TRUE; - } else { - - if (GST_EVENT_TYPE (event) == GST_EVENT_EOS && - parse->priv->framecount < MIN_FRAMES_TO_POST_BITRATE) - /* We've not posted bitrate tags yet - do so now */ - gst_base_parse_post_bitrates (parse, TRUE, TRUE, TRUE); - - if (bclass->event) - handled = bclass->event (parse, event); - - if (!handled) - handled = gst_base_parse_sink_eventfunc (parse, event); - - if (!handled) - ret = gst_pad_event_default (pad, event); - } - - gst_object_unref (parse); - GST_DEBUG_OBJECT (parse, "event handled"); - return ret; -} - - -/** - * gst_base_parse_sink_eventfunc: - * @parse: #GstBaseParse. - * @event: #GstEvent to be handled. - * - * Element-level event handler function. - * - * The event will be unreffed only if it has been handled and this - * function returns %TRUE - * - * Returns: %TRUE if the event was handled and not need forwarding. - */ -static gboolean -gst_base_parse_sink_eventfunc (GstBaseParse * parse, GstEvent * event) -{ - gboolean handled = FALSE; - GstEvent **eventp; - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_NEWSEGMENT: - { - gdouble rate, applied_rate; - GstFormat format; - gint64 start, stop, pos, next_ts, offset = 0; - gboolean update; - - gst_event_parse_new_segment_full (event, &update, &rate, &applied_rate, - &format, &start, &stop, &pos); - - GST_DEBUG_OBJECT (parse, "newseg rate %g, applied rate %g, " - "format %d, start = %" GST_TIME_FORMAT ", stop = %" GST_TIME_FORMAT - ", pos = %" GST_TIME_FORMAT, rate, applied_rate, format, - GST_TIME_ARGS (start), GST_TIME_ARGS (stop), GST_TIME_ARGS (pos)); - - if (format == GST_FORMAT_BYTES) { - GstClockTime seg_start, seg_stop; - GstBaseParseSeek *seek = NULL; - GSList *node; - - /* stop time is allowed to be open-ended, but not start & pos */ - seg_stop = GST_CLOCK_TIME_NONE; - seg_start = 0; - offset = pos; - - GST_OBJECT_LOCK (parse); - for (node = parse->priv->pending_seeks; node; node = node->next) { - GstBaseParseSeek *tmp = node->data; - - if (tmp->offset == pos) { - seek = tmp; - break; - } - } - parse->priv->pending_seeks = - g_slist_remove (parse->priv->pending_seeks, seek); - GST_OBJECT_UNLOCK (parse); - - if (seek) { - GST_DEBUG_OBJECT (parse, - "Matched newsegment to%s seek: %" GST_SEGMENT_FORMAT, - seek->accurate ? " accurate" : "", &seek->segment); - seg_start = seek->segment.start; - seg_stop = seek->segment.stop; - next_ts = seek->start_ts; - parse->priv->exact_position = seek->accurate; - g_free (seek); - } else { - /* best attempt convert */ - /* as these are only estimates, stop is kept open-ended to avoid - * premature cutting */ - gst_base_parse_convert (parse, GST_FORMAT_BYTES, start, - GST_FORMAT_TIME, (gint64 *) & seg_start); - parse->priv->exact_position = (start == 0); - next_ts = seg_start; - } - - gst_event_unref (event); - event = gst_event_new_new_segment_full (update, rate, applied_rate, - GST_FORMAT_TIME, seg_start, seg_stop, seg_start); - format = GST_FORMAT_TIME; - start = seg_start; - stop = seg_stop; - GST_DEBUG_OBJECT (parse, "Converted incoming segment to TIME. " - "start = %" GST_TIME_FORMAT ", stop = %" GST_TIME_FORMAT, - GST_TIME_ARGS (seg_start), GST_TIME_ARGS (seg_stop)); - } else if (format != GST_FORMAT_TIME) { - /* Unknown incoming segment format. Output a default open-ended - * TIME segment */ - gst_event_unref (event); - event = gst_event_new_new_segment_full (update, rate, applied_rate, - GST_FORMAT_TIME, 0, GST_CLOCK_TIME_NONE, 0); - format = GST_FORMAT_TIME; - next_ts = start = 0; - stop = GST_CLOCK_TIME_NONE; - } else { - /* not considered BYTE seekable if it is talking to us in TIME, - * whatever else it might claim */ - parse->priv->upstream_seekable = FALSE; - next_ts = start; - } - - gst_segment_set_newsegment_full (&parse->segment, update, rate, - applied_rate, format, start, stop, start); - - /* save the segment for later, right before we push a new buffer so that - * the caps are fixed and the next linked element can receive - * the segment. */ - eventp = &parse->pending_segment; - gst_event_replace (eventp, event); - gst_event_unref (event); - handled = TRUE; - - /* but finish the current segment */ - GST_DEBUG_OBJECT (parse, "draining current segment"); - if (parse->segment.rate > 0.0) - gst_base_parse_drain (parse); - else - gst_base_parse_process_fragment (parse, FALSE); - gst_adapter_clear (parse->adapter); - parse->priv->offset = offset; - parse->priv->sync_offset = offset; - parse->priv->next_ts = next_ts; - parse->priv->last_ts = GST_CLOCK_TIME_NONE; - parse->priv->discont = TRUE; - parse->priv->seen_keyframe = FALSE; - break; - } - - case GST_EVENT_FLUSH_START: - parse->priv->flushing = TRUE; - handled = gst_pad_push_event (parse->srcpad, gst_event_ref (event)); - if (handled) - gst_event_unref (event); - /* Wait for _chain() to exit by taking the srcpad STREAM_LOCK */ - GST_PAD_STREAM_LOCK (parse->srcpad); - GST_PAD_STREAM_UNLOCK (parse->srcpad); - - break; - - case GST_EVENT_FLUSH_STOP: - gst_adapter_clear (parse->adapter); - gst_base_parse_clear_queues (parse); - parse->priv->flushing = FALSE; - parse->priv->discont = TRUE; - parse->priv->last_ts = GST_CLOCK_TIME_NONE; - break; - - case GST_EVENT_EOS: - if (parse->segment.rate > 0.0) - gst_base_parse_drain (parse); - else - gst_base_parse_process_fragment (parse, FALSE); - - /* If we STILL have zero frames processed, fire an error */ - if (parse->priv->framecount == 0) { - GST_ELEMENT_ERROR (parse, STREAM, WRONG_TYPE, - ("No valid frames found before end of stream"), (NULL)); - } - /* newsegment before eos */ - if (parse->pending_segment) { - gst_pad_push_event (parse->srcpad, parse->pending_segment); - parse->pending_segment = NULL; - } - break; - - default: - break; - } - - return handled; -} - - -/** - * gst_base_parse_src_event: - * @pad: #GstPad that received the event. - * @event: #GstEvent that was received. - * - * Handler for source pad events. - * - * Returns: TRUE if the event was handled. - */ -static gboolean -gst_base_parse_src_event (GstPad * pad, GstEvent * event) -{ - GstBaseParse *parse; - GstBaseParseClass *bclass; - gboolean handled = FALSE; - gboolean ret = TRUE; - - parse = GST_BASE_PARSE (gst_pad_get_parent (pad)); - bclass = GST_BASE_PARSE_GET_CLASS (parse); - - GST_DEBUG_OBJECT (parse, "event %d, %s", GST_EVENT_TYPE (event), - GST_EVENT_TYPE_NAME (event)); - - if (bclass->src_event) - handled = bclass->src_event (parse, event); - - if (!handled) - ret = gst_pad_event_default (pad, event); - - gst_object_unref (parse); - return ret; -} - - -/** - * gst_base_parse_src_eventfunc: - * @parse: #GstBaseParse. - * @event: #GstEvent that was received. - * - * Default srcpad event handler. - * - * Returns: TRUE if the event was handled and can be dropped. - */ -static gboolean -gst_base_parse_src_eventfunc (GstBaseParse * parse, GstEvent * event) -{ - gboolean handled = FALSE; - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_SEEK: - { - if (parse->priv->seekable > GST_BASE_PARSE_SEEK_NONE) { - handled = gst_base_parse_handle_seek (parse, event); - } - break; - } - default: - break; - } - return handled; -} - - -/** - * gst_base_parse_convert_default: - * @parse: #GstBaseParse. - * @src_format: #GstFormat describing the source format. - * @src_value: Source value to be converted. - * @dest_format: #GstFormat defining the converted format. - * @dest_value: Pointer where the conversion result will be put. - * - * Default implementation of "convert" vmethod in #GstBaseParse class. - * - * Returns: TRUE if conversion was successful. - */ -gboolean -gst_base_parse_convert_default (GstBaseParse * parse, - GstFormat src_format, - gint64 src_value, GstFormat dest_format, gint64 * dest_value) -{ - gboolean ret = FALSE; - guint64 bytes, duration; - - if (G_UNLIKELY (src_format == dest_format)) { - *dest_value = src_value; - return TRUE; - } - - if (G_UNLIKELY (src_value == -1)) { - *dest_value = -1; - return TRUE; - } - - if (G_UNLIKELY (src_value == 0)) { - *dest_value = 0; - return TRUE; - } - - /* need at least some frames */ - if (!parse->priv->framecount) - return FALSE; - - duration = parse->priv->acc_duration / GST_MSECOND; - bytes = parse->priv->bytecount; - - if (G_UNLIKELY (!duration || !bytes)) - return FALSE; - - if (src_format == GST_FORMAT_BYTES) { - if (dest_format == GST_FORMAT_TIME) { - /* BYTES -> TIME conversion */ - GST_DEBUG_OBJECT (parse, "converting bytes -> time"); - *dest_value = gst_util_uint64_scale (src_value, duration, bytes); - *dest_value *= GST_MSECOND; - GST_DEBUG_OBJECT (parse, "conversion result: %" G_GINT64_FORMAT " ms", - *dest_value / GST_MSECOND); - ret = TRUE; - } - } else if (src_format == GST_FORMAT_TIME) { - if (dest_format == GST_FORMAT_BYTES) { - GST_DEBUG_OBJECT (parse, "converting time -> bytes"); - *dest_value = gst_util_uint64_scale (src_value / GST_MSECOND, bytes, - duration); - GST_DEBUG_OBJECT (parse, - "time %" G_GINT64_FORMAT " ms in bytes = %" G_GINT64_FORMAT, - src_value / GST_MSECOND, *dest_value); - ret = TRUE; - } - } else if (src_format == GST_FORMAT_DEFAULT) { - /* DEFAULT == frame-based */ - if (dest_format == GST_FORMAT_TIME) { - if (parse->priv->fps_den) { - *dest_value = gst_util_uint64_scale (src_value, - GST_SECOND * parse->priv->fps_den, parse->priv->fps_num); - ret = TRUE; - } - } else if (dest_format == GST_FORMAT_BYTES) { - } - } - - return ret; -} - -/** - * gst_base_parse_update_duration: - * @parse: #GstBaseParse. - * - */ -static void -gst_base_parse_update_duration (GstBaseParse * aacparse) -{ - GstPad *peer; - GstBaseParse *parse; - - parse = GST_BASE_PARSE (aacparse); - - peer = gst_pad_get_peer (parse->sinkpad); - if (peer) { - GstFormat pformat = GST_FORMAT_BYTES; - gboolean qres = FALSE; - gint64 ptot, dest_value; - - qres = gst_pad_query_duration (peer, &pformat, &ptot); - gst_object_unref (GST_OBJECT (peer)); - if (qres) { - if (gst_base_parse_convert (parse, pformat, ptot, - GST_FORMAT_TIME, &dest_value)) { - parse->priv->estimated_duration = dest_value; - GST_LOG_OBJECT (parse, - "updated estimated duration to %" GST_TIME_FORMAT, - GST_TIME_ARGS (dest_value)); - } - } - } -} - -static void -gst_base_parse_post_bitrates (GstBaseParse * parse, gboolean post_min, - gboolean post_avg, gboolean post_max) -{ - GstTagList *taglist = gst_tag_list_new (); - - if (post_min && parse->priv->post_min_bitrate) - gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, - GST_TAG_MINIMUM_BITRATE, parse->priv->min_bitrate, NULL); - - if (post_avg && parse->priv->post_avg_bitrate) { - parse->priv->posted_avg_bitrate = parse->priv->avg_bitrate; - gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, GST_TAG_BITRATE, - parse->priv->avg_bitrate, NULL); - } - - if (post_max && parse->priv->post_max_bitrate) - gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE, - GST_TAG_MAXIMUM_BITRATE, parse->priv->max_bitrate, NULL); - - GST_DEBUG_OBJECT (parse, "Updated bitrates. Min: %u, Avg: %u, Max: %u", - parse->priv->min_bitrate, parse->priv->avg_bitrate, - parse->priv->max_bitrate); - - gst_element_found_tags_for_pad (GST_ELEMENT (parse), parse->srcpad, taglist); -} - -/** - * gst_base_parse_update_bitrates: - * @parse: #GstBaseParse. - * @buffer: Current frame as a #GstBuffer - * - * Keeps track of the minimum and maximum bitrates, and also maintains a - * running average bitrate of the stream so far. - */ -static void -gst_base_parse_update_bitrates (GstBaseParse * parse, GstBaseParseFrame * frame) -{ - /* Only update the tag on a 10 kbps delta */ - static const gint update_threshold = 10000; - - GstBaseParseClass *klass; - guint64 data_len, frame_dur; - gint overhead, frame_bitrate, old_avg_bitrate; - gboolean update_min = FALSE, update_avg = FALSE, update_max = FALSE; - GstBuffer *buffer = frame->buffer; - - klass = GST_BASE_PARSE_GET_CLASS (parse); - - overhead = frame->overhead; - if (overhead == -1) - return; - - data_len = GST_BUFFER_SIZE (buffer) - overhead; - parse->priv->data_bytecount += data_len; - - /* duration should be valid by now, - * either set by subclass or maybe based on fps settings */ - if (GST_BUFFER_DURATION_IS_VALID (buffer) && parse->priv->acc_duration != 0) { - /* Calculate duration of a frame from buffer properties */ - frame_dur = GST_BUFFER_DURATION (buffer); - parse->priv->avg_bitrate = (8 * parse->priv->data_bytecount * GST_SECOND) / - parse->priv->acc_duration; - - } else { - /* No way to figure out frame duration (is this even possible?) */ - return; - } - - /* override if subclass provided bitrate, e.g. metadata based */ - if (parse->priv->bitrate) { - parse->priv->avg_bitrate = parse->priv->bitrate; - /* spread this (confirmed) info ASAP */ - if (parse->priv->posted_avg_bitrate != parse->priv->avg_bitrate) - gst_base_parse_post_bitrates (parse, FALSE, TRUE, FALSE); - } - - if (frame_dur) - frame_bitrate = (8 * data_len * GST_SECOND) / frame_dur; - else - return; - - GST_LOG_OBJECT (parse, "frame bitrate %u, avg bitrate %u", frame_bitrate, - parse->priv->avg_bitrate); - - if (parse->priv->framecount < MIN_FRAMES_TO_POST_BITRATE) { - goto exit; - } else if (parse->priv->framecount == MIN_FRAMES_TO_POST_BITRATE) { - /* always post all at threshold time */ - update_min = update_max = update_avg = TRUE; - } - - if (G_LIKELY (parse->priv->framecount >= MIN_FRAMES_TO_POST_BITRATE)) { - if (frame_bitrate < parse->priv->min_bitrate) { - parse->priv->min_bitrate = frame_bitrate; - update_min = TRUE; - } - - if (frame_bitrate > parse->priv->max_bitrate) { - parse->priv->max_bitrate = frame_bitrate; - update_max = TRUE; - } - - old_avg_bitrate = parse->priv->posted_avg_bitrate; - if ((gint) (old_avg_bitrate - parse->priv->avg_bitrate) > update_threshold - || (gint) (parse->priv->avg_bitrate - old_avg_bitrate) > - update_threshold) - update_avg = TRUE; - } - - if ((update_min || update_avg || update_max)) - gst_base_parse_post_bitrates (parse, update_min, update_avg, update_max); - - /* If average bitrate changes that much and no valid (time) duration provided, - * then post a new duration message so applications can update their cached - * values */ - if (update_avg && !(parse->priv->duration_fmt == GST_FORMAT_TIME && - GST_CLOCK_TIME_IS_VALID (parse->priv->duration))) - gst_element_post_message (GST_ELEMENT (parse), - gst_message_new_duration (GST_OBJECT (parse), GST_FORMAT_TIME, -1)); - -exit: - return; -} - -/** - * gst_base_parse_add_index_entry: - * @parse: #GstBaseParse. - * @offset: offset of entry - * @ts: timestamp associated with offset - * @key: whether entry refers to keyframe - * @force: add entry disregarding sanity checks - * - * Adds an entry to the index associating @offset to @ts. It is recommended - * to only add keyframe entries. @force allows to bypass checks, such as - * whether the stream is (upstream) seekable, another entry is already "close" - * to the new entry, etc. - * - * Returns: #gboolean indicating whether entry was added - */ -gboolean -gst_base_parse_add_index_entry (GstBaseParse * parse, guint64 offset, - GstClockTime ts, gboolean key, gboolean force) -{ - gboolean ret = FALSE; - GstIndexAssociation associations[2]; - - GST_LOG_OBJECT (parse, "Adding key=%d index entry %" GST_TIME_FORMAT - " @ offset 0x%08" G_GINT64_MODIFIER "x", key, GST_TIME_ARGS (ts), offset); - - if (G_LIKELY (!force)) { - - if (!parse->priv->upstream_seekable) { - GST_DEBUG_OBJECT (parse, "upstream not seekable; discarding"); - goto exit; - } - - /* FIXME need better helper data structure that handles these issues - * related to ongoing collecting of index entries */ - if (parse->priv->index_last_offset >= (gint64) offset) { - GST_DEBUG_OBJECT (parse, "already have entries up to offset " - "0x%08" G_GINT64_MODIFIER "x", parse->priv->index_last_offset); - goto exit; - } - - if (GST_CLOCK_TIME_IS_VALID (parse->priv->index_last_ts) && - GST_CLOCK_DIFF (parse->priv->index_last_ts, ts) < - parse->priv->idx_interval) { - GST_DEBUG_OBJECT (parse, "entry too close to last time %" GST_TIME_FORMAT, - GST_TIME_ARGS (parse->priv->index_last_ts)); - goto exit; - } - - /* if last is not really the last one */ - if (!parse->priv->index_last_valid) { - GstClockTime prev_ts; - - gst_base_parse_find_offset (parse, ts, TRUE, &prev_ts); - if (GST_CLOCK_DIFF (prev_ts, ts) < parse->priv->idx_interval) { - GST_DEBUG_OBJECT (parse, - "entry too close to existing entry %" GST_TIME_FORMAT, - GST_TIME_ARGS (prev_ts)); - parse->priv->index_last_offset = offset; - parse->priv->index_last_ts = ts; - goto exit; - } - } - } - - associations[0].format = GST_FORMAT_TIME; - associations[0].value = ts; - associations[1].format = GST_FORMAT_BYTES; - associations[1].value = offset; - - /* index might change on-the-fly, although that would be nutty app ... */ - GST_OBJECT_LOCK (parse); - gst_index_add_associationv (parse->priv->index, parse->priv->index_id, - (key) ? GST_ASSOCIATION_FLAG_KEY_UNIT : GST_ASSOCIATION_FLAG_NONE, - 2, (const GstIndexAssociation *) &associations); - GST_OBJECT_UNLOCK (parse); - - if (key) { - parse->priv->index_last_offset = offset; - parse->priv->index_last_ts = ts; - } - - ret = TRUE; - -exit: - return ret; -} - -/* check for seekable upstream, above and beyond a mere query */ -static void -gst_base_parse_check_seekability (GstBaseParse * parse) -{ - GstQuery *query; - gboolean seekable = FALSE; - gint64 start = -1, stop = -1; - guint idx_interval = 0; - - query = gst_query_new_seeking (GST_FORMAT_BYTES); - if (!gst_pad_peer_query (parse->sinkpad, query)) { - GST_DEBUG_OBJECT (parse, "seeking query failed"); - goto done; - } - - gst_query_parse_seeking (query, NULL, &seekable, &start, &stop); - - /* try harder to query upstream size if we didn't get it the first time */ - if (seekable && stop == -1) { - GstFormat fmt = GST_FORMAT_BYTES; - - GST_DEBUG_OBJECT (parse, "doing duration query to fix up unset stop"); - gst_pad_query_peer_duration (parse->sinkpad, &fmt, &stop); - } - - /* if upstream doesn't know the size, it's likely that it's not seekable in - * practice even if it technically may be seekable */ - if (seekable && (start != 0 || stop <= start)) { - GST_DEBUG_OBJECT (parse, "seekable but unknown start/stop -> disable"); - seekable = FALSE; - } - - /* let's not put every single frame into our index */ - if (seekable) { - if (stop < 10 * 1024 * 1024) - idx_interval = 100; - else if (stop < 100 * 1024 * 1024) - idx_interval = 500; - else - idx_interval = 1000; - } - -done: - gst_query_unref (query); - - GST_DEBUG_OBJECT (parse, "seekable: %d (%" G_GUINT64_FORMAT " - %" - G_GUINT64_FORMAT ")", seekable, start, stop); - parse->priv->upstream_seekable = seekable; - parse->priv->upstream_size = seekable ? stop : 0; - - GST_DEBUG_OBJECT (parse, "idx_interval: %ums", idx_interval); - parse->priv->idx_interval = idx_interval * GST_MSECOND; -} - -/* some misc checks on upstream */ -static void -gst_base_parse_check_upstream (GstBaseParse * parse) -{ - GstFormat fmt = GST_FORMAT_TIME; - gint64 stop; - - if (gst_pad_query_peer_duration (parse->sinkpad, &fmt, &stop)) - if (GST_CLOCK_TIME_IS_VALID (stop) && stop) { - /* upstream has one, accept it also, and no further updates */ - gst_base_parse_set_duration (parse, GST_FORMAT_TIME, stop, 0); - parse->priv->upstream_has_duration = TRUE; - } - - GST_DEBUG_OBJECT (parse, "upstream_has_duration: %d", - parse->priv->upstream_has_duration); -} - -/* checks src caps to determine if dealing with audio or video */ -/* TODO maybe forego automagic stuff and let subclass configure it ? */ -static void -gst_base_parse_check_media (GstBaseParse * parse) -{ - GstCaps *caps; - GstStructure *s; - - caps = GST_PAD_CAPS (parse->srcpad); - if (G_LIKELY (caps) && (s = gst_caps_get_structure (caps, 0))) { - parse->priv->is_video = - g_str_has_prefix (gst_structure_get_name (s), "video"); - } else { - /* historical default */ - parse->priv->is_video = FALSE; - } - - GST_DEBUG_OBJECT (parse, "media is video == %d", parse->priv->is_video); -} - -/** - * gst_base_parse_handle_and_push_buffer: - * @parse: #GstBaseParse. - * @klass: #GstBaseParseClass. - * @buffer: #GstBuffer. - * - * Parses the frame from given buffer and pushes it forward. Also performs - * timestamp handling and checks the segment limits. - * - * This is called with srcpad STREAM_LOCK held. - * - * Returns: #GstFlowReturn - */ -static GstFlowReturn -gst_base_parse_handle_and_push_frame (GstBaseParse * parse, - GstBaseParseClass * klass, GstBaseParseFrame * frame) -{ - GstFlowReturn ret; - gint64 offset; - GstBuffer *buffer; - - g_return_val_if_fail (frame != NULL, GST_FLOW_ERROR); - - buffer = frame->buffer; - - if (parse->priv->discont) { - GST_DEBUG_OBJECT (parse, "marking DISCONT"); - GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT); - parse->priv->discont = FALSE; - } - - /* some one-time start-up */ - if (G_UNLIKELY (!parse->priv->framecount)) { - gst_base_parse_check_seekability (parse); - gst_base_parse_check_upstream (parse); - } - - GST_LOG_OBJECT (parse, - "parsing frame at offset %" G_GUINT64_FORMAT - " (%#" G_GINT64_MODIFIER "x) of size %d", - GST_BUFFER_OFFSET (buffer), GST_BUFFER_OFFSET (buffer), - GST_BUFFER_SIZE (buffer)); - - /* use default handler to provide initial (upstream) metadata */ - gst_base_parse_parse_frame (parse, frame); - - /* store offset as it might get overwritten */ - offset = GST_BUFFER_OFFSET (buffer); - ret = klass->parse_frame (parse, frame); - /* sync */ - buffer = frame->buffer; - /* subclass must play nice */ - g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR); - - /* check if subclass/format can provide ts. - * If so, that allows and enables extra seek and duration determining options */ - if (G_UNLIKELY (parse->priv->first_frame_offset < 0 && ret == GST_FLOW_OK)) { - if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) && - GST_BASE_PARSE_HAS_TIME (parse) && - parse->priv->pad_mode == GST_ACTIVATE_PULL) { - parse->priv->first_frame_offset = offset; - parse->priv->first_frame_ts = GST_BUFFER_TIMESTAMP (buffer); - GST_DEBUG_OBJECT (parse, "subclass provided ts %" GST_TIME_FORMAT - " for first frame at offset %" G_GINT64_FORMAT, - GST_TIME_ARGS (parse->priv->first_frame_ts), - parse->priv->first_frame_offset); - if (!GST_CLOCK_TIME_IS_VALID (parse->priv->duration)) { - gint64 off; - GstClockTime last_ts = G_MAXINT64; - - GST_DEBUG_OBJECT (parse, "no duration; trying scan to determine"); - gst_base_parse_locate_time (parse, &last_ts, &off); - if (GST_CLOCK_TIME_IS_VALID (last_ts)) - gst_base_parse_set_duration (parse, GST_FORMAT_TIME, last_ts, 0); - } - } else { - /* disable further checks */ - parse->priv->first_frame_offset = 0; - } - } - - /* again use default handler to add missing metadata; - * we may have new information on frame properties */ - gst_base_parse_parse_frame (parse, frame); - if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) && - GST_BUFFER_DURATION_IS_VALID (buffer)) { - parse->priv->next_ts = - GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer); - } else { - /* we lost track, do not produce bogus time next time around - * (probably means parser subclass has given up on parsing as well) */ - GST_DEBUG_OBJECT (parse, "no next fallback timestamp"); - parse->priv->next_ts = GST_CLOCK_TIME_NONE; - } - - if (parse->priv->upstream_seekable && parse->priv->exact_position && - GST_BUFFER_TIMESTAMP_IS_VALID (buffer)) - gst_base_parse_add_index_entry (parse, offset, - GST_BUFFER_TIMESTAMP (buffer), - !GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT), FALSE); - - /* First buffers are dropped, this means that the subclass needs more - * frames to decide on the format and queues them internally */ - /* convert internal flow to OK and mark discont for the next buffer. */ - if (ret == GST_BASE_PARSE_FLOW_DROPPED) { - gst_base_parse_frame_clear (parse, frame); - return GST_FLOW_OK; - } else if (ret != GST_FLOW_OK) { - return ret; - } - - return gst_base_parse_push_frame (parse, frame); -} - -/** - * gst_base_parse_push_frame: - * @parse: #GstBaseParse. - * @frame: #GstBaseParseFrame. - * - * Pushes the frame downstream, sends any pending events and - * does some timestamp and segment handling. - * - * This must be called with sinkpad STREAM_LOCK held. - * - * Returns: #GstFlowReturn - */ -GstFlowReturn -gst_base_parse_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame) -{ - GstFlowReturn ret = GST_FLOW_OK; - GstClockTime last_start = GST_CLOCK_TIME_NONE; - GstClockTime last_stop = GST_CLOCK_TIME_NONE; - GstBaseParseClass *klass = GST_BASE_PARSE_GET_CLASS (parse); - GstBuffer *buffer; - - g_return_val_if_fail (frame != NULL, GST_FLOW_ERROR); - g_return_val_if_fail (frame->buffer != NULL, GST_FLOW_ERROR); - - buffer = frame->buffer; - - GST_LOG_OBJECT (parse, - "processing buffer of size %d with ts %" GST_TIME_FORMAT - ", duration %" GST_TIME_FORMAT, GST_BUFFER_SIZE (buffer), - GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)), - GST_TIME_ARGS (GST_BUFFER_DURATION (buffer))); - - /* update stats */ - parse->priv->bytecount += GST_BUFFER_SIZE (buffer); - if (G_LIKELY (!(frame->flags & GST_BASE_PARSE_FRAME_FLAG_NO_FRAME))) { - parse->priv->framecount++; - if (GST_BUFFER_DURATION_IS_VALID (buffer)) { - parse->priv->acc_duration += GST_BUFFER_DURATION (buffer); - } - } - /* 0 means disabled */ - if (parse->priv->update_interval < 0) - parse->priv->update_interval = 50; - else if (parse->priv->update_interval > 0 && - (parse->priv->framecount % parse->priv->update_interval) == 0) - gst_base_parse_update_duration (parse); - - if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer)) - last_start = last_stop = GST_BUFFER_TIMESTAMP (buffer); - if (last_start != GST_CLOCK_TIME_NONE - && GST_BUFFER_DURATION_IS_VALID (buffer)) - last_stop = last_start + GST_BUFFER_DURATION (buffer); - - /* should have caps by now */ - g_return_val_if_fail (GST_PAD_CAPS (parse->srcpad), GST_FLOW_ERROR); - - /* segment adjustment magic; only if we are running the whole show */ - if (!GST_BASE_PARSE_PASSTHROUGH (parse) && parse->segment.rate > 0.0 && - (parse->priv->pad_mode == GST_ACTIVATE_PULL || - parse->priv->upstream_seekable)) { - /* segment times are typically estimates, - * actual frame data might lead subclass to different timestamps, - * so override segment start from what is supplied there */ - if (G_UNLIKELY (parse->pending_segment && !parse->priv->exact_position && - GST_CLOCK_TIME_IS_VALID (last_start))) { - gst_event_unref (parse->pending_segment); - parse->segment.start = - MIN ((guint64) last_start, (guint64) parse->segment.stop); - GST_DEBUG_OBJECT (parse, - "adjusting pending segment start to %" GST_TIME_FORMAT, - GST_TIME_ARGS (parse->segment.start)); - parse->pending_segment = - gst_event_new_new_segment (FALSE, parse->segment.rate, - parse->segment.format, parse->segment.start, parse->segment.stop, - parse->segment.start); - } - /* handle gaps, e.g. non-zero start-time, in as much not handled by above */ - if (GST_CLOCK_TIME_IS_VALID (parse->segment.last_stop) && - GST_CLOCK_TIME_IS_VALID (last_start)) { - GstClockTimeDiff diff; - - /* only send newsegments with increasing start times, - * otherwise if these go back and forth downstream (sinks) increase - * accumulated time and running_time */ - diff = GST_CLOCK_DIFF (parse->segment.last_stop, last_start); - if (G_UNLIKELY (diff > 2 * GST_SECOND && last_start > parse->segment.start - && (!GST_CLOCK_TIME_IS_VALID (parse->segment.stop) || - last_start < parse->segment.stop))) { - GST_DEBUG_OBJECT (parse, - "Gap of %" G_GINT64_FORMAT " ns detected in stream " - "(%" GST_TIME_FORMAT " -> %" GST_TIME_FORMAT "). " - "Sending updated NEWSEGMENT events", diff, - GST_TIME_ARGS (parse->segment.last_stop), - GST_TIME_ARGS (last_start)); - if (G_UNLIKELY (parse->pending_segment)) { - gst_event_unref (parse->pending_segment); - parse->segment.start = last_start; - parse->pending_segment = - gst_event_new_new_segment (FALSE, parse->segment.rate, - parse->segment.format, parse->segment.start, parse->segment.stop, - parse->segment.start); - } else { - /* send newsegment events such that the gap is not accounted in - * accum time, hence running_time */ - /* close ahead of gap */ - gst_pad_push_event (parse->srcpad, - gst_event_new_new_segment (TRUE, parse->segment.rate, - parse->segment.format, parse->segment.last_stop, - parse->segment.last_stop, parse->segment.last_stop)); - /* skip gap */ - gst_pad_push_event (parse->srcpad, - gst_event_new_new_segment (FALSE, parse->segment.rate, - parse->segment.format, last_start, parse->segment.stop, - last_start)); - } - /* align segment view with downstream, - * prevents double-counting accum when closing segment */ - gst_segment_set_newsegment (&parse->segment, FALSE, - parse->segment.rate, parse->segment.format, last_start, - parse->segment.stop, last_start); - parse->segment.last_stop = last_start; - } - } - } - - /* and should then also be linked downstream, so safe to send some events */ - if (G_UNLIKELY (parse->close_segment)) { - /* only set up by loop */ - GST_DEBUG_OBJECT (parse, "loop sending close segment"); - gst_pad_push_event (parse->srcpad, parse->close_segment); - parse->close_segment = NULL; - } - if (G_UNLIKELY (parse->pending_segment)) { - GST_DEBUG_OBJECT (parse, "%s push pending segment", - parse->priv->pad_mode == GST_ACTIVATE_PULL ? "loop" : "chain"); - gst_pad_push_event (parse->srcpad, parse->pending_segment); - parse->pending_segment = NULL; - - /* have caps; check identity */ - gst_base_parse_check_media (parse); - } - - /* update bitrates and optionally post corresponding tags - * (following newsegment) */ - gst_base_parse_update_bitrates (parse, frame); - - if (G_UNLIKELY (parse->priv->pending_events)) { - GList *l; - - for (l = parse->priv->pending_events; l != NULL; l = l->next) { - gst_pad_push_event (parse->srcpad, GST_EVENT (l->data)); - } - g_list_free (parse->priv->pending_events); - parse->priv->pending_events = NULL; - } - - if (klass->pre_push_frame) { - ret = klass->pre_push_frame (parse, frame); - } else { - frame->flags |= GST_BASE_PARSE_FRAME_FLAG_CLIP; - } - - /* take final ownership of frame buffer */ - buffer = frame->buffer; - frame->buffer = NULL; - - /* subclass must play nice */ - g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR); - - /* decorate */ - gst_buffer_set_caps (buffer, GST_PAD_CAPS (parse->srcpad)); - - parse->priv->seen_keyframe |= parse->priv->is_video && - !GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT); - - if (frame->flags & GST_BASE_PARSE_FRAME_FLAG_CLIP) { - if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) && - GST_CLOCK_TIME_IS_VALID (parse->segment.stop) && - GST_BUFFER_TIMESTAMP (buffer) > - parse->segment.stop + parse->priv->lead_out_ts) { - GST_LOG_OBJECT (parse, "Dropped frame, after segment"); - ret = GST_FLOW_UNEXPECTED; - } else if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) && - GST_BUFFER_DURATION_IS_VALID (buffer) && - GST_CLOCK_TIME_IS_VALID (parse->segment.start) && - GST_BUFFER_TIMESTAMP (buffer) + GST_BUFFER_DURATION (buffer) + - parse->priv->lead_in_ts < parse->segment.start) { - if (parse->priv->seen_keyframe) { - GST_LOG_OBJECT (parse, "Frame before segment, after keyframe"); - ret = GST_FLOW_OK; - } else { - GST_LOG_OBJECT (parse, "Dropped frame, before segment"); - ret = GST_BASE_PARSE_FLOW_DROPPED; - } - } else { - ret = GST_FLOW_OK; - } - } - - if (ret == GST_BASE_PARSE_FLOW_DROPPED) { - GST_LOG_OBJECT (parse, "frame (%d bytes) dropped", - GST_BUFFER_SIZE (buffer)); - gst_buffer_unref (buffer); - ret = GST_FLOW_OK; - } else if (ret == GST_FLOW_OK) { - if (parse->segment.rate > 0.0) { - ret = gst_pad_push (parse->srcpad, buffer); - GST_LOG_OBJECT (parse, "frame (%d bytes) pushed: %s", - GST_BUFFER_SIZE (buffer), gst_flow_get_name (ret)); - } else { - GST_LOG_OBJECT (parse, "frame (%d bytes) queued for now", - GST_BUFFER_SIZE (buffer)); - parse->priv->buffers_queued = - g_slist_prepend (parse->priv->buffers_queued, buffer); - ret = GST_FLOW_OK; - } - } else { - gst_buffer_unref (buffer); - GST_LOG_OBJECT (parse, "frame (%d bytes) not pushed: %s", - GST_BUFFER_SIZE (buffer), gst_flow_get_name (ret)); - /* if we are not sufficiently in control, let upstream decide on EOS */ - if (ret == GST_FLOW_UNEXPECTED && - (GST_BASE_PARSE_PASSTHROUGH (parse) || - (parse->priv->pad_mode == GST_ACTIVATE_PUSH && - !parse->priv->upstream_seekable))) - ret = GST_FLOW_OK; - } - - /* Update current running segment position */ - if (ret == GST_FLOW_OK && last_stop != GST_CLOCK_TIME_NONE && - parse->segment.last_stop < last_stop) - gst_segment_set_last_stop (&parse->segment, GST_FORMAT_TIME, last_stop); - - gst_base_parse_frame_clear (parse, frame); - - return ret; -} - - -/** - * gst_base_parse_drain: - * @parse: #GstBaseParse. - * - * Drains the adapter until it is empty. It decreases the min_frame_size to - * match the current adapter size and calls chain method until the adapter - * is emptied or chain returns with error. - */ -static void -gst_base_parse_drain (GstBaseParse * parse) -{ - guint avail; - - GST_DEBUG_OBJECT (parse, "draining"); - parse->priv->drain = TRUE; - - for (;;) { - avail = gst_adapter_available (parse->adapter); - if (!avail) - break; - - if (gst_base_parse_chain (parse->sinkpad, NULL) != GST_FLOW_OK) { - break; - } - - /* nothing changed, maybe due to truncated frame; break infinite loop */ - if (avail == gst_adapter_available (parse->adapter)) { - GST_DEBUG_OBJECT (parse, "no change during draining; flushing"); - gst_adapter_clear (parse->adapter); - } - } - - parse->priv->drain = FALSE; -} - -/** - * gst_base_parse_process_fragment: - * @parse: #GstBaseParse. - * - * Sends buffers collected in send_buffers downstream, and ensures that list - * is empty at the end (errors or not). - */ -static GstFlowReturn -gst_base_parse_send_buffers (GstBaseParse * parse) -{ - GSList *send = NULL; - GstBuffer *buf; - GstFlowReturn ret = GST_FLOW_OK; - - send = parse->priv->buffers_send; - - /* send buffers */ - while (send) { - buf = GST_BUFFER_CAST (send->data); - GST_LOG_OBJECT (parse, "pushing buffer %p, timestamp %" - GST_TIME_FORMAT ", duration %" GST_TIME_FORMAT - ", offset %" G_GINT64_FORMAT, buf, - GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)), - GST_TIME_ARGS (GST_BUFFER_DURATION (buf)), GST_BUFFER_OFFSET (buf)); - - /* iterate output queue an push downstream */ - ret = gst_pad_push (parse->srcpad, buf); - send = g_slist_delete_link (send, send); - - /* clear any leftover if error */ - if (G_UNLIKELY (ret != GST_FLOW_OK)) { - while (send) { - buf = GST_BUFFER_CAST (send->data); - gst_buffer_unref (buf); - send = g_slist_delete_link (send, send); - } - } - } - - parse->priv->buffers_send = send; - - return ret; -} - -/** - * gst_base_parse_process_fragment: - * @parse: #GstBaseParse. - * - * Processes a reverse playback (forward) fragment: - * - append head of last fragment that was skipped to current fragment data - * - drain the resulting current fragment data (i.e. repeated chain) - * - add time/duration (if needed) to frames queued by chain - * - push queued data - */ -static GstFlowReturn -gst_base_parse_process_fragment (GstBaseParse * parse, gboolean push_only) -{ - GstBuffer *buf; - GstFlowReturn ret = GST_FLOW_OK; - gboolean seen_key = FALSE, seen_delta = FALSE; - - if (push_only) - goto push; - - /* restore order */ - parse->priv->buffers_pending = g_slist_reverse (parse->priv->buffers_pending); - while (parse->priv->buffers_pending) { - buf = GST_BUFFER_CAST (parse->priv->buffers_pending->data); - GST_LOG_OBJECT (parse, "adding pending buffer (size %d)", - GST_BUFFER_SIZE (buf)); - gst_adapter_push (parse->adapter, buf); - parse->priv->buffers_pending = - g_slist_delete_link (parse->priv->buffers_pending, - parse->priv->buffers_pending); - } - - /* invalidate so no fall-back timestamping is performed; - * ok if taken from subclass or upstream */ - parse->priv->next_ts = GST_CLOCK_TIME_NONE; - /* prevent it hanging around stop all the time */ - parse->segment.last_stop = GST_CLOCK_TIME_NONE; - /* mark next run */ - parse->priv->discont = TRUE; - - /* chain looks for frames and queues resulting ones (in stead of pushing) */ - /* initial skipped data is added to buffers_pending */ - gst_base_parse_drain (parse); - -push: - if (parse->priv->buffers_send) { - buf = GST_BUFFER_CAST (parse->priv->buffers_send->data); - seen_key |= !GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT); - } - - /* add metadata (if needed to queued buffers */ - GST_LOG_OBJECT (parse, "last timestamp: %" GST_TIME_FORMAT, - GST_TIME_ARGS (parse->priv->last_ts)); - while (parse->priv->buffers_queued) { - buf = GST_BUFFER_CAST (parse->priv->buffers_queued->data); - - /* no touching if upstream or parsing provided time */ - if (GST_BUFFER_TIMESTAMP_IS_VALID (buf)) { - GST_LOG_OBJECT (parse, "buffer has time %" GST_TIME_FORMAT, - GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf))); - } else if (GST_CLOCK_TIME_IS_VALID (parse->priv->last_ts) && - GST_BUFFER_DURATION_IS_VALID (buf)) { - if (G_LIKELY (GST_BUFFER_DURATION (buf) <= parse->priv->last_ts)) - parse->priv->last_ts -= GST_BUFFER_DURATION (buf); - else - parse->priv->last_ts = 0; - GST_BUFFER_TIMESTAMP (buf) = parse->priv->last_ts; - GST_LOG_OBJECT (parse, "applied time %" GST_TIME_FORMAT, - GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf))); - } else { - /* no idea, very bad */ - GST_WARNING_OBJECT (parse, "could not determine time for buffer"); - } - - parse->priv->last_ts = GST_BUFFER_TIMESTAMP (buf); - - /* reverse order for ascending sending */ - /* send downstream at keyframe not preceded by a keyframe - * (e.g. that should identify start of collection of IDR nals) */ - if (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT)) { - if (seen_key) { - ret = gst_base_parse_send_buffers (parse); - /* if a problem, throw all to sending */ - if (ret != GST_FLOW_OK) { - parse->priv->buffers_send = - g_slist_reverse (parse->priv->buffers_queued); - parse->priv->buffers_queued = NULL; - break; - } - seen_key = FALSE; - } - } else { - seen_delta = TRUE; - } - - seen_key |= !GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT); - - parse->priv->buffers_send = - g_slist_prepend (parse->priv->buffers_send, buf); - parse->priv->buffers_queued = - g_slist_delete_link (parse->priv->buffers_queued, - parse->priv->buffers_queued); - } - - /* audio may have all marked as keyframe, so arrange to send here */ - if (!seen_delta) - ret = gst_base_parse_send_buffers (parse); - - /* any trailing unused no longer usable (ideally none) */ - if (G_UNLIKELY (gst_adapter_available (parse->adapter))) { - GST_DEBUG_OBJECT (parse, "discarding %d trailing bytes", - gst_adapter_available (parse->adapter)); - gst_adapter_clear (parse->adapter); - } - - return ret; -} - -/* small helper that checks whether we have been trying to resync too long */ -static inline GstFlowReturn -gst_base_parse_check_sync (GstBaseParse * parse) -{ - if (G_UNLIKELY (parse->priv->discont && - parse->priv->offset - parse->priv->sync_offset > 2 * 1024 * 1024)) { - GST_ELEMENT_ERROR (parse, STREAM, DECODE, - ("Failed to parse stream"), (NULL)); - return GST_FLOW_ERROR; - } - - return GST_FLOW_OK; -} - - -/** - * gst_base_parse_chain: - * @pad: #GstPad. - * @buffer: #GstBuffer. - * - * Returns: #GstFlowReturn. - */ -static GstFlowReturn -gst_base_parse_chain (GstPad * pad, GstBuffer * buffer) -{ - GstBaseParseClass *bclass; - GstBaseParse *parse; - GstFlowReturn ret = GST_FLOW_OK; - GstBuffer *outbuf = NULL; - GstBuffer *tmpbuf = NULL; - guint fsize = 1; - gint skip = -1; - const guint8 *data; - guint old_min_size = 0, min_size, av; - GstClockTime timestamp; - GstBaseParseFrame _frame = { 0, }; - GstBaseParseFrame *frame; - - parse = GST_BASE_PARSE (GST_OBJECT_PARENT (pad)); - bclass = GST_BASE_PARSE_GET_CLASS (parse); - frame = &_frame; - - if (G_LIKELY (buffer)) { - GST_LOG_OBJECT (parse, "buffer size: %d, offset = %" G_GINT64_FORMAT, - GST_BUFFER_SIZE (buffer), GST_BUFFER_OFFSET (buffer)); - if (G_UNLIKELY (GST_BASE_PARSE_PASSTHROUGH (parse))) { - frame->buffer = gst_buffer_make_metadata_writable (buffer); - return gst_base_parse_push_frame (parse, frame); - } - /* upstream feeding us in reverse playback; - * gather each fragment, then process it in single run */ - if (parse->segment.rate < 0.0) { - if (G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT))) { - GST_DEBUG_OBJECT (parse, "buffer starts new reverse playback fragment"); - ret = gst_base_parse_process_fragment (parse, FALSE); - } - gst_adapter_push (parse->adapter, buffer); - return ret; - } - gst_adapter_push (parse->adapter, buffer); - } - - /* Parse and push as many frames as possible */ - /* Stop either when adapter is empty or we are flushing */ - while (!parse->priv->flushing) { - gboolean res; - - tmpbuf = gst_buffer_new (); - - old_min_size = 0; - /* Synchronization loop */ - for (;;) { - min_size = MAX (parse->priv->min_frame_size, fsize); - av = gst_adapter_available (parse->adapter); - - /* loop safety check */ - if (G_UNLIKELY (old_min_size >= min_size)) - goto invalid_min; - old_min_size = min_size; - - if (G_UNLIKELY (parse->priv->drain)) { - min_size = av; - GST_DEBUG_OBJECT (parse, "draining, data left: %d", min_size); - if (G_UNLIKELY (!min_size)) { - gst_buffer_unref (tmpbuf); - goto done; - } - } - - /* Collect at least min_frame_size bytes */ - if (av < min_size) { - GST_DEBUG_OBJECT (parse, "not enough data available (only %d bytes)", - av); - gst_buffer_unref (tmpbuf); - goto done; - } - - /* always pass all available data */ - data = gst_adapter_peek (parse->adapter, av); - GST_BUFFER_DATA (tmpbuf) = (guint8 *) data; - GST_BUFFER_SIZE (tmpbuf) = min_size; - GST_BUFFER_OFFSET (tmpbuf) = parse->priv->offset; - GST_BUFFER_FLAG_SET (tmpbuf, GST_MINI_OBJECT_FLAG_READONLY); - - if (parse->priv->discont) { - GST_DEBUG_OBJECT (parse, "marking DISCONT"); - GST_BUFFER_FLAG_SET (tmpbuf, GST_BUFFER_FLAG_DISCONT); - } - - skip = -1; - gst_base_parse_frame_update (parse, frame, tmpbuf); - res = bclass->check_valid_frame (parse, frame, &fsize, &skip); - gst_buffer_replace (&frame->buffer, NULL); - if (res) { - if (gst_adapter_available (parse->adapter) < fsize) { - GST_DEBUG_OBJECT (parse, - "found valid frame but not enough data available (only %d bytes)", - gst_adapter_available (parse->adapter)); - gst_buffer_unref (tmpbuf); - goto done; - } - GST_LOG_OBJECT (parse, "valid frame of size %d at pos %d", fsize, skip); - break; - } - if (skip == -1) { - /* subclass didn't touch this value. By default we skip 1 byte */ - skip = 1; - } - if (skip > 0) { - GST_LOG_OBJECT (parse, "finding sync, skipping %d bytes", skip); - if (parse->segment.rate < 0.0 && !parse->priv->buffers_queued) { - /* reverse playback, and no frames found yet, so we are skipping - * the leading part of a fragment, which may form the tail of - * fragment coming later, hopefully subclass skips efficiently ... */ - timestamp = gst_adapter_prev_timestamp (parse->adapter, NULL); - outbuf = gst_adapter_take_buffer (parse->adapter, skip); - outbuf = gst_buffer_make_metadata_writable (outbuf); - GST_BUFFER_TIMESTAMP (outbuf) = timestamp; - parse->priv->buffers_pending = - g_slist_prepend (parse->priv->buffers_pending, outbuf); - outbuf = NULL; - } else { - gst_adapter_flush (parse->adapter, skip); - } - parse->priv->offset += skip; - if (!parse->priv->discont) - parse->priv->sync_offset = parse->priv->offset; - parse->priv->discont = TRUE; - /* something changed least; nullify loop check */ - old_min_size = 0; - } - /* skip == 0 should imply subclass set min_size to need more data; - * we check this shortly */ - if ((ret = gst_base_parse_check_sync (parse)) != GST_FLOW_OK) { - gst_buffer_unref (tmpbuf); - goto done; - } - } - gst_buffer_unref (tmpbuf); - tmpbuf = NULL; - - if (skip > 0) { - /* Subclass found the sync, but still wants to skip some data */ - GST_LOG_OBJECT (parse, "skipping %d bytes", skip); - gst_adapter_flush (parse->adapter, skip); - parse->priv->offset += skip; - } - - /* Grab lock to prevent a race with FLUSH_START handler */ - GST_PAD_STREAM_LOCK (parse->srcpad); - - /* FLUSH_START event causes the "flushing" flag to be set. In this - * case we can leave the frame pushing loop */ - if (parse->priv->flushing) { - GST_PAD_STREAM_UNLOCK (parse->srcpad); - break; - } - - /* move along with upstream timestamp (if any), - * but interpolate in between */ - timestamp = gst_adapter_prev_timestamp (parse->adapter, NULL); - if (GST_CLOCK_TIME_IS_VALID (timestamp) && - (parse->priv->prev_ts != timestamp)) { - parse->priv->prev_ts = parse->priv->next_ts = timestamp; - } - - /* FIXME: Would it be more efficient to make a subbuffer instead? */ - outbuf = gst_adapter_take_buffer (parse->adapter, fsize); - outbuf = gst_buffer_make_metadata_writable (outbuf); - - /* Subclass may want to know the data offset */ - GST_BUFFER_OFFSET (outbuf) = parse->priv->offset; - parse->priv->offset += fsize; - GST_BUFFER_TIMESTAMP (outbuf) = GST_CLOCK_TIME_NONE; - GST_BUFFER_DURATION (outbuf) = GST_CLOCK_TIME_NONE; - - frame->buffer = outbuf; - ret = gst_base_parse_handle_and_push_frame (parse, bclass, frame); - GST_PAD_STREAM_UNLOCK (parse->srcpad); - - if (ret != GST_FLOW_OK) { - GST_LOG_OBJECT (parse, "push returned %d", ret); - break; - } - } - -done: - GST_LOG_OBJECT (parse, "chain leaving"); - return ret; - - /* ERRORS */ -invalid_min: - { - GST_ELEMENT_ERROR (parse, STREAM, FAILED, (NULL), - ("min_size evolution %d -> %d; breaking to avoid looping", - old_min_size, min_size)); - return GST_FLOW_ERROR; - } -} - -/* pull @size bytes at current offset, - * i.e. at least try to and possibly return a shorter buffer if near the end */ -static GstFlowReturn -gst_base_parse_pull_range (GstBaseParse * parse, guint size, - GstBuffer ** buffer) -{ - GstFlowReturn ret = GST_FLOW_OK; - - g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR); - - /* Caching here actually makes much less difference than one would expect. - * We do it mainly to avoid pulling buffers of 1 byte all the time */ - if (parse->priv->cache) { - gint64 cache_offset = GST_BUFFER_OFFSET (parse->priv->cache); - gint cache_size = GST_BUFFER_SIZE (parse->priv->cache); - - if (cache_offset <= parse->priv->offset && - (parse->priv->offset + size) <= (cache_offset + cache_size)) { - *buffer = gst_buffer_create_sub (parse->priv->cache, - parse->priv->offset - cache_offset, size); - GST_BUFFER_OFFSET (*buffer) = parse->priv->offset; - return GST_FLOW_OK; - } - /* not enough data in the cache, free cache and get a new one */ - gst_buffer_unref (parse->priv->cache); - parse->priv->cache = NULL; - } - - /* refill the cache */ - ret = - gst_pad_pull_range (parse->sinkpad, parse->priv->offset, MAX (size, - 64 * 1024), &parse->priv->cache); - if (ret != GST_FLOW_OK) { - parse->priv->cache = NULL; - return ret; - } - - if (GST_BUFFER_SIZE (parse->priv->cache) >= size) { - *buffer = gst_buffer_create_sub (parse->priv->cache, 0, size); - GST_BUFFER_OFFSET (*buffer) = parse->priv->offset; - return GST_FLOW_OK; - } - - /* Not possible to get enough data, try a last time with - * requesting exactly the size we need */ - gst_buffer_unref (parse->priv->cache); - parse->priv->cache = NULL; - - ret = gst_pad_pull_range (parse->sinkpad, parse->priv->offset, size, - &parse->priv->cache); - - if (ret != GST_FLOW_OK) { - GST_DEBUG_OBJECT (parse, "pull_range returned %d", ret); - *buffer = NULL; - return ret; - } - - if (GST_BUFFER_SIZE (parse->priv->cache) < size) { - GST_DEBUG_OBJECT (parse, "Returning short buffer at offset %" - G_GUINT64_FORMAT ": wanted %u bytes, got %u bytes", parse->priv->offset, - size, GST_BUFFER_SIZE (parse->priv->cache)); - - *buffer = parse->priv->cache; - parse->priv->cache = NULL; - - return GST_FLOW_OK; - } - - *buffer = gst_buffer_create_sub (parse->priv->cache, 0, size); - GST_BUFFER_OFFSET (*buffer) = parse->priv->offset; - - return GST_FLOW_OK; -} - -static GstFlowReturn -gst_base_parse_handle_previous_fragment (GstBaseParse * parse) -{ - gint64 offset = 0; - GstClockTime ts = 0; - GstBuffer *buffer; - GstFlowReturn ret; - - GST_DEBUG_OBJECT (parse, "fragment ended; last_ts = %" GST_TIME_FORMAT - ", last_offset = %" G_GINT64_FORMAT, GST_TIME_ARGS (parse->priv->last_ts), - parse->priv->last_offset); - - if (!parse->priv->last_offset || parse->priv->last_ts <= parse->segment.start) { - GST_DEBUG_OBJECT (parse, "past start of segment %" GST_TIME_FORMAT, - GST_TIME_ARGS (parse->segment.start)); - ret = GST_FLOW_UNEXPECTED; - goto exit; - } - - /* last fragment started at last_offset / last_ts; - * seek back 10s capped at 1MB */ - if (parse->priv->last_ts >= 10 * GST_SECOND) - ts = parse->priv->last_ts - 10 * GST_SECOND; - /* if we are exact now, we will be more so going backwards */ - if (parse->priv->exact_position) { - offset = gst_base_parse_find_offset (parse, ts, TRUE, NULL); - } else { - GstFormat dstformat = GST_FORMAT_BYTES; - - if (!gst_pad_query_convert (parse->srcpad, GST_FORMAT_TIME, ts, - &dstformat, &offset)) { - GST_DEBUG_OBJECT (parse, "conversion failed, only BYTE based"); - } - } - offset = CLAMP (offset, parse->priv->last_offset - 1024 * 1024, - parse->priv->last_offset - 1024); - offset = MAX (0, offset); - - GST_DEBUG_OBJECT (parse, "next fragment from offset %" G_GINT64_FORMAT, - offset); - parse->priv->offset = offset; - - ret = gst_base_parse_pull_range (parse, parse->priv->last_offset - offset, - &buffer); - if (ret != GST_FLOW_OK) - goto exit; - - /* offset will increase again as fragment is processed/parsed */ - parse->priv->last_offset = offset; - - gst_adapter_push (parse->adapter, buffer); - ret = gst_base_parse_process_fragment (parse, FALSE); - if (ret != GST_FLOW_OK) - goto exit; - - /* force previous fragment */ - parse->priv->offset = -1; - -exit: - return ret; -} - -/* PULL mode: - * pull and scan for next frame starting from current offset - * ajusts sync, drain and offset going along */ -static GstFlowReturn -gst_base_parse_scan_frame (GstBaseParse * parse, GstBaseParseClass * klass, - GstBaseParseFrame * frame, gboolean full) -{ - GstBuffer *buffer, *outbuf; - GstFlowReturn ret = GST_FLOW_OK; - guint fsize = 1, min_size, old_min_size = 0; - gint skip = 0; - - g_return_val_if_fail (frame != NULL, GST_FLOW_ERROR); - - GST_LOG_OBJECT (parse, "scanning for frame at offset %" G_GUINT64_FORMAT - " (%#" G_GINT64_MODIFIER "x)", parse->priv->offset, parse->priv->offset); - - while (TRUE) { - gboolean res; - - min_size = MAX (parse->priv->min_frame_size, fsize); - /* loop safety check */ - if (G_UNLIKELY (old_min_size >= min_size)) - goto invalid_min; - old_min_size = min_size; - - ret = gst_base_parse_pull_range (parse, min_size, &buffer); - if (ret != GST_FLOW_OK) - goto done; - - if (parse->priv->discont) { - GST_DEBUG_OBJECT (parse, "marking DISCONT"); - GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT); - } - - /* if we got a short read, inform subclass we are draining leftover - * and no more is to be expected */ - if (GST_BUFFER_SIZE (buffer) < min_size) - parse->priv->drain = TRUE; - - skip = -1; - gst_base_parse_frame_update (parse, frame, buffer); - res = klass->check_valid_frame (parse, frame, &fsize, &skip); - gst_buffer_replace (&frame->buffer, NULL); - if (res) { - parse->priv->drain = FALSE; - GST_LOG_OBJECT (parse, "valid frame of size %d at pos %d", fsize, skip); - break; - } - parse->priv->drain = FALSE; - if (skip == -1) - skip = 1; - if (skip > 0) { - GST_LOG_OBJECT (parse, "finding sync, skipping %d bytes", skip); - if (full && parse->segment.rate < 0.0 && !parse->priv->buffers_queued) { - /* reverse playback, and no frames found yet, so we are skipping - * the leading part of a fragment, which may form the tail of - * fragment coming later, hopefully subclass skips efficiently ... */ - outbuf = gst_buffer_create_sub (buffer, 0, skip); - parse->priv->buffers_pending = - g_slist_prepend (parse->priv->buffers_pending, outbuf); - outbuf = NULL; - } - parse->priv->offset += skip; - if (!parse->priv->discont) - parse->priv->sync_offset = parse->priv->offset; - parse->priv->discont = TRUE; - /* something changed least; nullify loop check */ - old_min_size = 0; - } - /* skip == 0 should imply subclass set min_size to need more data; - * we check this shortly */ - GST_DEBUG_OBJECT (parse, "finding sync..."); - gst_buffer_unref (buffer); - if ((ret = gst_base_parse_check_sync (parse)) != GST_FLOW_OK) { - goto done; - } - } - - /* Does the subclass want to skip too? */ - if (skip > 0) - parse->priv->offset += skip; - else if (skip < 0) - skip = 0; - - if (fsize + skip <= GST_BUFFER_SIZE (buffer)) { - outbuf = gst_buffer_create_sub (buffer, skip, fsize); - GST_BUFFER_OFFSET (outbuf) = GST_BUFFER_OFFSET (buffer) + skip; - GST_BUFFER_TIMESTAMP (outbuf) = GST_CLOCK_TIME_NONE; - gst_buffer_unref (buffer); - } else { - gst_buffer_unref (buffer); - ret = gst_base_parse_pull_range (parse, fsize, &outbuf); - if (ret != GST_FLOW_OK) - goto done; - if (GST_BUFFER_SIZE (outbuf) < fsize) { - gst_buffer_unref (outbuf); - ret = GST_FLOW_UNEXPECTED; - } - } - - parse->priv->offset += fsize; - - frame->buffer = outbuf; - -done: - return ret; - - /* ERRORS */ -invalid_min: - { - GST_ELEMENT_ERROR (parse, STREAM, FAILED, (NULL), - ("min_size evolution %d -> %d; breaking to avoid looping", - old_min_size, min_size)); - return GST_FLOW_ERROR; - } -} - -/** - * gst_base_parse_loop: - * @pad: GstPad - * - * Loop that is used in pull mode to retrieve data from upstream. - */ -static void -gst_base_parse_loop (GstPad * pad) -{ - GstBaseParse *parse; - GstBaseParseClass *klass; - GstFlowReturn ret = GST_FLOW_OK; - GstBaseParseFrame frame = { 0, }; - - parse = GST_BASE_PARSE (gst_pad_get_parent (pad)); - klass = GST_BASE_PARSE_GET_CLASS (parse); - - /* reverse playback: - * first fragment (closest to stop time) is handled normally below, - * then we pull in fragments going backwards */ - if (parse->segment.rate < 0.0) { - /* check if we jumped back to a previous fragment, - * which is a post-first fragment */ - if (parse->priv->offset < 0) { - ret = gst_base_parse_handle_previous_fragment (parse); - goto done; - } - } - - ret = gst_base_parse_scan_frame (parse, klass, &frame, TRUE); - if (ret != GST_FLOW_OK) - goto done; - - /* This always cleans up frame, even if error occurs */ - ret = gst_base_parse_handle_and_push_frame (parse, klass, &frame); - - /* eat expected eos signalling past segment in reverse playback */ - if (parse->segment.rate < 0.0 && ret == GST_FLOW_UNEXPECTED && - parse->segment.last_stop >= parse->segment.stop) { - GST_DEBUG_OBJECT (parse, "downstream has reached end of segment"); - /* push what was accumulated during loop run */ - gst_base_parse_process_fragment (parse, TRUE); - /* force previous fragment */ - parse->priv->offset = -1; - ret = GST_FLOW_OK; - } - -done: - if (ret == GST_FLOW_UNEXPECTED) - goto eos; - else if (ret != GST_FLOW_OK) - goto pause; - - gst_object_unref (parse); - return; - - /* ERRORS */ -eos: - { - ret = GST_FLOW_UNEXPECTED; - GST_DEBUG_OBJECT (parse, "eos"); - /* fall-through */ - } -pause: - { - gboolean push_eos = FALSE; - - GST_DEBUG_OBJECT (parse, "pausing task, reason %s", - gst_flow_get_name (ret)); - gst_pad_pause_task (parse->sinkpad); - - if (ret == GST_FLOW_UNEXPECTED) { - /* handle end-of-stream/segment */ - if (parse->segment.flags & GST_SEEK_FLAG_SEGMENT) { - gint64 stop; - - if ((stop = parse->segment.stop) == -1) - stop = parse->segment.duration; - - GST_DEBUG_OBJECT (parse, "sending segment_done"); - - gst_element_post_message - (GST_ELEMENT_CAST (parse), - gst_message_new_segment_done (GST_OBJECT_CAST (parse), - GST_FORMAT_TIME, stop)); - } else { - /* If we STILL have zero frames processed, fire an error */ - if (parse->priv->framecount == 0) { - GST_ELEMENT_ERROR (parse, STREAM, WRONG_TYPE, - ("No valid frames found before end of stream"), (NULL)); - } - push_eos = TRUE; - } - } else if (ret == GST_FLOW_NOT_LINKED || ret < GST_FLOW_UNEXPECTED) { - /* for fatal errors we post an error message, wrong-state is - * not fatal because it happens due to flushes and only means - * that we should stop now. */ - GST_ELEMENT_ERROR (parse, STREAM, FAILED, (NULL), - ("streaming stopped, reason %s", gst_flow_get_name (ret))); - push_eos = TRUE; - } - if (push_eos) { - /* newsegment before eos */ - if (parse->pending_segment) { - gst_pad_push_event (parse->srcpad, parse->pending_segment); - parse->pending_segment = NULL; - } - gst_pad_push_event (parse->srcpad, gst_event_new_eos ()); - } - gst_object_unref (parse); - } -} - - -/** - * gst_base_parse_sink_activate: - * @sinkpad: #GstPad to be activated. - * - * Returns: TRUE if activation succeeded. - */ -static gboolean -gst_base_parse_sink_activate (GstPad * sinkpad) -{ - GstBaseParse *parse; - gboolean result = TRUE; - - parse = GST_BASE_PARSE (gst_pad_get_parent (sinkpad)); - - GST_DEBUG_OBJECT (parse, "sink activate"); - - if (gst_pad_check_pull_range (sinkpad)) { - GST_DEBUG_OBJECT (parse, "trying to activate in pull mode"); - result = gst_pad_activate_pull (sinkpad, TRUE); - } else { - GST_DEBUG_OBJECT (parse, "trying to activate in push mode"); - result = gst_pad_activate_push (sinkpad, TRUE); - } - - GST_DEBUG_OBJECT (parse, "sink activate return %d", result); - gst_object_unref (parse); - return result; -} - - -/** - * gst_base_parse_activate: - * @parse: #GstBaseParse. - * @active: TRUE if element will be activated, FALSE if deactivated. - * - * Returns: TRUE if the operation succeeded. - */ -static gboolean -gst_base_parse_activate (GstBaseParse * parse, gboolean active) -{ - GstBaseParseClass *klass; - gboolean result = FALSE; - - GST_DEBUG_OBJECT (parse, "activate %d", active); - - klass = GST_BASE_PARSE_GET_CLASS (parse); - - if (active) { - if (parse->priv->pad_mode == GST_ACTIVATE_NONE && klass->start) - result = klass->start (parse); - } else { - /* We must make sure streaming has finished before resetting things - * and calling the ::stop vfunc */ - GST_PAD_STREAM_LOCK (parse->sinkpad); - GST_PAD_STREAM_UNLOCK (parse->sinkpad); - - if (parse->priv->pad_mode != GST_ACTIVATE_NONE && klass->stop) - result = klass->stop (parse); - - parse->priv->pad_mode = GST_ACTIVATE_NONE; - } - GST_DEBUG_OBJECT (parse, "activate return: %d", result); - return result; -} - - -/** - * gst_base_parse_sink_activate_push: - * @pad: #GstPad to be (de)activated. - * @active: TRUE when activating, FALSE when deactivating. - * - * Returns: TRUE if (de)activation succeeded. - */ -static gboolean -gst_base_parse_sink_activate_push (GstPad * pad, gboolean active) -{ - gboolean result = TRUE; - GstBaseParse *parse; - - parse = GST_BASE_PARSE (gst_pad_get_parent (pad)); - - GST_DEBUG_OBJECT (parse, "sink activate push %d", active); - - result = gst_base_parse_activate (parse, active); - - if (result) - parse->priv->pad_mode = active ? GST_ACTIVATE_PUSH : GST_ACTIVATE_NONE; - - GST_DEBUG_OBJECT (parse, "sink activate push return: %d", result); - - gst_object_unref (parse); - return result; -} - - -/** - * gst_base_parse_sink_activate_pull: - * @sinkpad: #GstPad to be (de)activated. - * @active: TRUE when activating, FALSE when deactivating. - * - * Returns: TRUE if (de)activation succeeded. - */ -static gboolean -gst_base_parse_sink_activate_pull (GstPad * sinkpad, gboolean active) -{ - gboolean result = FALSE; - GstBaseParse *parse; - - parse = GST_BASE_PARSE (gst_pad_get_parent (sinkpad)); - - GST_DEBUG_OBJECT (parse, "activate pull %d", active); - - result = gst_base_parse_activate (parse, active); - - if (result) { - if (active) { - parse->pending_segment = gst_event_new_new_segment (FALSE, - parse->segment.rate, parse->segment.format, - parse->segment.start, parse->segment.stop, parse->segment.last_stop); - result &= gst_pad_start_task (sinkpad, - (GstTaskFunction) gst_base_parse_loop, sinkpad); - } else { - result &= gst_pad_stop_task (sinkpad); - } - } - - if (result) - parse->priv->pad_mode = active ? GST_ACTIVATE_PULL : GST_ACTIVATE_NONE; - - GST_DEBUG_OBJECT (parse, "sink activate pull return: %d", result); - - gst_object_unref (parse); - return result; -} - - -/** - * gst_base_parse_set_duration: - * @parse: #GstBaseParse. - * @fmt: #GstFormat. - * @duration: duration value. - * - * Sets the duration of the currently playing media. Subclass can use this - * when it is able to determine duration and/or notices a change in the media - * duration. Alternatively, if @interval is non-zero (default), then stream - * duration is determined based on estimated bitrate, and updated every @interval - * frames. */ -void -gst_base_parse_set_duration (GstBaseParse * parse, - GstFormat fmt, gint64 duration, gint interval) -{ - g_return_if_fail (parse != NULL); - - if (parse->priv->upstream_has_duration) { - GST_DEBUG_OBJECT (parse, "using upstream duration; discarding update"); - goto exit; - } - - if (duration != parse->priv->duration) { - GstMessage *m; - - m = gst_message_new_duration (GST_OBJECT (parse), fmt, duration); - gst_element_post_message (GST_ELEMENT (parse), m); - - /* TODO: what about duration tag? */ - } - parse->priv->duration = duration; - parse->priv->duration_fmt = fmt; - GST_DEBUG_OBJECT (parse, "set duration: %" G_GINT64_FORMAT, duration); - if (fmt == GST_FORMAT_TIME && GST_CLOCK_TIME_IS_VALID (duration)) { - if (interval != 0) { - GST_DEBUG_OBJECT (parse, "valid duration provided, disabling estimate"); - interval = 0; - } - } - GST_DEBUG_OBJECT (parse, "set update interval: %d", interval); - parse->priv->update_interval = interval; -exit: - return; -} - -/** - * gst_base_parse_set_seek: - * @parse: #GstBaseParse. - * @seek: #GstBaseParseSeekable. - * @abitrate: average bitrate. - * - * Sets whether and how the media is seekable (in time). - * Also optionally provides average bitrate detected in media (if non-zero), - * e.g. based on metadata, as it will be posted to the application. - * - * By default, announced average bitrate is estimated, and seekability is assumed - * possible based on estimated bitrate. - */ -void -gst_base_parse_set_seek (GstBaseParse * parse, - GstBaseParseSeekable seek, guint bitrate) -{ - parse->priv->seekable = seek; - parse->priv->bitrate = bitrate; - GST_DEBUG_OBJECT (parse, "seek %d, bitrate %d", seek, bitrate); -} - - -/** - * gst_base_parse_set_min_frame_size: - * @parse: #GstBaseParse. - * @min_size: Minimum size of the data that this base class should give to - * subclass. - * - * Subclass can use this function to tell the base class that it needs to - * give at least #min_size buffers. - */ -void -gst_base_parse_set_min_frame_size (GstBaseParse * parse, guint min_size) -{ - g_return_if_fail (parse != NULL); - - parse->priv->min_frame_size = min_size; - GST_LOG_OBJECT (parse, "set frame_min_size: %d", min_size); -} - -/** - * gst_base_parse_set_format: - * @parse: the #GstBaseParseFormat to set or unset - * @flags: format flag to enable or disable - * @on: whether or not to enable - * - * Set flags describing characteristics of parsed format. - */ -void -gst_base_parse_set_format (GstBaseParse * parse, GstBaseParseFormat flag, - gboolean on) -{ - g_return_if_fail (parse != NULL); - - GST_LOG_OBJECT (parse, "set flag %d to %d", flag, on); - if (on) - parse->priv->format |= flag; - else - parse->priv->format &= ~flag; -} - -/** - * gst_base_parse_set_frame_props: - * @parse: the #GstBaseParse to set - * @fps_num: frames per second (numerator). - * @fps_den: frames per second (denominator). - * @lead_in: frames needed before a segment for subsequent decode - * @lead_out: frames needed after a segment - * - * If frames per second is configured, parser can take care of buffer duration - * and timestamping. When performing segment clipping, or seeking to a specific - * location, a corresponding decoder might need an initial @lead_in and a - * following @lead_out number of frames to ensure the desired segment is - * entirely filled upon decoding. - */ -void -gst_base_parse_set_frame_props (GstBaseParse * parse, guint fps_num, - guint fps_den, guint lead_in, guint lead_out) -{ - g_return_if_fail (parse != NULL); - - parse->priv->fps_num = fps_num; - parse->priv->fps_den = fps_den; - if (!fps_num || !fps_den) { - GST_DEBUG_OBJECT (parse, "invalid fps (%d/%d), ignoring parameters", - fps_num, fps_den); - fps_num = fps_den = 0; - parse->priv->frame_duration = GST_CLOCK_TIME_NONE; - parse->priv->lead_in = parse->priv->lead_out = 0; - parse->priv->lead_in_ts = parse->priv->lead_out_ts = 0; - } else { - parse->priv->frame_duration = - gst_util_uint64_scale (GST_SECOND, fps_den, fps_num); - parse->priv->lead_in = lead_in; - parse->priv->lead_out = lead_out; - parse->priv->lead_in_ts = - gst_util_uint64_scale (GST_SECOND, fps_den * lead_in, fps_num); - parse->priv->lead_out_ts = - gst_util_uint64_scale (GST_SECOND, fps_den * lead_out, fps_num); - /* aim for about 1.5s to estimate duration */ - if (parse->priv->update_interval < 0) { - parse->priv->update_interval = fps_num * 3 / (fps_den * 2); - GST_LOG_OBJECT (parse, "estimated update interval to %d frames", - parse->priv->update_interval); - } - } - GST_LOG_OBJECT (parse, "set fps: %d/%d => duration: %" G_GINT64_FORMAT " ms", - fps_num, fps_den, parse->priv->frame_duration / GST_MSECOND); - GST_LOG_OBJECT (parse, "set lead in: %d frames = %" G_GUINT64_FORMAT " ms, " - "lead out: %d frames = %" G_GUINT64_FORMAT " ms", - lead_in, parse->priv->lead_in_ts / GST_MSECOND, - lead_out, parse->priv->lead_out_ts / GST_MSECOND); -} - -static gboolean -gst_base_parse_get_duration (GstBaseParse * parse, GstFormat format, - GstClockTime * duration) -{ - gboolean res = FALSE; - - g_return_val_if_fail (duration != NULL, FALSE); - - *duration = GST_CLOCK_TIME_NONE; - if (parse->priv->duration != -1 && format == parse->priv->duration_fmt) { - GST_LOG_OBJECT (parse, "using provided duration"); - *duration = parse->priv->duration; - res = TRUE; - } else if (parse->priv->duration != -1) { - GST_LOG_OBJECT (parse, "converting provided duration"); - res = gst_base_parse_convert (parse, parse->priv->duration_fmt, - parse->priv->duration, format, (gint64 *) duration); - } else if (format == GST_FORMAT_TIME && parse->priv->estimated_duration != -1) { - GST_LOG_OBJECT (parse, "using estimated duration"); - *duration = parse->priv->estimated_duration; - res = TRUE; - } - - GST_LOG_OBJECT (parse, "res: %d, duration %" GST_TIME_FORMAT, res, - GST_TIME_ARGS (*duration)); - return res; -} - -/** - * gst_base_parse_get_querytypes: - * @pad: GstPad - * - * Returns: A table of #GstQueryType items describing supported query types. - */ -static const GstQueryType * -gst_base_parse_get_querytypes (GstPad * pad) -{ - static const GstQueryType list[] = { - GST_QUERY_POSITION, - GST_QUERY_DURATION, - GST_QUERY_FORMATS, - GST_QUERY_SEEKING, - GST_QUERY_CONVERT, - 0 - }; - - return list; -} - - -/** - * gst_base_parse_query: - * @pad: #GstPad. - * @query: #GstQuery. - * - * Returns: TRUE on success. - */ -static gboolean -gst_base_parse_query (GstPad * pad, GstQuery * query) -{ - GstBaseParse *parse; - gboolean res = FALSE; - - parse = GST_BASE_PARSE (GST_PAD_PARENT (pad)); - - GST_LOG_OBJECT (parse, "handling query: %" GST_PTR_FORMAT, query); - - switch (GST_QUERY_TYPE (query)) { - case GST_QUERY_POSITION: - { - gint64 dest_value; - GstFormat format; - - GST_DEBUG_OBJECT (parse, "position query"); - gst_query_parse_position (query, &format, NULL); - - GST_OBJECT_LOCK (parse); - if (format == GST_FORMAT_BYTES) { - dest_value = parse->priv->offset; - res = TRUE; - } else if (format == parse->segment.format && - GST_CLOCK_TIME_IS_VALID (parse->segment.last_stop)) { - dest_value = parse->segment.last_stop; - res = TRUE; - } - GST_OBJECT_UNLOCK (parse); - - if (res) - gst_query_set_position (query, format, dest_value); - else { - res = gst_pad_query_default (pad, query); - if (!res) { - /* no precise result, upstream no idea either, then best estimate */ - /* priv->offset is updated in both PUSH/PULL modes */ - res = gst_base_parse_convert (parse, - GST_FORMAT_BYTES, parse->priv->offset, format, &dest_value); - } - } - break; - } - case GST_QUERY_DURATION: - { - GstFormat format; - GstClockTime duration; - - GST_DEBUG_OBJECT (parse, "duration query"); - gst_query_parse_duration (query, &format, NULL); - - /* consult upstream */ - res = gst_pad_query_default (pad, query); - - /* otherwise best estimate from us */ - if (!res) { - res = gst_base_parse_get_duration (parse, format, &duration); - if (res) - gst_query_set_duration (query, format, duration); - } - break; - } - case GST_QUERY_SEEKING: - { - GstFormat fmt; - GstClockTime duration = GST_CLOCK_TIME_NONE; - gboolean seekable = FALSE; - - GST_DEBUG_OBJECT (parse, "seeking query"); - gst_query_parse_seeking (query, &fmt, NULL, NULL, NULL); - - /* consult upstream */ - res = gst_pad_query_default (pad, query); - - /* we may be able to help if in TIME */ - if (fmt == GST_FORMAT_TIME && - parse->priv->seekable > GST_BASE_PARSE_SEEK_NONE) { - gst_query_parse_seeking (query, &fmt, &seekable, NULL, NULL); - /* already OK if upstream takes care */ - GST_LOG_OBJECT (parse, "upstream handled %d, seekable %d", - res, seekable); - if (!(res && seekable)) { - if (!gst_base_parse_get_duration (parse, GST_FORMAT_TIME, &duration) - || duration == -1) { - /* seekable if we still have a chance to get duration later on */ - seekable = - parse->priv->upstream_seekable && parse->priv->update_interval; - } else { - seekable = parse->priv->upstream_seekable; - GST_LOG_OBJECT (parse, "already determine upstream seekabled: %d", - seekable); - } - gst_query_set_seeking (query, GST_FORMAT_TIME, seekable, 0, duration); - res = TRUE; - } - } - break; - } - case GST_QUERY_FORMATS: - gst_query_set_formatsv (query, 3, fmtlist); - res = TRUE; - break; - case GST_QUERY_CONVERT: - { - GstFormat src_format, dest_format; - gint64 src_value, dest_value; - - gst_query_parse_convert (query, &src_format, &src_value, - &dest_format, &dest_value); - - res = gst_base_parse_convert (parse, src_format, src_value, - dest_format, &dest_value); - if (res) { - gst_query_set_convert (query, src_format, src_value, - dest_format, dest_value); - } - break; - } - default: - res = gst_pad_query_default (pad, query); - break; - } - return res; -} - -/* scans for a cluster start from @pos, - * return GST_FLOW_OK and frame position/time in @pos/@time if found */ -static GstFlowReturn -gst_base_parse_find_frame (GstBaseParse * parse, gint64 * pos, - GstClockTime * time, GstClockTime * duration) -{ - GstBaseParseClass *klass; - gint64 orig_offset; - gboolean orig_drain, orig_discont; - GstFlowReturn ret = GST_FLOW_OK; - GstBuffer *buf = NULL; - GstBaseParseFrame frame = { 0, }; - - g_return_val_if_fail (GST_FLOW_ERROR, pos != NULL); - g_return_val_if_fail (GST_FLOW_ERROR, time != NULL); - g_return_val_if_fail (GST_FLOW_ERROR, duration != NULL); - - klass = GST_BASE_PARSE_GET_CLASS (parse); - - *time = GST_CLOCK_TIME_NONE; - *duration = GST_CLOCK_TIME_NONE; - - /* save state */ - orig_offset = parse->priv->offset; - orig_discont = parse->priv->discont; - orig_drain = parse->priv->drain; - - GST_DEBUG_OBJECT (parse, "scanning for frame starting at %" G_GINT64_FORMAT - " (%#" G_GINT64_MODIFIER "x)", *pos, *pos); - - /* jump elsewhere and locate next frame */ - parse->priv->offset = *pos; - ret = gst_base_parse_scan_frame (parse, klass, &frame, FALSE); - if (ret != GST_FLOW_OK) - goto done; - - buf = frame.buffer; - GST_LOG_OBJECT (parse, - "peek parsing frame at offset %" G_GUINT64_FORMAT - " (%#" G_GINT64_MODIFIER "x) of size %d", - GST_BUFFER_OFFSET (buf), GST_BUFFER_OFFSET (buf), GST_BUFFER_SIZE (buf)); - - /* get offset first, subclass parsing might dump other stuff in there */ - *pos = GST_BUFFER_OFFSET (buf); - ret = klass->parse_frame (parse, &frame); - buf = frame.buffer; - - /* but it should provide proper time */ - *time = GST_BUFFER_TIMESTAMP (buf); - *duration = GST_BUFFER_DURATION (buf); - gst_base_parse_frame_clear (parse, &frame); - - GST_LOG_OBJECT (parse, - "frame with time %" GST_TIME_FORMAT " at offset %" G_GINT64_FORMAT, - GST_TIME_ARGS (*time), *pos); - -done: - /* restore state */ - parse->priv->offset = orig_offset; - parse->priv->discont = orig_discont; - parse->priv->drain = orig_drain; - - return ret; -} - -/* bisect and scan through file for frame starting before @time, - * returns OK and @time/@offset if found, NONE and/or error otherwise - * If @time == G_MAXINT64, scan for duration ( == last frame) */ -static GstFlowReturn -gst_base_parse_locate_time (GstBaseParse * parse, GstClockTime * _time, - gint64 * _offset) -{ - GstFlowReturn ret = GST_FLOW_OK; - gint64 lpos, hpos, newpos; - GstClockTime time, ltime, htime, newtime, dur; - gboolean cont = TRUE; - const GstClockTime tolerance = TARGET_DIFFERENCE; - const guint chunk = 4 * 1024; - - g_return_val_if_fail (_time != NULL, GST_FLOW_ERROR); - g_return_val_if_fail (_offset != NULL, GST_FLOW_ERROR); - - /* TODO also make keyframe aware if useful some day */ - - time = *_time; - - /* basic cases */ - if (time == 0) { - *_offset = 0; - return GST_FLOW_OK; - } - - if (time == -1) { - *_offset = -1; - return GST_FLOW_OK; - } - - /* do not know at first */ - *_offset = -1; - *_time = GST_CLOCK_TIME_NONE; - - /* need initial positions; start and end */ - lpos = parse->priv->first_frame_offset; - ltime = parse->priv->first_frame_ts; - htime = parse->priv->duration; - hpos = parse->priv->upstream_size; - - /* check preconditions are satisfied; - * start and end are needed, except for special case where we scan for - * last frame to determine duration */ - if (parse->priv->pad_mode != GST_ACTIVATE_PULL || !hpos || - !GST_CLOCK_TIME_IS_VALID (ltime) || - (!GST_CLOCK_TIME_IS_VALID (htime) && time != G_MAXINT64)) { - return GST_FLOW_OK; - } - - /* shortcut cases */ - if (time < ltime) { - goto exit; - } else if (time < ltime + tolerance) { - *_offset = lpos; - *_time = ltime; - goto exit; - } else if (time >= htime) { - *_offset = hpos; - *_time = htime; - goto exit; - } - - while (htime > ltime && cont) { - GST_LOG_OBJECT (parse, - "lpos: %" G_GUINT64_FORMAT ", ltime: %" GST_TIME_FORMAT, lpos, - GST_TIME_ARGS (ltime)); - GST_LOG_OBJECT (parse, - "hpos: %" G_GUINT64_FORMAT ", htime: %" GST_TIME_FORMAT, hpos, - GST_TIME_ARGS (htime)); - if (G_UNLIKELY (time == G_MAXINT64)) { - newpos = hpos; - } else if (G_LIKELY (hpos > lpos)) { - newpos = - gst_util_uint64_scale (hpos - lpos, time - ltime, htime - ltime) + - lpos - chunk; - } else { - /* should mean lpos == hpos, since lpos <= hpos is invariant */ - newpos = lpos; - /* we check this case once, but not forever, so break loop */ - cont = FALSE; - } - - /* ensure */ - newpos = CLAMP (newpos, lpos, hpos); - GST_LOG_OBJECT (parse, - "estimated _offset for %" GST_TIME_FORMAT ": %" G_GINT64_FORMAT, - GST_TIME_ARGS (time), newpos); - - ret = gst_base_parse_find_frame (parse, &newpos, &newtime, &dur); - if (ret == GST_FLOW_UNEXPECTED) { - /* heuristic HACK */ - hpos = MAX (lpos, hpos - chunk); - continue; - } else if (ret != GST_FLOW_OK) { - goto exit; - } - - if (newtime == -1 || newpos == -1) { - GST_DEBUG_OBJECT (parse, "subclass did not provide metadata; aborting"); - break; - } - - if (G_UNLIKELY (time == G_MAXINT64)) { - *_offset = newpos; - *_time = newtime; - if (GST_CLOCK_TIME_IS_VALID (dur)) - *_time += dur; - break; - } else if (newtime > time) { - /* overshoot */ - hpos = (newpos >= hpos) ? MAX (lpos, hpos - chunk) : MAX (lpos, newpos); - htime = newtime; - } else if (newtime + tolerance > time) { - /* close enough undershoot */ - *_offset = newpos; - *_time = newtime; - break; - } else if (newtime < ltime) { - /* so a position beyond lpos resulted in earlier time than ltime ... */ - GST_DEBUG_OBJECT (parse, "non-ascending time; aborting"); - break; - } else { - /* undershoot too far */ - newpos += newpos == lpos ? chunk : 0; - lpos = CLAMP (newpos, lpos, hpos); - ltime = newtime; - } - } - -exit: - GST_LOG_OBJECT (parse, "return offset %" G_GINT64_FORMAT ", time %" - GST_TIME_FORMAT, *_offset, GST_TIME_ARGS (*_time)); - return ret; -} - -static gint64 -gst_base_parse_find_offset (GstBaseParse * parse, GstClockTime time, - gboolean before, GstClockTime * _ts) -{ - gint64 bytes = 0, ts = 0; - GstIndexEntry *entry = NULL; - - if (time == GST_CLOCK_TIME_NONE) { - ts = time; - bytes = -1; - goto exit; - } - - GST_OBJECT_LOCK (parse); - if (parse->priv->index) { - /* Let's check if we have an index entry for that time */ - entry = gst_index_get_assoc_entry (parse->priv->index, - parse->priv->index_id, - before ? GST_INDEX_LOOKUP_BEFORE : GST_INDEX_LOOKUP_AFTER, - GST_ASSOCIATION_FLAG_KEY_UNIT, GST_FORMAT_TIME, time); - } - - if (entry) { - gst_index_entry_assoc_map (entry, GST_FORMAT_BYTES, &bytes); - gst_index_entry_assoc_map (entry, GST_FORMAT_TIME, &ts); - - GST_DEBUG_OBJECT (parse, "found index entry for %" GST_TIME_FORMAT - " at %" GST_TIME_FORMAT ", offset %" G_GINT64_FORMAT, - GST_TIME_ARGS (time), GST_TIME_ARGS (ts), bytes); - } else { - GST_DEBUG_OBJECT (parse, "no index entry found for %" GST_TIME_FORMAT, - GST_TIME_ARGS (time)); - if (!before) { - bytes = -1; - ts = GST_CLOCK_TIME_NONE; - } - } - GST_OBJECT_UNLOCK (parse); - -exit: - if (_ts) - *_ts = ts; - - return bytes; -} - - -/** - * gst_base_parse_handle_seek: - * @parse: #GstBaseParse. - * @event: #GstEvent. - * - * Returns: TRUE if seek succeeded. - */ -static gboolean -gst_base_parse_handle_seek (GstBaseParse * parse, GstEvent * event) -{ - gdouble rate; - GstFormat format; - GstSeekFlags flags; - GstSeekType cur_type = GST_SEEK_TYPE_NONE, stop_type; - gboolean flush, update, res = TRUE, accurate; - gint64 cur, stop, seekpos, seekstop; - GstSegment seeksegment = { 0, }; - GstFormat dstformat; - GstClockTime start_ts; - - gst_event_parse_seek (event, &rate, &format, &flags, - &cur_type, &cur, &stop_type, &stop); - - GST_DEBUG_OBJECT (parse, "seek to format %s, rate %f, " - "start type %d at %" GST_TIME_FORMAT ", end type %d at %" - GST_TIME_FORMAT, gst_format_get_name (format), rate, - cur_type, GST_TIME_ARGS (cur), stop_type, GST_TIME_ARGS (stop)); - - /* no negative rates in push mode */ - if (rate < 0.0 && parse->priv->pad_mode == GST_ACTIVATE_PUSH) - goto negative_rate; - - if (cur_type != GST_SEEK_TYPE_SET || - (stop_type != GST_SEEK_TYPE_SET && stop_type != GST_SEEK_TYPE_NONE)) - goto wrong_type; - - /* For any format other than TIME, see if upstream handles - * it directly or fail. For TIME, try upstream, but do it ourselves if - * it fails upstream */ - if (format != GST_FORMAT_TIME) { - /* default action delegates to upstream */ - res = FALSE; - goto done; - } else { - gst_event_ref (event); - if ((res = gst_pad_push_event (parse->sinkpad, event))) { - goto done; - } - } - - /* get flush flag */ - flush = flags & GST_SEEK_FLAG_FLUSH; - - /* copy segment, we need this because we still need the old - * segment when we close the current segment. */ - memcpy (&seeksegment, &parse->segment, sizeof (GstSegment)); - - GST_DEBUG_OBJECT (parse, "configuring seek"); - gst_segment_set_seek (&seeksegment, rate, format, flags, - cur_type, cur, stop_type, stop, &update); - - /* accurate seeking implies seek tables are used to obtain position, - * and the requested segment is maintained exactly, not adjusted any way */ - accurate = flags & GST_SEEK_FLAG_ACCURATE; - - /* maybe we can be accurate for (almost) free */ - gst_base_parse_find_offset (parse, seeksegment.last_stop, TRUE, &start_ts); - if (seeksegment.last_stop <= start_ts + TARGET_DIFFERENCE) { - GST_DEBUG_OBJECT (parse, "accurate seek possible"); - accurate = TRUE; - } - if (accurate) { - GstClockTime startpos = seeksegment.last_stop; - - /* accurate requested, so ... seek a bit before target */ - if (startpos < parse->priv->lead_in_ts) - startpos = 0; - else - startpos -= parse->priv->lead_in_ts; - seekpos = gst_base_parse_find_offset (parse, startpos, TRUE, &start_ts); - seekstop = gst_base_parse_find_offset (parse, seeksegment.stop, FALSE, - NULL); - } else { - start_ts = seeksegment.last_stop; - dstformat = GST_FORMAT_BYTES; - if (!gst_pad_query_convert (parse->srcpad, format, seeksegment.last_stop, - &dstformat, &seekpos)) - goto convert_failed; - if (!gst_pad_query_convert (parse->srcpad, format, seeksegment.stop, - &dstformat, &seekstop)) - goto convert_failed; - } - - GST_DEBUG_OBJECT (parse, - "seek position %" G_GINT64_FORMAT " in bytes: %" G_GINT64_FORMAT, - start_ts, seekpos); - GST_DEBUG_OBJECT (parse, - "seek stop %" G_GINT64_FORMAT " in bytes: %" G_GINT64_FORMAT, - seeksegment.stop, seekstop); - - if (parse->priv->pad_mode == GST_ACTIVATE_PULL) { - gint64 last_stop; - - GST_DEBUG_OBJECT (parse, "seek in PULL mode"); - - if (flush) { - if (parse->srcpad) { - GST_DEBUG_OBJECT (parse, "sending flush start"); - gst_pad_push_event (parse->srcpad, gst_event_new_flush_start ()); - /* unlock upstream pull_range */ - gst_pad_push_event (parse->sinkpad, gst_event_new_flush_start ()); - } - } else { - gst_pad_pause_task (parse->sinkpad); - } - - /* we should now be able to grab the streaming thread because we stopped it - * with the above flush/pause code */ - GST_PAD_STREAM_LOCK (parse->sinkpad); - - /* save current position */ - last_stop = parse->segment.last_stop; - GST_DEBUG_OBJECT (parse, "stopped streaming at %" G_GINT64_FORMAT, - last_stop); - - /* now commit to new position */ - - /* prepare for streaming again */ - if (flush) { - GST_DEBUG_OBJECT (parse, "sending flush stop"); - gst_pad_push_event (parse->srcpad, gst_event_new_flush_stop ()); - gst_pad_push_event (parse->sinkpad, gst_event_new_flush_stop ()); - gst_base_parse_clear_queues (parse); - } else { - if (parse->close_segment) - gst_event_unref (parse->close_segment); - - parse->close_segment = gst_event_new_new_segment (TRUE, - parse->segment.rate, parse->segment.format, - parse->segment.accum, parse->segment.last_stop, parse->segment.accum); - - /* keep track of our last_stop */ - seeksegment.accum = parse->segment.last_stop; - - GST_DEBUG_OBJECT (parse, "Created close seg format %d, " - "start = %" GST_TIME_FORMAT ", stop = %" GST_TIME_FORMAT - ", pos = %" GST_TIME_FORMAT, format, - GST_TIME_ARGS (parse->segment.accum), - GST_TIME_ARGS (parse->segment.last_stop), - GST_TIME_ARGS (parse->segment.accum)); - } - - memcpy (&parse->segment, &seeksegment, sizeof (GstSegment)); - - /* store the newsegment event so it can be sent from the streaming thread. */ - if (parse->pending_segment) - gst_event_unref (parse->pending_segment); - - /* This will be sent later in _loop() */ - parse->pending_segment = - gst_event_new_new_segment (FALSE, parse->segment.rate, - parse->segment.format, parse->segment.start, parse->segment.stop, - parse->segment.start); - - GST_DEBUG_OBJECT (parse, "Created newseg format %d, " - "start = %" GST_TIME_FORMAT ", stop = %" GST_TIME_FORMAT - ", pos = %" GST_TIME_FORMAT, format, - GST_TIME_ARGS (parse->segment.start), - GST_TIME_ARGS (parse->segment.stop), - GST_TIME_ARGS (parse->segment.start)); - - /* one last chance in pull mode to stay accurate; - * maybe scan and subclass can find where to go */ - if (!accurate) { - gint64 scanpos; - GstClockTime ts = seeksegment.last_stop; - - gst_base_parse_locate_time (parse, &ts, &scanpos); - if (scanpos >= 0) { - accurate = TRUE; - seekpos = scanpos; - /* running collected index now consists of several intervals, - * so optimized check no longer possible */ - parse->priv->index_last_valid = FALSE; - parse->priv->index_last_offset = 0; - parse->priv->index_last_ts = 0; - } - } - - /* mark discont if we are going to stream from another position. */ - if (seekpos != parse->priv->offset) { - GST_DEBUG_OBJECT (parse, - "mark DISCONT, we did a seek to another position"); - parse->priv->offset = seekpos; - parse->priv->last_offset = seekpos; - parse->priv->seen_keyframe = FALSE; - parse->priv->discont = TRUE; - parse->priv->next_ts = start_ts; - parse->priv->last_ts = GST_CLOCK_TIME_NONE; - parse->priv->sync_offset = seekpos; - parse->priv->exact_position = accurate; - } - - /* Start streaming thread if paused */ - gst_pad_start_task (parse->sinkpad, - (GstTaskFunction) gst_base_parse_loop, parse->sinkpad); - - GST_PAD_STREAM_UNLOCK (parse->sinkpad); - - /* handled seek */ - res = TRUE; - } else { - GstEvent *new_event; - GstBaseParseSeek *seek; - - /* The only thing we need to do in PUSH-mode is to send the - seek event (in bytes) to upstream. Segment / flush handling happens - in corresponding src event handlers */ - GST_DEBUG_OBJECT (parse, "seek in PUSH mode"); - if (seekstop >= 0 && seekpos <= seekpos) - seekstop = seekpos; - new_event = gst_event_new_seek (rate, GST_FORMAT_BYTES, flush, - GST_SEEK_TYPE_SET, seekpos, stop_type, seekstop); - - /* store segment info so its precise details can be reconstructed when - * receiving newsegment; - * this matters for all details when accurate seeking, - * is most useful to preserve NONE stop time otherwise */ - seek = g_new0 (GstBaseParseSeek, 1); - seek->segment = seeksegment; - seek->accurate = accurate; - seek->offset = seekpos; - seek->start_ts = start_ts; - GST_OBJECT_LOCK (parse); - /* less optimal, but preserves order */ - parse->priv->pending_seeks = - g_slist_append (parse->priv->pending_seeks, seek); - GST_OBJECT_UNLOCK (parse); - - res = gst_pad_push_event (parse->sinkpad, new_event); - - if (!res) { - GST_OBJECT_LOCK (parse); - parse->priv->pending_seeks = - g_slist_remove (parse->priv->pending_seeks, seek); - GST_OBJECT_UNLOCK (parse); - g_free (seek); - } - } - -done: - /* handled event is ours to free */ - if (res) - gst_event_unref (event); - return res; - - /* ERRORS */ -negative_rate: - { - GST_DEBUG_OBJECT (parse, "negative playback rates delegated upstream."); - res = FALSE; - goto done; - } -wrong_type: - { - GST_DEBUG_OBJECT (parse, "unsupported seek type."); - res = FALSE; - goto done; - } -convert_failed: - { - GST_DEBUG_OBJECT (parse, "conversion TIME to BYTES failed."); - res = FALSE; - goto done; - } -} - -/** - * gst_base_parse_handle_tag: - * @parse: #GstBaseParse. - * @event: #GstEvent. - * - * Checks if bitrates are available from upstream tags so that we don't - * override them later - */ -static void -gst_base_parse_handle_tag (GstBaseParse * parse, GstEvent * event) -{ - GstTagList *taglist = NULL; - guint tmp; - - gst_event_parse_tag (event, &taglist); - - if (gst_tag_list_get_uint (taglist, GST_TAG_MINIMUM_BITRATE, &tmp)) { - GST_DEBUG_OBJECT (parse, "upstream min bitrate %d", tmp); - parse->priv->post_min_bitrate = FALSE; - } - if (gst_tag_list_get_uint (taglist, GST_TAG_BITRATE, &tmp)) { - GST_DEBUG_OBJECT (parse, "upstream avg bitrate %d", tmp); - parse->priv->post_avg_bitrate = FALSE; - } - if (gst_tag_list_get_uint (taglist, GST_TAG_MAXIMUM_BITRATE, &tmp)) { - GST_DEBUG_OBJECT (parse, "upstream max bitrate %d", tmp); - parse->priv->post_max_bitrate = FALSE; - } -} - -/** - * gst_base_parse_sink_setcaps: - * @pad: #GstPad. - * @caps: #GstCaps. - * - * Returns: TRUE if caps were accepted. - */ -static gboolean -gst_base_parse_sink_setcaps (GstPad * pad, GstCaps * caps) -{ - GstBaseParse *parse; - GstBaseParseClass *klass; - gboolean res = TRUE; - - parse = GST_BASE_PARSE (GST_PAD_PARENT (pad)); - klass = GST_BASE_PARSE_GET_CLASS (parse); - - GST_DEBUG_OBJECT (parse, "caps: %" GST_PTR_FORMAT, caps); - - if (klass->set_sink_caps) - res = klass->set_sink_caps (parse, caps); - - return res; -} - -static void -gst_base_parse_set_index (GstElement * element, GstIndex * index) -{ - GstBaseParse *parse = GST_BASE_PARSE (element); - - GST_OBJECT_LOCK (parse); - if (parse->priv->index) - gst_object_unref (parse->priv->index); - if (index) { - parse->priv->index = gst_object_ref (index); - gst_index_get_writer_id (index, GST_OBJECT (element), - &parse->priv->index_id); - parse->priv->own_index = FALSE; - } else - parse->priv->index = NULL; - GST_OBJECT_UNLOCK (parse); -} - -static GstIndex * -gst_base_parse_get_index (GstElement * element) -{ - GstBaseParse *parse = GST_BASE_PARSE (element); - GstIndex *result = NULL; - - GST_OBJECT_LOCK (parse); - if (parse->priv->index) - result = gst_object_ref (parse->priv->index); - GST_OBJECT_UNLOCK (parse); - - return result; -} - -static GstStateChangeReturn -gst_base_parse_change_state (GstElement * element, GstStateChange transition) -{ - GstBaseParse *parse; - GstStateChangeReturn result; - - parse = GST_BASE_PARSE (element); - - switch (transition) { - case GST_STATE_CHANGE_READY_TO_PAUSED: - /* If this is our own index destroy it as the - * old entries might be wrong for the new stream */ - if (parse->priv->own_index) { - gst_object_unref (parse->priv->index); - parse->priv->index = NULL; - parse->priv->own_index = FALSE; - } - - /* If no index was created, generate one */ - if (G_UNLIKELY (!parse->priv->index)) { - GST_DEBUG_OBJECT (parse, "no index provided creating our own"); - - parse->priv->index = gst_index_factory_make ("memindex"); - gst_index_get_writer_id (parse->priv->index, GST_OBJECT (parse), - &parse->priv->index_id); - parse->priv->own_index = TRUE; - } - break; - default: - break; - } - - result = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); - - switch (transition) { - case GST_STATE_CHANGE_PAUSED_TO_READY: - gst_base_parse_reset (parse); - break; - default: - break; - } - - return result; -} diff --git a/gst/videoparsers/gstbaseparse.h b/gst/videoparsers/gstbaseparse.h deleted file mode 100644 index 82ec5f6fb8..0000000000 --- a/gst/videoparsers/gstbaseparse.h +++ /dev/null @@ -1,358 +0,0 @@ -/* GStreamer - * Copyright (C) 2008 Nokia Corporation. All rights reserved. - * - * Contact: Stefan Kost - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef __GST_BASE_PARSE_H__ -#define __GST_BASE_PARSE_H__ - -#include -#include - -G_BEGIN_DECLS - -#define GST_TYPE_BASE_PARSE (gst_base_parse_get_type()) -#define GST_BASE_PARSE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_BASE_PARSE,GstBaseParse)) -#define GST_BASE_PARSE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_BASE_PARSE,GstBaseParseClass)) -#define GST_BASE_PARSE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_BASE_PARSE,GstBaseParseClass)) -#define GST_IS_BASE_PARSE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_BASE_PARSE)) -#define GST_IS_BASE_PARSE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_BASE_PARSE)) -#define GST_BASE_PARSE_CAST(obj) ((GstBaseParse *)(obj)) - -/** - * GST_BASE_PARSE_SINK_NAME: - * - * the name of the templates for the sink pad - */ -#define GST_BASE_PARSE_SINK_NAME "sink" -/** - * GST_BASE_PARSE_SRC_NAME: - * - * the name of the templates for the source pad - */ -#define GST_BASE_PARSE_SRC_NAME "src" - -/** - * GST_BASE_PARSE_SRC_PAD: - * @obj: base parse instance - * - * Gives the pointer to the source #GstPad object of the element. - * - * Since: 0.10.x - */ -#define GST_BASE_PARSE_SRC_PAD(obj) (GST_BASE_PARSE_CAST (obj)->srcpad) - -/** - * GST_BASE_PARSE_SINK_PAD: - * @obj: base parse instance - * - * Gives the pointer to the sink #GstPad object of the element. - * - * Since: 0.10.x - */ -#define GST_BASE_PARSE_SINK_PAD(obj) (GST_BASE_PARSE_CAST (obj)->sinkpad) - -/** - * GST_BASE_PARSE_SEGMENT: - * @obj: base parse instance - * - * Gives the segment of the element. - * - * Since: 0.10.x - */ -#define GST_BASE_PARSE_SEGMENT(obj) (GST_BASE_PARSE_CAST (obj)->segment) - -/** - * GST_BASE_PARSE_FLOW_DROPPED: - * - * A #GstFlowReturn that can be returned from parse_frame to - * indicate that no output buffer was generated, or from pre_push_buffer to - * to forego pushing buffer. - * - * Since: 0.10.x - */ -#define GST_BASE_PARSE_FLOW_DROPPED GST_FLOW_CUSTOM_SUCCESS - -/** - * GstBaseParseFrameFlags: - * @GST_BASE_PARSE_FRAME_FLAG_NONE: no flag - * @GST_BASE_PARSE_FRAME_FLAG_SYNC: indicates if parsing is 'in sync' - * @GST_BASE_PARSE_FRAME_FLAG_DRAIN: indicates if parser is 'draining'. - * That is, leftover data (e.g. in FLUSH or EOS situation) is being parsed. - * @GST_BASE_PARSE_FRAME_FLAG_NO_FRAME: set to indicate this buffer should not be - * counted as frame, e.g. if this frame is dependent on a previous one. - * As it is not counted as a frame, bitrate increases but frame to time - * conversions are maintained. - * @GST_BASE_PARSE_FRAME_FLAG_CLIP: @pre_push_buffer can set this to indicate - * that regular segment clipping can still be performed (as opposed to - * any custom one having been done). - * - * Flags to be used in a #GstBaseParseFrame. - * - * Since: 0.10.x - */ -typedef enum { - GST_BASE_PARSE_FRAME_FLAG_NONE = 0, - GST_BASE_PARSE_FRAME_FLAG_SYNC = (1 << 0), - GST_BASE_PARSE_FRAME_FLAG_DRAIN = (1 << 1), - GST_BASE_PARSE_FRAME_FLAG_NO_FRAME = (1 << 2), - GST_BASE_PARSE_FRAME_FLAG_CLIP = (1 << 3) -} GstBaseParseFrameFlags; - -/** - * GstBaseParseFrame: - * @buffer: data to check for valid frame or parsed frame. - * Subclass is allowed to replace this buffer. - * @overhead: subclass can set this to indicates the metadata overhead - * for the given frame, which is then used to enable more accurate bitrate - * computations. If this is -1, it is assumed that this frame should be - * skipped in bitrate calculation. - * @flags: a combination of input and output #GstBaseParseFrameFlags that - * convey additional context to subclass or allow subclass to tune - * subsequent #GstBaseParse actions. - * - * Frame (context) data passed to each frame parsing virtual methods. In - * addition to providing the data to be checked for a valid frame or an already - * identified frame, it conveys additional metadata or control information - * from and to the subclass w.r.t. the particular frame in question (rather - * than global parameters). Some of these may apply to each parsing stage, others - * only to some a particular one. These parameters are effectively zeroed at start - * of each frame's processing, i.e. parsing virtual method invocation sequence. - * - * Since: 0.10.x - */ -typedef struct { - GstBuffer *buffer; - guint flags; - gint overhead; -} GstBaseParseFrame; - -/** - * GST_BASE_PARSE_FRAME_SYNC: - * @frame: base parse frame instance - * - * Obtains current sync status indicated in frame. - * - * Since: 0.10.x - */ -#define GST_BASE_PARSE_FRAME_SYNC(frame) (!!(frame->flags & GST_BASE_PARSE_FRAME_FLAG_SYNC)) - -/** - * GST_BASE_PARSE_FRAME_DRAIN: - * @frame: base parse frame instance - * - * Obtains current drain status indicated in frame. - * - * Since: 0.10.x - */ -#define GST_BASE_PARSE_FRAME_DRAIN(frame) (!!(frame->flags & GST_BASE_PARSE_FRAME_FLAG_DRAIN)) - -/** - * GstBaseParseFormat: - * @GST_BASE_PARSE_FORMAT_NONE: default setting - * @GST_BASE_PARSE_FORMAT_PASSTHROUGH: nature of format or configuration - * does not allow (much) parsing, so parser should operate in passthrough mode - * (which only applies operating in pull mode). That is, incoming buffers - * are pushed through unmodified, i.e. no @check_valid_frame or @parse_frame - * callbacks will be invoked. On the other hand, @pre_push_buffer is still invoked, - * where subclass can perform as much or as little is appropriate for - * "passthrough" semantics. - * @GST_BASE_PARSE_FORMAT_HAS_TIME: frames carry timing info which subclass - * can (generally) parse and provide. In particular, intrinsic time - * (rather than estimated) can be obtained following seek. - * - * Since: 0.10.x - */ -typedef enum _GstBaseParseFormat { - GST_BASE_PARSE_FORMAT_NONE = 0, - GST_BASE_PARSE_FORMAT_PASSTHROUGH = (1 << 0), - GST_BASE_PARSE_FORMAT_HAS_TIME = (1 << 1), -} GstBaseParseFormat; - -/** - * GstBaseParseSeekable: - * @GST_BASE_PARSE_SEEK_NONE: No seeking possible. - * @GST_BASE_PARSE_SEEK_DEFAULT: Default seeking possible using estimated bitrate. - * @GST_BASE_PARSE_SEEK_TABLE: Additional metadata provides more accurate seeking. - * - * Indicates what level (of quality) of seeking is possible. - * - * Since: 0.10.x - */ -typedef enum _GstBaseParseSeekable { - GST_BASE_PARSE_SEEK_NONE, - GST_BASE_PARSE_SEEK_DEFAULT, - GST_BASE_PARSE_SEEK_TABLE -} GstBaseParseSeekable; - -typedef struct _GstBaseParse GstBaseParse; -typedef struct _GstBaseParseClass GstBaseParseClass; -typedef struct _GstBaseParsePrivate GstBaseParsePrivate; - -/** - * GstBaseParse: - * @element: the parent element. - * - * The opaque #GstBaseParse data structure. - */ -struct _GstBaseParse { - GstElement element; - GstAdapter *adapter; - - /*< protected >*/ - /* source and sink pads */ - GstPad *sinkpad; - GstPad *srcpad; - - /* MT-protected (with STREAM_LOCK) */ - GstSegment segment; - - /* Newsegment event to be sent after SEEK */ - GstEvent *pending_segment; - - /* Segment event that closes the running segment prior to SEEK */ - GstEvent *close_segment; - - /*< private >*/ - gpointer _gst_reserved[GST_PADDING_LARGE]; - GstBaseParsePrivate *priv; -}; - -/** - * GstBaseParseClass: - * @start: Optional. - * Called when the element starts processing. - * Allows opening external resources. - * @stop: Optional. - * Called when the element stops processing. - * Allows closing external resources. - * @set_sink_caps: allows the subclass to be notified of the actual caps set. - * @check_valid_frame: Check if the given piece of data contains a valid - * frame. - * @parse_frame: Parse the already checked frame. Subclass need to - * set the buffer timestamp, duration, caps and possibly - * other necessary metadata. This is called with srcpad's - * STREAM_LOCK held. - * @convert: Optional. - * Convert between formats. - * @find_frame: Optional. - * Finds a frame. Gets a position passed and should return - * TRUE and the offset in bytes where this position is. - * Will only be called in pull mode and the subclass can pull - * whatever it wants from upstream. If not implemented, - * the base class will implement it by calling - * @check_valid_frame and @parse_frame to find the wanted - * frame and build a seek table. - * @event: Optional. - * Event handler on the sink pad. This function should return - * TRUE if the event was handled and can be dropped. - * @src_event: Optional. - * Event handler on the source pad. Should return TRUE - * if the event was handled and can be dropped. - * - * @get_frame_overhead: Finds the metadata overhead for the given frame. This - * is used to enable more accurate bitrate computations. - * If NULL, the per-frame overhead is assumed to be 0. If - * this returns -1, it is assumed that this frame should - * be skipped in bitrate calculation. - * - * @pre_push_buffer: Optional. - * Called just prior to pushing a frame (after any pending - * events have been sent) to give subclass a chance to perform - * additional actions at this time (e.g. tag sending) or to - * decide whether this buffer should be dropped or not - * (e.g. custom segment clipping). - * - * Subclasses can override any of the available virtual methods or not, as - * needed. At minimum @check_valid_frame and @parse_frame needs to be - * overridden. - */ -struct _GstBaseParseClass { - GstElementClass parent_class; - - /*< public >*/ - /* virtual methods for subclasses */ - - gboolean (*start) (GstBaseParse *parse); - - gboolean (*stop) (GstBaseParse *parse); - - gboolean (*set_sink_caps) (GstBaseParse *parse, - GstCaps *caps); - - gboolean (*check_valid_frame) (GstBaseParse *parse, - GstBaseParseFrame *frame, - guint *framesize, - gint *skipsize); - - GstFlowReturn (*parse_frame) (GstBaseParse *parse, - GstBaseParseFrame *frame); - - GstFlowReturn (*pre_push_frame) (GstBaseParse *parse, - GstBaseParseFrame *frame); - - gboolean (*convert) (GstBaseParse * parse, - GstFormat src_format, - gint64 src_value, - GstFormat dest_format, - gint64 * dest_value); - - gboolean (*event) (GstBaseParse *parse, - GstEvent *event); - - gboolean (*src_event) (GstBaseParse *parse, - GstEvent *event); - - /*< private >*/ - gpointer _gst_reserved[GST_PADDING_LARGE]; -}; - -GType gst_base_parse_get_type (void); - -void gst_base_parse_frame_init (GstBaseParse * parse, - GstBaseParseFrame * frame); -GstFlowReturn gst_base_parse_push_frame (GstBaseParse *parse, - GstBaseParseFrame *frame); - -void gst_base_parse_set_duration (GstBaseParse *parse, - GstFormat fmt, gint64 duration, - gint interval); -void gst_base_parse_set_seek (GstBaseParse * parse, - GstBaseParseSeekable seek, - guint bitrate); -void gst_base_parse_set_min_frame_size (GstBaseParse *parse, - guint min_size); -void gst_base_parse_set_format (GstBaseParse * parse, - GstBaseParseFormat flag, - gboolean on); -void gst_base_parse_set_frame_props (GstBaseParse * parse, - guint fps_num, guint fps_den, - guint lead_in, guint lead_out); - -gboolean gst_base_parse_convert_default (GstBaseParse * parse, - GstFormat src_format, gint64 src_value, - GstFormat dest_format, gint64 * dest_value); - -gboolean gst_base_parse_add_index_entry (GstBaseParse * parse, - guint64 offset, GstClockTime ts, - gboolean key, gboolean force); - -G_END_DECLS - -#endif /* __GST_BASE_PARSE_H__ */ diff --git a/gst/videoparsers/gsth263parse.h b/gst/videoparsers/gsth263parse.h index 86ebb6b69c..571f100d5b 100644 --- a/gst/videoparsers/gsth263parse.h +++ b/gst/videoparsers/gsth263parse.h @@ -30,7 +30,7 @@ #include #include -#include +#include #include "h263parse.h" diff --git a/gst/videoparsers/gsth264parse.h b/gst/videoparsers/gsth264parse.h index 50f4cf2364..7f42bc5d99 100644 --- a/gst/videoparsers/gsth264parse.h +++ b/gst/videoparsers/gsth264parse.h @@ -23,7 +23,7 @@ #define __GST_H264_PARSE_H__ #include -#include "gstbaseparse.h" +#include #include "h264parse.h" diff --git a/gst/videoparsers/h263parse.h b/gst/videoparsers/h263parse.h index 81dbed3299..2e66f0e482 100644 --- a/gst/videoparsers/h263parse.h +++ b/gst/videoparsers/h263parse.h @@ -25,7 +25,7 @@ #include #include -#include +#include G_BEGIN_DECLS From 5a1132aaf1038d25ebad267e78063488eb147692 Mon Sep 17 00:00:00 2001 From: David Schleef Date: Sat, 9 Oct 2010 15:06:12 -0700 Subject: [PATCH 420/448] element-maker: Add baseparse template --- tools/element-templates/baseparse | 109 ++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 tools/element-templates/baseparse diff --git a/tools/element-templates/baseparse b/tools/element-templates/baseparse new file mode 100644 index 0000000000..ff56b3ca42 --- /dev/null +++ b/tools/element-templates/baseparse @@ -0,0 +1,109 @@ +% ClassName +GstBaseParse +% TYPE_CLASS_NAME +GST_TYPE_BASE_PARSE +% pkg-config +gstreamer-base-0.10 +% includes +#include +% prototypes +static gboolean gst_replace_start (GstBaseParse *parse); +static gboolean gst_replace_stop (GstBaseParse *parse); +static gboolean gst_replace_set_sink_caps (GstBaseParse *parse, GstCaps *caps); +static gboolean gst_replace_check_valid_frame (GstBaseParse *parse, + GstBaseParseFrame *frame, guint *framesize, gint *skipsize); +static GstFlowReturn gst_replace_parse_frame (GstBaseParse *parse, + GstBaseParseFrame *frame); +static gboolean gst_replace_convert (GstBaseParse * parse, + GstFormat src_format, gint64 src_value, GstFormat dest_format, + gint64 * dest_value); +static gboolean gst_replace_event (GstBaseParse *parse, GstEvent *event); +static gboolean gst_replace_src_event (GstBaseParse *parse, GstEvent *event); +static GstFlowReturn gst_replace_pre_push_frame (GstBaseParse *parse, + GstBaseParseFrame *frame); +% declare-class + GstBaseParseClass *base_parse_class = GST_BASE_PARSE_CLASS (klass); +% set-methods + base_parse_class->start = GST_DEBUG_FUNCPTR (gst_replace_start); + base_parse_class->stop = GST_DEBUG_FUNCPTR (gst_replace_stop); + base_parse_class->set_sink_caps = GST_DEBUG_FUNCPTR (gst_replace_set_sink_caps); + base_parse_class->check_valid_frame = GST_DEBUG_FUNCPTR (gst_replace_check_valid_frame); + base_parse_class->parse_frame = GST_DEBUG_FUNCPTR (gst_replace_parse_frame); + base_parse_class->pre_push_frame = GST_DEBUG_FUNCPTR (gst_replace_pre_push_frame); + base_parse_class->convert = GST_DEBUG_FUNCPTR (gst_replace_convert); + base_parse_class->event = GST_DEBUG_FUNCPTR (gst_replace_event); + base_parse_class->src_event = GST_DEBUG_FUNCPTR (gst_replace_src_event); +% methods + +static gboolean +gst_replace_start (GstBaseParse *parse) +{ + return TRUE; +} + +static gboolean +gst_replace_stop (GstBaseParse *parse) +{ + return TRUE; +} + +static gboolean +gst_replace_set_sink_caps (GstBaseParse *parse, GstCaps *caps) +{ + /* Called when sink caps are set */ + return TRUE; +} + +static gboolean +gst_replace_check_valid_frame (GstBaseParse *parse, + GstBaseParseFrame *frame, guint *framesize, gint *skipsize) +{ + /* Called when processing incoming buffers. Function should check + whether the buffer contains a valid frame */ + /* MUST implement */ + return TRUE; +} + +static GstFlowReturn +gst_replace_parse_frame (GstBaseParse *parse, + GstBaseParseFrame *frame) +{ + /* Called when processing incoming buffers. Function should parse + a checked frame. */ + /* MUST implement */ + return GST_FLOW_OK; +} + +static gboolean +gst_replace_convert (GstBaseParse * parse, GstFormat src_format, + gint64 src_value, GstFormat dest_format, gint64 * dest_value) +{ + /* Convert between formats */ + + return FALSE; +} + +static gboolean +gst_replace_event (GstBaseParse *parse, GstEvent *event) +{ + /* Sink pad event handler */ + + return FALSE; +} + +static gboolean +gst_replace_src_event (GstBaseParse *parse, GstEvent *event) +{ + /* Src pad event handler */ + + return FALSE; +} + +static GstFlowReturn +gst_replace_pre_push_frame (GstBaseParse *parse, GstBaseParseFrame *frame) +{ + + return GST_FLOW_OK; +} + +% end From fedcf43e29c4bf82c54dd088f931d873026664e8 Mon Sep 17 00:00:00 2001 From: David Schleef Date: Thu, 17 Feb 2011 13:20:46 -0800 Subject: [PATCH 421/448] element-maker: do test build with -fPIC --- tools/gst-element-maker | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/gst-element-maker b/tools/gst-element-maker index 53145bc3af..53b26cac8d 100755 --- a/tools/gst-element-maker +++ b/tools/gst-element-maker @@ -377,7 +377,7 @@ gst-indent $gstreplace.c echo pkg is $pkg -gcc -Wall $(pkg-config --cflags gstreamer-0.10 $pkg) -c -o $gstreplace.o $gstreplace.c +gcc -Wall -fPIC $(pkg-config --cflags gstreamer-0.10 $pkg) -c -o $gstreplace.o $gstreplace.c gcc -shared -o $gstreplace.so $gstreplace.o $(pkg-config --libs gstreamer-0.10 $pkg) From e9ea237d03cda3f7c2b5eabaa9ec65b6ef6cd4e4 Mon Sep 17 00:00:00 2001 From: David Schleef Date: Sat, 9 Oct 2010 15:08:39 -0700 Subject: [PATCH 422/448] videoparsers: Add dirac parser --- gst/videoparsers/Makefile.am | 8 +- gst/videoparsers/dirac_parse.c | 498 +++++++++++++++++++++++++++++++ gst/videoparsers/dirac_parse.h | 178 +++++++++++ gst/videoparsers/gstdiracparse.c | 352 ++++++++++++++++++++++ gst/videoparsers/gstdiracparse.h | 52 ++++ gst/videoparsers/plugin.c | 4 + 6 files changed, 1090 insertions(+), 2 deletions(-) create mode 100644 gst/videoparsers/dirac_parse.c create mode 100644 gst/videoparsers/dirac_parse.h create mode 100644 gst/videoparsers/gstdiracparse.c create mode 100644 gst/videoparsers/gstdiracparse.h diff --git a/gst/videoparsers/Makefile.am b/gst/videoparsers/Makefile.am index 59b5160211..a344117a71 100644 --- a/gst/videoparsers/Makefile.am +++ b/gst/videoparsers/Makefile.am @@ -1,11 +1,15 @@ plugin_LTLIBRARIES = libgsth263parse.la libgsth263parse_la_SOURCES = plugin.c \ - h263parse.c gsth263parse.c gsth264parse.c h264parse.c + h263parse.c gsth263parse.c \ + gsth264parse.c h264parse.c \ + gstdiracparse.c dirac_parse.c libgsth263parse_la_CFLAGS = $(GST_CFLAGS) libgsth263parse_la_LIBADD = $(GST_BASE_LIBS) $(GST_LIBS) libgsth263parse_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) libgsth263parse_la_LIBTOOLFLAGS = --tag=disable-static noinst_HEADERS = gsth263parse.h h263parse.h \ - gsth264parse.h h264parse.h + gsth264parse.h h264parse.h \ + gstdiracparse.h dirac_parse.h + diff --git a/gst/videoparsers/dirac_parse.c b/gst/videoparsers/dirac_parse.c new file mode 100644 index 0000000000..3a3193d925 --- /dev/null +++ b/gst/videoparsers/dirac_parse.c @@ -0,0 +1,498 @@ + +#include "dirac_parse.h" +#include + +#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) + +typedef struct _Unpack Unpack; + +struct _Unpack +{ + unsigned char *data; + int n_bits_left; + int index; + int guard_bit; +}; + +static void schro_unpack_init_with_data (Unpack * unpack, unsigned char *data, + int n_bytes, unsigned int guard_bit); + +static unsigned int schro_unpack_decode_bit (Unpack * unpack); +static unsigned int schro_unpack_decode_uint (Unpack * unpack); + + +void schro_video_format_set_std_video_format (DiracSequenceHeader * format, + int index); +void schro_video_format_set_std_frame_rate (DiracSequenceHeader * format, + int index); +void schro_video_format_set_std_aspect_ratio (DiracSequenceHeader * format, + int index); +void schro_video_format_set_std_signal_range (DiracSequenceHeader * format, + int index); +void schro_video_format_set_std_colour_spec (DiracSequenceHeader * format, + int index); + + + + +int +dirac_sequence_header_parse (DiracSequenceHeader * header, + unsigned char *data, int n_bytes) +{ + int bit; + int index; + Unpack _unpack; + Unpack *unpack = &_unpack; + int major_version; + int minor_version; + int profile; + int level; + + memset (header, 0, sizeof (*header)); + + schro_unpack_init_with_data (unpack, data, n_bytes, 1); + + /* parse parameters */ + major_version = schro_unpack_decode_uint (unpack); + minor_version = schro_unpack_decode_uint (unpack); + profile = schro_unpack_decode_uint (unpack); + level = schro_unpack_decode_uint (unpack); + + /* base video header */ + index = schro_unpack_decode_uint (unpack); + schro_video_format_set_std_video_format (header, index); + + header->major_version = major_version; + header->minor_version = minor_version; + header->profile = profile; + header->level = level; + + /* source parameters */ + /* frame dimensions */ + bit = schro_unpack_decode_bit (unpack); + if (bit) { + header->width = schro_unpack_decode_uint (unpack); + header->height = schro_unpack_decode_uint (unpack); + } + + /* chroma header */ + bit = schro_unpack_decode_bit (unpack); + if (bit) { + header->chroma_format = schro_unpack_decode_uint (unpack); + } + + /* scan header */ + bit = schro_unpack_decode_bit (unpack); + if (bit) { + header->interlaced = schro_unpack_decode_uint (unpack); + } + + /* frame rate */ + bit = schro_unpack_decode_bit (unpack); + if (bit) { + index = schro_unpack_decode_uint (unpack); + if (index == 0) { + header->frame_rate_numerator = schro_unpack_decode_uint (unpack); + header->frame_rate_denominator = schro_unpack_decode_uint (unpack); + } else { + schro_video_format_set_std_frame_rate (header, index); + } + } + + /* aspect ratio */ + bit = schro_unpack_decode_bit (unpack); + if (bit) { + index = schro_unpack_decode_uint (unpack); + if (index == 0) { + header->aspect_ratio_numerator = schro_unpack_decode_uint (unpack); + header->aspect_ratio_denominator = schro_unpack_decode_uint (unpack); + } else { + schro_video_format_set_std_aspect_ratio (header, index); + } + } + + /* clean area */ + bit = schro_unpack_decode_bit (unpack); + if (bit) { + header->clean_width = schro_unpack_decode_uint (unpack); + header->clean_height = schro_unpack_decode_uint (unpack); + header->left_offset = schro_unpack_decode_uint (unpack); + header->top_offset = schro_unpack_decode_uint (unpack); + } + + /* signal range */ + bit = schro_unpack_decode_bit (unpack); + if (bit) { + index = schro_unpack_decode_uint (unpack); + if (index == 0) { + header->luma_offset = schro_unpack_decode_uint (unpack); + header->luma_excursion = schro_unpack_decode_uint (unpack); + header->chroma_offset = schro_unpack_decode_uint (unpack); + header->chroma_excursion = schro_unpack_decode_uint (unpack); + } else { + schro_video_format_set_std_signal_range (header, index); + } + } + + /* colour spec */ + bit = schro_unpack_decode_bit (unpack); + if (bit) { + index = schro_unpack_decode_uint (unpack); + schro_video_format_set_std_colour_spec (header, index); + if (index == 0) { + /* colour primaries */ + bit = schro_unpack_decode_bit (unpack); + if (bit) { + header->colour_primaries = schro_unpack_decode_uint (unpack); + } + /* colour matrix */ + bit = schro_unpack_decode_bit (unpack); + if (bit) { + header->colour_matrix = schro_unpack_decode_uint (unpack); + } + /* transfer function */ + bit = schro_unpack_decode_bit (unpack); + if (bit) { + header->transfer_function = schro_unpack_decode_uint (unpack); + } + } + } + + header->interlaced_coding = schro_unpack_decode_uint (unpack); + + return 1; +} + +/* standard stuff */ + +static DiracSequenceHeader schro_video_formats[] = { + {0, 0, 0, 0, + 0, /* custom */ + 640, 480, SCHRO_CHROMA_420, + FALSE, FALSE, + 24000, 1001, 1, 1, + 640, 480, 0, 0, + 0, 255, 128, 255, + 0, 0, 0}, + {0, 0, 0, 0, + 1, /* QSIF525 */ + 176, 120, SCHRO_CHROMA_420, + FALSE, FALSE, + 15000, 1001, 10, 11, + 176, 120, 0, 0, + 0, 255, 128, 255, + 1, 1, 0}, + {0, 0, 0, 0, + 2, /* QCIF */ + 176, 144, SCHRO_CHROMA_420, + FALSE, TRUE, + 25, 2, 12, 11, + 176, 144, 0, 0, + 0, 255, 128, 255, + 2, 1, 0}, + {0, 0, 0, 0, + 3, /* SIF525 */ + 352, 240, SCHRO_CHROMA_420, + FALSE, FALSE, + 15000, 1001, 10, 11, + 352, 240, 0, 0, + 0, 255, 128, 255, + 1, 1, 0}, + {0, 0, 0, 0, + 4, /* CIF */ + 352, 288, SCHRO_CHROMA_420, + FALSE, TRUE, + 25, 2, 12, 11, + 352, 288, 0, 0, + 0, 255, 128, 255, + 2, 1, 0}, + {0, 0, 0, 0, + 5, /* 4SIF525 */ + 704, 480, SCHRO_CHROMA_420, + FALSE, FALSE, + 15000, 1001, 10, 11, + 704, 480, 0, 0, + 0, 255, 128, 255, + 1, 1, 0}, + {0, 0, 0, 0, + 6, /* 4CIF */ + 704, 576, SCHRO_CHROMA_420, + FALSE, TRUE, + 25, 2, 12, 11, + 704, 576, 0, 0, + 0, 255, 128, 255, + 2, 1, 0}, + {0, 0, 0, 0, + 7, /* SD480I-60 */ + 720, 480, SCHRO_CHROMA_422, + TRUE, FALSE, + 30000, 1001, 10, 11, + 704, 480, 8, 0, + 64, 876, 512, 896, + 1, 1, 0}, + {0, 0, 0, 0, + 8, /* SD576I-50 */ + 720, 576, SCHRO_CHROMA_422, + TRUE, TRUE, + 25, 1, 12, 11, + 704, 576, 8, 0, + 64, 876, 512, 896, + 2, 1, 0}, + {0, 0, 0, 0, + 9, /* HD720P-60 */ + 1280, 720, SCHRO_CHROMA_422, + FALSE, TRUE, + 60000, 1001, 1, 1, + 1280, 720, 0, 0, + 64, 876, 512, 896, + 0, 0, 0}, + {0, 0, 0, 0, + 10, /* HD720P-50 */ + 1280, 720, SCHRO_CHROMA_422, + FALSE, TRUE, + 50, 1, 1, 1, + 1280, 720, 0, 0, + 64, 876, 512, 896, + 0, 0, 0}, + {0, 0, 0, 0, + 11, /* HD1080I-60 */ + 1920, 1080, SCHRO_CHROMA_422, + TRUE, TRUE, + 30000, 1001, 1, 1, + 1920, 1080, 0, 0, + 64, 876, 512, 896, + 0, 0, 0}, + {0, 0, 0, 0, + 12, /* HD1080I-50 */ + 1920, 1080, SCHRO_CHROMA_422, + TRUE, TRUE, + 25, 1, 1, 1, + 1920, 1080, 0, 0, + 64, 876, 512, 896, + 0, 0, 0}, + {0, 0, 0, 0, + 13, /* HD1080P-60 */ + 1920, 1080, SCHRO_CHROMA_422, + FALSE, TRUE, + 60000, 1001, 1, 1, + 1920, 1080, 0, 0, + 64, 876, 512, 896, + 0, 0, 0}, + {0, 0, 0, 0, + 14, /* HD1080P-50 */ + 1920, 1080, SCHRO_CHROMA_422, + FALSE, TRUE, + 50, 1, 1, 1, + 1920, 1080, 0, 0, + 64, 876, 512, 896, + 0, 0, 0}, + {0, 0, 0, 0, + 15, /* DC2K */ + 2048, 1080, SCHRO_CHROMA_444, + FALSE, TRUE, + 24, 1, 1, 1, + 2048, 1080, 0, 0, + 256, 3504, 2048, 3584, + 3, 0, 0}, + {0, 0, 0, 0, + 16, /* DC4K */ + 4096, 2160, SCHRO_CHROMA_444, + FALSE, TRUE, + 24, 1, 1, 1, + 2048, 1536, 0, 0, + 256, 3504, 2048, 3584, + 3, 0, 0}, +}; + +void +schro_video_format_set_std_video_format (DiracSequenceHeader * format, + int index) +{ + + if (index < 0 || index >= ARRAY_SIZE (schro_video_formats)) { + return; + } + + memcpy (format, schro_video_formats + index, sizeof (DiracSequenceHeader)); +} + +typedef struct _SchroFrameRate SchroFrameRate; +struct _SchroFrameRate +{ + int numerator; + int denominator; +}; + +static SchroFrameRate schro_frame_rates[] = { + {0, 0}, + {24000, 1001}, + {24, 1}, + {25, 1}, + {30000, 1001}, + {30, 1}, + {50, 1}, + {60000, 1001}, + {60, 1}, + {15000, 1001}, + {25, 2} +}; + +void +schro_video_format_set_std_frame_rate (DiracSequenceHeader * format, int index) +{ + if (index < 1 || index >= ARRAY_SIZE (schro_frame_rates)) { + return; + } + + format->frame_rate_numerator = schro_frame_rates[index].numerator; + format->frame_rate_denominator = schro_frame_rates[index].denominator; +} + +typedef struct _SchroPixelAspectRatio SchroPixelAspectRatio; +struct _SchroPixelAspectRatio +{ + int numerator; + int denominator; +}; + +static const SchroPixelAspectRatio schro_aspect_ratios[] = { + {0, 0}, + {1, 1}, + {10, 11}, + {12, 11}, + {40, 33}, + {16, 11}, + {4, 3} +}; + +void +schro_video_format_set_std_aspect_ratio (DiracSequenceHeader * format, + int index) +{ + if (index < 1 || index >= ARRAY_SIZE (schro_aspect_ratios)) { + return; + } + + format->aspect_ratio_numerator = schro_aspect_ratios[index].numerator; + format->aspect_ratio_denominator = schro_aspect_ratios[index].denominator; + +} + +typedef struct _SchroSignalRangeStruct SchroSignalRangeStruct; +struct _SchroSignalRangeStruct +{ + int luma_offset; + int luma_excursion; + int chroma_offset; + int chroma_excursion; +}; + +static const SchroSignalRangeStruct schro_signal_ranges[] = { + {0, 0, 0, 0}, + {0, 255, 128, 255}, + {16, 219, 128, 224}, + {64, 876, 512, 896}, + {256, 3504, 2048, 3584} +}; + +void +schro_video_format_set_std_signal_range (DiracSequenceHeader * format, int i) +{ + if (i < 1 || i >= ARRAY_SIZE (schro_signal_ranges)) { + return; + } + + format->luma_offset = schro_signal_ranges[i].luma_offset; + format->luma_excursion = schro_signal_ranges[i].luma_excursion; + format->chroma_offset = schro_signal_ranges[i].chroma_offset; + format->chroma_excursion = schro_signal_ranges[i].chroma_excursion; +} + +typedef struct _SchroColourSpecStruct SchroColourSpecStruct; +struct _SchroColourSpecStruct +{ + int colour_primaries; + int colour_matrix; + int transfer_function; +}; + +static const SchroColourSpecStruct schro_colour_specs[] = { + { /* Custom */ + SCHRO_COLOUR_PRIMARY_HDTV, + SCHRO_COLOUR_MATRIX_HDTV, + SCHRO_TRANSFER_CHAR_TV_GAMMA}, + { /* SDTV 525 */ + SCHRO_COLOUR_PRIMARY_SDTV_525, + SCHRO_COLOUR_MATRIX_SDTV, + SCHRO_TRANSFER_CHAR_TV_GAMMA}, + { /* SDTV 625 */ + SCHRO_COLOUR_PRIMARY_SDTV_625, + SCHRO_COLOUR_MATRIX_SDTV, + SCHRO_TRANSFER_CHAR_TV_GAMMA}, + { /* HDTV */ + SCHRO_COLOUR_PRIMARY_HDTV, + SCHRO_COLOUR_MATRIX_HDTV, + SCHRO_TRANSFER_CHAR_TV_GAMMA}, + { /* Cinema */ + SCHRO_COLOUR_PRIMARY_CINEMA, + SCHRO_COLOUR_MATRIX_HDTV, + SCHRO_TRANSFER_CHAR_TV_GAMMA} +}; + +void +schro_video_format_set_std_colour_spec (DiracSequenceHeader * format, int i) +{ + if (i < 0 || i >= ARRAY_SIZE (schro_colour_specs)) { + return; + } + + format->colour_primaries = schro_colour_specs[i].colour_primaries; + format->colour_matrix = schro_colour_specs[i].colour_matrix; + format->transfer_function = schro_colour_specs[i].transfer_function; +} + + +/* unpack */ + +static void +schro_unpack_init_with_data (Unpack * unpack, unsigned char *data, + int n_bytes, unsigned int guard_bit) +{ + memset (unpack, 0, sizeof (Unpack)); + + unpack->data = data; + unpack->n_bits_left = 8 * n_bytes; + unpack->guard_bit = guard_bit; +} + +static unsigned int +schro_unpack_decode_bit (Unpack * unpack) +{ + int bit; + + if (unpack->n_bits_left < 1) { + return unpack->guard_bit; + } + bit = (unpack->data[unpack->index >> 3] >> (7 - (unpack->index & 7))) & 1; + unpack->index++; + unpack->n_bits_left--; + + return bit; +} + +static unsigned int +schro_unpack_decode_uint (Unpack * unpack) +{ + int count; + int value; + + count = 0; + value = 0; + while (!schro_unpack_decode_bit (unpack)) { + count++; + value <<= 1; + value |= schro_unpack_decode_bit (unpack); + } + + return (1 << count) - 1 + value; +} diff --git a/gst/videoparsers/dirac_parse.h b/gst/videoparsers/dirac_parse.h new file mode 100644 index 0000000000..9dc4ffec5f --- /dev/null +++ b/gst/videoparsers/dirac_parse.h @@ -0,0 +1,178 @@ + +#ifndef __DIRAC_PARSE_H__ +#define __DIRAC_PARSE_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef TRUE +#define TRUE 1 +#endif +#ifndef FALSE +#define FALSE 0 +#endif + +typedef enum _SchroParseCode { + SCHRO_PARSE_CODE_SEQUENCE_HEADER = 0x00, + SCHRO_PARSE_CODE_END_OF_SEQUENCE = 0x10, + SCHRO_PARSE_CODE_AUXILIARY_DATA = 0x20, + SCHRO_PARSE_CODE_PADDING = 0x30, + + SCHRO_PARSE_CODE_INTRA_REF = 0x0c, + SCHRO_PARSE_CODE_INTRA_NON_REF = 0x08, + SCHRO_PARSE_CODE_INTRA_REF_NOARITH = 0x4c, + SCHRO_PARSE_CODE_INTRA_NON_REF_NOARITH = 0x48, + + SCHRO_PARSE_CODE_INTER_REF_1 = 0x0d, + SCHRO_PARSE_CODE_INTER_REF_1_NOARITH = 0x4d, + SCHRO_PARSE_CODE_INTER_REF_2 = 0x0e, + SCHRO_PARSE_CODE_INTER_REF_2_NOARITH = 0x4e, + + SCHRO_PARSE_CODE_INTER_NON_REF_1 = 0x09, + SCHRO_PARSE_CODE_INTER_NON_REF_1_NOARITH = 0x49, + SCHRO_PARSE_CODE_INTER_NON_REF_2 = 0x0a, + SCHRO_PARSE_CODE_INTER_NON_REF_2_NOARITH = 0x4a, + + SCHRO_PARSE_CODE_LD_INTRA_REF = 0xcc, + SCHRO_PARSE_CODE_LD_INTRA_NON_REF = 0xc8 +} SchroParseCode; + +#define SCHRO_PARSE_CODE_PICTURE(is_ref,n_refs,is_lowdelay,is_noarith) \ + (8 | ((is_ref)<<2) | (n_refs) | ((is_lowdelay)<<7) | ((is_noarith)<<6)) + +#define SCHRO_PARSE_CODE_IS_SEQ_HEADER(x) ((x) == SCHRO_PARSE_CODE_SEQUENCE_HEADER) +#define SCHRO_PARSE_CODE_IS_END_OF_SEQUENCE(x) ((x) == SCHRO_PARSE_CODE_END_OF_SEQUENCE) +#define SCHRO_PARSE_CODE_IS_AUXILIARY_DATA(x) ((x) == SCHRO_PARSE_CODE_AUXILIARY_DATA) +#define SCHRO_PARSE_CODE_IS_PADDING(x) ((x) == SCHRO_PARSE_CODE_PADDING) +#define SCHRO_PARSE_CODE_IS_PICTURE(x) ((x) & 0x8) +#define SCHRO_PARSE_CODE_IS_LOW_DELAY(x) (((x) & 0x88) == 0x88) +#define SCHRO_PARSE_CODE_IS_CORE_SYNTAX(x) (((x) & 0x88) == 0x08) +#define SCHRO_PARSE_CODE_USING_AC(x) (((x) & 0x48) == 0x08) +#define SCHRO_PARSE_CODE_IS_REFERENCE(x) (((x) & 0xc) == 0x0c) +#define SCHRO_PARSE_CODE_IS_NON_REFERENCE(x) (((x) & 0xc) == 0x08) +#define SCHRO_PARSE_CODE_NUM_REFS(x) ((x) & 0x3) +#define SCHRO_PARSE_CODE_IS_INTRA(x) (SCHRO_PARSE_CODE_IS_PICTURE(x) && SCHRO_PARSE_CODE_NUM_REFS(x) == 0) +#define SCHRO_PARSE_CODE_IS_INTER(x) (SCHRO_PARSE_CODE_IS_PICTURE(x) && SCHRO_PARSE_CODE_NUM_REFS(x) > 0) + +#define SCHRO_PARSE_HEADER_SIZE (4+1+4+4) + +typedef enum _SchroVideoFormatEnum { + SCHRO_VIDEO_FORMAT_CUSTOM = 0, + SCHRO_VIDEO_FORMAT_QSIF, + SCHRO_VIDEO_FORMAT_QCIF, + SCHRO_VIDEO_FORMAT_SIF, + SCHRO_VIDEO_FORMAT_CIF, + SCHRO_VIDEO_FORMAT_4SIF, + SCHRO_VIDEO_FORMAT_4CIF, + SCHRO_VIDEO_FORMAT_SD480I_60, + SCHRO_VIDEO_FORMAT_SD576I_50, + SCHRO_VIDEO_FORMAT_HD720P_60, + SCHRO_VIDEO_FORMAT_HD720P_50, + SCHRO_VIDEO_FORMAT_HD1080I_60, + SCHRO_VIDEO_FORMAT_HD1080I_50, + SCHRO_VIDEO_FORMAT_HD1080P_60, + SCHRO_VIDEO_FORMAT_HD1080P_50, + SCHRO_VIDEO_FORMAT_DC2K_24, + SCHRO_VIDEO_FORMAT_DC4K_24 +} SchroVideoFormatEnum; + +typedef enum _SchroChromaFormat { + SCHRO_CHROMA_444 = 0, + SCHRO_CHROMA_422, + SCHRO_CHROMA_420 +} SchroChromaFormat; + +#define SCHRO_CHROMA_FORMAT_H_SHIFT(format) (((format) == SCHRO_CHROMA_444)?0:1) +#define SCHRO_CHROMA_FORMAT_V_SHIFT(format) (((format) == SCHRO_CHROMA_420)?1:0) + +typedef enum _SchroSignalRange { + SCHRO_SIGNAL_RANGE_CUSTOM = 0, + SCHRO_SIGNAL_RANGE_8BIT_FULL = 1, + SCHRO_SIGNAL_RANGE_8BIT_VIDEO = 2, + SCHRO_SIGNAL_RANGE_10BIT_VIDEO = 3, + SCHRO_SIGNAL_RANGE_12BIT_VIDEO = 4 +} SchroSignalRange; + +typedef enum _SchroColourSpec { + SCHRO_COLOUR_SPEC_CUSTOM = 0, + SCHRO_COLOUR_SPEC_SDTV_525 = 1, + SCHRO_COLOUR_SPEC_SDTV_625 = 2, + SCHRO_COLOUR_SPEC_HDTV = 3, + SCHRO_COLOUR_SPEC_CINEMA = 4 +} SchroColourSpec; + +typedef enum _SchroColourPrimaries { + SCHRO_COLOUR_PRIMARY_HDTV = 0, + SCHRO_COLOUR_PRIMARY_SDTV_525 = 1, + SCHRO_COLOUR_PRIMARY_SDTV_625 = 2, + SCHRO_COLOUR_PRIMARY_CINEMA = 3 +} SchroColourPrimaries; + +typedef enum _SchroColourMatrix { + SCHRO_COLOUR_MATRIX_HDTV = 0, + SCHRO_COLOUR_MATRIX_SDTV = 1, + SCHRO_COLOUR_MATRIX_REVERSIBLE = 2 +}SchroColourMatrix; + +typedef enum _SchroTransferFunction { + SCHRO_TRANSFER_CHAR_TV_GAMMA = 0, + SCHRO_TRANSFER_CHAR_EXTENDED_GAMUT = 1, + SCHRO_TRANSFER_CHAR_LINEAR = 2, + SCHRO_TRANSFER_CHAR_DCI_GAMMA = 3 +} SchroTransferFunction; + + + +typedef struct _DiracSequenceHeader DiracSequenceHeader; + +struct _DiracSequenceHeader { + int major_version; + int minor_version; + int profile; + int level; + + int index; + int width; + int height; + int chroma_format; + + int interlaced; + int top_field_first; + + int frame_rate_numerator; + int frame_rate_denominator; + int aspect_ratio_numerator; + int aspect_ratio_denominator; + + int clean_width; + int clean_height; + int left_offset; + int top_offset; + + int luma_offset; + int luma_excursion; + int chroma_offset; + int chroma_excursion; + + int colour_primaries; + int colour_matrix; + int transfer_function; + + int interlaced_coding; + + int unused0; + int unused1; + int unused2; +}; + + +int dirac_sequence_header_parse (DiracSequenceHeader *header, + unsigned char *data, int length); + +#ifdef __cplusplus +} +#endif + +#endif + diff --git a/gst/videoparsers/gstdiracparse.c b/gst/videoparsers/gstdiracparse.c new file mode 100644 index 0000000000..4ddcd3a5ae --- /dev/null +++ b/gst/videoparsers/gstdiracparse.c @@ -0,0 +1,352 @@ +/* GStreamer + * Copyright (C) 2010 David Schleef + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ +/** + * SECTION:element-gstdiracparse + * + * The gstdiracparse element does FIXME stuff. + * + * + * Example launch line + * |[ + * gst-launch -v fakesrc ! gstdiracparse ! FIXME ! fakesink + * ]| + * FIXME Describe what the pipeline does. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include +#include +#include "gstdiracparse.h" + +/* prototypes */ + + +static void gst_dirac_parse_set_property (GObject * object, + guint property_id, const GValue * value, GParamSpec * pspec); +static void gst_dirac_parse_get_property (GObject * object, + guint property_id, GValue * value, GParamSpec * pspec); +static void gst_dirac_parse_dispose (GObject * object); +static void gst_dirac_parse_finalize (GObject * object); + +static gboolean gst_dirac_parse_start (GstBaseParse * parse); +static gboolean gst_dirac_parse_stop (GstBaseParse * parse); +static gboolean gst_dirac_parse_set_sink_caps (GstBaseParse * parse, + GstCaps * caps); +static gboolean gst_dirac_parse_check_valid_frame (GstBaseParse * parse, + GstBaseParseFrame * frame, guint * framesize, gint * skipsize); +static GstFlowReturn gst_dirac_parse_parse_frame (GstBaseParse * parse, + GstBaseParseFrame * frame); +static gboolean gst_dirac_parse_convert (GstBaseParse * parse, + GstFormat src_format, gint64 src_value, GstFormat dest_format, + gint64 * dest_value); +static gboolean gst_dirac_parse_event (GstBaseParse * parse, GstEvent * event); +static gboolean gst_dirac_parse_src_event (GstBaseParse * parse, + GstEvent * event); +static GstFlowReturn gst_dirac_parse_pre_push_frame (GstBaseParse * parse, + GstBaseParseFrame * frame); + +enum +{ + PROP_0 +}; + +/* pad templates */ + +static GstStaticPadTemplate gst_dirac_parse_sink_template = +GST_STATIC_PAD_TEMPLATE ("sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("application/unknown") + ); + +static GstStaticPadTemplate gst_dirac_parse_src_template = +GST_STATIC_PAD_TEMPLATE ("src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + GST_STATIC_CAPS ("application/unknown") + ); + +/* class initialization */ + +GST_BOILERPLATE (GstDiracParse, gst_dirac_parse, GstBaseParse, + GST_TYPE_BASE_PARSE); + +static void +gst_dirac_parse_base_init (gpointer g_class) +{ + GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); + + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_dirac_parse_src_template)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_dirac_parse_sink_template)); + + gst_element_class_set_details_simple (element_class, "FIXME", + "Generic", "FIXME", "David Schleef "); +} + +static void +gst_dirac_parse_class_init (GstDiracParseClass * klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + GstBaseParseClass *base_parse_class = GST_BASE_PARSE_CLASS (klass); + + gobject_class->set_property = gst_dirac_parse_set_property; + gobject_class->get_property = gst_dirac_parse_get_property; + gobject_class->dispose = gst_dirac_parse_dispose; + gobject_class->finalize = gst_dirac_parse_finalize; + base_parse_class->start = GST_DEBUG_FUNCPTR (gst_dirac_parse_start); + base_parse_class->stop = GST_DEBUG_FUNCPTR (gst_dirac_parse_stop); + base_parse_class->set_sink_caps = + GST_DEBUG_FUNCPTR (gst_dirac_parse_set_sink_caps); + base_parse_class->check_valid_frame = + GST_DEBUG_FUNCPTR (gst_dirac_parse_check_valid_frame); + base_parse_class->parse_frame = + GST_DEBUG_FUNCPTR (gst_dirac_parse_parse_frame); + base_parse_class->convert = GST_DEBUG_FUNCPTR (gst_dirac_parse_convert); + base_parse_class->event = GST_DEBUG_FUNCPTR (gst_dirac_parse_event); + base_parse_class->src_event = GST_DEBUG_FUNCPTR (gst_dirac_parse_src_event); + base_parse_class->pre_push_frame = + GST_DEBUG_FUNCPTR (gst_dirac_parse_pre_push_frame); + +} + +static void +gst_dirac_parse_init (GstDiracParse * diracparse, + GstDiracParseClass * diracparse_class) +{ + gst_base_parse_set_min_frame_size (GST_BASE_PARSE (diracparse), 13); + +} + +void +gst_dirac_parse_set_property (GObject * object, guint property_id, + const GValue * value, GParamSpec * pspec) +{ + GstDiracParse *diracparse; + + g_return_if_fail (GST_IS_DIRAC_PARSE (object)); + diracparse = GST_DIRAC_PARSE (object); + + switch (property_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +void +gst_dirac_parse_get_property (GObject * object, guint property_id, + GValue * value, GParamSpec * pspec) +{ + GstDiracParse *diracparse; + + g_return_if_fail (GST_IS_DIRAC_PARSE (object)); + diracparse = GST_DIRAC_PARSE (object); + + switch (property_id) { + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +void +gst_dirac_parse_dispose (GObject * object) +{ + GstDiracParse *diracparse; + + g_return_if_fail (GST_IS_DIRAC_PARSE (object)); + diracparse = GST_DIRAC_PARSE (object); + + /* clean up as possible. may be called multiple times */ + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + +void +gst_dirac_parse_finalize (GObject * object) +{ + GstDiracParse *diracparse; + + g_return_if_fail (GST_IS_DIRAC_PARSE (object)); + diracparse = GST_DIRAC_PARSE (object); + + /* clean up object here */ + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + + +static gboolean +gst_dirac_parse_start (GstBaseParse * parse) +{ + return TRUE; +} + +static gboolean +gst_dirac_parse_stop (GstBaseParse * parse) +{ + return TRUE; +} + +static gboolean +gst_dirac_parse_set_sink_caps (GstBaseParse * parse, GstCaps * caps) +{ + /* Called when sink caps are set */ + return TRUE; +} + +static gboolean +gst_dirac_parse_frame_header (GstDiracParse * diracparse, + GstBuffer * buffer, guint * framesize) +{ + int next_header; + + next_header = GST_READ_UINT32_BE (GST_BUFFER_DATA (buffer) + 5); + + *framesize = next_header; + return TRUE; +} + +static gboolean +gst_dirac_parse_check_valid_frame (GstBaseParse * parse, + GstBaseParseFrame * frame, guint * framesize, gint * skipsize) +{ + GstByteReader reader = GST_BYTE_READER_INIT_FROM_BUFFER (frame->buffer); + GstDiracParse *diracparse = GST_DIRAC_PARSE (parse); + int off; + guint32 next_header; + gboolean sync; + gboolean drain; + + if (G_UNLIKELY (GST_BUFFER_SIZE (frame->buffer) < 13)) + return FALSE; + + off = gst_byte_reader_masked_scan_uint32 (&reader, 0xffffffff, + 0x42424344, 0, GST_BUFFER_SIZE (frame->buffer)); + + if (off < 0) { + *skipsize = GST_BUFFER_SIZE (frame->buffer) - 3; + return FALSE; + } + + GST_LOG_OBJECT (parse, "possible sync at buffer offset %d", off); + + if (off > 0) { + GST_ERROR ("skipping %d", off); + *skipsize = off; + return FALSE; + } + + if (!gst_dirac_parse_frame_header (diracparse, frame->buffer, framesize)) { + GST_ERROR ("bad header"); + *skipsize = 3; + return FALSE; + } + + GST_LOG ("framesize %d", *framesize); + + sync = GST_BASE_PARSE_FRAME_SYNC (frame); + drain = GST_BASE_PARSE_FRAME_DRAIN (frame); + + if (!sync && !drain) { + guint32 next_sync_word; + + next_header = GST_READ_UINT32_BE (GST_BUFFER_DATA (frame->buffer) + 5); + GST_LOG ("next header %d", next_header); + + if (!gst_byte_reader_skip (&reader, next_header) || + !gst_byte_reader_get_uint32_be (&reader, &next_sync_word)) { + gst_base_parse_set_min_frame_size (parse, next_header + 4); + *skipsize = 0; + return FALSE; + } else { + if (next_sync_word != 0x42424344) { + *skipsize = 3; + return FALSE; + } else { + gst_base_parse_set_min_frame_size (parse, next_header); + + } + } + } + + return TRUE; +} + +static GstFlowReturn +gst_dirac_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame) +{ + //GstDiracParse * diracparse = GST_DIRAC_PARSE (parse); + + /* Called when processing incoming buffers. Function should parse + a checked frame. */ + /* MUST implement */ + + if (GST_PAD_CAPS (GST_BASE_PARSE_SRC_PAD (parse)) == NULL) { + GstCaps *caps = gst_caps_new_simple ("video/x-dirac", NULL); + + gst_buffer_set_caps (frame->buffer, caps); + gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (parse), caps); + gst_caps_unref (caps); + + } + + gst_base_parse_set_min_frame_size (parse, 13); + + return GST_FLOW_OK; +} + +static gboolean +gst_dirac_parse_convert (GstBaseParse * parse, GstFormat src_format, + gint64 src_value, GstFormat dest_format, gint64 * dest_value) +{ + /* Convert between formats */ + + return FALSE; +} + +static gboolean +gst_dirac_parse_event (GstBaseParse * parse, GstEvent * event) +{ + /* Sink pad event handler */ + + return FALSE; +} + +static gboolean +gst_dirac_parse_src_event (GstBaseParse * parse, GstEvent * event) +{ + /* Src pad event handler */ + + return FALSE; +} + +static GstFlowReturn +gst_dirac_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame) +{ + + return GST_FLOW_OK; +} diff --git a/gst/videoparsers/gstdiracparse.h b/gst/videoparsers/gstdiracparse.h new file mode 100644 index 0000000000..64a1b8123d --- /dev/null +++ b/gst/videoparsers/gstdiracparse.h @@ -0,0 +1,52 @@ +/* GStreamer + * Copyright (C) 2010 REAL_NAME + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef _GST_DIRAC_PARSE_H_ +#define _GST_DIRAC_PARSE_H_ + +#include +#include + +G_BEGIN_DECLS + +#define GST_TYPE_DIRAC_PARSE (gst_dirac_parse_get_type()) +#define GST_DIRAC_PARSE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_DIRAC_PARSE,GstDiracParse)) +#define GST_DIRAC_PARSE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_DIRAC_PARSE,GstDiracParseClass)) +#define GST_IS_DIRAC_PARSE(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_DIRAC_PARSE)) +#define GST_IS_DIRAC_PARSE_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_DIRAC_PARSE)) + +typedef struct _GstDiracParse GstDiracParse; +typedef struct _GstDiracParseClass GstDiracParseClass; + +struct _GstDiracParse +{ + GstBaseParse base_diracparse; + +}; + +struct _GstDiracParseClass +{ + GstBaseParseClass base_diracparse_class; +}; + +GType gst_dirac_parse_get_type (void); + +G_END_DECLS + +#endif diff --git a/gst/videoparsers/plugin.c b/gst/videoparsers/plugin.c index 463e417cb6..cfd8a48285 100644 --- a/gst/videoparsers/plugin.c +++ b/gst/videoparsers/plugin.c @@ -1,5 +1,6 @@ /* GStreamer video parsers * Copyright (C) 2011 Mark Nauwelaerts + * Copyright (C) 2009 Tim-Philipp Müller * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public @@ -23,6 +24,7 @@ #include "gsth263parse.h" #include "gsth264parse.h" +#include "gstdiracparse.h" static gboolean plugin_init (GstPlugin * plugin) @@ -33,6 +35,8 @@ plugin_init (GstPlugin * plugin) GST_RANK_NONE, GST_TYPE_H263_PARSE); ret = gst_element_register (plugin, "h264parse", GST_RANK_NONE, GST_TYPE_H264_PARSE); + ret = gst_element_register (plugin, "diracparse", + GST_RANK_NONE, GST_TYPE_DIRAC_PARSE); return ret; } From 0b95d97e63d581c49b54851f0c444c78a83080b4 Mon Sep 17 00:00:00 2001 From: David Schleef Date: Wed, 13 Oct 2010 16:12:02 -0700 Subject: [PATCH 423/448] tests: fix baseparse test --- tests/check/Makefile.am | 3 +++ tests/check/elements/parser.c | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/check/Makefile.am b/tests/check/Makefile.am index 7826883a0e..9de5de2919 100644 --- a/tests/check/Makefile.am +++ b/tests/check/Makefile.am @@ -233,6 +233,9 @@ elements_assrender_LDADD = $(GST_PLUGINS_BASE_LIBS) -lgstvideo-0.10 -lgstapp-0.1 # parser unit test convenience lib noinst_LTLIBRARIES = libparser.la libparser_la_SOURCES = elements/parser.c elements/parser.h +libparser_la_CFLAGS = \ + -I$(top_srcdir)/tests/check \ + $(GST_CHECK_CFLAGS) $(GST_OPTION_CFLAGS) elements_aacparse_LDADD = libparser.la $(LDADD) diff --git a/tests/check/elements/parser.c b/tests/check/elements/parser.c index b0b4c8212b..7596889917 100644 --- a/tests/check/elements/parser.c +++ b/tests/check/elements/parser.c @@ -24,7 +24,7 @@ */ #include -#include "parser.h" +#include "elements/parser.h" /* context state variables */ From f2cc779d6888576ca679859cd62e6edd17c602e5 Mon Sep 17 00:00:00 2001 From: David Schleef Date: Thu, 17 Feb 2011 13:22:28 -0800 Subject: [PATCH 424/448] baseparse: update documentation for API changes --- gst-libs/gst/baseparse/gstbaseparse.h | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/gst-libs/gst/baseparse/gstbaseparse.h b/gst-libs/gst/baseparse/gstbaseparse.h index 82ec5f6fb8..d0f43ee7c4 100644 --- a/gst-libs/gst/baseparse/gstbaseparse.h +++ b/gst-libs/gst/baseparse/gstbaseparse.h @@ -251,14 +251,6 @@ struct _GstBaseParse { * STREAM_LOCK held. * @convert: Optional. * Convert between formats. - * @find_frame: Optional. - * Finds a frame. Gets a position passed and should return - * TRUE and the offset in bytes where this position is. - * Will only be called in pull mode and the subclass can pull - * whatever it wants from upstream. If not implemented, - * the base class will implement it by calling - * @check_valid_frame and @parse_frame to find the wanted - * frame and build a seek table. * @event: Optional. * Event handler on the sink pad. This function should return * TRUE if the event was handled and can be dropped. @@ -266,13 +258,7 @@ struct _GstBaseParse { * Event handler on the source pad. Should return TRUE * if the event was handled and can be dropped. * - * @get_frame_overhead: Finds the metadata overhead for the given frame. This - * is used to enable more accurate bitrate computations. - * If NULL, the per-frame overhead is assumed to be 0. If - * this returns -1, it is assumed that this frame should - * be skipped in bitrate calculation. - * - * @pre_push_buffer: Optional. + * @pre_push_frame: Optional. * Called just prior to pushing a frame (after any pending * events have been sent) to give subclass a chance to perform * additional actions at this time (e.g. tag sending) or to From de968b6c7d2853d072a812c7d1d26cd2c0c3ed79 Mon Sep 17 00:00:00 2001 From: David Schleef Date: Thu, 17 Feb 2011 14:32:46 -0800 Subject: [PATCH 425/448] mpegtsdemux: Fix disting of headers --- gst/mpegtsdemux/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst/mpegtsdemux/Makefile.am b/gst/mpegtsdemux/Makefile.am index bb88bbdd85..d3d2c3ed53 100644 --- a/gst/mpegtsdemux/Makefile.am +++ b/gst/mpegtsdemux/Makefile.am @@ -22,6 +22,6 @@ noinst_HEADERS = \ gstmpegdesc.h \ mpegtsbase.h \ mpegtspacketizer.h \ - mpegtsparse.c \ + mpegtsparse.h \ tsdemux.h From b96cf817a07ae00618f86baeca736ad10f95c4a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Fri, 18 Feb 2011 12:39:08 +0000 Subject: [PATCH 426/448] videoparsers: fix build Add includes and link against new libgstbaseparse in the build tree. --- gst/videoparsers/Makefile.am | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/gst/videoparsers/Makefile.am b/gst/videoparsers/Makefile.am index a344117a71..f50969c1aa 100644 --- a/gst/videoparsers/Makefile.am +++ b/gst/videoparsers/Makefile.am @@ -4,8 +4,11 @@ libgsth263parse_la_SOURCES = plugin.c \ h263parse.c gsth263parse.c \ gsth264parse.c h264parse.c \ gstdiracparse.c dirac_parse.c -libgsth263parse_la_CFLAGS = $(GST_CFLAGS) -libgsth263parse_la_LIBADD = $(GST_BASE_LIBS) $(GST_LIBS) +libgsth263parse_la_CFLAGS = \ + $(GST_PLUGINS_BAD_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) +libgsth263parse_la_LIBADD = \ + $(top_builddir)/gst-libs/gst/baseparse/libgstbaseparse-$(GST_MAJORMINOR).la \ + $(GST_BASE_LIBS) $(GST_LIBS) libgsth263parse_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) libgsth263parse_la_LIBTOOLFLAGS = --tag=disable-static From 5ac1c96e84888939e18999f7accd3451fdf19220 Mon Sep 17 00:00:00 2001 From: Olivier Aubert Date: Fri, 18 Feb 2011 09:40:00 +0100 Subject: [PATCH 427/448] rsvgoverlay: allow negative values for x/y/width/height --- ext/rsvg/gstrsvgoverlay.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/ext/rsvg/gstrsvgoverlay.c b/ext/rsvg/gstrsvgoverlay.c index 6875c9d4eb..1cbd0990c5 100644 --- a/ext/rsvg/gstrsvgoverlay.c +++ b/ext/rsvg/gstrsvgoverlay.c @@ -481,37 +481,37 @@ gst_rsvg_overlay_class_init (GstRsvgOverlayClass * klass) g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_X, g_param_spec_int ("x", "x offset", - "Specify an x offset.", 0, G_MAXINT, 0, + "Specify an x offset.", -G_MAXINT, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_Y, g_param_spec_int ("y", "y offset", - "Specify a y offset.", 0, G_MAXINT, 0, + "Specify a y offset.", -G_MAXINT, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_X_RELATIVE, g_param_spec_float ("x-relative", "x relative offset", - "Specify an x offset relative to the display size.", 0, G_MAXFLOAT, 0, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + "Specify an x offset relative to the display size.", -G_MAXFLOAT, + G_MAXFLOAT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_Y_RELATIVE, g_param_spec_float ("y-relative", "y relative offset", - "Specify a y offset relative to the display size.", 0, G_MAXFLOAT, 0, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + "Specify a y offset relative to the display size.", -G_MAXFLOAT, + G_MAXFLOAT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_WIDTH, g_param_spec_int ("width", "width", - "Specify a width in pixels.", 0, G_MAXINT, 0, + "Specify a width in pixels.", -G_MAXINT, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_HEIGHT, g_param_spec_int ("height", "height", - "Specify a height in pixels.", 0, G_MAXINT, 0, + "Specify a height in pixels.", -G_MAXINT, G_MAXINT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_WIDTH_RELATIVE, g_param_spec_float ("width-relative", "relative width", - "Specify a width relative to the display size.", 0, G_MAXFLOAT, 0, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + "Specify a width relative to the display size.", -G_MAXFLOAT, + G_MAXFLOAT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); g_object_class_install_property (G_OBJECT_CLASS (klass), PROP_HEIGHT_RELATIVE, g_param_spec_float ("height-relative", "relative height", - "Specify a height relative to the display size.", 0, G_MAXFLOAT, 0, - G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + "Specify a height relative to the display size.", -G_MAXFLOAT, + G_MAXFLOAT, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); basetransform_class->set_caps = gst_rsvg_overlay_set_caps; basetransform_class->transform_ip = gst_rsvg_overlay_transform_ip; From 99d23b3905fa5c04f10fc8fa3abd334cc0cecaf8 Mon Sep 17 00:00:00 2001 From: Stefan Kost Date: Fri, 18 Feb 2011 15:00:05 +0200 Subject: [PATCH 428/448] indexing-example: use proper signal names --- tests/examples/indexing/indexmpeg.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/examples/indexing/indexmpeg.c b/tests/examples/indexing/indexmpeg.c index a670ad8af3..c7d4473263 100644 --- a/tests/examples/indexing/indexmpeg.c +++ b/tests/examples/indexing/indexmpeg.c @@ -91,7 +91,7 @@ setup_dynamic_linking (GstElement * pipeline, link->pipeline = pipeline; link->index = index; - g_signal_connect (G_OBJECT (element), "new_pad", G_CALLBACK (dynamic_link), + g_signal_connect (G_OBJECT (element), "new-pad", G_CALLBACK (dynamic_link), link); } @@ -225,7 +225,7 @@ main (gint argc, gchar * argv[]) index = gst_index_factory_make ("memindex"); if (index) { if (verbose) - g_signal_connect (G_OBJECT (index), "entry_added", + g_signal_connect (G_OBJECT (index), "entry-added", G_CALLBACK (entry_added), NULL); g_object_set (G_OBJECT (index), "resolver", 1, NULL); @@ -245,7 +245,7 @@ main (gint argc, gchar * argv[]) } /* setup some default info/error handlers */ - g_signal_connect (G_OBJECT (pipeline), "deep_notify", + g_signal_connect (G_OBJECT (pipeline), "deep-notify", G_CALLBACK (gst_element_default_deep_notify), NULL); g_signal_connect (G_OBJECT (pipeline), "error", G_CALLBACK (gst_element_default_error), NULL); From 81e52d5585b58febd2def49054a4d8cf10a48735 Mon Sep 17 00:00:00 2001 From: Stefan Kost Date: Fri, 18 Feb 2011 15:05:03 +0200 Subject: [PATCH 429/448] baseparse: use delta-unit flags instead of none --- gst-libs/gst/baseparse/gstbaseparse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst-libs/gst/baseparse/gstbaseparse.c b/gst-libs/gst/baseparse/gstbaseparse.c index 16a6a081c9..456eab88c8 100644 --- a/gst-libs/gst/baseparse/gstbaseparse.c +++ b/gst-libs/gst/baseparse/gstbaseparse.c @@ -1334,7 +1334,7 @@ gst_base_parse_add_index_entry (GstBaseParse * parse, guint64 offset, /* index might change on-the-fly, although that would be nutty app ... */ GST_OBJECT_LOCK (parse); gst_index_add_associationv (parse->priv->index, parse->priv->index_id, - (key) ? GST_ASSOCIATION_FLAG_KEY_UNIT : GST_ASSOCIATION_FLAG_NONE, + (key) ? GST_ASSOCIATION_FLAG_KEY_UNIT : GST_ASSOCIATION_FLAG_DELTA_UNIT, 2, (const GstIndexAssociation *) &associations); GST_OBJECT_UNLOCK (parse); From 7a7e76981698309da4e14fad92e07f01a301e914 Mon Sep 17 00:00:00 2001 From: Stefan Kost Date: Fri, 18 Feb 2011 15:05:31 +0200 Subject: [PATCH 430/448] baseparse: trim trailing whitespace --- gst-libs/gst/baseparse/gstbaseparse.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/gst-libs/gst/baseparse/gstbaseparse.c b/gst-libs/gst/baseparse/gstbaseparse.c index 456eab88c8..df7aed7dce 100644 --- a/gst-libs/gst/baseparse/gstbaseparse.c +++ b/gst-libs/gst/baseparse/gstbaseparse.c @@ -24,7 +24,7 @@ * @short_description: Base class for stream parsers * @see_also: #GstBaseTransform * - * This base class is for parser elements that process data and splits it + * This base class is for parser elements that process data and splits it * into separate audio/video/whatever frames. * * It provides for: @@ -58,7 +58,7 @@ * * * At least in this point subclass needs to tell the GstBaseParse class - * how big data chunks it wants to receive (min_frame_size). It can do + * how big data chunks it wants to receive (min_frame_size). It can do * this with @gst_base_parse_set_min_frame_size. * * @@ -71,7 +71,7 @@ * * Parsing phase * - * GstBaseParse gathers at least min_frame_size bytes of data either + * GstBaseParse gathers at least min_frame_size bytes of data either * by pulling it from upstream or collecting buffers into internal * #GstAdapter. * @@ -123,8 +123,8 @@ * * * Subclass is responsible for providing pad template caps for - * source and sink pads. The pads need to be named "sink" and "src". It also - * needs to set the fixed caps on srcpad, when the format is ensured (e.g. + * source and sink pads. The pads need to be named "sink" and "src". It also + * needs to set the fixed caps on srcpad, when the format is ensured (e.g. * when base class calls subclass' @set_sink_caps function). * * This base class uses GST_FORMAT_DEFAULT as a meaning of frames. So, @@ -637,7 +637,7 @@ gst_base_parse_reset (GstBaseParse * parse) * in order to find the following frame header. * * Default callback for check_valid_frame. - * + * * Returns: Always TRUE. */ static gboolean @@ -874,7 +874,7 @@ gst_base_parse_sink_eventfunc (GstBaseParse * parse, GstEvent * event) "start = %" GST_TIME_FORMAT ", stop = %" GST_TIME_FORMAT, GST_TIME_ARGS (seg_start), GST_TIME_ARGS (seg_stop)); } else if (format != GST_FORMAT_TIME) { - /* Unknown incoming segment format. Output a default open-ended + /* Unknown incoming segment format. Output a default open-ended * TIME segment */ gst_event_unref (event); event = gst_event_new_new_segment_full (update, rate, applied_rate, From 6e321d2d873e8c8b11c3d355c1e9bc430f6a2557 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Fri, 18 Feb 2011 15:17:17 +0000 Subject: [PATCH 431/448] mpegtspacketizer: fix log message printf format --- gst/mpegtsdemux/mpegtspacketizer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst/mpegtsdemux/mpegtspacketizer.c b/gst/mpegtsdemux/mpegtspacketizer.c index 34ecc2ac14..f27918a0e6 100644 --- a/gst/mpegtsdemux/mpegtspacketizer.c +++ b/gst/mpegtsdemux/mpegtspacketizer.c @@ -2177,7 +2177,7 @@ mpegts_try_discover_packet_size (MpegTSPacketizer2 * packetizer) packetizer->know_packet_size, packetizer->packet_size); /* flush to sync byte */ if (pos > 0) { - GST_DEBUG ("Flushing out %d bytes"); + GST_DEBUG ("Flushing out %d bytes", pos); gst_adapter_flush (packetizer->adapter, pos); packetizer->offset += pos; } else if (!packetizer->know_packet_size) { From 493082abd7f9d1867ec1753b598576b1cab7294d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Fri, 18 Feb 2011 15:24:54 +0000 Subject: [PATCH 432/448] videoparsers: change plugin filename from libgsth263parse* to libgstvideoparsersbad* Due to a registry bug you may need to manually remove your registry file to make the new plugin appear with >0 features. --- Makefile.am | 1 + gst/videoparsers/Makefile.am | 12 ++++++------ 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/Makefile.am b/Makefile.am index 46fbdf5c9e..aaa72137dc 100644 --- a/Makefile.am +++ b/Makefile.am @@ -54,6 +54,7 @@ CRUFT_FILES = \ $(top_builddir)/gst/selector/.libs/*.{so,dll,DLL,dylib} \ $(top_builddir)/gst/shapewipe/.libs/*.{so,dll,DLL,dylib} \ $(top_builddir)/gst/valve/.libs/*.{so,dll,DLL,dylib} \ + $(top_builddir)/gst/videoparsers/.libs/libgsth263parse* \ $(top_builddir)/sys/oss4/.libs/*.{so,dll,DLL,dylib} \ $(top_builddir)/tests/check/elements/autocolorspace \ $(top_builddir)/tests/check/elements/capssetter \ diff --git a/gst/videoparsers/Makefile.am b/gst/videoparsers/Makefile.am index f50969c1aa..028959d0f7 100644 --- a/gst/videoparsers/Makefile.am +++ b/gst/videoparsers/Makefile.am @@ -1,16 +1,16 @@ -plugin_LTLIBRARIES = libgsth263parse.la +plugin_LTLIBRARIES = libgstvideoparsersbad.la -libgsth263parse_la_SOURCES = plugin.c \ +libgstvideoparsersbad_la_SOURCES = plugin.c \ h263parse.c gsth263parse.c \ gsth264parse.c h264parse.c \ gstdiracparse.c dirac_parse.c -libgsth263parse_la_CFLAGS = \ +libgstvideoparsersbad_la_CFLAGS = \ $(GST_PLUGINS_BAD_CFLAGS) $(GST_BASE_CFLAGS) $(GST_CFLAGS) -libgsth263parse_la_LIBADD = \ +libgstvideoparsersbad_la_LIBADD = \ $(top_builddir)/gst-libs/gst/baseparse/libgstbaseparse-$(GST_MAJORMINOR).la \ $(GST_BASE_LIBS) $(GST_LIBS) -libgsth263parse_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) -libgsth263parse_la_LIBTOOLFLAGS = --tag=disable-static +libgstvideoparsersbad_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) +libgstvideoparsersbad_la_LIBTOOLFLAGS = --tag=disable-static noinst_HEADERS = gsth263parse.h h263parse.h \ gsth264parse.h h264parse.h \ From 5b90c31ca2eb27236cbe0dab3d8be60ad189d45e Mon Sep 17 00:00:00 2001 From: David Schleef Date: Sat, 19 Feb 2011 13:07:39 -0800 Subject: [PATCH 433/448] basevideocodec: remove parser in favor of baseparse --- ext/schroedinger/Makefile.am | 1 - ext/schroedinger/gstschro.c | 3 - ext/schroedinger/gstschroparse.c | 586 ----------------- gst-libs/gst/video/Makefile.am | 6 +- gst-libs/gst/video/gstbasevideoparse.c | 862 ------------------------- gst-libs/gst/video/gstbasevideoparse.h | 142 ---- 6 files changed, 2 insertions(+), 1598 deletions(-) delete mode 100644 ext/schroedinger/gstschroparse.c delete mode 100644 gst-libs/gst/video/gstbasevideoparse.c delete mode 100644 gst-libs/gst/video/gstbasevideoparse.h diff --git a/ext/schroedinger/Makefile.am b/ext/schroedinger/Makefile.am index fdedd67f06..66b2e1e2f5 100644 --- a/ext/schroedinger/Makefile.am +++ b/ext/schroedinger/Makefile.am @@ -8,7 +8,6 @@ libgstschro_la_SOURCES = \ gstschro.c \ gstschrodec.c \ gstschroenc.c \ - gstschroparse.c \ gstschroutils.c libgstschro_la_CFLAGS = \ $(GST_PLUGINS_BAD_CFLAGS) \ diff --git a/ext/schroedinger/gstschro.c b/ext/schroedinger/gstschro.c index 44d9226e62..c486473f95 100644 --- a/ext/schroedinger/gstschro.c +++ b/ext/schroedinger/gstschro.c @@ -26,7 +26,6 @@ GType gst_schro_enc_get_type (void); GType gst_schro_dec_get_type (void); -GType gst_schro_parse_get_type (void); GST_DEBUG_CATEGORY (schro_debug); #define GST_CAT_DEFAULT schro_debug @@ -39,8 +38,6 @@ plugin_init (GstPlugin * plugin) GST_DEBUG_CATEGORY_INIT (schro_debug, "schro", 0, "Schroedinger"); gst_element_register (plugin, "schrodec", GST_RANK_PRIMARY, gst_schro_dec_get_type ()); - gst_element_register (plugin, "schroparse", GST_RANK_NONE, - gst_schro_parse_get_type ()); gst_element_register (plugin, "schroenc", GST_RANK_PRIMARY, gst_schro_enc_get_type ()); diff --git a/ext/schroedinger/gstschroparse.c b/ext/schroedinger/gstschroparse.c deleted file mode 100644 index a734f2dc53..0000000000 --- a/ext/schroedinger/gstschroparse.c +++ /dev/null @@ -1,586 +0,0 @@ -/* Schrodinger - * Copyright (C) 2006 David Schleef - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include -#include -#include -#include -#include -#include -#include - -#include - - -GST_DEBUG_CATEGORY_EXTERN (schro_debug); -#define GST_CAT_DEFAULT schro_debug - -#define GST_TYPE_SCHRO_PARSE \ - (gst_schro_parse_get_type()) -#define GST_SCHRO_PARSE(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_SCHRO_PARSE,GstSchroParse)) -#define GST_SCHRO_PARSE_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_SCHRO_PARSE,GstSchroParseClass)) -#define GST_IS_SCHRO_PARSE(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_SCHRO_PARSE)) -#define GST_IS_SCHRO_PARSE_CLASS(obj) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_SCHRO_PARSE)) - -typedef struct _GstSchroParse GstSchroParse; -typedef struct _GstSchroParseClass GstSchroParseClass; - -typedef enum -{ - GST_SCHRO_PARSE_OUTPUT_OGG, - GST_SCHRO_PARSE_OUTPUT_QUICKTIME, - GST_SCHRO_PARSE_OUTPUT_AVI, - GST_SCHRO_PARSE_OUTPUT_MPEG_TS, - GST_SCHRO_PARSE_OUTPUT_MP4 -} GstSchroParseOutputType; - -struct _GstSchroParse -{ - GstBaseVideoParse base_video_parse; - - GstPad *sinkpad, *srcpad; - - GstSchroParseOutputType output_format; - - GstBuffer *seq_header_buffer; - - /* state */ - - - gboolean have_picture; - int buf_picture_number; - int seq_hdr_picture_number; - int picture_number; - - guint64 last_granulepos; - - int bytes_per_picture; -}; - -struct _GstSchroParseClass -{ - GstBaseVideoParseClass base_video_parse_class; -}; - -GType gst_schro_parse_get_type (void); - - -/* GstSchroParse signals and args */ -enum -{ - LAST_SIGNAL -}; - -enum -{ - ARG_0 -}; - -static gboolean gst_schro_parse_start (GstBaseVideoParse * base_video_parse); -static gboolean gst_schro_parse_stop (GstBaseVideoParse * base_video_parse); -static gboolean gst_schro_parse_reset (GstBaseVideoParse * base_video_parse); -static int gst_schro_parse_scan_for_sync (GstAdapter * adapter, - gboolean at_eos, int offset, int n); -static gboolean gst_schro_parse_parse_data (GstBaseVideoParse * - base_video_parse, gboolean at_eos); -static gboolean gst_schro_parse_shape_output (GstBaseVideoParse * - base_video_parse, GstVideoFrame * frame); -static GstCaps *gst_schro_parse_get_caps (GstBaseVideoParse * base_video_parse); - - - -static GstStaticPadTemplate gst_schro_parse_sink_template = -GST_STATIC_PAD_TEMPLATE ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - GST_STATIC_CAPS ("video/x-dirac") - ); - -static GstStaticPadTemplate gst_schro_parse_src_template = - GST_STATIC_PAD_TEMPLATE ("src", - GST_PAD_SRC, - GST_PAD_ALWAYS, - GST_STATIC_CAPS - ("video/x-dirac;video/x-qt-part;video/x-avi-part;video/x-mp4-part") - ); - -GST_BOILERPLATE (GstSchroParse, gst_schro_parse, GstBaseVideoParse, - GST_TYPE_BASE_VIDEO_PARSE); - -static void -gst_schro_parse_base_init (gpointer g_class) -{ - - GstElementClass *element_class = GST_ELEMENT_CLASS (g_class); - - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&gst_schro_parse_src_template)); - gst_element_class_add_pad_template (element_class, - gst_static_pad_template_get (&gst_schro_parse_sink_template)); - - gst_element_class_set_details_simple (element_class, "Dirac Parser", - "Codec/Parser/Video", - "Parse Dirac streams", "David Schleef "); -} - -static void -gst_schro_parse_class_init (GstSchroParseClass * klass) -{ - GstBaseVideoParseClass *base_video_parse_class; - - base_video_parse_class = GST_BASE_VIDEO_PARSE_CLASS (klass); - - base_video_parse_class->start = GST_DEBUG_FUNCPTR (gst_schro_parse_start); - base_video_parse_class->stop = GST_DEBUG_FUNCPTR (gst_schro_parse_stop); - base_video_parse_class->reset = GST_DEBUG_FUNCPTR (gst_schro_parse_reset); - base_video_parse_class->parse_data = - GST_DEBUG_FUNCPTR (gst_schro_parse_parse_data); - base_video_parse_class->shape_output = - GST_DEBUG_FUNCPTR (gst_schro_parse_shape_output); - base_video_parse_class->scan_for_sync = - GST_DEBUG_FUNCPTR (gst_schro_parse_scan_for_sync); - base_video_parse_class->get_caps = - GST_DEBUG_FUNCPTR (gst_schro_parse_get_caps); - -} - -static void -gst_schro_parse_init (GstSchroParse * schro_parse, GstSchroParseClass * klass) -{ - GstBaseVideoParse *base_video_parse = GST_BASE_VIDEO_PARSE (schro_parse); - - GST_DEBUG ("gst_schro_parse_init"); - - schro_parse->output_format = GST_SCHRO_PARSE_OUTPUT_OGG; - - base_video_parse->reorder_depth = 2; -} - -static gboolean -gst_schro_parse_reset (GstBaseVideoParse * base_video_parse) -{ - GST_DEBUG ("reset"); - - return TRUE; -} - -static gboolean -gst_schro_parse_start (GstBaseVideoParse * base_video_parse) -{ - GstSchroParse *schro_parse = GST_SCHRO_PARSE (base_video_parse); - GstCaps *caps; - GstStructure *structure; - - GST_DEBUG ("start"); - caps = - gst_pad_get_allowed_caps (GST_BASE_VIDEO_CODEC_SRC_PAD - (base_video_parse)); - - if (gst_caps_is_empty (caps)) { - gst_caps_unref (caps); - return FALSE; - } - - structure = gst_caps_get_structure (caps, 0); - - if (gst_structure_has_name (structure, "video/x-dirac")) { - schro_parse->output_format = GST_SCHRO_PARSE_OUTPUT_OGG; - } else if (gst_structure_has_name (structure, "video/x-qt-part")) { - schro_parse->output_format = GST_SCHRO_PARSE_OUTPUT_QUICKTIME; - } else if (gst_structure_has_name (structure, "video/x-avi-part")) { - schro_parse->output_format = GST_SCHRO_PARSE_OUTPUT_AVI; - } else if (gst_structure_has_name (structure, "video/x-mpegts-part")) { - schro_parse->output_format = GST_SCHRO_PARSE_OUTPUT_MPEG_TS; - } else if (gst_structure_has_name (structure, "video/x-mp4-part")) { - schro_parse->output_format = GST_SCHRO_PARSE_OUTPUT_MP4; - } else { - return FALSE; - } - - gst_caps_unref (caps); - return TRUE; -} - -static gboolean -gst_schro_parse_stop (GstBaseVideoParse * base_video_parse) -{ - return TRUE; -} - -static void -parse_sequence_header (GstSchroParse * schro_parse, guint8 * data, int size) -{ - SchroVideoFormat video_format; - int ret; - GstVideoState *state; - - GST_DEBUG ("parse_sequence_header size=%d", size); - - state = gst_base_video_parse_get_state (GST_BASE_VIDEO_PARSE (schro_parse)); - - schro_parse->seq_header_buffer = gst_buffer_new_and_alloc (size); - memcpy (GST_BUFFER_DATA (schro_parse->seq_header_buffer), data, size); - - ret = schro_parse_decode_sequence_header (data + 13, size - 13, - &video_format); - if (ret) { - state->fps_n = video_format.frame_rate_numerator; - state->fps_d = video_format.frame_rate_denominator; - GST_DEBUG ("Frame rate is %d/%d", state->fps_n, state->fps_d); - - state->width = video_format.width; - state->height = video_format.height; - GST_DEBUG ("Frame dimensions are %d x %d\n", state->width, state->height); - - state->clean_width = video_format.clean_width; - state->clean_height = video_format.clean_height; - state->clean_offset_left = video_format.left_offset; - state->clean_offset_top = video_format.top_offset; - - state->par_n = video_format.aspect_ratio_numerator; - state->par_d = video_format.aspect_ratio_denominator; - GST_DEBUG ("Pixel aspect ratio is %d/%d", state->par_n, state->par_d); - - gst_base_video_parse_set_state (GST_BASE_VIDEO_PARSE (schro_parse), state); - } else { - GST_WARNING ("Failed to get frame rate from sequence header"); - } - -} - -static int -gst_schro_parse_scan_for_sync (GstAdapter * adapter, gboolean at_eos, - int offset, int n) -{ - int n_available = gst_adapter_available (adapter) - offset; - - if (n_available < 4) { - if (at_eos) { - return n_available; - } else { - return 0; - } - } - - n_available -= 3; - - return gst_adapter_masked_scan_uint32 (adapter, 0xffffffff, 0x42424344, - offset, MIN (n, n_available - 3)); -} - -static GstFlowReturn -gst_schro_parse_parse_data (GstBaseVideoParse * base_video_parse, - gboolean at_eos) -{ - GstSchroParse *schro_parse; - unsigned char header[SCHRO_PARSE_HEADER_SIZE]; - int next; - int prev; - int parse_code; - - GST_DEBUG ("parse_data"); - - schro_parse = GST_SCHRO_PARSE (base_video_parse); - - if (gst_adapter_available (base_video_parse->input_adapter) < - SCHRO_PARSE_HEADER_SIZE) { - return GST_BASE_VIDEO_PARSE_FLOW_NEED_DATA; - } - - GST_DEBUG ("available %d", - gst_adapter_available (base_video_parse->input_adapter)); - - gst_adapter_copy (base_video_parse->input_adapter, header, 0, - SCHRO_PARSE_HEADER_SIZE); - - parse_code = header[4]; - next = GST_READ_UINT32_BE (header + 5); - prev = GST_READ_UINT32_BE (header + 9); - - GST_DEBUG ("%08x %02x %08x %08x", - GST_READ_UINT32_BE (header), parse_code, next, prev); - - if (memcmp (header, "BBCD", 4) != 0 || - (next & 0xf0000000) || (prev & 0xf0000000)) { - gst_base_video_parse_lost_sync (base_video_parse); - return GST_BASE_VIDEO_PARSE_FLOW_NEED_DATA; - } - - if (SCHRO_PARSE_CODE_IS_END_OF_SEQUENCE (parse_code)) { - GstVideoFrame *frame; - - if (next != 0 && next != SCHRO_PARSE_HEADER_SIZE) { - GST_WARNING ("next is not 0 or 13 in EOS packet (%d)", next); - } - - gst_base_video_parse_add_to_frame (base_video_parse, - SCHRO_PARSE_HEADER_SIZE); - - frame = gst_base_video_parse_get_frame (base_video_parse); - frame->is_eos = TRUE; - - SCHRO_DEBUG ("eos"); - - return gst_base_video_parse_finish_frame (base_video_parse); - } - - if (gst_adapter_available (base_video_parse->input_adapter) < next) { - return GST_BASE_VIDEO_PARSE_FLOW_NEED_DATA; - } - - if (SCHRO_PARSE_CODE_IS_SEQ_HEADER (parse_code)) { - guint8 *data; - - data = g_malloc (next); - - gst_adapter_copy (base_video_parse->input_adapter, data, 0, next); - parse_sequence_header (schro_parse, data, next); - - base_video_parse->current_frame->is_sync_point = TRUE; - - g_free (data); - } - - if (schro_parse->seq_header_buffer == NULL) { - gst_adapter_flush (base_video_parse->input_adapter, next); - return GST_FLOW_OK; - } - - if (SCHRO_PARSE_CODE_IS_PICTURE (parse_code)) { - GstVideoFrame *frame; - guint8 tmp[4]; - - frame = gst_base_video_parse_get_frame (base_video_parse); - -#if 0 - if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (buf))) { - frame->presentation_timestamp = GST_BUFFER_TIMESTAMP (buf); - } -#endif - - gst_adapter_copy (base_video_parse->input_adapter, tmp, - SCHRO_PARSE_HEADER_SIZE, 4); - - frame->presentation_frame_number = GST_READ_UINT32_BE (tmp); - - gst_base_video_parse_add_to_frame (base_video_parse, next); - - return gst_base_video_parse_finish_frame (base_video_parse); - } else { - gst_base_video_parse_add_to_frame (base_video_parse, next); - } - - return GST_FLOW_OK; -} - -static GstFlowReturn -gst_schro_parse_shape_output_ogg (GstBaseVideoParse * base_video_parse, - GstVideoFrame * frame) -{ - GstSchroParse *schro_parse; - int dpn; - int delay; - int dist; - int pt; - int dt; - guint64 granulepos_hi; - guint64 granulepos_low; - GstBuffer *buf = frame->src_buffer; - - schro_parse = GST_SCHRO_PARSE (base_video_parse); - - dpn = frame->decode_frame_number; - - pt = frame->presentation_frame_number * 2; - dt = frame->decode_frame_number * 2; - delay = pt - dt; - dist = frame->distance_from_sync; - - GST_DEBUG ("sys %d dpn %d pt %d dt %d delay %d dist %d", - (int) frame->system_frame_number, - (int) frame->decode_frame_number, pt, dt, delay, dist); - - granulepos_hi = (((guint64) pt - delay) << 9) | ((dist >> 8)); - granulepos_low = (delay << 9) | (dist & 0xff); - GST_DEBUG ("granulepos %" G_GINT64_FORMAT ":%" G_GINT64_FORMAT, granulepos_hi, - granulepos_low); - - if (frame->is_eos) { - GST_BUFFER_OFFSET_END (buf) = schro_parse->last_granulepos; - } else { - schro_parse->last_granulepos = (granulepos_hi << 22) | (granulepos_low); - GST_BUFFER_OFFSET_END (buf) = schro_parse->last_granulepos; - } - - return gst_base_video_parse_push (base_video_parse, buf); -} - -static GstFlowReturn -gst_schro_parse_shape_output_quicktime (GstBaseVideoParse * base_video_parse, - GstVideoFrame * frame) -{ - GstBuffer *buf = frame->src_buffer; - const GstVideoState *state; - - state = gst_base_video_parse_get_state (base_video_parse); - - GST_BUFFER_OFFSET_END (buf) = gst_video_state_get_timestamp (state, - &base_video_parse->segment, frame->system_frame_number); - - if (frame->is_sync_point && - frame->presentation_frame_number == frame->system_frame_number) { - GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DELTA_UNIT); - GST_DEBUG ("sync point"); - } else { - GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT); - } - - return gst_base_video_parse_push (base_video_parse, buf); -} - -static GstFlowReturn -gst_schro_parse_shape_output_mpeg_ts (GstBaseVideoParse * base_video_parse, - GstVideoFrame * frame) -{ - GstBuffer *buf = frame->src_buffer; - - return gst_base_video_parse_push (base_video_parse, buf); -} - -static GstFlowReturn -gst_schro_parse_shape_output (GstBaseVideoParse * base_video_parse, - GstVideoFrame * frame) -{ - GstSchroParse *schro_parse; - - schro_parse = GST_SCHRO_PARSE (base_video_parse); - - switch (schro_parse->output_format) { - case GST_SCHRO_PARSE_OUTPUT_OGG: - return gst_schro_parse_shape_output_ogg (base_video_parse, frame); - case GST_SCHRO_PARSE_OUTPUT_QUICKTIME: - return gst_schro_parse_shape_output_quicktime (base_video_parse, frame); - case GST_SCHRO_PARSE_OUTPUT_MPEG_TS: - return gst_schro_parse_shape_output_mpeg_ts (base_video_parse, frame); - default: - break; - } - - return GST_FLOW_ERROR; -} - -static GstCaps * -gst_schro_parse_get_caps (GstBaseVideoParse * base_video_parse) -{ - GstCaps *caps; - GstVideoState *state; - GstSchroParse *schro_parse; - - schro_parse = GST_SCHRO_PARSE (base_video_parse); - - state = gst_base_video_parse_get_state (base_video_parse); - - if (schro_parse->output_format == GST_SCHRO_PARSE_OUTPUT_OGG) { - caps = gst_caps_new_simple ("video/x-dirac", - "width", G_TYPE_INT, state->width, - "height", G_TYPE_INT, state->height, - "framerate", GST_TYPE_FRACTION, state->fps_n, - state->fps_d, - "pixel-aspect-ratio", GST_TYPE_FRACTION, state->par_n, - state->par_d, NULL); - - GST_BUFFER_FLAG_SET (schro_parse->seq_header_buffer, - GST_BUFFER_FLAG_IN_CAPS); - - { - GValue array = { 0 }; - GValue value = { 0 }; - GstBuffer *buf; - int size; - - g_value_init (&array, GST_TYPE_ARRAY); - g_value_init (&value, GST_TYPE_BUFFER); - size = GST_BUFFER_SIZE (schro_parse->seq_header_buffer); - buf = gst_buffer_new_and_alloc (size + SCHRO_PARSE_HEADER_SIZE); - memcpy (GST_BUFFER_DATA (buf), - GST_BUFFER_DATA (schro_parse->seq_header_buffer), size); - GST_WRITE_UINT32_BE (GST_BUFFER_DATA (buf) + size + 0, 0x42424344); - GST_WRITE_UINT8 (GST_BUFFER_DATA (buf) + size + 4, - SCHRO_PARSE_CODE_END_OF_SEQUENCE); - GST_WRITE_UINT32_BE (GST_BUFFER_DATA (buf) + size + 5, 0); - GST_WRITE_UINT32_BE (GST_BUFFER_DATA (buf) + size + 9, size); - gst_value_set_buffer (&value, buf); - gst_buffer_unref (buf); - gst_value_array_append_value (&array, &value); - gst_structure_set_value (gst_caps_get_structure (caps, 0), - "streamheader", &array); - g_value_unset (&value); - g_value_unset (&array); - } - } else if (schro_parse->output_format == GST_SCHRO_PARSE_OUTPUT_QUICKTIME) { - caps = gst_caps_new_simple ("video/x-qt-part", - "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('d', 'r', 'a', 'c'), - "width", G_TYPE_INT, state->width, - "height", G_TYPE_INT, state->height, - "framerate", GST_TYPE_FRACTION, state->fps_n, - state->fps_d, - "pixel-aspect-ratio", GST_TYPE_FRACTION, state->par_n, - state->par_d, NULL); - } else if (schro_parse->output_format == GST_SCHRO_PARSE_OUTPUT_AVI) { - caps = gst_caps_new_simple ("video/x-avi-part", - "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('d', 'r', 'a', 'c'), - "width", G_TYPE_INT, state->width, - "height", G_TYPE_INT, state->height, - "framerate", GST_TYPE_FRACTION, state->fps_n, - state->fps_d, - "pixel-aspect-ratio", GST_TYPE_FRACTION, state->par_n, - state->par_d, NULL); - } else if (schro_parse->output_format == GST_SCHRO_PARSE_OUTPUT_MPEG_TS) { - caps = gst_caps_new_simple ("video/x-mpegts-part", - "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('d', 'r', 'a', 'c'), - "width", G_TYPE_INT, state->width, - "height", G_TYPE_INT, state->height, - "framerate", GST_TYPE_FRACTION, state->fps_n, - state->fps_d, - "pixel-aspect-ratio", GST_TYPE_FRACTION, state->par_n, - state->par_d, NULL); - } else if (schro_parse->output_format == GST_SCHRO_PARSE_OUTPUT_MP4) { - caps = gst_caps_new_simple ("video/x-mp4-part", - "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('d', 'r', 'a', 'c'), - "width", G_TYPE_INT, state->width, - "height", G_TYPE_INT, state->height, - "framerate", GST_TYPE_FRACTION, state->fps_n, - state->fps_d, - "pixel-aspect-ratio", GST_TYPE_FRACTION, state->par_n, - state->par_d, NULL); - } else { - g_assert_not_reached (); - caps = NULL; - } - - return caps; -} diff --git a/gst-libs/gst/video/Makefile.am b/gst-libs/gst/video/Makefile.am index 5072f1df68..a0c4026ec2 100644 --- a/gst-libs/gst/video/Makefile.am +++ b/gst-libs/gst/video/Makefile.am @@ -7,16 +7,14 @@ libgstbasevideo_@GST_MAJORMINOR@_la_SOURCES = \ gstbasevideoutils.c \ gstbasevideocodec.c \ gstbasevideodecoder.c \ - gstbasevideoencoder.c \ - gstbasevideoparse.c + gstbasevideoencoder.c libgstbasevideo_@GST_MAJORMINOR@includedir = $(includedir)/gstreamer-@GST_MAJORMINOR@/gst/video libgstbasevideo_@GST_MAJORMINOR@include_HEADERS = \ gstbasevideoutils.h \ gstbasevideocodec.h \ gstbasevideodecoder.h \ - gstbasevideoencoder.h \ - gstbasevideoparse.h + gstbasevideoencoder.h libgstbasevideo_@GST_MAJORMINOR@_la_CFLAGS = \ $(GST_PLUGINS_BAD_CFLAGS) \ diff --git a/gst-libs/gst/video/gstbasevideoparse.c b/gst-libs/gst/video/gstbasevideoparse.c deleted file mode 100644 index e200838a05..0000000000 --- a/gst-libs/gst/video/gstbasevideoparse.c +++ /dev/null @@ -1,862 +0,0 @@ -/* Schrodinger - * Copyright (C) 2006 David Schleef - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifdef HAVE_CONFIG_H -#include "config.h" -#endif - -#include "gstbasevideoparse.h" - -#include -#include - -GST_DEBUG_CATEGORY (basevideoparse_debug); -#define GST_CAT_DEFAULT basevideoparse_debug - - - -/* GstBaseVideoParse signals and args */ -enum -{ - LAST_SIGNAL -}; - -enum -{ - ARG_0 -}; - -static void gst_base_video_parse_finalize (GObject * object); - -static const GstQueryType *gst_base_video_parse_get_query_types (GstPad * pad); -static gboolean gst_base_video_parse_src_query (GstPad * pad, GstQuery * query); -static gboolean gst_base_video_parse_sink_query (GstPad * pad, - GstQuery * query); -static gboolean gst_base_video_parse_src_event (GstPad * pad, GstEvent * event); -static gboolean gst_base_video_parse_sink_event (GstPad * pad, - GstEvent * event); -static GstStateChangeReturn gst_base_video_parse_change_state (GstElement * - element, GstStateChange transition); -static GstFlowReturn gst_base_video_parse_push_all (GstBaseVideoParse * - base_video_parse, gboolean at_eos); -static GstFlowReturn gst_base_video_parse_chain (GstPad * pad, GstBuffer * buf); -static void gst_base_video_parse_free_frame (GstVideoFrame * frame); -static GstVideoFrame *gst_base_video_parse_new_frame (GstBaseVideoParse * - base_video_parse); - - -GST_BOILERPLATE (GstBaseVideoParse, gst_base_video_parse, - GstBaseVideoCodec, GST_TYPE_BASE_VIDEO_CODEC); - -static void -gst_base_video_parse_base_init (gpointer g_class) -{ - GST_DEBUG_CATEGORY_INIT (basevideoparse_debug, "basevideoparse", 0, - "Base Video Parse"); - - -} - -static void -gst_base_video_parse_class_init (GstBaseVideoParseClass * klass) -{ - GObjectClass *gobject_class; - GstElementClass *element_class; - - gobject_class = G_OBJECT_CLASS (klass); - element_class = GST_ELEMENT_CLASS (klass); - - gobject_class->finalize = gst_base_video_parse_finalize; - - element_class->change_state = gst_base_video_parse_change_state; -} - -static void -gst_base_video_parse_init (GstBaseVideoParse * base_video_parse, - GstBaseVideoParseClass * klass) -{ - GstPad *pad; - - GST_DEBUG ("gst_base_video_parse_init"); - - pad = GST_BASE_VIDEO_CODEC_SINK_PAD (base_video_parse); - - gst_pad_set_chain_function (pad, gst_base_video_parse_chain); - gst_pad_set_query_function (pad, gst_base_video_parse_sink_query); - gst_pad_set_event_function (pad, gst_base_video_parse_sink_event); - - pad = GST_BASE_VIDEO_CODEC_SRC_PAD (base_video_parse); - - gst_pad_set_query_type_function (pad, gst_base_video_parse_get_query_types); - gst_pad_set_query_function (pad, gst_base_video_parse_src_query); - gst_pad_set_event_function (pad, gst_base_video_parse_src_event); - - base_video_parse->input_adapter = gst_adapter_new (); - base_video_parse->output_adapter = gst_adapter_new (); - - base_video_parse->reorder_depth = 1; - - base_video_parse->current_frame = - gst_base_video_parse_new_frame (base_video_parse); -} - -static void -gst_base_video_parse_reset (GstBaseVideoParse * base_video_parse) -{ - GST_DEBUG ("reset"); - - base_video_parse->discont = TRUE; - base_video_parse->have_sync = FALSE; - - base_video_parse->system_frame_number = 0; - base_video_parse->presentation_frame_number = 0; - - if (base_video_parse->caps) { - gst_caps_unref (base_video_parse->caps); - base_video_parse->caps = NULL; - } - - gst_segment_init (&base_video_parse->segment, GST_FORMAT_TIME); - gst_adapter_clear (base_video_parse->input_adapter); - gst_adapter_clear (base_video_parse->output_adapter); - - if (base_video_parse->current_frame) { - gst_base_video_parse_free_frame (base_video_parse->current_frame); - } - base_video_parse->current_frame = - gst_base_video_parse_new_frame (base_video_parse); - -} - -static void -gst_base_video_parse_finalize (GObject * object) -{ - GstBaseVideoParse *base_video_parse; - - g_return_if_fail (GST_IS_BASE_VIDEO_PARSE (object)); - base_video_parse = GST_BASE_VIDEO_PARSE (object); - - if (base_video_parse->input_adapter) { - g_object_unref (base_video_parse->input_adapter); - } - if (base_video_parse->output_adapter) { - g_object_unref (base_video_parse->output_adapter); - } - - G_OBJECT_CLASS (parent_class)->finalize (object); -} - -static const GstQueryType * -gst_base_video_parse_get_query_types (GstPad * pad) -{ - static const GstQueryType query_types[] = { - GST_QUERY_POSITION, - GST_QUERY_DURATION, - GST_QUERY_CONVERT, - 0 - }; - - return query_types; -} - -#if 0 -static gboolean -gst_base_video_parse_src_convert (GstPad * pad, - GstFormat src_format, gint64 src_value, - GstFormat * dest_format, gint64 * dest_value) -{ - gboolean res; - GstBaseVideoParse *dec; - - if (src_format == *dest_format) { - *dest_value = src_value; - return TRUE; - } - - dec = GST_BASE_VIDEO_PARSE (gst_pad_get_parent (pad)); - - if (src_format == GST_FORMAT_DEFAULT && *dest_format == GST_FORMAT_TIME) { - if (dec->fps_d != 0) { - *dest_value = gst_util_uint64_scale (granulepos_to_frame (src_value), - dec->fps_d * GST_SECOND, dec->fps_n); - res = TRUE; - } else { - res = FALSE; - } - } else { - GST_WARNING ("unhandled conversion from %d to %d", src_format, - *dest_format); - res = FALSE; - } - - gst_object_unref (dec); - - return res; -} - -static gboolean -gst_base_video_parse_sink_convert (GstPad * pad, - GstFormat src_format, gint64 src_value, - GstFormat * dest_format, gint64 * dest_value) -{ - gboolean res = TRUE; - GstBaseVideoParse *dec; - - if (src_format == *dest_format) { - *dest_value = src_value; - return TRUE; - } - - dec = GST_BASE_VIDEO_PARSE (gst_pad_get_parent (pad)); - - /* FIXME: check if we are in a decoding state */ - - switch (src_format) { - case GST_FORMAT_DEFAULT: - switch (*dest_format) { - case GST_FORMAT_TIME: - *dest_value = gst_util_uint64_scale (src_value, - dec->fps_d * GST_SECOND, dec->fps_n); - break; - default: - res = FALSE; - } - break; - case GST_FORMAT_TIME: - switch (*dest_format) { - case GST_FORMAT_DEFAULT: - { - *dest_value = gst_util_uint64_scale (src_value, - dec->fps_n, dec->fps_d * GST_SECOND); - break; - } - default: - res = FALSE; - break; - } - break; - default: - res = FALSE; - break; - } - - gst_object_unref (dec); - - return res; -} -#endif - -static gboolean -gst_base_video_parse_src_query (GstPad * pad, GstQuery * query) -{ - GstBaseVideoParse *base_parse; - gboolean res = FALSE; - - base_parse = GST_BASE_VIDEO_PARSE (gst_pad_get_parent (pad)); - - switch (GST_QUERY_TYPE (query)) { - case GST_QUERY_POSITION: - { - GstFormat format; - gint64 time; - gint64 value; - - gst_query_parse_position (query, &format, NULL); - - time = gst_util_uint64_scale (base_parse->presentation_frame_number, - base_parse->state.fps_n, base_parse->state.fps_d); - time += base_parse->segment.time; - GST_DEBUG ("query position %" GST_TIME_FORMAT, GST_TIME_ARGS (time)); - res = gst_base_video_encoded_video_convert (&base_parse->state, - GST_FORMAT_TIME, time, &format, &value); - if (!res) - goto error; - - gst_query_set_position (query, format, value); - break; - } - case GST_QUERY_DURATION: - res = - gst_pad_query (GST_PAD_PEER (GST_BASE_VIDEO_CODEC_SINK_PAD - (base_parse)), query); - if (!res) - goto error; - break; - case GST_QUERY_CONVERT: - { - GstFormat src_fmt, dest_fmt; - gint64 src_val, dest_val; - - GST_WARNING ("query convert"); - - gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val); - res = gst_base_video_encoded_video_convert (&base_parse->state, - src_fmt, src_val, &dest_fmt, &dest_val); - if (!res) - goto error; - gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val); - break; - } - default: - res = gst_pad_query_default (pad, query); - break; - } -done: - gst_object_unref (base_parse); - - return res; -error: - GST_DEBUG_OBJECT (base_parse, "query failed"); - goto done; -} - -static gboolean -gst_base_video_parse_sink_query (GstPad * pad, GstQuery * query) -{ - GstBaseVideoParse *base_video_parse; - gboolean res = FALSE; - - base_video_parse = GST_BASE_VIDEO_PARSE (gst_pad_get_parent (pad)); - - switch (GST_QUERY_TYPE (query)) { - case GST_QUERY_CONVERT: - { - GstFormat src_fmt, dest_fmt; - gint64 src_val, dest_val; - - gst_query_parse_convert (query, &src_fmt, &src_val, &dest_fmt, &dest_val); - res = gst_base_video_encoded_video_convert (&base_video_parse->state, - src_fmt, src_val, &dest_fmt, &dest_val); - if (!res) - goto error; - gst_query_set_convert (query, src_fmt, src_val, dest_fmt, dest_val); - break; - } - default: - res = gst_pad_query_default (pad, query); - break; - } -done: - gst_object_unref (base_video_parse); - - return res; -error: - GST_DEBUG_OBJECT (base_video_parse, "query failed"); - goto done; -} - -static gboolean -gst_base_video_parse_src_event (GstPad * pad, GstEvent * event) -{ - GstBaseVideoParse *base_video_parse; - gboolean res = FALSE; - - base_video_parse = GST_BASE_VIDEO_PARSE (gst_pad_get_parent (pad)); - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_SEEK: - { - GstFormat format, tformat; - gdouble rate; - GstEvent *real_seek; - GstSeekFlags flags; - GstSeekType cur_type, stop_type; - gint64 cur, stop; - gint64 tcur, tstop; - - gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, - &cur, &stop_type, &stop); - gst_event_unref (event); - - tformat = GST_FORMAT_TIME; - res = gst_base_video_encoded_video_convert (&base_video_parse->state, - format, cur, &tformat, &tcur); - if (!res) - goto convert_error; - res = gst_base_video_encoded_video_convert (&base_video_parse->state, - format, stop, &tformat, &tstop); - if (!res) - goto convert_error; - - real_seek = gst_event_new_seek (rate, GST_FORMAT_TIME, - flags, cur_type, tcur, stop_type, tstop); - - res = - gst_pad_push_event (GST_BASE_VIDEO_CODEC_SINK_PAD (base_video_parse), - real_seek); - - break; - } -#if 0 - case GST_EVENT_QOS: - { - gdouble proportion; - GstClockTimeDiff diff; - GstClockTime timestamp; - - gst_event_parse_qos (event, &proportion, &diff, ×tamp); - - GST_OBJECT_LOCK (base_video_parse); - base_video_parse->proportion = proportion; - base_video_parse->earliest_time = timestamp + diff; - GST_OBJECT_UNLOCK (base_video_parse); - - GST_DEBUG_OBJECT (base_video_parse, - "got QoS %" GST_TIME_FORMAT ", %" G_GINT64_FORMAT, - GST_TIME_ARGS (timestamp), diff); - - res = gst_pad_push_event (base_video_parse->sinkpad, event); - break; - } -#endif - default: - res = - gst_pad_push_event (GST_BASE_VIDEO_CODEC_SINK_PAD (base_video_parse), - event); - break; - } -done: - gst_object_unref (base_video_parse); - return res; - -convert_error: - GST_DEBUG_OBJECT (base_video_parse, "could not convert format"); - goto done; -} - -static gboolean -gst_base_video_parse_sink_event (GstPad * pad, GstEvent * event) -{ - GstBaseVideoParse *base_video_parse; - gboolean ret = FALSE; - - base_video_parse = GST_BASE_VIDEO_PARSE (gst_pad_get_parent (pad)); - - switch (GST_EVENT_TYPE (event)) { - case GST_EVENT_FLUSH_START: - ret = - gst_pad_push_event (GST_BASE_VIDEO_CODEC_SRC_PAD (base_video_parse), - event); - break; - case GST_EVENT_FLUSH_STOP: - gst_base_video_parse_reset (base_video_parse); - ret = - gst_pad_push_event (GST_BASE_VIDEO_CODEC_SRC_PAD (base_video_parse), - event); - break; - case GST_EVENT_EOS: - if (gst_base_video_parse_push_all (base_video_parse, - FALSE) == GST_FLOW_ERROR) { - gst_event_unref (event); - return FALSE; - } - - ret = - gst_pad_push_event (GST_BASE_VIDEO_CODEC_SRC_PAD (base_video_parse), - event); - break; - case GST_EVENT_NEWSEGMENT: - { - gboolean update; - GstFormat format; - gdouble rate; - gint64 start, stop, time; - - gst_event_parse_new_segment (event, &update, &rate, &format, &start, - &stop, &time); - - if (format != GST_FORMAT_TIME) - goto newseg_wrong_format; - - if (rate <= 0.0) - goto newseg_wrong_rate; - - GST_DEBUG ("newsegment %" GST_TIME_FORMAT " %" GST_TIME_FORMAT, - GST_TIME_ARGS (start), GST_TIME_ARGS (time)); - gst_segment_set_newsegment (&base_video_parse->segment, update, - rate, format, start, stop, time); - - ret = - gst_pad_push_event (GST_BASE_VIDEO_CODEC_SRC_PAD (base_video_parse), - event); - break; - } - default: - ret = - gst_pad_push_event (GST_BASE_VIDEO_CODEC_SRC_PAD (base_video_parse), - event); - break; - } -done: - gst_object_unref (base_video_parse); - return ret; - -newseg_wrong_format: - GST_DEBUG_OBJECT (base_video_parse, "received non TIME newsegment"); - gst_event_unref (event); - goto done; - -newseg_wrong_rate: - GST_DEBUG_OBJECT (base_video_parse, "negative rates not supported"); - gst_event_unref (event); - goto done; -} - - -static GstStateChangeReturn -gst_base_video_parse_change_state (GstElement * element, - GstStateChange transition) -{ - GstBaseVideoParse *base_parse = GST_BASE_VIDEO_PARSE (element); - GstStateChangeReturn ret; - - switch (transition) { - case GST_STATE_CHANGE_NULL_TO_READY: - break; - case GST_STATE_CHANGE_READY_TO_PAUSED: - gst_base_video_parse_reset (base_parse); - break; - case GST_STATE_CHANGE_PAUSED_TO_PLAYING: - break; - default: - break; - } - - ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); - - switch (transition) { - case GST_STATE_CHANGE_PLAYING_TO_PAUSED: - break; - case GST_STATE_CHANGE_PAUSED_TO_READY: - gst_base_video_parse_reset (base_parse); - break; - case GST_STATE_CHANGE_READY_TO_NULL: - break; - default: - break; - } - - return ret; -} - -static guint64 -gst_base_video_parse_get_timestamp (GstBaseVideoParse * base_video_parse, - int picture_number) -{ - if (picture_number < 0) { - return base_video_parse->timestamp_offset - - (gint64) gst_util_uint64_scale (-picture_number, - base_video_parse->state.fps_d * GST_SECOND, - base_video_parse->state.fps_n); - } else { - return base_video_parse->timestamp_offset + - gst_util_uint64_scale (picture_number, - base_video_parse->state.fps_d * GST_SECOND, - base_video_parse->state.fps_n); - } -} - -static GstFlowReturn -gst_base_video_parse_push_all (GstBaseVideoParse * base_video_parse, - gboolean at_eos) -{ - GstFlowReturn ret = GST_FLOW_OK; - - /* FIXME do stuff */ - - return ret; -} - -static GstFlowReturn -gst_base_video_parse_chain (GstPad * pad, GstBuffer * buf) -{ - GstBaseVideoParse *base_video_parse; - GstBaseVideoParseClass *klass; - GstFlowReturn ret; - - GST_DEBUG ("chain with %d bytes", GST_BUFFER_SIZE (buf)); - - base_video_parse = GST_BASE_VIDEO_PARSE (GST_PAD_PARENT (pad)); - klass = GST_BASE_VIDEO_PARSE_GET_CLASS (base_video_parse); - - if (!base_video_parse->started) { - klass->start (base_video_parse); - base_video_parse->started = TRUE; - } - - if (G_UNLIKELY (GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DISCONT))) { - GST_DEBUG_OBJECT (base_video_parse, "received DISCONT buffer"); - gst_base_video_parse_reset (base_video_parse); - base_video_parse->discont = TRUE; - base_video_parse->have_sync = FALSE; - } - - if (GST_BUFFER_TIMESTAMP (buf) != GST_CLOCK_TIME_NONE) { - base_video_parse->last_timestamp = GST_BUFFER_TIMESTAMP (buf); - } - gst_adapter_push (base_video_parse->input_adapter, buf); - - if (!base_video_parse->have_sync) { - int n, m; - - GST_DEBUG ("no sync, scanning"); - - n = gst_adapter_available (base_video_parse->input_adapter); - m = klass->scan_for_sync (base_video_parse->input_adapter, FALSE, 0, n); - - gst_adapter_flush (base_video_parse->input_adapter, m); - - if (m < n) { - GST_DEBUG ("found possible sync after %d bytes (of %d)", m, n); - - /* this is only "maybe" sync */ - base_video_parse->have_sync = TRUE; - } - - if (!base_video_parse->have_sync) { - return GST_FLOW_OK; - } - } - - /* FIXME check klass->parse_data */ - - do { - ret = klass->parse_data (base_video_parse, FALSE); - } while (ret == GST_FLOW_OK); - - if (ret == GST_BASE_VIDEO_PARSE_FLOW_NEED_DATA) { - return GST_FLOW_OK; - } - return ret; -} - -GstVideoState * -gst_base_video_parse_get_state (GstBaseVideoParse * base_video_parse) -{ - return &base_video_parse->state; -} - -void -gst_base_video_parse_set_state (GstBaseVideoParse * base_video_parse, - GstVideoState * state) -{ - GST_DEBUG ("set_state"); - - memcpy (&base_video_parse->state, state, sizeof (GstVideoState)); - - /* FIXME set caps */ - -} - - -gboolean -gst_base_video_parse_set_src_caps (GstBaseVideoParse * base_video_parse, - GstCaps * caps) -{ - g_return_val_if_fail (GST_IS_BASE_VIDEO_PARSE (base_video_parse), FALSE); - - GST_DEBUG ("set_src_caps"); - - return gst_pad_set_caps (GST_BASE_VIDEO_CODEC_SRC_PAD (base_video_parse), - caps); -} - -void -gst_base_video_parse_lost_sync (GstBaseVideoParse * base_video_parse) -{ - g_return_if_fail (GST_IS_BASE_VIDEO_PARSE (base_video_parse)); - - GST_DEBUG ("lost_sync"); - - if (gst_adapter_available (base_video_parse->input_adapter) >= 1) { - gst_adapter_flush (base_video_parse->input_adapter, 1); - } - - base_video_parse->have_sync = FALSE; -} - -GstVideoFrame * -gst_base_video_parse_get_frame (GstBaseVideoParse * base_video_parse) -{ - g_return_val_if_fail (GST_IS_BASE_VIDEO_PARSE (base_video_parse), NULL); - - return base_video_parse->current_frame; -} - -void -gst_base_video_parse_add_to_frame (GstBaseVideoParse * base_video_parse, - int n_bytes) -{ - GstBuffer *buf; - - GST_DEBUG ("add_to_frame"); - - buf = gst_adapter_take_buffer (base_video_parse->input_adapter, n_bytes); - - gst_adapter_push (base_video_parse->output_adapter, buf); -} - -GstFlowReturn -gst_base_video_parse_finish_frame (GstBaseVideoParse * base_video_parse) -{ - GstVideoFrame *frame = base_video_parse->current_frame; - GstBuffer *buffer; - GstBaseVideoParseClass *base_video_parse_class; - GstFlowReturn ret; - - GST_DEBUG ("finish_frame"); - - base_video_parse_class = GST_BASE_VIDEO_PARSE_GET_CLASS (base_video_parse); - - buffer = gst_adapter_take_buffer (base_video_parse->output_adapter, - gst_adapter_available (base_video_parse->output_adapter)); - - if (frame->is_sync_point) { - base_video_parse->timestamp_offset = base_video_parse->last_timestamp - - gst_util_uint64_scale (frame->presentation_frame_number, - base_video_parse->state.fps_d * GST_SECOND, - base_video_parse->state.fps_n); - base_video_parse->distance_from_sync = 0; - } - - frame->distance_from_sync = base_video_parse->distance_from_sync; - base_video_parse->distance_from_sync++; - - frame->presentation_timestamp = - gst_base_video_parse_get_timestamp (base_video_parse, - frame->presentation_frame_number); - frame->presentation_duration = - gst_base_video_parse_get_timestamp (base_video_parse, - frame->presentation_frame_number + 1) - frame->presentation_timestamp; - frame->decode_timestamp = - gst_base_video_parse_get_timestamp (base_video_parse, - frame->decode_frame_number); - - GST_BUFFER_TIMESTAMP (buffer) = frame->presentation_timestamp; - GST_BUFFER_DURATION (buffer) = frame->presentation_duration; - if (frame->decode_frame_number < 0) { - GST_BUFFER_OFFSET (buffer) = 0; - } else { - GST_BUFFER_OFFSET (buffer) = frame->decode_timestamp; - } - GST_BUFFER_OFFSET_END (buffer) = GST_CLOCK_TIME_NONE; - - GST_DEBUG ("pts %" GST_TIME_FORMAT, - GST_TIME_ARGS (frame->presentation_timestamp)); - GST_DEBUG ("dts %" GST_TIME_FORMAT, GST_TIME_ARGS (frame->decode_timestamp)); - GST_DEBUG ("dist %d", frame->distance_from_sync); - - if (frame->is_sync_point) { - GST_BUFFER_FLAG_UNSET (buffer, GST_BUFFER_FLAG_DELTA_UNIT); - } else { - GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT); - } - - frame->src_buffer = buffer; - ret = base_video_parse_class->shape_output (base_video_parse, frame); - - gst_base_video_parse_free_frame (base_video_parse->current_frame); - - /* create new frame */ - base_video_parse->current_frame = - gst_base_video_parse_new_frame (base_video_parse); - - return ret; -} - -static void -gst_base_video_parse_free_frame (GstVideoFrame * frame) -{ - if (frame->sink_buffer) { - gst_buffer_unref (frame->sink_buffer); - } -#if 0 - if (frame->src_buffer) { - gst_buffer_unref (frame->src_buffer); - } -#endif - - g_free (frame); -} - -static GstVideoFrame * -gst_base_video_parse_new_frame (GstBaseVideoParse * base_video_parse) -{ - GstVideoFrame *frame; - - frame = g_malloc0 (sizeof (GstVideoFrame)); - - frame->system_frame_number = base_video_parse->system_frame_number; - base_video_parse->system_frame_number++; - - frame->decode_frame_number = frame->system_frame_number - - base_video_parse->reorder_depth; - - return frame; -} - -void -gst_base_video_parse_set_sync_point (GstBaseVideoParse * base_video_parse) -{ - GST_DEBUG ("set_sync_point"); - - base_video_parse->current_frame->is_sync_point = TRUE; - - base_video_parse->distance_from_sync = 0; -} - -GstFlowReturn -gst_base_video_parse_push (GstBaseVideoParse * base_video_parse, - GstBuffer * buffer) -{ - GstBaseVideoParseClass *base_video_parse_class; - - base_video_parse_class = GST_BASE_VIDEO_PARSE_GET_CLASS (base_video_parse); - - if (base_video_parse->caps == NULL) { - gboolean ret; - - base_video_parse->caps = - base_video_parse_class->get_caps (base_video_parse); - - ret = gst_pad_set_caps (GST_BASE_VIDEO_CODEC_SRC_PAD (base_video_parse), - base_video_parse->caps); - - if (!ret) { - GST_WARNING ("pad didn't accept caps"); - return GST_FLOW_ERROR; - } - } - gst_buffer_set_caps (buffer, base_video_parse->caps); - - GST_DEBUG ("pushing ts=%" GST_TIME_FORMAT " dur=%" GST_TIME_FORMAT - " off=%" G_GUINT64_FORMAT " off_end=%" G_GUINT64_FORMAT, - GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)), - GST_TIME_ARGS (GST_BUFFER_DURATION (buffer)), - GST_BUFFER_OFFSET (buffer), GST_BUFFER_OFFSET_END (buffer)); - - if (base_video_parse->discont) { - GST_BUFFER_FLAG_SET (buffer, GST_BUFFER_FLAG_DISCONT); - base_video_parse->discont = FALSE; - } else { - GST_BUFFER_FLAG_UNSET (buffer, GST_BUFFER_FLAG_DISCONT); - } - - return gst_pad_push (GST_BASE_VIDEO_CODEC_SRC_PAD (base_video_parse), buffer); -} diff --git a/gst-libs/gst/video/gstbasevideoparse.h b/gst-libs/gst/video/gstbasevideoparse.h deleted file mode 100644 index 252685acd1..0000000000 --- a/gst-libs/gst/video/gstbasevideoparse.h +++ /dev/null @@ -1,142 +0,0 @@ -/* GStreamer - * Copyright (C) 2008 David Schleef - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Library General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Library General Public License for more details. - * - * You should have received a copy of the GNU Library General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. - */ - -#ifndef _GST_BASE_VIDEO_PARSE_H_ -#define _GST_BASE_VIDEO_PARSE_H_ - -#ifndef GST_USE_UNSTABLE_API -#warning "GstBaseVideoParse is unstable API and may change in future." -#warning "You can define GST_USE_UNSTABLE_API to avoid this warning." -#endif - -#include -#include - -G_BEGIN_DECLS - -#define GST_TYPE_BASE_VIDEO_PARSE \ - (gst_base_video_parse_get_type()) -#define GST_BASE_VIDEO_PARSE(obj) \ - (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_BASE_VIDEO_PARSE,GstBaseVideoParse)) -#define GST_BASE_VIDEO_PARSE_CLASS(klass) \ - (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_BASE_VIDEO_PARSE,GstBaseVideoParseClass)) -#define GST_BASE_VIDEO_PARSE_GET_CLASS(obj) \ - (G_TYPE_INSTANCE_GET_CLASS((obj),GST_TYPE_BASE_VIDEO_PARSE,GstBaseVideoParseClass)) -#define GST_IS_BASE_VIDEO_PARSE(obj) \ - (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_BASE_VIDEO_PARSE)) -#define GST_IS_BASE_VIDEO_PARSE_CLASS(obj) \ - (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_BASE_VIDEO_PARSE)) - -/** - * GST_BASE_VIDEO_PARSE_SINK_NAME: - * - * The name of the templates for the sink pad. - */ -#define GST_BASE_VIDEO_PARSE_SINK_NAME "sink" -/** - * GST_BASE_VIDEO_PARSE_SRC_NAME: - * - * The name of the templates for the source pad. - */ -#define GST_BASE_VIDEO_PARSE_SRC_NAME "src" - -/** - * GST_BASE_VIDEO_PARSE_FLOW_NEED_DATA: - * - */ -#define GST_BASE_VIDEO_PARSE_FLOW_NEED_DATA GST_FLOW_CUSTOM_SUCCESS - -typedef struct _GstBaseVideoParse GstBaseVideoParse; -typedef struct _GstBaseVideoParseClass GstBaseVideoParseClass; - -struct _GstBaseVideoParse -{ - GstBaseVideoCodec base_video_codec; - - /*< private >*/ - GstAdapter *input_adapter; - GstAdapter *output_adapter; - - int reorder_depth; - - gboolean have_sync; - gboolean discont; - gboolean started; - - GstVideoFrame *current_frame; - GstVideoState state; - GstSegment segment; - int distance_from_sync; - - gboolean sink_clipping; - - guint64 presentation_frame_number; - guint64 system_frame_number; - - GstCaps *caps; - gboolean set_output_caps; - - GstClockTime last_timestamp; - - gint64 timestamp_offset; -}; - -struct _GstBaseVideoParseClass -{ - GstBaseVideoCodecClass base_video_codec_class; - - gboolean (*start) (GstBaseVideoParse *parse); - gboolean (*stop) (GstBaseVideoParse *parse); - gboolean (*reset) (GstBaseVideoParse *parse); - GstFlowReturn (*parse_data) (GstBaseVideoParse *parse, gboolean at_eos); - int (*scan_for_sync) (GstAdapter *adapter, gboolean at_eos, - int offset, int n); - GstFlowReturn (*shape_output) (GstBaseVideoParse *parse, GstVideoFrame *frame); - GstCaps *(*get_caps) (GstBaseVideoParse *parse); - -}; - -GType gst_base_video_parse_get_type (void); - -int gst_base_video_parse_get_width (GstBaseVideoParse *parse); -int gst_base_video_parse_get_height (GstBaseVideoParse *parse); -GstVideoState *gst_base_video_parse_get_state (GstBaseVideoParse *parse); -void gst_base_video_parse_set_state (GstBaseVideoParse *parse, - GstVideoState *state); - -guint64 gst_base_video_parse_get_timestamp_offset (GstBaseVideoParse *parse); - -gboolean gst_base_video_parse_set_src_caps (GstBaseVideoParse *base_video_parse, GstCaps *caps); - -GstFlowReturn gst_base_video_parse_end_of_stream (GstBaseVideoParse *base_video_parse, - GstBuffer *buffer); - -void gst_base_video_parse_lost_sync (GstBaseVideoParse *base_video_parse); - -GstVideoFrame * gst_base_video_parse_get_frame (GstBaseVideoParse *base_video_parse); -void gst_base_video_parse_add_to_frame (GstBaseVideoParse *base_video_parse, int n_bytes); -GstFlowReturn gst_base_video_parse_finish_frame (GstBaseVideoParse *base_video_parse); -void gst_base_video_parse_set_sync_point (GstBaseVideoParse *base_video_parse); -GstFlowReturn gst_base_video_parse_push (GstBaseVideoParse *base_video_parse, - GstBuffer *buffer); - -G_END_DECLS - -#endif - From 3192e69c0cf9db666c83ce65ff4a86dc046e1156 Mon Sep 17 00:00:00 2001 From: David Schleef Date: Sat, 19 Feb 2011 13:13:13 -0800 Subject: [PATCH 434/448] colorspace: Fix memleak --- gst/colorspace/gstcolorspace.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/gst/colorspace/gstcolorspace.c b/gst/colorspace/gstcolorspace.c index 8a823fa0d9..508fb8a708 100644 --- a/gst/colorspace/gstcolorspace.c +++ b/gst/colorspace/gstcolorspace.c @@ -229,6 +229,10 @@ gst_csp_set_caps (GstBaseTransform * btrans, GstCaps * incaps, space = GST_CSP (btrans); + if (space->convert) { + colorspace_convert_free (space->convert); + } + /* input caps */ ret = gst_video_format_parse_caps (incaps, &in_format, &in_width, &in_height); From 6fcdba78a8995d4ebee17bfaf418a39f0083ba31 Mon Sep 17 00:00:00 2001 From: David Schleef Date: Sat, 19 Feb 2011 13:12:41 -0800 Subject: [PATCH 435/448] colorspace: Add 16-bit-per-channel handling --- configure.ac | 2 +- gst/colorspace/colorspace.c | 477 +++++++++++++++++++++++++++++---- gst/colorspace/colorspace.h | 6 + gst/colorspace/gstcolorspace.c | 21 +- 4 files changed, 436 insertions(+), 70 deletions(-) diff --git a/configure.ac b/configure.ac index dd040a4e86..6b4bf57945 100644 --- a/configure.ac +++ b/configure.ac @@ -51,7 +51,7 @@ AM_PROG_LIBTOOL dnl *** required versions of GStreamer stuff *** GST_REQ=0.10.32.1 -GSTPB_REQ=0.10.32 +GSTPB_REQ=0.10.32.1 dnl *** autotools stuff **** diff --git a/gst/colorspace/colorspace.c b/gst/colorspace/colorspace.c index e69ab80a4b..b949fe28f3 100644 --- a/gst/colorspace/colorspace.c +++ b/gst/colorspace/colorspace.c @@ -27,8 +27,6 @@ #include #include "gstcolorspaceorc.h" -/* For GST_CHECK_PLUGINS_BASE_VERSION() */ -#include static void colorspace_convert_generic (ColorspaceConvert * convert, guint8 * dest, const guint8 * src); @@ -75,6 +73,13 @@ colorspace_convert_new (GstVideoFormat to_format, ColorSpaceColorSpec to_spec, convert->width = width; convert->convert = colorspace_convert_generic; + if (gst_video_format_get_component_depth (to_format, 0) > 8 || + gst_video_format_get_component_depth (from_format, 0) > 8) { + convert->use_16bit = TRUE; + } else { + convert->use_16bit = FALSE; + } + for (i = 0; i < 4; i++) { convert->dest_stride[i] = gst_video_format_get_row_stride (to_format, i, width); @@ -98,9 +103,9 @@ colorspace_convert_new (GstVideoFormat to_format, ColorSpaceColorSpec to_spec, colorspace_convert_lookup_fastpath (convert); colorspace_convert_lookup_getput (convert); - convert->tmpline = g_malloc (sizeof (guint32) * width * 2); + convert->tmpline = g_malloc (sizeof (guint8) * (width + 8) * 4); + convert->tmpline16 = g_malloc (sizeof (guint16) * (width + 8) * 4); -#if GST_CHECK_PLUGINS_BASE_VERSION(0, 10, 32) if (to_format == GST_VIDEO_FORMAT_RGB8_PALETTED) { /* build poor man's palette, taken from ffmpegcolorspace */ static const guint8 pal_value[6] = { 0x00, 0x33, 0x66, 0x99, 0xcc, 0xff }; @@ -122,7 +127,6 @@ colorspace_convert_new (GstVideoFormat to_format, ColorSpaceColorSpec to_spec, while (i < 256) palette[i++] = 0xff000000; } -#endif return convert; } @@ -130,10 +134,9 @@ colorspace_convert_new (GstVideoFormat to_format, ColorSpaceColorSpec to_spec, void colorspace_convert_free (ColorspaceConvert * convert) { - if (convert->palette) - g_free (convert->palette); - if (convert->tmpline) - g_free (convert->tmpline); + g_free (convert->palette); + g_free (convert->tmpline); + g_free (convert->tmpline16); g_free (convert); } @@ -390,25 +393,131 @@ putline_v210 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src, guint16 u0, u1, u2; guint16 v0, v1, v2; - y0 = src[4 * (i + 0) + 1]; - y1 = src[4 * (i + 1) + 1]; - y2 = src[4 * (i + 2) + 1]; - y3 = src[4 * (i + 3) + 1]; - y4 = src[4 * (i + 4) + 1]; - y5 = src[4 * (i + 5) + 1]; + y0 = src[4 * (i + 0) + 1] << 2; + y1 = src[4 * (i + 1) + 1] << 2; + y2 = src[4 * (i + 2) + 1] << 2; + y3 = src[4 * (i + 3) + 1] << 2; + y4 = src[4 * (i + 4) + 1] << 2; + y5 = src[4 * (i + 5) + 1] << 2; - u0 = (src[4 * (i + 0) + 2] + src[4 * (i + 1) + 2] + 1) >> 1; - u1 = (src[4 * (i + 2) + 2] + src[4 * (i + 3) + 2] + 1) >> 1; - u2 = (src[4 * (i + 4) + 2] + src[4 * (i + 5) + 2] + 1) >> 1; + u0 = (src[4 * (i + 0) + 2] + src[4 * (i + 1) + 2]) << 1; + u1 = (src[4 * (i + 2) + 2] + src[4 * (i + 3) + 2]) << 1; + u2 = (src[4 * (i + 4) + 2] + src[4 * (i + 5) + 2]) << 1; - v0 = (src[4 * (i + 0) + 3] + src[4 * (i + 1) + 3] + 1) >> 1; - v1 = (src[4 * (i + 2) + 3] + src[4 * (i + 3) + 3] + 1) >> 1; - v2 = (src[4 * (i + 4) + 3] + src[4 * (i + 5) + 3] + 1) >> 1; + v0 = (src[4 * (i + 0) + 3] + src[4 * (i + 1) + 3]) << 1; + v1 = (src[4 * (i + 2) + 3] + src[4 * (i + 3) + 3]) << 1; + v2 = (src[4 * (i + 4) + 3] + src[4 * (i + 5) + 3]) << 1; - a0 = (u0 << 2) | ((y0 << 2) << 10) | ((v0 << 2) << 20); - a1 = (y1 << 2) | ((u1 << 2) << 10) | ((y2 << 2) << 20); - a2 = (v1 << 2) | ((y3 << 2) << 10) | ((u2 << 2) << 20); - a3 = (y4 << 2) | ((v2 << 2) << 10) | ((y5 << 2) << 20); + a0 = u0 | (y0 << 10) | (v0 << 20); + a1 = y1 | (u1 << 10) | (y2 << 20); + a2 = v1 | (y3 << 10) | (u2 << 20); + a3 = y4 | (v2 << 10) | (y5 << 20); + + GST_WRITE_UINT32_LE (destline + (i / 6) * 16 + 0, a0); + GST_WRITE_UINT32_LE (destline + (i / 6) * 16 + 4, a1); + GST_WRITE_UINT32_LE (destline + (i / 6) * 16 + 8, a2); + GST_WRITE_UINT32_LE (destline + (i / 6) * 16 + 12, a3); + } +} + +static void +getline16_v210 (ColorspaceConvert * convert, guint16 * dest, const guint8 * src, + int j) +{ + int i; + const guint8 *srcline = FRAME_GET_LINE (src, 0, j); + + for (i = 0; i < convert->width; i += 6) { + guint32 a0, a1, a2, a3; + guint16 y0, y1, y2, y3, y4, y5; + guint16 u0, u2, u4; + guint16 v0, v2, v4; + + a0 = GST_READ_UINT32_LE (srcline + (i / 6) * 16 + 0); + a1 = GST_READ_UINT32_LE (srcline + (i / 6) * 16 + 4); + a2 = GST_READ_UINT32_LE (srcline + (i / 6) * 16 + 8); + a3 = GST_READ_UINT32_LE (srcline + (i / 6) * 16 + 12); + + u0 = ((a0 >> 0) & 0x3ff) << 6; + y0 = ((a0 >> 10) & 0x3ff) << 6; + v0 = ((a0 >> 20) & 0x3ff) << 6; + y1 = ((a1 >> 0) & 0x3ff) << 6; + + u2 = ((a1 >> 10) & 0x3ff) << 6; + y2 = ((a1 >> 20) & 0x3ff) << 6; + v2 = ((a2 >> 0) & 0x3ff) << 6; + y3 = ((a2 >> 10) & 0x3ff) << 6; + + u4 = ((a2 >> 20) & 0x3ff) << 6; + y4 = ((a3 >> 0) & 0x3ff) << 6; + v4 = ((a3 >> 10) & 0x3ff) << 6; + y5 = ((a3 >> 20) & 0x3ff) << 6; + + dest[4 * (i + 0) + 0] = 0xffff; + dest[4 * (i + 0) + 1] = y0; + dest[4 * (i + 0) + 2] = u0; + dest[4 * (i + 0) + 3] = v0; + + dest[4 * (i + 1) + 0] = 0xffff; + dest[4 * (i + 1) + 1] = y1; + dest[4 * (i + 1) + 2] = u0; + dest[4 * (i + 1) + 3] = v0; + + dest[4 * (i + 2) + 0] = 0xffff; + dest[4 * (i + 2) + 1] = y2; + dest[4 * (i + 2) + 2] = u2; + dest[4 * (i + 2) + 3] = v2; + + dest[4 * (i + 3) + 0] = 0xffff; + dest[4 * (i + 3) + 1] = y3; + dest[4 * (i + 3) + 2] = u2; + dest[4 * (i + 3) + 3] = v2; + + dest[4 * (i + 4) + 0] = 0xffff; + dest[4 * (i + 4) + 1] = y4; + dest[4 * (i + 4) + 2] = u4; + dest[4 * (i + 4) + 3] = v4; + + dest[4 * (i + 5) + 0] = 0xffff; + dest[4 * (i + 5) + 1] = y5; + dest[4 * (i + 5) + 2] = u4; + dest[4 * (i + 5) + 3] = v4; + + } +} + +static void +putline16_v210 (ColorspaceConvert * convert, guint8 * dest, const guint16 * src, + int j) +{ + int i; + guint8 *destline = FRAME_GET_LINE (dest, 0, j); + + for (i = 0; i < convert->width + 5; i += 6) { + guint32 a0, a1, a2, a3; + guint16 y0, y1, y2, y3, y4, y5; + guint16 u0, u1, u2; + guint16 v0, v1, v2; + + y0 = src[4 * (i + 0) + 1] >> 6; + y1 = src[4 * (i + 1) + 1] >> 6; + y2 = src[4 * (i + 2) + 1] >> 6; + y3 = src[4 * (i + 3) + 1] >> 6; + y4 = src[4 * (i + 4) + 1] >> 6; + y5 = src[4 * (i + 5) + 1] >> 6; + + u0 = (src[4 * (i + 0) + 2] + src[4 * (i + 1) + 2] + 1) >> 7; + u1 = (src[4 * (i + 2) + 2] + src[4 * (i + 3) + 2] + 1) >> 7; + u2 = (src[4 * (i + 4) + 2] + src[4 * (i + 5) + 2] + 1) >> 7; + + v0 = (src[4 * (i + 0) + 3] + src[4 * (i + 1) + 3] + 1) >> 7; + v1 = (src[4 * (i + 2) + 3] + src[4 * (i + 3) + 3] + 1) >> 7; + v2 = (src[4 * (i + 4) + 3] + src[4 * (i + 5) + 3] + 1) >> 7; + + a0 = u0 | (y0 << 10) | (v0 << 20); + a1 = y1 | (u1 << 10) | (y2 << 20); + a2 = v1 | (y3 << 10) | (u2 << 20); + a3 = y4 | (v2 << 10) | (y5 << 20); GST_WRITE_UINT32_LE (destline + (i / 6) * 16 + 0, a0); GST_WRITE_UINT32_LE (destline + (i / 6) * 16 + 4, a1); @@ -425,9 +534,9 @@ getline_v216 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src, const guint8 *srcline = FRAME_GET_LINE (src, 0, j); for (i = 0; i < convert->width; i++) { dest[i * 4 + 0] = 0xff; - dest[i * 4 + 1] = GST_READ_UINT16_LE (srcline + i * 4 + 2); - dest[i * 4 + 2] = GST_READ_UINT16_LE (srcline + (i >> 1) * 8 + 0); - dest[i * 4 + 3] = GST_READ_UINT16_LE (srcline + (i >> 1) * 8 + 4); + dest[i * 4 + 1] = GST_READ_UINT16_LE (srcline + i * 4 + 2) >> 8; + dest[i * 4 + 2] = GST_READ_UINT16_LE (srcline + (i >> 1) * 8 + 0) >> 8; + dest[i * 4 + 3] = GST_READ_UINT16_LE (srcline + (i >> 1) * 8 + 4) >> 8; } } @@ -445,6 +554,34 @@ putline_v216 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src, } } +static void +getline16_v216 (ColorspaceConvert * convert, guint16 * dest, const guint8 * src, + int j) +{ + int i; + const guint8 *srcline = FRAME_GET_LINE (src, 0, j); + for (i = 0; i < convert->width; i++) { + dest[i * 4 + 0] = 0xffff; + dest[i * 4 + 1] = GST_READ_UINT16_LE (srcline + i * 4 + 2); + dest[i * 4 + 2] = GST_READ_UINT16_LE (srcline + (i >> 1) * 8 + 0); + dest[i * 4 + 3] = GST_READ_UINT16_LE (srcline + (i >> 1) * 8 + 4); + } +} + +static void +putline16_v216 (ColorspaceConvert * convert, guint8 * dest, const guint16 * src, + int j) +{ + int i; + guint8 *destline = FRAME_GET_LINE (dest, 0, j); + for (i = 0; i < convert->width / 2; i++) { + GST_WRITE_UINT16_LE (destline + i * 8 + 0, src[(i * 2 + 0) * 4 + 2]); + GST_WRITE_UINT16_LE (destline + i * 8 + 2, src[(i * 2 + 0) * 4 + 1]); + GST_WRITE_UINT16_LE (destline + i * 8 + 4, src[(i * 2 + 1) * 4 + 3]); + GST_WRITE_UINT16_LE (destline + i * 8 + 8, src[(i * 2 + 0) * 4 + 1]); + } +} + static void getline_Y41B (ColorspaceConvert * convert, guint8 * dest, const guint8 * src, int j) @@ -875,7 +1012,6 @@ putline_A420 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src, FRAME_GET_LINE (dest, 3, j), src, convert->width / 2); } -#if GST_CHECK_PLUGINS_BASE_VERSION(0, 10, 32) static void getline_RGB8P (ColorspaceConvert * convert, guint8 * dest, const guint8 * src, int j) @@ -1053,7 +1189,64 @@ putline_IYU1 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src, destline[(i >> 2) * 6 + 3] = src[i * 4 + 3]; } } -#endif + +static void +getline_AY64 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src, + int j) +{ + int i; + const guint16 *srcline = (const guint16 *) FRAME_GET_LINE (src, 0, j); + for (i = 0; i < convert->width * 4; i++) { + dest[i] = srcline[i] >> 8; + } +} + +static void +putline_AY64 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src, + int j) +{ + int i; + guint16 *destline = (guint16 *) FRAME_GET_LINE (dest, 0, j); + for (i = 0; i < convert->width * 4; i++) { + destline[i] = src[i] << 8; + } +} + +static void +getline16_AY64 (ColorspaceConvert * convert, guint16 * dest, const guint8 * src, + int j) +{ + memcpy (dest, FRAME_GET_LINE (src, 0, j), convert->width * 8); +} + +static void +putline16_AY64 (ColorspaceConvert * convert, guint8 * dest, const guint16 * src, + int j) +{ + memcpy (FRAME_GET_LINE (dest, 0, j), src, convert->width * 8); +} + +static void +getline16_convert (ColorspaceConvert * convert, guint16 * dest, + const guint8 * src, int j) +{ + int i; + convert->getline (convert, convert->tmpline, src, j); + for (i = 0; i < convert->width * 4; i++) { + dest[i] = convert->tmpline[i] << 8; + } +} + +static void +putline16_convert (ColorspaceConvert * convert, guint8 * dest, + const guint16 * src, int j) +{ + int i; + for (i = 0; i < convert->width * 4; i++) { + convert->tmpline[i] = src[i] >> 8; + } + convert->putline (convert, dest, convert->tmpline, j); +} typedef struct { @@ -1062,6 +1255,10 @@ typedef struct const guint8 * src, int j); void (*putline) (ColorspaceConvert * convert, guint8 * dest, const guint8 * src, int j); + void (*getline16) (ColorspaceConvert * convert, guint16 * dest, + const guint8 * src, int j); + void (*putline16) (ColorspaceConvert * convert, guint8 * dest, + const guint16 * src, int j); } ColorspaceLine; static const ColorspaceLine lines[] = { {GST_VIDEO_FORMAT_I420, getline_I420, putline_I420}, @@ -1083,8 +1280,10 @@ static const ColorspaceLine lines[] = { {GST_VIDEO_FORMAT_Y42B, getline_Y42B, putline_Y42B}, {GST_VIDEO_FORMAT_YVYU, getline_YVYU, putline_YVYU}, {GST_VIDEO_FORMAT_Y444, getline_Y444, putline_Y444}, - {GST_VIDEO_FORMAT_v210, getline_v210, putline_v210}, - {GST_VIDEO_FORMAT_v216, getline_v216, putline_v216}, + {GST_VIDEO_FORMAT_v210, getline_v210, putline_v210, + getline16_v210, putline16_v210}, + {GST_VIDEO_FORMAT_v216, getline_v216, putline_v216, + getline16_v216, putline16_v216}, {GST_VIDEO_FORMAT_NV12, getline_NV12, putline_NV12}, {GST_VIDEO_FORMAT_NV21, getline_NV21, putline_NV21}, //{GST_VIDEO_FORMAT_GRAY8, getline_GRAY8, putline_GRAY8}, @@ -1099,12 +1298,14 @@ static const ColorspaceLine lines[] = { {GST_VIDEO_FORMAT_BGR15, getline_BGR15, putline_BGR15}, {GST_VIDEO_FORMAT_UYVP, getline_UYVP, putline_UYVP}, {GST_VIDEO_FORMAT_A420, getline_A420, putline_A420} -#if GST_CHECK_PLUGINS_BASE_VERSION(0, 10, 32) , {GST_VIDEO_FORMAT_RGB8_PALETTED, getline_RGB8P, putline_RGB8P}, {GST_VIDEO_FORMAT_YUV9, getline_YUV9, putline_YUV9}, {GST_VIDEO_FORMAT_YVU9, getline_YUV9, putline_YUV9}, /* alias */ - {GST_VIDEO_FORMAT_IYU1, getline_IYU1, putline_IYU1} -#endif + {GST_VIDEO_FORMAT_IYU1, getline_IYU1, putline_IYU1}, + {GST_VIDEO_FORMAT_ARGB64, getline_AY64, putline_AY64, getline16_AY64, + putline16_AY64}, + {GST_VIDEO_FORMAT_AYUV64, getline_AY64, putline_AY64, getline16_AY64, + putline16_AY64} }; static void @@ -1251,6 +1452,151 @@ matrix_identity (ColorspaceConvert * convert) /* do nothing */ } +static void +matrix16_rgb_to_yuv_bt470_6 (ColorspaceConvert * convert) +{ + int i; + int r, g, b; + int y, u, v; + guint16 *tmpline = convert->tmpline16; + + for (i = 0; i < convert->width; i++) { + r = tmpline[i * 4 + 1]; + g = tmpline[i * 4 + 2]; + b = tmpline[i * 4 + 3]; + + y = (66 * r + 129 * g + 25 * b + 4096 * 256) >> 8; + u = (-38 * r - 74 * g + 112 * b + 32768 * 256) >> 8; + v = (112 * r - 94 * g - 18 * b + 32768 * 256) >> 8; + + tmpline[i * 4 + 1] = CLAMP (y, 0, 65535); + tmpline[i * 4 + 2] = CLAMP (u, 0, 65535); + tmpline[i * 4 + 3] = CLAMP (v, 0, 65535); + } +} + +static void +matrix16_rgb_to_yuv_bt709 (ColorspaceConvert * convert) +{ + int i; + int r, g, b; + int y, u, v; + guint16 *tmpline = convert->tmpline16; + + for (i = 0; i < convert->width; i++) { + r = tmpline[i * 4 + 1]; + g = tmpline[i * 4 + 2]; + b = tmpline[i * 4 + 3]; + + y = (47 * r + 157 * g + 16 * b + 4096 * 256) >> 8; + u = (-26 * r - 87 * g + 112 * b + 32768 * 256) >> 8; + v = (112 * r - 102 * g - 10 * b + 32768 * 256) >> 8; + + tmpline[i * 4 + 1] = CLAMP (y, 0, 65535); + tmpline[i * 4 + 2] = CLAMP (u, 0, 65535); + tmpline[i * 4 + 3] = CLAMP (v, 0, 65535); + } +} + +static void +matrix16_yuv_bt470_6_to_rgb (ColorspaceConvert * convert) +{ + int i; + int r, g, b; + int y, u, v; + guint16 *tmpline = convert->tmpline16; + + for (i = 0; i < convert->width; i++) { + y = tmpline[i * 4 + 1]; + u = tmpline[i * 4 + 2]; + v = tmpline[i * 4 + 3]; + + r = (298 * y + 409 * v - 57068 * 256) >> 8; + g = (298 * y - 100 * u - 208 * v + 34707 * 256) >> 8; + b = (298 * y + 516 * u - 70870 * 256) >> 8; + + tmpline[i * 4 + 1] = CLAMP (y, 0, 65535); + tmpline[i * 4 + 2] = CLAMP (u, 0, 65535); + tmpline[i * 4 + 3] = CLAMP (v, 0, 65535); + } +} + +static void +matrix16_yuv_bt709_to_rgb (ColorspaceConvert * convert) +{ + int i; + int r, g, b; + int y, u, v; + guint16 *tmpline = convert->tmpline16; + + for (i = 0; i < convert->width; i++) { + y = tmpline[i * 4 + 1]; + u = tmpline[i * 4 + 2]; + v = tmpline[i * 4 + 3]; + + r = (298 * y + 459 * v - 63514 * 256) >> 8; + g = (298 * y - 55 * u - 136 * v + 19681 * 256) >> 8; + b = (298 * y + 541 * u - 73988 * 256) >> 8; + + tmpline[i * 4 + 1] = CLAMP (y, 0, 65535); + tmpline[i * 4 + 2] = CLAMP (u, 0, 65535); + tmpline[i * 4 + 3] = CLAMP (v, 0, 65535); + } +} + +static void +matrix16_yuv_bt709_to_yuv_bt470_6 (ColorspaceConvert * convert) +{ + int i; + int r, g, b; + int y, u, v; + guint16 *tmpline = convert->tmpline16; + + for (i = 0; i < convert->width; i++) { + y = tmpline[i * 4 + 1]; + u = tmpline[i * 4 + 2]; + v = tmpline[i * 4 + 3]; + + r = (256 * y + 25 * u + 49 * v - 9536 * 256) >> 8; + g = (253 * u - 28 * v + 3958 * 256) >> 8; + b = (-19 * u + 252 * v + 2918 * 256) >> 8; + + tmpline[i * 4 + 1] = CLAMP (y, 0, 65535); + tmpline[i * 4 + 2] = CLAMP (u, 0, 65535); + tmpline[i * 4 + 3] = CLAMP (v, 0, 65535); + } +} + +static void +matrix16_yuv_bt470_6_to_yuv_bt709 (ColorspaceConvert * convert) +{ + int i; + int r, g, b; + int y, u, v; + guint16 *tmpline = convert->tmpline16; + + for (i = 0; i < convert->width; i++) { + y = tmpline[i * 4 + 1]; + u = tmpline[i * 4 + 2]; + v = tmpline[i * 4 + 3]; + + r = (256 * y - 30 * u - 53 * v + 10600 * 256) >> 8; + g = (261 * u + 29 * v - 4367 * 256) >> 8; + b = (19 * u + 262 * v - 3289 * 256) >> 8; + + tmpline[i * 4 + 1] = CLAMP (y, 0, 65535); + tmpline[i * 4 + 2] = CLAMP (u, 0, 65535); + tmpline[i * 4 + 3] = CLAMP (v, 0, 65535); + } +} + +static void +matrix16_identity (ColorspaceConvert * convert) +{ + /* do nothing */ +} + + static void colorspace_convert_lookup_getput (ColorspaceConvert * convert) @@ -1258,41 +1604,60 @@ colorspace_convert_lookup_getput (ColorspaceConvert * convert) int i; convert->getline = NULL; + convert->getline16 = NULL; for (i = 0; i < sizeof (lines) / sizeof (lines[0]); i++) { if (lines[i].format == convert->from_format) { convert->getline = lines[i].getline; + convert->getline16 = lines[i].getline16; break; } } convert->putline = NULL; + convert->putline16 = NULL; for (i = 0; i < sizeof (lines) / sizeof (lines[0]); i++) { if (lines[i].format == convert->to_format) { convert->putline = lines[i].putline; + convert->putline16 = lines[i].putline16; break; } } GST_DEBUG ("get %p put %p", convert->getline, convert->putline); - if (convert->from_spec == convert->to_spec) + if (convert->getline16 == NULL) { + convert->getline16 = getline16_convert; + } + if (convert->putline16 == NULL) { + convert->putline16 = putline16_convert; + } + + if (convert->from_spec == convert->to_spec) { convert->matrix = matrix_identity; - else if (convert->from_spec == COLOR_SPEC_RGB - && convert->to_spec == COLOR_SPEC_YUV_BT470_6) + convert->matrix16 = matrix16_identity; + } else if (convert->from_spec == COLOR_SPEC_RGB + && convert->to_spec == COLOR_SPEC_YUV_BT470_6) { convert->matrix = matrix_rgb_to_yuv_bt470_6; - else if (convert->from_spec == COLOR_SPEC_RGB - && convert->to_spec == COLOR_SPEC_YUV_BT709) + convert->matrix16 = matrix16_rgb_to_yuv_bt470_6; + } else if (convert->from_spec == COLOR_SPEC_RGB + && convert->to_spec == COLOR_SPEC_YUV_BT709) { convert->matrix = matrix_rgb_to_yuv_bt709; - else if (convert->from_spec == COLOR_SPEC_YUV_BT470_6 - && convert->to_spec == COLOR_SPEC_RGB) + convert->matrix16 = matrix16_rgb_to_yuv_bt709; + } else if (convert->from_spec == COLOR_SPEC_YUV_BT470_6 + && convert->to_spec == COLOR_SPEC_RGB) { convert->matrix = matrix_yuv_bt470_6_to_rgb; - else if (convert->from_spec == COLOR_SPEC_YUV_BT709 - && convert->to_spec == COLOR_SPEC_RGB) + convert->matrix16 = matrix16_yuv_bt470_6_to_rgb; + } else if (convert->from_spec == COLOR_SPEC_YUV_BT709 + && convert->to_spec == COLOR_SPEC_RGB) { convert->matrix = matrix_yuv_bt709_to_rgb; - else if (convert->from_spec == COLOR_SPEC_YUV_BT709 - && convert->to_spec == COLOR_SPEC_YUV_BT470_6) + convert->matrix16 = matrix16_yuv_bt709_to_rgb; + } else if (convert->from_spec == COLOR_SPEC_YUV_BT709 + && convert->to_spec == COLOR_SPEC_YUV_BT470_6) { convert->matrix = matrix_yuv_bt709_to_yuv_bt470_6; - else if (convert->from_spec == COLOR_SPEC_YUV_BT470_6 - && convert->to_spec == COLOR_SPEC_YUV_BT709) + convert->matrix16 = matrix16_yuv_bt709_to_yuv_bt470_6; + } else if (convert->from_spec == COLOR_SPEC_YUV_BT470_6 + && convert->to_spec == COLOR_SPEC_YUV_BT709) { convert->matrix = matrix_yuv_bt470_6_to_yuv_bt709; + convert->matrix16 = matrix16_yuv_bt470_6_to_yuv_bt709; + } } static void @@ -1311,10 +1676,18 @@ colorspace_convert_generic (ColorspaceConvert * convert, guint8 * dest, return; } - for (j = 0; j < convert->height; j++) { - convert->getline (convert, convert->tmpline, src, j); - convert->matrix (convert); - convert->putline (convert, dest, convert->tmpline, j); + if (convert->use_16bit) { + for (j = 0; j < convert->height; j++) { + convert->getline16 (convert, convert->tmpline16, src, j); + convert->matrix16 (convert); + convert->putline16 (convert, dest, convert->tmpline16, j); + } + } else { + for (j = 0; j < convert->height; j++) { + convert->getline (convert, convert->tmpline, src, j); + convert->matrix (convert); + convert->putline (convert, dest, convert->tmpline, j); + } } } diff --git a/gst/colorspace/colorspace.h b/gst/colorspace/colorspace.h index b12b032df9..fe72524dde 100644 --- a/gst/colorspace/colorspace.h +++ b/gst/colorspace/colorspace.h @@ -43,6 +43,7 @@ struct _ColorspaceComponent { struct _ColorspaceConvert { gint width, height; gboolean interlaced; + gboolean use_16bit; GstVideoFormat from_format; ColorSpaceColorSpec from_spec; @@ -51,6 +52,7 @@ struct _ColorspaceConvert { guint32 *palette; guint8 *tmpline; + guint16 *tmpline16; int dest_offset[4]; int dest_stride[4]; @@ -61,6 +63,10 @@ struct _ColorspaceConvert { void (*getline) (ColorspaceConvert *convert, guint8 *dest, const guint8 *src, int j); void (*putline) (ColorspaceConvert *convert, guint8 *dest, const guint8 *src, int j); void (*matrix) (ColorspaceConvert *convert); + + void (*getline16) (ColorspaceConvert *convert, guint16 *dest, const guint8 *src, int j); + void (*putline16) (ColorspaceConvert *convert, guint8 *dest, const guint16 *src, int j); + void (*matrix16) (ColorspaceConvert *convert); }; ColorspaceConvert * colorspace_convert_new (GstVideoFormat to_format, diff --git a/gst/colorspace/gstcolorspace.c b/gst/colorspace/gstcolorspace.c index 508fb8a708..350b6c23ea 100644 --- a/gst/colorspace/gstcolorspace.c +++ b/gst/colorspace/gstcolorspace.c @@ -40,26 +40,16 @@ #include "gstcolorspace.h" #include -/* For GST_CHECK_PLUGINS_BASE_VERSION() */ -#include - #include GST_DEBUG_CATEGORY (colorspace_debug); #define GST_CAT_DEFAULT colorspace_debug GST_DEBUG_CATEGORY (colorspace_performance); -#if GST_CHECK_PLUGINS_BASE_VERSION(0, 10, 32) -#define VIDEO_CAPS_RGB8_PALETTED \ - GST_VIDEO_CAPS_RGB8_PALETTED "; " -#else -#define VIDEO_CAPS_RGB8_PALETTED /* no-op */ -#endif - #define CSP_VIDEO_CAPS \ "video/x-raw-yuv, width = "GST_VIDEO_SIZE_RANGE" , " \ "height="GST_VIDEO_SIZE_RANGE",framerate="GST_VIDEO_FPS_RANGE"," \ - "format= (fourcc) { I420 , NV12 , NV21 , YV12 , YUY2 , Y42B , Y444 , YUV9 , YVU9 , Y41B , Y800 , Y8 , GREY , Y16 , UYVY , YVYU , IYU1 , v308 , AYUV, v210, A420 } ;" \ + "format= (fourcc) { I420 , NV12 , NV21 , YV12 , YUY2 , Y42B , Y444 , YUV9 , YVU9 , Y41B , Y800 , Y8 , GREY , Y16 , UYVY , YVYU , IYU1 , v308 , AYUV, v210, A420, AY64 } ;" \ GST_VIDEO_CAPS_RGB";" \ GST_VIDEO_CAPS_BGR";" \ GST_VIDEO_CAPS_RGBx";" \ @@ -74,10 +64,11 @@ GST_DEBUG_CATEGORY (colorspace_performance); GST_VIDEO_CAPS_BGR_16";" \ GST_VIDEO_CAPS_RGB_15";" \ GST_VIDEO_CAPS_BGR_15";" \ - VIDEO_CAPS_RGB8_PALETTED \ + GST_VIDEO_CAPS_RGB8_PALETTED "; " \ GST_VIDEO_CAPS_GRAY8";" \ GST_VIDEO_CAPS_GRAY16("BIG_ENDIAN")";" \ - GST_VIDEO_CAPS_GRAY16("LITTLE_ENDIAN")";" + GST_VIDEO_CAPS_GRAY16("LITTLE_ENDIAN")";" \ + GST_VIDEO_CAPS_ARGB_64 static GstStaticPadTemplate gst_csp_src_template = GST_STATIC_PAD_TEMPLATE ("src", @@ -319,7 +310,6 @@ gst_csp_set_caps (GstBaseTransform * btrans, GstCaps * incaps, if (space->convert) { colorspace_convert_set_interlaced (space->convert, in_interlaced); } -#if GST_CHECK_PLUGINS_BASE_VERSION(0, 10, 32) /* palette, only for from data */ if (space->from_format == GST_VIDEO_FORMAT_RGB8_PALETTED && space->to_format == GST_VIDEO_FORMAT_RGB8_PALETTED) { @@ -347,7 +337,6 @@ gst_csp_set_caps (GstBaseTransform * btrans, GstCaps * incaps, gst_caps_set_simple (outcaps, "palette_data", GST_TYPE_BUFFER, p_buf, NULL); gst_buffer_unref (p_buf); } -#endif GST_DEBUG ("reconfigured %d %d", space->from_format, space->to_format); @@ -375,7 +364,6 @@ format_mismatch: space->to_format = GST_VIDEO_FORMAT_UNKNOWN; return FALSE; } -#if GST_CHECK_PLUGINS_BASE_VERSION(0, 10, 32) invalid_palette: { GST_ERROR_OBJECT (space, "invalid palette"); @@ -383,7 +371,6 @@ invalid_palette: space->to_format = GST_VIDEO_FORMAT_UNKNOWN; return FALSE; } -#endif } GST_BOILERPLATE (GstCsp, gst_csp, GstVideoFilter, GST_TYPE_VIDEO_FILTER); From f64b66ab23a9ad021b5ba7c3de36391221a769ea Mon Sep 17 00:00:00 2001 From: David Schleef Date: Sun, 20 Feb 2011 14:14:27 -0800 Subject: [PATCH 436/448] colorspace: fix a few formats --- gst/colorspace/colorspace.c | 5 +++-- gst/colorspace/gstcolorspace.c | 2 +- gst/colorspace/gstcolorspaceorc.orc | 3 ++- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/gst/colorspace/colorspace.c b/gst/colorspace/colorspace.c index b949fe28f3..d98ad20d7b 100644 --- a/gst/colorspace/colorspace.c +++ b/gst/colorspace/colorspace.c @@ -588,7 +588,8 @@ getline_Y41B (ColorspaceConvert * convert, guint8 * dest, const guint8 * src, { cogorc_getline_YUV9 (dest, FRAME_GET_LINE (src, 0, j), - FRAME_GET_LINE (src, 1, j), FRAME_GET_LINE (src, 2, j), convert->width); + FRAME_GET_LINE (src, 1, j), FRAME_GET_LINE (src, 2, j), + convert->width / 2); } static void @@ -1053,7 +1054,7 @@ getline_YUV9 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src, cogorc_getline_YUV9 (dest, FRAME_GET_LINE (src, 0, j), FRAME_GET_LINE (src, 1, j >> 2), - FRAME_GET_LINE (src, 2, j >> 2), convert->width); + FRAME_GET_LINE (src, 2, j >> 2), convert->width / 2); } static void diff --git a/gst/colorspace/gstcolorspace.c b/gst/colorspace/gstcolorspace.c index 350b6c23ea..84c9af956d 100644 --- a/gst/colorspace/gstcolorspace.c +++ b/gst/colorspace/gstcolorspace.c @@ -49,7 +49,7 @@ GST_DEBUG_CATEGORY (colorspace_performance); #define CSP_VIDEO_CAPS \ "video/x-raw-yuv, width = "GST_VIDEO_SIZE_RANGE" , " \ "height="GST_VIDEO_SIZE_RANGE",framerate="GST_VIDEO_FPS_RANGE"," \ - "format= (fourcc) { I420 , NV12 , NV21 , YV12 , YUY2 , Y42B , Y444 , YUV9 , YVU9 , Y41B , Y800 , Y8 , GREY , Y16 , UYVY , YVYU , IYU1 , v308 , AYUV, v210, A420, AY64 } ;" \ + "format= (fourcc) { I420 , NV12 , NV21 , YV12 , YUY2 , Y42B , Y444 , YUV9 , YVU9 , Y41B , Y800 , Y8 , GREY , Y16 , UYVY , YVYU , IYU1 , v308 , AYUV, v210, v216, A420, AY64 } ;" \ GST_VIDEO_CAPS_RGB";" \ GST_VIDEO_CAPS_BGR";" \ GST_VIDEO_CAPS_RGBx";" \ diff --git a/gst/colorspace/gstcolorspaceorc.orc b/gst/colorspace/gstcolorspaceorc.orc index 263992dd4e..086990e15e 100644 --- a/gst/colorspace/gstcolorspaceorc.orc +++ b/gst/colorspace/gstcolorspaceorc.orc @@ -1384,7 +1384,8 @@ x2 mergewl ayuv, ayay, uvuv .temp 4 ayay .temp 4 uvuv -x2 splitwb yy, uv, uyvy +x2 splitwb uv, yy, uyvy +swapw uv, uv x2 mergebw ayay, c255, yy mergewl uvuv, uv, uv x2 mergewl ayuv, ayay, uvuv From c696b54fa72343e5f863a100b09adf54b3b912b4 Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Tue, 11 Jan 2011 10:32:47 +0000 Subject: [PATCH 437/448] xviddec: bodge to avoid crashes It seems xvidcore overreads its input buffer, so a nasty workaround is to allocate some more memory (16 bytes seem to be enough). There is no apparent image corruption with these extra bytes set to 0, valgrind is much happier, and the crashes go away. It is ugly, and slower though. But then, xviddec is currently not autoplugged for playback anyway. https://bugzilla.gnome.org/show_bug.cgi?id=334107 --- ext/xvid/gstxviddec.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/ext/xvid/gstxviddec.c b/ext/xvid/gstxviddec.c index 84a0eaad90..67e33c03ec 100644 --- a/ext/xvid/gstxviddec.c +++ b/ext/xvid/gstxviddec.c @@ -310,7 +310,7 @@ gst_xviddec_chain (GstPad * pad, GstBuffer * buf) xvid_dec_frame_t xframe; xvid_dec_stats_t xstats; gint ret; - guint8 *data; + guint8 *data, *dupe = NULL; guint size; GstFlowReturn fret; @@ -333,6 +333,16 @@ gst_xviddec_chain (GstPad * pad, GstBuffer * buf) data = GST_BUFFER_DATA (buf); size = GST_BUFFER_SIZE (buf); + /* xvidcore overreads the input buffer, we need to alloc some extra padding + * to make things work reliably */ +#define EXTRA_PADDING 16 + if (EXTRA_PADDING > 0) { + dupe = g_malloc (size + EXTRA_PADDING); + memcpy (dupe, data, size); + memset (dupe + size, 0, EXTRA_PADDING); + data = dupe; + } + do { /* loop needed because xvidcore may return vol information */ /* decode and so ... */ gst_xvid_init_struct (xframe); @@ -412,6 +422,7 @@ gst_xviddec_chain (GstPad * pad, GstBuffer * buf) } done: + g_free (dupe); gst_buffer_unref (buf); return fret; From ab953ddf2feef34687c4f405d0a009b89f0d8e77 Mon Sep 17 00:00:00 2001 From: David Schleef Date: Sun, 20 Feb 2011 22:43:56 -0800 Subject: [PATCH 438/448] colorspace: Add dithering Dithering only happens when a 16-bit-per-channel format is involved. --- gst/colorspace/colorspace.c | 62 ++++++++++++++++++++++ gst/colorspace/colorspace.h | 10 ++++ gst/colorspace/gstcolorspace.c | 97 ++++++++++++++++++++++++++++++++++ gst/colorspace/gstcolorspace.h | 1 + 4 files changed, 170 insertions(+) diff --git a/gst/colorspace/colorspace.c b/gst/colorspace/colorspace.c index d98ad20d7b..107986625c 100644 --- a/gst/colorspace/colorspace.c +++ b/gst/colorspace/colorspace.c @@ -32,6 +32,9 @@ static void colorspace_convert_generic (ColorspaceConvert * convert, guint8 * dest, const guint8 * src); static void colorspace_convert_lookup_fastpath (ColorspaceConvert * convert); static void colorspace_convert_lookup_getput (ColorspaceConvert * convert); +static void colorspace_dither_none (ColorspaceConvert * convert, int j); +static void colorspace_dither_verterr (ColorspaceConvert * convert, int j); +static void colorspace_dither_halftone (ColorspaceConvert * convert, int j); ColorspaceConvert * @@ -72,6 +75,7 @@ colorspace_convert_new (GstVideoFormat to_format, ColorSpaceColorSpec to_spec, convert->height = height; convert->width = width; convert->convert = colorspace_convert_generic; + convert->dither16 = colorspace_dither_none; if (gst_video_format_get_component_depth (to_format, 0) > 8 || gst_video_format_get_component_depth (from_format, 0) > 8) { @@ -105,6 +109,7 @@ colorspace_convert_new (GstVideoFormat to_format, ColorSpaceColorSpec to_spec, convert->tmpline = g_malloc (sizeof (guint8) * (width + 8) * 4); convert->tmpline16 = g_malloc (sizeof (guint16) * (width + 8) * 4); + convert->errline = g_malloc (sizeof (guint16) * width * 4); if (to_format == GST_VIDEO_FORMAT_RGB8_PALETTED) { /* build poor man's palette, taken from ffmpegcolorspace */ @@ -137,6 +142,7 @@ colorspace_convert_free (ColorspaceConvert * convert) g_free (convert->palette); g_free (convert->tmpline); g_free (convert->tmpline16); + g_free (convert->errline); g_free (convert); } @@ -148,6 +154,23 @@ colorspace_convert_set_interlaced (ColorspaceConvert * convert, convert->interlaced = interlaced; } +void +colorspace_convert_set_dither (ColorspaceConvert * convert, int type) +{ + switch (type) { + case 0: + default: + convert->dither16 = colorspace_dither_none; + break; + case 1: + convert->dither16 = colorspace_dither_verterr; + break; + case 2: + convert->dither16 = colorspace_dither_halftone; + break; + } +} + void colorspace_convert_set_palette (ColorspaceConvert * convert, const guint32 * palette) @@ -1681,6 +1704,7 @@ colorspace_convert_generic (ColorspaceConvert * convert, guint8 * dest, for (j = 0; j < convert->height; j++) { convert->getline16 (convert, convert->tmpline16, src, j); convert->matrix16 (convert); + convert->dither16 (convert, j); convert->putline16 (convert, dest, convert->tmpline16, j); } } else { @@ -1692,6 +1716,44 @@ colorspace_convert_generic (ColorspaceConvert * convert, guint8 * dest, } } +static void +colorspace_dither_none (ColorspaceConvert * convert, int j) +{ +} + +static void +colorspace_dither_verterr (ColorspaceConvert * convert, int j) +{ + int i; + guint16 *tmpline = convert->tmpline16; + guint16 *errline = convert->errline; + + for (i = 0; i < 4 * convert->width; i++) { + tmpline[i] += errline[i]; + errline[i] = tmpline[i] & 0xff; + } +} + +static void +colorspace_dither_halftone (ColorspaceConvert * convert, int j) +{ + int i; + guint16 *tmpline = convert->tmpline16; + static guint16 halftone[8][8] = { + {0, 128, 32, 160, 8, 136, 40, 168}, + {192, 64, 224, 96, 200, 72, 232, 104}, + {48, 176, 16, 144, 56, 184, 24, 152}, + {240, 112, 208, 80, 248, 120, 216, 88}, + {12, 240, 44, 172, 4, 132, 36, 164}, + {204, 76, 236, 108, 196, 68, 228, 100}, + {60, 188, 28, 156, 52, 180, 20, 148}, + {252, 142, 220, 92, 244, 116, 212, 84} + }; + + for (i = 0; i < convert->width * 4; i++) { + tmpline[i] += halftone[(i >> 2) & 7][j & 7]; + } +} /* Fast paths */ diff --git a/gst/colorspace/colorspace.h b/gst/colorspace/colorspace.h index fe72524dde..05bcc18670 100644 --- a/gst/colorspace/colorspace.h +++ b/gst/colorspace/colorspace.h @@ -35,6 +35,12 @@ typedef enum { COLOR_SPEC_YUV_BT709 } ColorSpaceColorSpec; +typedef enum { + DITHER_NONE, + DITHER_VERTERR, + DITHER_HALFTONE +} ColorSpaceDitherMethod; + struct _ColorspaceComponent { int offset; int stride; @@ -44,6 +50,7 @@ struct _ColorspaceConvert { gint width, height; gboolean interlaced; gboolean use_16bit; + gboolean dither; GstVideoFormat from_format; ColorSpaceColorSpec from_spec; @@ -53,6 +60,7 @@ struct _ColorspaceConvert { guint8 *tmpline; guint16 *tmpline16; + guint16 *errline; int dest_offset[4]; int dest_stride[4]; @@ -67,11 +75,13 @@ struct _ColorspaceConvert { void (*getline16) (ColorspaceConvert *convert, guint16 *dest, const guint8 *src, int j); void (*putline16) (ColorspaceConvert *convert, guint8 *dest, const guint16 *src, int j); void (*matrix16) (ColorspaceConvert *convert); + void (*dither16) (ColorspaceConvert *convert, int j); }; ColorspaceConvert * colorspace_convert_new (GstVideoFormat to_format, ColorSpaceColorSpec from_spec, GstVideoFormat from_format, ColorSpaceColorSpec to_spec, int width, int height); +void colorspace_convert_set_dither (ColorspaceConvert * convert, int type); void colorspace_convert_set_interlaced (ColorspaceConvert *convert, gboolean interlaced); void colorspace_convert_set_palette (ColorspaceConvert *convert, diff --git a/gst/colorspace/gstcolorspace.c b/gst/colorspace/gstcolorspace.c index 84c9af956d..658bc8a849 100644 --- a/gst/colorspace/gstcolorspace.c +++ b/gst/colorspace/gstcolorspace.c @@ -46,6 +46,12 @@ GST_DEBUG_CATEGORY (colorspace_debug); #define GST_CAT_DEFAULT colorspace_debug GST_DEBUG_CATEGORY (colorspace_performance); +enum +{ + PROP_0, + PROP_DITHER +}; + #define CSP_VIDEO_CAPS \ "video/x-raw-yuv, width = "GST_VIDEO_SIZE_RANGE" , " \ "height="GST_VIDEO_SIZE_RANGE",framerate="GST_VIDEO_FPS_RANGE"," \ @@ -86,6 +92,12 @@ GST_STATIC_PAD_TEMPLATE ("sink", GType gst_csp_get_type (void); +static void gst_csp_set_property (GObject * object, + guint property_id, const GValue * value, GParamSpec * pspec); +static void gst_csp_get_property (GObject * object, + guint property_id, GValue * value, GParamSpec * pspec); +static void gst_csp_dispose (GObject * object); + static gboolean gst_csp_set_caps (GstBaseTransform * btrans, GstCaps * incaps, GstCaps * outcaps); static gboolean gst_csp_get_unit_size (GstBaseTransform * btrans, @@ -97,6 +109,25 @@ static GQuark _QRAWRGB; /* "video/x-raw-rgb" */ static GQuark _QRAWYUV; /* "video/x-raw-yuv" */ static GQuark _QALPHAMASK; /* "alpha_mask" */ + +static GType +dither_method_get_type (void) +{ + static GType gtype = 0; + + if (gtype == 0) { + static const GEnumValue values[] = { + {DITHER_NONE, "No dithering (default)", "none"}, + {DITHER_VERTERR, "Vertical error propogation", "verterr"}, + {DITHER_HALFTONE, "Half-tone", "halftone"}, + {0, NULL, NULL} + }; + + gtype = g_enum_register_static ("GstColorspaceDitherMethod", values); + } + return gtype; +} + /* copies the given caps */ static GstCaps * gst_csp_caps_remove_format_info (GstCaps * caps) @@ -395,6 +426,19 @@ gst_csp_base_init (gpointer klass) _QALPHAMASK = g_quark_from_string ("alpha_mask"); } +void +gst_csp_dispose (GObject * object) +{ + GstCsp *csp; + + g_return_if_fail (GST_IS_CSP (object)); + csp = GST_CSP (object); + + /* clean up as possible. may be called multiple times */ + + G_OBJECT_CLASS (parent_class)->dispose (object); +} + static void gst_csp_finalize (GObject * obj) { @@ -415,6 +459,9 @@ gst_csp_class_init (GstCspClass * klass) GstBaseTransformClass *gstbasetransform_class = (GstBaseTransformClass *) klass; + gobject_class->set_property = gst_csp_set_property; + gobject_class->get_property = gst_csp_get_property; + gobject_class->dispose = gst_csp_dispose; gobject_class->finalize = gst_csp_finalize; gstbasetransform_class->transform_caps = @@ -425,6 +472,12 @@ gst_csp_class_init (GstCspClass * klass) gstbasetransform_class->transform = GST_DEBUG_FUNCPTR (gst_csp_transform); gstbasetransform_class->passthrough_on_same_caps = TRUE; + + g_object_class_install_property (gobject_class, PROP_DITHER, + g_param_spec_enum ("dither", "Dither", "Apply dithering while converting", + dither_method_get_type (), DITHER_NONE, + G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + } static void @@ -434,6 +487,44 @@ gst_csp_init (GstCsp * space, GstCspClass * klass) space->to_format = GST_VIDEO_FORMAT_UNKNOWN; } +void +gst_csp_set_property (GObject * object, guint property_id, + const GValue * value, GParamSpec * pspec) +{ + GstCsp *csp; + + g_return_if_fail (GST_IS_CSP (object)); + csp = GST_CSP (object); + + switch (property_id) { + case PROP_DITHER: + csp->dither = g_value_get_enum (value); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + +void +gst_csp_get_property (GObject * object, guint property_id, + GValue * value, GParamSpec * pspec) +{ + GstCsp *csp; + + g_return_if_fail (GST_IS_CSP (object)); + csp = GST_CSP (object); + + switch (property_id) { + case PROP_DITHER: + g_value_set_enum (value, csp->dither); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec); + break; + } +} + static gboolean gst_csp_get_unit_size (GstBaseTransform * btrans, GstCaps * caps, guint * size) { @@ -465,6 +556,12 @@ gst_csp_transform (GstBaseTransform * btrans, GstBuffer * inbuf, space->to_format == GST_VIDEO_FORMAT_UNKNOWN)) goto unknown_format; + if (space->dither) { + colorspace_convert_set_dither (space->convert, 1); + } else { + colorspace_convert_set_dither (space->convert, 0); + } + colorspace_convert_convert (space->convert, GST_BUFFER_DATA (outbuf), GST_BUFFER_DATA (inbuf)); diff --git a/gst/colorspace/gstcolorspace.h b/gst/colorspace/gstcolorspace.h index c97705ceac..71245b831e 100644 --- a/gst/colorspace/gstcolorspace.h +++ b/gst/colorspace/gstcolorspace.h @@ -56,6 +56,7 @@ struct _GstCsp { ColorSpaceColorSpec to_spec; ColorspaceConvert *convert; + gboolean dither; }; struct _GstCspClass From cad8a864ffdd7c314550737517c55ef9f1465561 Mon Sep 17 00:00:00 2001 From: David Schleef Date: Sun, 20 Feb 2011 23:01:30 -0800 Subject: [PATCH 439/448] colorspace: Fix YUV->RGB matrixing --- gst/colorspace/colorspace.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/gst/colorspace/colorspace.c b/gst/colorspace/colorspace.c index 107986625c..761e505a1e 100644 --- a/gst/colorspace/colorspace.c +++ b/gst/colorspace/colorspace.c @@ -1539,9 +1539,9 @@ matrix16_yuv_bt470_6_to_rgb (ColorspaceConvert * convert) g = (298 * y - 100 * u - 208 * v + 34707 * 256) >> 8; b = (298 * y + 516 * u - 70870 * 256) >> 8; - tmpline[i * 4 + 1] = CLAMP (y, 0, 65535); - tmpline[i * 4 + 2] = CLAMP (u, 0, 65535); - tmpline[i * 4 + 3] = CLAMP (v, 0, 65535); + tmpline[i * 4 + 1] = CLAMP (r, 0, 65535); + tmpline[i * 4 + 2] = CLAMP (g, 0, 65535); + tmpline[i * 4 + 3] = CLAMP (b, 0, 65535); } } @@ -1562,9 +1562,9 @@ matrix16_yuv_bt709_to_rgb (ColorspaceConvert * convert) g = (298 * y - 55 * u - 136 * v + 19681 * 256) >> 8; b = (298 * y + 541 * u - 73988 * 256) >> 8; - tmpline[i * 4 + 1] = CLAMP (y, 0, 65535); - tmpline[i * 4 + 2] = CLAMP (u, 0, 65535); - tmpline[i * 4 + 3] = CLAMP (v, 0, 65535); + tmpline[i * 4 + 1] = CLAMP (r, 0, 65535); + tmpline[i * 4 + 2] = CLAMP (g, 0, 65535); + tmpline[i * 4 + 3] = CLAMP (b, 0, 65535); } } @@ -1585,9 +1585,9 @@ matrix16_yuv_bt709_to_yuv_bt470_6 (ColorspaceConvert * convert) g = (253 * u - 28 * v + 3958 * 256) >> 8; b = (-19 * u + 252 * v + 2918 * 256) >> 8; - tmpline[i * 4 + 1] = CLAMP (y, 0, 65535); - tmpline[i * 4 + 2] = CLAMP (u, 0, 65535); - tmpline[i * 4 + 3] = CLAMP (v, 0, 65535); + tmpline[i * 4 + 1] = CLAMP (r, 0, 65535); + tmpline[i * 4 + 2] = CLAMP (g, 0, 65535); + tmpline[i * 4 + 3] = CLAMP (b, 0, 65535); } } @@ -1608,9 +1608,9 @@ matrix16_yuv_bt470_6_to_yuv_bt709 (ColorspaceConvert * convert) g = (261 * u + 29 * v - 4367 * 256) >> 8; b = (19 * u + 262 * v - 3289 * 256) >> 8; - tmpline[i * 4 + 1] = CLAMP (y, 0, 65535); - tmpline[i * 4 + 2] = CLAMP (u, 0, 65535); - tmpline[i * 4 + 3] = CLAMP (v, 0, 65535); + tmpline[i * 4 + 1] = CLAMP (r, 0, 65535); + tmpline[i * 4 + 2] = CLAMP (g, 0, 65535); + tmpline[i * 4 + 3] = CLAMP (b, 0, 65535); } } From 6d8740476ccd3a3498dc4f18c19733643825c7b8 Mon Sep 17 00:00:00 2001 From: David Schleef Date: Sun, 20 Feb 2011 23:57:19 -0800 Subject: [PATCH 440/448] Check that collectpads exists before removing pad The core now calls release pad from finalize, at which point the collectpads might have already been freed. --- gst/mpegpsmux/mpegpsmux.c | 4 +++- gst/qtmux/gstqtmux.c | 5 ++++- gst/videomeasure/gstvideomeasure_ssim.c | 4 +++- 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/gst/mpegpsmux/mpegpsmux.c b/gst/mpegpsmux/mpegpsmux.c index d64fb353d7..249dfc9efb 100644 --- a/gst/mpegpsmux/mpegpsmux.c +++ b/gst/mpegpsmux/mpegpsmux.c @@ -588,7 +588,9 @@ mpegpsmux_release_pad (GstElement * element, GstPad * pad) } GST_OBJECT_UNLOCK (pad); - gst_collect_pads_remove_pad (mux->collect, pad); + if (mux->collect) { + gst_collect_pads_remove_pad (mux->collect, pad); + } } static gboolean diff --git a/gst/qtmux/gstqtmux.c b/gst/qtmux/gstqtmux.c index 1477db7c8e..728e1f3c59 100644 --- a/gst/qtmux/gstqtmux.c +++ b/gst/qtmux/gstqtmux.c @@ -503,6 +503,7 @@ gst_qt_mux_finalize (GObject * object) atoms_context_free (qtmux->context); gst_object_unref (qtmux->collect); + qtmux->collect = NULL; g_slist_free (qtmux->sinkpads); @@ -3165,7 +3166,9 @@ gst_qt_mux_release_pad (GstElement * element, GstPad * pad) } } - gst_collect_pads_remove_pad (mux->collect, pad); + if (mux->collect) { + gst_collect_pads_remove_pad (mux->collect, pad); + } } static GstPad * diff --git a/gst/videomeasure/gstvideomeasure_ssim.c b/gst/videomeasure/gstvideomeasure_ssim.c index a99fa9ff3a..5043e93c6b 100644 --- a/gst/videomeasure/gstvideomeasure_ssim.c +++ b/gst/videomeasure/gstvideomeasure_ssim.c @@ -1253,7 +1253,9 @@ gst_ssim_release_pad (GstElement * element, GstPad * pad) GST_DEBUG_OBJECT (ssim, "release pad %s:%s", GST_DEBUG_PAD_NAME (pad)); - gst_collect_pads_remove_pad (ssim->collect, pad); + if (ssim->collect) { + gst_collect_pads_remove_pad (ssim->collect, pad); + } gst_element_remove_pad (element, pad); } From 715529c9632353097157433e2649cf1c2e69a9e5 Mon Sep 17 00:00:00 2001 From: Edward Hervey Date: Mon, 21 Feb 2011 12:14:59 +0100 Subject: [PATCH 441/448] Revert "Check that collectpads exists before removing pad" This reverts commit 6d8740476ccd3a3498dc4f18c19733643825c7b8. Depends on a core commit that was reverted --- gst/mpegpsmux/mpegpsmux.c | 4 +--- gst/qtmux/gstqtmux.c | 5 +---- gst/videomeasure/gstvideomeasure_ssim.c | 4 +--- 3 files changed, 3 insertions(+), 10 deletions(-) diff --git a/gst/mpegpsmux/mpegpsmux.c b/gst/mpegpsmux/mpegpsmux.c index 249dfc9efb..d64fb353d7 100644 --- a/gst/mpegpsmux/mpegpsmux.c +++ b/gst/mpegpsmux/mpegpsmux.c @@ -588,9 +588,7 @@ mpegpsmux_release_pad (GstElement * element, GstPad * pad) } GST_OBJECT_UNLOCK (pad); - if (mux->collect) { - gst_collect_pads_remove_pad (mux->collect, pad); - } + gst_collect_pads_remove_pad (mux->collect, pad); } static gboolean diff --git a/gst/qtmux/gstqtmux.c b/gst/qtmux/gstqtmux.c index 728e1f3c59..1477db7c8e 100644 --- a/gst/qtmux/gstqtmux.c +++ b/gst/qtmux/gstqtmux.c @@ -503,7 +503,6 @@ gst_qt_mux_finalize (GObject * object) atoms_context_free (qtmux->context); gst_object_unref (qtmux->collect); - qtmux->collect = NULL; g_slist_free (qtmux->sinkpads); @@ -3166,9 +3165,7 @@ gst_qt_mux_release_pad (GstElement * element, GstPad * pad) } } - if (mux->collect) { - gst_collect_pads_remove_pad (mux->collect, pad); - } + gst_collect_pads_remove_pad (mux->collect, pad); } static GstPad * diff --git a/gst/videomeasure/gstvideomeasure_ssim.c b/gst/videomeasure/gstvideomeasure_ssim.c index 5043e93c6b..a99fa9ff3a 100644 --- a/gst/videomeasure/gstvideomeasure_ssim.c +++ b/gst/videomeasure/gstvideomeasure_ssim.c @@ -1253,9 +1253,7 @@ gst_ssim_release_pad (GstElement * element, GstPad * pad) GST_DEBUG_OBJECT (ssim, "release pad %s:%s", GST_DEBUG_PAD_NAME (pad)); - if (ssim->collect) { - gst_collect_pads_remove_pad (ssim->collect, pad); - } + gst_collect_pads_remove_pad (ssim->collect, pad); gst_element_remove_pad (element, pad); } From 246c4a7cf49cf901b853a1ce4f8d101120ba3938 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Mon, 21 Feb 2011 13:24:03 +0000 Subject: [PATCH 442/448] baseparse: rename GType from GstAudioBaseParseBad to GstBaseParseBad We use it for video as well now. --- gst-libs/gst/baseparse/gstbaseparse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst-libs/gst/baseparse/gstbaseparse.c b/gst-libs/gst/baseparse/gstbaseparse.c index df7aed7dce..a4a312aa6f 100644 --- a/gst-libs/gst/baseparse/gstbaseparse.c +++ b/gst-libs/gst/baseparse/gstbaseparse.c @@ -329,7 +329,7 @@ gst_base_parse_get_type (void) }; base_parse_type = g_type_register_static (GST_TYPE_ELEMENT, - "GstAudioBaseParseBad", &base_parse_info, G_TYPE_FLAG_ABSTRACT); + "GstBaseParseBad", &base_parse_info, G_TYPE_FLAG_ABSTRACT); } return base_parse_type; } From 6526548962cc3f4e855d8f35c812e9add3db36a9 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Thu, 24 Feb 2011 09:29:51 -0300 Subject: [PATCH 443/448] jifmux: tests: Increase bus waiting timeout Double bus waiting timeout as sometimes the test would fail because it would timeout and get no messages from the bus. --- tests/check/elements/jifmux.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tests/check/elements/jifmux.c b/tests/check/elements/jifmux.c index b481dbf9e0..f76d77a842 100644 --- a/tests/check/elements/jifmux.c +++ b/tests/check/elements/jifmux.c @@ -942,9 +942,10 @@ generate_jif_file_with_tags_from_taglist (GstTagList * taglist, fail_if (gst_element_set_state (pipeline, GST_STATE_PLAYING) == GST_STATE_CHANGE_FAILURE); - msg = gst_bus_timed_pop_filtered (bus, GST_SECOND * 5, GST_MESSAGE_EOS | + msg = gst_bus_timed_pop_filtered (bus, GST_SECOND * 10, GST_MESSAGE_EOS | GST_MESSAGE_ERROR); - fail_if (!msg || GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR); + fail_if (!msg); + fail_if (GST_MESSAGE_TYPE (msg) == GST_MESSAGE_ERROR); gst_message_unref (msg); gst_object_unref (bus); From 7920622ac7d135ed3247c4d17ec1751a25f4115b Mon Sep 17 00:00:00 2001 From: David Schleef Date: Wed, 23 Feb 2011 17:24:14 -0800 Subject: [PATCH 444/448] baseparse: make_metadata_writable() fix --- gst-libs/gst/baseparse/gstbaseparse.c | 1 + 1 file changed, 1 insertion(+) diff --git a/gst-libs/gst/baseparse/gstbaseparse.c b/gst-libs/gst/baseparse/gstbaseparse.c index a4a312aa6f..e465529dbd 100644 --- a/gst-libs/gst/baseparse/gstbaseparse.c +++ b/gst-libs/gst/baseparse/gstbaseparse.c @@ -1725,6 +1725,7 @@ gst_base_parse_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame) g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR); /* decorate */ + buffer = gst_buffer_make_metadata_writable (buffer); gst_buffer_set_caps (buffer, GST_PAD_CAPS (parse->srcpad)); parse->priv->seen_keyframe |= parse->priv->is_video && From e49b89d5c5a1244fa0dcb8bb4996e38fb9bff9e5 Mon Sep 17 00:00:00 2001 From: David Schleef Date: Wed, 23 Feb 2011 17:25:03 -0800 Subject: [PATCH 445/448] aacparse: allow parsed frames on sink pad --- gst/audioparsers/gstaacparse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst/audioparsers/gstaacparse.c b/gst/audioparsers/gstaacparse.c index 09e3e71f2c..fbdc165774 100644 --- a/gst/audioparsers/gstaacparse.c +++ b/gst/audioparsers/gstaacparse.c @@ -58,7 +58,7 @@ static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, GST_STATIC_CAPS ("audio/mpeg, " - "framed = (boolean) false, " "mpegversion = (int) { 2, 4 };")); + "framed = (boolean) { true, false}, " "mpegversion = (int) { 2, 4 };")); GST_DEBUG_CATEGORY_STATIC (gst_aacparse_debug); #define GST_CAT_DEFAULT gst_aacparse_debug From afc74832472afc9f25e90738e76a266e8005a8c7 Mon Sep 17 00:00:00 2001 From: David Schleef Date: Fri, 25 Feb 2011 19:57:47 -0800 Subject: [PATCH 446/448] colorspace: Add support for r210 --- gst/colorspace/colorspace.c | 69 +++++++++++++++++++++++++++++++++- gst/colorspace/gstcolorspace.c | 1 + 2 files changed, 69 insertions(+), 1 deletion(-) diff --git a/gst/colorspace/colorspace.c b/gst/colorspace/colorspace.c index 761e505a1e..8bcd2c4295 100644 --- a/gst/colorspace/colorspace.c +++ b/gst/colorspace/colorspace.c @@ -1250,6 +1250,71 @@ putline16_AY64 (ColorspaceConvert * convert, guint8 * dest, const guint16 * src, memcpy (FRAME_GET_LINE (dest, 0, j), src, convert->width * 8); } +static void +getline_r210 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src, + int j) +{ + int i; + const guint8 *srcline = FRAME_GET_LINE (src, 0, j); + for (i = 0; i < convert->width; i++) { + guint8 x; + dest[i * 4 + 0] = 0xff; + x = GST_READ_UINT32_BE (srcline + i * 4); + dest[i * 4 + 1] = (x >> 22) & 0xff; + dest[i * 4 + 2] = (x >> 12) & 0xff; + dest[i * 4 + 3] = (x >> 2) & 0xff; + } +} + +static void +putline_r210 (ColorspaceConvert * convert, guint8 * dest, const guint8 * src, + int j) +{ + int i; + guint8 *destline = FRAME_GET_LINE (dest, 0, j); + for (i = 0; i < convert->width / 2; i++) { + guint32 x = 0; + x |= src[i * 4 + 1] << 22; + x |= (src[i * 4 + 1] & 0xc0) << 14; + x |= src[i * 4 + 2] << 12; + x |= (src[i * 4 + 2] & 0xc0) << 10; + x |= src[i * 4 + 3] << 2; + x |= (src[i * 4 + 3] & 0xc0) >> 6; + GST_WRITE_UINT32_BE (destline + i * 4, x); + } +} + +static void +getline16_r210 (ColorspaceConvert * convert, guint16 * dest, const guint8 * src, + int j) +{ + int i; + const guint8 *srcline = FRAME_GET_LINE (src, 0, j); + for (i = 0; i < convert->width; i++) { + guint32 x; + dest[i * 4 + 0] = 0xffff; + x = GST_READ_UINT32_BE (srcline + i * 4); + dest[i * 4 + 1] = ((x >> 14) & 0xffc0) | (x >> 24); + dest[i * 4 + 2] = ((x >> 4) & 0xffc0) | ((x >> 14) & 0x3f); + dest[i * 4 + 3] = ((x << 6) & 0xffc0) | ((x >> 4) & 0x3f); + } +} + +static void +putline16_r210 (ColorspaceConvert * convert, guint8 * dest, const guint16 * src, + int j) +{ + int i; + guint8 *destline = FRAME_GET_LINE (dest, 0, j); + for (i = 0; i < convert->width / 2; i++) { + guint32 x = 0; + x |= (src[i * 4 + 1] & 0xffc0) << 14; + x |= (src[i * 4 + 2] & 0xffc0) << 4; + x |= (src[i * 4 + 3] & 0xffc0) >> 6; + GST_WRITE_UINT32_BE (destline + i * 4, x); + } +} + static void getline16_convert (ColorspaceConvert * convert, guint16 * dest, const guint8 * src, int j) @@ -1329,7 +1394,9 @@ static const ColorspaceLine lines[] = { {GST_VIDEO_FORMAT_ARGB64, getline_AY64, putline_AY64, getline16_AY64, putline16_AY64}, {GST_VIDEO_FORMAT_AYUV64, getline_AY64, putline_AY64, getline16_AY64, - putline16_AY64} + putline16_AY64}, + {GST_VIDEO_FORMAT_r210, getline_r210, putline_r210, getline16_r210, + putline16_r210} }; static void diff --git a/gst/colorspace/gstcolorspace.c b/gst/colorspace/gstcolorspace.c index 658bc8a849..bdd1c89ea2 100644 --- a/gst/colorspace/gstcolorspace.c +++ b/gst/colorspace/gstcolorspace.c @@ -74,6 +74,7 @@ enum GST_VIDEO_CAPS_GRAY8";" \ GST_VIDEO_CAPS_GRAY16("BIG_ENDIAN")";" \ GST_VIDEO_CAPS_GRAY16("LITTLE_ENDIAN")";" \ + GST_VIDEO_CAPS_r210";" \ GST_VIDEO_CAPS_ARGB_64 static GstStaticPadTemplate gst_csp_src_template = From 0bb6b6f2452b8cb7d9aca3c6d31e0ed87db24e23 Mon Sep 17 00:00:00 2001 From: David Schleef Date: Fri, 25 Feb 2011 19:59:05 -0800 Subject: [PATCH 447/448] colorspace: set dithering enum directly --- gst/colorspace/gstcolorspace.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/gst/colorspace/gstcolorspace.c b/gst/colorspace/gstcolorspace.c index bdd1c89ea2..3d934a5ed3 100644 --- a/gst/colorspace/gstcolorspace.c +++ b/gst/colorspace/gstcolorspace.c @@ -557,11 +557,7 @@ gst_csp_transform (GstBaseTransform * btrans, GstBuffer * inbuf, space->to_format == GST_VIDEO_FORMAT_UNKNOWN)) goto unknown_format; - if (space->dither) { - colorspace_convert_set_dither (space->convert, 1); - } else { - colorspace_convert_set_dither (space->convert, 0); - } + colorspace_convert_set_dither (space->convert, space->dither); colorspace_convert_convert (space->convert, GST_BUFFER_DATA (outbuf), GST_BUFFER_DATA (inbuf)); From a68137c4dcdbf3dce5cd278403478aef1de62f59 Mon Sep 17 00:00:00 2001 From: David Schleef Date: Sat, 26 Feb 2011 13:53:44 -0800 Subject: [PATCH 448/448] Revert "aacparse: allow parsed frames on sink pad" This reverts commit e49b89d5c5a1244fa0dcb8bb4996e38fb9bff9e5. --- gst/audioparsers/gstaacparse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst/audioparsers/gstaacparse.c b/gst/audioparsers/gstaacparse.c index fbdc165774..09e3e71f2c 100644 --- a/gst/audioparsers/gstaacparse.c +++ b/gst/audioparsers/gstaacparse.c @@ -58,7 +58,7 @@ static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, GST_STATIC_CAPS ("audio/mpeg, " - "framed = (boolean) { true, false}, " "mpegversion = (int) { 2, 4 };")); + "framed = (boolean) false, " "mpegversion = (int) { 2, 4 };")); GST_DEBUG_CATEGORY_STATIC (gst_aacparse_debug); #define GST_CAT_DEFAULT gst_aacparse_debug