WSS data in vdr-xine

Message ID b98c6b1a0507110431404dfea4@mail.gmail.com
State New
Headers

Commit Message

mike lewis July 11, 2005, 11:31 a.m. UTC
  >From a message posted on softdevice's mailing list..

---------- Forwarded message ----------
From: Vadim Catana <vcatana@registru.md>
Date: Jul 11, 2005 2:09 PM
Subject: [Softdevice-devel] [PATCH]
To: softdevice-devel@berlios.de


Hi,

This patch makes the following modifications to
softdevice plugin from CVS:

1. Some channels display white dots at the top and bottom of
    the screen due to WSS data encoded in the picture.
    This problem has been mentioned on vdr, linux-dvb and
    dxr3 mailinglists a few times. I added two new items in
    the softdevice menu that allow to cut off a number of lines
    from top and bottom of the picture. It is implemented now
    only for -vo vidix and dfb with i420/YV12 format and hardware
    alpha blending.
...
-------------

I always wondered what this was on my DVB streams.  Is there something
similar in vdr-xine?

Mick
  

Comments

Reinhard Nissl July 11, 2005, 9:33 p.m. UTC | #1
Hi,

mike lewis wrote:

> 1. Some channels display white dots at the top and bottom of
>     the screen due to WSS data encoded in the picture.
>     This problem has been mentioned on vdr, linux-dvb and
>     dxr3 mailinglists a few times. I added two new items in
>     the softdevice menu that allow to cut off a number of lines
>     from top and bottom of the picture. It is implemented now
>     only for -vo vidix and dfb with i420/YV12 format and hardware
>     alpha blending.
> ...
> 
> I always wondered what this was on my DVB streams.  Is there something
> similar in vdr-xine?

Well, in the case of vdr-xine, it's xine related, as xine has to deal 
with decoding the images. xine has the possibilty to do something like 
that (my patched expand post plugin makes use of it).

Just create a post video plugin that modifies crop_top / crop_bottom of 
each frame.

Bye.
  

Patch

diff -urNbB ./softdevice/mpeg2decoder.c ./softdevice.crop/mpeg2decoder.c
--- ./softdevice/mpeg2decoder.c	2005-07-06 09:55:48.000000000 +0300
+++ ./softdevice.crop/mpeg2decoder.c	2005-07-10 13:43:56.000000000 +0300
@@ -1057,7 +1057,7 @@ 
 };
 
 int cMpeg2Decoder::seek(offset_t offset, int whence) {
-   printf("unimplemented: seek offset %lld whence %d\n",offset,whence);
+   printf("unimplemented: seek offset %lld whence %d\n", (long long int)offset, whence);
    return -EINVAL;
 };
 
diff -urNbB ./softdevice/setup-softdevice.c ./softdevice.crop/setup-softdevice.c
--- ./softdevice/setup-softdevice.c	2005-07-06 09:55:48.000000000 +0300
+++ ./softdevice.crop/setup-softdevice.c	2005-07-10 15:34:10.000000000 +0300
@@ -59,7 +59,7 @@ 
 char *pix_fmt [] = {
         "I420",
         "YV12",
-        "YUV2",
+        "YUY2",
         NULL
      };
 
@@ -154,6 +154,8 @@ 
   outputMethod  = 0;
   cropMode      = 0;
   cropModeToggleKey = 0;
+  cropTopLines      = 0;
+  cropBottomLines   = 0;
   deintMethod   = 0;
   ppMethod   = 0;
   ppQuality   = 0;
@@ -224,6 +226,16 @@ 
              "[setup-softdevice] cropping mode toggle key set to %d (%s)\n",
              cropModeToggleKey,
              userKeyUsage [cropModeToggleKey]);
+  } else if(!strcasecmp(Name,"CropTopLines")) {
+    cropTopLines = atoi(Value);
+    cropTopLines = clamp (0, cropTopLines, 100);
+    fprintf(stderr,"[setup-softdevice] Cropping %d lines from top\n",
+	    cropTopLines);
+  } else if(!strcasecmp(Name,"CropBottomLines")) {
+    cropBottomLines = atoi(Value);
+    cropBottomLines = clamp (0, cropBottomLines, 100);
+    fprintf(stderr,"[setup-softdevice] Cropping %d lines from bottom\n",
+	    cropBottomLines);
   } else if (!strcasecmp(Name,"PixelFormat")) {
     pixelFormat = atoi(Value);
     pixelFormat = clamp (0, pixelFormat, 2);
@@ -370,6 +380,16 @@ 
                             10,
                             userKeyUsage));
 
