diff --git a/ChangeLog b/ChangeLog index e5b37e65b9..0f0318a29f 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,14 @@ +2004-10-02 Ronald S. Bultje + + * ext/ffmpeg/gstffmpegcodecmap.c: (gst_ffmpeg_pixfmt_to_caps), + (gst_ffmpeg_caps_to_pixfmt): + * ext/ffmpeg/gstffmpegcolorspace.c: (gst_ffmpegcsp_pad_link), + (gst_ffmpegcsp_init), (gst_ffmpegcsp_chain), + (gst_ffmpegcsp_change_state), (gst_ffmpegcsp_register): + * ext/ffmpeg/gstffmpegdec.c: (gst_ffmpegdec_chain): + Move palette handling over from the decoder to the colorspace + conversion plugin (where you would expect it). + 2004-10-01 Ronald S. Bultje * ext/ffmpeg/gstffmpegcodecmap.c: (gst_ffmpeg_codecid_to_caps), diff --git a/ext/ffmpeg/gstffmpegcodecmap.c b/ext/ffmpeg/gstffmpegcodecmap.c index efaac09d30..67987ac142 100644 --- a/ext/ffmpeg/gstffmpegcodecmap.c +++ b/ext/ffmpeg/gstffmpegcodecmap.c @@ -783,19 +783,33 @@ gst_ffmpeg_pixfmt_to_caps (enum PixelFormat pix_fmt, AVCodecContext * context) g_mask = 0x03e0; b_mask = 0x001f; break; + case PIX_FMT_PAL8: + bpp = depth = 8; + endianness = G_BYTE_ORDER; + break; default: /* give up ... */ break; } if (bpp != 0) { - caps = GST_FF_VID_CAPS_NEW ("video/x-raw-rgb", - "bpp", G_TYPE_INT, bpp, - "depth", G_TYPE_INT, depth, - "red_mask", G_TYPE_INT, r_mask, - "green_mask", G_TYPE_INT, g_mask, - "blue_mask", G_TYPE_INT, b_mask, - "endianness", G_TYPE_INT, endianness, NULL); + if (r_mask != 0) { + caps = GST_FF_VID_CAPS_NEW ("video/x-raw-rgb", + "bpp", G_TYPE_INT, bpp, + "depth", G_TYPE_INT, depth, + "red_mask", G_TYPE_INT, r_mask, + "green_mask", G_TYPE_INT, g_mask, + "blue_mask", G_TYPE_INT, b_mask, + "endianness", G_TYPE_INT, endianness, NULL); + } else { + caps = GST_FF_VID_CAPS_NEW ("video/x-raw-rgb", + "bpp", G_TYPE_INT, bpp, + "depth", G_TYPE_INT, depth, + "endianness", G_TYPE_INT, endianness, NULL); + if (context) { + gst_ffmpeg_set_palette (caps, context); + } + } } else if (fmt) { caps = GST_FF_VID_CAPS_NEW ("video/x-raw-yuv", "format", GST_TYPE_FOURCC, fmt, NULL); @@ -1012,34 +1026,40 @@ gst_ffmpeg_caps_to_pixfmt (const GstCaps * caps, gint bpp = 0, rmask = 0, endianness = 0; if (gst_structure_get_int (structure, "bpp", &bpp) && - gst_structure_get_int (structure, "endianness", &endianness) && - gst_structure_get_int (structure, "red_mask", &rmask)) { - switch (bpp) { - case 32: + gst_structure_get_int (structure, "endianness", &endianness)) { + if (gst_structure_get_int (structure, "red_mask", &rmask)) { + switch (bpp) { + case 32: #if (G_BYTE_ORDER == G_BIG_ENDIAN) - if (rmask == 0x00ff0000) + if (rmask == 0x00ff0000) #else - if (rmask == 0x0000ff00) + if (rmask == 0x0000ff00) #endif - context->pix_fmt = PIX_FMT_RGBA32; - break; - case 24: - if (rmask == 0x0000FF) - context->pix_fmt = PIX_FMT_BGR24; - else - context->pix_fmt = PIX_FMT_RGB24; - break; - case 16: - if (endianness == G_BYTE_ORDER) - context->pix_fmt = PIX_FMT_RGB565; - break; - case 15: - if (endianness == G_BYTE_ORDER) - context->pix_fmt = PIX_FMT_RGB555; - break; - default: - /* nothing */ - break; + context->pix_fmt = PIX_FMT_RGBA32; + break; + case 24: + if (rmask == 0x0000FF) + context->pix_fmt = PIX_FMT_BGR24; + else + context->pix_fmt = PIX_FMT_RGB24; + break; + case 16: + if (endianness == G_BYTE_ORDER) + context->pix_fmt = PIX_FMT_RGB565; + break; + case 15: + if (endianness == G_BYTE_ORDER) + context->pix_fmt = PIX_FMT_RGB555; + break; + default: + /* nothing */ + break; + } + } else { + if (bpp == 8) { + context->pix_fmt = PIX_FMT_PAL8; + gst_ffmpeg_get_palette (caps, context); + } } } } diff --git a/ext/ffmpeg/gstffmpegcolorspace.c b/ext/ffmpeg/gstffmpegcolorspace.c index 3f3d2e1fa0..43b17c41ec 100644 --- a/ext/ffmpeg/gstffmpegcolorspace.c +++ b/ext/ffmpeg/gstffmpegcolorspace.c @@ -56,6 +56,7 @@ struct _GstFFMpegCsp gfloat fps; enum PixelFormat from_pixfmt, to_pixfmt; AVFrame *from_frame, *to_frame; + AVPaletteControl *palette; GstCaps *sinkcaps; }; @@ -227,6 +228,11 @@ gst_ffmpegcsp_pad_link (GstPad * pad, const GstCaps * caps) space->to_pixfmt = ctx->pix_fmt; } else { space->from_pixfmt = ctx->pix_fmt; + + /* palette */ + if (space->palette) + av_free (space->palette); + space->palette = ctx->palctrl; } av_free (ctx); if (space->from_frame) @@ -311,6 +317,7 @@ gst_ffmpegcsp_init (GstFFMpegCsp * space) space->from_pixfmt = space->to_pixfmt = PIX_FMT_NB; space->from_frame = space->to_frame = NULL; + space->palette = NULL; } static void @@ -344,25 +351,54 @@ gst_ffmpegcsp_chain (GstPad * pad, GstData * data) if (space->from_pixfmt == space->to_pixfmt) { outbuf = inbuf; } else { - /* use bufferpool here */ + enum PixelFormat from_pixfmt = + (space->from_pixfmt == PIX_FMT_PAL8) ? + PIX_FMT_RGBA32 : space->from_pixfmt; guint size = avpicture_get_size (space->to_pixfmt, - space->width, - space->height); + space->width, space->height); + GstBuffer *inbuf2; + + if (from_pixfmt != space->from_pixfmt) { + /* manual conversion from palette to RGBA32 */ + gint x, y, pix, wd = space->width; + guint8 *dest; + guint32 conv; + AVPaletteControl *pal = space->palette; + + inbuf2 = gst_buffer_new_and_alloc (4 * + space->width * space->height); + dest = GST_BUFFER_DATA (inbuf2); + + for (y = 0; y < space->height; y++) { + for (x = 0; x < space->width; x++) { + pix = GST_BUFFER_DATA (inbuf)[y * wd + x]; + conv = pal->palette[pix]; + dest[(y * wd + x) * 4] = ((guint8 *) &conv)[0]; + dest[(y * wd + x) * 4 + 1] = ((guint8 *) &conv)[1]; + dest[(y * wd + x) * 4 + 2] = ((guint8 *) &conv)[2]; + dest[(y * wd + x) * 4 + 3] = ((guint8 *) &conv)[3]; + } + } + } else { + inbuf2 = inbuf; + } outbuf = gst_pad_alloc_buffer (space->srcpad, GST_BUFFER_OFFSET_NONE, size); /* convert */ - avpicture_fill ((AVPicture *) space->from_frame, GST_BUFFER_DATA (inbuf), - space->from_pixfmt, space->width, space->height); + avpicture_fill ((AVPicture *) space->from_frame, GST_BUFFER_DATA (inbuf2), + from_pixfmt, space->width, space->height); avpicture_fill ((AVPicture *) space->to_frame, GST_BUFFER_DATA (outbuf), space->to_pixfmt, space->width, space->height); img_convert ((AVPicture *) space->to_frame, space->to_pixfmt, - (AVPicture *) space->from_frame, space->from_pixfmt, + (AVPicture *) space->from_frame, from_pixfmt, space->width, space->height); GST_BUFFER_TIMESTAMP (outbuf) = GST_BUFFER_TIMESTAMP (inbuf); GST_BUFFER_DURATION (outbuf) = GST_BUFFER_DURATION (inbuf); + if (inbuf != inbuf2) + gst_buffer_unref (inbuf2); gst_buffer_unref (inbuf); } @@ -382,8 +418,11 @@ gst_ffmpegcsp_change_state (GstElement * element) av_free (space->from_frame); if (space->to_frame) av_free (space->to_frame); + if (space->palette) + av_free (space->palette); space->from_frame = NULL; space->to_frame = NULL; + space->palette = NULL; break; } @@ -437,6 +476,8 @@ gst_ffmpegcsp_register (GstPlugin * plugin) /* build templates */ srctempl = gst_pad_template_new ("src", GST_PAD_SRC, GST_PAD_ALWAYS, gst_caps_copy (caps)); + + /* the sink template will do palette handling as well... */ sinktempl = gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, caps); return gst_element_register (plugin, "ffcolorspace", diff --git a/ext/ffmpeg/gstffmpegdec.c b/ext/ffmpeg/gstffmpegdec.c index 8076d58098..272f2e3b4c 100644 --- a/ext/ffmpeg/gstffmpegdec.c +++ b/ext/ffmpeg/gstffmpegdec.c @@ -409,40 +409,18 @@ gst_ffmpegdec_chain (GstPad * pad, GstData * _data) * errors inside. This drives me crazy, so we let it allocate * it's own buffers and copy to our own buffer afterwards... */ AVPicture pic; - enum PixelFormat to_fmt = - (ffmpegdec->context->pix_fmt == PIX_FMT_PAL8) ? - PIX_FMT_RGBA32 : ffmpegdec->context->pix_fmt; - gint size = avpicture_get_size (to_fmt, + gint size = avpicture_get_size (ffmpegdec->context->pix_fmt, ffmpegdec->context->width, ffmpegdec->context->height); outbuf = gst_buffer_new_and_alloc (size); - avpicture_fill (&pic, GST_BUFFER_DATA (outbuf), to_fmt, + avpicture_fill (&pic, GST_BUFFER_DATA (outbuf), + ffmpegdec->context->pix_fmt, + ffmpegdec->context->width, ffmpegdec->context->height); + img_convert (&pic, ffmpegdec->context->pix_fmt, + (AVPicture *) ffmpegdec->picture, + ffmpegdec->context->pix_fmt, ffmpegdec->context->width, ffmpegdec->context->height); - if (to_fmt == ffmpegdec->context->pix_fmt) { - img_convert (&pic, ffmpegdec->context->pix_fmt, - (AVPicture *) ffmpegdec->picture, - ffmpegdec->context->pix_fmt, - ffmpegdec->context->width, ffmpegdec->context->height); - } else { - /* manual conversion from palette to RGBA32 */ - gint x, y, pix, ws = ffmpegdec->picture->linesize[0], - wd = ffmpegdec->context->width; - guint8 *dest = GST_BUFFER_DATA (outbuf); - guint32 conv; - AVPaletteControl *pal = ffmpegdec->context->palctrl; - - for (y = 0; y < ffmpegdec->context->height; y++) { - for (x = 0; x < ffmpegdec->context->width; x++) { - pix = ffmpegdec->picture->data[0][y * ws + x]; - conv = pal->palette[pix]; - dest[(y * wd + x) * 4] = ((guint8 *) &conv)[0]; - dest[(y * wd + x) * 4 + 1] = ((guint8 *) &conv)[1]; - dest[(y * wd + x) * 4 + 2] = ((guint8 *) &conv)[2]; - dest[(y * wd + x) * 4 + 3] = ((guint8 *) &conv)[3]; - } - } - } /* note that ffmpeg sometimes gets the FPS wrong */ if (GST_CLOCK_TIME_IS_VALID (expected_ts)) {