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