home *** CD-ROM | disk | FTP | other *** search
- /* loco.c -- A video compression codec based loosely on LOCO-I
-
- Copyright (C) 2003 Mohammad Rezaei
-
- Author: Mohammad Rezaei
-
- This program is free software; you can redistribute it and/or
- modify it under the terms of the GNU General Public License
- as published by the Free Software Foundation; either version 2
- of the License, or (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
-
- ---------
- */
-
- #include <stdio.h>
- #include <stdlib.h>
- #include "loco.h"
- #define MAX_NUM_ERR 16
-
-
- #ifdef FREQ_OUTPUT
- int freq_initialized = 0;
- int freq[512];
- int frame = 0;
- #endif
-
- #define MSG_OUTPUT
- #ifdef MSG_OUTPUT
- #define LOG_LINE 3
-
-
- static int this_line = 0;
- #include <windows.h>
-
- /* ---------------------------------------- */
-
- static void Msg(const char fmt[], ...) {
- static int debug = 0;
-
- debug = GetPrivateProfileInt("debug", "log", 0, "lococodec.ini");
- if (!debug) return;
- else
- {
- DWORD written;
- char buf[2000];
- const COORD _80x50 = {80,500};
- static BOOL startup = 0;
- va_list val;
-
-
- va_start(val, fmt);
- wvsprintf(buf, fmt, val);
-
- startup = (AllocConsole(), SetConsoleScreenBufferSize(GetStdHandle(STD_OUTPUT_HANDLE), _80x50));
- WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), buf, lstrlen(buf), &written, 0);
- }
- }
- #endif
-
-
- /* ---------------------------------------- */
- /* Bit-IO Routines */
-
- #include <limits.h>
-
-
-
-
- __inline static void write_bit_buffer(struct prediction_info *pi)
- {
- *(pi->buffer) = pi->bit_buffer;
- pi->buffer++;
- pi->num_bits_in_buf = 0;
- pi->bit_buffer = 0;
-
- }
-
- /* Flush any remaining bits. */
- __inline static void flush_bits(struct prediction_info *pi)
- {
- if (pi->num_bits_in_buf > 0)
- write_bit_buffer(pi);
- }
-
- /* Write a bunch of zeros */
- __inline static void output_zero_bits(struct prediction_info *pi, int bits)
- {
- pi->num_bits_in_buf+= bits;
-
- while (pi->num_bits_in_buf >= CHAR_BIT)
- {
- *(pi->buffer) = pi->bit_buffer;
- //if (pi->bit_buffer == 111) Msg("found 111 %d\n",this_line);
- pi->buffer++;
- pi->num_bits_in_buf -= CHAR_BIT;
- pi->bit_buffer = 0;
- }
- }
-
- /* Write one bit. */
- __inline static void output_one_bit(struct prediction_info *pi)
- {
- pi->bit_buffer |= (1 << (CHAR_BIT-1-pi->num_bits_in_buf)); /* fill from the left */
- pi->num_bits_in_buf++;
-
- if (pi->num_bits_in_buf == CHAR_BIT)
- write_bit_buffer(pi);
- }
-
- __inline static void copy_bits(struct prediction_info *pi, unsigned int from, int len)
- {
- if (len == 0) return;
- from &= ((1 << len)-1);
- while(len > CHAR_BIT - pi->num_bits_in_buf)
- {
- pi->bit_buffer |= (from >> (len-CHAR_BIT+pi->num_bits_in_buf));
- len -= (CHAR_BIT-pi->num_bits_in_buf);
- from &= (1 << (len+1))-1;
- *(pi->buffer) = pi->bit_buffer;
- pi->buffer++;
- pi->num_bits_in_buf = 0;
- pi->bit_buffer = 0;
-
- }
- if (len == 0) return;
- pi->bit_buffer |= (from << (CHAR_BIT-len-pi->num_bits_in_buf));
- pi->num_bits_in_buf += len;
- if (pi->num_bits_in_buf == CHAR_BIT)
- write_bit_buffer(pi);
- }
-
-
- /* Read one bit. */
- __inline static int input_bit(struct prediction_info *pi)
- {
- if (pi->num_bits_in_buf == 0) {
- pi->bit_buffer = (unsigned char)(*(pi->buffer));
- pi->buffer++;
- pi->num_bits_in_buf += CHAR_BIT; /* This might be too much. The application must
- figure-out the exact end of the bitstream. */
- }
-
- pi->num_bits_in_buf--;
- return (pi->bit_buffer & (1 << pi->num_bits_in_buf)) > 0;
- }
-
- __inline static void flush_run_length(struct prediction_info *pip)
- {
- if (pip->run_length > 0 && pip->saved_bits >= 0)
- {
- int x = pip->run_length-1;
- int quot = x >> 2;
- unsigned int rem = x&3;
- output_zero_bits(pip, quot);
- output_one_bit(pip);
- copy_bits(pip, rem, 2);
- }
- if (pip->run_length > 2) pip->saved_bits+= pip->run_length;
- else pip->saved_bits-=3;
- pip->run_length = 0;
- }
-
- /* ---------------------------------------- */
- /* Rice Coding Routines */
-
- /* Write the Rice(b) code for X on stdout. X is a nonnegative integer. B
- must be a strictly positive integer. */
- __inline static void rice_encode(struct prediction_info *pip, unsigned int x, unsigned int log_b)
- {
-
- #ifdef FREQ_OUTPUT
- freq[x]++;
- #endif
- if (x == 0)
- {
- if (pip->run_length == 0 || pip->saved_bits < 0)
- {
- output_one_bit(pip);
- output_zero_bits(pip, log_b);
- }
- pip->run_length++;
- }
- else
- {
- int quot = x >> log_b;
- unsigned int rem = x&((1 << log_b)-1);
- if (pip->run_length > 0)
- {
- flush_run_length(pip);
- }
- output_zero_bits(pip, quot);
- output_one_bit(pip);
-
- copy_bits(pip, rem, log_b);
- }
-
- }
-
- /* Read the next Rice(b) code and return it. */
- __inline static int rice_decode(struct prediction_info *pip, unsigned int log_b)
- {
- unsigned int quot, r;
- int i;
-
- if (pip->run_length > 0)
- {
- pip->run_length--;
- return 0;
- }
-
- for (quot=0; input_bit(pip) == 0; quot++);
- r = quot << log_b;
- for (i=log_b-1; i>=0; i--) r = r | (input_bit(pip) << i);
- if (r == 0)
- {
- if (pip->saved_bits >= 0)
- {
- for (quot=0; input_bit(pip) == 0; quot++);
- pip->run_length = quot << 2;
- for (i=1; i>=0; i--) pip->run_length |= (input_bit(pip) << i);
- if (pip->run_length > 1) pip->saved_bits+=pip->run_length+1;
- else pip->saved_bits-=3;
- }
- else pip->decode_run_length++;
- }
- else if (pip->decode_run_length > 0)
- {
- if (pip->decode_run_length > 2) pip->saved_bits+=pip->decode_run_length;
- else pip->saved_bits-=3;
- pip->decode_run_length = 0;
- }
- return r;
- }
-
- __inline static int calcLoco(struct prediction_info *pip)
- {
- int c = *(pip->prevLine-pip->xStep);
- int a = *(pip->prevLine);
- int b = *(pip->currentLine-pip->xStep);
- int minab = a < b ? a : b;
- int maxab = a > b ? a : b;
- int result;
- if (c >= maxab) result = minab;
- else if (c <= minab) result = maxab;
- else result = a+b-c;
- pip->prevLine += pip->xStep;
- return result;
-
- }
-
- __inline static void calcLoco16(struct prediction_info *pip)
- {
- #define SSE2
- #ifdef SSE2
- unsigned char * prev = pip->prevLine;
- unsigned char * curr = pip->currentLine;
- short * coded = pip->coded_error;
- short * abs_err = pip->abs_error;
- __asm
- {
- mov eax, prev
- movdqa xmm2, XMMWORD PTR[eax-1] // xmm2 = c
- movdqu xmm0, XMMWORD PTR[eax] // xmm0 = a
- mov ebx, curr
- movdqa xmm1, XMMWORD PTR[ebx-1] // xmm1 = b
- movdqa xmm3, xmm0 // xmm3 = a
- pminub xmm0, xmm1 // xmm0 is now min
- pmaxub xmm1, xmm3 // xmm1 is now max
- movdqa xmm4, xmm2 // xmm4 = c
- pminub xmm4, xmm0 // xmm4 = min(c, min(a,b))
- movdqa xmm3, xmm2 // xmm3 = c
- pmaxub xmm3, xmm1 // xmm3 = max(c, max(a,b))
- pcmpeqb xmm4, xmm2 // xmm4 = (c <= min(a,b))
- pcmpeqb xmm3, xmm2 // xmm3 = (c >= max(a,b))
- movdqa xmm7, xmm3
- por xmm7, xmm4
- pandn xmm7, xmm2 // xmm7 = c &&! (c >= max || c <= min)
- movdqa xmm2, xmm4
- pandn xmm2, xmm0 // xmm2 = min &&! c<=min
- pandn xmm4, xmm3
- pandn xmm4, xmm1 // xmm4 = max &&! (c>=max &&! c<=min)
-
- movdqu xmm5, XMMWORD PTR[ebx] // xmm5 = current pixel
-
- pxor xmm1, xmm1 // xmm1 = 0
- punpcklbw xmm1, xmm2
- psrldq xmm1, 1
- pxor xmm3, xmm3
- punpcklbw xmm3, xmm4
- psrldq xmm3, 1
- paddsw xmm1, xmm3
- pxor xmm3, xmm3
- punpcklbw xmm3, xmm7
- psrldq xmm3, 1
- psubsw xmm1, xmm3
- pxor xmm3, xmm3
- punpcklbw xmm3, xmm5
- psrldq xmm3, 1
- psubsw xmm1, xmm3
-
- pxor xmm3, xmm3
- psubsw xmm3, xmm1 // xmm3 = -xmm1
-
- pmaxsw xmm3, xmm1 // xmm3 = abs(xmm1)
-
- pxor xmm0, xmm0 // xmm0 = 0
- mov ebx, abs_err
- movdqa XMMWORD PTR[ebx], xmm3
-
- mov eax, coded
-
- psllw xmm3, 1 // xmm3 <<= 1
- pcmpgtw xmm1, xmm0 // error > 0
- psrlw xmm1, 15 // make FF's into 1's
- psubsw xmm3, xmm1 // xmm3 -= xmm1
-
- movdqa XMMWORD PTR[eax], xmm3
-
- pxor xmm3, xmm3
- punpckhbw xmm2, xmm3
- punpckhbw xmm4, xmm3
- paddsw xmm2, xmm4
- punpckhbw xmm7, xmm3
- psubsw xmm2, xmm7
- punpckhbw xmm5, xmm3
- psubsw xmm2, xmm5
-
- psubsw xmm3, xmm2 // xmm3 = -xmm2
- pmaxsw xmm3, xmm2 // xmm3 = abs(xmm2)
-
- movdqa XMMWORD PTR[ebx+16], xmm3
-
- psllw xmm3, 1
- pcmpgtw xmm2, xmm0
- psrlw xmm2, 15
- psubsw xmm3, xmm2
-
- movdqa XMMWORD PTR[eax+16], xmm3
-
- }
- pip->prevLine += 16;
- pip->currentLine += 16;
- #else
- int i;
- for(i=0;i<16;i++)
- {
- int c = *(pip->prevLine-1);
- int a = *(pip->prevLine);
- int b = *(pip->currentLine-1);
- int minab = a < b ? a : b;
- int maxab = a > b ? a : b;
- int result;
- if (c >= maxab) result = minab;
- else if (c <= minab) result = maxab;
- else result = a+b-c;
- pip->prevLine++;
- result -= *(pip->currentLine);
- pip->currentLine++;
- pip->abs_error[i] = result > 0 ? result : -result;
- pip->coded_error[i] = (pip->abs_error[i] << 1) - (result >=1);
- }
- #endif
-
- }
-
- __inline static void calcLocoTop(struct prediction_info *pip, int j)
- {
- if (j > 0)
- pip->mean = *(pip->currentLine-pip->xStep);
- else
- pip->mean = 128;
- }
-
- __inline static void calcLocoLeft(struct prediction_info *pip)
- {
- pip->mean = *(pip->prevLine);
- pip->prevLine += pip->xStep;
- }
-
-
- __inline static int rice_param(struct prediction_info *pip)
- {
- int n = pip->num_err;
- int a = pip->abs_err;
-
- if (n >= a) return 0;
- if ((n += n) >= a) return 1;
- if ((n += n) >= a) return 2;
- if ((n += n) >= a) return 3;
- if ((n += n) >= a) return 4;
- if ((n += n) >= a) return 5;
- if ((n += n) >= a) return 6;
- if ((n += n) >= a) return 7;
- if ((n += n) >= a) return 8;
- return 9;
- }
-
- /* have the Rice coder generate a compressed
- representation for pip->pict[i][j] using the mean and Rice parameter */
- __inline static void comp_one_pel(struct prediction_info *pip)
- {
- int e, mapped_err;
-
- int rice = rice_param(pip);
-
- /* Code the actual pixel: */
- e = pip->mean - *(pip->currentLine);
- pip->currentLine += pip->xStep;
- mapped_err = (e > 0 ? e : -e) ;
- pip->abs_err += mapped_err;
- mapped_err <<= 1;
- mapped_err -= (e >= 1);
- pip->num_err++;
-
- rice_encode(pip, mapped_err, rice);
- if (pip->num_err == MAX_NUM_ERR)
- {
- pip->num_err >>= 1;
- pip->abs_err >>= 1;
- }
-
-
- }
-
- /* have the Rice coder generate a compressed
- representation for pip->pict[i][j] using the mean and Rice parameter */
- __inline static void comp_one_pel_lossy(struct prediction_info *pip)
- {
- int e, mapped_err;
-
- int rice = rice_param(pip);
-
- /* Code the actual pixel: */
- e = pip->mean - *(pip->currentLine);
- mapped_err = (e > 0 ? e : -e) ;
- if (mapped_err <= pip->max_loss)
- {
- *(pip->currentLine) = pip->mean;
- mapped_err = 0;
- }
- else
- {
- mapped_err -= pip->max_loss;
- pip->abs_err += mapped_err;
- mapped_err <<= 1;
- mapped_err -= (e >= 1);
- }
- pip->currentLine += pip->xStep;
- pip->num_err++;
-
- rice_encode(pip, mapped_err, rice);
- if (pip->num_err == MAX_NUM_ERR)
- {
- pip->num_err >>= 1;
- pip->abs_err >>= 1;
- }
-
-
- }
-
- __inline static void comp_16_pel(struct prediction_info *pip)
- {
- int i;
- for(i=0;i<16;i++)
- {
- int rice = rice_param(pip);
-
- pip->abs_err += pip->abs_error[i];
- pip->num_err++;
-
- rice_encode(pip, pip->coded_error[i], rice);
- if (pip->num_err == MAX_NUM_ERR)
- {
- pip->num_err >>= 1;
- pip->abs_err >>= 1;
- }
- }
-
-
- }
-
-
- /* decode the next pixel. */
- __inline static void decomp_one_pel(struct prediction_info *pip)
- {
- int e, mapped_err;
- int rice = rice_param(pip);
-
- /* decode the actual pixel: */
- mapped_err = rice_decode(pip, rice);
- if (mapped_err > 0)
- {
- e = (mapped_err & 1) ? (mapped_err+1)>>1 : -(mapped_err >> 1);
- pip->abs_err += e > 0 ? e: -e;
- if (e > 0)
- {
- e += pip->max_loss;
- }
- else if (e < 0)
- {
- e -= pip->max_loss;
- }
-
- }
- else e = 0;
-
- pip->num_err++;
- if (pip->num_err == MAX_NUM_ERR)
- {
- pip->num_err >>= 1;
- pip->abs_err >>= 1;
- }
-
- *(pip->currentLine) = pip->mean - e;
- pip->currentLine += pip->xStep;
-
-
- }
-
- void initialize_pi(struct prediction_info *pi, unsigned char *imageBuffer, unsigned char *outBuffer, int height, int width, int xOffset,
- int xStep, int yOffset, int yStep, int maxLoss)
- {
- /* INITIALIZATIONS: */
- pi->xStep = xStep;
- pi->yStride = width*yStep;
- pi->effectiveHeight = height/yStep-yOffset/yStep;
- pi->effectiveWidth = width/xStep-xOffset/xStep;
- pi->buffer = outBuffer;
- pi->currentLine = imageBuffer+yOffset*pi->yStride+xOffset;
- pi->prevLine = pi->currentLine;
- pi->max_loss = maxLoss;
-
- pi->num_bits_in_buf = 0;
- pi->bit_buffer = 0;
- pi->abs_err = 8;
- pi->num_err = 1;
- pi->run_length = 0;
- pi->decode_run_length = 0;
- pi->saved_bits = 0;
- // this_line = 0;
- }
-
- __inline static void copyLine(unsigned char *dest, unsigned char *src, int xOffset, int xStep, int width)
- {
- int i;
- int j=xOffset;
- for(i=0;i<width;i++,j+=xStep)
- {
- dest[i] = src[j];
- }
- }
-
- __inline static void copyLine1(unsigned char *dest, unsigned char *src, int xOffset, int width)
- {
- #ifdef SSE2
- int i;
- int end;
- unsigned char *end_ptr;
- end = width;
- if ((width - 1) % 16)
- {
- end -= (width - 1) % 16;
- }
- end_ptr = dest+end;
- __asm {
- mov eax, dest
- mov ebx, src
- add ebx, xOffset
- START_LOOP_1:
- movdqu xmm0, XMMWORD PTR[ebx]
- add ebx, 16
- movdqa XMMWORD PTR[eax], xmm0
- add eax, 16
- cmp eax, end_ptr
- jl SHORT START_LOOP_1
- }
- for(i=end;i<width;i++)
- {
- dest[i] = src[i+xOffset];
- }
- #else
- copyLine(dest, src, xOffset, 1, width);
- #endif
- }
-
- __inline static void copyLine2(unsigned char *dest, unsigned char *src, int xOffset, int width)
- {
- #ifdef SSE2
- int i,j;
- int end;
- unsigned char *end_ptr;
- end = width;
- if ((width - 1) % 16)
- {
- end -= (width - 1) % 16;
- }
- end_ptr = dest+end;
-
- __asm {
- mov eax, dest
- mov ebx, src
- add ebx, xOffset
- pcmpeqb xmm4, xmm4
- psrlw xmm4, 8
- START_LOOP_2:
- movdqu xmm0, XMMWORD PTR[ebx]
- movdqu xmm1, XMMWORD PTR[ebx+16]
- pand xmm0, xmm4
- pand xmm1, xmm4
- packuswb xmm0, xmm1
- add ebx, 32
- movdqa XMMWORD PTR[eax], xmm0
- add eax, 16
- cmp eax, end_ptr
- jl SHORT START_LOOP_2
- }
- j=(end << 1)+xOffset;
- for(i=end;i<width;i++,j+=2)
- {
- dest[i] = src[j];
- }
- #else
- copyLine(dest, src, xOffset, 2, width);
- #endif
- }
-
- __inline static void copyLine3(unsigned char *dest, unsigned char *src, int xOffset, int width)
- {
- copyLine(dest, src, xOffset, 3, width);
- }
-
- __inline static void copyLine4(unsigned char *dest, unsigned char *src, int xOffset, int width)
- {
- #ifdef SSE2
- int i,j;
- int end;
- unsigned char *end_ptr;
- end = width;
- if ((width - 1) % 16)
- {
- end -= (width - 1) % 16;
- }
- end_ptr = dest+end;
- __asm {
- mov eax, dest
- mov ebx, src
- add ebx, xOffset
- pcmpeqb xmm4, xmm4
- psrld xmm4, 24
- START_LOOP_4:
- movdqu xmm0, XMMWORD PTR[ebx]
- movdqu xmm1, XMMWORD PTR[ebx+16]
- pand xmm0, xmm4
- pand xmm1, xmm4
- packuswb xmm0, xmm1
- add ebx, 32
-
- movdqu xmm1, XMMWORD PTR[ebx]
- movdqu xmm2, XMMWORD PTR[ebx+16]
- pand xmm1, xmm4
- pand xmm2, xmm4
- packuswb xmm1, xmm2
- packuswb xmm0, xmm1
- add ebx, 32
- movdqa XMMWORD PTR[eax], xmm0
- add eax, 16
- cmp eax, end_ptr
- jl SHORT START_LOOP_4
-
- }
- j=(end << 2)+xOffset;
- for(i=end;i<width;i++,j+=4)
- {
- dest[i] = src[j];
- }
- #else
- copyLine(dest, src, xOffset, 4, width);
- #endif
- }
-
- void (*copy_line_array[4])(unsigned char *dest, unsigned char *src, int xOffset, int width)
- = {copyLine1, copyLine2, copyLine3, copyLine4};
-
-
-
- __inline void *alloc_buffers(struct prediction_info *pip)
- {
- int size = (pip->effectiveWidth << 1)*sizeof(char) + 32*sizeof(short)+32;
-
- return malloc(size);
- }
-
- #ifndef SSE2
- unsigned char * loco_codec_compress_non_vector(unsigned char *inBuffer, unsigned char *outBuffer,
- int height, int width, int xOffset,
- int xStep, int yOffset, int yStep)
- {
- int i,j;
- struct prediction_info pi;
-
- initialize_pi(&pi, inBuffer, outBuffer, height, width, xOffset, xStep, yOffset, yStep, 0);
-
- // first line
- for (j = 0; j < pi.effectiveWidth; j++) {
- calcLocoTop(&pi, j);
- comp_one_pel(&pi);
- }
- /* MAIN LOOP: */
- for (i = 1; i < pi.effectiveHeight; i++)
- {
- // left most pixel
- calcLocoLeft(&pi);
- comp_one_pel(&pi);
- for (j = 1; j < pi.effectiveWidth; j++) {
- pi.mean = calcLoco(&pi);
- comp_one_pel(&pi);
- }
- }
-
-
-
- /* CLEAN-UP: */
- flush_run_length(&pi);
- flush_bits(&pi);
-
- return pi.buffer;
- }
- #endif
-
- #ifdef FREQ_OUTPUT
- void print_freq()
- {
- int i=0;
-
- for(i =0;i<512;i++) Msg("%d ..%d ~",i,freq[i]);
- Msg("\n");
-
- }
- #endif
-
- unsigned char * loco_codec_compress(unsigned char *inBuffer, unsigned char *outBuffer, int height, int width, int xOffset,
- int xStep, int yOffset, int yStep)
- {
- int i,j, end;
- struct prediction_info pi;
- unsigned char *currentBuffer, *prevBuffer, *tmp;
- void *tmp_buffer;
- void (*copy_line_ptr)(unsigned char *dest, unsigned char *src, int xOffset, int width);
-
- copy_line_ptr = copy_line_array[xStep-1];
-
- initialize_pi(&pi, inBuffer, outBuffer, height, width, xOffset, xStep, yOffset, yStep, 0);
-
- tmp_buffer = alloc_buffers(&pi);
-
-
- pi.abs_error = (short *)(((unsigned int)tmp_buffer+15) & ~15 );
- pi.coded_error = pi.abs_error + 16;
- currentBuffer = (unsigned char *) (pi.coded_error + 16);
- tmp = currentBuffer + pi.effectiveWidth;
- prevBuffer = (unsigned char *)(((unsigned int)tmp+15) & ~15 );
-
- pi.xStep = 1;
- end = pi.effectiveWidth;
- if ((pi.effectiveWidth - 1) % 16)
- {
- end -= (pi.effectiveWidth - 1) % 16;
- }
- (*copy_line_ptr)(currentBuffer, inBuffer, xOffset, pi.effectiveWidth);
- pi.currentLine = currentBuffer;
- // first line
- for (j = 0; j < pi.effectiveWidth; j++) {
- calcLocoTop(&pi, j);
- comp_one_pel(&pi);
- }
- /* MAIN LOOP: */
- for (i = 1; i < pi.effectiveHeight; i++)
- {
- tmp = prevBuffer;
- prevBuffer = currentBuffer;
- currentBuffer = tmp;
- pi.prevLine = prevBuffer;
- (*copy_line_ptr)(currentBuffer, inBuffer+i*pi.yStride, xOffset, pi.effectiveWidth);
- pi.currentLine = currentBuffer;
- // left most pixel
- calcLocoLeft(&pi);
- comp_one_pel(&pi);
- for (j = 1; j < end; j+=16) {
- calcLoco16(&pi);
- comp_16_pel(&pi);
- }
- for(;j< pi.effectiveWidth;j++)
- {
- pi.mean = calcLoco(&pi);
- comp_one_pel(&pi);
- }
- }
-
-
-
- /* CLEAN-UP: */
- flush_run_length(&pi);
- flush_bits(&pi);
- free(tmp_buffer);
-
- #ifdef FREQ_OUTPUT
- frame++;
- if (frame % 100 == 0)
- {
- print_freq();
- }
- #endif
-
- return pi.buffer;
- }
-
- #ifdef FREQ_OUTPUT
- void initialize_freq()
- {
- int i;
- if (!freq_initialized)
- {
- for(i=0;i<512;i++) freq[i] = 0;
- freq_initialized = 1;
- }
- }
- #endif
-
- unsigned char * loco_codec_compress_lossy(unsigned char *inBuffer, unsigned char *outBuffer, int height, int width, int xOffset,
- int xStep, int yOffset, int yStep, int maxLoss)
- {
- int i,j;
- struct prediction_info pi;
- unsigned char *currentBuffer, *prevBuffer, *tmp;
- void *tmp_buffer;
-
- #ifdef FREQ_OUTPUT
- initialize_freq();
- #endif
- #ifdef SSE2
- if (maxLoss == 0) return loco_codec_compress(inBuffer, outBuffer, height, width, xOffset,
- xStep, yOffset, yStep);
- #else
- if (maxLoss == 0) return loco_codec_compress_non_vector(inBuffer, outBuffer, height, width, xOffset,
- xStep, yOffset, yStep);
- #endif
-
-
- initialize_pi(&pi, inBuffer, outBuffer, height, width, xOffset, xStep, yOffset, yStep, maxLoss);
-
- tmp_buffer = alloc_buffers(&pi);
-
-
- pi.abs_error = (short *)(((unsigned int)tmp_buffer+15) & ~15 );
- pi.coded_error = pi.abs_error + 16;
- currentBuffer = (unsigned char *) (pi.coded_error + 16);
- tmp = currentBuffer + pi.effectiveWidth;
- prevBuffer = (unsigned char *)(((unsigned int)tmp+15) & ~15 );
-
-
- pi.xStep = 1;
- copyLine(currentBuffer, inBuffer, xOffset, xStep, pi.effectiveWidth);
- pi.currentLine = currentBuffer;
- // first line
- for (j = 0; j < pi.effectiveWidth; j++) {
- calcLocoTop(&pi, j);
- comp_one_pel_lossy(&pi);
- }
- /* MAIN LOOP: */
- for (i = 1; i < pi.effectiveHeight; i++)
- {
- tmp = prevBuffer;
- prevBuffer = currentBuffer;
- currentBuffer = tmp;
- pi.prevLine = prevBuffer;
- copyLine(currentBuffer, inBuffer+i*pi.yStride, xOffset, xStep, pi.effectiveWidth);
- pi.currentLine = currentBuffer;
- // left most pixel
- calcLocoLeft(&pi);
- comp_one_pel_lossy(&pi);
- for (j = 1; j < pi.effectiveWidth; j++) {
- pi.mean = calcLoco(&pi);
- comp_one_pel_lossy(&pi);
- }
- }
-
-
-
- /* CLEAN-UP: */
- flush_run_length(&pi);
- flush_bits(&pi);
- free(tmp_buffer);
-
- #ifdef FREQ_OUTPUT
- frame++;
- if (frame % 100 == 0)
- {
- print_freq();
- }
- #endif
-
- return pi.buffer;
- }
-
- unsigned char * loco_codec_decompress(unsigned char *inBuffer, unsigned char *outBuffer, int height, int width, int xOffset,
- int xStep, int yOffset, int yStep, int maxLoss)
- {
- int i,j;
- struct prediction_info pi;
-
- initialize_pi(&pi, outBuffer, inBuffer, height, width, xOffset, xStep, yOffset, yStep, maxLoss);
-
- for (j = 0; j < pi.effectiveWidth; j++) {
- calcLocoTop(&pi,j);
- decomp_one_pel(&pi);
- }
- /* MAIN LOOP: */
- for (i = 1; i < pi.effectiveHeight; i++)
- {
- calcLocoLeft(&pi);
- decomp_one_pel(&pi);
- for (j = 1; j < pi.effectiveWidth; j++) {
- pi.mean = calcLoco(&pi);
- decomp_one_pel(&pi);
- }
- }
- /* CLEAN-UP: */
- return pi.buffer;
-
- }
-