home *** CD-ROM | disk | FTP | other *** search
/ PC Welt 2001 September / PC-WELT 9-2001.ISO / software / hw / brennen / flask_src.exe / YUVtoRGB.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2000-05-14  |  12.7 KB  |  531 lines

  1. /* 
  2.  *  YUVtoRGB.cpp 
  3.  *
  4.  *    Copyright (C) Alberto Vigata - January 2000 - ultraflask@yahoo.com
  5.  *
  6.  *  This file is part of FlasKMPEG, a free MPEG to MPEG/AVI converter
  7.  *    
  8.  *  FlasKMPEG is free software; you can redistribute it and/or modify
  9.  *  it under the terms of the GNU General Public License as published by
  10.  *  the Free Software Foundation; either version 2, or (at your option)
  11.  *  any later version.
  12.  *   
  13.  *  FlasKMPEG is distributed in the hope that it will be useful,
  14.  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.  *  GNU General Public License for more details.
  17.  *   
  18.  *  You should have received a copy of the GNU General Public License
  19.  *  along with GNU Make; see the file COPYING.  If not, write to
  20.  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. 
  21.  *
  22.  */
  23.  
  24. #include "mmx.h"
  25. #include <windows.h>
  26.  
  27. //////////////////////////////////////////////////////////////
  28. #include "YUVtoRGB.h"
  29.  
  30. static void YUVToRGB24(YUVPixel *Y_ptr, YUVPixel *U_ptr, YUVPixel *V_ptr, unsigned char *dst, long bpr, long w, long h);
  31. static void YUVToRGB16(YUVPixel *Y_ptr, YUVPixel *U_ptr, YUVPixel *V_ptr, unsigned char *dst, long bpr, long w, long h);
  32. static void YUVToUYVY16(YUVPixel *Y_ptr, YUVPixel *U_ptr, YUVPixel *V_ptr, unsigned char *dst, long bpr, long w, long h);
  33. static void YUVToYUYV16(YUVPixel *Y_ptr, YUVPixel *U_ptr, YUVPixel *V_ptr, unsigned char *dst, long bpr, long w, long h);
  34. static void YUVToYUV12(YUVPixel *Y_ptr, YUVPixel *U_ptr, YUVPixel *V_ptr, unsigned char *dst, long bpr, long w, long h);
  35. static long y_pitch, uv_pitch;
  36.  
  37.  
  38.  
  39. extern "C" void asm_YUVtoRGB32_row(
  40.         unsigned long *ARGB1_pointer,
  41.         unsigned long *ARGB2_pointer,
  42.         YUVPixel *Y1_pointer,
  43.         YUVPixel *Y2_pointer,
  44.         YUVPixel *U_pointer,
  45.         YUVPixel *V_pointer,
  46.         long width
  47.         );
  48.  
  49. extern "C" void asm_YUVtoRGB24_row(
  50.         unsigned long *ARGB1_pointer,
  51.         unsigned long *ARGB2_pointer,
  52.         YUVPixel *Y1_pointer,
  53.         YUVPixel *Y2_pointer,
  54.         YUVPixel *U_pointer,
  55.         YUVPixel *V_pointer,
  56.         long width
  57.         );
  58.  
  59. extern "C" void asm_YUVtoRGB16_row(
  60.         unsigned long *ARGB1_pointer,
  61.         unsigned long *ARGB2_pointer,
  62.         YUVPixel *Y1_pointer,
  63.         YUVPixel *Y2_pointer,
  64.         YUVPixel *U_pointer,
  65.         YUVPixel *V_pointer,
  66.         long width
  67.         );
  68.  
  69. void YUVToRGB32(YUVPixel *Y_ptr, YUVPixel *U_ptr, YUVPixel *V_ptr, unsigned char *dst, long bpr, long w, long h) {
  70.     dst = dst + bpr * (2*h - 2);
  71.         y_pitch    = bpr>>2;
  72.         uv_pitch= bpr>>3;
  73.     do {
  74.         asm_YUVtoRGB32_row(
  75.                 (unsigned long *)(dst + bpr),
  76.                 (unsigned long *)dst,
  77.                 Y_ptr,
  78.                 Y_ptr + y_pitch,
  79.                 U_ptr,
  80.                 V_ptr,
  81.                 w);
  82.  
  83.         dst = dst - 2*bpr;
  84.         Y_ptr = Y_ptr + 2*y_pitch;
  85.         U_ptr = U_ptr + uv_pitch;
  86.         V_ptr = V_ptr + uv_pitch;
  87.     } while(--h);
  88.  
  89.     if (MMX_enabled)
  90.         __asm emms
  91. }
  92.  
  93. // YUVtoRGB wrapper
  94. int YUVtoRGB(YUVimage *inp, unsigned char *dst)
  95. {
  96.     int oxsize,oysize;
  97.  
  98.     //Sanity checks
  99.     if (!inp)
  100.         return 0;
  101.     oxsize = inp->Yxsize;
  102.     oysize = inp->Yysize;
  103.  
  104.     if (inp->Yysize <= 0 || inp->Yysize >= 1024)
  105.         return 0;
  106.     if (inp->Cysize <= 0 || inp->Cysize >= 1024)
  107.         return 0;
  108.     if (inp->Y==NULL || inp->U==NULL || inp->V==NULL)
  109.         return 0;
  110.     YUVToRGB32(inp->Y, inp->U,inp->V, (unsigned char *)dst, oxsize*4, oxsize>>1, oysize>>1); 
  111.     return 1;
  112. }
  113.  
  114. static void YUVToRGB24(YUVPixel *Y_ptr, YUVPixel *U_ptr, YUVPixel *V_ptr, unsigned char *dst, long bpr, long w, long h) {
  115.     dst = dst + bpr * (2*h - 2);
  116.  
  117.     do {
  118.         asm_YUVtoRGB24_row(
  119.                 (unsigned long *)(dst + bpr),
  120.                 (unsigned long *)dst,
  121.                 Y_ptr,
  122.                 Y_ptr + y_pitch,
  123.                 U_ptr,
  124.                 V_ptr,
  125.                 w);
  126.  
  127.         dst = dst - 2*bpr;
  128.         Y_ptr = Y_ptr + 2*y_pitch;
  129.         U_ptr = U_ptr + uv_pitch;
  130.         V_ptr = V_ptr + uv_pitch;
  131.     } while(--h);
  132.  
  133.     if (MMX_enabled)
  134.         __asm emms
  135. }
  136. static void YUVToRGB16(YUVPixel *Y_ptr, YUVPixel *U_ptr, YUVPixel *V_ptr, unsigned char *dst, long bpr, long w, long h) {
  137.     dst = dst + bpr * (2*h - 2);
  138.  
  139.     do {
  140.         asm_YUVtoRGB16_row(
  141.                 (unsigned long *)(dst + bpr),
  142.                 (unsigned long *)dst,
  143.                 Y_ptr,
  144.                 Y_ptr + y_pitch,
  145.                 U_ptr,
  146.                 V_ptr,
  147.                 w);
  148.  
  149.         dst = dst - 2*bpr;
  150.         Y_ptr = Y_ptr + 2*y_pitch;
  151.         U_ptr = U_ptr + uv_pitch;
  152.         V_ptr = V_ptr + uv_pitch;
  153.     } while(--h);
  154.  
  155.     if (MMX_enabled)
  156.         __asm emms
  157. }
  158.  
  159. static void __declspec(naked) YUVtoUYVY16_MMX(
  160.                 YUVPixel *Y_ptr,        // [esp+4+16]
  161.                 YUVPixel *U_ptr,        // [esp+8+16]
  162.                 YUVPixel *V_ptr,        // [esp+12+16]
  163.                 unsigned char *dst,        // [esp+16+16]
  164.                 long bpr,                // [esp+20+16]
  165.                 long w,                    // [esp+24+16]
  166.                 long h) {                // [esp+28+16]
  167.  
  168.     __asm {
  169.         push        ebp
  170.         push        edi
  171.         push        esi
  172.         push        ebx
  173.  
  174.         mov            edx,[esp+24+16]            ;load width (mult of 8)
  175.  
  176.         mov            ebx,[esp+8+16]            ;load source U ptr
  177.         mov            ecx,[esp+12+16]            ;load source V ptr
  178.         mov            eax,[esp+4+16]            ;load source Y ptr
  179.         mov            edi,[esp+16+16]            ;load destination ptr
  180.         mov            esi,[esp+20+16]            ;load destination pitch
  181.         mov            ebp,[esp+28+16]            ;load height
  182.  
  183.         lea            ebx,[ebx+edx]            ;bias pointers
  184.         lea            ecx,[ecx+edx]            ;(we count from -n to 0)
  185.         lea            eax,[eax+edx*2]
  186.         lea            edi,[edi+edx*4]
  187.  
  188.         neg            edx
  189.         mov            [esp+24+16],edx
  190. xyloop:
  191.         movq        mm0,[ebx+edx]            ;U0-U7
  192.  
  193.         movq        mm7,[ecx+edx]            ;V0-V7
  194.         movq        mm2,mm0                    ;U0-U7
  195.  
  196.         movq        mm4,[eax+edx*2]
  197.         punpcklbw    mm0,mm7                    ;[V3][U3][V2][U2][V1][U1][V0][U0]
  198.  
  199.         movq        mm5,[eax+edx*2+8]
  200.         punpckhbw    mm2,mm7                    ;[V7][U7][V6][U6][V5][U5][V4][U4]
  201.  
  202.         movq        mm1,mm0
  203.         punpcklbw    mm0,mm4                    ;[Y3][V1][Y2][U1][Y1][V0][Y0][U0]
  204.  
  205.         punpckhbw    mm1,mm4                    ;[Y7][V3][Y6][U3][Y5][V2][Y4][U2]
  206.         movq        mm3,mm2
  207.  
  208.         movq        [edi+edx*4+ 0],mm0
  209.         punpcklbw    mm2,mm5                    ;[YB][V5][YA][U5][Y9][V4][Y8][U4]
  210.  
  211.         movq        [edi+edx*4+ 8],mm1
  212.         punpckhbw    mm3,mm5                    ;[YF][V7][YE][U7][YD][V6][YC][U6]
  213.  
  214.         movq        [edi+edx*4+16],mm2
  215.  
  216.         movq        [edi+edx*4+24],mm3
  217.  
  218.         add            edx,8
  219.         jnc            xyloop
  220.  
  221.         mov            edx,[esp+24+16]            ;reload width counter
  222.  
  223.         test        ebp,1                    ;update U/V row every other row only
  224.         jz            oddline
  225.  
  226.         sub            ebx,edx                    ;advance U pointer
  227.         sub            ecx,edx                    ;advance V pointer
  228.  
  229. oddline:
  230.         sub            eax,edx                    ;advance Y pointer
  231.         sub            eax,edx                    ;advance Y pointer
  232.  
  233.         add            edi,esi                    ;advance dest ptr
  234.  
  235.         dec            ebp
  236.         jne            xyloop
  237.  
  238.         pop            ebx
  239.         pop            esi
  240.         pop            edi
  241.         pop            ebp
  242.         emms
  243.         ret
  244.     }
  245. }
  246.  
  247. static void YUVToUYVY16(YUVPixel *Y_ptr, YUVPixel *U_ptr, YUVPixel *V_ptr, unsigned char *dst, long bpr, long w, long h) {
  248.     if (MMX_enabled) {
  249.         YUVtoUYVY16_MMX(Y_ptr, U_ptr, V_ptr, dst, bpr, w, h*2);
  250.         return;
  251.     }
  252.  
  253.     do {
  254.         int wt;
  255.  
  256.         wt = w;
  257.         do {
  258.             *dst++ = *U_ptr++;
  259.             *dst++ = *Y_ptr++;
  260.             *dst++ = *V_ptr++;
  261.             *dst++ = *Y_ptr++;
  262.         } while(--wt);
  263.  
  264.         U_ptr = U_ptr - uv_pitch;
  265.         V_ptr = V_ptr - uv_pitch;
  266.         
  267.         wt = w;
  268.         do {
  269.             *dst++ = *U_ptr++;
  270.             *dst++ = *Y_ptr++;
  271.             *dst++ = *V_ptr++;
  272.             *dst++ = *Y_ptr++;
  273.         } while(--wt);
  274.  
  275.     } while(--h);
  276. }
  277.  
  278. static void __declspec(naked) YUVtoYUYV16_MMX(
  279.                 YUVPixel *Y_ptr,        // [esp+4+16]
  280.                 YUVPixel *U_ptr,        // [esp+8+16]
  281.                 YUVPixel *V_ptr,        // [esp+12+16]
  282.                 unsigned char *dst,        // [esp+16+16]
  283.                 long bpr,                // [esp+20+16]
  284.                 long w,                    // [esp+24+16]
  285.                 long h) {                // [esp+28+16]
  286.  
  287.     __asm {
  288.         push        ebp
  289.         push        edi
  290.         push        esi
  291.         push        ebx
  292.  
  293.         mov            edx,[esp+24+16]            ;multiply width by 8
  294.  
  295.         mov            ebx,[esp+8+16]            ;load source U ptr
  296.         mov            ecx,[esp+12+16]            ;load source V ptr
  297.         mov            eax,[esp+4+16]            ;load source Y ptr
  298.         mov            edi,[esp+16+16]            ;load destination ptr
  299.         mov            esi,[esp+20+16]            ;load destination pitch
  300.         mov            ebp,[esp+28+16]            ;load height
  301.  
  302.         lea            ebx,[ebx+edx]            ;bias pointers
  303.         lea            ecx,[ecx+edx]            ;(we count from -n to 0)
  304.         lea            eax,[eax+edx*2]
  305.         lea            edi,[edi+edx*4]
  306.  
  307.         neg            edx
  308.         mov            [esp+24+16],edx
  309. xyloop:
  310.         movq        mm0,[ebx+edx]            ;U0-U7
  311.  
  312.         movq        mm7,[ecx+edx]            ;V0-V7
  313.         movq        mm1,mm0                    ;U0-U7
  314.  
  315.         movq        mm2,[eax+edx*2]            ;Y0-Y7
  316.         punpcklbw    mm0,mm7                    ;[V3][U3][V2][U2][V1][U1][V0][U0]
  317.  
  318.         movq        mm4,[eax+edx*2+8]        ;Y8-YF
  319.         punpckhbw    mm1,mm7                    ;[V7][U7][V6][U6][V5][U5][V4][U4]
  320.  
  321.         movq        mm3,mm2
  322.         punpcklbw    mm2,mm0                    ;[V1][Y3][U1][Y2][V0][Y1][U0][Y0]
  323.  
  324.         movq        mm5,mm4
  325.         punpckhbw    mm3,mm0                    ;[V3][Y7][U3][Y6][V2][Y5][U2][Y4]
  326.  
  327.         movq        [edi+edx*4+ 0],mm2
  328.         punpcklbw    mm4,mm1                    ;[V5][YB][U5][YA][V4][Y9][U4][Y8]
  329.  
  330.         movq        [edi+edx*4+ 8],mm3
  331.         punpckhbw    mm5,mm1                    ;[V7][YF][U7][YE][V6][YD][U6][YC]
  332.  
  333.         movq        [edi+edx*4+16],mm4
  334.  
  335.         movq        [edi+edx*4+24],mm5
  336.         add            edx,8
  337.  
  338.         jnc            xyloop
  339.  
  340.         mov            edx,[esp+24+16]            ;reload width counter
  341.  
  342.         test        ebp,1                    ;update U/V row every other row only
  343.         jz            oddline
  344.  
  345.         sub            ebx,edx                    ;advance U pointer
  346.         sub            ecx,edx                    ;advance V pointer
  347.  
  348. oddline:
  349.         sub            eax,edx                    ;advance Y pointer
  350.         sub            eax,edx                    ;advance Y pointer
  351.  
  352.         add            edi,esi                    ;advance dest ptr
  353.  
  354.         dec            ebp
  355.         jne            xyloop
  356.  
  357.         pop            ebx
  358.         pop            esi
  359.         pop            edi
  360.         pop            ebp
  361.         emms
  362.         ret
  363.     }
  364. }
  365.  
  366. static void YUVToYUYV16(YUVPixel *Y_ptr, YUVPixel *U_ptr, YUVPixel *V_ptr, unsigned char *dst, long bpr, long w, long h) {
  367.  
  368.     if (MMX_enabled) {
  369.         YUVtoYUYV16_MMX(Y_ptr, U_ptr, V_ptr, dst, bpr, w, h*2);
  370.         return;
  371.     }
  372.  
  373.     do {
  374.         int wt;
  375.  
  376.         wt = w;
  377.         do {
  378.             *dst++ = *Y_ptr++;
  379.             *dst++ = *U_ptr++;
  380.             *dst++ = *Y_ptr++;
  381.             *dst++ = *V_ptr++;
  382.         } while(--wt);
  383.  
  384.         U_ptr = U_ptr - uv_pitch;
  385.         V_ptr = V_ptr - uv_pitch;
  386.         
  387.         wt = w;
  388.         do {
  389.             *dst++ = *Y_ptr++;
  390.             *dst++ = *U_ptr++;
  391.             *dst++ = *Y_ptr++;
  392.             *dst++ = *V_ptr++;
  393.         } while(--wt);
  394.  
  395.     } while(--h);
  396. }
  397.  
  398. // Image manipulation
  399. #define ASM_COPY  __asm             \
  400. {                                    \
  401. __asm            mov ecx, runsize    \
  402. __asm            mov esi, i          \
  403. __asm           mov edi, o          \
  404. __asm            rep movsd           \
  405. }
  406.  
  407.  
  408. /*{                                      \
  409. __asm             mov ecx, runsize    \
  410. __asm            mov ebx, o          \
  411. __asm            mov edx, i            \
  412. __asm            mov eax, [edx]      \
  413. __asm            mov [ebx], eax      \
  414. __asm            add edx,4           \
  415. __asm            add ebx,4           \
  416. __asm           sub ecx,1           \
  417. __asm           cmp ecx,0           \
  418. __asm            jnz $-16            \
  419. }
  420. */
  421. void image_zero(YUVImageTag *input){
  422.     memset(input->Y, 0, input->Yxsize*input->Yysize );
  423.     memset(input->U, 0, input->Cxsize*input->Cysize );
  424.     memset(input->V, 0, input->Cxsize*input->Cysize );
  425. }
  426. void image_copy(YUVImageTag *output, YUVImageTag *input)
  427. {
  428.     int runsize, *i, *o;
  429.     if(output==NULL || input==NULL) return;
  430.  
  431.     runsize = (input->Yxsize*input->Yysize) >> 2;
  432.     o = (int *) output->Y;
  433.     i = (int *) input->Y;
  434.     ASM_COPY;
  435.         
  436.     runsize = (input->Cxsize*input->Cysize) >> 2;
  437.     o = (int *) output->U;
  438.     i = (int *) input->U;
  439.     ASM_COPY;
  440.  
  441.     o = (int *) output->V;
  442.     i = (int *) input->V;
  443.     ASM_COPY;
  444.  
  445.  
  446. /*    run_size = (input->Cxsize*input->Cysize) >> 2;
  447.     asm_copy((int *) output->U, (int *) input->U, run_size);
  448.     asm_copy((int *) output->V, (int *) input->V, run_size);*/
  449. /*    memcpy( output->Y, input->Y, input->Yxsize*input->Yysize );
  450.     memcpy( output->U, input->U, input->Cxsize*input->Cysize );
  451.     memcpy( output->V, input->V, input->Cxsize*input->Cysize );*/
  452.     return;
  453. }
  454. void field_copy_swap(YUVImageTag *output, YUVImageTag *input,  int field){
  455.     int y,first, runsize;
  456.     int *i, *o;
  457.     int swap;
  458.     if(output==NULL || input==NULL) return;
  459.     
  460.     if (field==1)
  461.         first=0;
  462.     else
  463.         first=1;
  464.  
  465.     swap = first ? -1 : 1;
  466.     
  467.     runsize = (input->Yxsize) >> 2;
  468.     for(y=first; y<input->Yysize; y=y+2){
  469.         o = (int *) &output->Y[(y+swap)*output->Yxsize];
  470.         i = (int *)  &input->Y[y*output->Yxsize];
  471.         ASM_COPY;
  472.     }
  473.  
  474.     runsize = (input->Cxsize) >> 2;
  475.     for(y=first; y<input->Cysize; y=y+2){
  476.         o = (int *) &output->U[(y+swap)*output->Cxsize];
  477.         i = (int *)  &input->U[y*output->Cxsize];
  478.         ASM_COPY;
  479.     }
  480.  
  481.     runsize = (input->Cxsize) >> 2;
  482.     for(y=first; y<input->Cysize; y=y+2){
  483.         o = (int *) &output->V[(y+swap)*output->Cxsize];
  484.         i = (int *)  &input->V[y*output->Cxsize];
  485.         ASM_COPY;
  486.     }
  487.     return;
  488. }
  489. void field_copy(YUVImageTag *output, YUVImageTag *input, int field)
  490. {
  491.     int y,first, runsize;
  492.     int *i, *o;
  493.     if(output==NULL || input==NULL) return;
  494.     
  495.     if (field==1)
  496.         first=0;
  497.     else
  498.         first=1;
  499.     
  500.     runsize = (input->Yxsize) >> 2;
  501.     for(y=first; y<input->Yysize; y=y+2){
  502.         o = (int *) &output->Y[y*output->Yxsize];
  503.         i = (int *)  &input->Y[y*output->Yxsize];
  504.         ASM_COPY;
  505.     }
  506.  
  507.     runsize = (input->Cxsize) >> 2;
  508.     for(y=first; y<input->Cysize; y=y+2){
  509.         o = (int *) &output->U[y*output->Cxsize];
  510.         i = (int *)  &input->U[y*output->Cxsize];
  511.         ASM_COPY;
  512.     }
  513.  
  514.     runsize = (input->Cxsize) >> 2;
  515.     for(y=first; y<input->Cysize; y=y+2){
  516.         o = (int *) &output->V[y*output->Cxsize];
  517.         i = (int *)  &input->V[y*output->Cxsize];
  518.         ASM_COPY;
  519.     }
  520.  
  521. /*    for(y=first; y<input->Cysize; y=y+2){
  522.         for(x=0; x<input->Cxsize; x++)
  523.             output->U[y*output->Cxsize + x] = input->U[y*input->Cxsize + x];
  524.     }
  525.     for(y=first; y<input->Cysize; y=y+2){
  526.         for(x=0; x<input->Cxsize; x++)
  527.             output->V[y*output->Cxsize + x] = input->V[y*input->Cxsize + x];
  528.     }
  529. */
  530.     return;
  531. }