3 * Copyright (c) 2006 Reimar Doeffinger
5 * This file is part of FFmpeg.
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.
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.
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
27 #include "intreadwrite.h"
30 /// Define if we may write up to 12 bytes beyond the output buffer.
31 #define OUTBUF_PADDED 1
32 /// Define if we may read up to 8 bytes beyond the input buffer.
33 #define INBUF_PADDED 1
35 typedef struct LZOContext
{
36 const uint8_t *in
, *in_end
;
37 uint8_t *out_start
, *out
, *out_end
;
42 * @brief Reads one byte from the input buffer, avoiding an overrun.
45 static inline int get_byte(LZOContext
*c
)
47 if (c
->in
< c
->in_end
)
49 c
->error
|= AV_LZO_INPUT_DEPLETED
;
54 #define GETB(c) (*(c).in++)
56 #define GETB(c) get_byte(&(c))
60 * @brief Decodes a length value in the coding used by lzo.
61 * @param x previous byte value
62 * @param mask bits used from x
63 * @return decoded length value
65 static inline int get_len(LZOContext
*c
, int x
, int mask
)
69 while (!(x
= get_byte(c
))) {
70 if (cnt
>= INT_MAX
- 1000) {
71 c
->error
|= AV_LZO_ERROR
;
82 * @brief Copies bytes from input to output buffer with checking.
83 * @param cnt number of bytes to copy, must be >= 0
85 static inline void copy(LZOContext
*c
, int cnt
)
87 register const uint8_t *src
= c
->in
;
88 register uint8_t *dst
= c
->out
;
90 if (cnt
> c
->in_end
- src
) {
91 cnt
= FFMAX(c
->in_end
- src
, 0);
92 c
->error
|= AV_LZO_INPUT_DEPLETED
;
94 if (cnt
> c
->out_end
- dst
) {
95 cnt
= FFMAX(c
->out_end
- dst
, 0);
96 c
->error
|= AV_LZO_OUTPUT_FULL
;
98 #if defined(INBUF_PADDED) && defined(OUTBUF_PADDED)
105 memcpy(dst
, src
, cnt
);
111 * @brief Copies previously decoded bytes to current position.
112 * @param back how many bytes back we start, must be > 0
113 * @param cnt number of bytes to copy, must be > 0
115 * cnt > back is valid, this will copy the bytes we just copied,
116 * thus creating a repeating pattern with a period length of back.
118 static inline void copy_backptr(LZOContext
*c
, int back
, int cnt
)
120 register uint8_t *dst
= c
->out
;
122 if (dst
- c
->out_start
< back
) {
123 c
->error
|= AV_LZO_INVALID_BACKPTR
;
126 if (cnt
> c
->out_end
- dst
) {
127 cnt
= FFMAX(c
->out_end
- dst
, 0);
128 c
->error
|= AV_LZO_OUTPUT_FULL
;
130 av_memcpy_backptr(dst
, back
, cnt
);
134 int av_lzo1x_decode(void *out
, int *outlen
, const void *in
, int *inlen
)
139 if (*outlen
<= 0 || *inlen
<= 0) {
142 res
|= AV_LZO_OUTPUT_FULL
;
144 res
|= AV_LZO_INPUT_DEPLETED
;
148 c
.in_end
= (const uint8_t *)in
+ *inlen
;
149 c
.out
= c
.out_start
= out
;
150 c
.out_end
= (uint8_t *)out
+ *outlen
;
157 c
.error
|= AV_LZO_ERROR
;
160 c
.error
|= AV_LZO_INPUT_DEPLETED
;
166 back
= (GETB(c
) << 3) + ((x
>> 2) & 7) + 1;
168 cnt
= get_len(&c
, x
, 31);
170 back
= (GETB(c
) << 6) + (x
>> 2) + 1;
172 cnt
= get_len(&c
, x
, 7);
173 back
= (1 << 14) + ((x
& 8) << 11);
175 back
+= (GETB(c
) << 6) + (x
>> 2);
176 if (back
== (1 << 14)) {
178 c
.error
|= AV_LZO_ERROR
;
183 cnt
= get_len(&c
, x
, 15);
189 back
= (1 << 11) + (GETB(c
) << 2) + (x
>> 2) + 1;
192 back
= (GETB(c
) << 2) + (x
>> 2) + 1;
194 copy_backptr(&c
, back
, cnt
+ 2);
200 *inlen
= c
.in_end
- c
.in
;
203 *outlen
= c
.out_end
- c
.out
;
209 #include <lzo/lzo1x.h>
211 #define MAXSZ (10*1024*1024)
213 /* Define one of these to 1 if you wish to benchmark liblzo
214 * instead of our native implementation. */
215 #define BENCHMARK_LIBLZO_SAFE 0
216 #define BENCHMARK_LIBLZO_UNSAFE 0
218 int main(int argc
, char *argv
[]) {
219 FILE *in
= fopen(argv
[1], "rb");
220 int comp_level
= argc
> 2 ? atoi(argv
[2]) : 0;
221 uint8_t *orig
= av_malloc(MAXSZ
+ 16);
222 uint8_t *comp
= av_malloc(2*MAXSZ
+ 16);
223 uint8_t *decomp
= av_malloc(MAXSZ
+ 16);
224 size_t s
= fread(orig
, 1, MAXSZ
, in
);
226 long tmp
[LZO1X_MEM_COMPRESS
];
229 av_log_set_level(AV_LOG_DEBUG
);
230 if (comp_level
== 0) {
231 lzo1x_1_compress(orig
, s
, comp
, &clen
, tmp
);
232 } else if (comp_level
== 11) {
233 lzo1x_1_11_compress(orig
, s
, comp
, &clen
, tmp
);
234 } else if (comp_level
== 12) {
235 lzo1x_1_12_compress(orig
, s
, comp
, &clen
, tmp
);
236 } else if (comp_level
== 15) {
237 lzo1x_1_15_compress(orig
, s
, comp
, &clen
, tmp
);
239 lzo1x_999_compress(orig
, s
, comp
, &clen
, tmp
);
240 for (i
= 0; i
< 300; i
++) {
242 inlen
= clen
; outlen
= MAXSZ
;
243 #if BENCHMARK_LIBLZO_SAFE
244 if (lzo1x_decompress_safe(comp
, inlen
, decomp
, &outlen
, NULL
))
245 #elif BENCHMARK_LIBLZO_UNSAFE
246 if (lzo1x_decompress(comp
, inlen
, decomp
, &outlen
, NULL
))
248 if (av_lzo1x_decode(decomp
, &outlen
, comp
, &inlen
))
250 av_log(NULL
, AV_LOG_ERROR
, "decompression error\n");
253 if (memcmp(orig
, decomp
, s
))
254 av_log(NULL
, AV_LOG_ERROR
, "decompression incorrect\n");
256 av_log(NULL
, AV_LOG_ERROR
, "decompression OK\n");