diff --git a/ChangeLog b/ChangeLog index 285e334563..a2cb26f1e2 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2004-02-11 David Schleef + + * ext/lcs/gstcolorspace.c: (colorspace_find_lcs_format), + (gst_colorspace_caps_get_fourcc), (colorspace_setup_converter), + (gst_colorspace_getcaps), (gst_colorspace_link), + (gst_colorspace_base_init), (gst_colorspace_init), + (gst_colorspace_chain), (gst_colorspace_change_state), + (plugin_init): Merge Ronald's patch (bug #117897) and update + for new caps and negotiation. Seems to work, although it + shows off bugs in lcs. + 2004-02-11 David Schleef * ext/alsa/Makefile.am: Fix linking against libgstinterfaces. diff --git a/ext/lcs/gstcolorspace.c b/ext/lcs/gstcolorspace.c index 948b97a692..128e017e5c 100644 --- a/ext/lcs/gstcolorspace.c +++ b/ext/lcs/gstcolorspace.c @@ -23,6 +23,7 @@ #include #include #include +#include #define GST_TYPE_COLORSPACE \ (gst_colorspace_get_type()) @@ -38,11 +39,6 @@ typedef struct _GstColorspace GstColorspace; typedef struct _GstColorspaceClass GstColorspaceClass; -typedef enum { - GST_COLORSPACE_NONE, - GST_COLORSPACE_LCS, -} GstColorSpaceConverterType; - struct _GstColorspace { GstElement element; @@ -50,14 +46,10 @@ struct _GstColorspace { LCSConverter *converter; - GstColorSpaceConverterType type; + gboolean passthrough; gint width, height; - gfloat fps; + double framerate; gboolean disabled; - - GstCaps *sinkcaps; - - GstBufferPool *pool; }; struct _GstColorspaceClass { @@ -97,73 +89,122 @@ static void gst_colorspace_get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec); static GstPadLinkReturn - gst_colorspace_sinkconnect (GstPad *pad, GstCaps *caps); -static GstPadLinkReturn - gst_colorspace_srcconnect (GstPad *pad, GstCaps *caps); -static GstPadLinkReturn - gst_colorspace_srcconnect_func (GstPad *pad, GstCaps *caps, gboolean newcaps); + gst_colorspace_link (GstPad *pad, const GstCaps *caps); static void gst_colorspace_chain (GstPad *pad, GstData *_data); static GstElementStateReturn gst_colorspace_change_state (GstElement *element); -static GstPadTemplate *srctempl, *sinktempl; static GstElementClass *parent_class = NULL; /*static guint gst_colorspace_signals[LAST_SIGNAL] = { 0 }; */ -static GstBufferPool* -colorspace_get_bufferpool (GstPad *pad) -{ - GstColorspace *space; +static GstStaticPadTemplate gst_colorspace_src_template = +GST_STATIC_PAD_TEMPLATE ( + "src", + GST_PAD_SRC, + GST_PAD_ALWAYS, + 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_RGB_16 "; " + GST_VIDEO_CAPS_RGB_15 "; " + GST_VIDEO_CAPS_YUV("{ I420, YV12, YUY2, YVYU, UYVY, YUV9, YVU9, " + "Y800, Y41P, Y41B, Y42B, IUY2 }") + ) +); - space = GST_COLORSPACE (gst_pad_get_parent (pad)); - - if (space->type == GST_COLORSPACE_NONE && !space->disabled) - return gst_pad_get_bufferpool (space->srcpad); - else - return NULL; -} +static GstStaticPadTemplate gst_colorspace_sink_template = +GST_STATIC_PAD_TEMPLATE ( + "sink", + GST_PAD_SINK, + GST_PAD_ALWAYS, + 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_RGB_16 "; " + GST_VIDEO_CAPS_RGB_15 "; " + GST_VIDEO_CAPS_YUV("{ I420, YV12, YUY2, YVYU, UYVY, YUV9, YVU9, " + "Y800, Y41P, Y41B, Y42B, IUY2 }") + ) +); static const LCSFormat* -colorspace_find_lcs_format (GstCaps *caps) +colorspace_find_lcs_format (const GstCaps *caps) { const LCSFormat *format = NULL; - guint32 space; + const char *name; + const GstStructure *structure = gst_caps_get_structure (caps, 0); - gst_caps_get_fourcc_int (caps, "format", &space); + name = gst_structure_get_name (structure); - if (space == GST_MAKE_FOURCC ('R','G','B',' ')) { - gint mask, depth; + if (strcmp (name, "video/x-raw-rgb") == 0) { + LCSRGBPackedFormat *rgb_fmt = g_new (LCSRGBPackedFormat, 1); + gint mask; + gchar *format_name; + int endianness; - gulong red_bits, red_shift; - gulong green_bits, green_shift; - gulong blue_bits, blue_shift; - - gst_caps_get_int (caps, "depth", &depth); - gst_caps_get_int (caps, "red_mask", &mask); - lcs_utils_mask_to_shift (mask, &red_bits, &red_shift); - gst_caps_get_int (caps, "green_mask", &mask); - lcs_utils_mask_to_shift (mask, &green_bits, &green_shift); - gst_caps_get_int (caps, "blue_mask", &mask); - lcs_utils_mask_to_shift (mask, &blue_bits, &blue_shift); + format = (const LCSFormat *) rgb_fmt; - format = lcs_format_new_simple_rgb_packed (red_bits, green_bits, blue_bits, 0, - red_shift, green_shift, blue_shift, 0, depth, G_BYTE_ORDER); + ((LCSFormat *) rgb_fmt)->type = LCS_FORMAT_RGB_PACKED; + gst_structure_get_int (structure, "bpp", + &((LCSFormat *) rgb_fmt)->bits_per_pixel); + gst_structure_get_int (structure, "red_mask", &mask); + lcs_utils_mask_to_shift (mask, &rgb_fmt->bits_per_component[LCS_R], + &rgb_fmt->component_bit_offset[LCS_R]); + gst_structure_get_int (structure, "green_mask", &mask); + lcs_utils_mask_to_shift (mask, &rgb_fmt->bits_per_component[LCS_G], + &rgb_fmt->component_bit_offset[LCS_G]); + gst_structure_get_int (structure, "blue_mask", &mask); + lcs_utils_mask_to_shift (mask, &rgb_fmt->bits_per_component[LCS_B], + &rgb_fmt->component_bit_offset[LCS_B]); + rgb_fmt->bits_per_component[LCS_A] = 0; + rgb_fmt->component_bit_offset[LCS_A] = 0; + gst_structure_get_int (structure, "endianness", &endianness); + rgb_fmt->endianness = endianness; - GST_DEBUG ("%lu %lu %lu %lu %lu %lu %u %s\n", red_bits, green_bits, blue_bits, - red_shift, green_shift, blue_shift, depth, lcs_format_get_layout (format)); + format_name = g_strdup_printf ("GST_RGB_%d", format->bits_per_pixel); + lcs_register_format (format_name, (LCSFormat *) rgb_fmt, 1); } - else { + else if (strcmp (name, "video/x-raw-yuv") == 0) { + guint32 space; gchar fourcc[5]; + gst_structure_get_fourcc (structure, "format", &space); lcs_utils_fourcc_to_string (space, fourcc); - format = lcs_alias_find_format (fourcc); + fourcc[4] = '\0'; + format = lcs_find_format (fourcc); + } else { + g_assert_not_reached(); } return format; } +static guint32 +gst_colorspace_caps_get_fourcc (const GstCaps *caps) +{ + guint32 format; + GstStructure *structure; + + structure = gst_caps_get_structure (caps, 0); + if (strcmp (gst_structure_get_name (structure), "video/x-raw-rgb") == 0) { + format = GST_MAKE_FOURCC ('R','G','B',' '); + } else { + gst_structure_get_fourcc (structure, "format", &format); + } + return format; +} + static gboolean -colorspace_setup_converter (GstColorspace *space, GstCaps *from_caps, GstCaps *to_caps) +colorspace_setup_converter (GstColorspace *space, const GstCaps *from_caps, + const GstCaps *to_caps) { const LCSFormat *from_format = NULL; const LCSFormat *to_format = NULL; @@ -172,25 +213,22 @@ colorspace_setup_converter (GstColorspace *space, GstCaps *from_caps, GstCaps *t g_return_val_if_fail (to_caps != NULL, FALSE); g_return_val_if_fail (from_caps != NULL, FALSE); - if (gst_caps_has_property (from_caps, "format")) - gst_caps_get_fourcc_int (from_caps, "format", &from_space); - else - from_space = GST_MAKE_FOURCC ('R','G','B',' '); - - if (gst_caps_has_property (to_caps, "format")) - gst_caps_get_fourcc_int (to_caps, "format", &to_space); - else - to_space = GST_MAKE_FOURCC ('R','G','B',' '); + from_space = gst_colorspace_caps_get_fourcc (from_caps); + to_space = gst_colorspace_caps_get_fourcc (to_caps); from_format = colorspace_find_lcs_format (from_caps); to_format = colorspace_find_lcs_format (to_caps); - GST_DEBUG ("trying from %4.4s to %4.4s\n", (gchar*)&from_space, (gchar*)&to_space); - space->converter = lcs_get_converter (from_format, to_format, LCS_FLAG_FAST); + GST_DEBUG ("trying from " GST_FOURCC_FORMAT " to " GST_FOURCC_FORMAT, + GST_FOURCC_ARGS (from_space), + GST_FOURCC_ARGS (to_space)); + space->converter = lcs_find_converter (from_format, to_format, LCS_FLAG_FAST); if (space->converter) { - GST_DEBUG ("converting from %4.4s to %4.4s\n", (gchar*)&from_space, (gchar*)&to_space); - space->type = GST_COLORSPACE_LCS; + GST_DEBUG ("trying from " GST_FOURCC_FORMAT " to " GST_FOURCC_FORMAT, + GST_FOURCC_ARGS (from_space), + GST_FOURCC_ARGS (to_space)); + space->disabled = FALSE; return TRUE; } @@ -198,8 +236,9 @@ colorspace_setup_converter (GstColorspace *space, GstCaps *from_caps, GstCaps *t } static GstCaps* -gst_colorspace_getcaps (GstPad *pad, GstCaps *caps) +gst_colorspace_getcaps (GstPad *pad) { +#if unused GstColorspace *space; GstCaps *result; GstCaps *peercaps; @@ -216,113 +255,67 @@ gst_colorspace_getcaps (GstPad *pad, GstCaps *caps) result = gst_caps_prepend (ourcaps, peercaps); return result; +#endif + return gst_caps_copy (gst_pad_get_pad_template_caps (pad)); } static GstPadLinkReturn -gst_colorspace_sinkconnect (GstPad *pad, GstCaps *caps) +gst_colorspace_link (GstPad *pad, const GstCaps *caps) { + GstStructure *structure; + GstPad *otherpad; + GstCaps *othercaps; GstColorspace *space; - GstPad *peer; + int width; + int height; + double framerate; + GstPadLinkReturn ret; space = GST_COLORSPACE (gst_pad_get_parent (pad)); - if (!GST_CAPS_IS_FIXED (caps)) { - return GST_PAD_LINK_DELAYED; + otherpad = (pad == space->srcpad) ? space->sinkpad : space->srcpad; + + structure = gst_caps_get_structure (caps, 0); + + gst_structure_get_int (structure, "width", &width); + gst_structure_get_int (structure, "height", &height); + gst_structure_get_double (structure, "framerate", &framerate); + + ret = gst_pad_try_set_caps (otherpad, caps); + if (GST_PAD_LINK_SUCCESSFUL (ret)) { + /* passthrough */ + space->passthrough = TRUE; + return GST_PAD_LINK_OK; } + space->passthrough = FALSE; - gst_caps_get_int (caps, "width", &space->width); - gst_caps_get_int (caps, "height", &space->height); - gst_caps_get_float (caps, "framerate", &space->fps); + if (gst_pad_is_negotiated (otherpad)) { + othercaps = gst_caps_copy (gst_pad_get_negotiated_caps (otherpad)); - GST_INFO ( "size: %dx%d", space->width, space->height); + gst_caps_set_simple (othercaps, + "width", G_TYPE_INT, width, + "height", G_TYPE_INT, height, + "framerate", G_TYPE_DOUBLE, framerate, + NULL); - space->sinkcaps = caps; + ret = gst_pad_try_set_caps (otherpad, othercaps); + if (!GST_PAD_LINK_SUCCESSFUL (ret)) { + return ret; + } - peer = gst_pad_get_peer (pad); - if (peer) { - if (gst_colorspace_srcconnect_func (pad, gst_pad_get_allowed_caps (space->srcpad), FALSE) < 1) { - space->sinkcaps = NULL; + if (colorspace_setup_converter (space, caps, othercaps)) { + + space->width = width; + space->height = height; + space->framerate = framerate; + } else { return GST_PAD_LINK_REFUSED; } } - + return GST_PAD_LINK_OK; } -static GstPadLinkReturn -gst_colorspace_srcconnect (GstPad *pad, GstCaps *caps) -{ - return gst_colorspace_srcconnect_func (pad, caps, TRUE); -} - -static GstPadLinkReturn -gst_colorspace_srcconnect_func (GstPad *pad, GstCaps *caps, gboolean newcaps) -{ - GstColorspace *space; - GstCaps *peercaps; - GstCaps *ourcaps; - - space = GST_COLORSPACE (gst_pad_get_parent (pad)); - - /* we cannot operate if we didn't get src caps */ - ourcaps = space->sinkcaps; - if (!ourcaps) { - if (newcaps) - gst_pad_recalc_allowed_caps (space->sinkpad); - - return GST_PAD_LINK_DELAYED; - } - - /* first see if we can do the format natively by filtering the peer caps - * with our incomming caps */ - peercaps = gst_caps_intersect (caps, ourcaps); - if (peercaps) { - /* see if the peer likes it too, it should as the caps say so.. */ - if (gst_pad_try_set_caps (space->srcpad, peercaps) > 0) { - space->type = GST_COLORSPACE_NONE; - space->disabled = FALSE; - return GST_PAD_LINK_DONE; - } - } - /* then see what the peer has that matches the size */ - peercaps = gst_caps_intersect (caps, - gst_caps_append ( - GST_CAPS_NEW ( - "colorspace_filter", - "video/x-raw-yuv", - "width", GST_PROPS_INT (space->width), - "height", GST_PROPS_INT (space->height), - "framerate", GST_PROPS_FLOAT (space->fps) - ), GST_CAPS_NEW ( - "colorspace_filter", - "video/x-raw-rgb", - "width", GST_PROPS_INT (space->width), - "height", GST_PROPS_INT (space->height), - "framerate", GST_PROPS_FLOAT (space->fps) - ))); - - /* we are looping over the caps, so we have to get rid of the lists */ - peercaps = gst_caps_normalize (peercaps); - - /* loop over all possibilities and select the first one we can convert and - * is accepted by the peer */ - while (peercaps) { - if (colorspace_setup_converter (space, ourcaps, peercaps)) { - if (gst_pad_try_set_caps (space->srcpad, peercaps) > 0) { - space->disabled = FALSE; - return GST_PAD_LINK_DONE; - } - } - peercaps = peercaps->next; - } - - GST_ELEMENT_ERROR (space, CORE, NEGOTIATION, (NULL), (NULL)); - /* we disable ourself here */ - space->disabled = TRUE; - - return GST_PAD_LINK_REFUSED; -} - static GType gst_colorspace_get_type (void) { @@ -350,8 +343,10 @@ gst_colorspace_base_init (GstColorspaceClass *klass) { GstElementClass *element_class = GST_ELEMENT_CLASS (klass); - gst_element_class_add_pad_template (element_class, srctempl); - gst_element_class_add_pad_template (element_class, sinktempl); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_colorspace_src_template)); + gst_element_class_add_pad_template (element_class, + gst_static_pad_template_get (&gst_colorspace_sink_template)); gst_element_class_set_details (element_class, &colorspace_details); } @@ -375,18 +370,18 @@ gst_colorspace_class_init (GstColorspaceClass *klass) static void gst_colorspace_init (GstColorspace *space) { - space->sinkpad = gst_pad_new_from_template (sinktempl, "sink"); - gst_pad_set_link_function (space->sinkpad, gst_colorspace_sinkconnect); + space->sinkpad = gst_pad_new_from_template ( + gst_static_pad_template_get(&gst_colorspace_sink_template), "sink"); + gst_pad_set_link_function (space->sinkpad, gst_colorspace_link); gst_pad_set_getcaps_function (space->sinkpad, gst_colorspace_getcaps); - gst_pad_set_bufferpool_function (space->sinkpad, colorspace_get_bufferpool); gst_pad_set_chain_function(space->sinkpad,gst_colorspace_chain); gst_element_add_pad(GST_ELEMENT(space),space->sinkpad); - space->srcpad = gst_pad_new_from_template (srctempl, "src"); + space->srcpad = gst_pad_new_from_template ( + gst_static_pad_template_get(&gst_colorspace_src_template), "src"); gst_element_add_pad(GST_ELEMENT(space),space->srcpad); - gst_pad_set_link_function (space->srcpad, gst_colorspace_srcconnect); + gst_pad_set_link_function (space->srcpad, gst_colorspace_link); - space->pool = NULL; space->disabled = TRUE; } @@ -395,7 +390,7 @@ gst_colorspace_chain (GstPad *pad,GstData *_data) { GstBuffer *buf = GST_BUFFER (_data); GstColorspace *space; - GstBuffer *outbuf = NULL; + GstBuffer *outbuf; g_return_if_fail (pad != NULL); g_return_if_fail (GST_IS_PAD (pad)); @@ -406,39 +401,25 @@ gst_colorspace_chain (GstPad *pad,GstData *_data) g_return_if_fail (space != NULL); g_return_if_fail (GST_IS_COLORSPACE (space)); - if (space->disabled) { - gst_buffer_unref (buf); - return; - } - - if (space->type == GST_COLORSPACE_NONE) { + if (space->passthrough) { outbuf = buf; } else { - if (space->pool) { - outbuf = gst_buffer_new_from_pool (space->pool, 0, 0); - } + unsigned long size; - if (!outbuf) { - guint size; - outbuf = gst_buffer_new (); + lcs_format_buffer_size ( + lcs_converter_get_dest_format (space->converter), + space->width, space->height, &size); - lcs_format_buffer_size ( - lcs_convert_get_dest_format (space->converter), - space->width, space->height, &size); + outbuf = gst_pad_alloc_buffer (space->srcpad, GST_BUFFER_OFFSET_NONE, size); - GST_BUFFER_SIZE (outbuf) = size; - GST_BUFFER_DATA (outbuf) = g_malloc (size); - } - - if (space->type == GST_COLORSPACE_LCS) { - lcs_convert_auto (space->converter, - GST_BUFFER_DATA (buf), - GST_BUFFER_DATA (outbuf), - space->width, space->height); - } + lcs_convert_auto (space->converter, + GST_BUFFER_DATA (buf), + GST_BUFFER_DATA (outbuf), + space->width, space->height); GST_BUFFER_TIMESTAMP (outbuf) = GST_BUFFER_TIMESTAMP (buf); + GST_BUFFER_DURATION (outbuf) = GST_BUFFER_DURATION (buf); gst_buffer_unref (buf); } @@ -453,11 +434,7 @@ gst_colorspace_change_state (GstElement *element) space = GST_COLORSPACE (element); switch (GST_STATE_TRANSITION (element)) { - case GST_STATE_PAUSED_TO_PLAYING: - space->pool = gst_pad_get_bufferpool (space->srcpad); - break; - case GST_STATE_PLAYING_TO_PAUSED: - space->pool = NULL; + case GST_STATE_PAUSED_TO_READY: break; } @@ -500,45 +477,13 @@ gst_colorspace_get_property (GObject *object, guint prop_id, GValue *value, GPar static gboolean plugin_init (GstPlugin *plugin) { - GstCaps *caps; - lcs_init (NULL, NULL); - if (!gst_element_register (plugin, "colorspace", GST_RANK_NONE, - GST_TYPE_COLORSPACE)) - return FALSE; - - /* create caps for templates */ - caps = gst_caps_new ("csp_templ_yuv", - "video/x-raw-yuv", - GST_VIDEO_YUV_PAD_TEMPLATE_PROPS ( - GST_PROPS_LIST ( - GST_PROPS_FOURCC (GST_STR_FOURCC ("I420")), - GST_PROPS_FOURCC (GST_STR_FOURCC ("YV12")), - GST_PROPS_FOURCC (GST_STR_FOURCC ("YUY2"))))); - caps = gst_caps_append (caps, - gst_caps_new ("csp_templ_rgb24_32", - "video/x-raw-rgb", - GST_VIDEO_RGB_PAD_TEMPLATE_PROPS_24_32)); - caps = gst_caps_append (caps, - gst_caps_new ("csp_templ_rgb15_16", - "video/x-raw-rgb", - GST_VIDEO_RGB_PAD_TEMPLATE_PROPS_15_16)); - - /* build templates */ - srctempl = gst_pad_template_new ("src", - GST_PAD_SRC, - GST_PAD_ALWAYS, - caps, NULL); - gst_caps_ref (caps); - sinktempl = gst_pad_template_new ("sink", - GST_PAD_SINK, - GST_PAD_ALWAYS, - caps, NULL); - - return TRUE; + return gst_element_register (plugin, "lcscolorspace", GST_RANK_NONE, + GST_TYPE_COLORSPACE); } + GST_PLUGIN_DEFINE ( GST_VERSION_MAJOR, GST_VERSION_MINOR, @@ -547,7 +492,6 @@ GST_PLUGIN_DEFINE ( plugin_init, VERSION, "LGPL", - "(c) 2003 The LCS team", - "LCS", - "http://www.codecs.org/" + GST_PACKAGE, + GST_ORIGIN )