00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <string.h>
00023
00024 #include "avutil.h"
00025 #include "common.h"
00026 #include "intreadwrite.h"
00027 #include "lzo.h"
00028
00030 #define OUTBUF_PADDED 1
00032 #define INBUF_PADDED 1
00033
00034 typedef struct LZOContext {
00035 const uint8_t *in, *in_end;
00036 uint8_t *out_start, *out, *out_end;
00037 int error;
00038 } LZOContext;
00039
00044 static inline int get_byte(LZOContext *c)
00045 {
00046 if (c->in < c->in_end)
00047 return *c->in++;
00048 c->error |= AV_LZO_INPUT_DEPLETED;
00049 return 1;
00050 }
00051
00052 #ifdef INBUF_PADDED
00053 #define GETB(c) (*(c).in++)
00054 #else
00055 #define GETB(c) get_byte(&(c))
00056 #endif
00057
00064 static inline int get_len(LZOContext *c, int x, int mask)
00065 {
00066 int cnt = x & mask;
00067 if (!cnt) {
00068 while (!(x = get_byte(c)))
00069 cnt += 255;
00070 cnt += mask + x;
00071 }
00072 return cnt;
00073 }
00074
00079 static inline void copy(LZOContext *c, int cnt)
00080 {
00081 register const uint8_t *src = c->in;
00082 register uint8_t *dst = c->out;
00083 if (cnt > c->in_end - src) {
00084 cnt = FFMAX(c->in_end - src, 0);
00085 c->error |= AV_LZO_INPUT_DEPLETED;
00086 }
00087 if (cnt > c->out_end - dst) {
00088 cnt = FFMAX(c->out_end - dst, 0);
00089 c->error |= AV_LZO_OUTPUT_FULL;
00090 }
00091 #if defined(INBUF_PADDED) && defined(OUTBUF_PADDED)
00092 AV_COPY32U(dst, src);
00093 src += 4;
00094 dst += 4;
00095 cnt -= 4;
00096 if (cnt > 0)
00097 #endif
00098 memcpy(dst, src, cnt);
00099 c->in = src + cnt;
00100 c->out = dst + cnt;
00101 }
00102
00111 static inline void copy_backptr(LZOContext *c, int back, int cnt)
00112 {
00113 register const uint8_t *src = &c->out[-back];
00114 register uint8_t *dst = c->out;
00115 if (src < c->out_start || src > dst) {
00116 c->error |= AV_LZO_INVALID_BACKPTR;
00117 return;
00118 }
00119 if (cnt > c->out_end - dst) {
00120 cnt = FFMAX(c->out_end - dst, 0);
00121 c->error |= AV_LZO_OUTPUT_FULL;
00122 }
00123 av_memcpy_backptr(dst, back, cnt);
00124 c->out = dst + cnt;
00125 }
00126
00127 int av_lzo1x_decode(void *out, int *outlen, const void *in, int *inlen)
00128 {
00129 int state = 0;
00130 int x;
00131 LZOContext c;
00132 if (*outlen <= 0 || *inlen <= 0) {
00133 int res = 0;
00134 if (*outlen <= 0)
00135 res |= AV_LZO_OUTPUT_FULL;
00136 if (*inlen <= 0)
00137 res |= AV_LZO_INPUT_DEPLETED;
00138 return res;
00139 }
00140 c.in = in;
00141 c.in_end = (const uint8_t *)in + *inlen;
00142 c.out = c.out_start = out;
00143 c.out_end = (uint8_t *)out + *outlen;
00144 c.error = 0;
00145 x = GETB(c);
00146 if (x > 17) {
00147 copy(&c, x - 17);
00148 x = GETB(c);
00149 if (x < 16)
00150 c.error |= AV_LZO_ERROR;
00151 }
00152 if (c.in > c.in_end)
00153 c.error |= AV_LZO_INPUT_DEPLETED;
00154 while (!c.error) {
00155 int cnt, back;
00156 if (x > 15) {
00157 if (x > 63) {
00158 cnt = (x >> 5) - 1;
00159 back = (GETB(c) << 3) + ((x >> 2) & 7) + 1;
00160 } else if (x > 31) {
00161 cnt = get_len(&c, x, 31);
00162 x = GETB(c);
00163 back = (GETB(c) << 6) + (x >> 2) + 1;
00164 } else {
00165 cnt = get_len(&c, x, 7);
00166 back = (1 << 14) + ((x & 8) << 11);
00167 x = GETB(c);
00168 back += (GETB(c) << 6) + (x >> 2);
00169 if (back == (1 << 14)) {
00170 if (cnt != 1)
00171 c.error |= AV_LZO_ERROR;
00172 break;
00173 }
00174 }
00175 } else if (!state) {
00176 cnt = get_len(&c, x, 15);
00177 copy(&c, cnt + 3);
00178 x = GETB(c);
00179 if (x > 15)
00180 continue;
00181 cnt = 1;
00182 back = (1 << 11) + (GETB(c) << 2) + (x >> 2) + 1;
00183 } else {
00184 cnt = 0;
00185 back = (GETB(c) << 2) + (x >> 2) + 1;
00186 }
00187 copy_backptr(&c, back, cnt + 2);
00188 state =
00189 cnt = x & 3;
00190 copy(&c, cnt);
00191 x = GETB(c);
00192 }
00193 *inlen = c.in_end - c.in;
00194 if (c.in > c.in_end)
00195 *inlen = 0;
00196 *outlen = c.out_end - c.out;
00197 return c.error;
00198 }
00199
00200 #ifdef TEST
00201 #include <stdio.h>
00202 #include <lzo/lzo1x.h>
00203 #include "log.h"
00204 #define MAXSZ (10*1024*1024)
00205
00206
00207
00208 #define BENCHMARK_LIBLZO_SAFE 0
00209 #define BENCHMARK_LIBLZO_UNSAFE 0
00210
00211 int main(int argc, char *argv[]) {
00212 FILE *in = fopen(argv[1], "rb");
00213 uint8_t *orig = av_malloc(MAXSZ + 16);
00214 uint8_t *comp = av_malloc(2*MAXSZ + 16);
00215 uint8_t *decomp = av_malloc(MAXSZ + 16);
00216 size_t s = fread(orig, 1, MAXSZ, in);
00217 lzo_uint clen = 0;
00218 long tmp[LZO1X_MEM_COMPRESS];
00219 int inlen, outlen;
00220 int i;
00221 av_log_set_level(AV_LOG_DEBUG);
00222 lzo1x_999_compress(orig, s, comp, &clen, tmp);
00223 for (i = 0; i < 300; i++) {
00224 START_TIMER
00225 inlen = clen; outlen = MAXSZ;
00226 #if BENCHMARK_LIBLZO_SAFE
00227 if (lzo1x_decompress_safe(comp, inlen, decomp, &outlen, NULL))
00228 #elif BENCHMARK_LIBLZO_UNSAFE
00229 if (lzo1x_decompress(comp, inlen, decomp, &outlen, NULL))
00230 #else
00231 if (av_lzo1x_decode(decomp, &outlen, comp, &inlen))
00232 #endif
00233 av_log(NULL, AV_LOG_ERROR, "decompression error\n");
00234 STOP_TIMER("lzod")
00235 }
00236 if (memcmp(orig, decomp, s))
00237 av_log(NULL, AV_LOG_ERROR, "decompression incorrect\n");
00238 else
00239 av_log(NULL, AV_LOG_ERROR, "decompression OK\n");
00240 return 0;
00241 }
00242 #endif