Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4349 | Serge | 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 |
||
37 | #include |
||
38 | #include |
||
39 | |||
40 | #include "libavutil/intreadwrite.h" |
||
41 | #include "avcodec.h" |
||
42 | #include "bytestream.h" |
||
43 | #include "get_bits.h" |
||
44 | #include "internal.h" |
||
45 | |||
46 | typedef struct BlockInfo { |
||
47 | uint8_t *pos; |
||
48 | int size; |
||
49 | } BlockInfo; |
||
50 | |||
51 | typedef struct FlashSVContext { |
||
52 | AVCodecContext *avctx; |
||
53 | AVFrame frame; |
||
54 | int image_width, image_height; |
||
55 | int block_width, block_height; |
||
56 | uint8_t *tmpblock; |
||
57 | int block_size; |
||
58 | z_stream zstream; |
||
59 | int ver; |
||
60 | const uint32_t *pal; |
||
61 | int is_keyframe; |
||
62 | uint8_t *keyframedata; |
||
63 | uint8_t *keyframe; |
||
64 | BlockInfo *blocks; |
||
65 | uint8_t *deflate_block; |
||
66 | int deflate_block_size; |
||
67 | int color_depth; |
||
68 | int zlibprime_curr, zlibprime_prev; |
||
69 | int diff_start, diff_height; |
||
70 | } FlashSVContext; |
||
71 | |||
72 | |||
73 | static int decode_hybrid(const uint8_t *sptr, uint8_t *dptr, int dx, int dy, |
||
74 | int h, int w, int stride, const uint32_t *pal) |
||
75 | { |
||
76 | int x, y; |
||
77 | const uint8_t *orig_src = sptr; |
||
78 | |||
79 | for (y = dx+h; y > dx; y--) { |
||
80 | uint8_t *dst = dptr + (y * stride) + dy * 3; |
||
81 | for (x = 0; x < w; x++) { |
||
82 | if (*sptr & 0x80) { |
||
83 | /* 15-bit color */ |
||
84 | unsigned c = AV_RB16(sptr) & ~0x8000; |
||
85 | unsigned b = c & 0x1F; |
||
86 | unsigned g = (c >> 5) & 0x1F; |
||
87 | unsigned r = c >> 10; |
||
88 | /* 000aaabb -> aaabbaaa */ |
||
89 | *dst++ = (b << 3) | (b >> 2); |
||
90 | *dst++ = (g << 3) | (g >> 2); |
||
91 | *dst++ = (r << 3) | (r >> 2); |
||
92 | sptr += 2; |
||
93 | } else { |
||
94 | /* palette index */ |
||
95 | uint32_t c = pal[*sptr++]; |
||
96 | bytestream_put_le24(&dst, c); |
||
97 | } |
||
98 | } |
||
99 | } |
||
100 | return sptr - orig_src; |
||
101 | } |
||
102 | |||
103 | static av_cold int flashsv_decode_init(AVCodecContext *avctx) |
||
104 | { |
||
105 | FlashSVContext *s = avctx->priv_data; |
||
106 | int zret; // Zlib return code |
||
107 | |||
108 | s->avctx = avctx; |
||
109 | s->zstream.zalloc = Z_NULL; |
||
110 | s->zstream.zfree = Z_NULL; |
||
111 | s->zstream.opaque = Z_NULL; |
||
112 | zret = inflateInit(&s->zstream); |
||
113 | if (zret != Z_OK) { |
||
114 | av_log(avctx, AV_LOG_ERROR, "Inflate init error: %d\n", zret); |
||
115 | return 1; |
||
116 | } |
||
117 | avctx->pix_fmt = AV_PIX_FMT_BGR24; |
||
118 | avcodec_get_frame_defaults(&s->frame); |
||
119 | |||
120 | return 0; |
||
121 | } |
||
122 | |||
123 | |||
124 | static int flashsv2_prime(FlashSVContext *s, uint8_t *src, int size) |
||
125 | { |
||
126 | z_stream zs; |
||
127 | int zret; // Zlib return code |
||
128 | |||
129 | if (!src) |
||
130 | return AVERROR_INVALIDDATA; |
||
131 | |||
132 | zs.zalloc = NULL; |
||
133 | zs.zfree = NULL; |
||
134 | zs.opaque = NULL; |
||
135 | |||
136 | s->zstream.next_in = src; |
||
137 | s->zstream.avail_in = size; |
||
138 | s->zstream.next_out = s->tmpblock; |
||
139 | s->zstream.avail_out = s->block_size * 3; |
||
140 | inflate(&s->zstream, Z_SYNC_FLUSH); |
||
141 | |||
142 | if (deflateInit(&zs, 0) != Z_OK) |
||
143 | return -1; |
||
144 | zs.next_in = s->tmpblock; |
||
145 | zs.avail_in = s->block_size * 3 - s->zstream.avail_out; |
||
146 | zs.next_out = s->deflate_block; |
||
147 | zs.avail_out = s->deflate_block_size; |
||
148 | deflate(&zs, Z_SYNC_FLUSH); |
||
149 | deflateEnd(&zs); |
||
150 | |||
151 | if ((zret = inflateReset(&s->zstream)) != Z_OK) { |
||
152 | av_log(s->avctx, AV_LOG_ERROR, "Inflate reset error: %d\n", zret); |
||
153 | return AVERROR_UNKNOWN; |
||
154 | } |
||
155 | |||
156 | s->zstream.next_in = s->deflate_block; |
||
157 | s->zstream.avail_in = s->deflate_block_size - zs.avail_out; |
||
158 | s->zstream.next_out = s->tmpblock; |
||
159 | s->zstream.avail_out = s->block_size * 3; |
||
160 | inflate(&s->zstream, Z_SYNC_FLUSH); |
||
161 | |||
162 | return 0; |
||
163 | } |
||
164 | |||
165 | static int flashsv_decode_block(AVCodecContext *avctx, AVPacket *avpkt, |
||
166 | GetBitContext *gb, int block_size, |
||
167 | int width, int height, int x_pos, int y_pos, |
||
168 | int blk_idx) |
||
169 | { |
||
170 | struct FlashSVContext *s = avctx->priv_data; |
||
171 | uint8_t *line = s->tmpblock; |
||
172 | int k; |
||
173 | int ret = inflateReset(&s->zstream); |
||
174 | if (ret != Z_OK) { |
||
175 | av_log(avctx, AV_LOG_ERROR, "Inflate reset error: %d\n", ret); |
||
176 | return AVERROR_UNKNOWN; |
||
177 | } |
||
178 | if (s->zlibprime_curr || s->zlibprime_prev) { |
||
179 | ret = flashsv2_prime(s, |
||
180 | s->blocks[blk_idx].pos, |
||
181 | s->blocks[blk_idx].size); |
||
182 | if (ret < 0) |
||
183 | return ret; |
||
184 | } |
||
185 | s->zstream.next_in = avpkt->data + get_bits_count(gb) / 8; |
||
186 | s->zstream.avail_in = block_size; |
||
187 | s->zstream.next_out = s->tmpblock; |
||
188 | s->zstream.avail_out = s->block_size * 3; |
||
189 | ret = inflate(&s->zstream, Z_FINISH); |
||
190 | if (ret == Z_DATA_ERROR) { |
||
191 | av_log(avctx, AV_LOG_ERROR, "Zlib resync occurred\n"); |
||
192 | inflateSync(&s->zstream); |
||
193 | ret = inflate(&s->zstream, Z_FINISH); |
||
194 | } |
||
195 | |||
196 | if (ret != Z_OK && ret != Z_STREAM_END) { |
||
197 | //return -1; |
||
198 | } |
||
199 | |||
200 | if (s->is_keyframe) { |
||
201 | s->blocks[blk_idx].pos = s->keyframedata + (get_bits_count(gb) / 8); |
||
202 | s->blocks[blk_idx].size = block_size; |
||
203 | } |
||
204 | if (!s->color_depth) { |
||
205 | /* Flash Screen Video stores the image upside down, so copy |
||
206 | * lines to destination in reverse order. */ |
||
207 | for (k = 1; k <= s->diff_height; k++) { |
||
208 | memcpy(s->frame.data[0] + x_pos * 3 + |
||
209 | (s->image_height - y_pos - s->diff_start - k) * s->frame.linesize[0], |
||
210 | line, width * 3); |
||
211 | /* advance source pointer to next line */ |
||
212 | line += width * 3; |
||
213 | } |
||
214 | } else { |
||
215 | /* hybrid 15-bit/palette mode */ |
||
216 | decode_hybrid(s->tmpblock, s->frame.data[0], |
||
217 | s->image_height - (y_pos + 1 + s->diff_start + s->diff_height), |
||
218 | x_pos, s->diff_height, width, |
||
219 | s->frame.linesize[0], s->pal); |
||
220 | } |
||
221 | skip_bits_long(gb, 8 * block_size); /* skip the consumed bits */ |
||
222 | return 0; |
||
223 | } |
||
224 | |||
225 | static int calc_deflate_block_size(int tmpblock_size) |
||
226 | { |
||
227 | z_stream zstream; |
||
228 | int size; |
||
229 | |||
230 | zstream.zalloc = Z_NULL; |
||
231 | zstream.zfree = Z_NULL; |
||
232 | zstream.opaque = Z_NULL; |
||
233 | if (deflateInit(&zstream, 0) != Z_OK) |
||
234 | return -1; |
||
235 | size = deflateBound(&zstream, tmpblock_size); |
||
236 | deflateEnd(&zstream); |
||
237 | |||
238 | return size; |
||
239 | } |
||
240 | |||
241 | static int flashsv_decode_frame(AVCodecContext *avctx, void *data, |
||
242 | int *got_frame, AVPacket *avpkt) |
||
243 | { |
||
244 | int buf_size = avpkt->size; |
||
245 | FlashSVContext *s = avctx->priv_data; |
||
246 | int h_blocks, v_blocks, h_part, v_part, i, j, ret; |
||
247 | GetBitContext gb; |
||
248 | int last_blockwidth = s->block_width; |
||
249 | int last_blockheight= s->block_height; |
||
250 | |||
251 | /* no supplementary picture */ |
||
252 | if (buf_size == 0) |
||
253 | return 0; |
||
254 | if (buf_size < 4) |
||
255 | return -1; |
||
256 | |||
257 | init_get_bits(&gb, avpkt->data, buf_size * 8); |
||
258 | |||
259 | /* start to parse the bitstream */ |
||
260 | s->block_width = 16 * (get_bits(&gb, 4) + 1); |
||
261 | s->image_width = get_bits(&gb, 12); |
||
262 | s->block_height = 16 * (get_bits(&gb, 4) + 1); |
||
263 | s->image_height = get_bits(&gb, 12); |
||
264 | |||
265 | if ( last_blockwidth != s->block_width |
||
266 | || last_blockheight!= s->block_height) |
||
267 | av_freep(&s->blocks); |
||
268 | |||
269 | if (s->ver == 2) { |
||
270 | skip_bits(&gb, 6); |
||
271 | if (get_bits1(&gb)) { |
||
272 | avpriv_request_sample(avctx, "iframe"); |
||
273 | return AVERROR_PATCHWELCOME; |
||
274 | } |
||
275 | if (get_bits1(&gb)) { |
||
276 | avpriv_request_sample(avctx, "Custom palette"); |
||
277 | return AVERROR_PATCHWELCOME; |
||
278 | } |
||
279 | } |
||
280 | |||
281 | /* calculate number of blocks and size of border (partial) blocks */ |
||
282 | h_blocks = s->image_width / s->block_width; |
||
283 | h_part = s->image_width % s->block_width; |
||
284 | v_blocks = s->image_height / s->block_height; |
||
285 | v_part = s->image_height % s->block_height; |
||
286 | |||
287 | /* the block size could change between frames, make sure the buffer |
||
288 | * is large enough, if not, get a larger one */ |
||
289 | if (s->block_size < s->block_width * s->block_height) { |
||
290 | int tmpblock_size = 3 * s->block_width * s->block_height; |
||
291 | |||
292 | s->tmpblock = av_realloc(s->tmpblock, tmpblock_size); |
||
293 | if (!s->tmpblock) { |
||
294 | av_log(avctx, AV_LOG_ERROR, "Can't allocate decompression buffer.\n"); |
||
295 | return AVERROR(ENOMEM); |
||
296 | } |
||
297 | if (s->ver == 2) { |
||
298 | s->deflate_block_size = calc_deflate_block_size(tmpblock_size); |
||
299 | if (s->deflate_block_size <= 0) { |
||
300 | av_log(avctx, AV_LOG_ERROR, "Can't determine deflate buffer size.\n"); |
||
301 | return -1; |
||
302 | } |
||
303 | s->deflate_block = av_realloc(s->deflate_block, s->deflate_block_size); |
||
304 | if (!s->deflate_block) { |
||
305 | av_log(avctx, AV_LOG_ERROR, "Can't allocate deflate buffer.\n"); |
||
306 | return AVERROR(ENOMEM); |
||
307 | } |
||
308 | } |
||
309 | } |
||
310 | s->block_size = s->block_width * s->block_height; |
||
311 | |||
312 | /* initialize the image size once */ |
||
313 | if (avctx->width == 0 && avctx->height == 0) { |
||
314 | avcodec_set_dimensions(avctx, s->image_width, s->image_height); |
||
315 | } |
||
316 | |||
317 | /* check for changes of image width and image height */ |
||
318 | if (avctx->width != s->image_width || avctx->height != s->image_height) { |
||
319 | av_log(avctx, AV_LOG_ERROR, |
||
320 | "Frame width or height differs from first frame!\n"); |
||
321 | av_log(avctx, AV_LOG_ERROR, "fh = %d, fv %d vs ch = %d, cv = %d\n", |
||
322 | avctx->height, avctx->width, s->image_height, s->image_width); |
||
323 | return AVERROR_INVALIDDATA; |
||
324 | } |
||
325 | |||
326 | /* we care for keyframes only in Screen Video v2 */ |
||
327 | s->is_keyframe = (avpkt->flags & AV_PKT_FLAG_KEY) && (s->ver == 2); |
||
328 | if (s->is_keyframe) { |
||
329 | s->keyframedata = av_realloc(s->keyframedata, avpkt->size); |
||
330 | memcpy(s->keyframedata, avpkt->data, avpkt->size); |
||
331 | } |
||
332 | if(s->ver == 2 && !s->blocks) |
||
333 | s->blocks = av_mallocz((v_blocks + !!v_part) * (h_blocks + !!h_part) |
||
334 | * sizeof(s->blocks[0])); |
||
335 | |||
336 | av_dlog(avctx, "image: %dx%d block: %dx%d num: %dx%d part: %dx%d\n", |
||
337 | s->image_width, s->image_height, s->block_width, s->block_height, |
||
338 | h_blocks, v_blocks, h_part, v_part); |
||
339 | |||
340 | if ((ret = ff_reget_buffer(avctx, &s->frame)) < 0) |
||
341 | return ret; |
||
342 | |||
343 | /* loop over all block columns */ |
||
344 | for (j = 0; j < v_blocks + (v_part ? 1 : 0); j++) { |
||
345 | |||
346 | int y_pos = j * s->block_height; // vertical position in frame |
||
347 | int cur_blk_height = (j < v_blocks) ? s->block_height : v_part; |
||
348 | |||
349 | /* loop over all block rows */ |
||
350 | for (i = 0; i < h_blocks + (h_part ? 1 : 0); i++) { |
||
351 | int x_pos = i * s->block_width; // horizontal position in frame |
||
352 | int cur_blk_width = (i < h_blocks) ? s->block_width : h_part; |
||
353 | int has_diff = 0; |
||
354 | |||
355 | /* get the size of the compressed zlib chunk */ |
||
356 | int size = get_bits(&gb, 16); |
||
357 | |||
358 | s->color_depth = 0; |
||
359 | s->zlibprime_curr = 0; |
||
360 | s->zlibprime_prev = 0; |
||
361 | s->diff_start = 0; |
||
362 | s->diff_height = cur_blk_height; |
||
363 | |||
364 | if (8 * size > get_bits_left(&gb)) { |
||
365 | av_frame_unref(&s->frame); |
||
366 | return AVERROR_INVALIDDATA; |
||
367 | } |
||
368 | |||
369 | if (s->ver == 2 && size) { |
||
370 | skip_bits(&gb, 3); |
||
371 | s->color_depth = get_bits(&gb, 2); |
||
372 | has_diff = get_bits1(&gb); |
||
373 | s->zlibprime_curr = get_bits1(&gb); |
||
374 | s->zlibprime_prev = get_bits1(&gb); |
||
375 | |||
376 | if (s->color_depth != 0 && s->color_depth != 2) { |
||
377 | av_log(avctx, AV_LOG_ERROR, |
||
378 | "%dx%d invalid color depth %d\n", i, j, s->color_depth); |
||
379 | return AVERROR_INVALIDDATA; |
||
380 | } |
||
381 | |||
382 | if (has_diff) { |
||
383 | if (!s->keyframe) { |
||
384 | av_log(avctx, AV_LOG_ERROR, |
||
385 | "inter frame without keyframe\n"); |
||
386 | return AVERROR_INVALIDDATA; |
||
387 | } |
||
388 | s->diff_start = get_bits(&gb, 8); |
||
389 | s->diff_height = get_bits(&gb, 8); |
||
390 | if (s->diff_start + s->diff_height > cur_blk_height) { |
||
391 | av_log(avctx, AV_LOG_ERROR, "Block parameters invalid\n"); |
||
392 | return AVERROR_INVALIDDATA; |
||
393 | } |
||
394 | av_log(avctx, AV_LOG_DEBUG, |
||
395 | "%dx%d diff start %d height %d\n", |
||
396 | i, j, s->diff_start, s->diff_height); |
||
397 | size -= 2; |
||
398 | } |
||
399 | |||
400 | if (s->zlibprime_prev) |
||
401 | av_log(avctx, AV_LOG_DEBUG, "%dx%d zlibprime_prev\n", i, j); |
||
402 | |||
403 | if (s->zlibprime_curr) { |
||
404 | int col = get_bits(&gb, 8); |
||
405 | int row = get_bits(&gb, 8); |
||
406 | av_log(avctx, AV_LOG_DEBUG, "%dx%d zlibprime_curr %dx%d\n", i, j, col, row); |
||
407 | size -= 2; |
||
408 | avpriv_request_sample(avctx, "zlibprime_curr"); |
||
409 | return AVERROR_PATCHWELCOME; |
||
410 | } |
||
411 | if (!s->blocks && (s->zlibprime_curr || s->zlibprime_prev)) { |
||
412 | av_log(avctx, AV_LOG_ERROR, "no data available for zlib " |
||
413 | "priming\n"); |
||
414 | return AVERROR_INVALIDDATA; |
||
415 | } |
||
416 | size--; // account for flags byte |
||
417 | } |
||
418 | |||
419 | if (has_diff) { |
||
420 | int k; |
||
421 | int off = (s->image_height - y_pos - 1) * s->frame.linesize[0]; |
||
422 | |||
423 | for (k = 0; k < cur_blk_height; k++) |
||
424 | memcpy(s->frame.data[0] + off - k*s->frame.linesize[0] + x_pos*3, |
||
425 | s->keyframe + off - k*s->frame.linesize[0] + x_pos*3, |
||
426 | cur_blk_width * 3); |
||
427 | } |
||
428 | |||
429 | /* skip unchanged blocks, which have size 0 */ |
||
430 | if (size) { |
||
431 | if (flashsv_decode_block(avctx, avpkt, &gb, size, |
||
432 | cur_blk_width, cur_blk_height, |
||
433 | x_pos, y_pos, |
||
434 | i + j * (h_blocks + !!h_part))) |
||
435 | av_log(avctx, AV_LOG_ERROR, |
||
436 | "error in decompression of block %dx%d\n", i, j); |
||
437 | } |
||
438 | } |
||
439 | } |
||
440 | if (s->is_keyframe && s->ver == 2) { |
||
441 | if (!s->keyframe) { |
||
442 | s->keyframe = av_malloc(s->frame.linesize[0] * avctx->height); |
||
443 | if (!s->keyframe) { |
||
444 | av_log(avctx, AV_LOG_ERROR, "Cannot allocate image data\n"); |
||
445 | return AVERROR(ENOMEM); |
||
446 | } |
||
447 | } |
||
448 | memcpy(s->keyframe, s->frame.data[0], s->frame.linesize[0] * avctx->height); |
||
449 | } |
||
450 | |||
451 | if ((ret = av_frame_ref(data, &s->frame)) < 0) |
||
452 | return ret; |
||
453 | |||
454 | *got_frame = 1; |
||
455 | |||
456 | if ((get_bits_count(&gb) / 8) != buf_size) |
||
457 | av_log(avctx, AV_LOG_ERROR, "buffer not fully consumed (%d != %d)\n", |
||
458 | buf_size, (get_bits_count(&gb) / 8)); |
||
459 | |||
460 | /* report that the buffer was completely consumed */ |
||
461 | return buf_size; |
||
462 | } |
||
463 | |||
464 | |||
465 | static av_cold int flashsv_decode_end(AVCodecContext *avctx) |
||
466 | { |
||
467 | FlashSVContext *s = avctx->priv_data; |
||
468 | inflateEnd(&s->zstream); |
||
469 | /* release the frame if needed */ |
||
470 | av_frame_unref(&s->frame); |
||
471 | |||
472 | /* free the tmpblock */ |
||
473 | av_free(s->tmpblock); |
||
474 | |||
475 | return 0; |
||
476 | } |
||
477 | |||
478 | |||
479 | #if CONFIG_FLASHSV_DECODER |
||
480 | AVCodec ff_flashsv_decoder = { |
||
481 | .name = "flashsv", |
||
482 | .long_name = NULL_IF_CONFIG_SMALL("Flash Screen Video v1"), |
||
483 | .type = AVMEDIA_TYPE_VIDEO, |
||
484 | .id = AV_CODEC_ID_FLASHSV, |
||
485 | .priv_data_size = sizeof(FlashSVContext), |
||
486 | .init = flashsv_decode_init, |
||
487 | .close = flashsv_decode_end, |
||
488 | .decode = flashsv_decode_frame, |
||
489 | .capabilities = CODEC_CAP_DR1, |
||
490 | .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_BGR24, AV_PIX_FMT_NONE }, |
||
491 | }; |
||
492 | #endif /* CONFIG_FLASHSV_DECODER */ |
||
493 | |||
494 | #if CONFIG_FLASHSV2_DECODER |
||
495 | static const uint32_t ff_flashsv2_default_palette[128] = { |
||
496 | 0x000000, 0x333333, 0x666666, 0x999999, 0xCCCCCC, 0xFFFFFF, |
||
497 | 0x330000, 0x660000, 0x990000, 0xCC0000, 0xFF0000, 0x003300, |
||
498 | 0x006600, 0x009900, 0x00CC00, 0x00FF00, 0x000033, 0x000066, |
||
499 | 0x000099, 0x0000CC, 0x0000FF, 0x333300, 0x666600, 0x999900, |
||
500 | 0xCCCC00, 0xFFFF00, 0x003333, 0x006666, 0x009999, 0x00CCCC, |
||
501 | 0x00FFFF, 0x330033, 0x660066, 0x990099, 0xCC00CC, 0xFF00FF, |
||
502 | 0xFFFF33, 0xFFFF66, 0xFFFF99, 0xFFFFCC, 0xFF33FF, 0xFF66FF, |
||
503 | 0xFF99FF, 0xFFCCFF, 0x33FFFF, 0x66FFFF, 0x99FFFF, 0xCCFFFF, |
||
504 | 0xCCCC33, 0xCCCC66, 0xCCCC99, 0xCCCCFF, 0xCC33CC, 0xCC66CC, |
||
505 | 0xCC99CC, 0xCCFFCC, 0x33CCCC, 0x66CCCC, 0x99CCCC, 0xFFCCCC, |
||
506 | 0x999933, 0x999966, 0x9999CC, 0x9999FF, 0x993399, 0x996699, |
||
507 | 0x99CC99, 0x99FF99, 0x339999, 0x669999, 0xCC9999, 0xFF9999, |
||
508 | 0x666633, 0x666699, 0x6666CC, 0x6666FF, 0x663366, 0x669966, |
||
509 | 0x66CC66, 0x66FF66, 0x336666, 0x996666, 0xCC6666, 0xFF6666, |
||
510 | 0x333366, 0x333399, 0x3333CC, 0x3333FF, 0x336633, 0x339933, |
||
511 | 0x33CC33, 0x33FF33, 0x663333, 0x993333, 0xCC3333, 0xFF3333, |
||
512 | 0x003366, 0x336600, 0x660033, 0x006633, 0x330066, 0x663300, |
||
513 | 0x336699, 0x669933, 0x993366, 0x339966, 0x663399, 0x996633, |
||
514 | 0x6699CC, 0x99CC66, 0xCC6699, 0x66CC99, 0x9966CC, 0xCC9966, |
||
515 | 0x99CCFF, 0xCCFF99, 0xFF99CC, 0x99FFCC, 0xCC99FF, 0xFFCC99, |
||
516 | 0x111111, 0x222222, 0x444444, 0x555555, 0xAAAAAA, 0xBBBBBB, |
||
517 | 0xDDDDDD, 0xEEEEEE |
||
518 | }; |
||
519 | |||
520 | static av_cold int flashsv2_decode_init(AVCodecContext *avctx) |
||
521 | { |
||
522 | FlashSVContext *s = avctx->priv_data; |
||
523 | flashsv_decode_init(avctx); |
||
524 | s->pal = ff_flashsv2_default_palette; |
||
525 | s->ver = 2; |
||
526 | |||
527 | return 0; |
||
528 | } |
||
529 | |||
530 | static av_cold int flashsv2_decode_end(AVCodecContext *avctx) |
||
531 | { |
||
532 | FlashSVContext *s = avctx->priv_data; |
||
533 | |||
534 | av_freep(&s->keyframedata); |
||
535 | av_freep(&s->blocks); |
||
536 | av_freep(&s->keyframe); |
||
537 | av_freep(&s->deflate_block); |
||
538 | flashsv_decode_end(avctx); |
||
539 | |||
540 | return 0; |
||
541 | } |
||
542 | |||
543 | AVCodec ff_flashsv2_decoder = { |
||
544 | .name = "flashsv2", |
||
545 | .long_name = NULL_IF_CONFIG_SMALL("Flash Screen Video v2"), |
||
546 | .type = AVMEDIA_TYPE_VIDEO, |
||
547 | .id = AV_CODEC_ID_FLASHSV2, |
||
548 | .priv_data_size = sizeof(FlashSVContext), |
||
549 | .init = flashsv2_decode_init, |
||
550 | .close = flashsv2_decode_end, |
||
551 | .decode = flashsv_decode_frame, |
||
552 | .capabilities = CODEC_CAP_DR1, |
||
553 | .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_BGR24, AV_PIX_FMT_NONE }, |
||
554 | }; |
||
555 | #endif /* CONFIG_FLASHSV2_DECODER */>>>>>>>=>>>=>>><>><>><>> |