ext/ffmpeg/: Move palette handling over from the decoder to the colorspace conversion plugin (where you would expect ...

Original commit message from CVS:
* 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).
This commit is contained in:
Ronald S. Bultje 2004-10-02 14:10:27 +00:00
parent 7c945b8254
commit 79d1288887
4 changed files with 117 additions and 67 deletions

View file

@ -1,3 +1,14 @@
2004-10-02 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
* 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 <rbultje@ronald.bitfreak.net> 2004-10-01 Ronald S. Bultje <rbultje@ronald.bitfreak.net>
* ext/ffmpeg/gstffmpegcodecmap.c: (gst_ffmpeg_codecid_to_caps), * ext/ffmpeg/gstffmpegcodecmap.c: (gst_ffmpeg_codecid_to_caps),

View file

@ -783,19 +783,33 @@ gst_ffmpeg_pixfmt_to_caps (enum PixelFormat pix_fmt, AVCodecContext * context)
g_mask = 0x03e0; g_mask = 0x03e0;
b_mask = 0x001f; b_mask = 0x001f;
break; break;
case PIX_FMT_PAL8:
bpp = depth = 8;
endianness = G_BYTE_ORDER;
break;
default: default:
/* give up ... */ /* give up ... */
break; break;
} }
if (bpp != 0) { if (bpp != 0) {
caps = GST_FF_VID_CAPS_NEW ("video/x-raw-rgb", if (r_mask != 0) {
"bpp", G_TYPE_INT, bpp, caps = GST_FF_VID_CAPS_NEW ("video/x-raw-rgb",
"depth", G_TYPE_INT, depth, "bpp", G_TYPE_INT, bpp,
"red_mask", G_TYPE_INT, r_mask, "depth", G_TYPE_INT, depth,
"green_mask", G_TYPE_INT, g_mask, "red_mask", G_TYPE_INT, r_mask,
"blue_mask", G_TYPE_INT, b_mask, "green_mask", G_TYPE_INT, g_mask,
"endianness", G_TYPE_INT, endianness, NULL); "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) { } else if (fmt) {
caps = GST_FF_VID_CAPS_NEW ("video/x-raw-yuv", caps = GST_FF_VID_CAPS_NEW ("video/x-raw-yuv",
"format", GST_TYPE_FOURCC, fmt, NULL); "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; gint bpp = 0, rmask = 0, endianness = 0;
if (gst_structure_get_int (structure, "bpp", &bpp) && if (gst_structure_get_int (structure, "bpp", &bpp) &&
gst_structure_get_int (structure, "endianness", &endianness) && gst_structure_get_int (structure, "endianness", &endianness)) {
gst_structure_get_int (structure, "red_mask", &rmask)) { if (gst_structure_get_int (structure, "red_mask", &rmask)) {
switch (bpp) { switch (bpp) {
case 32: case 32:
#if (G_BYTE_ORDER == G_BIG_ENDIAN) #if (G_BYTE_ORDER == G_BIG_ENDIAN)
if (rmask == 0x00ff0000) if (rmask == 0x00ff0000)
#else #else
if (rmask == 0x0000ff00) if (rmask == 0x0000ff00)
#endif #endif
context->pix_fmt = PIX_FMT_RGBA32; context->pix_fmt = PIX_FMT_RGBA32;
break; break;
case 24: case 24:
if (rmask == 0x0000FF) if (rmask == 0x0000FF)
context->pix_fmt = PIX_FMT_BGR24; context->pix_fmt = PIX_FMT_BGR24;
else else
context->pix_fmt = PIX_FMT_RGB24; context->pix_fmt = PIX_FMT_RGB24;
break; break;
case 16: case 16:
if (endianness == G_BYTE_ORDER) if (endianness == G_BYTE_ORDER)
context->pix_fmt = PIX_FMT_RGB565; context->pix_fmt = PIX_FMT_RGB565;
break; break;
case 15: case 15:
if (endianness == G_BYTE_ORDER) if (endianness == G_BYTE_ORDER)
context->pix_fmt = PIX_FMT_RGB555; context->pix_fmt = PIX_FMT_RGB555;
break; break;
default: default:
/* nothing */ /* nothing */
break; break;
}
} else {
if (bpp == 8) {
context->pix_fmt = PIX_FMT_PAL8;
gst_ffmpeg_get_palette (caps, context);
}
} }
} }
} }

View file

@ -56,6 +56,7 @@ struct _GstFFMpegCsp
gfloat fps; gfloat fps;
enum PixelFormat from_pixfmt, to_pixfmt; enum PixelFormat from_pixfmt, to_pixfmt;
AVFrame *from_frame, *to_frame; AVFrame *from_frame, *to_frame;
AVPaletteControl *palette;
GstCaps *sinkcaps; GstCaps *sinkcaps;
}; };
@ -227,6 +228,11 @@ gst_ffmpegcsp_pad_link (GstPad * pad, const GstCaps * caps)
space->to_pixfmt = ctx->pix_fmt; space->to_pixfmt = ctx->pix_fmt;
} else { } else {
space->from_pixfmt = ctx->pix_fmt; space->from_pixfmt = ctx->pix_fmt;
/* palette */
if (space->palette)
av_free (space->palette);
space->palette = ctx->palctrl;
} }
av_free (ctx); av_free (ctx);
if (space->from_frame) if (space->from_frame)
@ -311,6 +317,7 @@ gst_ffmpegcsp_init (GstFFMpegCsp * space)
space->from_pixfmt = space->to_pixfmt = PIX_FMT_NB; space->from_pixfmt = space->to_pixfmt = PIX_FMT_NB;
space->from_frame = space->to_frame = NULL; space->from_frame = space->to_frame = NULL;
space->palette = NULL;
} }
static void static void
@ -344,25 +351,54 @@ gst_ffmpegcsp_chain (GstPad * pad, GstData * data)
if (space->from_pixfmt == space->to_pixfmt) { if (space->from_pixfmt == space->to_pixfmt) {
outbuf = inbuf; outbuf = inbuf;
} else { } 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, guint size = avpicture_get_size (space->to_pixfmt,
space->width, space->width, space->height);
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); outbuf = gst_pad_alloc_buffer (space->srcpad, GST_BUFFER_OFFSET_NONE, size);
/* convert */ /* convert */
avpicture_fill ((AVPicture *) space->from_frame, GST_BUFFER_DATA (inbuf), avpicture_fill ((AVPicture *) space->from_frame, GST_BUFFER_DATA (inbuf2),
space->from_pixfmt, space->width, space->height); from_pixfmt, space->width, space->height);
avpicture_fill ((AVPicture *) space->to_frame, GST_BUFFER_DATA (outbuf), avpicture_fill ((AVPicture *) space->to_frame, GST_BUFFER_DATA (outbuf),
space->to_pixfmt, space->width, space->height); space->to_pixfmt, space->width, space->height);
img_convert ((AVPicture *) space->to_frame, space->to_pixfmt, 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); space->width, space->height);
GST_BUFFER_TIMESTAMP (outbuf) = GST_BUFFER_TIMESTAMP (inbuf); GST_BUFFER_TIMESTAMP (outbuf) = GST_BUFFER_TIMESTAMP (inbuf);
GST_BUFFER_DURATION (outbuf) = GST_BUFFER_DURATION (inbuf); GST_BUFFER_DURATION (outbuf) = GST_BUFFER_DURATION (inbuf);
if (inbuf != inbuf2)
gst_buffer_unref (inbuf2);
gst_buffer_unref (inbuf); gst_buffer_unref (inbuf);
} }
@ -382,8 +418,11 @@ gst_ffmpegcsp_change_state (GstElement * element)
av_free (space->from_frame); av_free (space->from_frame);
if (space->to_frame) if (space->to_frame)
av_free (space->to_frame); av_free (space->to_frame);
if (space->palette)
av_free (space->palette);
space->from_frame = NULL; space->from_frame = NULL;
space->to_frame = NULL; space->to_frame = NULL;
space->palette = NULL;
break; break;
} }
@ -437,6 +476,8 @@ gst_ffmpegcsp_register (GstPlugin * plugin)
/* build templates */ /* build templates */
srctempl = gst_pad_template_new ("src", srctempl = gst_pad_template_new ("src",
GST_PAD_SRC, GST_PAD_ALWAYS, gst_caps_copy (caps)); 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); sinktempl = gst_pad_template_new ("sink", GST_PAD_SINK, GST_PAD_ALWAYS, caps);
return gst_element_register (plugin, "ffcolorspace", return gst_element_register (plugin, "ffcolorspace",

View file

@ -409,40 +409,18 @@ gst_ffmpegdec_chain (GstPad * pad, GstData * _data)
* errors inside. This drives me crazy, so we let it allocate * errors inside. This drives me crazy, so we let it allocate
* it's own buffers and copy to our own buffer afterwards... */ * it's own buffers and copy to our own buffer afterwards... */
AVPicture pic; AVPicture pic;
enum PixelFormat to_fmt = gint size = avpicture_get_size (ffmpegdec->context->pix_fmt,
(ffmpegdec->context->pix_fmt == PIX_FMT_PAL8) ?
PIX_FMT_RGBA32 : ffmpegdec->context->pix_fmt;
gint size = avpicture_get_size (to_fmt,
ffmpegdec->context->width, ffmpegdec->context->width,
ffmpegdec->context->height); ffmpegdec->context->height);
outbuf = gst_buffer_new_and_alloc (size); 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); 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 */ /* note that ffmpeg sometimes gets the FPS wrong */
if (GST_CLOCK_TIME_IS_VALID (expected_ts)) { if (GST_CLOCK_TIME_IS_VALID (expected_ts)) {