Commit 79d12888 authored by Ronald S. Bultje's avatar Ronald S. Bultje

ext/ffmpeg/: Move palette handling over from the decoder to the colorspace...

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).
parent 7c945b82
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>
* ext/ffmpeg/gstffmpegcodecmap.c: (gst_ffmpeg_codecid_to_caps),
......
......@@ -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);
}
}
}
}
......
......@@ -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",
......
......@@ -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)) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment