flashsv.c 20.3 KB
Newer Older
1 2 3 4 5
/*
 * Flash Screen Video decoder
 * Copyright (C) 2004 Alex Beregszaszi
 * Copyright (C) 2006 Benjamin Larsson
 *
6 7 8
 * This file is part of FFmpeg.
 *
 * FFmpeg is free software; you can redistribute it and/or
9 10
 * modify it under the terms of the GNU Lesser General Public
 * 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 15 16 17 18
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * 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 21 22 23
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 */

/**
24
 * @file
25 26 27
 * Flash Screen Video decoder
 * @author Alex Beregszaszi
 * @author Benjamin Larsson
28 29
 * @author Daniel Verkamp
 * @author Konstantin Shishkov
30
 *
31 32 33
 * A description of the bitstream format for Flash Screen Video version 1/2
 * is part of the SWF File Format Specification (version 10), which can be
 * downloaded from http://www.adobe.com/devnet/swf.html.
34 35 36 37
 */

#include <stdio.h>
#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 47 48 49 50
typedef struct BlockInfo {
    uint8_t *pos;
    int      size;
} BlockInfo;

51 52
typedef struct FlashSVContext {
    AVCodecContext *avctx;
53
    AVFrame        *frame;
54 55 56 57 58
    int             image_width, image_height;
    int             block_width, block_height;
    uint8_t        *tmpblock;
    int             block_size;
    z_stream        zstream;
59 60 61 62 63 64 65 66 67 68 69
    int             ver;
    const uint32_t *pal;
    int             is_keyframe;
    uint8_t        *keyframedata;
    uint8_t        *keyframe;
    BlockInfo      *blocks;
    uint8_t        *deflate_block;
    int             deflate_block_size;
    int             color_depth;
    int             zlibprime_curr, zlibprime_prev;
    int             diff_start, diff_height;
70 71
} FlashSVContext;

72
static int decode_hybrid(const uint8_t *sptr, const uint8_t *sptr_end, uint8_t *dptr, int dx, int dy,
73 74 75 76 77
                         int h, int w, int stride, const uint32_t *pal)
{
    int x, y;
    const uint8_t *orig_src = sptr;

78
    for (y = dx + h; y > dx; y--) {
79 80
        uint8_t *dst = dptr + (y * stride) + dy * 3;
        for (x = 0; x < w; x++) {
81 82
            if (sptr >= sptr_end)
                return AVERROR_INVALIDDATA;
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103
            if (*sptr & 0x80) {
                /* 15-bit color */
                unsigned c = AV_RB16(sptr) & ~0x8000;
                unsigned b =  c        & 0x1F;
                unsigned g = (c >>  5) & 0x1F;
                unsigned r =  c >> 10;
                /* 000aaabb -> aaabbaaa  */
                *dst++ = (b << 3) | (b >> 2);
                *dst++ = (g << 3) | (g >> 2);
                *dst++ = (r << 3) | (r >> 2);
                sptr += 2;
            } else {
                /* palette index */
                uint32_t c = pal[*sptr++];
                bytestream_put_le24(&dst, c);
            }
        }
    }
    return sptr - orig_src;
}

104 105 106 107 108 109 110 111
static av_cold int flashsv_decode_end(AVCodecContext *avctx)
{
    FlashSVContext *s = avctx->priv_data;
    inflateEnd(&s->zstream);
    /* release the frame if needed */
    av_frame_free(&s->frame);

    /* free the tmpblock */
112
    av_freep(&s->tmpblock);
113 114 115 116

    return 0;
}

117
static av_cold int flashsv_decode_init(AVCodecContext *avctx)
118
{
119
    FlashSVContext *s = avctx->priv_data;
120 121
    int zret; // Zlib return code

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 128 129 130
    if (zret != Z_OK) {
        av_log(avctx, AV_LOG_ERROR, "Inflate init error: %d\n", zret);
        return 1;
    }
131
    avctx->pix_fmt = AV_PIX_FMT_BGR24;
132 133 134 135 136

    s->frame = av_frame_alloc();
    if (!s->frame) {
        return AVERROR(ENOMEM);
    }
137 138 139 140

    return 0;
}

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 147 148
    if (!src)
        return AVERROR_INVALIDDATA;

