Line | Branch | Exec | Source |
---|---|---|---|
1 | /* | ||
2 | * Flash Screen Video decoder | ||
3 | * Copyright (C) 2004 Alex Beregszaszi | ||
4 | * Copyright (C) 2006 Benjamin Larsson | ||
5 | * | ||
6 | * This file is part of FFmpeg. | ||
7 | * | ||
8 | * FFmpeg is free software; you can redistribute it and/or | ||
9 | * modify it under the terms of the GNU Lesser General Public | ||
10 | * License as published by the Free Software Foundation; either | ||
11 | * version 2.1 of the License, or (at your option) any later version. | ||
12 | * | ||
13 | * FFmpeg is distributed in the hope that it will be useful, | ||
14 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
16 | * Lesser General Public License for more details. | ||
17 | * | ||
18 | * You should have received a copy of the GNU Lesser General Public | ||
19 | * License along with FFmpeg; if not, write to the Free Software | ||
20 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | ||
21 | */ | ||
22 | |||
23 | /** | ||
24 | * @file | ||
25 | * Flash Screen Video decoder | ||
26 | * @author Alex Beregszaszi | ||
27 | * @author Benjamin Larsson | ||
28 | * @author Daniel Verkamp | ||
29 | * @author Konstantin Shishkov | ||
30 | * | ||
31 | * A description of the bitstream format for Flash Screen Video version 1/2 | ||
32 | * is part of the SWF File Format Specification (version 10), which can be | ||
33 | * downloaded from http://www.adobe.com/devnet/swf.html. | ||
34 | */ | ||
35 | |||
36 | #include "config_components.h" | ||
37 | |||
38 | #include <stddef.h> | ||
39 | #include <zlib.h> | ||
40 | |||
41 | #include "libavutil/intreadwrite.h" | ||
42 | #include "libavutil/mem.h" | ||
43 | #include "avcodec.h" | ||
44 | #include "bytestream.h" | ||
45 | #include "codec_internal.h" | ||
46 | #include "decode.h" | ||
47 | #include "get_bits.h" | ||
48 | #include "zlib_wrapper.h" | ||
49 | |||
50 | typedef struct BlockInfo { | ||
51 | const uint8_t *pos; | ||
52 | int size; | ||
53 | } BlockInfo; | ||
54 | |||
55 | typedef struct FlashSVContext { | ||
56 | AVCodecContext *avctx; | ||
57 | AVFrame *frame; | ||
58 | int image_width, image_height; | ||
59 | int block_width, block_height; | ||
60 | uint8_t *tmpblock; | ||
61 | int block_size; | ||
62 | int ver; | ||
63 | const uint32_t *pal; | ||
64 | int is_keyframe; | ||
65 | const uint8_t *keyframedata; | ||
66 | AVBufferRef *keyframedata_buf; | ||
67 | uint8_t *keyframe; | ||
68 | BlockInfo *blocks; | ||
69 | int color_depth; | ||
70 | int zlibprime_curr, zlibprime_prev; | ||
71 | int diff_start, diff_height; | ||
72 | FFZStream zstream; | ||
73 | uint8_t tmp[UINT16_MAX]; | ||
74 | } FlashSVContext; | ||
75 | |||
76 | 4641 | static int decode_hybrid(const uint8_t *sptr, const uint8_t *sptr_end, uint8_t *dptr, int dx, int dy, | |
77 | int h, int w, int stride, const uint32_t *pal) | ||
78 | { | ||
79 | int x, y; | ||
80 | 4641 | const uint8_t *orig_src = sptr; | |
81 | |||
82 |
2/2✓ Branch 0 taken 266118 times.
✓ Branch 1 taken 4641 times.
|
270759 | for (y = dx + h; y > dx; y--) { |
83 | 266118 | uint8_t *dst = dptr + (y * stride) + dy * 3; | |
84 |
2/2✓ Branch 0 taken 15569484 times.
✓ Branch 1 taken 266118 times.
|
15835602 | for (x = 0; x < w; x++) { |
85 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 15569484 times.
|
15569484 | if (sptr >= sptr_end) |
86 | ✗ | return AVERROR_INVALIDDATA; | |
87 |
2/2✓ Branch 0 taken 12342661 times.
✓ Branch 1 taken 3226823 times.
|
15569484 | if (*sptr & 0x80) { |
88 | /* 15-bit color */ | ||
89 | 12342661 | unsigned c = AV_RB16(sptr) & ~0x8000; | |
90 | 12342661 | unsigned b = c & 0x1F; | |
91 | 12342661 | unsigned g = (c >> 5) & 0x1F; | |
92 | 12342661 | unsigned r = c >> 10; | |
93 | /* 000aaabb -> aaabbaaa */ | ||
94 | 12342661 | *dst++ = (b << 3) | (b >> 2); | |
95 | 12342661 | *dst++ = (g << 3) | (g >> 2); | |
96 | 12342661 | *dst++ = (r << 3) | (r >> 2); | |
97 | 12342661 | sptr += 2; | |
98 | } else { | ||
99 | /* palette index */ | ||
100 | 3226823 | uint32_t c = pal[*sptr++]; | |
101 | 3226823 | bytestream_put_le24(&dst, c); | |
102 | } | ||
103 | } | ||
104 | } | ||
105 | 4641 | return sptr - orig_src; | |
106 | } | ||
107 | |||
108 | 17 | static av_cold int flashsv_decode_end(AVCodecContext *avctx) | |
109 | { | ||
110 | 17 | FlashSVContext *s = avctx->priv_data; | |
111 | |||
112 | 17 | ff_inflate_end(&s->zstream); | |
113 | /* release the frame if needed */ | ||
114 | 17 | av_frame_free(&s->frame); | |
115 | |||
116 | /* free the tmpblock */ | ||
117 | 17 | av_freep(&s->tmpblock); | |
118 | |||
119 | 17 | return 0; | |
120 | } | ||
121 | |||
122 | 17 | static av_cold int flashsv_decode_init(AVCodecContext *avctx) | |
123 | { | ||
124 | 17 | FlashSVContext *s = avctx->priv_data; | |
125 | |||
126 | 17 | s->avctx = avctx; | |
127 | 17 | avctx->pix_fmt = AV_PIX_FMT_BGR24; | |
128 | |||
129 | 17 | s->frame = av_frame_alloc(); | |
130 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 17 times.
|
17 | if (!s->frame) { |
131 | ✗ | return AVERROR(ENOMEM); | |
132 | } | ||
133 | |||
134 | 17 | return ff_inflate_init(&s->zstream, avctx); | |
135 | } | ||
136 | |||
137 | 4095 | static int flashsv2_prime(FlashSVContext *s, const uint8_t *src, int size) | |
138 | { | ||
139 | int zret; // Zlib return code | ||
140 | static const uint8_t zlib_header[] = { 0x78, 0x01 }; | ||
141 | 4095 | z_stream *const zstream = &s->zstream.zstream; | |
142 | 4095 | uint8_t *data = s->tmpblock; | |
143 | unsigned remaining; | ||
144 | |||
145 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4095 times.
|
4095 | if (!src) |
146 | ✗ | return AVERROR_INVALIDDATA; | |
147 | |||
148 | 4095 | zstream->next_in = src; | |
149 | 4095 | zstream->avail_in = size; | |
150 | 4095 | zstream->next_out = data; | |
151 | 4095 | zstream->avail_out = s->block_size * 3; | |
152 | 4095 | zret = inflate(zstream, Z_SYNC_FLUSH); | |
153 |
2/4✓ Branch 0 taken 4095 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4095 times.
|
4095 | if (zret != Z_OK && zret != Z_STREAM_END) |
154 | ✗ | return AVERROR_UNKNOWN; | |
155 | 4095 | remaining = s->block_size * 3 - zstream->avail_out; | |
156 | |||
157 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 4095 times.
|
4095 | if ((zret = inflateReset(zstream)) != Z_OK) { |
158 | ✗ | av_log(s->avctx, AV_LOG_ERROR, "Inflate reset error: %d\n", zret); | |
159 | ✗ | return AVERROR_UNKNOWN; | |
160 | } | ||
161 | |||
162 | /* Create input for zlib that is equivalent to encoding the output | ||
163 | * from above and decoding it again (the net result of this is that | ||
164 | * the dictionary of past decoded data is correctly primed and | ||
165 | * the adler32 checksum is correctly initialized). | ||
166 | * This is accomplished by synthetizing blocks of uncompressed data | ||
167 | * out of the output from above. See section 3.2.4 of RFC 1951. */ | ||
168 | 4095 | zstream->next_in = zlib_header; | |
169 | 4095 | zstream->avail_in = sizeof(zlib_header); | |
170 | 4095 | zret = inflate(zstream, Z_SYNC_FLUSH); | |
171 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4095 times.
|
4095 | if (zret != Z_OK) |
172 | ✗ | return AVERROR_UNKNOWN; | |
173 |
2/2✓ Branch 0 taken 4095 times.
✓ Branch 1 taken 4095 times.
|
8190 | while (remaining > 0) { |
174 | 4095 | unsigned block_size = FFMIN(UINT16_MAX, remaining); | |
175 | uint8_t header[5]; | ||
176 | /* Bit 0: Non-last-block, bits 1-2: BTYPE for uncompressed block */ | ||
177 | 4095 | header[0] = 0; | |
178 | /* Block size */ | ||
179 | 4095 | AV_WL16(header + 1, block_size); | |
180 | /* Block size (one's complement) */ | ||
181 | 4095 | AV_WL16(header + 3, block_size ^ 0xFFFF); | |
182 | 4095 | zstream->next_in = header; | |
183 | 4095 | zstream->avail_in = sizeof(header); | |
184 | 4095 | zstream->next_out = s->tmp; | |
185 | 4095 | zstream->avail_out = sizeof(s->tmp); | |
186 | 4095 | zret = inflate(zstream, Z_SYNC_FLUSH); | |
187 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4095 times.
|
4095 | if (zret != Z_OK) |
188 | ✗ | return AVERROR_UNKNOWN; | |
189 | 4095 | zstream->next_in = data; | |
190 | 4095 | zstream->avail_in = block_size; | |
191 | 4095 | zret = inflate(zstream, Z_SYNC_FLUSH); | |
192 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4095 times.
|
4095 | if (zret != Z_OK) |
193 | ✗ | return AVERROR_UNKNOWN; | |
194 | 4095 | data += block_size; | |
195 | 4095 | remaining -= block_size; | |
196 | } | ||
197 | |||
198 | 4095 | return 0; | |
199 | } | ||
200 | |||
201 | 9312 | static int flashsv_decode_block(AVCodecContext *avctx, const AVPacket *avpkt, | |
202 | GetBitContext *gb, int block_size, | ||
203 | int width, int height, int x_pos, int y_pos, | ||
204 | int blk_idx) | ||
205 | { | ||
206 | 9312 | struct FlashSVContext *s = avctx->priv_data; | |
207 | 9312 | z_stream *const zstream = &s->zstream.zstream; | |
208 | 9312 | uint8_t *line = s->tmpblock; | |
209 | int k; | ||
210 | 9312 | int ret = inflateReset(zstream); | |
211 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9312 times.
|
9312 | if (ret != Z_OK) { |
212 | ✗ | av_log(avctx, AV_LOG_ERROR, "Inflate reset error: %d\n", ret); | |
213 | ✗ | return AVERROR_UNKNOWN; | |
214 | } | ||
215 |
3/4✓ Branch 0 taken 9312 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 4095 times.
✓ Branch 3 taken 5217 times.
|
9312 | if (s->zlibprime_curr || s->zlibprime_prev) { |
216 | 4095 | ret = flashsv2_prime(s, | |
217 | 4095 | s->blocks[blk_idx].pos, | |
218 | 4095 | s->blocks[blk_idx].size); | |
219 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4095 times.
|
4095 | if (ret < 0) |
220 | ✗ | return ret; | |
221 | } | ||
222 | 9312 | zstream->next_in = avpkt->data + get_bits_count(gb) / 8; | |
223 | 9312 | zstream->avail_in = block_size; | |
224 | 9312 | zstream->next_out = s->tmpblock; | |
225 | 9312 | zstream->avail_out = s->block_size * 3; | |
226 | 9312 | ret = inflate(zstream, Z_FINISH); | |
227 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9312 times.
|
9312 | if (ret == Z_DATA_ERROR) { |
228 | ✗ | av_log(avctx, AV_LOG_ERROR, "Zlib resync occurred\n"); | |
229 | ✗ | inflateSync(zstream); | |
230 | ✗ | ret = inflate(zstream, Z_FINISH); | |
231 | } | ||
232 | |||
233 | if (ret != Z_OK && ret != Z_STREAM_END) { | ||
234 | //return -1; | ||
235 | } | ||
236 | |||
237 |
2/2✓ Branch 0 taken 546 times.
✓ Branch 1 taken 8766 times.
|
9312 | if (s->is_keyframe) { |
238 | 546 | s->blocks[blk_idx].pos = s->keyframedata + (get_bits_count(gb) / 8); | |
239 | 546 | s->blocks[blk_idx].size = block_size; | |
240 | } | ||
241 | |||
242 | 9312 | y_pos += s->diff_start; | |
243 | |||
244 |
2/2✓ Branch 0 taken 4671 times.
✓ Branch 1 taken 4641 times.
|
9312 | if (!s->color_depth) { |
245 | /* Flash Screen Video stores the image upside down, so copy | ||
246 | * lines to destination in reverse order. */ | ||
247 |
2/2✓ Branch 0 taken 267846 times.
✓ Branch 1 taken 4671 times.
|
272517 | for (k = 1; k <= s->diff_height; k++) { |
248 | 267846 | memcpy(s->frame->data[0] + x_pos * 3 + | |
249 | 267846 | (s->image_height - y_pos - k) * s->frame->linesize[0], | |
250 | 267846 | line, width * 3); | |
251 | /* advance source pointer to next line */ | ||
252 | 267846 | line += width * 3; | |
253 | } | ||
254 | } else { | ||
255 | /* hybrid 15-bit/palette mode */ | ||
256 | 4641 | ret = decode_hybrid(s->tmpblock, zstream->next_out, | |
257 | 4641 | s->frame->data[0], | |
258 | 4641 | s->image_height - (y_pos + 1 + s->diff_height), | |
259 | x_pos, s->diff_height, width, | ||
260 | 4641 | s->frame->linesize[0], s->pal); | |
261 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4641 times.
|
4641 | if (ret < 0) { |
262 | ✗ | av_log(avctx, AV_LOG_ERROR, "decode_hybrid failed\n"); | |
263 | ✗ | return ret; | |
264 | } | ||
265 | } | ||
266 | 9312 | skip_bits_long(gb, 8 * block_size); /* skip the consumed bits */ | |
267 | 9312 | return 0; | |
268 | } | ||
269 | |||
270 | 409 | static int flashsv_decode_frame(AVCodecContext *avctx, AVFrame *rframe, | |
271 | int *got_frame, AVPacket *avpkt) | ||
272 | { | ||
273 | 409 | int buf_size = avpkt->size; | |
274 | 409 | FlashSVContext *s = avctx->priv_data; | |
275 | int h_blocks, v_blocks, h_part, v_part, i, j, ret; | ||
276 | GetBitContext gb; | ||
277 | 409 | int last_blockwidth = s->block_width; | |
278 | 409 | int last_blockheight= s->block_height; | |
279 | |||
280 | /* no supplementary picture */ | ||
281 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 409 times.
|
409 | if (buf_size == 0) |
282 | ✗ | return 0; | |
283 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 409 times.
|
409 | if (buf_size < 4) |
284 | ✗ | return -1; | |
285 | |||
286 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 409 times.
|
409 | if ((ret = init_get_bits8(&gb, avpkt->data, buf_size)) < 0) |
287 | ✗ | return ret; | |
288 | |||
289 | /* start to parse the bitstream */ | ||
290 | 409 | s->block_width = 16 * (get_bits(&gb, 4) + 1); | |
291 | 409 | s->image_width = get_bits(&gb, 12); | |
292 | 409 | s->block_height = 16 * (get_bits(&gb, 4) + 1); | |
293 | 409 | s->image_height = get_bits(&gb, 12); | |
294 | |||
295 |
2/2✓ Branch 0 taken 392 times.
✓ Branch 1 taken 17 times.
|
409 | if ( last_blockwidth != s->block_width |
296 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 392 times.
|
392 | || last_blockheight!= s->block_height) |
297 | 17 | av_freep(&s->blocks); | |
298 | |||
299 |
2/2✓ Branch 0 taken 204 times.
✓ Branch 1 taken 205 times.
|
409 | if (s->ver == 2) { |
300 | 204 | skip_bits(&gb, 6); | |
301 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 204 times.
|
204 | if (get_bits1(&gb)) { |
302 | ✗ | avpriv_request_sample(avctx, "iframe"); | |
303 | ✗ | return AVERROR_PATCHWELCOME; | |
304 | } | ||
305 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 204 times.
|
204 | if (get_bits1(&gb)) { |
306 | ✗ | avpriv_request_sample(avctx, "Custom palette"); | |
307 | ✗ | return AVERROR_PATCHWELCOME; | |
308 | } | ||
309 | } | ||
310 | |||
311 | /* calculate number of blocks and size of border (partial) blocks */ | ||
312 | 409 | h_blocks = s->image_width / s->block_width; | |
313 | 409 | h_part = s->image_width % s->block_width; | |
314 | 409 | v_blocks = s->image_height / s->block_height; | |
315 | 409 | v_part = s->image_height % s->block_height; | |
316 | |||
317 | /* the block size could change between frames, make sure the buffer | ||
318 | * is large enough, if not, get a larger one */ | ||
319 |
2/2✓ Branch 0 taken 17 times.
✓ Branch 1 taken 392 times.
|
409 | if (s->block_size < s->block_width * s->block_height) { |
320 | 17 | int tmpblock_size = 3 * s->block_width * s->block_height, err; | |
321 | |||
322 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 17 times.
|
17 | if ((err = av_reallocp(&s->tmpblock, tmpblock_size)) < 0) { |
323 | ✗ | s->block_size = 0; | |
324 | ✗ | av_log(avctx, AV_LOG_ERROR, | |
325 | "Cannot allocate decompression buffer.\n"); | ||
326 | ✗ | return err; | |
327 | } | ||
328 | } | ||
329 | 409 | s->block_size = s->block_width * s->block_height; | |
330 | |||
331 | /* initialize the image size once */ | ||
332 |
3/4✓ Branch 0 taken 9 times.
✓ Branch 1 taken 400 times.
✓ Branch 2 taken 9 times.
✗ Branch 3 not taken.
|
409 | if (avctx->width == 0 && avctx->height == 0) { |
333 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 9 times.
|
9 | if ((ret = ff_set_dimensions(avctx, s->image_width, s->image_height)) < 0) |
334 | ✗ | return ret; | |
335 | } | ||
336 | |||
337 | /* check for changes of image width and image height */ | ||
338 |
2/4✓ Branch 0 taken 409 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 409 times.
|
409 | if (avctx->width != s->image_width || avctx->height != s->image_height) { |
339 | ✗ | av_log(avctx, AV_LOG_ERROR, | |
340 | "Frame width or height differs from first frame!\n"); | ||
341 | ✗ | av_log(avctx, AV_LOG_ERROR, "fh = %d, fv %d vs ch = %d, cv = %d\n", | |
342 | avctx->height, avctx->width, s->image_height, s->image_width); | ||
343 | ✗ | return AVERROR_INVALIDDATA; | |
344 | } | ||
345 | |||
346 | /* we care for keyframes only in Screen Video v2 */ | ||
347 |
4/4✓ Branch 0 taken 229 times.
✓ Branch 1 taken 180 times.
✓ Branch 2 taken 24 times.
✓ Branch 3 taken 205 times.
|
409 | s->is_keyframe = (avpkt->flags & AV_PKT_FLAG_KEY) && (s->ver == 2); |
348 |
2/2✓ Branch 0 taken 24 times.
✓ Branch 1 taken 385 times.
|
409 | if (s->is_keyframe) { |
349 | 24 | int err = av_buffer_replace(&s->keyframedata_buf, avpkt->buf); | |
350 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 24 times.
|
24 | if (err < 0) |
351 | ✗ | return err; | |
352 | 24 | s->keyframedata = avpkt->data; | |
353 |
2/2✓ Branch 0 taken 16 times.
✓ Branch 1 taken 8 times.
|
24 | if (s->blocks) |
354 | 16 | memset(s->blocks, 0, (v_blocks + !!v_part) * (h_blocks + !!h_part) * | |
355 | sizeof(s->blocks[0])); | ||
356 | } | ||
357 |
4/4✓ Branch 0 taken 204 times.
✓ Branch 1 taken 205 times.
✓ Branch 2 taken 8 times.
✓ Branch 3 taken 196 times.
|
409 | if(s->ver == 2 && !s->blocks) |
358 | 8 | s->blocks = av_mallocz((v_blocks + !!v_part) * (h_blocks + !!h_part) * | |
359 | sizeof(s->blocks[0])); | ||
360 | |||
361 | ff_dlog(avctx, "image: %dx%d block: %dx%d num: %dx%d part: %dx%d\n", | ||
362 | s->image_width, s->image_height, s->block_width, s->block_height, | ||
363 | h_blocks, v_blocks, h_part, v_part); | ||
364 | |||
365 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 409 times.
|
409 | if ((ret = ff_reget_buffer(avctx, s->frame, 0)) < 0) |
366 | ✗ | return ret; | |
367 | |||
368 | /* loop over all block columns */ | ||
369 |
2/2✓ Branch 0 taken 1637 times.
✓ Branch 1 taken 409 times.
|
2046 | for (j = 0; j < v_blocks + (v_part ? 1 : 0); j++) { |
370 | |||
371 | 1637 | int y_pos = j * s->block_height; // vertical position in frame | |
372 |
2/2✓ Branch 0 taken 1228 times.
✓ Branch 1 taken 409 times.
|
1637 | int cur_blk_height = (j < v_blocks) ? s->block_height : v_part; |
373 | |||
374 | /* loop over all block rows */ | ||
375 |
2/2✓ Branch 0 taken 9312 times.
✓ Branch 1 taken 1637 times.
|
10949 | for (i = 0; i < h_blocks + (h_part ? 1 : 0); i++) { |
376 | 9312 | int x_pos = i * s->block_width; // horizontal position in frame | |
377 |
2/2✓ Branch 0 taken 7675 times.
✓ Branch 1 taken 1637 times.
|
9312 | int cur_blk_width = (i < h_blocks) ? s->block_width : h_part; |
378 | 9312 | int has_diff = 0; | |
379 | |||
380 | /* get the size of the compressed zlib chunk */ | ||
381 | 9312 | int size = get_bits(&gb, 16); | |
382 | |||
383 | 9312 | s->color_depth = 0; | |
384 | 9312 | s->zlibprime_curr = 0; | |
385 | 9312 | s->zlibprime_prev = 0; | |
386 | 9312 | s->diff_start = 0; | |
387 | 9312 | s->diff_height = cur_blk_height; | |
388 | |||
389 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 9312 times.
|
9312 | if (8 * size > get_bits_left(&gb)) { |
390 | ✗ | av_frame_unref(s->frame); | |
391 | ✗ | return AVERROR_INVALIDDATA; | |
392 | } | ||
393 | |||
394 |
3/4✓ Branch 0 taken 4641 times.
✓ Branch 1 taken 4671 times.
✓ Branch 2 taken 4641 times.
✗ Branch 3 not taken.
|
9312 | if (s->ver == 2 && size) { |
395 | 4641 | skip_bits(&gb, 3); | |
396 | 4641 | s->color_depth = get_bits(&gb, 2); | |
397 | 4641 | has_diff = get_bits1(&gb); | |
398 | 4641 | s->zlibprime_curr = get_bits1(&gb); | |
399 | 4641 | s->zlibprime_prev = get_bits1(&gb); | |
400 | |||
401 |
2/4✓ Branch 0 taken 4641 times.
✗ Branch 1 not taken.
✗ Branch 2 not taken.
✓ Branch 3 taken 4641 times.
|
4641 | if (s->color_depth != 0 && s->color_depth != 2) { |
402 | ✗ | av_log(avctx, AV_LOG_ERROR, | |
403 | "%dx%d invalid color depth %d\n", | ||
404 | i, j, s->color_depth); | ||
405 | ✗ | return AVERROR_INVALIDDATA; | |
406 | } | ||
407 | |||
408 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4641 times.
|
4641 | if (has_diff) { |
409 | ✗ | if (size < 3) { | |
410 | ✗ | av_log(avctx, AV_LOG_ERROR, "size too small for diff\n"); | |
411 | ✗ | return AVERROR_INVALIDDATA; | |
412 | } | ||
413 | ✗ | if (!s->keyframe) { | |
414 | ✗ | av_log(avctx, AV_LOG_ERROR, | |
415 | "Inter frame without keyframe\n"); | ||
416 | ✗ | return AVERROR_INVALIDDATA; | |
417 | } | ||
418 | ✗ | s->diff_start = get_bits(&gb, 8); | |
419 | ✗ | s->diff_height = get_bits(&gb, 8); | |
420 | ✗ | if (s->diff_start + s->diff_height > cur_blk_height) { | |
421 | ✗ | av_log(avctx, AV_LOG_ERROR, | |
422 | "Block parameters invalid: %d + %d > %d\n", | ||
423 | s->diff_start, s->diff_height, cur_blk_height); | ||
424 | ✗ | return AVERROR_INVALIDDATA; | |
425 | } | ||
426 | ✗ | av_log(avctx, AV_LOG_DEBUG, | |
427 | "%dx%d diff start %d height %d\n", | ||
428 | i, j, s->diff_start, s->diff_height); | ||
429 | ✗ | size -= 2; | |
430 | } | ||
431 | |||
432 |
2/2✓ Branch 0 taken 4095 times.
✓ Branch 1 taken 546 times.
|
4641 | if (s->zlibprime_prev) |
433 | 4095 | av_log(avctx, AV_LOG_DEBUG, "%dx%d zlibprime_prev\n", i, j); | |
434 | |||
435 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 4641 times.
|
4641 | if (s->zlibprime_curr) { |
436 | ✗ | int col = get_bits(&gb, 8); | |
437 | ✗ | int row = get_bits(&gb, 8); | |
438 | ✗ | av_log(avctx, AV_LOG_DEBUG, "%dx%d zlibprime_curr %dx%d\n", | |
439 | i, j, col, row); | ||
440 | ✗ | if (size < 3) { | |
441 | ✗ | av_log(avctx, AV_LOG_ERROR, "size too small for zlibprime_curr\n"); | |
442 | ✗ | return AVERROR_INVALIDDATA; | |
443 | } | ||
444 | ✗ | size -= 2; | |
445 | ✗ | avpriv_request_sample(avctx, "zlibprime_curr"); | |
446 | ✗ | return AVERROR_PATCHWELCOME; | |
447 | } | ||
448 |
1/6✗ Branch 0 not taken.
✓ Branch 1 taken 4641 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
✗ Branch 4 not taken.
✗ Branch 5 not taken.
|
4641 | if (!s->blocks && (s->zlibprime_curr || s->zlibprime_prev)) { |
449 | ✗ | av_log(avctx, AV_LOG_ERROR, | |
450 | "no data available for zlib priming\n"); | ||
451 | ✗ | return AVERROR_INVALIDDATA; | |
452 | } | ||
453 | 4641 | size--; // account for flags byte | |
454 | } | ||
455 | |||
456 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9312 times.
|
9312 | if (has_diff) { |
457 | int k; | ||
458 | ✗ | int off = (s->image_height - y_pos - 1) * s->frame->linesize[0]; | |
459 | |||
460 | ✗ | for (k = 0; k < cur_blk_height; k++) { | |
461 | ✗ | int x = off - k * s->frame->linesize[0] + x_pos * 3; | |
462 | ✗ | memcpy(s->frame->data[0] + x, s->keyframe + x, | |
463 | ✗ | cur_blk_width * 3); | |
464 | } | ||
465 | } | ||
466 | |||
467 | /* skip unchanged blocks, which have size 0 */ | ||
468 |
1/2✓ Branch 0 taken 9312 times.
✗ Branch 1 not taken.
|
9312 | if (size) { |
469 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 9312 times.
|
9312 | if (flashsv_decode_block(avctx, avpkt, &gb, size, |
470 | cur_blk_width, cur_blk_height, | ||
471 | x_pos, y_pos, | ||
472 | 9312 | i + j * (h_blocks + !!h_part))) | |
473 | ✗ | av_log(avctx, AV_LOG_ERROR, | |
474 | "error in decompression of block %dx%d\n", i, j); | ||
475 | } | ||
476 | } | ||
477 | } | ||
478 |
3/4✓ Branch 0 taken 24 times.
✓ Branch 1 taken 385 times.
✓ Branch 2 taken 24 times.
✗ Branch 3 not taken.
|
409 | if (s->is_keyframe && s->ver == 2) { |
479 |
2/2✓ Branch 0 taken 8 times.
✓ Branch 1 taken 16 times.
|
24 | if (!s->keyframe) { |
480 | 8 | s->keyframe = av_malloc(s->frame->linesize[0] * avctx->height); | |
481 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
|
8 | if (!s->keyframe) { |
482 | ✗ | av_log(avctx, AV_LOG_ERROR, "Cannot allocate image data\n"); | |
483 | ✗ | return AVERROR(ENOMEM); | |
484 | } | ||
485 | } | ||
486 | 24 | memcpy(s->keyframe, s->frame->data[0], | |
487 | 24 | s->frame->linesize[0] * avctx->height); | |
488 | } | ||
489 | |||
490 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 409 times.
|
409 | if ((ret = av_frame_ref(rframe, s->frame)) < 0) |
491 | ✗ | return ret; | |
492 | |||
493 | 409 | *got_frame = 1; | |
494 | |||
495 |
1/2✗ Branch 1 not taken.
✓ Branch 2 taken 409 times.
|
409 | if ((get_bits_count(&gb) / 8) != buf_size) |
496 | ✗ | av_log(avctx, AV_LOG_ERROR, "buffer not fully consumed (%d != %d)\n", | |
497 | ✗ | buf_size, (get_bits_count(&gb) / 8)); | |
498 | |||
499 | /* report that the buffer was completely consumed */ | ||
500 | 409 | return buf_size; | |
501 | } | ||
502 | |||
503 | #if CONFIG_FLASHSV_DECODER | ||
504 | const FFCodec ff_flashsv_decoder = { | ||
505 | .p.name = "flashsv", | ||
506 | CODEC_LONG_NAME("Flash Screen Video v1"), | ||
507 | .p.type = AVMEDIA_TYPE_VIDEO, | ||
508 | .p.id = AV_CODEC_ID_FLASHSV, | ||
509 | .priv_data_size = sizeof(FlashSVContext), | ||
510 | .init = flashsv_decode_init, | ||
511 | .close = flashsv_decode_end, | ||
512 | FF_CODEC_DECODE_CB(flashsv_decode_frame), | ||
513 | .p.capabilities = AV_CODEC_CAP_DR1, | ||
514 | .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, | ||
515 | }; | ||
516 | #endif /* CONFIG_FLASHSV_DECODER */ | ||
517 | |||
518 | #if CONFIG_FLASHSV2_DECODER | ||
519 | static const uint32_t ff_flashsv2_default_palette[128] = { | ||
520 | 0x000000, 0x333333, 0x666666, 0x999999, 0xCCCCCC, 0xFFFFFF, | ||
521 | 0x330000, 0x660000, 0x990000, 0xCC0000, 0xFF0000, 0x003300, | ||
522 | 0x006600, 0x009900, 0x00CC00, 0x00FF00, 0x000033, 0x000066, | ||
523 | 0x000099, 0x0000CC, 0x0000FF, 0x333300, 0x666600, 0x999900, | ||
524 | 0xCCCC00, 0xFFFF00, 0x003333, 0x006666, 0x009999, 0x00CCCC, | ||
525 | 0x00FFFF, 0x330033, 0x660066, 0x990099, 0xCC00CC, 0xFF00FF, | ||
526 | 0xFFFF33, 0xFFFF66, 0xFFFF99, 0xFFFFCC, 0xFF33FF, 0xFF66FF, | ||
527 | 0xFF99FF, 0xFFCCFF, 0x33FFFF, 0x66FFFF, 0x99FFFF, 0xCCFFFF, | ||
528 | 0xCCCC33, 0xCCCC66, 0xCCCC99, 0xCCCCFF, 0xCC33CC, 0xCC66CC, | ||
529 | 0xCC99CC, 0xCCFFCC, 0x33CCCC, 0x66CCCC, 0x99CCCC, 0xFFCCCC, | ||
530 | 0x999933, 0x999966, 0x9999CC, 0x9999FF, 0x993399, 0x996699, | ||
531 | 0x99CC99, 0x99FF99, 0x339999, 0x669999, 0xCC9999, 0xFF9999, | ||
532 | 0x666633, 0x666699, 0x6666CC, 0x6666FF, 0x663366, 0x669966, | ||
533 | 0x66CC66, 0x66FF66, 0x336666, 0x996666, 0xCC6666, 0xFF6666, | ||
534 | 0x333366, 0x333399, 0x3333CC, 0x3333FF, 0x336633, 0x339933, | ||
535 | 0x33CC33, 0x33FF33, 0x663333, 0x993333, 0xCC3333, 0xFF3333, | ||
536 | 0x003366, 0x336600, 0x660033, 0x006633, 0x330066, 0x663300, | ||
537 | 0x336699, 0x669933, 0x993366, 0x339966, 0x663399, 0x996633, | ||
538 | 0x6699CC, 0x99CC66, 0xCC6699, 0x66CC99, 0x9966CC, 0xCC9966, | ||
539 | 0x99CCFF, 0xCCFF99, 0xFF99CC, 0x99FFCC, 0xCC99FF, 0xFFCC99, | ||
540 | 0x111111, 0x222222, 0x444444, 0x555555, 0xAAAAAA, 0xBBBBBB, | ||
541 | 0xDDDDDD, 0xEEEEEE | ||
542 | }; | ||
543 | |||
544 | 8 | static av_cold int flashsv2_decode_init(AVCodecContext *avctx) | |
545 | { | ||
546 | 8 | FlashSVContext *s = avctx->priv_data; | |
547 | int ret; | ||
548 | |||
549 | 8 | ret = flashsv_decode_init(avctx); | |
550 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 8 times.
|
8 | if (ret < 0) |
551 | ✗ | return ret; | |
552 | 8 | s->pal = ff_flashsv2_default_palette; | |
553 | 8 | s->ver = 2; | |
554 | |||
555 | 8 | return 0; | |
556 | } | ||
557 | |||
558 | 8 | static av_cold int flashsv2_decode_end(AVCodecContext *avctx) | |
559 | { | ||
560 | 8 | FlashSVContext *s = avctx->priv_data; | |
561 | |||
562 | 8 | av_buffer_unref(&s->keyframedata_buf); | |
563 | 8 | s->keyframedata = NULL; | |
564 | 8 | av_freep(&s->blocks); | |
565 | 8 | av_freep(&s->keyframe); | |
566 | 8 | flashsv_decode_end(avctx); | |
567 | |||
568 | 8 | return 0; | |
569 | } | ||
570 | |||
571 | const FFCodec ff_flashsv2_decoder = { | ||
572 | .p.name = "flashsv2", | ||
573 | CODEC_LONG_NAME("Flash Screen Video v2"), | ||
574 | .p.type = AVMEDIA_TYPE_VIDEO, | ||
575 | .p.id = AV_CODEC_ID_FLASHSV2, | ||
576 | .priv_data_size = sizeof(FlashSVContext), | ||
577 | .init = flashsv2_decode_init, | ||
578 | .close = flashsv2_decode_end, | ||
579 | FF_CODEC_DECODE_CB(flashsv_decode_frame), | ||
580 | .p.capabilities = AV_CODEC_CAP_DR1, | ||
581 | .caps_internal = FF_CODEC_CAP_INIT_CLEANUP, | ||
582 | }; | ||
583 | #endif /* CONFIG_FLASHSV2_DECODER */ | ||
584 |