summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiguel Freitas <miguelfreitas@users.sourceforge.net>2003-05-31 13:54:27 +0000
committerMiguel Freitas <miguelfreitas@users.sourceforge.net>2003-05-31 13:54:27 +0000
commit0306990681bdf214741c6ab2798b47bf8e578c97 (patch)
treef43a27309afe964044303c90b09cef5335ef9ae7
parent3228b320ac0c2c46d695a7ac2913db1ff74eb0ba (diff)
downloadxine-lib-0306990681bdf214741c6ab2798b47bf8e578c97.tar.gz
xine-lib-0306990681bdf214741c6ab2798b47bf8e578c97.tar.bz2
provide yv12 to yuy2 conversion
CVS patchset: 4993 CVS date: 2003/05/31 13:54:27
-rw-r--r--src/xine-utils/color.c145
-rw-r--r--src/xine-utils/xineutils.h8
2 files changed, 151 insertions, 2 deletions
diff --git a/src/xine-utils/color.c b/src/xine-utils/color.c
index 7c81217cf..89cc0448f 100644
--- a/src/xine-utils/color.c
+++ b/src/xine-utils/color.c
@@ -61,7 +61,7 @@
* instructions), these macros will automatically map to those special
* instructions.
*
- * $Id: color.c,v 1.14 2003/02/02 06:07:20 tmmm Exp $
+ * $Id: color.c,v 1.15 2003/05/31 13:54:27 miguelfreitas Exp $
*/
#include "xine_internal.h"
@@ -142,6 +142,13 @@ void (*yuv411_to_yv12)
unsigned char *u_src, int u_src_pitch, unsigned char *u_dest, int u_dest_pitch,
unsigned char *v_src, int v_src_pitch, unsigned char *v_dest, int v_dest_pitch,
int width, int height);
+void (*yv12_to_yuy2)
+ (unsigned char *y_src, int y_src_pitch,
+ unsigned char *u_src, int u_src_pitch,
+ unsigned char *v_src, int v_src_pitch,
+ unsigned char *yuy2_map, int yuy2_pitch,
+ int width, int height);
+
/*
* init_yuv_planes
@@ -647,6 +654,136 @@ void yuv411_to_yv12_c
}
+#define C_YUV420_YUYV( ) \
+ *(p_line1)++ = *(p_y1)++; *(p_line2)++ = *(p_y2)++; \
+ *(p_line1)++ = *(p_line2)++ = *(p_u)++; \
+ *(p_line1)++ = *(p_y1)++; *(p_line2)++ = *(p_y2)++; \
+ *(p_line1)++ = *(p_line2)++ = *(p_v)++; \
+
+/*****************************************************************************
+ * I420_YUY2: planar YUV 4:2:0 to packed YUYV 4:2:2
+ * conversion routine from Videolan project
+ *****************************************************************************/
+void yv12_to_yuy2_c
+ (unsigned char *y_src, int y_src_pitch,
+ unsigned char *u_src, int u_src_pitch,
+ unsigned char *v_src, int v_src_pitch,
+ unsigned char *yuy2_map, int yuy2_pitch,
+ int width, int height) {
+
+ uint8_t *p_line1, *p_line2 = yuy2_map;
+ uint8_t *p_y1, *p_y2 = y_src;
+ uint8_t *p_u = u_src;
+ uint8_t *p_v = v_src;
+
+ int i_x, i_y;
+
+ const int i_source_margin = y_src_pitch - width;
+ const int i_source_u_margin = u_src_pitch - width/2;
+ const int i_source_v_margin = v_src_pitch - width/2;
+ const int i_dest_margin = yuy2_pitch - width*2;
+
+ for( i_y = height / 2 ; i_y-- ; )
+ {
+ p_line1 = p_line2;
+ p_line2 += yuy2_pitch;
+
+ p_y1 = p_y2;
+ p_y2 += y_src_pitch;
+
+ for( i_x = width / 8 ; i_x-- ; )
+ {
+ C_YUV420_YUYV( );
+ C_YUV420_YUYV( );
+ C_YUV420_YUYV( );
+ C_YUV420_YUYV( );
+ }
+
+ p_y1 += i_source_margin;
+ p_y2 += i_source_margin;
+ p_u += i_source_u_margin;
+ p_v += i_source_v_margin;
+ p_line1 += i_dest_margin;
+ p_line2 += i_dest_margin;
+ }
+}
+
+#ifdef ARCH_X86
+
+#define MMX_CALL(MMX_INSTRUCTIONS) \
+ do { \
+ __asm__ __volatile__( \
+ ".align 8 \n\t" \
+ MMX_INSTRUCTIONS \
+ : \
+ : "r" (p_line1), "r" (p_line2), "r" (p_y1), "r" (p_y2), \
+ "r" (p_u), "r" (p_v) ); \
+ p_line1 += 16; p_line2 += 16; p_y1 += 8; p_y2 += 8; p_u += 4; p_v += 4; \
+ } while(0); \
+
+#define MMX_YUV420_YUYV " \n\
+movq (%2), %%mm0 # Load 8 Y y7 y6 y5 y4 y3 y2 y1 y0 \n\
+movd (%4), %%mm1 # Load 4 Cb 00 00 00 00 u3 u2 u1 u0 \n\
+movd (%5), %%mm2 # Load 4 Cr 00 00 00 00 v3 v2 v1 v0 \n\
+punpcklbw %%mm2, %%mm1 # v3 u3 v2 u2 v1 u1 v0 u0 \n\
+movq %%mm0, %%mm2 # y7 y6 y5 y4 y3 y2 y1 y0 \n\
+punpcklbw %%mm1, %%mm2 # v1 y3 u1 y2 v0 y1 u0 y0 \n\
+movq %%mm2, (%0) # Store low YUYV \n\
+punpckhbw %%mm1, %%mm0 # v3 y7 u3 y6 v2 y5 u2 y4 \n\
+movq %%mm0, 8(%0) # Store high YUYV \n\
+movq (%3), %%mm0 # Load 8 Y Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 \n\
+movq %%mm0, %%mm2 # Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0 \n\
+punpcklbw %%mm1, %%mm2 # v1 Y3 u1 Y2 v0 Y1 u0 Y0 \n\
+movq %%mm2, (%1) # Store low YUYV \n\
+punpckhbw %%mm1, %%mm0 # v3 Y7 u3 Y6 v2 Y5 u2 Y4 \n\
+movq %%mm0, 8(%1) # Store high YUYV \n\
+"
+#endif
+
+void yv12_to_yuy2_mmx
+ (unsigned char *y_src, int y_src_pitch,
+ unsigned char *u_src, int u_src_pitch,
+ unsigned char *v_src, int v_src_pitch,
+ unsigned char *yuy2_map, int yuy2_pitch,
+ int width, int height) {
+#ifdef ARCH_X86
+ uint8_t *p_line1, *p_line2 = yuy2_map;
+ uint8_t *p_y1, *p_y2 = y_src;
+ uint8_t *p_u = u_src;
+ uint8_t *p_v = v_src;
+
+ int i_x, i_y;
+
+ const int i_source_margin = y_src_pitch - width;
+ const int i_source_u_margin = u_src_pitch - width/2;
+ const int i_source_v_margin = v_src_pitch - width/2;
+ const int i_dest_margin = yuy2_pitch - width*2;
+
+ for( i_y = height / 2; i_y-- ; )
+ {
+ p_line1 = p_line2;
+ p_line2 += yuy2_pitch;
+
+ p_y1 = p_y2;
+ p_y2 += y_src_pitch;
+
+ for( i_x = width / 8 ; i_x-- ; )
+ {
+ MMX_CALL( MMX_YUV420_YUYV );
+ }
+
+ p_y1 += i_source_margin;
+ p_y2 += i_source_margin;
+ p_u += i_source_u_margin;
+ p_v += i_source_v_margin;
+ p_line1 += i_dest_margin;
+ p_line2 += i_dest_margin;
+ }
+ emms();
+
+#endif
+}
+
/*
* init_yuv_conversion
*
@@ -680,6 +817,12 @@ void init_yuv_conversion(void) {
else
yuv444_to_yuy2 = yuv444_to_yuy2_c;
+ /* determine best YV12 -> YUY2 converter to use */
+ if (xine_mm_accel() & MM_ACCEL_X86_MMX)
+ yv12_to_yuy2 = yv12_to_yuy2_mmx;
+ else
+ yv12_to_yuy2 = yv12_to_yuy2_c;
+
/* determine best YUV9 -> YV12 converter to use (only the portable C
* version is available so far) */
yuv9_to_yv12 = yuv9_to_yv12_c;
diff --git a/src/xine-utils/xineutils.h b/src/xine-utils/xineutils.h
index 23edb48e6..fee9f6e3f 100644
--- a/src/xine-utils/xineutils.h
+++ b/src/xine-utils/xineutils.h
@@ -17,7 +17,7 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
*
- * $Id: xineutils.h,v 1.50 2003/05/20 13:54:57 mroi Exp $
+ * $Id: xineutils.h,v 1.51 2003/05/31 13:54:27 miguelfreitas Exp $
*
*/
#ifndef XINEUTILS_H
@@ -771,6 +771,12 @@ extern void (*yuv411_to_yv12)
unsigned char *u_src, int u_src_pitch, unsigned char *u_dest, int u_dest_pitch,
unsigned char *v_src, int v_src_pitch, unsigned char *v_dest, int v_dest_pitch,
int width, int height);
+extern void (*yv12_to_yuy2)
+ (unsigned char *y_src, int y_src_pitch,
+ unsigned char *u_src, int u_src_pitch,
+ unsigned char *v_src, int v_src_pitch,
+ unsigned char *yuy2_map, int yuy2_pitch,
+ int width, int height);
#define SCALEFACTOR 65536
#define CENTERSAMPLE 128