149 150 151 152 153 154 155 156 157 158
    zs.zalloc = NULL;
    zs.zfree  = NULL;
    zs.opaque = NULL;

    s->zstream.next_in   = src;
    s->zstream.avail_in  = size;
    s->zstream.next_out  = s->tmpblock;
    s->zstream.avail_out = s->block_size * 3;
    inflate(&s->zstream, Z_SYNC_FLUSH);

159 160
    if (deflateInit(&zs, 0) != Z_OK)
        return -1;
161 162 163 164 165 166 167
    zs.next_in   = s->tmpblock;
    zs.avail_in  = s->block_size * 3 - s->zstream.avail_out;
    zs.next_out  = s->deflate_block;
    zs.avail_out = s->deflate_block_size;
    deflate(&zs, Z_SYNC_FLUSH);
    deflateEnd(&zs);

168 169 170 171
    if ((zret = inflateReset(&s->zstream)) != Z_OK) {
        av_log(s->avctx, AV_LOG_ERROR, "Inflate reset error: %d\n", zret);
        return AVERROR_UNKNOWN;
    }
172 173 174 175 176 177

    s->zstream.next_in   = s->deflate_block;
    s->zstream.avail_in  = s->deflate_block_size - zs.avail_out;
    s->zstream.next_out  = s->tmpblock;
    s->zstream.avail_out = s->block_size * 3;
    inflate(&s->zstream, Z_SYNC_FLUSH);
178 179

    return 0;
180 181
}

182 183
static int flashsv_decode_block(AVCodecContext *avctx, AVPacket *avpkt,
                                GetBitContext *gb, int block_size,
184 185
                                int width, int height, int x_pos, int y_pos,
                                int blk_idx)