+  Add(new cMenuEditIntItem(tr("Crop lines from top"),
+                            &data->cropTopLines,
+                            0,
+                            100));
+
+  Add(new cMenuEditIntItem(tr("Crop lines from bottom"),
+                            &data->cropBottomLines,
+                            0,
+                            100));
+
   if (data->outputMethod == VOUT_FB)
   {
     Add(new cMenuEditStraItem(tr("Deinterlace Method"),
@@ -483,6 +503,8 @@ 
   //SetupStore ("Xv-MaxArea",         setupStore.xvMaxArea);
   SetupStore ("CropMode",           setupStore.cropMode);
   SetupStore ("CropModeToggleKey",     setupStore.cropModeToggleKey);
+  SetupStore ("CropTopLines",        setupStore.cropTopLines);
+  SetupStore ("CropBottomLines",     setupStore.cropBottomLines);  
   SetupStore ("Deinterlace Method", setupStore.deintMethod);
   SetupStore ("Postprocess Method", setupStore.ppMethod);
   SetupStore ("Postprocess Quality", setupStore.ppQuality);
diff -urNbB ./softdevice/setup-softdevice.h ./softdevice.crop/setup-softdevice.h
--- ./softdevice/setup-softdevice.h	2005-06-20 17:02:10.000000000 +0300
+++ ./softdevice.crop/setup-softdevice.h	2005-07-10 10:59:58.000000000 +0300
@@ -21,6 +21,7 @@ 
 class cSetupStore {
   public:
                   cSetupStore ();
+    virtual       ~cSetupStore () {};
     bool          SetupParse(const char *Name, const char *Value);
     char          *getPPdeintValue(void);
     char          *getPPValue(void);
@@ -35,6 +36,8 @@ 
     int   pixelFormat;
     int   cropMode;
     int   cropModeToggleKey;
+    int   cropTopLines;
+    int   cropBottomLines;
     int   deintMethod;
     int   ppMethod;
     int   ppQuality;
diff -urNbB ./softdevice/utils.c ./softdevice.crop/utils.c
--- ./softdevice/utils.c	2005-07-01 17:09:19.000000000 +0300
+++ ./softdevice.crop/utils.c	2005-07-10 14:01:59.000000000 +0300
@@ -20,6 +20,79 @@ 
 #include "utils.h"
 #include "setup-softdevice.h"
 
+void yv12_to_yuy2(const uint8_t *ysrc, const uint8_t *usrc, const uint8_t *vsrc, uint8_t *dst,
+		  int width, int height, int lumStride, int chromStride, int dstStride)
+{
+#ifndef USE_MMX
+    const unsigned chromWidth = width >> 1;
+
+    for(int y=0; y<height; y++)
+    {
+	uint32_t *idst = (uint32_t *) dst;
+	const uint8_t *yc = ysrc, *uc = usrc, *vc = vsrc;
+
+	for(unsigned i = 0; i < chromWidth; i++)
+	{
+	    *idst++ = (yc[0] << 0)+ (uc[0] << 8) + (yc[1] << 16) + (vc[0] << 24);
+	    yc += 2;
+	    uc++;
+	    vc++;
+	}
+
+	if( (y&1) == 1)
+	{
+	    usrc += chromStride;
+	    vsrc += chromStride;
+	}
+
+	ysrc += lumStride;
+	dst  += dstStride;
+    }
+#else
+    for (int i=0; i<height; i++)
+    {
+	const uint8_t *pu, *pv, *py;
+	uint8_t  *srfc;
+
+	pu = usrc;
+	pv = vsrc;
+	py = ysrc;
+	
+	srfc = dst;
+	
+	for (int j =0; j < width/8; j++)
+	{
+	    movd_m2r(*pu, mm1);       // mm1 = 00 00 00 00 U3 U2 U1 U0
+	    movd_m2r(*pv, mm2);       // mm2 = 00 00 00 00 V3 V2 V1 V0
+	    movq_m2r(*py, mm0);       // mm0 = Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0
+	    punpcklbw_r2r(mm2, mm1);  // mm1 = V3 U3 V2 U2 V1 U1 V0 U0
+	    movq_r2r(mm0,mm3);        // mm3 = Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0
+	    movq_r2r(mm1,mm4);        // mm4 = V3 U3 V2 U2 V1 U1 V0 U0
+	    punpcklbw_r2r(mm1, mm0);  // mm0 = V1 Y3 U1 Y2 V0 Y1 U0 Y0
+	    punpckhbw_r2r(mm4, mm3);  // mm3 = V3 Y7 U3 Y6 V2 Y5 U2 Y4
+
+	    movntq(mm0,*srfc);        // Am Meisten brauchen die Speicherzugriffe
+	    srfc+=8;
+	    py+=8;
+	    pu+=4;
+	    pv+=4;
+	    movntq(mm3,*srfc);      // wenn movntq nicht geht, dann movq verwenden
+	    srfc+=8;
+	}
+	
+	ysrc += lumStride;;
+	
+	if (i % 2 == 1)
+	{
+	    usrc += chromStride;
+	    vsrc += chromStride;
+	}
+	
+	dst += width*2;
+    }
+#endif
+}
+
 #define VERT_SCALING
 void (*mmx_unpack)(uint8_t * image, int lines, int stride);
 
@@ -341,7 +414,8 @@ 
 	: "memory");\
 }
 
- void * fast_memcpy(void * to, const void * from, size_t len)
+#if 0
+void * fast_memcpy(void * to, const void * from, size_t len)
 {
 	void *retval;
 	size_t i;
@@ -380,7 +454,7 @@ 
         */
 
 	// Align destination at BLOCK_SIZE boundary
-	for(; ((int)to & (BLOCK_SIZE-1)) && i>0; i--)
+	for(; ((long)to & (BLOCK_SIZE-1)) && i>0; i--)
 	{
 		__asm__ __volatile__ (
 #ifdef USE_MMX2
@@ -512,5 +586,4 @@ 
 	if(len) small_memcpy(to, from, len);
 	return retval;
 }
-
-
+#endif
diff -urNbB ./softdevice/utils.h ./softdevice.crop/utils.h
--- ./softdevice/utils.h	2005-06-20 17:02:10.000000000 +0300
+++ ./softdevice.crop/utils.h	2005-07-10 13:35:51.000000000 +0300
@@ -19,10 +19,17 @@ 
 #define movntq(src,dest) do { movq_r2m (src, dest); } while (0);
 #endif
 
-/*    else			\
-	movq_r2m (src, dest);	\
-} while (0)
-*/
+void yv12_to_yuy2( const uint8_t *ysrc,
+                   const uint8_t *usrc,
+                   const uint8_t *vsrc,
+                   uint8_t *dst,
+                   int width,
+                   int height,
+                   int lumStride,
+                   int chromStride,
+                   int dstStride
+                 );
+
 void yuv_to_rgb (uint8_t * image, uint8_t * py,
                  uint8_t * pu, uint8_t * pv,
                  int width, int height,
diff -urNbB ./softdevice/video.c ./softdevice.crop/video.c
--- ./softdevice/video.c	2005-07-01 17:09:19.000000000 +0300
+++ ./softdevice.crop/video.c	2005-07-10 13:25:12.000000000 +0300
@@ -757,6 +757,7 @@ 
                 alpha+=8;
                 dest+=8;
        }
+       EMMS;
 #endif //USE_MMX
 
        //fallback version and the last missing bytes...
diff -urNbB ./softdevice/video-dfb.c ./softdevice.crop/video-dfb.c
--- ./softdevice/video-dfb.c	2005-07-01 17:09:19.000000000 +0300
+++ ./softdevice.crop/video-dfb.c	2005-07-10 14:53:27.000000000 +0300
@@ -571,6 +571,8 @@ 
   }
 }
 
+static int cutTop, cutBottom;
+
 /* ---------------------------------------------------------------------------
  */
 void cDFBVideoOut::SetParams()
@@ -581,11 +583,13 @@ 
 
   if (videoLayer || useStretchBlit)
   {
-    if (!videoSurface ||
-        aspect_changed ||
-        currentPixelFormat != setupStore->pixelFormat)
+	if ( ! videoSurface || aspect_changed || currentPixelFormat != setupStore->pixelFormat ||
+	        cutTop != setupStore->cropTopLines || cutBottom != setupStore->cropBottomLines )
     {
 
+	    cutTop    = setupStore->cropTopLines;
+	    cutBottom = setupStore->cropBottomLines;
+
       fprintf(stderr,
               "[dfb] (re)configuring Videolayer to %d x %d (%dx%d)\n",
               fwidth,fheight,swidth,sheight);
@@ -600,8 +606,8 @@ 
       else if (setupStore->pixelFormat == 2)
       {
         dlc.pixelformat = DSPF_YUY2;
-        useStretchBlit = true;
-        OSDpseudo_alpha = false;
+//		useStretchBlit = true;
+//		OSDpseudo_alpha = false;
       }
 
 #if HAVE_SetSourceLocation
@@ -1026,23 +1035,29 @@ 
       dst += pitch / 2;
     }
 #else
+	Py += (Ystride  * syoff)   + Ystride  * cutTop * 2;
+	Pv += (UVstride * syoff/2) + UVstride * cutTop;
+	Pu += (UVstride * syoff/2) + UVstride * cutTop;
 
-    Py += (Ystride * syoff);
-    Pv += (UVstride * syoff/2);
-    Pu += (UVstride * syoff/2);
+	dst += pitch * cutTop * 2;
 
-    for(hi=0; hi < sheight; hi++){
+	for(hi=cutTop*2; hi < sheight-cutBottom*2; hi++){
       memcpy(dst, Py+sxoff, swidth);
       Py  += Ystride;
       dst += pitch;
     }
-    for(hi=0; hi < sheight/2; hi++) {
+
+	dst += pitch * cutBottom * 2 + pitch * cutTop / 2;
+
+	for(hi=cutTop; hi < sheight/2-cutBottom; hi++) {
       memcpy(dst, Pu+sxoff/2, swidth/2);
       Pu  += UVstride;
       dst += pitch / 2;
     }
 
-    for(hi=0; hi < sheight/2; hi++) {
+	dst += pitch * cutBottom / 2 + pitch * cutTop / 2;
+
+	for(hi=cutTop; hi < sheight/2-cutBottom; hi++) {
       memcpy(dst, Pv+sxoff/2, swidth/2);
       Pv  += UVstride;
       dst += pitch / 2;
@@ -1050,59 +1065,9 @@ 
 #endif
   } else if (pixelformat == DSPF_YUY2) {
 
-#ifndef USE_MMX
-//#if 1
-    /* reference implementation */
-      int p = pitch - Width*2;
-    for (int i=0; i<Height; i++) {
-      for (int j =0; j < Width/2; j++) {
-        *dst = *(Py + (j*2) + i * Ystride);
-        dst +=1;
-        *dst = *(Pu + j + (i/2) * UVstride);
-        dst +=1;
-        *dst = *(Py + (j*2)+1 + i * Ystride);
-        dst +=1;
-        *dst = *(Pv + j + (i/2) * UVstride);
-        dst +=1;
-      }
-      dst +=p;
-    }
-#else
-    /* deltas */
-    for (int i=0; i<Height; i++) {
-        uint8_t *pu, *pv, *py, *srfc;
-
-      pu = Pu;
-      pv = Pv;
-      py = Py;
-      srfc = dst;
-      for (int j =0; j < Width/8; j++) {
-        movd_m2r(*pu, mm1);       // mm1 = 00 00 00 00 U3 U2 U1 U0
-        movd_m2r(*pv, mm2);       // mm2 = 00 00 00 00 V3 V2 V1 V0
-        movq_m2r(*py, mm0);       // mm0 = Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0
-        punpcklbw_r2r(mm2, mm1);  // mm1 = V3 U3 V2 U2 V1 U1 V0 U0
-        movq_r2r(mm0,mm3);        // mm3 = Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0
-        movq_r2r(mm1,mm4);        // mm4 = V3 U3 V2 U2 V1 U1 V0 U0
-        punpcklbw_r2r(mm1, mm0);  // mm0 = V1 Y3 U1 Y2 V0 Y1 U0 Y0
-        punpckhbw_r2r(mm4, mm3);  // mm3 = V3 Y7 U3 Y6 V2 Y5 U2 Y4
-
-        movntq(mm0,*srfc);        // Am Meisten brauchen die Speicherzugriffe
-        srfc+=8;
-        py+=8;
-        pu+=4;
-        pv+=4;
-        movntq(mm3,*srfc);      // wenn movntq nicht geht, dann movq verwenden
-        srfc+=8;
-      }
-      Py += Ystride;;
-      if (i % 2 == 1) {
-        Pu += UVstride;
-        Pv += UVstride;
-      }
-      dst += pitch;
-    }
-#endif
+	yv12_to_yuy2(Py, Pu, Pv, dst, Width, Height, Ystride, UVstride, pitch);
   }
+
   videoSurface->Unlock();
 
   try {
diff -urNbB ./softdevice/video-vidix.c ./softdevice.crop/video-vidix.c
--- ./softdevice/video-vidix.c	2005-06-08 16:44:25.000000000 +0300
+++ ./softdevice.crop/video-vidix.c	2005-07-10 15:33:08.000000000 +0300
@@ -133,7 +133,7 @@ 
 
     printf("cVidixVideoOut: vidix version: %i\n", vidix_version);
 
-    vidix_handler = vdlOpen(VIDIX_DIR, NULL, TYPE_OUTPUT, 1);
+    vidix_handler = vdlOpen(VIDIX_DIR, NULL, TYPE_OUTPUT, 0);
 
     if( !vidix_handler )
     {
@@ -161,7 +161,6 @@ 
     currentPixelFormat = setupStore->pixelFormat;
     screenPixelAspect = -1;
 
-    vdlQueryFourcc(vidix_handler, &vidix_fourcc);
     if (vdlQueryFourcc(vidix_handler, &vidix_fourcc))
     {
       if (!MatchPixelFormat())
@@ -312,10 +311,17 @@ 
 {
     uint8_t *dst;
     int hi, wi;
+    
+    static int cutTop, cutBottom;
+    
     START;
     TIMINGS("start...\n");
-    if (aspect_changed || currentPixelFormat != setupStore->pixelFormat)
+    if (aspect_changed || currentPixelFormat != setupStore->pixelFormat ||
+        cutTop != setupStore->cropTopLines || cutBottom != setupStore->cropBottomLines )
     {
+       cutTop    = setupStore->cropTopLines;
+       cutBottom = setupStore->cropBottomLines;
+    
        printf("cVidixVideoOut: Video changed format to %dx%d\n", Width, Height);
 
        if((Xres > Width || Yres > Height) &&
@@ -400,20 +407,44 @@ 
     if (currentPixelFormat == 0 || currentPixelFormat == 1)
     {
 #if VDRVERSNUM >= 10307
-      if (OSDpresent && current_osdMode==OSDMODE_SOFTWARE) {
+	if (OSDpresent && current_osdMode==OSDMODE_SOFTWARE)
+	{
         for(hi=0; hi < sheight; hi++){
-          AlphaBlend(dst,OsdPy+hi*OSD_FULL_WIDTH,
-              Py + sxoff,
-              OsdPAlphaY+hi*OSD_FULL_WIDTH,swidth);
+		AlphaBlend(dst, OsdPy+hi*OSD_FULL_WIDTH, Py + sxoff, OsdPAlphaY+hi*OSD_FULL_WIDTH, swidth);
           Py  += Ystride;
           dst += dstrides.y;
+	    }
+	    
+	    // Plane U
+	    dst = (uint8_t *)vidix_play.dga_addr + vidix_play.offsets[next_frame] + vidix_play.offset.u;
+	    for(hi=0; hi < sheight/2; hi++){
+		    AlphaBlend(dst,OsdPu+hi*OSD_FULL_WIDTH/2, Pu + sxoff/2, OsdPAlphaUV+hi*OSD_FULL_WIDTH/2,swidth/2);
+		    Pu  += UVstride;
+		    dst += dstrides.y / 2;
+	    }
 
+	    // Plane V
+	    dst = (uint8_t *)vidix_play.dga_addr + vidix_play.offsets[next_frame] + vidix_play.offset.v;
+	    for(hi=0; hi < sheight/2; hi++) {
+		    AlphaBlend(dst, OsdPv+hi*OSD_FULL_WIDTH/2, Pv + sxoff/2, OsdPAlphaUV+hi*OSD_FULL_WIDTH/2, swidth/2);
+		    Pv  += UVstride;
+		    dst += dstrides.v / 2;
         }
-        EMMS;
       } else
 #endif
+	{	
+	    int chromaWidth  = swidth >> 1;
+	    int chromaOffset = sxoff >> 1;
 
-        for(hi=0; hi < sheight; hi++){
+	    Py += Ystride  * cutTop * 2;
+	    Pv += UVstride * cutTop;
+	    Pu += UVstride * cutTop;
+
+	    dst += dstrides.y * cutTop * 2;
+
+
+	    for(hi=cutTop*2; hi < sheight-cutBottom*2; hi++)
+	    {
           memcpy(dst, Py+sxoff, swidth);
           Py  += Ystride;
           dst += dstrides.y;
@@ -423,15 +454,22 @@ 
 
       if (vidix_play.flags & VID_PLAY_INTERLEAVED_UV)
       {
-        dst = (uint8_t *)vidix_play.dga_addr + vidix_play.offsets[next_frame] + vidix_play.offset.v;
+		int dstStride = dstrides.v << 1;
+		dst = (uint8_t *)vidix_play.dga_addr + vidix_play.offsets[next_frame] + vidix_play.offset.v + dstStride * cutTop;
+
+		for(hi = cutTop; hi < sheight/2; hi++)
+		{
+		    uint16_t *idst = (uint16_t *) dst;
+		    uint8_t  *usrc = Pu + chromaOffset, *vsrc = Pv + chromaOffset;
 
-        for(hi = 0; hi < sheight/2; hi++) {
-          for(wi = 0; wi < swidth/2; wi++) {
-            dst[2*wi+0] = Pu[wi+sxoff/2];
-            dst[2*wi+1] = Pv[wi+sxoff/2];
+		    for(wi = 0; wi < chromaWidth; wi++)
+		    {
+			*idst++ = ( usrc[0] << 8 ) + vsrc[0];
+			usrc++;
+			vsrc++;
           }
 
-          dst += dstrides.y;
+		    dst += dstStride;
           Pu += UVstride;
           Pv += UVstride;
         }
@@ -435,48 +473,33 @@ 
           Pu += UVstride;
           Pv += UVstride;
         }
+
       } else {
 
+		int dstStride;
+		
         // Plane U
-        dst = (uint8_t *)vidix_play.dga_addr + vidix_play.offsets[next_frame] + vidix_play.offset.u;
+		dstStride = dstrides.u >> 1;		
+		dst = (uint8_t *)vidix_play.dga_addr + vidix_play.offsets[next_frame] + vidix_play.offset.u + dstStride * cutTop;
 
-#if VDRVERSNUM >= 10307
-        if (OSDpresent && current_osdMode==OSDMODE_SOFTWARE) {
-          for(hi=0; hi < sheight/2; hi++){
-            AlphaBlend(dst,OsdPu+hi*OSD_FULL_WIDTH/2,
-               Pu + sxoff/2,
-               OsdPAlphaUV+hi*OSD_FULL_WIDTH/2,swidth/2);
+		for(hi=cutTop; hi < sheight/2 - cutBottom; hi++)
+		{
+    		    memcpy(dst, Pu+chromaOffset, chromaWidth);
             Pu  += UVstride;
-            dst += dstrides.y / 2;
+		    dst += dstStride;
           }
 
           // Plane V
-          dst = (uint8_t *)vidix_play.dga_addr + vidix_play.offsets[next_frame] + vidix_play.offset.v;
-          for(hi=0; hi < sheight/2; hi++) {
-            AlphaBlend(dst, OsdPv+hi*OSD_FULL_WIDTH/2,
-                   Pv + sxoff/2,
-                   OsdPAlphaUV+hi*OSD_FULL_WIDTH/2, swidth/2);
-            Pv  += UVstride;
-            dst += dstrides.v / 2;
-          }
+		dstStride = dstrides.v >> 1;
+		dst = (uint8_t *)vidix_play.dga_addr + vidix_play.offsets[next_frame] + vidix_play.offset.v + dstStride * cutTop;
 
-          EMMS;
-        } else
-#endif
+		for(hi=cutTop; hi < sheight/2 - cutBottom; hi++)
         {
-          for(hi=0; hi < sheight/2; hi++) {
-            memcpy(dst, Pu+sxoff/2, swidth/2);
-            Pu   += UVstride;
-            dst += dstrides.u / 2;
-          }
-
-          // Plane V
-          dst = (uint8_t *)vidix_play.dga_addr + vidix_play.offsets[next_frame] + vidix_play.offset.v;
-          for(hi=0; hi < sheight/2; hi++) {
-            memcpy(dst, Pv+sxoff/2, swidth/2);
+    		    memcpy(dst, Pv+chromaOffset, chromaWidth);
             Pv   += UVstride;
-            dst += dstrides.v / 2;
+		    dst += dstStride;
           }
+
         }
       }
     } else if (currentPixelFormat == 2) {
@@ -481,58 +504,7 @@ 
       }
     } else if (currentPixelFormat == 2) {
 
-#ifndef USE_MMX
-
-      /* reference implementation */
-      //int p = vidix_play.src.pitch.y - Width*2;
-      for (int i=0; i<Height; i++) {
-        for (int j =0; j < Width/2; j++) {
-          *dst = *(Py + (j*2) + i * Ystride);
-          dst +=1;
-          *dst = *(Pu + j + (i/2) * UVstride);
-          dst +=1;
-          *dst = *(Py + (j*2)+1 + i * Ystride);
-          dst +=1;
-          *dst = *(Pv + j + (i/2) * UVstride);
-          dst +=1;
-        }
-        //dst +=p;
-      }
-#else
-      /* deltas */
-      for (int i=0; i<Height; i++) {
-          uint8_t *pu, *pv, *py, *srfc;
-
-        pu = Pu;
-        pv = Pv;
-        py = Py;
-        srfc = dst;
-        for (int j =0; j < Width/8; j++) {
-          movd_m2r(*pu, mm1);       // mm1 = 00 00 00 00 U3 U2 U1 U0
-          movd_m2r(*pv, mm2);       // mm2 = 00 00 00 00 V3 V2 V1 V0
-          movq_m2r(*py, mm0);       // mm0 = Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0
-          punpcklbw_r2r(mm2, mm1);  // mm1 = V3 U3 V2 U2 V1 U1 V0 U0
-          movq_r2r(mm0,mm3);        // mm3 = Y7 Y6 Y5 Y4 Y3 Y2 Y1 Y0
-          movq_r2r(mm1,mm4);        // mm4 = V3 U3 V2 U2 V1 U1 V0 U0
-          punpcklbw_r2r(mm1, mm0);  // mm0 = V1 Y3 U1 Y2 V0 Y1 U0 Y0
-          punpckhbw_r2r(mm4, mm3);  // mm3 = V3 Y7 U3 Y6 V2 Y5 U2 Y4
-
-          movntq(mm0,*srfc);        // Am Meisten brauchen die Speicherzugriffe
-          srfc+=8;
-          py+=8;
-          pu+=4;
-          pv+=4;
-          movntq(mm3,*srfc);      // wenn movntq nicht geht, dann movq verwenden
-          srfc+=8;
-        }
-        Py += Ystride;;
-        if (i % 2 == 1) {
-          Pu += UVstride;
-          Pv += UVstride;
-        }
-        dst += Width*2;
-      }
-#endif
+	yv12_to_yuy2(Py, Pu, Pv, dst, Width, Height, Ystride, UVstride, dstrides.y*2);
     }
 
     TIMINGS("After UV\n");