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"
32 /// Define if we may write up to 12 bytes beyond the output buffer.
33 #define OUTBUF_PADDED 1
34 /// Define if we may read up to 8 bytes beyond the input buffer.
35 #define INBUF_PADDED 1
37 typedef struct LZOContext
{
38 const uint8_t *in
, *in_end
;
39 uint8_t *out_start
, *out
, *out_end
;
44 * @brief Reads one byte from the input buffer, avoiding an overrun.
47 static inline int get_byte(LZOContext
*c
)
49 if (c
->in
< c
->in_end
)
51 c
->error
|= AV_LZO_INPUT_DEPLETED
;
56 #define GETB(c) (*(c).in++)
58 #define GETB(c) get_byte(&(c))
62 * @brief Decodes a length value in the coding used by lzo.
63 * @param x previous byte value
64 * @param mask bits used from x
65 * @return decoded length value
67 static inline int get_len(LZOContext
*c
, int x
, int mask
)
71 while (!(x
= get_byte(c
))) {
72 if (cnt
>= INT_MAX
- 1000) {
73 c
->error
|= AV_LZO_ERROR
;
84 * @brief Copies bytes from input to output buffer with checking.
85 * @param cnt number of bytes to copy, must be >= 0
87 static inline void copy(LZOContext
*c
, int cnt
)
89 register const uint8_t *src
= c
->in
;
90 register uint8_t *dst
= c
->out
;
92 if (cnt
> c
->in_end
- src
) {
93 cnt
= FFMAX(c
->in_end
- src
, 0);
94 c
->error
|= AV_LZO_INPUT_DEPLETED
;
96 if (cnt
> c
->out_end
- dst
) {
97 cnt
= FFMAX(c
->out_end
- dst
, 0);
98 c
->error
|= AV_LZO_OUTPUT_FULL
;
100 #if defined(INBUF_PADDED) && defined(OUTBUF_PADDED)
101 AV_COPY32U(dst
, src
);
107 memcpy(dst
, src
, cnt
);
113 * @brief Copies previously decoded bytes to current position.
114 * @param back how many bytes back we start, must be > 0
115 * @param cnt number of bytes to copy, must be > 0
117 * cnt > back is valid, this will copy the bytes we just copied,
118 * thus creating a repeating pattern with a period length of back.
120 static inline void copy_backptr(LZOContext
*c
, int back
, int cnt
)
122 register uint8_t *dst
= c
->out
;
124 if (dst
- c
->out_start
< back
) {
125 c
->error
|= AV_LZO_INVALID_BACKPTR
;
128 if (cnt
> c
->out_end
- dst
) {
129 cnt
= FFMAX(c
->out_end
- dst
, 0);
130 c
->error
|= AV_LZO_OUTPUT_FULL
;
132 av_memcpy_backptr(dst
, back
, cnt
);
136 int av_lzo1x_decode(void *out
, int *outlen
, const void *in
, int *inlen
)
141 if (*outlen
<= 0 || *inlen
<= 0) {
144 res
|= AV_LZO_OUTPUT_FULL
;
146 res
|= AV_LZO_INPUT_DEPLETED
;
150 c
.in_end
= (const uint8_t *)in
+ *inlen
;
151 c
.out
= c
.out_start
= out
;
152 c
.out_end
= (uint8_t *)out
+ *outlen
;
159 c
.error
|= AV_LZO_ERROR
;
162 c
.error
|= AV_LZO_INPUT_DEPLETED
;
168 back
= (GETB(c
) << 3) + ((x
>> 2) & 7) + 1;
170 cnt
= get_len(&c
, x
, 31);
172 back
= (GETB(c
) << 6) + (x
>> 2) + 1;
174 cnt
= get_len(&c
, x
, 7);
175 back
= (1 << 14) + ((x
& 8) << 11);
177 back
+= (GETB(c
) << 6) + (x
>> 2);
178 if (back
== (1 << 14)) {
180 c
.error
|= AV_LZO_ERROR
;
185 cnt
= get_len(&c
, x
, 15);
191 back
= (1 << 11) + (GETB(c
) << 2) + (x
>> 2) + 1;
194 back
= (GETB(c
) << 2) + (x
>> 2) + 1;
196 copy_backptr(&c
, back
, cnt
+ 2);
202 *inlen
= c
.in_end
- c
.in
;
205 *outlen
= c
.out_end
- c
.out
;