186 187 188 189 190 191
{
    struct FlashSVContext *s = avctx->priv_data;
    uint8_t *line = s->tmpblock;
    int k;
    int ret = inflateReset(&s->zstream);
    if (ret != Z_OK) {
192 193
        av_log(avctx, AV_LOG_ERROR, "Inflate reset error: %d\n", ret);
        return AVERROR_UNKNOWN;
194
    }
195
    if (s->zlibprime_curr || s->zlibprime_prev) {
196 197 198
        ret = flashsv2_prime(s,
                             s->blocks[blk_idx].pos,
                             s->blocks[blk_idx].size);
199 200
        if (ret < 0)
            return ret;
201
    }
202 203 204 205 206 207 208 209 210 211 212 213 214 215
    s->zstream.next_in   = avpkt->data + get_bits_count(gb) / 8;
    s->zstream.avail_in  = block_size;
    s->zstream.next_out  = s->tmpblock;
    s->zstream.avail_out = s->block_size * 3;
    ret = inflate(&s->zstream, Z_FINISH);
    if (ret == Z_DATA_ERROR) {
        av_log(avctx, AV_LOG_ERROR, "Zlib resync occurred\n");
        inflateSync(&s->zstream);
        ret = inflate(&s->zstream, Z_FINISH);
    }

    if (ret != Z_OK && ret != Z_STREAM_END) {
        //return -1;
    }
216 217

    if (s->is_keyframe) {
218 219
        s->blocks[blk_idx].pos  = s->keyframedata + (get_bits_count(gb) / 8);
        s->blocks[blk_idx].size = block_size;
220
    }
221 222 223

    y_pos += s->diff_start;

224 225 226 227
    if (!s->color_depth) {
        /* Flash Screen Video stores the image upside down, so copy
         * lines to destination in reverse order. */
        for (k = 1; k <= s->diff_height; k++) {
228 229
            memcpy(s->frame->data[0] + x_pos * 3 +
                   (s->image_height - y_pos - k) * s->frame->linesize[0],
230 231 232 233 234 235
                   line, width * 3);
            /* advance source pointer to next line */
            line += width * 3;
        }
    } else {
        /* hybrid 15-bit/palette mode */
236 237
        ret = decode_hybrid(s->tmpblock, s->zstream.next_out,
                      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 242 243 244
        if (ret < 0) {
            av_log(avctx, AV_LOG_ERROR, "decode_hybrid failed\n");
            return ret;
        }
245 246 247 248 249
    }
    skip_bits_long(gb, 8 * block_size); /* skip the consumed bits */
    return 0;
}

250 251 252 253 254 255 256 257 258 259 260 261 262 263 264
static int calc_deflate_block_size(int tmpblock_size)
{
    z_stream zstream;
    int size;

    zstream.zalloc = Z_NULL;
    zstream.zfree  = Z_NULL;
    zstream.opaque = Z_NULL;
    if (deflateInit(&zstream, 0) != Z_OK)
        return -1;
    size = deflateBound(&zstream, tmpblock_size);
    deflateEnd(&zstream);

    return size;
}
265

266
static int flashsv_decode_frame(AVCodecContext *avctx, void *data,
267
                                int *got_frame, AVPacket *avpkt)
268
{
269 270
    int buf_size = avpkt->size;
    FlashSVContext *s = avctx->priv_data;
271
    int h_blocks, v_blocks, h_part, v_part, i, j, ret;
272
    GetBitContext gb;
273 274
    int last_blockwidth = s->block_width;
    int last_blockheight= s->block_height;
275 276 277 278

    /* no supplementary picture */
    if (buf_size == 0)
        return 0;
279 280
    if (buf_size < 4)
        return -1;
281

Paul B Mahol's avatar
Paul B Mahol committed
282
    if ((ret = init_get_bits8(&gb, avpkt->data, buf_size)) < 0)
283
        return ret;
284 285

    /* start to parse the bitstream */
286 287 288 289
    s->block_width  = 16 * (get_bits(&gb, 4) + 1);
    s->image_width  = get_bits(&gb, 12);
    s->block_height = 16 * (get_bits(&gb, 4) + 1);
    s->image_height = get_bits(&gb, 12);
290

291 292 293 294
    if (   last_blockwidth != s->block_width
        || last_blockheight!= s->block_height)
        av_freep(&s->blocks);

295 296 297
    if (s->ver == 2) {
        skip_bits(&gb, 6);
        if (get_bits1(&gb)) {
298
            avpriv_request_sample(avctx, "iframe");
299 300 301
            return AVERROR_PATCHWELCOME;
        }
        if (get_bits1(&gb)) {
302
            avpriv_request_sample(avctx, "Custom palette");
303 304 305 306
            return AVERROR_PATCHWELCOME;
        }
    }

307
    /* calculate number of blocks and size of border (partial) blocks */
308 309
    h_blocks = s->image_width  / s->block_width;
    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 314

    /* the block size could change between frames, make sure the buffer
     * 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 319
        if ((err = av_reallocp(&s->tmpblock, tmpblock_size)) < 0) {
            s->block_size = 0;
320 321
            av_log(avctx, AV_LOG_ERROR,
                   "Cannot allocate decompression buffer.\n");
322
            return err;
323
        }
324 325 326
        if (s->ver == 2) {
            s->deflate_block_size = calc_deflate_block_size(tmpblock_size);
            if (s->deflate_block_size <= 0) {
327 328
                av_log(avctx, AV_LOG_ERROR,
                       "Cannot determine deflate buffer size.\n");
329 330
                return -1;
            }
331 332 333 334
            if ((err = av_reallocp(&s->deflate_block, s->deflate_block_size)) < 0) {
                s->block_size = 0;
                av_log(avctx, AV_LOG_ERROR, "Cannot allocate deflate buffer.\n");
                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 343
        if ((ret = ff_set_dimensions(avctx, s->image_width, s->image_height)) < 0)
            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 351
        av_log(avctx, AV_LOG_ERROR, "fh = %d, fv %d  vs  ch = %d, cv = %d\n",
               avctx->height, avctx->width, s->image_height, s->image_width);
352
        return AVERROR_INVALIDDATA;
353 354
    }

355 356 357
    /* we care for keyframes only in Screen Video v2 */
    s->is_keyframe = (avpkt->flags & AV_PKT_FLAG_KEY) && (s->ver == 2);
    if (s->is_keyframe) {
358 359 360
        int err;
        if ((err = av_reallocp(&s->keyframedata, avpkt->size)) < 0)
            return err;
361 362
        memcpy(s->keyframedata, avpkt->data, avpkt->size);
    }
363
    if(s->ver == 2 && !s->blocks)
364 365
        s->blocks = av_mallocz((v_blocks + !!v_part) * (h_blocks + !!h_part) *
                               sizeof(s->blocks[0]));
366

367
    ff_dlog(avctx, "image: %dx%d block: %dx%d num: %dx%d part: %dx%d\n",
368 369
            s->image_width, s->image_height, s->block_width, s->block_height,
            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 378
        int y_pos  = j * s->block_height; // vertical position in frame
        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 383
            int x_pos = i * s->block_width; // horizontal position in frame
            int cur_blk_width = (i < h_blocks) ? s->block_width : h_part;
384
            int has_diff = 0;
385 386 387

            /* get the size of the compressed zlib chunk */
            int size = get_bits(&gb, 16);
388 389 390 391 392 393 394

            s->color_depth    = 0;
            s->zlibprime_curr = 0;
            s->zlibprime_prev = 0;
            s->diff_start     = 0;
            s->diff_height    = cur_blk_height;

395
            if (8 * size > get_bits_left(&gb)) {
396
                av_frame_unref(s->frame);
397
                return AVERROR_INVALIDDATA;
398
            }
399

400 401 402 403 404 405 406 407 408
            if (s->ver == 2 && size) {
                skip_bits(&gb, 3);
                s->color_depth    = get_bits(&gb, 2);
                has_diff          = get_bits1(&gb);
                s->zlibprime_curr = get_bits1(&gb);
                s->zlibprime_prev = get_bits1(&gb);

                if (s->color_depth != 0 && s->color_depth != 2) {
                    av_log(avctx, AV_LOG_ERROR,
409 410
                           "%dx%d invalid color depth %d\n",
                           i, j, s->color_depth);
411
                    return AVERROR_INVALIDDATA;
412 413 414
                }

                if (has_diff) {
415 416 417 418
                    if (size < 3) {
                        av_log(avctx, AV_LOG_ERROR, "size too small for diff\n");
                        return AVERROR_INVALIDDATA;
                    }
419 420
                    if (!s->keyframe) {
                        av_log(avctx, AV_LOG_ERROR,
421
                               "Inter frame without keyframe\n");
422 423
                        return AVERROR_INVALIDDATA;
                    }
424 425
                    s->diff_start  = get_bits(&gb, 8);
                    s->diff_height = get_bits(&gb, 8);
426
                    if (s->diff_start + s->diff_height > cur_blk_height) {
427 428 429
                        av_log(avctx, AV_LOG_ERROR,
                               "Block parameters invalid: %d + %d > %d\n",
                               s->diff_start, s->diff_height, cur_blk_height);
430 431
                        return AVERROR_INVALIDDATA;
                    }
432 433 434 435 436 437 438 439 440 441 442 443
                    av_log(avctx, AV_LOG_DEBUG,
                           "%dx%d diff start %d height %d\n",
                           i, j, s->diff_start, s->diff_height);
                    size -= 2;
                }

                if (s->zlibprime_prev)
                    av_log(avctx, AV_LOG_DEBUG, "%dx%d zlibprime_prev\n", i, j);

                if (s->zlibprime_curr) {
                    int col = get_bits(&gb, 8);
                    int row = get_bits(&gb, 8);
444 445
                    av_log(avctx, AV_LOG_DEBUG, "%dx%d zlibprime_curr %dx%d\n",
                           i, j, col, row);
446 447 448 449
                    if (size < 3) {
                        av_log(avctx, AV_LOG_ERROR, "size too small for zlibprime_curr\n");
                        return AVERROR_INVALIDDATA;
                    }
450
                    size -= 2;
451
                    avpriv_request_sample(avctx, "zlibprime_curr");
452 453
                    return AVERROR_PATCHWELCOME;
                }
454
                if (!s->blocks && (s->zlibprime_curr || s->zlibprime_prev)) {
455 456
                    av_log(avctx, AV_LOG_ERROR,
                           "no data available for zlib priming\n");
457 458
                    return AVERROR_INVALIDDATA;
                }
459 460 461 462 463
                size--; // account for flags byte
            }

            if (has_diff) {
                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 468
                    int x = off - k * s->frame->linesize[0] + x_pos * 3;
                    memcpy(s->frame->data[0] + x, s->keyframe + x,
469
                           cur_blk_width * 3);
470
                }
471 472
            }

473 474
            /* skip unchanged blocks, which have size 0 */
            if (size) {
475 476
                if (flashsv_decode_block(avctx, avpkt, &gb, size,
                                         cur_blk_width, cur_blk_height,
477 478
                                         x_pos, y_pos,
                                         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 485
    if (s->is_keyframe && s->ver == 2) {
        if (!s->keyframe) {
486
            s->keyframe = av_malloc(s->frame->linesize[0] * avctx->height);
487 488 489 490 491
            if (!s->keyframe) {
                av_log(avctx, AV_LOG_ERROR, "Cannot allocate image data\n");
                return AVERROR(ENOMEM);
            }
        }
492 493
        memcpy(s->keyframe, s->frame->data[0],
               s->frame->linesize[0] * avctx->height);
494
    }
495

496
    if ((ret = av_frame_ref(data, s->frame)) < 0)
497 498
        return ret;

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 506 507 508

    /* report that the buffer was completely consumed */
    return buf_size;
}

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 516 517 518
    .priv_data_size = sizeof(FlashSVContext),
    .init           = flashsv_decode_init,
    .close          = flashsv_decode_end,
    .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 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553
#endif /* CONFIG_FLASHSV_DECODER */

#if CONFIG_FLASHSV2_DECODER
static const uint32_t ff_flashsv2_default_palette[128] = {
    0x000000, 0x333333, 0x666666, 0x999999, 0xCCCCCC, 0xFFFFFF,
    0x330000, 0x660000, 0x990000, 0xCC0000, 0xFF0000, 0x003300,
    0x006600, 0x009900, 0x00CC00, 0x00FF00, 0x000033, 0x000066,
    0x000099, 0x0000CC, 0x0000FF, 0x333300, 0x666600, 0x999900,
    0xCCCC00, 0xFFFF00, 0x003333, 0x006666, 0x009999, 0x00CCCC,
    0x00FFFF, 0x330033, 0x660066, 0x990099, 0xCC00CC, 0xFF00FF,
    0xFFFF33, 0xFFFF66, 0xFFFF99, 0xFFFFCC, 0xFF33FF, 0xFF66FF,
    0xFF99FF, 0xFFCCFF, 0x33FFFF, 0x66FFFF, 0x99FFFF, 0xCCFFFF,
    0xCCCC33, 0xCCCC66, 0xCCCC99, 0xCCCCFF, 0xCC33CC, 0xCC66CC,
    0xCC99CC, 0xCCFFCC, 0x33CCCC, 0x66CCCC, 0x99CCCC, 0xFFCCCC,
    0x999933, 0x999966, 0x9999CC, 0x9999FF, 0x993399, 0x996699,
    0x99CC99, 0x99FF99, 0x339999, 0x669999, 0xCC9999, 0xFF9999,
    0x666633, 0x666699, 0x6666CC, 0x6666FF, 0x663366, 0x669966,
    0x66CC66, 0x66FF66, 0x336666, 0x996666, 0xCC6666, 0xFF6666,
    0x333366, 0x333399, 0x3333CC, 0x3333FF, 0x336633, 0x339933,
    0x33CC33, 0x33FF33, 0x663333, 0x993333, 0xCC3333, 0xFF3333,
    0x003366, 0x336600, 0x660033, 0x006633, 0x330066, 0x663300,
    0x336699, 0x669933, 0x993366, 0x339966, 0x663399, 0x996633,
    0x6699CC, 0x99CC66, 0xCC6699, 0x66CC99, 0x9966CC, 0xCC9966,
    0x99CCFF, 0xCCFF99, 0xFF99CC, 0x99FFCC, 0xCC99FF, 0xFFCC99,
    0x111111, 0x222222, 0x444444, 0x555555, 0xAAAAAA, 0xBBBBBB,
    0xDDDDDD, 0xEEEEEE
};

static av_cold int flashsv2_decode_init(AVCodecContext *avctx)
{
    FlashSVContext *s = avctx->priv_data;
554 555 556 557 558
    int ret;

    ret = flashsv_decode_init(avctx);
    if (ret < 0)
        return ret;
559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579
    s->pal = ff_flashsv2_default_palette;
    s->ver = 2;

    return 0;
}

static av_cold int flashsv2_decode_end(AVCodecContext *avctx)
{
    FlashSVContext *s = avctx->priv_data;

    av_freep(&s->keyframedata);
    av_freep(&s->blocks);
    av_freep(&s->keyframe);
    av_freep(&s->deflate_block);
    flashsv_decode_end(avctx);

    return 0;
}

AVCodec ff_flashsv2_decoder = {
    .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 584 585 586
    .priv_data_size = sizeof(FlashSVContext),
    .init           = flashsv2_decode_init,
    .close          = flashsv2_decode_end,
    .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 */