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