home *** CD-ROM | disk | FTP | other *** search
/ Spidla DivX / DivX.bin / LocoCodec / loco.c < prev    next >
Encoding:
C/C++ Source or Header  |  2003-04-27  |  22.0 KB  |  940 lines

  1. /* loco.c -- A video compression codec based loosely on LOCO-I
  2.  
  3.     Copyright (C) 2003  Mohammad Rezaei
  4.  
  5.     Author: Mohammad Rezaei
  6.  
  7.   This program is free software; you can redistribute it and/or
  8.   modify it under the terms of the GNU General Public License
  9.   as published by the Free Software Foundation; either version 2
  10.   of the License, or (at your option) any later version.
  11.  
  12.   This program is distributed in the hope that it will be useful,
  13.   but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.   GNU General Public License for more details.
  16.  
  17.   You should have received a copy of the GNU General Public License
  18.   along with this program; if not, write to the Free Software
  19.   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  20.  
  21.   ---------
  22.   */
  23.  
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. #include "loco.h"
  27. #define MAX_NUM_ERR 16
  28.  
  29.  
  30. #ifdef FREQ_OUTPUT
  31. int freq_initialized = 0;
  32. int freq[512];
  33. int frame = 0;
  34. #endif
  35.  
  36. #define MSG_OUTPUT
  37. #ifdef MSG_OUTPUT
  38. #define LOG_LINE 3
  39.  
  40.  
  41. static int this_line = 0;
  42. #include <windows.h>
  43.  
  44. /* ---------------------------------------- */
  45.  
  46. static void Msg(const char fmt[], ...) {
  47.   static int debug = 0;
  48.   
  49.   debug = GetPrivateProfileInt("debug", "log", 0, "lococodec.ini");
  50.   if (!debug) return;
  51.   else
  52.   {
  53.     DWORD written;
  54.     char buf[2000];
  55.     const COORD _80x50 = {80,500};
  56.     static BOOL startup = 0;
  57.     va_list val;
  58.  
  59.  
  60.     va_start(val, fmt);
  61.     wvsprintf(buf, fmt, val);
  62.  
  63.     startup = (AllocConsole(), SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), _80x50));
  64.     WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), buf, lstrlen(buf), &written, 0);
  65.   }
  66. }
  67. #endif
  68.  
  69.  
  70. /* ---------------------------------------- */
  71. /* Bit-IO Routines */
  72.  
  73. #include <limits.h>
  74.  
  75.  
  76.  
  77.  
  78. __inline static void write_bit_buffer(struct prediction_info *pi)
  79. {
  80.   *(pi->buffer) = pi->bit_buffer;
  81.   pi->buffer++;
  82.   pi->num_bits_in_buf = 0;
  83.   pi->bit_buffer = 0;
  84.  
  85. }
  86.  
  87. /* Flush any remaining bits. */
  88. __inline static void flush_bits(struct prediction_info *pi)
  89. {
  90.   if (pi->num_bits_in_buf > 0)
  91.     write_bit_buffer(pi);
  92. }
  93.  
  94. /* Write a bunch of zeros */
  95. __inline static void output_zero_bits(struct prediction_info *pi, int bits)
  96. {
  97.   pi->num_bits_in_buf+= bits;
  98.  
  99.   while (pi->num_bits_in_buf >= CHAR_BIT)
  100.   {
  101.     *(pi->buffer) = pi->bit_buffer;
  102.   //if (pi->bit_buffer == 111) Msg("found 111 %d\n",this_line);
  103.     pi->buffer++;
  104.     pi->num_bits_in_buf -= CHAR_BIT;
  105.     pi->bit_buffer = 0;
  106.   }
  107. }
  108.  
  109. /* Write one bit. */
  110. __inline static void output_one_bit(struct prediction_info *pi)
  111. {
  112.   pi->bit_buffer |= (1 << (CHAR_BIT-1-pi->num_bits_in_buf));  /* fill from the left */
  113.   pi->num_bits_in_buf++;
  114.  
  115.   if (pi->num_bits_in_buf == CHAR_BIT)
  116.     write_bit_buffer(pi);
  117. }
  118.  
  119. __inline static void copy_bits(struct prediction_info *pi, unsigned int from, int len)
  120. {
  121.   if (len == 0) return;
  122.   from &= ((1 << len)-1);
  123.   while(len > CHAR_BIT - pi->num_bits_in_buf)
  124.   {
  125.     pi->bit_buffer |= (from >> (len-CHAR_BIT+pi->num_bits_in_buf));
  126.     len -= (CHAR_BIT-pi->num_bits_in_buf);
  127.     from &= (1 << (len+1))-1;
  128.     *(pi->buffer) = pi->bit_buffer;
  129.     pi->buffer++;
  130.     pi->num_bits_in_buf = 0;
  131.     pi->bit_buffer = 0;
  132.  
  133.   }
  134.   if (len == 0) return;
  135.   pi->bit_buffer |= (from << (CHAR_BIT-len-pi->num_bits_in_buf));
  136.   pi->num_bits_in_buf += len;
  137.   if (pi->num_bits_in_buf == CHAR_BIT)
  138.     write_bit_buffer(pi);
  139. }
  140.  
  141.  
  142. /* Read one bit. */
  143. __inline static int input_bit(struct prediction_info *pi)
  144. {
  145.   if (pi->num_bits_in_buf == 0) {
  146.     pi->bit_buffer = (unsigned char)(*(pi->buffer));
  147.       pi->buffer++;
  148.     pi->num_bits_in_buf += CHAR_BIT; /* This might be too much. The application must
  149.                     figure-out the exact end of the bitstream. */
  150.   }
  151.  
  152.   pi->num_bits_in_buf--;
  153.   return (pi->bit_buffer & (1 << pi->num_bits_in_buf)) > 0;
  154. }
  155.  
  156. __inline static void flush_run_length(struct prediction_info *pip)
  157. {
  158.   if (pip->run_length > 0 && pip->saved_bits >= 0)
  159.   {
  160.     int x = pip->run_length-1;
  161.     int quot = x >> 2;
  162.     unsigned int rem = x&3;
  163.     output_zero_bits(pip, quot);
  164.     output_one_bit(pip);
  165.     copy_bits(pip, rem, 2);
  166.   }
  167.   if (pip->run_length > 2) pip->saved_bits+= pip->run_length;
  168.   else pip->saved_bits-=3;
  169.   pip->run_length = 0;
  170. }
  171.  
  172. /* ---------------------------------------- */
  173. /* Rice Coding Routines */
  174.  
  175. /* Write the Rice(b) code for X on stdout. X is a nonnegative integer. B
  176.    must be a strictly positive integer. */
  177. __inline static void rice_encode(struct prediction_info *pip, unsigned int x, unsigned int log_b)
  178. {
  179.  
  180. #ifdef FREQ_OUTPUT
  181.   freq[x]++;
  182. #endif
  183.   if (x == 0)
  184.   {
  185.     if (pip->run_length == 0 || pip->saved_bits < 0)
  186.     {
  187.       output_one_bit(pip);
  188.       output_zero_bits(pip, log_b);
  189.     }
  190.     pip->run_length++;
  191.   }
  192.   else 
  193.   {
  194.     int quot = x >> log_b;
  195.     unsigned int rem = x&((1 << log_b)-1);
  196.     if (pip->run_length > 0)
  197.     {
  198.       flush_run_length(pip);
  199.     }
  200.     output_zero_bits(pip, quot);
  201.     output_one_bit(pip);
  202.  
  203.     copy_bits(pip, rem, log_b);
  204.   }
  205.  
  206. }
  207.  
  208. /* Read the next Rice(b) code and return it. */
  209. __inline static int rice_decode(struct prediction_info *pip, unsigned int log_b)
  210. {
  211.   unsigned int quot, r;
  212.   int i;
  213.  
  214.   if (pip->run_length > 0)
  215.   {
  216.     pip->run_length--;
  217.     return 0;
  218.   }
  219.  
  220.   for (quot=0; input_bit(pip) == 0; quot++);
  221.   r = quot << log_b;
  222.   for (i=log_b-1; i>=0; i--) r = r | (input_bit(pip) << i);
  223.   if (r == 0)
  224.   {
  225.     if (pip->saved_bits >= 0)
  226.     {
  227.       for (quot=0; input_bit(pip) == 0; quot++);
  228.       pip->run_length  = quot << 2;
  229.       for (i=1; i>=0; i--) pip->run_length |= (input_bit(pip) << i);
  230.       if (pip->run_length > 1) pip->saved_bits+=pip->run_length+1;
  231.       else pip->saved_bits-=3;
  232.     }
  233.     else pip->decode_run_length++;
  234.   }
  235.   else if (pip->decode_run_length > 0)
  236.   {
  237.     if (pip->decode_run_length > 2) pip->saved_bits+=pip->decode_run_length;
  238.     else pip->saved_bits-=3;
  239.     pip->decode_run_length = 0;
  240.   }
  241.   return r;
  242. }
  243.  
  244. __inline static int calcLoco(struct prediction_info *pip)
  245. {
  246.   int c = *(pip->prevLine-pip->xStep);
  247.   int a = *(pip->prevLine);
  248.   int b = *(pip->currentLine-pip->xStep);
  249.   int minab = a < b ? a : b;
  250.   int maxab = a > b ? a : b;
  251.   int result;
  252.   if (c >= maxab) result = minab;
  253.   else if (c <= minab) result = maxab;
  254.   else result = a+b-c;
  255.   pip->prevLine += pip->xStep;
  256.   return result;
  257.  
  258. }
  259.  
  260. __inline static void calcLoco16(struct prediction_info *pip)
  261. {
  262. #define SSE2
  263. #ifdef SSE2
  264.   unsigned char * prev = pip->prevLine;
  265.   unsigned char * curr = pip->currentLine;
  266.   short * coded = pip->coded_error;
  267.   short * abs_err = pip->abs_error;
  268.   __asm
  269.   {
  270.     mov eax, prev
  271.     movdqa xmm2, XMMWORD PTR[eax-1] // xmm2 = c
  272.     movdqu xmm0, XMMWORD PTR[eax] // xmm0 = a
  273.     mov ebx, curr
  274.     movdqa xmm1, XMMWORD PTR[ebx-1] // xmm1 = b
  275.     movdqa xmm3, xmm0 // xmm3 = a
  276.     pminub xmm0, xmm1 // xmm0 is now min
  277.     pmaxub xmm1, xmm3 // xmm1 is now max
  278.     movdqa xmm4, xmm2 // xmm4 = c
  279.     pminub xmm4, xmm0 // xmm4 = min(c, min(a,b))
  280.     movdqa xmm3, xmm2 // xmm3 = c
  281.     pmaxub xmm3, xmm1 // xmm3 = max(c, max(a,b))
  282.     pcmpeqb xmm4, xmm2 // xmm4 = (c <= min(a,b))
  283.     pcmpeqb xmm3, xmm2 // xmm3 = (c >= max(a,b))
  284.     movdqa xmm7, xmm3
  285.     por xmm7, xmm4
  286.     pandn xmm7, xmm2 // xmm7 = c &&! (c >= max || c <= min)
  287.     movdqa xmm2, xmm4
  288.     pandn xmm2, xmm0 // xmm2 = min &&! c<=min
  289.     pandn xmm4, xmm3
  290.     pandn xmm4, xmm1 // xmm4 = max &&! (c>=max &&! c<=min)
  291.  
  292.     movdqu xmm5, XMMWORD PTR[ebx] // xmm5 = current pixel
  293.     
  294.     pxor xmm1, xmm1 // xmm1 = 0
  295.     punpcklbw xmm1, xmm2
  296.     psrldq xmm1, 1
  297.     pxor xmm3, xmm3
  298.     punpcklbw xmm3, xmm4
  299.     psrldq xmm3, 1
  300.     paddsw xmm1, xmm3
  301.     pxor xmm3, xmm3
  302.     punpcklbw xmm3, xmm7
  303.     psrldq xmm3, 1
  304.     psubsw xmm1, xmm3
  305.     pxor xmm3, xmm3
  306.     punpcklbw xmm3, xmm5
  307.     psrldq xmm3, 1
  308.     psubsw xmm1, xmm3
  309.  
  310.     pxor xmm3, xmm3
  311.     psubsw xmm3, xmm1 // xmm3 = -xmm1
  312.     
  313.     pmaxsw xmm3, xmm1 // xmm3 = abs(xmm1)
  314.  
  315.     pxor xmm0, xmm0 // xmm0 = 0
  316.     mov ebx, abs_err
  317.     movdqa XMMWORD PTR[ebx], xmm3
  318.  
  319.     mov eax, coded
  320.  
  321.     psllw xmm3, 1 // xmm3 <<= 1
  322.     pcmpgtw xmm1, xmm0 // error > 0
  323.     psrlw xmm1, 15 // make FF's into 1's
  324.     psubsw xmm3, xmm1 // xmm3 -= xmm1
  325.  
  326.     movdqa XMMWORD PTR[eax], xmm3
  327.  
  328.     pxor xmm3, xmm3
  329.     punpckhbw xmm2, xmm3
  330.     punpckhbw xmm4, xmm3
  331.     paddsw xmm2, xmm4
  332.     punpckhbw xmm7, xmm3
  333.     psubsw xmm2, xmm7
  334.     punpckhbw xmm5, xmm3
  335.     psubsw xmm2, xmm5
  336.  
  337.     psubsw xmm3, xmm2 // xmm3 = -xmm2
  338.     pmaxsw xmm3, xmm2 // xmm3 = abs(xmm2)
  339.  
  340.     movdqa XMMWORD PTR[ebx+16], xmm3
  341.  
  342.     psllw xmm3, 1
  343.     pcmpgtw xmm2, xmm0
  344.     psrlw xmm2, 15
  345.     psubsw xmm3, xmm2
  346.  
  347.     movdqa XMMWORD PTR[eax+16], xmm3
  348.  
  349.   }
  350.   pip->prevLine += 16;
  351.   pip->currentLine += 16;
  352. #else
  353.   int i;
  354.   for(i=0;i<16;i++)
  355.   {
  356.     int c = *(pip->prevLine-1);
  357.     int a = *(pip->prevLine);
  358.     int b = *(pip->currentLine-1);
  359.     int minab = a < b ? a : b;
  360.     int maxab = a > b ? a : b;
  361.     int result;
  362.     if (c >= maxab) result = minab;
  363.     else if (c <= minab) result = maxab;
  364.     else result = a+b-c;
  365.     pip->prevLine++;
  366.     result -= *(pip->currentLine);
  367.     pip->currentLine++;
  368.     pip->abs_error[i] = result > 0 ? result : -result;
  369.     pip->coded_error[i] = (pip->abs_error[i] << 1) - (result >=1);
  370.   }
  371. #endif
  372.  
  373. }
  374.  
  375. __inline static void calcLocoTop(struct prediction_info *pip, int j)
  376. {
  377.   if (j > 0)
  378.     pip->mean = *(pip->currentLine-pip->xStep);
  379.   else
  380.     pip->mean = 128;
  381. }
  382.  
  383. __inline static void calcLocoLeft(struct prediction_info *pip)
  384. {
  385.   pip->mean = *(pip->prevLine);
  386.   pip->prevLine += pip->xStep;
  387. }
  388.  
  389.  
  390. __inline static int rice_param(struct prediction_info *pip)
  391. {
  392.   int n = pip->num_err;
  393.   int a = pip->abs_err;
  394.  
  395.   if (n >= a) return 0;
  396.   if ((n += n) >= a) return 1;
  397.   if ((n += n) >= a) return 2;
  398.   if ((n += n) >= a) return 3;
  399.   if ((n += n) >= a) return 4;
  400.   if ((n += n) >= a) return 5;
  401.   if ((n += n) >= a) return 6;
  402.   if ((n += n) >= a) return 7;
  403.   if ((n += n) >= a) return 8;
  404.   return 9;
  405. }
  406.  
  407. /* have the Rice coder generate a compressed
  408.    representation for pip->pict[i][j] using the mean and Rice parameter */
  409. __inline static void comp_one_pel(struct prediction_info *pip)
  410. {
  411.   int e, mapped_err;
  412.  
  413.   int rice = rice_param(pip);
  414.  
  415.   /* Code the actual pixel: */
  416.   e = pip->mean - *(pip->currentLine);
  417.   pip->currentLine += pip->xStep;
  418.   mapped_err = (e > 0 ? e : -e) ;
  419.   pip->abs_err += mapped_err;
  420.   mapped_err <<= 1;
  421.   mapped_err -= (e >= 1);
  422.   pip->num_err++;
  423.   
  424.   rice_encode(pip, mapped_err, rice);
  425.   if (pip->num_err == MAX_NUM_ERR)
  426.   {
  427.     pip->num_err >>= 1;
  428.     pip->abs_err >>= 1;
  429.   }
  430.  
  431.  
  432. }
  433.  
  434. /* have the Rice coder generate a compressed
  435.    representation for pip->pict[i][j] using the mean and Rice parameter */
  436. __inline static void comp_one_pel_lossy(struct prediction_info *pip)
  437. {
  438.   int e, mapped_err;
  439.  
  440.   int rice = rice_param(pip);
  441.  
  442.   /* Code the actual pixel: */
  443.   e = pip->mean - *(pip->currentLine);
  444.   mapped_err = (e > 0 ? e : -e) ;
  445.   if (mapped_err <= pip->max_loss)
  446.   {
  447.     *(pip->currentLine) = pip->mean;
  448.     mapped_err = 0;
  449.   }
  450.   else
  451.   {
  452.     mapped_err -= pip->max_loss;
  453.     pip->abs_err += mapped_err;
  454.     mapped_err <<= 1;
  455.     mapped_err -= (e >= 1);
  456.   }
  457.   pip->currentLine += pip->xStep;
  458.   pip->num_err++;
  459.   
  460.   rice_encode(pip, mapped_err, rice);
  461.   if (pip->num_err == MAX_NUM_ERR)
  462.   {
  463.     pip->num_err >>= 1;
  464.     pip->abs_err >>= 1;
  465.   }
  466.  
  467.  
  468. }
  469.  
  470. __inline static void comp_16_pel(struct prediction_info *pip)
  471. {
  472.   int i;
  473.   for(i=0;i<16;i++)
  474.   {
  475.     int rice = rice_param(pip);
  476.  
  477.     pip->abs_err += pip->abs_error[i];
  478.     pip->num_err++;
  479.   
  480.     rice_encode(pip, pip->coded_error[i], rice);
  481.     if (pip->num_err == MAX_NUM_ERR)
  482.     {
  483.       pip->num_err >>= 1;
  484.       pip->abs_err >>= 1;
  485.     }
  486.   }
  487.  
  488.  
  489. }
  490.  
  491.  
  492. /*  decode the next pixel. */
  493. __inline static void decomp_one_pel(struct prediction_info *pip)
  494. {
  495.   int e, mapped_err;
  496.   int rice = rice_param(pip);
  497.  
  498.   /* decode the actual pixel: */
  499.   mapped_err = rice_decode(pip, rice);
  500.   if (mapped_err > 0)
  501.   {
  502.     e = (mapped_err & 1) ? (mapped_err+1)>>1 : -(mapped_err >> 1);
  503.     pip->abs_err += e > 0 ? e: -e;
  504.     if (e > 0)
  505.     {
  506.       e += pip->max_loss;
  507.     }
  508.     else if (e < 0)
  509.     {
  510.       e -= pip->max_loss;
  511.     }
  512.  
  513.   }
  514.   else e = 0;
  515.  
  516.   pip->num_err++;
  517.   if (pip->num_err == MAX_NUM_ERR)
  518.   {
  519.     pip->num_err >>= 1;
  520.     pip->abs_err >>= 1;
  521.   }
  522.  
  523.   *(pip->currentLine) = pip->mean - e;
  524.   pip->currentLine += pip->xStep;
  525.   
  526.  
  527. }
  528.  
  529. void initialize_pi(struct prediction_info *pi, unsigned char *imageBuffer, unsigned char *outBuffer, int height, int width, int xOffset, 
  530.               int xStep, int yOffset, int yStep, int maxLoss)
  531. {
  532.   /* INITIALIZATIONS: */
  533.   pi->xStep = xStep;
  534.   pi->yStride = width*yStep;
  535.   pi->effectiveHeight = height/yStep-yOffset/yStep;
  536.   pi->effectiveWidth = width/xStep-xOffset/xStep;
  537.   pi->buffer = outBuffer;
  538.   pi->currentLine = imageBuffer+yOffset*pi->yStride+xOffset;
  539.   pi->prevLine = pi->currentLine;
  540.   pi->max_loss = maxLoss;
  541.  
  542.   pi->num_bits_in_buf = 0;
  543.   pi->bit_buffer = 0;
  544.   pi->abs_err = 8;
  545.   pi->num_err = 1;
  546.   pi->run_length = 0;
  547.   pi->decode_run_length = 0;
  548.   pi->saved_bits = 0;
  549. //  this_line = 0;
  550. }
  551.  
  552. __inline static void copyLine(unsigned char *dest, unsigned char *src, int xOffset, int xStep, int width)
  553. {
  554.   int i;
  555.   int j=xOffset;
  556.   for(i=0;i<width;i++,j+=xStep)
  557.   {
  558.     dest[i] = src[j];
  559.   }
  560. }
  561.  
  562. __inline static void copyLine1(unsigned char *dest, unsigned char *src, int xOffset, int width)
  563. {
  564. #ifdef SSE2
  565.   int i;
  566.   int end;
  567.   unsigned char *end_ptr;
  568.   end = width;
  569.   if ((width - 1) % 16)
  570.   {
  571.     end -= (width - 1) % 16;
  572.   }
  573.   end_ptr = dest+end;
  574.   __asm {
  575.     mov eax, dest
  576.     mov ebx, src
  577.     add ebx, xOffset
  578. START_LOOP_1:
  579.     movdqu xmm0, XMMWORD PTR[ebx]
  580.     add ebx, 16
  581.     movdqa XMMWORD PTR[eax], xmm0
  582.     add eax, 16
  583.     cmp eax, end_ptr
  584.     jl    SHORT START_LOOP_1
  585.   }
  586.   for(i=end;i<width;i++)
  587.   {
  588.     dest[i] = src[i+xOffset];
  589.   }
  590. #else
  591.   copyLine(dest, src, xOffset, 1, width);
  592. #endif
  593. }
  594.  
  595. __inline static void copyLine2(unsigned char *dest, unsigned char *src, int xOffset, int width)
  596. {
  597. #ifdef SSE2
  598.   int i,j;
  599.   int end;
  600.   unsigned char *end_ptr;
  601.   end = width;
  602.   if ((width - 1) % 16)
  603.   {
  604.     end -= (width - 1) % 16;
  605.   }
  606.   end_ptr = dest+end;
  607.  
  608.   __asm {
  609.     mov eax, dest
  610.     mov ebx, src
  611.     add ebx, xOffset
  612.     pcmpeqb xmm4, xmm4
  613.     psrlw xmm4, 8
  614. START_LOOP_2:
  615.     movdqu xmm0, XMMWORD PTR[ebx]
  616.     movdqu xmm1, XMMWORD PTR[ebx+16]
  617.     pand xmm0, xmm4
  618.     pand xmm1, xmm4
  619.     packuswb xmm0, xmm1
  620.     add ebx, 32
  621.     movdqa XMMWORD PTR[eax], xmm0
  622.     add eax, 16
  623.     cmp eax, end_ptr
  624.     jl    SHORT START_LOOP_2
  625.   }
  626.   j=(end << 1)+xOffset;
  627.   for(i=end;i<width;i++,j+=2)
  628.   {
  629.     dest[i] = src[j];
  630.   }
  631. #else
  632.   copyLine(dest, src, xOffset, 2, width);
  633. #endif
  634. }
  635.  
  636. __inline static void copyLine3(unsigned char *dest, unsigned char *src, int xOffset, int width)
  637. {
  638.   copyLine(dest, src, xOffset, 3, width);
  639. }
  640.  
  641. __inline static void copyLine4(unsigned char *dest, unsigned char *src, int xOffset, int width)
  642. {
  643. #ifdef SSE2
  644.   int i,j;
  645.   int end;
  646.   unsigned char *end_ptr;
  647.   end = width;
  648.   if ((width - 1) % 16)
  649.   {
  650.     end -= (width - 1) % 16;
  651.   }
  652.   end_ptr = dest+end;
  653.   __asm {
  654.     mov eax, dest
  655.     mov ebx, src
  656.     add ebx, xOffset
  657.     pcmpeqb xmm4, xmm4
  658.     psrld xmm4, 24
  659. START_LOOP_4:
  660.     movdqu xmm0, XMMWORD PTR[ebx]
  661.     movdqu xmm1, XMMWORD PTR[ebx+16]
  662.     pand xmm0, xmm4
  663.     pand xmm1, xmm4
  664.     packuswb xmm0, xmm1
  665.     add ebx, 32
  666.  
  667.     movdqu xmm1, XMMWORD PTR[ebx]
  668.     movdqu xmm2, XMMWORD PTR[ebx+16]
  669.     pand xmm1, xmm4
  670.     pand xmm2, xmm4
  671.     packuswb xmm1, xmm2
  672.     packuswb xmm0, xmm1
  673.     add ebx, 32
  674.     movdqa XMMWORD PTR[eax], xmm0
  675.     add eax, 16
  676.     cmp eax, end_ptr
  677.     jl    SHORT START_LOOP_4
  678.  
  679.   }
  680.   j=(end << 2)+xOffset;
  681.   for(i=end;i<width;i++,j+=4)
  682.   {
  683.     dest[i] = src[j];
  684.   }
  685. #else
  686.   copyLine(dest, src, xOffset, 4, width);
  687. #endif
  688. }
  689.  
  690. void (*copy_line_array[4])(unsigned char *dest, unsigned char *src, int xOffset, int width)
  691. = {copyLine1, copyLine2, copyLine3, copyLine4};
  692.  
  693.  
  694.  
  695. __inline void *alloc_buffers(struct prediction_info *pip)
  696. {
  697.   int size = (pip->effectiveWidth << 1)*sizeof(char) + 32*sizeof(short)+32;
  698.  
  699.   return malloc(size);
  700. }
  701.  
  702. #ifndef SSE2
  703. unsigned char * loco_codec_compress_non_vector(unsigned char *inBuffer, unsigned char *outBuffer, 
  704.                                                int height, int width, int xOffset, 
  705.               int xStep, int yOffset, int yStep)
  706. {
  707.   int i,j;
  708.   struct prediction_info pi;
  709.  
  710.   initialize_pi(&pi, inBuffer, outBuffer, height, width, xOffset, xStep, yOffset, yStep, 0);
  711.  
  712.   // first line
  713.   for (j = 0; j < pi.effectiveWidth; j++) {
  714.     calcLocoTop(&pi, j);
  715.     comp_one_pel(&pi);
  716.   }
  717.   /* MAIN LOOP: */
  718.   for (i = 1; i < pi.effectiveHeight; i++)
  719.   {
  720.     // left most pixel
  721.     calcLocoLeft(&pi);
  722.     comp_one_pel(&pi);
  723.     for (j = 1; j < pi.effectiveWidth; j++) {
  724.       pi.mean = calcLoco(&pi);
  725.       comp_one_pel(&pi);
  726.     }
  727.   }
  728.  
  729.  
  730.   
  731.   /* CLEAN-UP: */
  732.   flush_run_length(&pi);
  733.   flush_bits(&pi);
  734.  
  735.   return pi.buffer;
  736. }
  737. #endif
  738.  
  739. #ifdef FREQ_OUTPUT
  740. void print_freq()
  741. {
  742.   int i=0;
  743.  
  744.   for(i =0;i<512;i++) Msg("%d ..%d ~",i,freq[i]);
  745.   Msg("\n");
  746.  
  747. }
  748. #endif
  749.  
  750. unsigned char * loco_codec_compress(unsigned char *inBuffer, unsigned char *outBuffer, int height, int width, int xOffset, 
  751.               int xStep, int yOffset, int yStep)
  752. {
  753.   int i,j, end;
  754.   struct prediction_info pi;
  755.   unsigned char *currentBuffer, *prevBuffer, *tmp;
  756.   void *tmp_buffer;
  757.   void (*copy_line_ptr)(unsigned char *dest, unsigned char *src, int xOffset, int width);
  758.  
  759.   copy_line_ptr = copy_line_array[xStep-1];
  760.  
  761.   initialize_pi(&pi, inBuffer, outBuffer, height, width, xOffset, xStep, yOffset, yStep, 0);
  762.  
  763.   tmp_buffer = alloc_buffers(&pi);
  764.  
  765.  
  766.   pi.abs_error = (short *)(((unsigned int)tmp_buffer+15) & ~15 );
  767.   pi.coded_error = pi.abs_error + 16;
  768.   currentBuffer = (unsigned char *) (pi.coded_error + 16);
  769.   tmp = currentBuffer + pi.effectiveWidth;
  770.   prevBuffer = (unsigned char *)(((unsigned int)tmp+15) & ~15 );
  771.  
  772.   pi.xStep = 1;
  773.   end = pi.effectiveWidth;
  774.   if ((pi.effectiveWidth - 1) % 16)
  775.   {
  776.     end -= (pi.effectiveWidth - 1) % 16;
  777.   }
  778.   (*copy_line_ptr)(currentBuffer, inBuffer, xOffset, pi.effectiveWidth);
  779.   pi.currentLine = currentBuffer;
  780.   // first line
  781.   for (j = 0; j < pi.effectiveWidth; j++) {
  782.     calcLocoTop(&pi, j);
  783.     comp_one_pel(&pi);
  784.   }
  785.   /* MAIN LOOP: */
  786.   for (i = 1; i < pi.effectiveHeight; i++)
  787.   {
  788.     tmp = prevBuffer;
  789.     prevBuffer = currentBuffer;
  790.     currentBuffer = tmp;
  791.     pi.prevLine = prevBuffer;
  792.     (*copy_line_ptr)(currentBuffer, inBuffer+i*pi.yStride, xOffset, pi.effectiveWidth);
  793.     pi.currentLine = currentBuffer;
  794.     // left most pixel
  795.     calcLocoLeft(&pi);
  796.     comp_one_pel(&pi);
  797.     for (j = 1; j < end; j+=16) {
  798.       calcLoco16(&pi);
  799.       comp_16_pel(&pi);
  800.     }
  801.     for(;j< pi.effectiveWidth;j++)
  802.     {
  803.       pi.mean = calcLoco(&pi);
  804.       comp_one_pel(&pi);
  805.     }
  806.   }
  807.  
  808.  
  809.   
  810.   /* CLEAN-UP: */
  811.   flush_run_length(&pi);
  812.   flush_bits(&pi);
  813.   free(tmp_buffer);
  814.  
  815. #ifdef FREQ_OUTPUT
  816.   frame++;
  817.   if (frame % 100 == 0)
  818.   {
  819.     print_freq();
  820.   }
  821. #endif
  822.  
  823.   return pi.buffer;
  824. }
  825.  
  826. #ifdef FREQ_OUTPUT
  827. void initialize_freq()
  828. {
  829.   int i;
  830.   if (!freq_initialized)
  831.   {
  832.     for(i=0;i<512;i++) freq[i] = 0;
  833.     freq_initialized = 1;
  834.   }
  835. }
  836. #endif
  837.  
  838. unsigned char * loco_codec_compress_lossy(unsigned char *inBuffer, unsigned char *outBuffer, int height, int width, int xOffset, 
  839.               int xStep, int yOffset, int yStep, int maxLoss)
  840. {
  841.   int i,j;
  842.   struct prediction_info pi;
  843.   unsigned char *currentBuffer, *prevBuffer, *tmp;
  844.   void *tmp_buffer;
  845.  
  846. #ifdef FREQ_OUTPUT
  847.   initialize_freq();
  848. #endif
  849. #ifdef SSE2
  850.   if (maxLoss == 0) return loco_codec_compress(inBuffer, outBuffer, height, width, xOffset, 
  851.     xStep, yOffset, yStep);
  852. #else
  853.   if (maxLoss == 0) return loco_codec_compress_non_vector(inBuffer, outBuffer, height, width, xOffset, 
  854.     xStep, yOffset, yStep);
  855. #endif
  856.  
  857.  
  858.   initialize_pi(&pi, inBuffer, outBuffer, height, width, xOffset, xStep, yOffset, yStep, maxLoss);
  859.  
  860.   tmp_buffer = alloc_buffers(&pi);
  861.  
  862.  
  863.   pi.abs_error = (short *)(((unsigned int)tmp_buffer+15) & ~15 );
  864.   pi.coded_error = pi.abs_error + 16;
  865.   currentBuffer = (unsigned char *) (pi.coded_error + 16);
  866.   tmp = currentBuffer + pi.effectiveWidth;
  867.   prevBuffer = (unsigned char *)(((unsigned int)tmp+15) & ~15 );
  868.  
  869.  
  870.   pi.xStep = 1;
  871.   copyLine(currentBuffer, inBuffer, xOffset, xStep, pi.effectiveWidth);
  872.   pi.currentLine = currentBuffer;
  873.   // first line
  874.   for (j = 0; j < pi.effectiveWidth; j++) {
  875.     calcLocoTop(&pi, j);
  876.     comp_one_pel_lossy(&pi);
  877.   }
  878.   /* MAIN LOOP: */
  879.   for (i = 1; i < pi.effectiveHeight; i++)
  880.   {
  881.     tmp = prevBuffer;
  882.     prevBuffer = currentBuffer;
  883.     currentBuffer = tmp;
  884.     pi.prevLine = prevBuffer;
  885.     copyLine(currentBuffer, inBuffer+i*pi.yStride, xOffset, xStep, pi.effectiveWidth);
  886.     pi.currentLine = currentBuffer;
  887.     // left most pixel
  888.     calcLocoLeft(&pi);
  889.     comp_one_pel_lossy(&pi);
  890.     for (j = 1; j < pi.effectiveWidth; j++) {
  891.       pi.mean = calcLoco(&pi);
  892.       comp_one_pel_lossy(&pi);
  893.     }
  894.   }
  895.  
  896.  
  897.   
  898.   /* CLEAN-UP: */
  899.   flush_run_length(&pi);
  900.   flush_bits(&pi);
  901.   free(tmp_buffer);
  902.  
  903. #ifdef FREQ_OUTPUT
  904.   frame++;
  905.   if (frame % 100 == 0)
  906.   {
  907.     print_freq();
  908.   }
  909. #endif
  910.  
  911.   return pi.buffer;
  912. }
  913.  
  914. unsigned char * loco_codec_decompress(unsigned char *inBuffer, unsigned char *outBuffer, int height, int width, int xOffset, 
  915.               int xStep, int yOffset, int yStep, int maxLoss)
  916. {
  917.   int i,j;
  918.   struct prediction_info pi;
  919.  
  920.   initialize_pi(&pi, outBuffer, inBuffer, height, width, xOffset, xStep, yOffset, yStep, maxLoss);
  921.  
  922.   for (j = 0; j < pi.effectiveWidth; j++) {
  923.     calcLocoTop(&pi,j);
  924.     decomp_one_pel(&pi);
  925.   }
  926.   /* MAIN LOOP: */
  927.   for (i = 1; i < pi.effectiveHeight; i++)
  928.   {
  929.     calcLocoLeft(&pi);
  930.     decomp_one_pel(&pi);
  931.     for (j = 1; j < pi.effectiveWidth; j++) {
  932.       pi.mean = calcLoco(&pi);
  933.       decomp_one_pel(&pi);
  934.     }
  935.   }
  936.   /* CLEAN-UP: */
  937.   return pi.buffer;
  938.  
  939. }
  940.