home *** CD-ROM | disk | FTP | other *** search
/ Computer Shopper 275 / DPCS0111DVD.ISO / Toolkit / Audio-Visual / VirtualDub / Source / VirtualDub-1.9.10-src.7z / src / Kasumi / source / blt_reference_yuvrev.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2009-09-14  |  14.3 KB  |  531 lines

  1. #include <vd2/system/cpuaccel.h>
  2. #include <vd2/system/vdtypes.h>
  3. #include <vd2/system/vdstl.h>
  4. #include <vd2/Kasumi/pixmap.h>
  5. #include <vd2/Kasumi/pixmaputils.h>
  6. #include "blt_spanutils.h"
  7.  
  8. #ifdef _M_IX86
  9.     #include "blt_spanutils_x86.h"
  10. #endif
  11.  
  12. using namespace nsVDPixmapSpanUtils;
  13.  
  14. namespace {
  15.     // From Jim Blinn's "Dirty Pixels":
  16.     //
  17.     // Y  = .299R + .587G + .114B
  18.     // Cr = 0.713(R-Y)
  19.     // Cb = 0.564(B-Y)
  20.     //
  21.     // IY  = 219Y  + 16  = ((yt = 1052IR + 2065IG + 401IB) + 67584) >> 12
  22.     // ICr = 224Cr + 128 = (yt*2987 - 10507932IR + 2155872256) >> 24
  23.     // ICb = 224Cb + 128 = (yt*2363 - 8312025IB + 2155872256) >> 24
  24.  
  25.     void ConvertRGB32ToXVYU32(uint32 *dst, const uint8 *src, sint32 count) {
  26.         do {
  27.             const sint32 r  = src[2];
  28.             const sint32 g  = src[1];
  29.             const sint32 b  = src[0];
  30.             const sint32 yt = 1052*r + 2065*g + 401*b;
  31.             const sint32 y  = (yt + 67584) >> 4;                            // <<8 alignment shift
  32.             const sint32 cr = (10507932*r - yt*2987 + 2155872256U) >> 8;    // <<16 alignment shift
  33.             const sint32 cb = ( 8312025*b - yt*2363 + 2155872256U) >> 24;
  34.  
  35.             *dst++ = (y&0xff00) + cb + (cr&0xff0000);        // VYU order
  36.             src += 4;
  37.         } while(--count);
  38.     }
  39.  
  40.     void ConvertRGB24ToXVYU32(uint32 *dst, const uint8 *src, sint32 count) {
  41.         do {
  42.             const sint32 r  = src[2];
  43.             const sint32 g  = src[1];
  44.             const sint32 b  = src[0];
  45.             const sint32 yt = 1052*r + 2065*g + 401*b;
  46.             const sint32 y  = (yt + 67584) >> 4;                            // <<8 alignment shift
  47.             const sint32 cr = (10507932*r - yt*2987 + 2155872256U) >> 8;    // <<16 alignment shift
  48.             const sint32 cb = ( 8312025*b - yt*2363 + 2155872256U) >> 24;
  49.  
  50.             *dst++ = (y&0xff00) + cb + (cr&0xff0000);        // VYU order
  51.             src += 3;
  52.         } while(--count);
  53.     }
  54.  
  55.     void ConvertRGB16ToXVYU32(uint32 *dst, const uint16 *src, sint32 count) {
  56.         do {
  57.             const sint16 px = *src++;
  58.             const sint32 r  = (px & 0xf800) >> 11;
  59.             const sint32 g  = (px & 0x07e0) >> 5;
  60.             const sint32 b  = (px & 0x001f);
  61.             const sint32 yt = 8652*r + 8358*g + 3299*b;
  62.             const sint32 y  = (yt + 67584) >> 4;                            // <<8 alignment shift
  63.             const sint32 cr = (86436217*r - yt*2987 + 2155872256U) >> 8;
  64.             const sint32 cb = (68373108*b - yt*2363 + 2155872256U) >> 24;    // <<16 alignment shift
  65.  
  66.             *dst++ = (y&0xff00) + cb + (cr&0xff0000);        // VYU order
  67.         } while(--count);
  68.     }
  69.  
  70.     void ConvertRGB15ToXVYU32(uint32 *dst, const uint16 *src, sint32 count) {
  71.         do {
  72.             const sint16 px = *src++;
  73.             const sint32 r  = (px & 0x7c00) >> 10;
  74.             const sint32 g  = (px & 0x03e0) >> 5;
  75.             const sint32 b  = (px & 0x001f);
  76.             const sint32 yt = 8652*r + 16986*g + 3299*b;
  77.             const sint32 y  = (yt + 67584) >> 4;                            // <<8 alignment shift
  78.             const sint32 cr = (86436217*r - yt*2987 + 2155872256U) >> 8;    // <<16 alignment shift
  79.             const sint32 cb = (68373108*b - yt*2363 + 2155872256U) >> 24;
  80.  
  81.             *dst++ = (y&0xff00) + cb + (cr&0xff0000);        // VYU order
  82.         } while(--count);
  83.     }
  84.  
  85.     void ConvertRGB32ToY8(uint8 *dst, const uint8 *src, sint32 count) {
  86.         do {
  87.             const sint32 r  = src[2];
  88.             const sint32 g  = src[1];
  89.             const sint32 b  = src[0];
  90.             *dst++ = (uint8)((1052*r + 2065*g + 401*b + 67584) >> 12);
  91.             src += 4;
  92.         } while(--count);
  93.     }
  94.  
  95.     void ConvertRGB24ToY8(uint8 *dst, const uint8 *src, sint32 count) {
  96.         do {
  97.             const sint32 r  = src[2];
  98.             const sint32 g  = src[1];
  99.             const sint32 b  = src[0];
  100.             *dst++ = (uint8)((1052*r + 2065*g + 401*b + 67584) >> 12);
  101.             src += 3;
  102.         } while(--count);
  103.     }
  104.  
  105.     void ConvertRGB16ToY8(uint8 *dst, const uint16 *src, sint32 count) {
  106.         do {
  107.             const sint16 px = *src++;
  108.             const sint32 r  = (px & 0xf800) >> 11;
  109.             const sint32 g  = (px & 0x07e0) >> 5;
  110.             const sint32 b  = (px & 0x001f);
  111.             *dst++ = (uint8)((8652*r + 8358*g + 3299*b + 67584) >> 12);
  112.         } while(--count);
  113.     }
  114.  
  115.     void ConvertRGB15ToY8(uint8 *dst, const uint16 *src, sint32 count) {
  116.         do {
  117.             const sint16 px = *src++;
  118.             const sint32 r  = (px & 0x7c00) >> 10;
  119.             const sint32 g  = (px & 0x03e0) >> 5;
  120.             const sint32 b  = (px & 0x001f);
  121.             *dst++ = (uint8)((8652*r + 16986*g + 3299*b + 67584) >> 12);
  122.         } while(--count);
  123.     }
  124. }
  125.  
  126. #define DECLARE_YUV_REV(x, y) void VDPixmapBlt_##x##_to_##y##_reference(void *dst0, ptrdiff_t dstpitch, const void *src0, ptrdiff_t srcpitch, vdpixsize w, vdpixsize h)
  127.  
  128. DECLARE_YUV_REV(XRGB1555, XVYU) {
  129.     do {
  130.         ConvertRGB15ToXVYU32((uint32 *)dst0, (const uint16 *)src0, w);
  131.  
  132.         vdptrstep(dst0, dstpitch);
  133.         vdptrstep(src0, srcpitch);
  134.     } while(--h);
  135. }
  136.  
  137. DECLARE_YUV_REV(RGB565, XVYU) {
  138.     do {
  139.         ConvertRGB16ToXVYU32((uint32 *)dst0, (const uint16 *)src0, w);
  140.  
  141.         vdptrstep(dst0, dstpitch);
  142.         vdptrstep(src0, srcpitch);
  143.     } while(--h);
  144. }
  145.  
  146. DECLARE_YUV_REV(RGB888, XVYU) {
  147.     do {
  148.         ConvertRGB24ToXVYU32((uint32 *)dst0, (const uint8 *)src0, w);
  149.  
  150.         vdptrstep(dst0, dstpitch);
  151.         vdptrstep(src0, srcpitch);
  152.     } while(--h);
  153. }
  154.  
  155. DECLARE_YUV_REV(XRGB8888, XVYU) {
  156.     do {
  157.         ConvertRGB32ToXVYU32((uint32 *)dst0, (const uint8 *)src0, w);
  158.  
  159.         vdptrstep(dst0, dstpitch);
  160.         vdptrstep(src0, srcpitch);
  161.     } while(--h);
  162. }
  163.  
  164. DECLARE_YUV_REV(XRGB1555, Y8) {
  165.     do {
  166.         ConvertRGB15ToY8((uint8 *)dst0, (const uint16 *)src0, w);
  167.  
  168.         vdptrstep(dst0, dstpitch);
  169.         vdptrstep(src0, srcpitch);
  170.     } while(--h);
  171. }
  172.  
  173. DECLARE_YUV_REV(RGB565, Y8) {
  174.     do {
  175.         ConvertRGB16ToY8((uint8 *)dst0, (const uint16 *)src0, w);
  176.  
  177.         vdptrstep(dst0, dstpitch);
  178.         vdptrstep(src0, srcpitch);
  179.     } while(--h);
  180. }
  181.  
  182. DECLARE_YUV_REV(RGB888, Y8) {
  183.     do {
  184.         ConvertRGB24ToY8((uint8 *)dst0, (const uint8 *)src0, w);
  185.  
  186.         vdptrstep(dst0, dstpitch);
  187.         vdptrstep(src0, srcpitch);
  188.     } while(--h);
  189. }
  190.  
  191. DECLARE_YUV_REV(XRGB8888, Y8) {
  192.     do {
  193.         ConvertRGB32ToY8((uint8 *)dst0, (const uint8 *)src0, w);
  194.  
  195.         vdptrstep(dst0, dstpitch);
  196.         vdptrstep(src0, srcpitch);
  197.     } while(--h);
  198. }
  199.  
  200.  
  201.  
  202.  
  203.  
  204. namespace {
  205.     void ConvertRGB32ToYUVPlanar(uint8 *ydst, uint8 *cbdst, uint8 *crdst, const void *src0, sint32 count) {
  206.         const uint8 *src = (const uint8 *)src0;
  207.  
  208.         do {
  209.             const sint32 r  = src[2];
  210.             const sint32 g  = src[1];
  211.             const sint32 b  = src[0];
  212.             const sint32 yt = 1052*r + 2065*g + 401*b;
  213.             *ydst++  = (yt + 67584) >> 12;
  214.             *crdst++ = (10507932*r - yt*2987 + 2155872256U) >> 24;
  215.             *cbdst++ = ( 8312025*b - yt*2363 + 2155872256U) >> 24;
  216.             src += 4;
  217.         } while(--count);
  218.     }
  219.  
  220.     void ConvertRGB24ToYUVPlanar(uint8 *ydst, uint8 *cbdst, uint8 *crdst, const void *src0, sint32 count) {
  221.         const uint8 *src = (const uint8 *)src0;
  222.  
  223.         do {
  224.             const sint32 r  = src[2];
  225.             const sint32 g  = src[1];
  226.             const sint32 b  = src[0];
  227.             const sint32 yt = 1052*r + 2065*g + 401*b;
  228.             *ydst++  = (yt + 67584) >> 12;
  229.             *crdst++ = (10507932*r - yt*2987 + 2155872256U) >> 24;
  230.             *cbdst++ = ( 8312025*b - yt*2363 + 2155872256U) >> 24;
  231.             src += 3;
  232.         } while(--count);
  233.     }
  234.  
  235.     void ConvertRGB16ToYUVPlanar(uint8 *ydst, uint8 *cbdst, uint8 *crdst, const void *src0, sint32 count) {
  236.         const uint16 *src = (const uint16 *)src0;
  237.  
  238.         do {
  239.             const sint16 px = *src++;
  240.             const sint32 r  = (px & 0xf800) >> 11;
  241.             const sint32 g  = (px & 0x07e0) >> 5;
  242.             const sint32 b  = (px & 0x001f);
  243.             const sint32 yt = 8652*r + 8358*g + 3299*b;
  244.             *ydst++  = (yt + 67584) >> 12;
  245.             *crdst++ = (86436217*r - yt*2987 + 2155872256U) >> 24;
  246.             *cbdst++ = (68373108*b - yt*2363 + 2155872256U) >> 24;
  247.         } while(--count);
  248.     }
  249.  
  250.     void ConvertRGB15ToYUVPlanar(uint8 *ydst, uint8 *cbdst, uint8 *crdst, const void *src0, sint32 count) {
  251.         const uint16 *src = (const uint16 *)src0;
  252.  
  253.         do {
  254.             const sint16 px = *src++;
  255.             const sint32 r  = (px & 0x7c00) >> 10;
  256.             const sint32 g  = (px & 0x03e0) >> 5;
  257.             const sint32 b  = (px & 0x001f);
  258.             const sint32 yt = 8652*r + 16986*g + 3299*b;
  259.             *ydst++  = (yt + 67584) >> 12;
  260.             *crdst++ = (86436217*r - yt*2987 + 2155872256U) >> 24;
  261.             *cbdst++ = (68373108*b - yt*2363 + 2155872256U) >> 24;
  262.         } while(--count);
  263.     }
  264.  
  265.     void ConvertUYVYToYUVPlanar(uint8 *ydst, uint8 *cbdst, uint8 *crdst, const void *src0, sint32 count) {
  266.         const uint8 *src = (const uint8 *)src0;
  267.  
  268.         do {
  269.             *cbdst++ = src[0];
  270.             *ydst++ = src[1];
  271.             *crdst++ = src[2];
  272.             if (!--count)
  273.                 break;
  274.             *ydst++ = src[3];
  275.             src += 4;
  276.         } while(--count);
  277.     }
  278.  
  279.     void ConvertYUYVToYUVPlanar(uint8 *ydst, uint8 *cbdst, uint8 *crdst, const void *src0, sint32 count) {
  280.         const uint8 *src = (const uint8 *)src0;
  281.  
  282.         do {
  283.             *cbdst++ = src[1];
  284.             *ydst++ = src[0];
  285.             *crdst++ = src[3];
  286.             if (!--count)
  287.                 break;
  288.             *ydst++ = src[2];
  289.             src += 4;
  290.         } while(--count);
  291.     }
  292. }
  293.  
  294. void VDPixmapBlt_YUVPlanar_encode_reference(const VDPixmap& dstbm, const VDPixmap& srcbm, vdpixsize w, vdpixsize h) {
  295.     void (*cfunc)(uint8 *ydst, uint8 *cbdst, uint8 *crdst, const void *src, sint32 w) = NULL;
  296.     void (*hfunc)(uint8 *dst, const uint8 *src, sint32 w) = NULL;
  297.     void (*vfunc)(uint8 *dst, const uint8 *const *sources, sint32 w, uint8 phase) = NULL;
  298.  
  299.     bool halfchroma = false;
  300.  
  301.     switch(srcbm.format) {
  302.     case nsVDPixmap::kPixFormat_XRGB1555:
  303.         cfunc = ConvertRGB15ToYUVPlanar;
  304.         break;
  305.     case nsVDPixmap::kPixFormat_RGB565:
  306.         cfunc = ConvertRGB16ToYUVPlanar;
  307.         break;
  308.     case nsVDPixmap::kPixFormat_RGB888:
  309.         cfunc = ConvertRGB24ToYUVPlanar;
  310.         break;
  311.     case nsVDPixmap::kPixFormat_XRGB8888:
  312.         cfunc = ConvertRGB32ToYUVPlanar;
  313.         break;
  314.     case nsVDPixmap::kPixFormat_YUV422_UYVY:
  315.         cfunc = ConvertUYVYToYUVPlanar;
  316.         halfchroma = true;
  317.         break;
  318.     case nsVDPixmap::kPixFormat_YUV422_YUYV:
  319.         cfunc = ConvertYUYVToYUVPlanar;
  320.         halfchroma = true;
  321.         break;
  322.     default:
  323.         VDNEVERHERE;
  324.         return;
  325.     }
  326.  
  327.     vdpixsize w2 = w;
  328.     vdpixsize h2 = h;
  329.     int winstep = 1;
  330.     int winsize = 1;
  331.     int winposnext = 0;
  332.     vdpixsize chroma_srcw = w;
  333.  
  334.     switch(dstbm.format) {
  335.  
  336.     case nsVDPixmap::kPixFormat_YUV444_Planar:
  337.         if (halfchroma)
  338.             hfunc = horiz_expand2x_coaligned;
  339.         break;
  340.  
  341.     case nsVDPixmap::kPixFormat_YUV422_Planar:
  342.         if (halfchroma)
  343.             chroma_srcw = (chroma_srcw + 1) >> 1;
  344.         else
  345.             hfunc = horiz_compress2x_coaligned;
  346.  
  347.         w2 = (w2+1) >> 1;
  348.         break;
  349.  
  350.     case nsVDPixmap::kPixFormat_YUV422_Planar_Centered:
  351.         if (halfchroma) {
  352.             chroma_srcw = (chroma_srcw + 1) >> 1;
  353.             hfunc = horiz_realign_to_centered;
  354.         } else
  355.             hfunc = horiz_compress2x_centered;
  356.  
  357.         w2 = (w2+1) >> 1;
  358.         break;
  359.  
  360.     case nsVDPixmap::kPixFormat_YUV420_Planar:
  361.         if (halfchroma)
  362.             chroma_srcw = (chroma_srcw + 1) >> 1;
  363.         else
  364.             hfunc = horiz_compress2x_coaligned;
  365.  
  366.         vfunc = vert_compress2x_centered;
  367.         winstep = 2;
  368.         winposnext = 2;
  369.         winsize = 4;
  370.         h2 = (h+1) >> 1;
  371.         w2 = (w2+1) >> 1;
  372.         break;
  373.  
  374.     case nsVDPixmap::kPixFormat_YUV420_Planar_Centered:
  375.         if (halfchroma) {
  376.             chroma_srcw = (chroma_srcw + 1) >> 1;
  377.             hfunc = horiz_realign_to_centered;
  378.         } else
  379.             hfunc = horiz_compress2x_centered;
  380.  
  381.         vfunc = vert_compress2x_centered;
  382.         winstep = 2;
  383.         winposnext = 2;
  384.         winsize = 4;
  385.         h2 = (h+1) >> 1;
  386.         w2 = (w2+1) >> 1;
  387.         break;
  388.  
  389.     case nsVDPixmap::kPixFormat_YUV411_Planar:
  390.         if (halfchroma) {
  391.             chroma_srcw = (chroma_srcw + 1) >> 1;
  392.             hfunc = horiz_compress2x_coaligned;
  393.         } else
  394.             hfunc = horiz_compress4x_coaligned;
  395.         w2 = (w2+1) >> 2;
  396.         break;
  397.  
  398.     case nsVDPixmap::kPixFormat_YUV410_Planar:
  399.         if (halfchroma) {
  400.             chroma_srcw = (chroma_srcw + 1) >> 1;
  401.             hfunc = horiz_compress2x_coaligned;
  402.         } else
  403.             hfunc = horiz_compress4x_coaligned;
  404.         vfunc = vert_compress4x_centered;
  405.         winsize = 8;
  406.         winposnext = 5;
  407.         winstep = 4;
  408.         h2 = (h+3) >> 2;
  409.         w2 = (w2+3) >> 2;
  410.         break;
  411.     }
  412.  
  413. #ifdef _M_IX86
  414.     uint32 cpuflags = CPUGetEnabledExtensions();
  415.  
  416.     if (cpuflags & CPUF_SUPPORTS_INTEGER_SSE) {
  417.         if (hfunc == horiz_expand2x_coaligned)
  418.             hfunc = horiz_expand2x_coaligned_ISSE;
  419.     }
  420. #endif
  421.  
  422.     const uint8 *src = (const uint8 *)srcbm.data;
  423.     const ptrdiff_t srcpitch = srcbm.pitch;
  424.  
  425.     uint8 *ydst = (uint8 *)dstbm.data;
  426.     uint8 *cbdst = (uint8 *)dstbm.data2;
  427.     uint8 *crdst = (uint8 *)dstbm.data3;
  428.     const ptrdiff_t ydstpitch = dstbm.pitch;
  429.     const ptrdiff_t cbdstpitch = dstbm.pitch2;
  430.     const ptrdiff_t crdstpitch = dstbm.pitch3;
  431.  
  432.     if (!vfunc) {
  433.         if (hfunc) {
  434.             uint32 tmpsize = (w + 15) & ~15;
  435.  
  436.             vdblock<uint8> tmp(tmpsize * 2);
  437.             uint8 *const cbtmp = tmp.data();
  438.             uint8 *const crtmp = cbtmp + tmpsize;
  439.  
  440.             do {
  441.                 cfunc(ydst, cbtmp, crtmp, src, w);
  442.                 src += srcpitch;
  443.                 ydst += ydstpitch;
  444.                 hfunc(cbdst, cbtmp, chroma_srcw);
  445.                 hfunc(crdst, crtmp, chroma_srcw);
  446.                 cbdst += cbdstpitch;
  447.                 crdst += crdstpitch;
  448.             } while(--h);
  449.         } else if (dstbm.format == nsVDPixmap::kPixFormat_Y8) {
  450.             // wasteful, but oh well
  451.             uint32 tmpsize = (w2+15)&~15;
  452.             vdblock<uint8> tmp(tmpsize);
  453.  
  454.             cbdst = tmp.data();
  455.             crdst = cbdst + tmpsize;
  456.  
  457.             do {
  458.                 cfunc(ydst, cbdst, crdst, src, w);
  459.                 src += srcpitch;
  460.                 ydst += ydstpitch;
  461.             } while(--h2);
  462.         } else {
  463.             do {
  464.                 cfunc(ydst, cbdst, crdst, src, w);
  465.                 src += srcpitch;
  466.                 ydst += ydstpitch;
  467.                 cbdst += cbdstpitch;
  468.                 crdst += crdstpitch;
  469.             } while(--h2);
  470.         }
  471.     } else {
  472.         const uint32 tmpsize = w2;
  473.  
  474.         vdblock<uint8>        tmpbuf(tmpsize * (winsize + 1) * 2 + 2 * w);
  475.  
  476.         uint8 *cbwindow[16];
  477.         uint8 *crwindow[16];
  478.  
  479.         uint8 *p = tmpbuf.data();
  480.         for(int i=0; i<winsize; ++i) {
  481.             cbwindow[i] = cbwindow[winsize+i] = p;
  482.             p += tmpsize;
  483.             crwindow[i] = crwindow[winsize+i] = p;
  484.             p += tmpsize;
  485.         }
  486.  
  487.         uint8 *cbtmp = p;
  488.         uint8 *crtmp = p + w;
  489.  
  490.         int winoffset;
  491.         int winpos = winposnext - winsize;
  492.         bool firstline = true;
  493.  
  494.         do {
  495.             while(winpos < winposnext) {
  496.                 winoffset = ++winpos & (winsize - 1);
  497.  
  498.                 bool valid = (unsigned)(winpos-1) < (unsigned)(h-1);        // -1 because we generate line 0 as the first window line
  499.                 if (valid || firstline) {
  500.                     if (hfunc) {
  501.                         cfunc(ydst, cbtmp, crtmp, src, w);
  502.                         hfunc(cbwindow[winoffset + winsize - 1], cbtmp, chroma_srcw);
  503.                         hfunc(crwindow[winoffset + winsize - 1], crtmp, chroma_srcw);
  504.                     } else {
  505.                         cfunc(ydst, cbwindow[winoffset + winsize - 1], crwindow[winoffset + winsize - 1], src, w);
  506.                     }
  507.                     src += srcpitch;
  508.                     ydst += ydstpitch;
  509.                     firstline = false;
  510.                 } else {
  511.                     // dupe last generated line -- could be done by pointer swabbing, but I'm lazy
  512.                     memcpy(cbwindow[winoffset + winsize - 1], cbwindow[winoffset + winsize - 2], w2);
  513.                     memcpy(crwindow[winoffset + winsize - 1], crwindow[winoffset + winsize - 2], w2);
  514.                 }
  515.             }
  516.             winposnext += winstep;
  517.  
  518.             vfunc(cbdst, cbwindow + winoffset, w2, 0);
  519.             vfunc(crdst, crwindow + winoffset, w2, 0);
  520.             cbdst += cbdstpitch;
  521.             crdst += crdstpitch;
  522.         } while(--h2);
  523.     }
  524.  
  525. #ifdef _M_IX86
  526.     if (cpuflags & CPUF_SUPPORTS_MMX) {
  527.         __asm emms
  528.     }
  529. #endif
  530. }
  531.