Mercurial > audlegacy-plugins
comparison src/ffmpeg/libavcodec/lzo.c @ 808:e8776388b02a trunk
[svn] - add ffmpeg
| author | nenolod |
|---|---|
| date | Mon, 12 Mar 2007 11:18:54 -0700 |
| parents | |
| children |
comparison
equal
deleted
inserted
replaced
| 807:0f9c8d4d3ac4 | 808:e8776388b02a |
|---|---|
| 1 /* | |
| 2 * LZO 1x decompression | |
| 3 * Copyright (c) 2006 Reimar Doeffinger | |
| 4 * | |
| 5 * This file is part of FFmpeg. | |
| 6 * | |
| 7 * FFmpeg is free software; you can redistribute it and/or | |
| 8 * modify it under the terms of the GNU Lesser General Public | |
| 9 * License as published by the Free Software Foundation; either | |
| 10 * version 2.1 of the License, or (at your option) any later version. | |
| 11 * | |
| 12 * FFmpeg 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 GNU | |
| 15 * Lesser General Public License for more details. | |
| 16 * | |
| 17 * You should have received a copy of the GNU Lesser General Public | |
| 18 * License along with FFmpeg; if not, write to the Free Software | |
| 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
| 20 */ | |
| 21 #include "common.h" | |
| 22 //! avoid e.g. MPlayers fast_memcpy, it slows things down here | |
| 23 #undef memcpy | |
| 24 #include <string.h> | |
| 25 #include "lzo.h" | |
| 26 | |
| 27 //! define if we may write up to 12 bytes beyond the output buffer | |
| 28 #define OUTBUF_PADDED 1 | |
| 29 //! define if we may read up to 4 bytes beyond the input buffer | |
| 30 #define INBUF_PADDED 1 | |
| 31 typedef struct LZOContext { | |
| 32 uint8_t *in, *in_end; | |
| 33 uint8_t *out_start, *out, *out_end; | |
| 34 int error; | |
| 35 } LZOContext; | |
| 36 | |
| 37 /** | |
| 38 * \brief read one byte from input buffer, avoiding overrun | |
| 39 * \return byte read | |
| 40 */ | |
| 41 static inline int get_byte(LZOContext *c) { | |
| 42 if (c->in < c->in_end) | |
| 43 return *c->in++; | |
| 44 c->error |= LZO_INPUT_DEPLETED; | |
| 45 return 1; | |
| 46 } | |
| 47 | |
| 48 /** | |
| 49 * \brief decode a length value in the coding used by lzo | |
| 50 * \param x previous byte value | |
| 51 * \param mask bits used from x | |
| 52 * \return decoded length value | |
| 53 */ | |
| 54 static inline int get_len(LZOContext *c, int x, int mask) { | |
| 55 int cnt = x & mask; | |
| 56 if (!cnt) { | |
| 57 while (!(x = get_byte(c))) cnt += 255; | |
| 58 cnt += mask + x; | |
| 59 } | |
| 60 return cnt; | |
| 61 } | |
| 62 | |
| 63 /** | |
| 64 * \brief copy bytes from input to output buffer with checking | |
| 65 * \param cnt number of bytes to copy, must be > 0 | |
| 66 */ | |
| 67 static inline void copy(LZOContext *c, int cnt) { | |
| 68 register uint8_t *src = c->in; | |
| 69 register uint8_t *dst = c->out; | |
| 70 if (src + cnt > c->in_end) { | |
| 71 cnt = c->in_end - src; | |
| 72 c->error |= LZO_INPUT_DEPLETED; | |
| 73 } | |
| 74 if (dst + cnt > c->out_end) { | |
| 75 cnt = c->out_end - dst; | |
| 76 c->error |= LZO_OUTPUT_FULL; | |
| 77 } | |
| 78 #if defined(INBUF_PADDED) && defined(OUTBUF_PADDED) | |
| 79 dst[0] = src[0]; | |
| 80 dst[1] = src[1]; | |
| 81 dst[2] = src[2]; | |
| 82 dst[3] = src[3]; | |
| 83 src += 4; | |
| 84 dst += 4; | |
| 85 cnt -= 4; | |
| 86 if (cnt > 0) | |
| 87 #endif | |
| 88 memcpy(dst, src, cnt); | |
| 89 c->in = src + cnt; | |
| 90 c->out = dst + cnt; | |
| 91 } | |
| 92 | |
| 93 /** | |
| 94 * \brief copy previously decoded bytes to current position | |
| 95 * \param back how many bytes back we start | |
| 96 * \param cnt number of bytes to copy, must be > 0 | |
| 97 * | |
| 98 * cnt > back is valid, this will copy the bytes we just copied, | |
| 99 * thus creating a repeating pattern with a period length of back. | |
| 100 */ | |
| 101 static inline void copy_backptr(LZOContext *c, int back, int cnt) { | |
| 102 register uint8_t *src = &c->out[-back]; | |
| 103 register uint8_t *dst = c->out; | |
| 104 if (src < c->out_start) { | |
| 105 c->error |= LZO_INVALID_BACKPTR; | |
| 106 return; | |
| 107 } | |
| 108 if (dst + cnt > c->out_end) { | |
| 109 cnt = c->out_end - dst; | |
| 110 c->error |= LZO_OUTPUT_FULL; | |
| 111 } | |
| 112 if (back == 1) { | |
| 113 memset(dst, *src, cnt); | |
| 114 dst += cnt; | |
| 115 } else { | |
| 116 #ifdef OUTBUF_PADDED | |
| 117 dst[0] = src[0]; | |
| 118 dst[1] = src[1]; | |
| 119 dst[2] = src[2]; | |
| 120 dst[3] = src[3]; | |
| 121 src += 4; | |
| 122 dst += 4; | |
| 123 cnt -= 4; | |
| 124 if (cnt > 0) { | |
| 125 dst[0] = src[0]; | |
| 126 dst[1] = src[1]; | |
| 127 dst[2] = src[2]; | |
| 128 dst[3] = src[3]; | |
| 129 dst[4] = src[4]; | |
| 130 dst[5] = src[5]; | |
| 131 dst[6] = src[6]; | |
| 132 dst[7] = src[7]; | |
| 133 src += 8; | |
| 134 dst += 8; | |
| 135 cnt -= 8; | |
| 136 } | |
| 137 #endif | |
| 138 if (cnt > 0) { | |
| 139 int blocklen = back; | |
| 140 while (cnt > blocklen) { | |
| 141 memcpy(dst, src, blocklen); | |
| 142 dst += blocklen; | |
| 143 cnt -= blocklen; | |
| 144 blocklen <<= 1; | |
| 145 } | |
| 146 memcpy(dst, src, cnt); | |
| 147 } | |
| 148 dst += cnt; | |
| 149 } | |
| 150 c->out = dst; | |
| 151 } | |
| 152 | |
| 153 /** | |
| 154 * \brief decode LZO 1x compressed data | |
| 155 * \param out output buffer | |
| 156 * \param outlen size of output buffer, number of bytes left are returned here | |
| 157 * \param in input buffer | |
| 158 * \param inlen size of input buffer, number of bytes left are returned here | |
| 159 * \return 0 on success, otherwise error flags, see lzo.h | |
| 160 * | |
| 161 * make sure all buffers are appropriately padded, in must provide | |
| 162 * LZO_INPUT_PADDING, out must provide LZO_OUTPUT_PADDING additional bytes | |
| 163 */ | |
| 164 int lzo1x_decode(void *out, int *outlen, void *in, int *inlen) { | |
| 165 enum {COPY, BACKPTR} state = COPY; | |
| 166 int x; | |
| 167 LZOContext c; | |
| 168 c.in = in; | |
| 169 c.in_end = (uint8_t *)in + *inlen; | |
| 170 c.out = c.out_start = out; | |
| 171 c.out_end = (uint8_t *)out + * outlen; | |
| 172 c.error = 0; | |
| 173 x = get_byte(&c); | |
| 174 if (x > 17) { | |
| 175 copy(&c, x - 17); | |
| 176 x = get_byte(&c); | |
| 177 if (x < 16) c.error |= LZO_ERROR; | |
| 178 } | |
| 179 while (!c.error) { | |
| 180 int cnt, back; | |
| 181 if (x >> 4) { | |
| 182 if (x >> 6) { | |
| 183 cnt = (x >> 5) - 1; | |
| 184 back = (get_byte(&c) << 3) + ((x >> 2) & 7) + 1; | |
| 185 } else if (x >> 5) { | |
| 186 cnt = get_len(&c, x, 31); | |
| 187 x = get_byte(&c); | |
| 188 back = (get_byte(&c) << 6) + (x >> 2) + 1; | |
| 189 } else { | |
| 190 cnt = get_len(&c, x, 7); | |
| 191 back = (1 << 14) + ((x & 8) << 11); | |
| 192 x = get_byte(&c); | |
| 193 back += (get_byte(&c) << 6) + (x >> 2); | |
| 194 if (back == (1 << 14)) { | |
| 195 if (cnt != 1) | |
| 196 c.error |= LZO_ERROR; | |
| 197 break; | |
| 198 } | |
| 199 } | |
| 200 } else | |
| 201 switch (state) { | |
| 202 case COPY: | |
| 203 cnt = get_len(&c, x, 15); | |
| 204 copy(&c, cnt + 3); | |
| 205 x = get_byte(&c); | |
| 206 if (x >> 4) | |
| 207 continue; | |
| 208 cnt = 1; | |
| 209 back = (1 << 11) + (get_byte(&c) << 2) + (x >> 2) + 1; | |
| 210 break; | |
| 211 case BACKPTR: | |
| 212 cnt = 0; | |
| 213 back = (get_byte(&c) << 2) + (x >> 2) + 1; | |
| 214 break; | |
| 215 } | |
| 216 copy_backptr(&c, back, cnt + 2); | |
| 217 cnt = x & 3; | |
| 218 state = cnt ? BACKPTR : COPY; | |
| 219 if (cnt) | |
| 220 copy(&c, cnt); | |
| 221 x = get_byte(&c); | |
| 222 } | |
| 223 *inlen = c.in_end - c.in; | |
| 224 *outlen = c.out_end - c.out; | |
| 225 return c.error; | |
| 226 } |
