diff options
author | Miguel Freitas <miguelfreitas@users.sourceforge.net> | 2003-05-31 13:54:27 +0000 |
---|---|---|
committer | Miguel Freitas <miguelfreitas@users.sourceforge.net> | 2003-05-31 13:54:27 +0000 |
commit | 0306990681bdf214741c6ab2798b47bf8e578c97 (patch) | |
tree | f43a27309afe964044303c90b09cef5335ef9ae7 | |
parent | 3228b320ac0c2c46d695a7ac2913db1ff74eb0ba (diff) | |
download | xine-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.c | 145 | ||||
-rw-r--r-- | src/xine-utils/xineutils.h | 8 |
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 |