/src/ffmpeg/libavcodec/qtrle.c
Line | Count | Source |
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 <string.h> |
35 | | |
36 | | #include "avcodec.h" |
37 | | #include "decode.h" |
38 | | #include "bytestream.h" |
39 | | #include "codec_internal.h" |
40 | | |
41 | | #include "libavutil/attributes.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 | 3.85M | if ((pixel_ptr + n > pixel_limit) || (pixel_ptr + n < 0)) { \ |
53 | 21.2k | av_log (s->avctx, AV_LOG_ERROR, "Problem: pixel_ptr = %d, pixel_limit = %d\n",\ |
54 | 21.2k | pixel_ptr + n, pixel_limit); \ |
55 | 21.2k | return; \ |
56 | 21.2k | } \ |
57 | | |
58 | | static void qtrle_decode_1bpp(QtrleContext *s, int row_ptr, int lines_to_change) |
59 | 4.74k | { |
60 | 4.74k | int rle_code; |
61 | 4.74k | int pixel_ptr; |
62 | 4.74k | int row_inc = s->frame->linesize[0]; |
63 | 4.74k | uint8_t pi0, pi1; /* 2 8-pixel values */ |
64 | 4.74k | uint8_t *rgb = s->frame->data[0]; |
65 | 4.74k | int pixel_limit = s->frame->linesize[0] * s->avctx->height; |
66 | 4.74k | 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 | 4.74k | row_ptr -= row_inc; |
77 | 4.74k | pixel_ptr = row_ptr; |
78 | 4.74k | lines_to_change++; |
79 | 25.4k | while (lines_to_change) { |
80 | 25.2k | skip = bytestream2_get_byte(&s->g); |
81 | 25.2k | rle_code = (int8_t)bytestream2_get_byte(&s->g); |
82 | 25.2k | if (rle_code == 0) |
83 | 3.17k | break; |
84 | 22.0k | if(skip & 0x80) { |
85 | 18.6k | lines_to_change--; |
86 | 18.6k | row_ptr += row_inc; |
87 | 18.6k | pixel_ptr = row_ptr + 2 * 8 * (skip & 0x7f); |
88 | 18.6k | } else |
89 | 3.35k | pixel_ptr += 2 * 8 * skip; |
90 | 22.0k | CHECK_PIXEL_PTR(0); /* make sure pixel_ptr is positive */ |
91 | | |
92 | 21.2k | if(rle_code == -1) |
93 | 15.0k | continue; |
94 | | |
95 | 6.20k | if (rle_code < 0) { |
96 | | /* decode the run length code */ |
97 | 4.50k | 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 | 4.50k | pi0 = bytestream2_get_byte(&s->g); |
102 | 4.50k | pi1 = bytestream2_get_byte(&s->g); |
103 | 4.50k | CHECK_PIXEL_PTR(rle_code * 2 * 8); |
104 | | |
105 | 209k | while (rle_code--) { |
106 | 205k | rgb[pixel_ptr++] = (pi0 >> 7) & 0x01; |
107 | 205k | rgb[pixel_ptr++] = (pi0 >> 6) & 0x01; |
108 | 205k | rgb[pixel_ptr++] = (pi0 >> 5) & 0x01; |
109 | 205k | rgb[pixel_ptr++] = (pi0 >> 4) & 0x01; |
110 | 205k | rgb[pixel_ptr++] = (pi0 >> 3) & 0x01; |
111 | 205k | rgb[pixel_ptr++] = (pi0 >> 2) & 0x01; |
112 | 205k | rgb[pixel_ptr++] = (pi0 >> 1) & 0x01; |
113 | 205k | rgb[pixel_ptr++] = pi0 & 0x01; |
114 | 205k | rgb[pixel_ptr++] = (pi1 >> 7) & 0x01; |
115 | 205k | rgb[pixel_ptr++] = (pi1 >> 6) & 0x01; |
116 | 205k | rgb[pixel_ptr++] = (pi1 >> 5) & 0x01; |
117 | 205k | rgb[pixel_ptr++] = (pi1 >> 4) & 0x01; |
118 | 205k | rgb[pixel_ptr++] = (pi1 >> 3) & 0x01; |
119 | 205k | rgb[pixel_ptr++] = (pi1 >> 2) & 0x01; |
120 | 205k | rgb[pixel_ptr++] = (pi1 >> 1) & 0x01; |
121 | 205k | rgb[pixel_ptr++] = pi1 & 0x01; |
122 | 205k | } |
123 | 4.21k | } else { |
124 | | /* copy the same pixel directly to output 2 times */ |
125 | 1.70k | rle_code *= 2; |
126 | 1.70k | CHECK_PIXEL_PTR(rle_code * 8); |
127 | | |
128 | 129k | while (rle_code--) { |
129 | 128k | int x = bytestream2_get_byte(&s->g); |
130 | 128k | rgb[pixel_ptr++] = (x >> 7) & 0x01; |
131 | 128k | rgb[pixel_ptr++] = (x >> 6) & 0x01; |
132 | 128k | rgb[pixel_ptr++] = (x >> 5) & 0x01; |
133 | 128k | rgb[pixel_ptr++] = (x >> 4) & 0x01; |
134 | 128k | rgb[pixel_ptr++] = (x >> 3) & 0x01; |
135 | 128k | rgb[pixel_ptr++] = (x >> 2) & 0x01; |
136 | 128k | rgb[pixel_ptr++] = (x >> 1) & 0x01; |
137 | 128k | rgb[pixel_ptr++] = x & 0x01; |
138 | 128k | } |
139 | 1.47k | } |
140 | 6.20k | } |
141 | 4.74k | } |
142 | | |
143 | | static inline void qtrle_decode_2n4bpp(QtrleContext *s, int row_ptr, |
144 | | int lines_to_change, int bpp) |
145 | 5.26k | { |
146 | 5.26k | int rle_code, i; |
147 | 5.26k | int pixel_ptr; |
148 | 5.26k | int row_inc = s->frame->linesize[0]; |
149 | 5.26k | uint8_t pi[16]; /* 16 palette indices */ |
150 | 5.26k | uint8_t *rgb = s->frame->data[0]; |
151 | 5.26k | int pixel_limit = s->frame->linesize[0] * s->avctx->height; |
152 | 5.26k | int num_pixels = (bpp == 4) ? 8 : 16; |
153 | | |
154 | 54.1k | while (lines_to_change--) { |
155 | 53.7k | pixel_ptr = row_ptr + (num_pixels * (bytestream2_get_byte(&s->g) - 1)); |
156 | 53.7k | CHECK_PIXEL_PTR(0); |
157 | | |
158 | 97.9k | while ((rle_code = (int8_t)bytestream2_get_byte(&s->g)) != -1) { |
159 | 49.0k | if (bytestream2_get_bytes_left(&s->g) < 1) |
160 | 1.60k | return; |
161 | 47.4k | if (rle_code == 0) { |
162 | | /* there's another skip code in the stream */ |
163 | 15.3k | pixel_ptr += (num_pixels * (bytestream2_get_byte(&s->g) - 1)); |
164 | 15.3k | CHECK_PIXEL_PTR(0); /* make sure pixel_ptr is positive */ |
165 | 32.1k | } else if (rle_code < 0) { |
166 | | /* decode the run length code */ |
167 | 25.7k | 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 | 356k | for (i = num_pixels-1; i >= 0; i--) { |
171 | 330k | pi[num_pixels-1-i] = (bytestream2_peek_byte(&s->g) >> ((i*bpp) & 0x07)) & ((1<<bpp)-1); |
172 | 330k | bytestream2_skip(&s->g, ((i & ((num_pixels>>2)-1)) == 0)); |
173 | 330k | } |
174 | 25.7k | CHECK_PIXEL_PTR(rle_code * num_pixels); |
175 | 1.86M | while (rle_code--) { |
176 | 1.84M | memcpy(&rgb[pixel_ptr], &pi, num_pixels); |
177 | 1.84M | pixel_ptr += num_pixels; |
178 | 1.84M | } |
179 | 25.5k | } else { |
180 | | /* copy the same pixel directly to output 4 times */ |
181 | 6.36k | rle_code *= 4; |
182 | 6.36k | CHECK_PIXEL_PTR(rle_code*(num_pixels>>2)); |
183 | 660k | while (rle_code--) { |
184 | 654k | if(bpp == 4) { |
185 | 238k | int x = bytestream2_get_byte(&s->g); |
186 | 238k | rgb[pixel_ptr++] = (x >> 4) & 0x0f; |
187 | 238k | rgb[pixel_ptr++] = x & 0x0f; |
188 | 415k | } else { |
189 | 415k | int x = bytestream2_get_byte(&s->g); |
190 | 415k | rgb[pixel_ptr++] = (x >> 6) & 0x03; |
191 | 415k | rgb[pixel_ptr++] = (x >> 4) & 0x03; |
192 | 415k | rgb[pixel_ptr++] = (x >> 2) & 0x03; |
193 | 415k | rgb[pixel_ptr++] = x & 0x03; |
194 | 415k | } |
195 | 654k | } |
196 | 6.13k | } |
197 | 47.4k | } |
198 | 48.9k | row_ptr += row_inc; |
199 | 48.9k | } |
200 | 5.26k | } |
201 | | |
202 | | static void qtrle_decode_8bpp(QtrleContext *s, int row_ptr, int lines_to_change) |
203 | 7.19k | { |
204 | 7.19k | int rle_code; |
205 | 7.19k | int pixel_ptr; |
206 | 7.19k | int row_inc = s->frame->linesize[0]; |
207 | 7.19k | uint8_t pi1, pi2, pi3, pi4; /* 4 palette indexes */ |
208 | 7.19k | uint8_t *rgb = s->frame->data[0]; |
209 | 7.19k | int pixel_limit = s->frame->linesize[0] * s->avctx->height; |
210 | | |
211 | 685k | while (lines_to_change--) { |
212 | 684k | pixel_ptr = row_ptr + (4 * (bytestream2_get_byte(&s->g) - 1)); |
213 | 684k | CHECK_PIXEL_PTR(0); |
214 | | |
215 | 1.43M | while ((rle_code = (int8_t)bytestream2_get_byte(&s->g)) != -1) { |
216 | 753k | if (bytestream2_get_bytes_left(&s->g) < 1) |
217 | 2.19k | return; |
218 | 751k | if (rle_code == 0) { |
219 | | /* there's another skip code in the stream */ |
220 | 205k | pixel_ptr += (4 * (bytestream2_get_byte(&s->g) - 1)); |
221 | 205k | CHECK_PIXEL_PTR(0); /* make sure pixel_ptr is positive */ |
222 | 546k | } else if (rle_code < 0) { |
223 | | /* decode the run length code */ |
224 | 481k | 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 | 481k | pi1 = bytestream2_get_byte(&s->g); |
228 | 481k | pi2 = bytestream2_get_byte(&s->g); |
229 | 481k | pi3 = bytestream2_get_byte(&s->g); |
230 | 481k | pi4 = bytestream2_get_byte(&s->g); |
231 | | |
232 | 481k | CHECK_PIXEL_PTR(rle_code * 4); |
233 | | |
234 | 40.6M | while (rle_code--) { |
235 | 40.1M | rgb[pixel_ptr++] = pi1; |
236 | 40.1M | rgb[pixel_ptr++] = pi2; |
237 | 40.1M | rgb[pixel_ptr++] = pi3; |
238 | 40.1M | rgb[pixel_ptr++] = pi4; |
239 | 40.1M | } |
240 | 481k | } else { |
241 | | /* copy the same pixel directly to output 4 times */ |
242 | 64.4k | rle_code *= 4; |
243 | 64.4k | CHECK_PIXEL_PTR(rle_code); |
244 | | |
245 | 64.1k | bytestream2_get_buffer(&s->g, &rgb[pixel_ptr], rle_code); |
246 | 64.1k | pixel_ptr += rle_code; |
247 | 64.1k | } |
248 | 751k | } |
249 | 677k | row_ptr += row_inc; |
250 | 677k | } |
251 | 7.19k | } |
252 | | |
253 | | static void qtrle_decode_16bpp(QtrleContext *s, int row_ptr, int lines_to_change) |
254 | 5.08k | { |
255 | 5.08k | int rle_code; |
256 | 5.08k | int pixel_ptr; |
257 | 5.08k | int row_inc = s->frame->linesize[0]; |
258 | 5.08k | uint16_t rgb16; |
259 | 5.08k | uint8_t *rgb = s->frame->data[0]; |
260 | 5.08k | int pixel_limit = s->frame->linesize[0] * s->avctx->height; |
261 | | |
262 | 258k | while (lines_to_change--) { |
263 | 257k | pixel_ptr = row_ptr + (bytestream2_get_byte(&s->g) - 1) * 2; |
264 | 257k | CHECK_PIXEL_PTR(0); |
265 | | |
266 | 690k | while ((rle_code = (int8_t)bytestream2_get_byte(&s->g)) != -1) { |
267 | 436k | if (bytestream2_get_bytes_left(&s->g) < 1) |
268 | 1.75k | return; |
269 | 435k | if (rle_code == 0) { |
270 | | /* there's another skip code in the stream */ |
271 | 134k | pixel_ptr += (bytestream2_get_byte(&s->g) - 1) * 2; |
272 | 134k | CHECK_PIXEL_PTR(0); /* make sure pixel_ptr is positive */ |
273 | 300k | } else if (rle_code < 0) { |
274 | | /* decode the run length code */ |
275 | 275k | rle_code = -rle_code; |
276 | 275k | rgb16 = bytestream2_get_be16(&s->g); |
277 | | |
278 | 275k | CHECK_PIXEL_PTR(rle_code * 2); |
279 | | |
280 | 22.0M | while (rle_code--) { |
281 | 21.7M | *(uint16_t *)(&rgb[pixel_ptr]) = rgb16; |
282 | 21.7M | pixel_ptr += 2; |
283 | 21.7M | } |
284 | 275k | } else { |
285 | 24.8k | CHECK_PIXEL_PTR(rle_code * 2); |
286 | | |
287 | | /* copy pixels directly to output */ |
288 | 623k | while (rle_code--) { |
289 | 599k | rgb16 = bytestream2_get_be16(&s->g); |
290 | 599k | *(uint16_t *)(&rgb[pixel_ptr]) = rgb16; |
291 | 599k | pixel_ptr += 2; |
292 | 599k | } |
293 | 24.6k | } |
294 | 435k | } |
295 | 253k | row_ptr += row_inc; |
296 | 253k | } |
297 | 5.08k | } |
298 | | |
299 | | static void qtrle_decode_24bpp(QtrleContext *s, int row_ptr, int lines_to_change) |
300 | 8.17k | { |
301 | 8.17k | int rle_code, rle_code_half; |
302 | 8.17k | int pixel_ptr; |
303 | 8.17k | int row_inc = s->frame->linesize[0]; |
304 | 8.17k | uint8_t b; |
305 | 8.17k | uint16_t rg; |
306 | 8.17k | uint8_t *rgb = s->frame->data[0]; |
307 | 8.17k | int pixel_limit = s->frame->linesize[0] * s->avctx->height; |
308 | | |
309 | 638k | while (lines_to_change--) { |
310 | 638k | pixel_ptr = row_ptr + (bytestream2_get_byte(&s->g) - 1) * 3; |
311 | 638k | CHECK_PIXEL_PTR(0); |
312 | | |
313 | 1.38M | while ((rle_code = (int8_t)bytestream2_get_byte(&s->g)) != -1) { |
314 | 749k | if (bytestream2_get_bytes_left(&s->g) < 1) |
315 | 3.09k | return; |
316 | 746k | if (rle_code == 0) { |
317 | | /* there's another skip code in the stream */ |
318 | 163k | pixel_ptr += (bytestream2_get_byte(&s->g) - 1) * 3; |
319 | 163k | CHECK_PIXEL_PTR(0); /* make sure pixel_ptr is positive */ |
320 | 583k | } else if (rle_code < 0) { |
321 | | /* decode the run length code */ |
322 | 524k | rle_code = -rle_code; |
323 | 524k | rg = bytestream2_get_ne16(&s->g); |
324 | 524k | b = bytestream2_get_byte(&s->g); |
325 | | |
326 | 524k | CHECK_PIXEL_PTR(rle_code * 3); |
327 | | |
328 | 43.8M | while (rle_code--) { |
329 | 43.3M | AV_WN16(rgb + pixel_ptr, rg); |
330 | 43.3M | rgb[pixel_ptr + 2] = b; |
331 | 43.3M | pixel_ptr += 3; |
332 | 43.3M | } |
333 | 524k | } else { |
334 | 58.3k | CHECK_PIXEL_PTR(rle_code * 3); |
335 | | |
336 | 58.1k | rle_code_half = rle_code / 2; |
337 | | |
338 | 867k | while (rle_code_half--) { /* copy 2 raw rgb value at the same time */ |
339 | 809k | AV_WN32(rgb + pixel_ptr, bytestream2_get_ne32(&s->g)); /* rgbr */ |
340 | 809k | AV_WN16(rgb + pixel_ptr + 4, bytestream2_get_ne16(&s->g)); /* rgbr */ |
341 | 809k | pixel_ptr += 6; |
342 | 809k | } |
343 | | |
344 | 58.1k | if (rle_code % 2 != 0){ /* not even raw value */ |
345 | 30.8k | AV_WN16(rgb + pixel_ptr, bytestream2_get_ne16(&s->g)); |
346 | 30.8k | rgb[pixel_ptr + 2] = bytestream2_get_byte(&s->g); |
347 | 30.8k | pixel_ptr += 3; |
348 | 30.8k | } |
349 | 58.1k | } |
350 | 746k | } |
351 | 630k | row_ptr += row_inc; |
352 | 630k | } |
353 | 8.17k | } |
354 | | |
355 | | static void qtrle_decode_32bpp(QtrleContext *s, int row_ptr, int lines_to_change) |
356 | 8.26k | { |
357 | 8.26k | int rle_code, rle_code_half; |
358 | 8.26k | int pixel_ptr; |
359 | 8.26k | int row_inc = s->frame->linesize[0]; |
360 | 8.26k | unsigned int argb; |
361 | 8.26k | uint8_t *rgb = s->frame->data[0]; |
362 | 8.26k | int pixel_limit = s->frame->linesize[0] * s->avctx->height; |
363 | | |
364 | 19.4k | while (lines_to_change--) { |
365 | 18.9k | pixel_ptr = row_ptr + (bytestream2_get_byte(&s->g) - 1) * 4; |
366 | 18.9k | CHECK_PIXEL_PTR(0); |
367 | | |
368 | 207k | while ((rle_code = (int8_t)bytestream2_get_byte(&s->g)) != -1) { |
369 | 196k | if (bytestream2_get_bytes_left(&s->g) < 1) |
370 | 2.88k | return; |
371 | 193k | if (rle_code == 0) { |
372 | | /* there's another skip code in the stream */ |
373 | 149k | pixel_ptr += (bytestream2_get_byte(&s->g) - 1) * 4; |
374 | 149k | CHECK_PIXEL_PTR(0); /* make sure pixel_ptr is positive */ |
375 | 148k | } else if (rle_code < 0) { |
376 | | /* decode the run length code */ |
377 | 37.0k | rle_code = -rle_code; |
378 | 37.0k | argb = bytestream2_get_ne32(&s->g); |
379 | | |
380 | 37.0k | CHECK_PIXEL_PTR(rle_code * 4); |
381 | | |
382 | 3.21M | while (rle_code--) { |
383 | 3.17M | AV_WN32A(rgb + pixel_ptr, argb); |
384 | 3.17M | pixel_ptr += 4; |
385 | 3.17M | } |
386 | 36.4k | } else { |
387 | 6.73k | CHECK_PIXEL_PTR(rle_code * 4); |
388 | | |
389 | | /* copy pixels directly to output */ |
390 | 6.44k | rle_code_half = rle_code / 2; |
391 | 91.5k | while (rle_code_half--) { /* copy 2 argb raw value at the same time */ |
392 | 85.0k | AV_WN64(rgb + pixel_ptr, bytestream2_get_ne64(&s->g)); |
393 | 85.0k | pixel_ptr += 8; |
394 | 85.0k | } |
395 | | |
396 | 6.44k | if (rle_code % 2 != 0){ /* not even raw value */ |
397 | 3.55k | AV_WN32A(rgb + pixel_ptr, bytestream2_get_ne32(&s->g)); |
398 | 3.55k | pixel_ptr += 4; |
399 | 3.55k | } |
400 | 6.44k | } |
401 | 193k | } |
402 | 11.2k | row_ptr += row_inc; |
403 | 11.2k | } |
404 | 8.26k | } |
405 | | |
406 | | static av_cold int qtrle_decode_init(AVCodecContext *avctx) |
407 | 1.57k | { |
408 | 1.57k | QtrleContext *s = avctx->priv_data; |
409 | | |
410 | 1.57k | s->avctx = avctx; |
411 | 1.57k | switch (avctx->bits_per_coded_sample) { |
412 | 174 | case 1: |
413 | 249 | case 2: |
414 | 369 | case 4: |
415 | 547 | case 8: |
416 | 579 | case 33: |
417 | 610 | case 34: |
418 | 639 | case 36: |
419 | 731 | case 40: |
420 | 731 | avctx->pix_fmt = AV_PIX_FMT_PAL8; |
421 | 731 | break; |
422 | | |
423 | 233 | case 16: |
424 | 233 | avctx->pix_fmt = AV_PIX_FMT_RGB555; |
425 | 233 | break; |
426 | | |
427 | 235 | case 24: |
428 | 235 | avctx->pix_fmt = AV_PIX_FMT_RGB24; |
429 | 235 | break; |
430 | | |
431 | 245 | case 32: |
432 | 245 | avctx->pix_fmt = AV_PIX_FMT_ARGB; |
433 | 245 | break; |
434 | | |
435 | 134 | default: |
436 | 134 | av_log (avctx, AV_LOG_ERROR, "Unsupported colorspace: %d bits/sample?\n", |
437 | 134 | avctx->bits_per_coded_sample); |
438 | 134 | return AVERROR_INVALIDDATA; |
439 | 1.57k | } |
440 | | |
441 | 1.44k | s->frame = av_frame_alloc(); |
442 | 1.44k | if (!s->frame) |
443 | 0 | return AVERROR(ENOMEM); |
444 | | |
445 | 1.44k | return 0; |
446 | 1.44k | } |
447 | | |
448 | | static int qtrle_decode_frame(AVCodecContext *avctx, AVFrame *rframe, |
449 | | int *got_frame, AVPacket *avpkt) |
450 | 157k | { |
451 | 157k | QtrleContext *s = avctx->priv_data; |
452 | 157k | int header, start_line; |
453 | 157k | int height, row_ptr; |
454 | 157k | int has_palette = 0; |
455 | 157k | int duplicate = 0; |
456 | 157k | int ret, size; |
457 | | |
458 | 157k | bytestream2_init(&s->g, avpkt->data, avpkt->size); |
459 | | |
460 | | /* check if this frame is even supposed to change */ |
461 | 157k | if (avpkt->size < 8) { |
462 | 105k | duplicate = 1; |
463 | 105k | goto done; |
464 | 105k | } |
465 | | |
466 | | /* start after the chunk size */ |
467 | 52.0k | size = bytestream2_get_be32(&s->g) & 0x3FFFFFFF; |
468 | 52.0k | if (size - avpkt->size > size * (int64_t)avctx->discard_damaged_percentage / 100) |
469 | 8.90k | return AVERROR_INVALIDDATA; |
470 | | |
471 | | |
472 | | /* fetch the header */ |
473 | 43.1k | header = bytestream2_get_be16(&s->g); |
474 | | |
475 | | /* if a header is present, fetch additional decoding parameters */ |
476 | 43.1k | if (header & 0x0008) { |
477 | 7.68k | if (avpkt->size < 14) { |
478 | 1.05k | duplicate = 1; |
479 | 1.05k | goto done; |
480 | 1.05k | } |
481 | 6.62k | start_line = bytestream2_get_be16(&s->g); |
482 | 6.62k | bytestream2_skip(&s->g, 2); |
483 | 6.62k | height = bytestream2_get_be16(&s->g); |
484 | 6.62k | bytestream2_skip(&s->g, 2); |
485 | 6.62k | if (height > s->avctx->height - start_line) { |
486 | 2.28k | duplicate = 1; |
487 | 2.28k | goto done; |
488 | 2.28k | } |
489 | 35.5k | } else { |
490 | 35.5k | start_line = 0; |
491 | 35.5k | height = s->avctx->height; |
492 | 35.5k | } |
493 | 39.8k | if ((ret = ff_reget_buffer(avctx, s->frame, 0)) < 0) |
494 | 1.12k | return ret; |
495 | | |
496 | 38.7k | row_ptr = s->frame->linesize[0] * start_line; |
497 | | |
498 | 38.7k | switch (avctx->bits_per_coded_sample) { |
499 | 3.01k | case 1: |
500 | 4.74k | case 33: |
501 | 4.74k | qtrle_decode_1bpp(s, row_ptr, height); |
502 | 4.74k | has_palette = 1; |
503 | 4.74k | break; |
504 | | |
505 | 935 | case 2: |
506 | 2.52k | case 34: |
507 | 2.52k | qtrle_decode_2n4bpp(s, row_ptr, height, 2); |
508 | 2.52k | has_palette = 1; |
509 | 2.52k | break; |
510 | | |
511 | 2.40k | case 4: |
512 | 2.74k | case 36: |
513 | 2.74k | qtrle_decode_2n4bpp(s, row_ptr, height, 4); |
514 | 2.74k | has_palette = 1; |
515 | 2.74k | break; |
516 | | |
517 | 1.03k | case 8: |
518 | 7.19k | case 40: |
519 | 7.19k | qtrle_decode_8bpp(s, row_ptr, height); |
520 | 7.19k | has_palette = 1; |
521 | 7.19k | break; |
522 | | |
523 | 5.08k | case 16: |
524 | 5.08k | qtrle_decode_16bpp(s, row_ptr, height); |
525 | 5.08k | break; |
526 | | |
527 | 8.17k | case 24: |
528 | 8.17k | qtrle_decode_24bpp(s, row_ptr, height); |
529 | 8.17k | break; |
530 | | |
531 | 8.26k | case 32: |
532 | 8.26k | qtrle_decode_32bpp(s, row_ptr, height); |
533 | 8.26k | break; |
534 | | |
535 | 0 | default: |
536 | 0 | av_log (s->avctx, AV_LOG_ERROR, "Unsupported colorspace: %d bits/sample?\n", |
537 | 0 | avctx->bits_per_coded_sample); |
538 | 0 | break; |
539 | 38.7k | } |
540 | | |
541 | 38.7k | if(has_palette) { |
542 | 17.2k | ff_copy_palette(s->pal, avpkt, avctx); |
543 | | /* make the palette available on the way out */ |
544 | 17.2k | memcpy(s->frame->data[1], s->pal, AVPALETTE_SIZE); |
545 | 17.2k | } |
546 | | |
547 | 147k | done: |
548 | 147k | if (!s->frame->data[0]) |
549 | 24.0k | return AVERROR_INVALIDDATA; |
550 | 123k | if (duplicate) { |
551 | | // ff_reget_buffer() isn't needed when frames don't change, so just update |
552 | | // frame props. |
553 | 84.6k | ret = ff_decode_frame_props(avctx, s->frame); |
554 | 84.6k | if (ret < 0) |
555 | 0 | return ret; |
556 | 84.6k | } |
557 | | |
558 | 123k | if ((ret = av_frame_ref(rframe, s->frame)) < 0) |
559 | 0 | return ret; |
560 | 123k | *got_frame = 1; |
561 | | |
562 | | /* always report that the buffer was completely consumed */ |
563 | 123k | return avpkt->size; |
564 | 123k | } |
565 | | |
566 | | static av_cold void qtrle_decode_flush(AVCodecContext *avctx) |
567 | 28.5k | { |
568 | 28.5k | QtrleContext *s = avctx->priv_data; |
569 | | |
570 | 28.5k | av_frame_unref(s->frame); |
571 | 28.5k | } |
572 | | |
573 | | static av_cold int qtrle_decode_end(AVCodecContext *avctx) |
574 | 1.44k | { |
575 | 1.44k | QtrleContext *s = avctx->priv_data; |
576 | | |
577 | 1.44k | av_frame_free(&s->frame); |
578 | | |
579 | 1.44k | return 0; |
580 | 1.44k | } |
581 | | |
582 | | const FFCodec ff_qtrle_decoder = { |
583 | | .p.name = "qtrle", |
584 | | CODEC_LONG_NAME("QuickTime Animation (RLE) video"), |
585 | | .p.type = AVMEDIA_TYPE_VIDEO, |
586 | | .p.id = AV_CODEC_ID_QTRLE, |
587 | | .priv_data_size = sizeof(QtrleContext), |
588 | | .init = qtrle_decode_init, |
589 | | .close = qtrle_decode_end, |
590 | | FF_CODEC_DECODE_CB(qtrle_decode_frame), |
591 | | .flush = qtrle_decode_flush, |
592 | | .p.capabilities = AV_CODEC_CAP_DR1, |
593 | | }; |