/src/ffmpeg/libavcodec/indeo3.c
Line | Count | Source |
1 | | /* |
2 | | * Indeo Video v3 compatible decoder |
3 | | * Copyright (c) 2009 - 2011 Maxim Poliakovski |
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 | | * This is a decoder for Intel Indeo Video v3. |
25 | | * It is based on vector quantization, run-length coding and motion compensation. |
26 | | * Known container formats: .avi and .mov |
27 | | * Known FOURCCs: 'IV31', 'IV32' |
28 | | * |
29 | | * @see http://wiki.multimedia.cx/index.php?title=Indeo_3 |
30 | | */ |
31 | | |
32 | | #include "libavutil/attributes.h" |
33 | | #include "libavutil/imgutils.h" |
34 | | #include "libavutil/intreadwrite.h" |
35 | | #include "libavutil/mem.h" |
36 | | #include "libavutil/thread.h" |
37 | | #include "avcodec.h" |
38 | | #include "codec_internal.h" |
39 | | #include "decode.h" |
40 | | #include "copy_block.h" |
41 | | #include "bytestream.h" |
42 | | #include "get_bits.h" |
43 | | #include "hpeldsp.h" |
44 | | |
45 | | #include "indeo3data.h" |
46 | | |
47 | | /* RLE opcodes. */ |
48 | | enum { |
49 | | RLE_ESC_F9 = 249, ///< same as RLE_ESC_FA + do the same with next block |
50 | | RLE_ESC_FA = 250, ///< INTRA: skip block, INTER: copy data from reference |
51 | | RLE_ESC_FB = 251, ///< apply null delta to N blocks / skip N blocks |
52 | | RLE_ESC_FC = 252, ///< same as RLE_ESC_FD + do the same with next block |
53 | | RLE_ESC_FD = 253, ///< apply null delta to all remaining lines of this block |
54 | | RLE_ESC_FE = 254, ///< apply null delta to all lines up to the 3rd line |
55 | | RLE_ESC_FF = 255 ///< apply null delta to all lines up to the 2nd line |
56 | | }; |
57 | | |
58 | | |
59 | | /* Some constants for parsing frame bitstream flags. */ |
60 | 16.2k | #define BS_8BIT_PEL (1 << 1) ///< 8-bit pixel bitdepth indicator |
61 | 15.3k | #define BS_KEYFRAME (1 << 2) ///< intra frame indicator |
62 | 15.7k | #define BS_MV_Y_HALF (1 << 4) ///< vertical mv halfpel resolution indicator |
63 | 31.8k | #define BS_MV_X_HALF (1 << 5) ///< horizontal mv halfpel resolution indicator |
64 | 31.0k | #define BS_NONREF (1 << 8) ///< nonref (discardable) frame indicator |
65 | 15.1k | #define BS_BUFFER 9 ///< indicates which of two frame buffers should be used |
66 | | |
67 | | |
68 | | typedef struct Plane { |
69 | | uint8_t *buffers[2]; |
70 | | uint8_t *pixels[2]; ///< pointer to the actual pixel data of the buffers above |
71 | | uint32_t width; |
72 | | uint32_t height; |
73 | | ptrdiff_t pitch; |
74 | | } Plane; |
75 | | |
76 | 19.3k | #define CELL_STACK_MAX 20 |
77 | | |
78 | | typedef struct Cell { |
79 | | int16_t xpos; ///< cell coordinates in 4x4 blocks |
80 | | int16_t ypos; |
81 | | int16_t width; ///< cell width in 4x4 blocks |
82 | | int16_t height; ///< cell height in 4x4 blocks |
83 | | uint8_t tree; ///< tree id: 0- MC tree, 1 - VQ tree |
84 | | const int8_t *mv_ptr; ///< ptr to the motion vector if any |
85 | | } Cell; |
86 | | |
87 | | typedef struct Indeo3DecodeContext { |
88 | | AVCodecContext *avctx; |
89 | | HpelDSPContext hdsp; |
90 | | |
91 | | GetBitContext gb; |
92 | | int need_resync; |
93 | | int skip_bits; |
94 | | const uint8_t *next_cell_data; |
95 | | const uint8_t *last_byte; |
96 | | const int8_t *mc_vectors; |
97 | | unsigned num_vectors; ///< number of motion vectors in mc_vectors |
98 | | |
99 | | int16_t width, height; |
100 | | uint32_t frame_num; ///< current frame number (zero-based) |
101 | | int data_size; ///< size of the frame data in bytes |
102 | | uint16_t frame_flags; ///< frame properties |
103 | | uint8_t cb_offset; ///< needed for selecting VQ tables |
104 | | uint8_t buf_sel; ///< active frame buffer: 0 - primary, 1 -secondary |
105 | | const uint8_t *y_data_ptr; |
106 | | const uint8_t *v_data_ptr; |
107 | | const uint8_t *u_data_ptr; |
108 | | int32_t y_data_size; |
109 | | int32_t v_data_size; |
110 | | int32_t u_data_size; |
111 | | const uint8_t *alt_quant; ///< secondary VQ table set for the modes 1 and 4 |
112 | | Plane planes[3]; |
113 | | } Indeo3DecodeContext; |
114 | | |
115 | | |
116 | | static uint8_t requant_tab[8][128]; |
117 | | |
118 | | /* |
119 | | * Build the static requantization table. |
120 | | * This table is used to remap pixel values according to a specific |
121 | | * quant index and thus avoid overflows while adding deltas. |
122 | | */ |
123 | | static av_cold void build_requant_tab(void) |
124 | 1 | { |
125 | 1 | static const int8_t offsets[8] = { 1, 1, 2, -3, -3, 3, 4, 4 }; |
126 | 1 | static const int8_t deltas [8] = { 0, 1, 0, 4, 4, 1, 0, 1 }; |
127 | | |
128 | 1 | int i, j, step; |
129 | | |
130 | 9 | for (i = 0; i < 8; i++) { |
131 | 8 | step = i + 2; |
132 | 1.03k | for (j = 0; j < 128; j++) |
133 | 1.02k | requant_tab[i][j] = (j + offsets[i]) / step * step + deltas[i]; |
134 | 8 | } |
135 | | |
136 | | /* some last elements calculated above will have values >= 128 */ |
137 | | /* pixel values shall never exceed 127 so set them to non-overflowing values */ |
138 | | /* according with the quantization step of the respective section */ |
139 | 1 | requant_tab[0][127] = 126; |
140 | 1 | requant_tab[1][119] = 118; |
141 | 1 | requant_tab[1][120] = 118; |
142 | 1 | requant_tab[2][126] = 124; |
143 | 1 | requant_tab[2][127] = 124; |
144 | 1 | requant_tab[6][124] = 120; |
145 | 1 | requant_tab[6][125] = 120; |
146 | 1 | requant_tab[6][126] = 120; |
147 | 1 | requant_tab[6][127] = 120; |
148 | | |
149 | | /* Patch for compatibility with the Intel's binary decoders */ |
150 | 1 | requant_tab[1][7] = 10; |
151 | 1 | requant_tab[4][8] = 10; |
152 | 1 | } |
153 | | |
154 | | |
155 | | static av_cold void free_frame_buffers(Indeo3DecodeContext *ctx) |
156 | 7.32k | { |
157 | 7.32k | int p; |
158 | | |
159 | 7.32k | ctx->width = ctx->height = 0; |
160 | | |
161 | 29.2k | for (p = 0; p < 3; p++) { |
162 | 21.9k | av_freep(&ctx->planes[p].buffers[0]); |
163 | 21.9k | av_freep(&ctx->planes[p].buffers[1]); |
164 | 21.9k | ctx->planes[p].pixels[0] = ctx->planes[p].pixels[1] = 0; |
165 | 21.9k | } |
166 | 7.32k | } |
167 | | |
168 | | |
169 | | static av_cold int allocate_frame_buffers(Indeo3DecodeContext *ctx, |
170 | | AVCodecContext *avctx, int luma_width, int luma_height) |
171 | 7.32k | { |
172 | 7.32k | int p, chroma_width, chroma_height; |
173 | 7.32k | int luma_size, chroma_size; |
174 | 7.32k | ptrdiff_t luma_pitch, chroma_pitch; |
175 | | |
176 | 7.32k | luma_width = FFALIGN(luma_width , 2); |
177 | 7.32k | luma_height = FFALIGN(luma_height, 2); |
178 | | |
179 | 7.32k | if (luma_width < 16 || luma_width > 640 || |
180 | 7.16k | luma_height < 16 || luma_height > 480 || |
181 | 7.15k | luma_width & 1 || luma_height & 1) { |
182 | 171 | av_log(avctx, AV_LOG_ERROR, "Invalid picture dimensions: %d x %d!\n", |
183 | 171 | luma_width, luma_height); |
184 | 171 | return AVERROR_INVALIDDATA; |
185 | 171 | } |
186 | | |
187 | 7.15k | ctx->width = luma_width ; |
188 | 7.15k | ctx->height = luma_height; |
189 | | |
190 | 7.15k | chroma_width = FFALIGN(luma_width >> 2, 4); |
191 | 7.15k | chroma_height = FFALIGN(luma_height >> 2, 4); |
192 | | |
193 | 7.15k | luma_pitch = FFALIGN(luma_width, 16); |
194 | 7.15k | chroma_pitch = FFALIGN(chroma_width, 16); |
195 | | |
196 | | /* Calculate size of the luminance plane. */ |
197 | | /* Add one line more for INTRA prediction. */ |
198 | 7.15k | luma_size = luma_pitch * (luma_height + 1); |
199 | | |
200 | | /* Calculate size of a chrominance planes. */ |
201 | | /* Add one line more for INTRA prediction. */ |
202 | 7.15k | chroma_size = chroma_pitch * (chroma_height + 1); |
203 | | |
204 | | /* allocate frame buffers */ |
205 | 28.6k | for (p = 0; p < 3; p++) { |
206 | 21.4k | ctx->planes[p].pitch = !p ? luma_pitch : chroma_pitch; |
207 | 21.4k | ctx->planes[p].width = !p ? luma_width : chroma_width; |
208 | 21.4k | ctx->planes[p].height = !p ? luma_height : chroma_height; |
209 | | |
210 | 21.4k | ctx->planes[p].buffers[0] = av_malloc(!p ? luma_size : chroma_size); |
211 | 21.4k | ctx->planes[p].buffers[1] = av_malloc(!p ? luma_size : chroma_size); |
212 | | |
213 | 21.4k | if (!ctx->planes[p].buffers[0] || !ctx->planes[p].buffers[1]) |
214 | 0 | return AVERROR(ENOMEM); |
215 | | |
216 | | /* fill the INTRA prediction lines with the middle pixel value = 64 */ |
217 | 21.4k | memset(ctx->planes[p].buffers[0], 0x40, ctx->planes[p].pitch); |
218 | 21.4k | memset(ctx->planes[p].buffers[1], 0x40, ctx->planes[p].pitch); |
219 | | |
220 | | /* set buffer pointers = buf_ptr + pitch and thus skip the INTRA prediction line */ |
221 | 21.4k | ctx->planes[p].pixels[0] = ctx->planes[p].buffers[0] + ctx->planes[p].pitch; |
222 | 21.4k | ctx->planes[p].pixels[1] = ctx->planes[p].buffers[1] + ctx->planes[p].pitch; |
223 | 21.4k | memset(ctx->planes[p].pixels[0], 0, ctx->planes[p].pitch * ctx->planes[p].height); |
224 | 21.4k | memset(ctx->planes[p].pixels[1], 0, ctx->planes[p].pitch * ctx->planes[p].height); |
225 | 21.4k | } |
226 | | |
227 | 7.15k | return 0; |
228 | 7.15k | } |
229 | | |
230 | | /** |
231 | | * Copy pixels of the cell(x + mv_x, y + mv_y) from the previous frame into |
232 | | * the cell(x, y) in the current frame. |
233 | | * |
234 | | * @param ctx pointer to the decoder context |
235 | | * @param plane pointer to the plane descriptor |
236 | | * @param cell pointer to the cell descriptor |
237 | | */ |
238 | | static int copy_cell(Indeo3DecodeContext *ctx, Plane *plane, Cell *cell) |
239 | 21.9k | { |
240 | 21.9k | int h, w, mv_x, mv_y, offset, offset_dst; |
241 | 21.9k | uint8_t *src, *dst; |
242 | | |
243 | | /* setup output and reference pointers */ |
244 | 21.9k | offset_dst = (cell->ypos << 2) * plane->pitch + (cell->xpos << 2); |
245 | 21.9k | dst = plane->pixels[ctx->buf_sel] + offset_dst; |
246 | 21.9k | if(cell->mv_ptr){ |
247 | 21.9k | mv_y = cell->mv_ptr[0]; |
248 | 21.9k | mv_x = cell->mv_ptr[1]; |
249 | 21.9k | }else |
250 | 0 | mv_x= mv_y= 0; |
251 | | |
252 | | /* -1 because there is an extra line on top for prediction */ |
253 | 21.9k | if ((cell->ypos << 2) + mv_y < -1 || (cell->xpos << 2) + mv_x < 0 || |
254 | 21.4k | ((cell->ypos + cell->height) << 2) + mv_y > plane->height || |
255 | 21.2k | ((cell->xpos + cell->width) << 2) + mv_x > plane->width) { |
256 | 1.01k | av_log(ctx->avctx, AV_LOG_ERROR, |
257 | 1.01k | "Motion vectors point out of the frame.\n"); |
258 | 1.01k | return AVERROR_INVALIDDATA; |
259 | 1.01k | } |
260 | | |
261 | 20.9k | offset = offset_dst + mv_y * plane->pitch + mv_x; |
262 | 20.9k | src = plane->pixels[ctx->buf_sel ^ 1] + offset; |
263 | | |
264 | 20.9k | h = cell->height << 2; |
265 | | |
266 | 46.2k | for (w = cell->width; w > 0;) { |
267 | | /* copy using 16xH blocks */ |
268 | 25.3k | if (!((cell->xpos << 2) & 15) && w >= 4) { |
269 | 187k | for (; w >= 4; src += 16, dst += 16, w -= 4) |
270 | 170k | ctx->hdsp.put_pixels_tab[0][0](dst, src, plane->pitch, h); |
271 | 17.3k | } |
272 | | |
273 | | /* copy using 8xH blocks */ |
274 | 25.3k | if (!((cell->xpos << 2) & 7) && w >= 2) { |
275 | 14.8k | ctx->hdsp.put_pixels_tab[1][0](dst, src, plane->pitch, h); |
276 | 14.8k | w -= 2; |
277 | 14.8k | src += 8; |
278 | 14.8k | dst += 8; |
279 | 14.8k | } else if (w >= 1) { |
280 | 2.76k | ctx->hdsp.put_pixels_tab[2][0](dst, src, plane->pitch, h); |
281 | 2.76k | w--; |
282 | 2.76k | src += 4; |
283 | 2.76k | dst += 4; |
284 | 2.76k | } |
285 | 25.3k | } |
286 | | |
287 | 20.9k | return 0; |
288 | 21.9k | } |
289 | | |
290 | | |
291 | | /* Average 4/8 pixels at once without rounding using SWAR */ |
292 | | #define AVG_32(dst, src, ref) \ |
293 | 34.8k | AV_WN32A(dst, ((AV_RN32(src) + AV_RN32(ref)) >> 1) & 0x7F7F7F7FUL) |
294 | | |
295 | | #define AVG_64(dst, src, ref) \ |
296 | 17.8k | AV_WN64A(dst, ((AV_RN64(src) + AV_RN64(ref)) >> 1) & 0x7F7F7F7F7F7F7F7FULL) |
297 | | |
298 | | |
299 | | /* |
300 | | * Replicate each even pixel as follows: |
301 | | * ABCDEFGH -> AACCEEGG |
302 | | */ |
303 | 3.56k | static inline uint64_t replicate64(uint64_t a) { |
304 | | #if HAVE_BIGENDIAN |
305 | | a &= 0xFF00FF00FF00FF00ULL; |
306 | | a |= a >> 8; |
307 | | #else |
308 | 3.56k | a &= 0x00FF00FF00FF00FFULL; |
309 | 3.56k | a |= a << 8; |
310 | 3.56k | #endif |
311 | 3.56k | return a; |
312 | 3.56k | } |
313 | | |
314 | 5.40k | static inline uint32_t replicate32(uint32_t a) { |
315 | | #if HAVE_BIGENDIAN |
316 | | a &= 0xFF00FF00UL; |
317 | | a |= a >> 8; |
318 | | #else |
319 | 5.40k | a &= 0x00FF00FFUL; |
320 | 5.40k | a |= a << 8; |
321 | 5.40k | #endif |
322 | 5.40k | return a; |
323 | 5.40k | } |
324 | | |
325 | | |
326 | | /* Fill n lines with 64-bit pixel value pix */ |
327 | | static inline void fill_64(uint8_t *dst, const uint64_t pix, int32_t n, |
328 | | ptrdiff_t row_offset) |
329 | 8.10k | { |
330 | 64.6k | for (; n > 0; dst += row_offset, n--) |
331 | 56.5k | AV_WN64A(dst, pix); |
332 | 8.10k | } |
333 | | |
334 | | |
335 | | /* Error codes for cell decoding. */ |
336 | | enum { |
337 | | IV3_NOERR = 0, |
338 | | IV3_BAD_RLE = 1, |
339 | | IV3_BAD_DATA = 2, |
340 | | IV3_BAD_COUNTER = 3, |
341 | | IV3_UNSUPPORTED = 4, |
342 | | IV3_OUT_OF_DATA = 5 |
343 | | }; |
344 | | |
345 | | |
346 | 234k | #define BUFFER_PRECHECK \ |
347 | 234k | if (*data_ptr >= last_ptr) \ |
348 | 234k | return IV3_OUT_OF_DATA; \ |
349 | | |
350 | | #define RLE_BLOCK_COPY \ |
351 | 20.6k | if (cell->mv_ptr || !skip_flag) \ |
352 | 20.6k | copy_block4(dst, ref, row_offset, row_offset, 4 << v_zoom) |
353 | | |
354 | | #define RLE_BLOCK_COPY_8 \ |
355 | 4.58k | pix64 = AV_RN64(ref);\ |
356 | 4.58k | if (is_first_row) {/* special prediction case: top line of a cell */\ |
357 | 1.92k | pix64 = replicate64(pix64);\ |
358 | 1.92k | fill_64(dst + row_offset, pix64, 7, row_offset);\ |
359 | 1.92k | AVG_64(dst, ref, dst + row_offset);\ |
360 | 1.92k | } else \ |
361 | 4.58k | fill_64(dst, pix64, 8, row_offset) |
362 | | |
363 | | #define RLE_LINES_COPY \ |
364 | 4.98k | copy_block4(dst, ref, row_offset, row_offset, num_lines << v_zoom) |
365 | | |
366 | | #define RLE_LINES_COPY_M10 \ |
367 | 3.51k | pix64 = AV_RN64(ref);\ |
368 | 3.51k | if (is_top_of_cell) {\ |
369 | 1.64k | pix64 = replicate64(pix64);\ |
370 | 1.64k | fill_64(dst + row_offset, pix64, (num_lines << 1) - 1, row_offset);\ |
371 | 1.64k | AVG_64(dst, ref, dst + row_offset);\ |
372 | 1.64k | } else \ |
373 | 3.51k | fill_64(dst, pix64, num_lines << 1, row_offset) |
374 | | |
375 | | #define APPLY_DELTA_4 \ |
376 | 87.9k | AV_WN16A(dst + line_offset ,\ |
377 | 87.9k | (AV_RN16(ref ) + delta_tab->deltas[dyad1]) & 0x7F7F);\ |
378 | 87.9k | AV_WN16A(dst + line_offset + 2,\ |
379 | 87.9k | (AV_RN16(ref + 2) + delta_tab->deltas[dyad2]) & 0x7F7F);\ |
380 | 87.9k | if (mode >= 3) {\ |
381 | 36.7k | if (is_top_of_cell && !cell->ypos) {\ |
382 | 1.87k | AV_COPY32U(dst, dst + row_offset);\ |
383 | 34.8k | } else {\ |
384 | 34.8k | AVG_32(dst, ref, dst + row_offset);\ |
385 | 34.8k | }\ |
386 | 36.7k | } |
387 | | |
388 | | #define APPLY_DELTA_8 \ |
389 | | /* apply two 32-bit VQ deltas to next even line */\ |
390 | 14.2k | if (is_top_of_cell) { \ |
391 | 2.70k | AV_WN32A(dst + row_offset , \ |
392 | 2.70k | (replicate32(AV_RN32(ref )) + delta_tab->deltas_m10[dyad1]) & 0x7F7F7F7F);\ |
393 | 2.70k | AV_WN32A(dst + row_offset + 4, \ |
394 | 2.70k | (replicate32(AV_RN32(ref + 4)) + delta_tab->deltas_m10[dyad2]) & 0x7F7F7F7F);\ |
395 | 11.5k | } else { \ |
396 | 11.5k | AV_WN32A(dst + row_offset , \ |
397 | 11.5k | (AV_RN32(ref ) + delta_tab->deltas_m10[dyad1]) & 0x7F7F7F7F);\ |
398 | 11.5k | AV_WN32A(dst + row_offset + 4, \ |
399 | 11.5k | (AV_RN32(ref + 4) + delta_tab->deltas_m10[dyad2]) & 0x7F7F7F7F);\ |
400 | 11.5k | } \ |
401 | 14.2k | /* odd lines are not coded but rather interpolated/replicated */\ |
402 | 14.2k | /* first line of the cell on the top of image? - replicate */\ |
403 | 14.2k | /* otherwise - interpolate */\ |
404 | 14.2k | if (is_top_of_cell && !cell->ypos) {\ |
405 | 2.23k | AV_COPY64U(dst, dst + row_offset);\ |
406 | 2.23k | } else \ |
407 | 14.2k | AVG_64(dst, ref, dst + row_offset); |
408 | | |
409 | | |
410 | | #define APPLY_DELTA_1011_INTER \ |
411 | 16.5k | if (mode == 10) { \ |
412 | 3.10k | AV_WN32A(dst , \ |
413 | 3.10k | (AV_RN32(dst ) + delta_tab->deltas_m10[dyad1]) & 0x7F7F7F7F);\ |
414 | 3.10k | AV_WN32A(dst + 4 , \ |
415 | 3.10k | (AV_RN32(dst + 4 ) + delta_tab->deltas_m10[dyad2]) & 0x7F7F7F7F);\ |
416 | 3.10k | AV_WN32A(dst + row_offset , \ |
417 | 3.10k | (AV_RN32(dst + row_offset ) + delta_tab->deltas_m10[dyad1]) & 0x7F7F7F7F);\ |
418 | 3.10k | AV_WN32A(dst + row_offset + 4, \ |
419 | 3.10k | (AV_RN32(dst + row_offset + 4) + delta_tab->deltas_m10[dyad2]) & 0x7F7F7F7F);\ |
420 | 13.4k | } else { \ |
421 | 13.4k | AV_WN16A(dst , \ |
422 | 13.4k | (AV_RN16(dst ) + delta_tab->deltas[dyad1]) & 0x7F7F);\ |
423 | 13.4k | AV_WN16A(dst + 2 , \ |
424 | 13.4k | (AV_RN16(dst + 2 ) + delta_tab->deltas[dyad2]) & 0x7F7F);\ |
425 | 13.4k | AV_WN16A(dst + row_offset , \ |
426 | 13.4k | (AV_RN16(dst + row_offset ) + delta_tab->deltas[dyad1]) & 0x7F7F);\ |
427 | 13.4k | AV_WN16A(dst + row_offset + 2, \ |
428 | 13.4k | (AV_RN16(dst + row_offset + 2) + delta_tab->deltas[dyad2]) & 0x7F7F);\ |
429 | 13.4k | } |
430 | | |
431 | | |
432 | | static int decode_cell_data(Indeo3DecodeContext *ctx, Cell *cell, |
433 | | uint8_t *block, const uint8_t *ref_block, |
434 | | ptrdiff_t row_offset, int h_zoom, int v_zoom, int mode, |
435 | | const vqEntry *delta[2], int swap_quads[2], |
436 | | const uint8_t **data_ptr, const uint8_t *last_ptr) |
437 | 7.82k | { |
438 | 7.82k | int x, y, line, num_lines; |
439 | 7.82k | int rle_blocks = 0; |
440 | 7.82k | const vqEntry *delta_tab; |
441 | 7.82k | unsigned int dyad1, dyad2; |
442 | 7.82k | uint64_t pix64; |
443 | 7.82k | int skip_flag = 0, is_top_of_cell, is_first_row = 1; |
444 | | |
445 | 7.82k | const ptrdiff_t blk_row_offset = (row_offset << (2 + v_zoom)) - (cell->width << 2); |
446 | 7.82k | const ptrdiff_t line_offset = v_zoom ? row_offset : 0; |
447 | | |
448 | 7.82k | if (cell->height & v_zoom || cell->width & h_zoom) |
449 | 1.05k | return IV3_BAD_DATA; |
450 | | |
451 | 18.7k | for (y = 0; y < cell->height; is_first_row = 0, y += 1 + v_zoom) { |
452 | 89.9k | for (x = 0; x < cell->width; x += 1 + h_zoom) { |
453 | 78.0k | const uint8_t *ref = ref_block; |
454 | 78.0k | uint8_t *dst = block; |
455 | | |
456 | 78.0k | if (rle_blocks > 0) { |
457 | 35.5k | if (mode <= 4) { |
458 | 20.6k | RLE_BLOCK_COPY; |
459 | 20.6k | } else if (mode == 10 && !cell->mv_ptr) { |
460 | 4.58k | RLE_BLOCK_COPY_8; |
461 | 4.58k | } |
462 | 35.5k | rle_blocks--; |
463 | 42.4k | } else { |
464 | 175k | for (line = 0; line < 4;) { |
465 | 134k | num_lines = 1; |
466 | 134k | is_top_of_cell = is_first_row && !line; |
467 | | |
468 | | /* select primary VQ table for odd, secondary for even lines */ |
469 | 134k | if (mode <= 4) |
470 | 96.7k | delta_tab = delta[line & 1]; |
471 | 38.1k | else |
472 | 38.1k | delta_tab = delta[1]; |
473 | 134k | BUFFER_PRECHECK; |
474 | 134k | uint8_t code = bytestream_get_byte(data_ptr); |
475 | 134k | if (code < 248) { |
476 | 119k | if (code < delta_tab->num_dyads) { |
477 | 94.4k | BUFFER_PRECHECK; |
478 | 94.2k | dyad1 = bytestream_get_byte(data_ptr); |
479 | 94.2k | dyad2 = code; |
480 | 94.2k | if (dyad1 >= delta_tab->num_dyads || dyad1 >= 248) |
481 | 430 | return IV3_BAD_DATA; |
482 | 94.2k | } else { |
483 | | /* process QUADS */ |
484 | 24.9k | code -= delta_tab->num_dyads; |
485 | 24.9k | dyad1 = code / delta_tab->quad_exp; |
486 | 24.9k | dyad2 = code % delta_tab->quad_exp; |
487 | 24.9k | if (swap_quads[line & 1]) |
488 | 15.6k | FFSWAP(unsigned int, dyad1, dyad2); |
489 | 24.9k | } |
490 | 118k | if (mode <= 4) { |
491 | 87.9k | APPLY_DELTA_4; |
492 | 87.9k | } else if (mode == 10 && !cell->mv_ptr) { |
493 | 14.2k | APPLY_DELTA_8; |
494 | 16.5k | } else { |
495 | 16.5k | APPLY_DELTA_1011_INTER; |
496 | 16.5k | } |
497 | 118k | } else { |
498 | | /* process RLE codes */ |
499 | 15.1k | switch (code) { |
500 | 1.19k | case RLE_ESC_FC: |
501 | 1.19k | skip_flag = 0; |
502 | 1.19k | rle_blocks = 1; |
503 | 1.19k | code = 253; |
504 | 1.19k | av_fallthrough; |
505 | 2.64k | case RLE_ESC_FF: |
506 | 2.99k | case RLE_ESC_FE: |
507 | 6.09k | case RLE_ESC_FD: |
508 | 6.09k | num_lines = 257 - code - line; |
509 | 6.09k | if (num_lines <= 0) |
510 | 314 | return IV3_BAD_RLE; |
511 | 5.78k | if (mode <= 4) { |
512 | 2.86k | RLE_LINES_COPY; |
513 | 2.91k | } else if (mode == 10 && !cell->mv_ptr) { |
514 | 1.80k | RLE_LINES_COPY_M10; |
515 | 1.80k | } |
516 | 5.78k | break; |
517 | 5.62k | case RLE_ESC_FB: |
518 | 5.62k | BUFFER_PRECHECK; |
519 | 5.42k | code = bytestream_get_byte(data_ptr); |
520 | 5.42k | rle_blocks = (code & 0x1F) - 1; /* set block counter */ |
521 | 5.42k | if (code >= 64 || rle_blocks < 0) |
522 | 454 | return IV3_BAD_COUNTER; |
523 | 4.97k | skip_flag = code & 0x20; |
524 | 4.97k | num_lines = 4 - line; /* enforce next block processing */ |
525 | 4.97k | if (mode >= 10 || (cell->mv_ptr || !skip_flag)) { |
526 | 4.50k | if (mode <= 4) { |
527 | 1.53k | RLE_LINES_COPY; |
528 | 2.96k | } else if (mode == 10 && !cell->mv_ptr) { |
529 | 1.71k | RLE_LINES_COPY_M10; |
530 | 1.71k | } |
531 | 4.50k | } |
532 | 4.97k | break; |
533 | 1.65k | case RLE_ESC_F9: |
534 | 1.65k | skip_flag = 1; |
535 | 1.65k | rle_blocks = 1; |
536 | 1.65k | av_fallthrough; |
537 | 3.23k | case RLE_ESC_FA: |
538 | 3.23k | if (line) |
539 | 203 | return IV3_BAD_RLE; |
540 | 3.03k | num_lines = 4; /* enforce next block processing */ |
541 | 3.03k | if (cell->mv_ptr) { |
542 | 1.45k | if (mode <= 4) { |
543 | 583 | RLE_LINES_COPY; |
544 | 871 | } else if (mode == 10 && !cell->mv_ptr) { |
545 | 0 | RLE_LINES_COPY_M10; |
546 | 0 | } |
547 | 1.45k | } |
548 | 3.03k | break; |
549 | 206 | default: |
550 | 206 | return IV3_UNSUPPORTED; |
551 | 15.1k | } |
552 | 15.1k | } |
553 | | |
554 | 132k | line += num_lines; |
555 | 132k | ref += row_offset * (num_lines << v_zoom); |
556 | 132k | dst += row_offset * (num_lines << v_zoom); |
557 | 132k | } |
558 | 42.4k | } |
559 | | |
560 | | /* move to next horizontal block */ |
561 | 75.7k | block += 4 << h_zoom; |
562 | 75.7k | ref_block += 4 << h_zoom; |
563 | 75.7k | } |
564 | | |
565 | | /* move to next line of blocks */ |
566 | 11.9k | ref_block += blk_row_offset; |
567 | 11.9k | block += blk_row_offset; |
568 | 11.9k | } |
569 | 4.49k | return IV3_NOERR; |
570 | 6.77k | } |
571 | | |
572 | | |
573 | | /** |
574 | | * Decode a vector-quantized cell. |
575 | | * It consists of several routines, each of which handles one or more "modes" |
576 | | * with which a cell can be encoded. |
577 | | * |
578 | | * @param ctx pointer to the decoder context |
579 | | * @param avctx ptr to the AVCodecContext |
580 | | * @param plane pointer to the plane descriptor |
581 | | * @param cell pointer to the cell descriptor |
582 | | * @param data_ptr pointer to the compressed data |
583 | | * @param last_ptr pointer to the last byte to catch reads past end of buffer |
584 | | * @return number of consumed bytes or negative number in case of error |
585 | | */ |
586 | | static int decode_cell(Indeo3DecodeContext *ctx, AVCodecContext *avctx, |
587 | | Plane *plane, Cell *cell, const uint8_t *data_ptr, |
588 | | const uint8_t *last_ptr) |
589 | 10.7k | { |
590 | 10.7k | int x, mv_x, mv_y, mode, vq_index, prim_indx, second_indx; |
591 | 10.7k | int zoom_fac; |
592 | 10.7k | int offset, error = 0, swap_quads[2]; |
593 | 10.7k | uint8_t code, *block, *ref_block = 0; |
594 | 10.7k | const vqEntry *delta[2]; |
595 | 10.7k | const uint8_t *data_start = data_ptr; |
596 | | |
597 | | /* get coding mode and VQ table index from the VQ descriptor byte */ |
598 | 10.7k | code = *data_ptr++; |
599 | 10.7k | mode = code >> 4; |
600 | 10.7k | vq_index = code & 0xF; |
601 | | |
602 | | /* setup output and reference pointers */ |
603 | 10.7k | offset = (cell->ypos << 2) * plane->pitch + (cell->xpos << 2); |
604 | 10.7k | block = plane->pixels[ctx->buf_sel] + offset; |
605 | | |
606 | 10.7k | if (!cell->mv_ptr) { |
607 | | /* use previous line as reference for INTRA cells */ |
608 | 4.79k | ref_block = block - plane->pitch; |
609 | 5.94k | } else if (mode >= 10) { |
610 | | /* for mode 10 and 11 INTER first copy the predicted cell into the current one */ |
611 | | /* so we don't need to do data copying for each RLE code later */ |
612 | 2.47k | int ret = copy_cell(ctx, plane, cell); |
613 | 2.47k | if (ret < 0) |
614 | 946 | return ret; |
615 | 3.47k | } else { |
616 | | /* set the pointer to the reference pixels for modes 0-4 INTER */ |
617 | 3.47k | mv_y = cell->mv_ptr[0]; |
618 | 3.47k | mv_x = cell->mv_ptr[1]; |
619 | | |
620 | | /* -1 because there is an extra line on top for prediction */ |
621 | 3.47k | if ((cell->ypos << 2) + mv_y < -1 || (cell->xpos << 2) + mv_x < 0 || |
622 | 3.06k | ((cell->ypos + cell->height) << 2) + mv_y > plane->height || |
623 | 2.86k | ((cell->xpos + cell->width) << 2) + mv_x > plane->width) { |
624 | 812 | av_log(ctx->avctx, AV_LOG_ERROR, |
625 | 812 | "Motion vectors point out of the frame.\n"); |
626 | 812 | return AVERROR_INVALIDDATA; |
627 | 812 | } |
628 | | |
629 | 2.65k | offset += mv_y * plane->pitch + mv_x; |
630 | 2.65k | ref_block = plane->pixels[ctx->buf_sel ^ 1] + offset; |
631 | 2.65k | } |
632 | | |
633 | | /* select VQ tables as follows: */ |
634 | | /* modes 0 and 3 use only the primary table for all lines in a block */ |
635 | | /* while modes 1 and 4 switch between primary and secondary tables on alternate lines */ |
636 | 8.99k | if (mode == 1 || mode == 4) { |
637 | 1.71k | code = ctx->alt_quant[vq_index]; |
638 | 1.71k | prim_indx = (code >> 4) + ctx->cb_offset; |
639 | 1.71k | second_indx = (code & 0xF) + ctx->cb_offset; |
640 | 7.27k | } else { |
641 | 7.27k | vq_index += ctx->cb_offset; |
642 | 7.27k | prim_indx = second_indx = vq_index; |
643 | 7.27k | } |
644 | | |
645 | 8.99k | if (prim_indx >= 24 || second_indx >= 24) { |
646 | 443 | av_log(avctx, AV_LOG_ERROR, "Invalid VQ table indexes! Primary: %d, secondary: %d!\n", |
647 | 443 | prim_indx, second_indx); |
648 | 443 | return AVERROR_INVALIDDATA; |
649 | 443 | } |
650 | | |
651 | 8.54k | delta[0] = &vq_tab[second_indx]; |
652 | 8.54k | delta[1] = &vq_tab[prim_indx]; |
653 | 8.54k | swap_quads[0] = second_indx >= 16; |
654 | 8.54k | swap_quads[1] = prim_indx >= 16; |
655 | | |
656 | | /* requantize the prediction if VQ index of this cell differs from VQ index */ |
657 | | /* of the predicted cell in order to avoid overflows. */ |
658 | 8.54k | if (vq_index >= 8 && ref_block) { |
659 | 575k | for (x = 0; x < cell->width << 2; x++) |
660 | 570k | ref_block[x] = requant_tab[vq_index & 7][ref_block[x] & 127]; |
661 | 4.60k | } |
662 | | |
663 | 8.54k | error = IV3_NOERR; |
664 | | |
665 | 8.54k | switch (mode) { |
666 | 2.89k | case 0: /*------------------ MODES 0 & 1 (4x4 block processing) --------------------*/ |
667 | 4.04k | case 1: |
668 | 4.77k | case 3: /*------------------ MODES 3 & 4 (4x8 block processing) --------------------*/ |
669 | 5.13k | case 4: |
670 | 5.13k | if (mode >= 3 && cell->mv_ptr) { |
671 | 218 | av_log(avctx, AV_LOG_ERROR, "Attempt to apply Mode 3/4 to an INTER cell!\n"); |
672 | 218 | return AVERROR_INVALIDDATA; |
673 | 218 | } |
674 | | |
675 | 4.92k | zoom_fac = mode >= 3; |
676 | 4.92k | error = decode_cell_data(ctx, cell, block, ref_block, plane->pitch, |
677 | 4.92k | 0, zoom_fac, mode, delta, swap_quads, |
678 | 4.92k | &data_ptr, last_ptr); |
679 | 4.92k | break; |
680 | 2.20k | case 10: /*-------------------- MODE 10 (8x8 block processing) ---------------------*/ |
681 | 3.14k | case 11: /*----------------- MODE 11 (4x8 INTER block processing) ------------------*/ |
682 | 3.14k | if (mode == 10 && !cell->mv_ptr) { /* MODE 10 INTRA processing */ |
683 | 1.61k | error = decode_cell_data(ctx, cell, block, ref_block, plane->pitch, |
684 | 1.61k | 1, 1, mode, delta, swap_quads, |
685 | 1.61k | &data_ptr, last_ptr); |
686 | 1.61k | } else { /* mode 10 and 11 INTER processing */ |
687 | 1.52k | if (mode == 11 && !cell->mv_ptr) { |
688 | 242 | av_log(avctx, AV_LOG_ERROR, "Attempt to use Mode 11 for an INTRA cell!\n"); |
689 | 242 | return AVERROR_INVALIDDATA; |
690 | 242 | } |
691 | | |
692 | 1.28k | zoom_fac = mode == 10; |
693 | 1.28k | av_assert2(!ref_block); |
694 | 1.28k | error = decode_cell_data(ctx, cell, block, |
695 | 1.28k | block /* dummy to avoid UB pointer arithmetic */, |
696 | 1.28k | plane->pitch, zoom_fac, 1, mode, delta, |
697 | 1.28k | swap_quads, &data_ptr, last_ptr); |
698 | 1.28k | } |
699 | 2.90k | break; |
700 | 2.90k | default: |
701 | 261 | av_log(avctx, AV_LOG_ERROR, "Unsupported coding mode: %d\n", mode); |
702 | 261 | return AVERROR_INVALIDDATA; |
703 | 8.54k | }//switch mode |
704 | | |
705 | 7.82k | switch (error) { |
706 | 517 | case IV3_BAD_RLE: |
707 | 517 | av_log(avctx, AV_LOG_ERROR, "Mode %d: RLE code %X is not allowed at the current line\n", |
708 | 517 | mode, data_ptr[-1]); |
709 | 517 | return AVERROR_INVALIDDATA; |
710 | 1.48k | case IV3_BAD_DATA: |
711 | 1.48k | av_log(avctx, AV_LOG_ERROR, "Mode %d: invalid VQ data\n", mode); |
712 | 1.48k | return AVERROR_INVALIDDATA; |
713 | 454 | case IV3_BAD_COUNTER: |
714 | 454 | av_log(avctx, AV_LOG_ERROR, "Mode %d: RLE-FB invalid counter: %d\n", mode, code); |
715 | 454 | return AVERROR_INVALIDDATA; |
716 | 206 | case IV3_UNSUPPORTED: |
717 | 206 | av_log(avctx, AV_LOG_ERROR, "Mode %d: unsupported RLE code: %X\n", mode, data_ptr[-1]); |
718 | 206 | return AVERROR_INVALIDDATA; |
719 | 673 | case IV3_OUT_OF_DATA: |
720 | 673 | av_log(avctx, AV_LOG_ERROR, "Mode %d: attempt to read past end of buffer\n", mode); |
721 | 673 | return AVERROR_INVALIDDATA; |
722 | 7.82k | } |
723 | | |
724 | 4.49k | return data_ptr - data_start; /* report number of bytes consumed from the input buffer */ |
725 | 7.82k | } |
726 | | |
727 | | |
728 | | /* Binary tree codes. */ |
729 | | enum { |
730 | | H_SPLIT = 0, |
731 | | V_SPLIT = 1, |
732 | | INTRA_NULL = 2, |
733 | | INTER_DATA = 3 |
734 | | }; |
735 | | |
736 | | |
737 | 38.5k | #define SPLIT_CELL(size, new_size) (new_size) = ((size) > 2) ? ((((size) + 2) >> 2) << 1) : 1 |
738 | | |
739 | | #define UPDATE_BITPOS(n) \ |
740 | 24.9k | ctx->skip_bits += (n); \ |
741 | 24.9k | ctx->need_resync = 1 |
742 | | |
743 | | #define RESYNC_BITSTREAM \ |
744 | 119k | if (ctx->need_resync && !(get_bits_count(&ctx->gb) & 7)) { \ |
745 | 9.13k | skip_bits_long(&ctx->gb, ctx->skip_bits); \ |
746 | 9.13k | ctx->skip_bits = 0; \ |
747 | 9.13k | ctx->need_resync = 0; \ |
748 | 9.13k | } |
749 | | |
750 | | #define CHECK_CELL \ |
751 | 30.4k | if (curr_cell.xpos + curr_cell.width > (plane->width >> 2) || \ |
752 | 30.4k | curr_cell.ypos + curr_cell.height > (plane->height >> 2)) { \ |
753 | 0 | av_log(avctx, AV_LOG_ERROR, "Invalid cell: x=%d, y=%d, w=%d, h=%d\n", \ |
754 | 0 | curr_cell.xpos, curr_cell.ypos, curr_cell.width, curr_cell.height); \ |
755 | 0 | return AVERROR_INVALIDDATA; \ |
756 | 0 | } |
757 | | |
758 | | |
759 | | static int parse_bintree(Indeo3DecodeContext *ctx, AVCodecContext *avctx, |
760 | | Plane *plane, int code, Cell *ref_cell, |
761 | | const int depth, const int strip_width) |
762 | 63.3k | { |
763 | 63.3k | Cell curr_cell; |
764 | 63.3k | int bytes_used, ret; |
765 | | |
766 | 63.3k | if (depth <= 0) { |
767 | 0 | av_log(avctx, AV_LOG_ERROR, "Stack overflow (corrupted binary tree)!\n"); |
768 | 0 | return AVERROR_INVALIDDATA; // unwind recursion |
769 | 0 | } |
770 | | |
771 | 63.3k | curr_cell = *ref_cell; // clone parent cell |
772 | 63.3k | if (code == H_SPLIT) { |
773 | 30.2k | SPLIT_CELL(ref_cell->height, curr_cell.height); |
774 | 30.2k | ref_cell->ypos += curr_cell.height; |
775 | 30.2k | ref_cell->height -= curr_cell.height; |
776 | 30.2k | if (ref_cell->height <= 0 || curr_cell.height <= 0) |
777 | 1.09k | return AVERROR_INVALIDDATA; |
778 | 33.1k | } else if (code == V_SPLIT) { |
779 | 13.7k | if (curr_cell.width > strip_width) { |
780 | | /* split strip */ |
781 | 5.37k | curr_cell.width = (curr_cell.width <= (strip_width << 1) ? 1 : 2) * strip_width; |
782 | 5.37k | } else |
783 | 8.36k | SPLIT_CELL(ref_cell->width, curr_cell.width); |
784 | 13.7k | ref_cell->xpos += curr_cell.width; |
785 | 13.7k | ref_cell->width -= curr_cell.width; |
786 | 13.7k | if (ref_cell->width <= 0 || curr_cell.width <= 0) |
787 | 215 | return AVERROR_INVALIDDATA; |
788 | 13.7k | } |
789 | | |
790 | 100k | while (get_bits_left(&ctx->gb) >= 2) { /* loop until return */ |
791 | 99.7k | RESYNC_BITSTREAM; |
792 | 99.7k | switch (code = get_bits(&ctx->gb, 2)) { |
793 | 30.2k | case H_SPLIT: |
794 | 43.9k | case V_SPLIT: |
795 | 43.9k | if (parse_bintree(ctx, avctx, plane, code, &curr_cell, depth - 1, strip_width)) |
796 | 29.8k | return AVERROR_INVALIDDATA; |
797 | 14.1k | break; |
798 | 23.5k | case INTRA_NULL: |
799 | 23.5k | if (!curr_cell.tree) { /* MC tree INTRA code */ |
800 | 3.56k | curr_cell.mv_ptr = 0; /* mark the current strip as INTRA */ |
801 | 3.56k | curr_cell.tree = 1; /* enter the VQ tree */ |
802 | 20.0k | } else { /* VQ tree NULL code */ |
803 | 20.0k | RESYNC_BITSTREAM; |
804 | 20.0k | code = get_bits(&ctx->gb, 2); |
805 | 20.0k | if (code >= 2) { |
806 | 289 | av_log(avctx, AV_LOG_ERROR, "Invalid VQ_NULL code: %d\n", code); |
807 | 289 | return AVERROR_INVALIDDATA; |
808 | 289 | } |
809 | 19.7k | if (code == 1) |
810 | 5.30k | av_log(avctx, AV_LOG_ERROR, "SkipCell procedure not implemented yet!\n"); |
811 | | |
812 | 19.7k | CHECK_CELL |
813 | 19.7k | if (!curr_cell.mv_ptr) |
814 | 229 | return AVERROR_INVALIDDATA; |
815 | | |
816 | 19.5k | ret = copy_cell(ctx, plane, &curr_cell); |
817 | 19.5k | return ret; |
818 | 19.7k | } |
819 | 3.56k | break; |
820 | 32.1k | case INTER_DATA: |
821 | 32.1k | if (!curr_cell.tree) { /* MC tree INTER code */ |
822 | 21.4k | unsigned mv_idx; |
823 | | /* get motion vector index and setup the pointer to the mv set */ |
824 | 21.4k | if (!ctx->need_resync) |
825 | 21.2k | ctx->next_cell_data = &ctx->gb.buffer[(get_bits_count(&ctx->gb) + 7) >> 3]; |
826 | 21.4k | if (ctx->next_cell_data >= ctx->last_byte) { |
827 | 571 | av_log(avctx, AV_LOG_ERROR, "motion vector out of array\n"); |
828 | 571 | return AVERROR_INVALIDDATA; |
829 | 571 | } |
830 | 20.8k | mv_idx = *(ctx->next_cell_data++); |
831 | 20.8k | if (mv_idx >= ctx->num_vectors) { |
832 | 409 | av_log(avctx, AV_LOG_ERROR, "motion vector index out of range\n"); |
833 | 409 | return AVERROR_INVALIDDATA; |
834 | 409 | } |
835 | 20.4k | curr_cell.mv_ptr = &ctx->mc_vectors[mv_idx << 1]; |
836 | 20.4k | curr_cell.tree = 1; /* enter the VQ tree */ |
837 | 20.4k | UPDATE_BITPOS(8); |
838 | 20.4k | } else { /* VQ tree DATA code */ |
839 | 10.7k | if (!ctx->need_resync) |
840 | 4.82k | ctx->next_cell_data = &ctx->gb.buffer[(get_bits_count(&ctx->gb) + 7) >> 3]; |
841 | | |
842 | 10.7k | CHECK_CELL |
843 | 10.7k | bytes_used = decode_cell(ctx, avctx, plane, &curr_cell, |
844 | 10.7k | ctx->next_cell_data, ctx->last_byte); |
845 | 10.7k | if (bytes_used < 0) |
846 | 6.25k | return AVERROR_INVALIDDATA; |
847 | | |
848 | 4.49k | UPDATE_BITPOS(bytes_used << 3); |
849 | 4.49k | ctx->next_cell_data += bytes_used; |
850 | 4.49k | return 0; |
851 | 10.7k | } |
852 | 20.4k | break; |
853 | 99.7k | } |
854 | 99.7k | }//while |
855 | | |
856 | 450 | return AVERROR_INVALIDDATA; |
857 | 62.0k | } |
858 | | |
859 | | |
860 | | static int decode_plane(Indeo3DecodeContext *ctx, AVCodecContext *avctx, |
861 | | Plane *plane, const uint8_t *data, int32_t data_size, |
862 | | int32_t strip_width) |
863 | 22.9k | { |
864 | 22.9k | Cell curr_cell; |
865 | 22.9k | unsigned num_vectors; |
866 | | |
867 | | /* each plane data starts with mc_vector_count field, */ |
868 | | /* an optional array of motion vectors followed by the vq data */ |
869 | 22.9k | num_vectors = bytestream_get_le32(&data); data_size -= 4; |
870 | 22.9k | if (num_vectors > 256) { |
871 | 3.12k | av_log(ctx->avctx, AV_LOG_ERROR, |
872 | 3.12k | "Read invalid number of motion vectors %d\n", num_vectors); |
873 | 3.12k | return AVERROR_INVALIDDATA; |
874 | 3.12k | } |
875 | 19.8k | if (num_vectors * 2 > data_size) |
876 | 441 | return AVERROR_INVALIDDATA; |
877 | | |
878 | 19.3k | ctx->num_vectors = num_vectors; |
879 | 19.3k | ctx->mc_vectors = num_vectors ? data : 0; |
880 | | |
881 | | /* init the bitreader */ |
882 | 19.3k | init_get_bits(&ctx->gb, &data[num_vectors * 2], (data_size - num_vectors * 2) << 3); |
883 | 19.3k | ctx->skip_bits = 0; |
884 | 19.3k | ctx->need_resync = 0; |
885 | | |
886 | 19.3k | ctx->last_byte = data + data_size; |
887 | | |
888 | | /* initialize the 1st cell and set its dimensions to whole plane */ |
889 | 19.3k | curr_cell.xpos = curr_cell.ypos = 0; |
890 | 19.3k | curr_cell.width = plane->width >> 2; |
891 | 19.3k | curr_cell.height = plane->height >> 2; |
892 | 19.3k | curr_cell.tree = 0; // we are in the MC tree now |
893 | 19.3k | curr_cell.mv_ptr = 0; // no motion vector = INTRA cell |
894 | | |
895 | 19.3k | return parse_bintree(ctx, avctx, plane, INTRA_NULL, &curr_cell, CELL_STACK_MAX, strip_width); |
896 | 19.8k | } |
897 | | |
898 | | |
899 | 676k | #define OS_HDR_ID MKBETAG('F', 'R', 'M', 'H') |
900 | | |
901 | | static int decode_frame_headers(Indeo3DecodeContext *ctx, AVCodecContext *avctx, |
902 | | const uint8_t *buf, int buf_size) |
903 | 676k | { |
904 | 676k | GetByteContext gb; |
905 | 676k | const uint8_t *bs_hdr; |
906 | 676k | uint32_t frame_num, word2, check_sum, data_size; |
907 | 676k | int y_offset, u_offset, v_offset; |
908 | 676k | uint32_t starts[3], ends[3]; |
909 | 676k | uint16_t height, width; |
910 | 676k | int i, j; |
911 | | |
912 | 676k | bytestream2_init(&gb, buf, buf_size); |
913 | | |
914 | | /* parse and check the OS header */ |
915 | 676k | frame_num = bytestream2_get_le32(&gb); |
916 | 676k | word2 = bytestream2_get_le32(&gb); |
917 | 676k | check_sum = bytestream2_get_le32(&gb); |
918 | 676k | data_size = bytestream2_get_le32(&gb); |
919 | | |
920 | 676k | if ((frame_num ^ word2 ^ data_size ^ OS_HDR_ID) != check_sum) { |
921 | 531k | av_log(avctx, AV_LOG_ERROR, "OS header checksum mismatch!\n"); |
922 | 531k | return AVERROR_INVALIDDATA; |
923 | 531k | } |
924 | | |
925 | | /* parse the bitstream header */ |
926 | 145k | bs_hdr = gb.buffer; |
927 | | |
928 | 145k | if (bytestream2_get_le16(&gb) != 32) { |
929 | 800 | av_log(avctx, AV_LOG_ERROR, "Unsupported codec version!\n"); |
930 | 800 | return AVERROR_INVALIDDATA; |
931 | 800 | } |
932 | | |
933 | 144k | ctx->frame_num = frame_num; |
934 | 144k | ctx->frame_flags = bytestream2_get_le16(&gb); |
935 | 144k | ctx->data_size = (bytestream2_get_le32(&gb) + 7) >> 3; |
936 | 144k | ctx->cb_offset = bytestream2_get_byte(&gb); |
937 | | |
938 | 144k | if (ctx->data_size == 16) |
939 | 116k | return 4; |
940 | 27.4k | ctx->data_size = FFMIN(ctx->data_size, buf_size - 16); |
941 | | |
942 | 27.4k | bytestream2_skip(&gb, 3); // skip reserved byte and checksum |
943 | | |
944 | | /* check frame dimensions */ |
945 | 27.4k | height = bytestream2_get_le16(&gb); |
946 | 27.4k | width = bytestream2_get_le16(&gb); |
947 | 27.4k | if (av_image_check_size(width, height, 0, avctx)) |
948 | 2.16k | return AVERROR_INVALIDDATA; |
949 | | |
950 | 25.3k | if (width != ctx->width || height != ctx->height) { |
951 | 8.42k | int res; |
952 | | |
953 | 8.42k | ff_dlog(avctx, "Frame dimensions changed!\n"); |
954 | | |
955 | 8.42k | if (width < 16 || width > 640 || |
956 | 7.73k | height < 16 || height > 480 || |
957 | 6.83k | width & 3 || height & 3) { |
958 | 2.68k | av_log(avctx, AV_LOG_ERROR, |
959 | 2.68k | "Invalid picture dimensions: %d x %d!\n", width, height); |
960 | 2.68k | return AVERROR_INVALIDDATA; |
961 | 2.68k | } |
962 | 5.73k | free_frame_buffers(ctx); |
963 | 5.73k | if ((res = allocate_frame_buffers(ctx, avctx, width, height)) < 0) |
964 | 0 | return res; |
965 | 5.73k | if ((res = ff_set_dimensions(avctx, width, height)) < 0) |
966 | 0 | return res; |
967 | 5.73k | } |
968 | | |
969 | 22.6k | y_offset = bytestream2_get_le32(&gb); |
970 | 22.6k | v_offset = bytestream2_get_le32(&gb); |
971 | 22.6k | u_offset = bytestream2_get_le32(&gb); |
972 | 22.6k | bytestream2_skip(&gb, 4); |
973 | | |
974 | | /* unfortunately there is no common order of planes in the buffer */ |
975 | | /* so we use that sorting algo for determining planes data sizes */ |
976 | 22.6k | starts[0] = y_offset; |
977 | 22.6k | starts[1] = v_offset; |
978 | 22.6k | starts[2] = u_offset; |
979 | | |
980 | 90.4k | for (j = 0; j < 3; j++) { |
981 | 67.8k | ends[j] = ctx->data_size; |
982 | 271k | for (i = 2; i >= 0; i--) |
983 | 203k | if (starts[i] < ends[j] && starts[i] > starts[j]) |
984 | 30.5k | ends[j] = starts[i]; |
985 | 67.8k | } |
986 | | |
987 | 22.6k | ctx->y_data_size = ends[0] - starts[0]; |
988 | 22.6k | ctx->v_data_size = ends[1] - starts[1]; |
989 | 22.6k | ctx->u_data_size = ends[2] - starts[2]; |
990 | 22.6k | if (FFMIN3(y_offset, v_offset, u_offset) < 0 || |
991 | 21.9k | FFMAX3(y_offset, v_offset, u_offset) >= ctx->data_size - 16 || |
992 | 18.2k | FFMIN3(y_offset, v_offset, u_offset) < gb.buffer - bs_hdr + 16 || |
993 | 16.2k | FFMIN3(ctx->y_data_size, ctx->v_data_size, ctx->u_data_size) <= 0) { |
994 | 6.33k | av_log(avctx, AV_LOG_ERROR, "One of the y/u/v offsets is invalid\n"); |
995 | 6.33k | return AVERROR_INVALIDDATA; |
996 | 6.33k | } |
997 | | |
998 | 16.2k | ctx->y_data_ptr = bs_hdr + y_offset; |
999 | 16.2k | ctx->v_data_ptr = bs_hdr + v_offset; |
1000 | 16.2k | ctx->u_data_ptr = bs_hdr + u_offset; |
1001 | 16.2k | ctx->alt_quant = gb.buffer; |
1002 | | |
1003 | 16.2k | if (ctx->data_size == 16) { |
1004 | 0 | av_log(avctx, AV_LOG_DEBUG, "Sync frame encountered!\n"); |
1005 | 0 | return 16; |
1006 | 0 | } |
1007 | | |
1008 | 16.2k | if (ctx->frame_flags & BS_8BIT_PEL) { |
1009 | 356 | avpriv_request_sample(avctx, "8-bit pixel format"); |
1010 | 356 | return AVERROR_PATCHWELCOME; |
1011 | 356 | } |
1012 | | |
1013 | 15.9k | if (ctx->frame_flags & BS_MV_X_HALF || ctx->frame_flags & BS_MV_Y_HALF) { |
1014 | 391 | avpriv_request_sample(avctx, "Halfpel motion vectors"); |
1015 | 391 | return AVERROR_PATCHWELCOME; |
1016 | 391 | } |
1017 | | |
1018 | 15.5k | return 0; |
1019 | 15.9k | } |
1020 | | |
1021 | | |
1022 | | /** |
1023 | | * Convert and output the current plane. |
1024 | | * All pixel values will be upsampled by shifting right by one bit. |
1025 | | * |
1026 | | * @param[in] plane pointer to the descriptor of the plane being processed |
1027 | | * @param[in] buf_sel indicates which frame buffer the input data stored in |
1028 | | * @param[out] dst pointer to the buffer receiving converted pixels |
1029 | | * @param[in] dst_pitch pitch for moving to the next y line |
1030 | | * @param[in] dst_height output plane height |
1031 | | */ |
1032 | | static void output_plane(const Plane *plane, int buf_sel, uint8_t *dst, |
1033 | | ptrdiff_t dst_pitch, int dst_height) |
1034 | 5.96k | { |
1035 | 5.96k | int x,y; |
1036 | 5.96k | const uint8_t *src = plane->pixels[buf_sel]; |
1037 | 5.96k | ptrdiff_t pitch = plane->pitch; |
1038 | | |
1039 | 5.96k | dst_height = FFMIN(dst_height, plane->height); |
1040 | 718k | for (y = 0; y < dst_height; y++) { |
1041 | | /* convert four pixels at once using SWAR */ |
1042 | 33.5M | for (x = 0; x < plane->width >> 2; x++) { |
1043 | 32.8M | AV_WN32A(dst, (AV_RN32A(src) & 0x7F7F7F7F) << 1); |
1044 | 32.8M | src += 4; |
1045 | 32.8M | dst += 4; |
1046 | 32.8M | } |
1047 | | |
1048 | 712k | for (x <<= 2; x < plane->width; x++) |
1049 | 0 | *dst++ = *src++ << 1; |
1050 | | |
1051 | 712k | src += pitch - plane->width; |
1052 | 712k | dst += dst_pitch - plane->width; |
1053 | 712k | } |
1054 | 5.96k | } |
1055 | | |
1056 | | |
1057 | | static av_cold int decode_init(AVCodecContext *avctx) |
1058 | 1.58k | { |
1059 | 1.58k | static AVOnce init_static_once = AV_ONCE_INIT; |
1060 | 1.58k | Indeo3DecodeContext *ctx = avctx->priv_data; |
1061 | | |
1062 | 1.58k | ctx->avctx = avctx; |
1063 | 1.58k | avctx->pix_fmt = AV_PIX_FMT_YUV410P; |
1064 | | |
1065 | 1.58k | ff_thread_once(&init_static_once, build_requant_tab); |
1066 | | |
1067 | 1.58k | ff_hpeldsp_init(&ctx->hdsp, avctx->flags); |
1068 | | |
1069 | 1.58k | return allocate_frame_buffers(ctx, avctx, avctx->width, avctx->height); |
1070 | 1.58k | } |
1071 | | |
1072 | | |
1073 | | static int decode_frame(AVCodecContext *avctx, AVFrame *frame, |
1074 | | int *got_frame, AVPacket *avpkt) |
1075 | 676k | { |
1076 | 676k | Indeo3DecodeContext *ctx = avctx->priv_data; |
1077 | 676k | const uint8_t *buf = avpkt->data; |
1078 | 676k | int buf_size = avpkt->size; |
1079 | 676k | int res; |
1080 | | |
1081 | 676k | res = decode_frame_headers(ctx, avctx, buf, buf_size); |
1082 | 676k | if (res < 0) |
1083 | 544k | return res; |
1084 | | |
1085 | | /* skip sync(null) frames */ |
1086 | 132k | if (res) { |
1087 | | // we have processed 16 bytes but no data was decoded |
1088 | 116k | *got_frame = 0; |
1089 | 116k | return buf_size; |
1090 | 116k | } |
1091 | | |
1092 | | /* skip droppable INTER frames if requested */ |
1093 | 15.5k | if (ctx->frame_flags & BS_NONREF && |
1094 | 886 | (avctx->skip_frame >= AVDISCARD_NONREF)) |
1095 | 198 | return 0; |
1096 | | |
1097 | | /* skip INTER frames if requested */ |
1098 | 15.3k | if (!(ctx->frame_flags & BS_KEYFRAME) && avctx->skip_frame >= AVDISCARD_NONKEY) |
1099 | 212 | return 0; |
1100 | | |
1101 | | /* use BS_BUFFER flag for buffer switching */ |
1102 | 15.1k | ctx->buf_sel = (ctx->frame_flags >> BS_BUFFER) & 1; |
1103 | | |
1104 | 15.1k | if ((res = ff_get_buffer(avctx, frame, 0)) < 0) |
1105 | 0 | return res; |
1106 | | |
1107 | | /* decode luma plane */ |
1108 | 15.1k | if ((res = decode_plane(ctx, avctx, ctx->planes, ctx->y_data_ptr, ctx->y_data_size, 40))) |
1109 | 10.9k | return res; |
1110 | | |
1111 | | /* decode chroma planes */ |
1112 | 4.17k | if ((res = decode_plane(ctx, avctx, &ctx->planes[1], ctx->u_data_ptr, ctx->u_data_size, 10))) |
1113 | 531 | return res; |
1114 | | |
1115 | 3.64k | if ((res = decode_plane(ctx, avctx, &ctx->planes[2], ctx->v_data_ptr, ctx->v_data_size, 10))) |
1116 | 1.65k | return res; |
1117 | | |
1118 | 1.98k | output_plane(&ctx->planes[0], ctx->buf_sel, |
1119 | 1.98k | frame->data[0], frame->linesize[0], |
1120 | 1.98k | avctx->height); |
1121 | 1.98k | output_plane(&ctx->planes[1], ctx->buf_sel, |
1122 | 1.98k | frame->data[1], frame->linesize[1], |
1123 | 1.98k | (avctx->height + 3) >> 2); |
1124 | 1.98k | output_plane(&ctx->planes[2], ctx->buf_sel, |
1125 | 1.98k | frame->data[2], frame->linesize[2], |
1126 | 1.98k | (avctx->height + 3) >> 2); |
1127 | | |
1128 | 1.98k | *got_frame = 1; |
1129 | | |
1130 | 1.98k | return buf_size; |
1131 | 3.64k | } |
1132 | | |
1133 | | |
1134 | | static av_cold int decode_close(AVCodecContext *avctx) |
1135 | 1.58k | { |
1136 | 1.58k | free_frame_buffers(avctx->priv_data); |
1137 | | |
1138 | 1.58k | return 0; |
1139 | 1.58k | } |
1140 | | |
1141 | | const FFCodec ff_indeo3_decoder = { |
1142 | | .p.name = "indeo3", |
1143 | | CODEC_LONG_NAME("Intel Indeo 3"), |
1144 | | .p.type = AVMEDIA_TYPE_VIDEO, |
1145 | | .p.id = AV_CODEC_ID_INDEO3, |
1146 | | .priv_data_size = sizeof(Indeo3DecodeContext), |
1147 | | .init = decode_init, |
1148 | | .close = decode_close, |
1149 | | FF_CODEC_DECODE_CB(decode_frame), |
1150 | | .p.capabilities = AV_CODEC_CAP_DR1, |
1151 | | .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, |
1152 | | }; |