1 |
|
|
/* |
2 |
|
|
* Quicktime Animation (RLE) Video Decoder |
3 |
|
|
* Copyright (C) 2004 The FFmpeg project |
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 |
|
|
|
22 |
|
|
/** |
23 |
|
|
* @file |
24 |
|
|
* QT RLE Video Decoder by Mike Melanson (melanson@pcisys.net) |
25 |
|
|
* For more information about the QT RLE format, visit: |
26 |
|
|
* http://www.pcisys.net/~melanson/codecs/ |
27 |
|
|
* |
28 |
|
|
* The QT RLE decoder has seven modes of operation: |
29 |
|
|
* 1, 2, 4, 8, 16, 24, and 32 bits per pixel. For modes 1, 2, 4, and 8 |
30 |
|
|
* the decoder outputs PAL8 colorspace data. 16-bit data yields RGB555 |
31 |
|
|
* data. 24-bit data is RGB24 and 32-bit data is RGB32. |
32 |
|
|
*/ |
33 |
|
|
|
34 |
|
|
#include <stdio.h> |
35 |
|
|
#include <stdlib.h> |
36 |
|
|
#include <string.h> |
37 |
|
|
|
38 |
|
|
#include "avcodec.h" |
39 |
|
|
#include "decode.h" |
40 |
|
|
#include "bytestream.h" |
41 |
|
|
#include "internal.h" |
42 |
|
|
|
43 |
|
|
typedef struct QtrleContext { |
44 |
|
|
AVCodecContext *avctx; |
45 |
|
|
AVFrame *frame; |
46 |
|
|
|
47 |
|
|
GetByteContext g; |
48 |
|
|
uint32_t pal[256]; |
49 |
|
|
} QtrleContext; |
50 |
|
|
|
51 |
|
|
#define CHECK_PIXEL_PTR(n) \ |
52 |
|
|
if ((pixel_ptr + n > pixel_limit) || (pixel_ptr + n < 0)) { \ |
53 |
|
|
av_log (s->avctx, AV_LOG_ERROR, "Problem: pixel_ptr = %d, pixel_limit = %d\n",\ |
54 |
|
|
pixel_ptr + n, pixel_limit); \ |
55 |
|
|
return; \ |
56 |
|
|
} \ |
57 |
|
|
|
58 |
|
38 |
static void qtrle_decode_1bpp(QtrleContext *s, int row_ptr, int lines_to_change) |
59 |
|
|
{ |
60 |
|
|
int rle_code; |
61 |
|
|
int pixel_ptr; |
62 |
|
38 |
int row_inc = s->frame->linesize[0]; |
63 |
|
|
uint8_t pi0, pi1; /* 2 8-pixel values */ |
64 |
|
38 |
uint8_t *rgb = s->frame->data[0]; |
65 |
|
38 |
int pixel_limit = s->frame->linesize[0] * s->avctx->height; |
66 |
|
|
int skip; |
67 |
|
|
/* skip & 0x80 appears to mean 'start a new line', which can be interpreted |
68 |
|
|
* as 'go to next line' during the decoding of a frame but is 'go to first |
69 |
|
|
* line' at the beginning. Since we always interpret it as 'go to next line' |
70 |
|
|
* in the decoding loop (which makes code simpler/faster), the first line |
71 |
|
|
* would not be counted, so we count one more. |
72 |
|
|
* See: https://trac.ffmpeg.org/ticket/226 |
73 |
|
|
* In the following decoding loop, row_ptr will be the position of the |
74 |
|
|
* current row. */ |
75 |
|
|
|
76 |
|
38 |
row_ptr -= row_inc; |
77 |
|
38 |
pixel_ptr = row_ptr; |
78 |
|
38 |
lines_to_change++; |
79 |
✓✗ |
13034 |
while (lines_to_change) { |
80 |
|
13034 |
skip = bytestream2_get_byte(&s->g); |
81 |
|
13034 |
rle_code = (int8_t)bytestream2_get_byte(&s->g); |
82 |
✓✓ |
13034 |
if (rle_code == 0) |
83 |
|
38 |
break; |
84 |
✓✓ |
12996 |
if(skip & 0x80) { |
85 |
|
9120 |
lines_to_change--; |
86 |
|
9120 |
row_ptr += row_inc; |
87 |
|
9120 |
pixel_ptr = row_ptr + 2 * 8 * (skip & 0x7f); |
88 |
|
|
} else |
89 |
|
3876 |
pixel_ptr += 2 * 8 * skip; |
90 |
✓✗✗✓
|
12996 |
CHECK_PIXEL_PTR(0); /* make sure pixel_ptr is positive */ |
91 |
|
|
|
92 |
✗✓ |
12996 |
if(rle_code == -1) |
93 |
|
|
continue; |
94 |
|
|
|
95 |
✓✓ |
12996 |
if (rle_code < 0) { |
96 |
|
|
/* decode the run length code */ |
97 |
|
1825 |
rle_code = -rle_code; |
98 |
|
|
/* get the next 2 bytes from the stream, treat them as groups |
99 |
|
|
* of 8 pixels, and output them rle_code times */ |
100 |
|
|
|
101 |
|
1825 |
pi0 = bytestream2_get_byte(&s->g); |
102 |
|
1825 |
pi1 = bytestream2_get_byte(&s->g); |
103 |
✓✗✗✓
|
1825 |
CHECK_PIXEL_PTR(rle_code * 2 * 8); |
104 |
|
|
|
105 |
✓✓ |
7072 |
while (rle_code--) { |
106 |
|
5247 |
rgb[pixel_ptr++] = (pi0 >> 7) & 0x01; |
107 |
|
5247 |
rgb[pixel_ptr++] = (pi0 >> 6) & 0x01; |
108 |
|
5247 |
rgb[pixel_ptr++] = (pi0 >> 5) & 0x01; |
109 |
|
5247 |
rgb[pixel_ptr++] = (pi0 >> 4) & 0x01; |
110 |
|
5247 |
rgb[pixel_ptr++] = (pi0 >> 3) & 0x01; |
111 |
|
5247 |
rgb[pixel_ptr++] = (pi0 >> 2) & 0x01; |
112 |
|
5247 |
rgb[pixel_ptr++] = (pi0 >> 1) & 0x01; |
113 |
|
5247 |
rgb[pixel_ptr++] = pi0 & 0x01; |
114 |
|
5247 |
rgb[pixel_ptr++] = (pi1 >> 7) & 0x01; |
115 |
|
5247 |
rgb[pixel_ptr++] = (pi1 >> 6) & 0x01; |
116 |
|
5247 |
rgb[pixel_ptr++] = (pi1 >> 5) & 0x01; |
117 |
|
5247 |
rgb[pixel_ptr++] = (pi1 >> 4) & 0x01; |
118 |
|
5247 |
rgb[pixel_ptr++] = (pi1 >> 3) & 0x01; |
119 |
|
5247 |
rgb[pixel_ptr++] = (pi1 >> 2) & 0x01; |
120 |
|
5247 |
rgb[pixel_ptr++] = (pi1 >> 1) & 0x01; |
121 |
|
5247 |
rgb[pixel_ptr++] = pi1 & 0x01; |
122 |
|
|
} |
123 |
|
|
} else { |
124 |
|
|
/* copy the same pixel directly to output 2 times */ |
125 |
|
11171 |
rle_code *= 2; |
126 |
✓✗✗✓
|
11171 |
CHECK_PIXEL_PTR(rle_code * 8); |
127 |
|
|
|
128 |
✓✓ |
363961 |
while (rle_code--) { |
129 |
|
352790 |
int x = bytestream2_get_byte(&s->g); |
130 |
|
352790 |
rgb[pixel_ptr++] = (x >> 7) & 0x01; |
131 |
|
352790 |
rgb[pixel_ptr++] = (x >> 6) & 0x01; |
132 |
|
352790 |
rgb[pixel_ptr++] = (x >> 5) & 0x01; |
133 |
|
352790 |
rgb[pixel_ptr++] = (x >> 4) & 0x01; |
134 |
|
352790 |
rgb[pixel_ptr++] = (x >> 3) & 0x01; |
135 |
|
352790 |
rgb[pixel_ptr++] = (x >> 2) & 0x01; |
136 |
|
352790 |
rgb[pixel_ptr++] = (x >> 1) & 0x01; |
137 |
|
352790 |
rgb[pixel_ptr++] = x & 0x01; |
138 |
|
|
} |
139 |
|
|
} |
140 |
|
|
} |
141 |
|
|
} |
142 |
|
|
|
143 |
|
114 |
static inline void qtrle_decode_2n4bpp(QtrleContext *s, int row_ptr, |
144 |
|
|
int lines_to_change, int bpp) |
145 |
|
|
{ |
146 |
|
|
int rle_code, i; |
147 |
|
|
int pixel_ptr; |
148 |
|
114 |
int row_inc = s->frame->linesize[0]; |
149 |
|
|
uint8_t pi[16]; /* 16 palette indices */ |
150 |
|
114 |
uint8_t *rgb = s->frame->data[0]; |
151 |
|
114 |
int pixel_limit = s->frame->linesize[0] * s->avctx->height; |
152 |
✓✓ |
114 |
int num_pixels = (bpp == 4) ? 8 : 16; |
153 |
|
|
|
154 |
✓✓ |
27474 |
while (lines_to_change--) { |
155 |
|
27360 |
pixel_ptr = row_ptr + (num_pixels * (bytestream2_get_byte(&s->g) - 1)); |
156 |
✓✗✗✓
|
27360 |
CHECK_PIXEL_PTR(0); |
157 |
|
|
|
158 |
✓✓ |
172476 |
while ((rle_code = (int8_t)bytestream2_get_byte(&s->g)) != -1) { |
159 |
✗✓ |
145116 |
if (bytestream2_get_bytes_left(&s->g) < 1) |
160 |
|
|
return; |
161 |
✓✓ |
145116 |
if (rle_code == 0) { |
162 |
|
|
/* there's another skip code in the stream */ |
163 |
|
32727 |
pixel_ptr += (num_pixels * (bytestream2_get_byte(&s->g) - 1)); |
164 |
✓✗✗✓
|
32727 |
CHECK_PIXEL_PTR(0); /* make sure pixel_ptr is positive */ |
165 |
✓✓ |
112389 |
} else if (rle_code < 0) { |
166 |
|
|
/* decode the run length code */ |
167 |
|
30399 |
rle_code = -rle_code; |
168 |
|
|
/* get the next 4 bytes from the stream, treat them as palette |
169 |
|
|
* indexes, and output them rle_code times */ |
170 |
✓✓ |
292911 |
for (i = num_pixels-1; i >= 0; i--) { |
171 |
|
262512 |
pi[num_pixels-1-i] = (bytestream2_peek_byte(&s->g) >> ((i*bpp) & 0x07)) & ((1<<bpp)-1); |
172 |
|
262512 |
bytestream2_skip(&s->g, ((i & ((num_pixels>>2)-1)) == 0)); |
173 |
|
|
} |
174 |
✓✗✗✓
|
30399 |
CHECK_PIXEL_PTR(rle_code * num_pixels); |
175 |
✓✓ |
131895 |
while (rle_code--) { |
176 |
|
101496 |
memcpy(&rgb[pixel_ptr], &pi, num_pixels); |
177 |
|
101496 |
pixel_ptr += num_pixels; |
178 |
|
|
} |
179 |
|
|
} else { |
180 |
|
|
/* copy the same pixel directly to output 4 times */ |
181 |
|
81990 |
rle_code *= 4; |
182 |
✓✗✗✓
|
81990 |
CHECK_PIXEL_PTR(rle_code*(num_pixels>>2)); |
183 |
✓✓ |
2966410 |
while (rle_code--) { |
184 |
✓✓ |
2884420 |
if(bpp == 4) { |
185 |
|
2213528 |
int x = bytestream2_get_byte(&s->g); |
186 |
|
2213528 |
rgb[pixel_ptr++] = (x >> 4) & 0x0f; |
187 |
|
2213528 |
rgb[pixel_ptr++] = x & 0x0f; |
188 |
|
|
} else { |
189 |
|
670892 |
int x = bytestream2_get_byte(&s->g); |
190 |
|
670892 |
rgb[pixel_ptr++] = (x >> 6) & 0x03; |
191 |
|
670892 |
rgb[pixel_ptr++] = (x >> 4) & 0x03; |
192 |
|
670892 |
rgb[pixel_ptr++] = (x >> 2) & 0x03; |
193 |
|
670892 |
rgb[pixel_ptr++] = x & 0x03; |
194 |
|
|
} |
195 |
|
|
} |
196 |
|
|
} |
197 |
|
|
} |
198 |
|
27360 |
row_ptr += row_inc; |
199 |
|
|
} |
200 |
|
|
} |
201 |
|
|
|
202 |
|
208 |
static void qtrle_decode_8bpp(QtrleContext *s, int row_ptr, int lines_to_change) |
203 |
|
|
{ |
204 |
|
|
int rle_code; |
205 |
|
|
int pixel_ptr; |
206 |
|
208 |
int row_inc = s->frame->linesize[0]; |
207 |
|
|
uint8_t pi1, pi2, pi3, pi4; /* 4 palette indexes */ |
208 |
|
208 |
uint8_t *rgb = s->frame->data[0]; |
209 |
|
208 |
int pixel_limit = s->frame->linesize[0] * s->avctx->height; |
210 |
|
|
|
211 |
✓✓ |
48519 |
while (lines_to_change--) { |
212 |
|
48311 |
pixel_ptr = row_ptr + (4 * (bytestream2_get_byte(&s->g) - 1)); |
213 |
✓✗✗✓
|
48311 |
CHECK_PIXEL_PTR(0); |
214 |
|
|
|
215 |
✓✓ |
199338 |
while ((rle_code = (int8_t)bytestream2_get_byte(&s->g)) != -1) { |
216 |
✗✓ |
151027 |
if (bytestream2_get_bytes_left(&s->g) < 1) |
217 |
|
|
return; |
218 |
✓✓ |
151027 |
if (rle_code == 0) { |
219 |
|
|
/* there's another skip code in the stream */ |
220 |
|
39089 |
pixel_ptr += (4 * (bytestream2_get_byte(&s->g) - 1)); |
221 |
✓✗✗✓
|
39089 |
CHECK_PIXEL_PTR(0); /* make sure pixel_ptr is positive */ |
222 |
✓✓ |
111938 |
} else if (rle_code < 0) { |
223 |
|
|
/* decode the run length code */ |
224 |
|
18173 |
rle_code = -rle_code; |
225 |
|
|
/* get the next 4 bytes from the stream, treat them as palette |
226 |
|
|
* indexes, and output them rle_code times */ |
227 |
|
18173 |
pi1 = bytestream2_get_byte(&s->g); |
228 |
|
18173 |
pi2 = bytestream2_get_byte(&s->g); |
229 |
|
18173 |
pi3 = bytestream2_get_byte(&s->g); |
230 |
|
18173 |
pi4 = bytestream2_get_byte(&s->g); |
231 |
|
|
|
232 |
✓✗✗✓
|
18173 |
CHECK_PIXEL_PTR(rle_code * 4); |
233 |
|
|
|
234 |
✓✓ |
119754 |
while (rle_code--) { |
235 |
|
101581 |
rgb[pixel_ptr++] = pi1; |
236 |
|
101581 |
rgb[pixel_ptr++] = pi2; |
237 |
|
101581 |
rgb[pixel_ptr++] = pi3; |
238 |
|
101581 |
rgb[pixel_ptr++] = pi4; |
239 |
|
|
} |
240 |
|
|
} else { |
241 |
|
|
/* copy the same pixel directly to output 4 times */ |
242 |
|
93765 |
rle_code *= 4; |
243 |
✓✗✗✓
|
93765 |
CHECK_PIXEL_PTR(rle_code); |
244 |
|
|
|
245 |
|
93765 |
bytestream2_get_buffer(&s->g, &rgb[pixel_ptr], rle_code); |
246 |
|
93765 |
pixel_ptr += rle_code; |
247 |
|
|
} |
248 |
|
|
} |
249 |
|
48311 |
row_ptr += row_inc; |
250 |
|
|
} |
251 |
|
|
} |
252 |
|
|
|
253 |
|
83 |
static void qtrle_decode_16bpp(QtrleContext *s, int row_ptr, int lines_to_change) |
254 |
|
|
{ |
255 |
|
|
int rle_code; |
256 |
|
|
int pixel_ptr; |
257 |
|
83 |
int row_inc = s->frame->linesize[0]; |
258 |
|
|
uint16_t rgb16; |
259 |
|
83 |
uint8_t *rgb = s->frame->data[0]; |
260 |
|
83 |
int pixel_limit = s->frame->linesize[0] * s->avctx->height; |
261 |
|
|
|
262 |
✓✓ |
10043 |
while (lines_to_change--) { |
263 |
|
9960 |
pixel_ptr = row_ptr + (bytestream2_get_byte(&s->g) - 1) * 2; |
264 |
✓✗✗✓
|
9960 |
CHECK_PIXEL_PTR(0); |
265 |
|
|
|
266 |
✓✓ |
278662 |
while ((rle_code = (int8_t)bytestream2_get_byte(&s->g)) != -1) { |
267 |
✗✓ |
268702 |
if (bytestream2_get_bytes_left(&s->g) < 1) |
268 |
|
|
return; |
269 |
✗✓ |
268702 |
if (rle_code == 0) { |
270 |
|
|
/* there's another skip code in the stream */ |
271 |
|
|
pixel_ptr += (bytestream2_get_byte(&s->g) - 1) * 2; |
272 |
|
|
CHECK_PIXEL_PTR(0); /* make sure pixel_ptr is positive */ |
273 |
✓✓ |
268702 |
} else if (rle_code < 0) { |
274 |
|
|
/* decode the run length code */ |
275 |
|
234583 |
rle_code = -rle_code; |
276 |
|
234583 |
rgb16 = bytestream2_get_be16(&s->g); |
277 |
|
|
|
278 |
✓✗✗✓
|
234583 |
CHECK_PIXEL_PTR(rle_code * 2); |
279 |
|
|
|
280 |
✓✓ |
1764013 |
while (rle_code--) { |
281 |
|
1529430 |
*(uint16_t *)(&rgb[pixel_ptr]) = rgb16; |
282 |
|
1529430 |
pixel_ptr += 2; |
283 |
|
|
} |
284 |
|
|
} else { |
285 |
✓✗✗✓
|
34119 |
CHECK_PIXEL_PTR(rle_code * 2); |
286 |
|
|
|
287 |
|
|
/* copy pixels directly to output */ |
288 |
✓✓ |
98289 |
while (rle_code--) { |
289 |
|
64170 |
rgb16 = bytestream2_get_be16(&s->g); |
290 |
|
64170 |
*(uint16_t *)(&rgb[pixel_ptr]) = rgb16; |
291 |
|
64170 |
pixel_ptr += 2; |
292 |
|
|
} |
293 |
|
|
} |
294 |
|
|
} |
295 |
|
9960 |
row_ptr += row_inc; |
296 |
|
|
} |
297 |
|
|
} |
298 |
|
|
|
299 |
|
250 |
static void qtrle_decode_24bpp(QtrleContext *s, int row_ptr, int lines_to_change) |
300 |
|
|
{ |
301 |
|
|
int rle_code, rle_code_half; |
302 |
|
|
int pixel_ptr; |
303 |
|
250 |
int row_inc = s->frame->linesize[0]; |
304 |
|
|
uint8_t b; |
305 |
|
|
uint16_t rg; |
306 |
|
250 |
uint8_t *rgb = s->frame->data[0]; |
307 |
|
250 |
int pixel_limit = s->frame->linesize[0] * s->avctx->height; |
308 |
|
|
|
309 |
✓✓ |
51552 |
while (lines_to_change--) { |
310 |
|
51302 |
pixel_ptr = row_ptr + (bytestream2_get_byte(&s->g) - 1) * 3; |
311 |
✓✗✗✓
|
51302 |
CHECK_PIXEL_PTR(0); |
312 |
|
|
|
313 |
✓✓ |
1607159 |
while ((rle_code = (int8_t)bytestream2_get_byte(&s->g)) != -1) { |
314 |
✗✓ |
1555857 |
if (bytestream2_get_bytes_left(&s->g) < 1) |
315 |
|
|
return; |
316 |
✓✓ |
1555857 |
if (rle_code == 0) { |
317 |
|
|
/* there's another skip code in the stream */ |
318 |
|
109372 |
pixel_ptr += (bytestream2_get_byte(&s->g) - 1) * 3; |
319 |
✓✗✗✓
|
109372 |
CHECK_PIXEL_PTR(0); /* make sure pixel_ptr is positive */ |
320 |
✓✓ |
1446485 |
} else if (rle_code < 0) { |
321 |
|
|
/* decode the run length code */ |
322 |
|
764625 |
rle_code = -rle_code; |
323 |
|
764625 |
rg = bytestream2_get_ne16(&s->g); |
324 |
|
764625 |
b = bytestream2_get_byte(&s->g); |
325 |
|
|
|
326 |
✓✗✗✓
|
764625 |
CHECK_PIXEL_PTR(rle_code * 3); |
327 |
|
|
|
328 |
✓✓ |
3138145 |
while (rle_code--) { |
329 |
|
2373520 |
AV_WN16(rgb + pixel_ptr, rg); |
330 |
|
2373520 |
rgb[pixel_ptr + 2] = b; |
331 |
|
2373520 |
pixel_ptr += 3; |
332 |
|
|
} |
333 |
|
|
} else { |
334 |
✓✗✗✓
|
681860 |
CHECK_PIXEL_PTR(rle_code * 3); |
335 |
|
|
|
336 |
|
681860 |
rle_code_half = rle_code / 2; |
337 |
|
|
|
338 |
✓✓ |
7319587 |
while (rle_code_half--) { /* copy 2 raw rgb value at the same time */ |
339 |
|
6637727 |
AV_WN32(rgb + pixel_ptr, bytestream2_get_ne32(&s->g)); /* rgbr */ |
340 |
|
6637727 |
AV_WN16(rgb + pixel_ptr + 4, bytestream2_get_ne16(&s->g)); /* rgbr */ |
341 |
|
6637727 |
pixel_ptr += 6; |
342 |
|
|
} |
343 |
|
|
|
344 |
✓✓ |
681860 |
if (rle_code % 2 != 0){ /* not even raw value */ |
345 |
|
229085 |
AV_WN16(rgb + pixel_ptr, bytestream2_get_ne16(&s->g)); |
346 |
|
229085 |
rgb[pixel_ptr + 2] = bytestream2_get_byte(&s->g); |
347 |
|
229085 |
pixel_ptr += 3; |
348 |
|
|
} |
349 |
|
|
} |
350 |
|
|
} |
351 |
|
51302 |
row_ptr += row_inc; |
352 |
|
|
} |
353 |
|
|
} |
354 |
|
|
|
355 |
|
26 |
static void qtrle_decode_32bpp(QtrleContext *s, int row_ptr, int lines_to_change) |
356 |
|
|
{ |
357 |
|
|
int rle_code, rle_code_half; |
358 |
|
|
int pixel_ptr; |
359 |
|
26 |
int row_inc = s->frame->linesize[0]; |
360 |
|
|
unsigned int argb; |
361 |
|
26 |
uint8_t *rgb = s->frame->data[0]; |
362 |
|
26 |
int pixel_limit = s->frame->linesize[0] * s->avctx->height; |
363 |
|
|
|
364 |
✓✓ |
12506 |
while (lines_to_change--) { |
365 |
|
12480 |
pixel_ptr = row_ptr + (bytestream2_get_byte(&s->g) - 1) * 4; |
366 |
✓✗✗✓
|
12480 |
CHECK_PIXEL_PTR(0); |
367 |
|
|
|
368 |
✓✓ |
1205972 |
while ((rle_code = (int8_t)bytestream2_get_byte(&s->g)) != -1) { |
369 |
✗✓ |
1193492 |
if (bytestream2_get_bytes_left(&s->g) < 1) |
370 |
|
|
return; |
371 |
✓✓ |
1193492 |
if (rle_code == 0) { |
372 |
|
|
/* there's another skip code in the stream */ |
373 |
|
244756 |
pixel_ptr += (bytestream2_get_byte(&s->g) - 1) * 4; |
374 |
✓✗✗✓
|
244756 |
CHECK_PIXEL_PTR(0); /* make sure pixel_ptr is positive */ |
375 |
✓✓ |
948736 |
} else if (rle_code < 0) { |
376 |
|
|
/* decode the run length code */ |
377 |
|
565158 |
rle_code = -rle_code; |
378 |
|
565158 |
argb = bytestream2_get_ne32(&s->g); |
379 |
|
|
|
380 |
✓✗✗✓
|
565158 |
CHECK_PIXEL_PTR(rle_code * 4); |
381 |
|
|
|
382 |
✓✓ |
2768198 |
while (rle_code--) { |
383 |
|
2203040 |
AV_WN32A(rgb + pixel_ptr, argb); |
384 |
|
2203040 |
pixel_ptr += 4; |
385 |
|
|
} |
386 |
|
|
} else { |
387 |
✓✗✗✓
|
383578 |
CHECK_PIXEL_PTR(rle_code * 4); |
388 |
|
|
|
389 |
|
|
/* copy pixels directly to output */ |
390 |
|
383578 |
rle_code_half = rle_code / 2; |
391 |
✓✓ |
871158 |
while (rle_code_half--) { /* copy 2 argb raw value at the same time */ |
392 |
|
487580 |
AV_WN64(rgb + pixel_ptr, bytestream2_get_ne64(&s->g)); |
393 |
|
487580 |
pixel_ptr += 8; |
394 |
|
|
} |
395 |
|
|
|
396 |
✓✓ |
383578 |
if (rle_code % 2 != 0){ /* not even raw value */ |
397 |
|
256768 |
AV_WN32A(rgb + pixel_ptr, bytestream2_get_ne32(&s->g)); |
398 |
|
256768 |
pixel_ptr += 4; |
399 |
|
|
} |
400 |
|
|
} |
401 |
|
|
} |
402 |
|
12480 |
row_ptr += row_inc; |
403 |
|
|
} |
404 |
|
|
} |
405 |
|
|
|
406 |
|
39 |
static av_cold int qtrle_decode_init(AVCodecContext *avctx) |
407 |
|
|
{ |
408 |
|
39 |
QtrleContext *s = avctx->priv_data; |
409 |
|
|
|
410 |
|
39 |
s->avctx = avctx; |
411 |
✓✓✓✓ ✗ |
39 |
switch (avctx->bits_per_coded_sample) { |
412 |
|
17 |
case 1: |
413 |
|
|
case 2: |
414 |
|
|
case 4: |
415 |
|
|
case 8: |
416 |
|
|
case 33: |
417 |
|
|
case 34: |
418 |
|
|
case 36: |
419 |
|
|
case 40: |
420 |
|
17 |
avctx->pix_fmt = AV_PIX_FMT_PAL8; |
421 |
|
17 |
break; |
422 |
|
|
|
423 |
|
2 |
case 16: |
424 |
|
2 |
avctx->pix_fmt = AV_PIX_FMT_RGB555; |
425 |
|
2 |
break; |
426 |
|
|
|
427 |
|
18 |
case 24: |
428 |
|
18 |
avctx->pix_fmt = AV_PIX_FMT_RGB24; |
429 |
|
18 |
break; |
430 |
|
|
|
431 |
|
2 |
case 32: |
432 |
|
2 |
avctx->pix_fmt = AV_PIX_FMT_ARGB; |
433 |
|
2 |
break; |
434 |
|
|
|
435 |
|
|
default: |
436 |
|
|
av_log (avctx, AV_LOG_ERROR, "Unsupported colorspace: %d bits/sample?\n", |
437 |
|
|
avctx->bits_per_coded_sample); |
438 |
|
|
return AVERROR_INVALIDDATA; |
439 |
|
|
} |
440 |
|
|
|
441 |
|
39 |
s->frame = av_frame_alloc(); |
442 |
✗✓ |
39 |
if (!s->frame) |
443 |
|
|
return AVERROR(ENOMEM); |
444 |
|
|
|
445 |
|
39 |
return 0; |
446 |
|
|
} |
447 |
|
|
|
448 |
|
828 |
static int qtrle_decode_frame(AVCodecContext *avctx, |
449 |
|
|
void *data, int *got_frame, |
450 |
|
|
AVPacket *avpkt) |
451 |
|
|
{ |
452 |
|
828 |
QtrleContext *s = avctx->priv_data; |
453 |
|
|
int header, start_line; |
454 |
|
|
int height, row_ptr; |
455 |
|
828 |
int has_palette = 0; |
456 |
|
828 |
int duplicate = 0; |
457 |
|
|
int ret, size; |
458 |
|
|
|
459 |
|
828 |
bytestream2_init(&s->g, avpkt->data, avpkt->size); |
460 |
|
|
|
461 |
|
|
/* check if this frame is even supposed to change */ |
462 |
✓✓ |
828 |
if (avpkt->size < 8) { |
463 |
|
109 |
duplicate = 1; |
464 |
|
109 |
goto done; |
465 |
|
|
} |
466 |
|
|
|
467 |
|
|
/* start after the chunk size */ |
468 |
|
719 |
size = bytestream2_get_be32(&s->g) & 0x3FFFFFFF; |
469 |
✗✓ |
719 |
if (size - avpkt->size > size * (int64_t)avctx->discard_damaged_percentage / 100) |
470 |
|
|
return AVERROR_INVALIDDATA; |
471 |
|
|
|
472 |
|
|
|
473 |
|
|
/* fetch the header */ |
474 |
|
719 |
header = bytestream2_get_be16(&s->g); |
475 |
|
|
|
476 |
|
|
/* if a header is present, fetch additional decoding parameters */ |
477 |
✓✓ |
719 |
if (header & 0x0008) { |
478 |
✗✓ |
369 |
if (avpkt->size < 14) { |
479 |
|
|
duplicate = 1; |
480 |
|
|
goto done; |
481 |
|
|
} |
482 |
|
369 |
start_line = bytestream2_get_be16(&s->g); |
483 |
|
369 |
bytestream2_skip(&s->g, 2); |
484 |
|
369 |
height = bytestream2_get_be16(&s->g); |
485 |
|
369 |
bytestream2_skip(&s->g, 2); |
486 |
✗✓ |
369 |
if (height > s->avctx->height - start_line) { |
487 |
|
|
duplicate = 1; |
488 |
|
|
goto done; |
489 |
|
|
} |
490 |
|
|
} else { |
491 |
|
350 |
start_line = 0; |
492 |
|
350 |
height = s->avctx->height; |
493 |
|
|
} |
494 |
✗✓ |
719 |
if ((ret = ff_reget_buffer(avctx, s->frame, 0)) < 0) |
495 |
|
|
return ret; |
496 |
|
|
|
497 |
|
719 |
row_ptr = s->frame->linesize[0] * start_line; |
498 |
|
|
|
499 |
✓✓✓✓ ✓✓✓✗
|
719 |
switch (avctx->bits_per_coded_sample) { |
500 |
|
38 |
case 1: |
501 |
|
|
case 33: |
502 |
|
38 |
qtrle_decode_1bpp(s, row_ptr, height); |
503 |
|
38 |
has_palette = 1; |
504 |
|
38 |
break; |
505 |
|
|
|
506 |
|
38 |
case 2: |
507 |
|
|
case 34: |
508 |
|
38 |
qtrle_decode_2n4bpp(s, row_ptr, height, 2); |
509 |
|
38 |
has_palette = 1; |
510 |
|
38 |
break; |
511 |
|
|
|
512 |
|
76 |
case 4: |
513 |
|
|
case 36: |
514 |
|
76 |
qtrle_decode_2n4bpp(s, row_ptr, height, 4); |
515 |
|
76 |
has_palette = 1; |
516 |
|
76 |
break; |
517 |
|
|
|
518 |
|
208 |
case 8: |
519 |
|
|
case 40: |
520 |
|
208 |
qtrle_decode_8bpp(s, row_ptr, height); |
521 |
|
208 |
has_palette = 1; |
522 |
|
208 |
break; |
523 |
|
|
|
524 |
|
83 |
case 16: |
525 |
|
83 |
qtrle_decode_16bpp(s, row_ptr, height); |
526 |
|
83 |
break; |
527 |
|
|
|
528 |
|
250 |
case 24: |
529 |
|
250 |
qtrle_decode_24bpp(s, row_ptr, height); |
530 |
|
250 |
break; |
531 |
|
|
|
532 |
|
26 |
case 32: |
533 |
|
26 |
qtrle_decode_32bpp(s, row_ptr, height); |
534 |
|
26 |
break; |
535 |
|
|
|
536 |
|
|
default: |
537 |
|
|
av_log (s->avctx, AV_LOG_ERROR, "Unsupported colorspace: %d bits/sample?\n", |
538 |
|
|
avctx->bits_per_coded_sample); |
539 |
|
|
break; |
540 |
|
|
} |
541 |
|
|
|
542 |
✓✓ |
719 |
if(has_palette) { |
543 |
|
360 |
s->frame->palette_has_changed = ff_copy_palette(s->pal, avpkt, avctx); |
544 |
|
|
|
545 |
|
|
/* make the palette available on the way out */ |
546 |
|
360 |
memcpy(s->frame->data[1], s->pal, AVPALETTE_SIZE); |
547 |
|
|
} |
548 |
|
|
|
549 |
|
359 |
done: |
550 |
✗✓ |
828 |
if (!s->frame->data[0]) |
551 |
|
|
return AVERROR_INVALIDDATA; |
552 |
✓✓ |
828 |
if (duplicate) { |
553 |
|
|
// ff_reget_buffer() isn't needed when frames don't change, so just update |
554 |
|
|
// frame props. |
555 |
|
109 |
ret = ff_decode_frame_props(avctx, s->frame); |
556 |
✗✓ |
109 |
if (ret < 0) |
557 |
|
|
return ret; |
558 |
|
|
} |
559 |
|
|
|
560 |
✗✓ |
828 |
if ((ret = av_frame_ref(data, s->frame)) < 0) |
561 |
|
|
return ret; |
562 |
|
828 |
*got_frame = 1; |
563 |
|
|
|
564 |
|
|
/* always report that the buffer was completely consumed */ |
565 |
|
828 |
return avpkt->size; |
566 |
|
|
} |
567 |
|
|
|
568 |
|
|
static void qtrle_decode_flush(AVCodecContext *avctx) |
569 |
|
|
{ |
570 |
|
|
QtrleContext *s = avctx->priv_data; |
571 |
|
|
|
572 |
|
|
av_frame_unref(s->frame); |
573 |
|
|
} |
574 |
|
|
|
575 |
|
39 |
static av_cold int qtrle_decode_end(AVCodecContext *avctx) |
576 |
|
|
{ |
577 |
|
39 |
QtrleContext *s = avctx->priv_data; |
578 |
|
|
|
579 |
|
39 |
av_frame_free(&s->frame); |
580 |
|
|
|
581 |
|
39 |
return 0; |
582 |
|
|
} |
583 |
|
|
|
584 |
|
|
AVCodec ff_qtrle_decoder = { |
585 |
|
|
.name = "qtrle", |
586 |
|
|
.long_name = NULL_IF_CONFIG_SMALL("QuickTime Animation (RLE) video"), |
587 |
|
|
.type = AVMEDIA_TYPE_VIDEO, |
588 |
|
|
.id = AV_CODEC_ID_QTRLE, |
589 |
|
|
.priv_data_size = sizeof(QtrleContext), |
590 |
|
|
.init = qtrle_decode_init, |
591 |
|
|
.close = qtrle_decode_end, |
592 |
|
|
.decode = qtrle_decode_frame, |
593 |
|
|
.flush = qtrle_decode_flush, |
594 |
|
|
.capabilities = AV_CODEC_CAP_DR1, |
595 |
|
|
}; |