From db93fd53ad6a2c53c4a22b79fe6520df5463133e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Fri, 18 Feb 2005 10:38:34 +0000 Subject: [PATCH] Fix rowstrides Original commit message from CVS: Fix rowstrides --- ChangeLog | 6 ++++++ ext/jpeg/gstjpegdec.c | 49 +++++++++++++++++++++++-------------------- ext/jpeg/gstjpegenc.c | 46 +++++++++++++++++++++++++++------------- 3 files changed, 63 insertions(+), 38 deletions(-) diff --git a/ChangeLog b/ChangeLog index 5dd1dc788c..fa9f164eef 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,9 @@ +2005-02-18 Tim-Philipp Müller + + * ext/jpeg/gstjpegdec.c: (gst_jpegdec_chain): + * ext/jpeg/gstjpegenc.c: (gst_jpegenc_resync), (gst_jpegenc_chain): + Use same rowstrides for I420 as used everywhere else. + 2005-02-17 Tim-Philipp Müller * gst/avi/gstavidemux.c: (gst_avi_demux_invert): diff --git a/ext/jpeg/gstjpegdec.c b/ext/jpeg/gstjpegdec.c index bfc5881fba..7c26f61c40 100644 --- a/ext/jpeg/gstjpegdec.c +++ b/ext/jpeg/gstjpegdec.c @@ -37,18 +37,24 @@ GstElementDetails gst_jpegdec_details = { GST_DEBUG_CATEGORY (jpegdec_debug); #define GST_CAT_DEFAULT jpegdec_debug -/* JpegDec signals and args */ -enum -{ - /* FILL ME */ - LAST_SIGNAL -}; -enum -{ - ARG_0 - /* FILL ME */ -}; +/* These macros are adapted from videotestsrc.c + * and/or gst-plugins/gst/games/gstvideoimage.c */ +#define ROUND_UP_2(x) (((x)+1)&~1) +#define ROUND_UP_4(x) (((x)+3)&~3) +#define ROUND_UP_8(x) (((x)+7)&~7) + +/* I420 */ +#define I420_Y_ROWSTRIDE(width) (ROUND_UP_4(width)) +#define I420_U_ROWSTRIDE(width) (ROUND_UP_8(width)/2) +#define I420_V_ROWSTRIDE(width) ((ROUND_UP_8(I420_Y_ROWSTRIDE(width)))/2) + +#define I420_Y_OFFSET(w,h) (0) +#define I420_U_OFFSET(w,h) (I420_Y_OFFSET(w,h)+(I420_Y_ROWSTRIDE(w)*ROUND_UP_2(h))) +#define I420_V_OFFSET(w,h) (I420_U_OFFSET(w,h)+(I420_U_ROWSTRIDE(w)*ROUND_UP_2(h)/2)) + +#define I420_SIZE(w,h) (I420_V_OFFSET(w,h)+(I420_V_ROWSTRIDE(w)*ROUND_UP_2(h)/2)) + static void gst_jpegdec_base_init (gpointer g_class); static void gst_jpegdec_class_init (GstJpegDec * klass); @@ -375,7 +381,7 @@ gst_jpegdec_chain (GstPad * pad, GstData * _data) GstBuffer *outbuf; /*GstMeta *meta; */ - gint width, height, width2; + gint width, height; guchar *base[3]; gint i, j, k; gint r_h, r_v; @@ -443,7 +449,7 @@ gst_jpegdec_chain (GstPad * pad, GstData * _data) /* FIXME: someone needs to do the work to figure out how to correctly * calculate an output size that takes into account everything libjpeg * needs, like padding for DCT size and so on. */ - outsize = width * height + width * height / 2; + outsize = I420_SIZE (width, height); outbuf = gst_pad_alloc_buffer (jpegdec->srcpad, GST_BUFFER_OFFSET_NONE, outsize); outdata = GST_BUFFER_DATA (outbuf); @@ -453,28 +459,25 @@ gst_jpegdec_chain (GstPad * pad, GstData * _data) height, outsize); /* mind the swap, jpeglib outputs blue chroma first */ - /* FIXME: this needs stride love */ - base[0] = outdata; - base[1] = base[0] + width * height; - base[2] = base[1] + width * height / 4; - - width2 = width >> 1; + base[0] = outdata + I420_Y_OFFSET (width, height); + base[1] = outdata + I420_U_OFFSET (width, height); + base[2] = outdata + I420_V_OFFSET (width, height); GST_LOG_OBJECT (jpegdec, "decompressing %u", jpegdec->cinfo.rec_outbuf_height); for (i = 0; i < height; i += r_v * DCTSIZE) { for (j = 0, k = 0; j < (r_v * DCTSIZE); j += r_v, k++) { jpegdec->line[0][j] = base[0]; - base[0] += width; + base[0] += I420_Y_ROWSTRIDE (width); if (r_v == 2) { jpegdec->line[0][j + 1] = base[0]; - base[0] += width; + base[0] += I420_Y_ROWSTRIDE (width); } jpegdec->line[1][k] = base[1]; jpegdec->line[2][k] = base[2]; if (r_v == 2 || k & 1) { - base[1] += width2; - base[2] += width2; + base[1] += I420_U_ROWSTRIDE (width); + base[2] += I420_V_ROWSTRIDE (width); } } /*g_print ("%d\n", jpegdec->cinfo.output_scanline); */ diff --git a/ext/jpeg/gstjpegenc.c b/ext/jpeg/gstjpegenc.c index ffce61f39a..ca0e07f033 100644 --- a/ext/jpeg/gstjpegenc.c +++ b/ext/jpeg/gstjpegenc.c @@ -39,6 +39,23 @@ GST_DEBUG_CATEGORY (jpegenc_debug); #define JPEG_DEFAULT_QUALITY 85 +/* These macros are adapted from videotestsrc.c + * and/or gst-plugins/gst/games/gstvideoimage.c */ +#define ROUND_UP_2(x) (((x)+1)&~1) +#define ROUND_UP_4(x) (((x)+3)&~3) +#define ROUND_UP_8(x) (((x)+7)&~7) + +/* I420 */ +#define I420_Y_ROWSTRIDE(width) (ROUND_UP_4(width)) +#define I420_U_ROWSTRIDE(width) (ROUND_UP_8(width)/2) +#define I420_V_ROWSTRIDE(width) ((ROUND_UP_8(I420_Y_ROWSTRIDE(width)))/2) + +#define I420_Y_OFFSET(w,h) (0) +#define I420_U_OFFSET(w,h) (I420_Y_OFFSET(w,h)+(I420_Y_ROWSTRIDE(w)*ROUND_UP_2(h))) +#define I420_V_OFFSET(w,h) (I420_U_OFFSET(w,h)+(I420_U_ROWSTRIDE(w)*ROUND_UP_2(h)/2)) + +#define I420_SIZE(w,h) (I420_V_OFFSET(w,h)+(I420_V_ROWSTRIDE(w)*ROUND_UP_2(h)/2)) + /* JpegEnc signals and args */ enum { @@ -291,7 +308,6 @@ gst_jpegenc_link (GstPad * pad, const GstCaps * caps) static void gst_jpegenc_resync (GstJpegEnc * jpegenc) { - guint size = 0; gint width, height; GST_DEBUG ("gst_jpegenc_resync: resync"); @@ -311,14 +327,14 @@ gst_jpegenc_resync (GstJpegEnc * jpegenc) #if 0 switch (jpegenc->format) { case GST_COLORSPACE_RGB24: - size = 3; + jpegenc->bufsize = jpegenc->width * jpegenc->height * 3; GST_DEBUG ("gst_jpegenc_resync: setting format to RGB24"); jpegenc->cinfo.in_color_space = JCS_RGB; jpegenc->cinfo.raw_data_in = FALSE; break; case GST_COLORSPACE_YUV420P: #endif - size = 2; + jpegenc->bufsize = I420_SIZE (jpegenc->width, jpegenc->height); jpegenc->cinfo.raw_data_in = TRUE; jpegenc->cinfo.in_color_space = JCS_YCbCr; GST_DEBUG ("gst_jpegenc_resync: setting format to YUV420P"); @@ -343,12 +359,11 @@ gst_jpegenc_resync (GstJpegEnc * jpegenc) break; default: printf ("gst_jpegenc_resync: unsupported colorspace, using RGB\n"); - size = 3; + jpegenc->bufsize = jpegenc->width * jpegenc->height * 3; jpegenc->cinfo.in_color_space = JCS_RGB; break; } #endif - jpegenc->bufsize = jpegenc->width * jpegenc->height * size; jpeg_suppress_tables (&jpegenc->cinfo, TRUE); //jpeg_suppress_tables(&jpegenc->cinfo, FALSE); @@ -367,7 +382,7 @@ gst_jpegenc_chain (GstPad * pad, GstData * _data) GstBuffer *outbuf; /* GstMeta *meta; */ - guint height, width, width2; + guint height, width; guchar *base[3]; gint i, j, k; @@ -394,9 +409,9 @@ gst_jpegenc_chain (GstPad * pad, GstData * _data) width = jpegenc->width; height = jpegenc->height; - base[0] = data; - base[1] = base[0] + width * height; - base[2] = base[1] + width * height / 4; + base[0] = data + I420_Y_OFFSET (width, height); + base[1] = data + I420_U_OFFSET (width, height); + base[2] = data + I420_V_OFFSET (width, height); jpegenc->jdest.next_output_byte = outdata; jpegenc->jdest.free_in_buffer = outsize; @@ -405,22 +420,23 @@ gst_jpegenc_chain (GstPad * pad, GstData * _data) jpeg_set_quality (&jpegenc->cinfo, jpegenc->quality, TRUE); jpeg_start_compress (&jpegenc->cinfo, TRUE); - width2 = width >> 1; GST_DEBUG ("gst_jpegdec_chain: compressing"); for (i = 0; i < height; i += 2 * DCTSIZE) { - for (j = 0, k = 0; j < 2 * DCTSIZE; j += 2, k++) { + /*g_print ("next scanline: %d\n", jpegenc->cinfo.next_scanline); */ + for (j = 0, k = 0; j < (2 * DCTSIZE); j += 2, k++) { jpegenc->line[0][j] = base[0]; - base[0] += width; + base[0] += I420_Y_ROWSTRIDE (width); jpegenc->line[0][j + 1] = base[0]; - base[0] += width; + base[0] += I420_Y_ROWSTRIDE (width); jpegenc->line[1][k] = base[1]; - base[1] += width2; + base[1] += I420_U_ROWSTRIDE (width); jpegenc->line[2][k] = base[2]; - base[2] += width2; + base[2] += I420_V_ROWSTRIDE (width); } jpeg_write_raw_data (&jpegenc->cinfo, jpegenc->line, 2 * DCTSIZE); } + jpeg_finish_compress (&jpegenc->cinfo); GST_DEBUG ("gst_jpegdec_chain: compressing done");