GCC Code Coverage Report
Directory: ../../../ffmpeg/ Exec Total Coverage
File: src/libavcodec/flashsv2enc.c Lines: 328 408 80.4 %
Date: 2020-09-21 17:35:45 Branches: 126 204 61.8 %

Line Branch Exec Source
1
/*
2
 * Flash Screen Video Version 2 encoder
3
 * Copyright (C) 2009 Joshua Warner
4
 *
5
 * This file is part of FFmpeg.
6
 *
7
 * FFmpeg is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU Lesser General Public
9
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
11
 *
12
 * FFmpeg is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with FFmpeg; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
 */
21
22
/**
23
 * @file
24
 * Flash Screen Video Version 2 encoder
25
 * @author Joshua Warner
26
 */
27
28
/* Differences from version 1 stream:
29
 * NOTE: Currently, the only player that supports version 2 streams is Adobe Flash Player itself.
30
 * * Supports sending only a range of scanlines in a block,
31
 *   indicating a difference from the corresponding block in the last keyframe.
32
 * * Supports initializing the zlib dictionary with data from the corresponding
33
 *   block in the last keyframe, to improve compression.
34
 * * Supports a hybrid 15-bit rgb / 7-bit palette color space.
35
 */
36
37
/* TODO:
38
 * Don't keep Block structures for both current frame and keyframe.
39
 * Make better heuristics for deciding stream parameters (optimum_* functions).  Currently these return constants.
40
 * Figure out how to encode palette information in the stream, choose an optimum palette at each keyframe.
41
 * Figure out how the zlibPrimeCompressCurrent flag works, implement support.
42
 * Find other sample files (that weren't generated here), develop a decoder.
43
 */
44
45
#include <stdio.h>
46
#include <stdlib.h>
47
#include <zlib.h>
48
49
#include "libavutil/imgutils.h"
50
#include "avcodec.h"
51
#include "internal.h"
52
#include "put_bits.h"
53
#include "bytestream.h"
54
55
#define HAS_IFRAME_IMAGE 0x02
56
#define HAS_PALLET_INFO 0x01
57
58
#define COLORSPACE_BGR 0x00
59
#define COLORSPACE_15_7 0x10
60
#define HAS_DIFF_BLOCKS 0x04
61
#define ZLIB_PRIME_COMPRESS_CURRENT 0x02
62
#define ZLIB_PRIME_COMPRESS_PREVIOUS 0x01
63
64
// Disables experimental "smart" parameter-choosing code, as well as the statistics that it depends on.
65
// At the moment, the "smart" code is a great example of how the parameters *shouldn't* be chosen.
66
#define FLASHSV2_DUMB
67
68
typedef struct Block {
69
    uint8_t *enc;
70
    uint8_t *sl_begin, *sl_end;
71
    int enc_size;
72
    uint8_t *data;
73
    unsigned long data_size;
74
75
    uint8_t start, len;
76
    uint8_t dirty;
77
    uint8_t col, row, width, height;
78
    uint8_t flags;
79
} Block;
80
81
typedef struct Palette {
82
    unsigned colors[128];
83
    uint8_t index[1 << 15];
84
} Palette;
85
86
typedef struct FlashSV2Context {
87
    AVCodecContext *avctx;
88
    uint8_t *current_frame;
89
    uint8_t *key_frame;
90
    uint8_t *encbuffer;
91
    uint8_t *keybuffer;
92
    uint8_t *databuffer;
93
94
    uint8_t *blockbuffer;
95
    int blockbuffer_size;
96
97
    Block *frame_blocks;
98
    Block *key_blocks;
99
    int frame_size;
100
    int blocks_size;
101
102
    int use15_7, dist, comp;
103
104
    int rows, cols;
105
106
    int last_key_frame;
107
108
    int image_width, image_height;
109
    int block_width, block_height;
110
    uint8_t flags;
111
    uint8_t use_custom_palette;
112
    uint8_t palette_type;       ///< 0=>default, 1=>custom - changed when palette regenerated.
113
    Palette palette;
114
#ifndef FLASHSV2_DUMB
115
    double tot_blocks;          ///< blocks encoded since last keyframe
116
    double diff_blocks;         ///< blocks that were different since last keyframe
117
    double tot_lines;           ///< total scanlines in image since last keyframe
118
    double diff_lines;          ///< scanlines that were different since last keyframe
119
    double raw_size;            ///< size of raw frames since last keyframe
120
    double comp_size;           ///< size of compressed data since last keyframe
121
    double uncomp_size;         ///< size of uncompressed data since last keyframe
122
123
    double total_bits;          ///< total bits written to stream so far
124
#endif
125
} FlashSV2Context;
126
127
4
static av_cold void cleanup(FlashSV2Context * s)
128
{
129
4
    av_freep(&s->encbuffer);
130
4
    av_freep(&s->keybuffer);
131
4
    av_freep(&s->databuffer);
132
4
    av_freep(&s->blockbuffer);
133
4
    av_freep(&s->current_frame);
134
4
    av_freep(&s->key_frame);
135
136
4
    av_freep(&s->frame_blocks);
137
4
    av_freep(&s->key_blocks);
138
4
}
139
140
16
static void init_blocks(FlashSV2Context * s, Block * blocks,
141
                        uint8_t * encbuf, uint8_t * databuf)
142
{
143
    int row, col;
144
    Block *b;
145
254
    for (col = 0; col < s->cols; col++) {
146
5108
        for (row = 0; row < s->rows; row++) {
147
4870
            b = blocks + (col + row * s->cols);
148
4870
            b->width = (col < s->cols - 1) ?
149
4662
                s->block_width :
150
208
                s->image_width - col * s->block_width;
151
152
4870
            b->height = (row < s->rows - 1) ?
153
4632
                s->block_height :
154
238
                s->image_height - row * s->block_height;
155
156
4870
            b->row   = row;
157
4870
            b->col   = col;
158
4870
            b->enc   = encbuf;
159
4870
            b->data  = databuf;
160
4870
            encbuf  += b->width * b->height * 3;
161
4870
            databuf += !databuf ? 0 : b->width * b->height * 6;
162
        }
163
    }
164
16
}
165
166
24
static void reset_stats(FlashSV2Context * s)
167
{
168
#ifndef FLASHSV2_DUMB
169
    s->diff_blocks = 0.1;
170
    s->tot_blocks = 1;
171
    s->diff_lines = 0.1;
172
    s->tot_lines = 1;
173
    s->raw_size = s->comp_size = s->uncomp_size = 10;
174
#endif
175
24
}
176
177
4
static av_cold int flashsv2_encode_init(AVCodecContext * avctx)
178
{
179
4
    FlashSV2Context *s = avctx->priv_data;
180
    int ret;
181
182
4
    s->avctx = avctx;
183
184
4
    s->comp = avctx->compression_level;
185
4
    if (s->comp == -1)
186
        s->comp = 9;
187

4
    if (s->comp < 0 || s->comp > 9) {
188
        av_log(avctx, AV_LOG_ERROR,
189
               "Compression level should be 0-9, not %d\n", s->comp);
190
        return AVERROR(EINVAL);
191
    }
192
193
194

4
    if ((avctx->width > 4095) || (avctx->height > 4095)) {
195
        av_log(avctx, AV_LOG_ERROR,
196
               "Input dimensions too large, input must be max 4095x4095 !\n");
197
        return AVERROR(EINVAL);
198
    }
199

4
    if ((avctx->width < 16) || (avctx->height < 16)) {
200
        av_log(avctx, AV_LOG_ERROR,
201
               "Input dimensions too small, input must be at least 16x16 !\n");
202
        return AVERROR(EINVAL);
203
    }
204
205
4
    if ((ret = av_image_check_size(avctx->width, avctx->height, 0, avctx)) < 0)
206
        return ret;
207
208
209
4
    s->last_key_frame = 0;
210
211
4
    s->image_width  = avctx->width;
212
4
    s->image_height = avctx->height;
213
214
4
    s->block_width  = (s->image_width /  12) & ~15;
215
4
    s->block_height = (s->image_height / 12) & ~15;
216
217
4
    if(!s->block_width)
218
1
        s->block_width = 1;
219
4
    if(!s->block_height)
220
1
        s->block_height = 1;
221
222
4
    s->rows = (s->image_height + s->block_height - 1) / s->block_height;
223
4
    s->cols = (s->image_width +  s->block_width -  1) / s->block_width;
224
225
4
    s->frame_size  = s->image_width * s->image_height * 3;
226
4
    s->blocks_size = s->rows * s->cols * sizeof(Block);
227
228
4
    s->encbuffer     = av_mallocz(s->frame_size);
229
4
    s->keybuffer     = av_mallocz(s->frame_size);
230
4
    s->databuffer    = av_mallocz(s->frame_size * 6);
231
4
    s->current_frame = av_mallocz(s->frame_size);
232
4
    s->key_frame     = av_mallocz(s->frame_size);
233
4
    s->frame_blocks  = av_mallocz(s->blocks_size);
234
4
    s->key_blocks    = av_mallocz(s->blocks_size);
235

4
    if (!s->encbuffer || !s->keybuffer || !s->databuffer
236

4
        || !s->current_frame || !s->key_frame || !s->key_blocks
237
4
        || !s->frame_blocks) {
238
        av_log(avctx, AV_LOG_ERROR, "Memory allocation failed.\n");
239
        return AVERROR(ENOMEM);
240
    }
241
242
4
    s->blockbuffer      = NULL;
243
4
    s->blockbuffer_size = 0;
244
245
4
    init_blocks(s, s->frame_blocks, s->encbuffer, s->databuffer);
246
4
    init_blocks(s, s->key_blocks,   s->keybuffer, 0);
247
4
    reset_stats(s);
248
#ifndef FLASHSV2_DUMB
249
    s->total_bits = 1;
250
#endif
251
252
4
    s->use_custom_palette =  0;
253
4
    s->palette_type       = -1;        // so that the palette will be generated in reconfigure_at_keyframe
254
255
4
    return 0;
256
}
257
258
20
static int new_key_frame(FlashSV2Context * s)
259
{
260
    int i;
261
20
    memcpy(s->key_blocks, s->frame_blocks, s->blocks_size);
262
20
    memcpy(s->key_frame, s->current_frame, s->frame_size);
263
264
475
    for (i = 0; i < s->rows * s->cols; i++) {
265
455
        s->key_blocks[i].enc += (s->keybuffer - s->encbuffer);
266
455
        s->key_blocks[i].sl_begin = 0;
267
455
        s->key_blocks[i].sl_end   = 0;
268
455
        s->key_blocks[i].data     = 0;
269
    }
270
20
    memcpy(s->keybuffer, s->encbuffer, s->frame_size);
271
272
20
    return 0;
273
}
274
275
static int write_palette(FlashSV2Context * s, uint8_t * buf, int buf_size)
276
{
277
    //this isn't implemented yet!  Default palette only!
278
    return -1;
279
}
280
281
200
static int write_header(FlashSV2Context * s, uint8_t * buf, int buf_size)
282
{
283
    PutBitContext pb;
284
    int buf_pos, len;
285
286
200
    if (buf_size < 5)
287
        return -1;
288
289
200
    init_put_bits(&pb, buf, buf_size);
290
291
200
    put_bits(&pb, 4, (s->block_width  >> 4) - 1);
292
200
    put_bits(&pb, 12, s->image_width);
293
200
    put_bits(&pb, 4, (s->block_height >> 4) - 1);
294
200
    put_bits(&pb, 12, s->image_height);
295
296
200
    flush_put_bits(&pb);
297
200
    buf_pos = 4;
298
299
200
    buf[buf_pos++] = s->flags;
300
301
200
    if (s->flags & HAS_PALLET_INFO) {
302
        len = write_palette(s, buf + buf_pos, buf_size - buf_pos);
303
        if (len < 0)
304
            return -1;
305
        buf_pos += len;
306
    }
307
308
200
    return buf_pos;
309
}
310
311
4550
static int write_block(Block * b, uint8_t * buf, int buf_size)
312
{
313
4550
    int buf_pos = 0;
314
4550
    unsigned block_size = b->data_size;
315
316
4550
    if (b->flags & HAS_DIFF_BLOCKS)
317
        block_size += 2;
318
4550
    if (b->flags & ZLIB_PRIME_COMPRESS_CURRENT)
319
        block_size += 2;
320
4550
    if (block_size > 0)
321
4550
        block_size += 1;
322
4550
    if (buf_size < block_size + 2)
323
        return -1;
324
325
4550
    buf[buf_pos++] = block_size >> 8;
326
4550
    buf[buf_pos++] = block_size;
327
328
4550
    if (block_size == 0)
329
        return buf_pos;
330
331
4550
    buf[buf_pos++] = b->flags;
332
333
4550
    if (b->flags & HAS_DIFF_BLOCKS) {
334
        buf[buf_pos++] = (b->start);
335
        buf[buf_pos++] = (b->len);
336
    }
337
338
4550
    if (b->flags & ZLIB_PRIME_COMPRESS_CURRENT) {
339
        //This feature of the format is poorly understood, and as of now, unused.
340
        buf[buf_pos++] = (b->col);
341
        buf[buf_pos++] = (b->row);
342
    }
343
344
4550
    memcpy(buf + buf_pos, b->data, b->data_size);
345
346
4550
    buf_pos += b->data_size;
347
348
4550
    return buf_pos;
349
}
350
351
4550
static int encode_zlib(Block * b, uint8_t * buf, unsigned long *buf_size, int comp)
352
{
353
4550
    int res = compress2(buf, buf_size, b->sl_begin, b->sl_end - b->sl_begin, comp);
354
4550
    return res == Z_OK ? 0 : -1;
355
}
356
357
4095
static int encode_zlibprime(Block * b, Block * prime, uint8_t * buf,
358
                            int *buf_size, int comp)
359
{
360
    z_stream s;
361
    int res;
362
4095
    s.zalloc = NULL;
363
4095
    s.zfree  = NULL;
364
4095
    s.opaque = NULL;
365
4095
    res = deflateInit(&s, comp);
366
4095
    if (res < 0)
367
        return -1;
368
369
4095
    s.next_in  = prime->enc;
370
4095
    s.avail_in = prime->enc_size;
371
8190
    while (s.avail_in > 0) {
372
4095
        s.next_out  = buf;
373
4095
        s.avail_out = *buf_size;
374
4095
        res = deflate(&s, Z_SYNC_FLUSH);
375
4095
        if (res < 0)
376
            return -1;
377
    }
378
379
4095
    s.next_in   = b->sl_begin;
380
4095
    s.avail_in  = b->sl_end - b->sl_begin;
381
4095
    s.next_out  = buf;
382
4095
    s.avail_out = *buf_size;
383
4095
    res = deflate(&s, Z_FINISH);
384
4095
    deflateEnd(&s);
385
4095
    *buf_size -= s.avail_out;
386
4095
    if (res != Z_STREAM_END)
387
        return -1;
388
4095
    return 0;
389
}
390
391
static int encode_bgr(Block * b, const uint8_t * src, int stride)
392
{
393
    int i;
394
    uint8_t *ptr = b->enc;
395
    for (i = 0; i < b->start; i++)
396
        memcpy(ptr + i * b->width * 3, src + i * stride, b->width * 3);
397
    b->sl_begin = ptr + i * b->width * 3;
398
    for (; i < b->start + b->len; i++)
399
        memcpy(ptr + i * b->width * 3, src + i * stride, b->width * 3);
400
    b->sl_end = ptr + i * b->width * 3;
401
    for (; i < b->height; i++)
402
        memcpy(ptr + i * b->width * 3, src + i * stride, b->width * 3);
403
    b->enc_size = ptr + i * b->width * 3 - b->enc;
404
    return b->enc_size;
405
}
406
407
15264200
static inline unsigned pixel_color15(const uint8_t * src)
408
{
409
15264200
    return (src[0] >> 3) | ((src[1] & 0xf8) << 2) | ((src[2] & 0xf8) << 7);
410
}
411
412
47305616
static inline unsigned int chroma_diff(unsigned int c1, unsigned int c2)
413
{
414
#define ABSDIFF(a,b) (abs((int)(a)-(int)(b)))
415
416
47305616
    unsigned int t1 = (c1 & 0x000000ff) + ((c1 & 0x0000ff00) >> 8) + ((c1 & 0x00ff0000) >> 16);
417
47305616
    unsigned int t2 = (c2 & 0x000000ff) + ((c2 & 0x0000ff00) >> 8) + ((c2 & 0x00ff0000) >> 16);
418
419
47305616
    return ABSDIFF(t1, t2) + ABSDIFF(c1 & 0x000000ff, c2 & 0x000000ff) +
420
94611232
        ABSDIFF((c1 & 0x0000ff00) >> 8 , (c2 & 0x0000ff00) >> 8) +
421
47305616
        ABSDIFF((c1 & 0x00ff0000) >> 16, (c2 & 0x00ff0000) >> 16);
422
}
423
424
15264200
static inline int pixel_color7_fast(Palette * palette, unsigned c15)
425
{
426
15264200
    return palette->index[c15];
427
}
428
429
131072
static int pixel_color7_slow(Palette * palette, unsigned color)
430
{
431
131072
    int i, min = 0x7fffffff;
432
131072
    int minc = -1;
433
16908288
    for (i = 0; i < 128; i++) {
434
16777216
        int c1 = palette->colors[i];
435
16777216
        int diff = chroma_diff(c1, color);
436
16777216
        if (diff < min) {
437
813324
            min = diff;
438
813324
            minc = i;
439
        }
440
    }
441
131072
    return minc;
442
}
443
444
15264200
static inline unsigned pixel_bgr(const uint8_t * src)
445
{
446
15264200
    return (src[0]) | (src[1] << 8) | (src[2] << 16);
447
}
448
449
15264200
static int write_pixel_15_7(Palette * palette, uint8_t * dest, const uint8_t * src,
450
                            int dist)
451
{
452
15264200
    unsigned c15 = pixel_color15(src);
453
15264200
    unsigned color = pixel_bgr(src);
454
15264200
    int d15 = chroma_diff(color, color & 0x00f8f8f8);
455
15264200
    int c7 = pixel_color7_fast(palette, c15);
456
15264200
    int d7 = chroma_diff(color, palette->colors[c7]);
457
15264200
    if (dist + d15 >= d7) {
458
3161177
        dest[0] = c7;
459
3161177
        return 1;
460
    } else {
461
12103023
        dest[0] = 0x80 | (c15 >> 8);
462
12103023
        dest[1] = c15 & 0xff;
463
12103023
        return 2;
464
    }
465
}
466
467
4
static int update_palette_index(Palette * palette)
468
{
469
    int r, g, b;
470
    unsigned int bgr, c15, index;
471
132
    for (r = 4; r < 256; r += 8) {
472
4224
        for (g = 4; g < 256; g += 8) {
473
135168
            for (b = 4; b < 256; b += 8) {
474
131072
                bgr = b | (g << 8) | (r << 16);
475
131072
                c15 = (b >> 3) | ((g & 0xf8) << 2) | ((r & 0xf8) << 7);
476
131072
                index = pixel_color7_slow(palette, bgr);
477
478
131072
                palette->index[c15] = index;
479
            }
480
        }
481
    }
482
4
    return 0;
483
}
484
485
static const unsigned int default_screen_video_v2_palette[128] = {
486
    0x00000000, 0x00333333, 0x00666666, 0x00999999, 0x00CCCCCC, 0x00FFFFFF,
487
    0x00330000, 0x00660000, 0x00990000, 0x00CC0000, 0x00FF0000, 0x00003300,
488
    0x00006600, 0x00009900, 0x0000CC00, 0x0000FF00, 0x00000033, 0x00000066,
489
    0x00000099, 0x000000CC, 0x000000FF, 0x00333300, 0x00666600, 0x00999900,
490
    0x00CCCC00, 0x00FFFF00, 0x00003333, 0x00006666, 0x00009999, 0x0000CCCC,
491
    0x0000FFFF, 0x00330033, 0x00660066, 0x00990099, 0x00CC00CC, 0x00FF00FF,
492
    0x00FFFF33, 0x00FFFF66, 0x00FFFF99, 0x00FFFFCC, 0x00FF33FF, 0x00FF66FF,
493
    0x00FF99FF, 0x00FFCCFF, 0x0033FFFF, 0x0066FFFF, 0x0099FFFF, 0x00CCFFFF,
494
    0x00CCCC33, 0x00CCCC66, 0x00CCCC99, 0x00CCCCFF, 0x00CC33CC, 0x00CC66CC,
495
    0x00CC99CC, 0x00CCFFCC, 0x0033CCCC, 0x0066CCCC, 0x0099CCCC, 0x00FFCCCC,
496
    0x00999933, 0x00999966, 0x009999CC, 0x009999FF, 0x00993399, 0x00996699,
497
    0x0099CC99, 0x0099FF99, 0x00339999, 0x00669999, 0x00CC9999, 0x00FF9999,
498
    0x00666633, 0x00666699, 0x006666CC, 0x006666FF, 0x00663366, 0x00669966,
499
    0x0066CC66, 0x0066FF66, 0x00336666, 0x00996666, 0x00CC6666, 0x00FF6666,
500
    0x00333366, 0x00333399, 0x003333CC, 0x003333FF, 0x00336633, 0x00339933,
501
    0x0033CC33, 0x0033FF33, 0x00663333, 0x00993333, 0x00CC3333, 0x00FF3333,
502
    0x00003366, 0x00336600, 0x00660033, 0x00006633, 0x00330066, 0x00663300,
503
    0x00336699, 0x00669933, 0x00993366, 0x00339966, 0x00663399, 0x00996633,
504
    0x006699CC, 0x0099CC66, 0x00CC6699, 0x0066CC99, 0x009966CC, 0x00CC9966,
505
    0x0099CCFF, 0x00CCFF99, 0x00FF99CC, 0x0099FFCC, 0x00CC99FF, 0x00FFCC99,
506
    0x00111111, 0x00222222, 0x00444444, 0x00555555, 0x00AAAAAA, 0x00BBBBBB,
507
    0x00DDDDDD, 0x00EEEEEE
508
};
509
510
4
static int generate_default_palette(Palette * palette)
511
{
512
4
    memcpy(palette->colors, default_screen_video_v2_palette,
513
           sizeof(default_screen_video_v2_palette));
514
515
4
    return update_palette_index(palette);
516
}
517
518
static int generate_optimum_palette(Palette * palette, const uint8_t * image,
519
                                   int width, int height, int stride)
520
{
521
    //this isn't implemented yet!  Default palette only!
522
    return -1;
523
}
524
525
260900
static inline int encode_15_7_sl(Palette * palette, uint8_t * dest,
526
                                 const uint8_t * src, int width, int dist)
527
{
528
260900
    int len = 0, x;
529
15525100
    for (x = 0; x < width; x++) {
530
15264200
        len += write_pixel_15_7(palette, dest + len, src + 3 * x, dist);
531
    }
532
260900
    return len;
533
}
534
535
4550
static int encode_15_7(Palette * palette, Block * b, const uint8_t * src,
536
                       int stride, int dist)
537
{
538
    int i;
539
4550
    uint8_t *ptr = b->enc;
540
4550
    for (i = 0; i < b->start; i++)
541
        ptr += encode_15_7_sl(palette, ptr, src + i * stride, b->width, dist);
542
4550
    b->sl_begin = ptr;
543
265450
    for (; i < b->start + b->len; i++)
544
260900
        ptr += encode_15_7_sl(palette, ptr, src + i * stride, b->width, dist);
545
4550
    b->sl_end = ptr;
546
4550
    for (; i < b->height; i++)
547
        ptr += encode_15_7_sl(palette, ptr, src + i * stride, b->width, dist);
548
4550
    b->enc_size = ptr - b->enc;
549
4550
    return b->enc_size;
550
}
551
552
4550
static int encode_block(FlashSV2Context *s, Palette * palette, Block * b,
553
                        Block * prev, const uint8_t * src, int stride, int comp,
554
                        int dist, int keyframe)
555
{
556
4550
    unsigned buf_size = b->width * b->height * 6;
557
4550
    uint8_t *buf = s->blockbuffer;
558
    int res;
559
560
4550
    if (b->flags & COLORSPACE_15_7) {
561
4550
        encode_15_7(palette, b, src, stride, dist);
562
    } else {
563
        encode_bgr(b, src, stride);
564
    }
565
566
4550
    if (b->len > 0) {
567
4550
        b->data_size = buf_size;
568
4550
        res = encode_zlib(b, b->data, &b->data_size, comp);
569
4550
        if (res)
570
            return res;
571
572
4550
        if (!keyframe) {
573
4095
            res = encode_zlibprime(b, prev, buf, &buf_size, comp);
574
4095
            if (res)
575
                return res;
576
577
4095
            if (buf_size < b->data_size) {
578
4095
                b->data_size = buf_size;
579
4095
                memcpy(b->data, buf, buf_size);
580
4095
                b->flags |= ZLIB_PRIME_COMPRESS_PREVIOUS;
581
            }
582
        }
583
    } else {
584
        b->data_size = 0;
585
    }
586
4550
    return 0;
587
}
588
589
260900
static int compare_sl(FlashSV2Context * s, Block * b, const uint8_t * src,
590
                      uint8_t * frame, uint8_t * key, int y, int keyframe)
591
{
592
260900
    if (memcmp(src, frame, b->width * 3) != 0) {
593
260900
        b->dirty = 1;
594
260900
        memcpy(frame, src, b->width * 3);
595
#ifndef FLASHSV2_DUMB
596
        s->diff_lines++;
597
#endif
598
    }
599
260900
    if (memcmp(src, key, b->width * 3) != 0) {
600
260900
        if (b->len == 0)
601
4550
            b->start = y;
602
260900
        b->len = y + 1 - b->start;
603
    }
604
260900
    return 0;
605
}
606
607
200
static int mark_all_blocks(FlashSV2Context * s, const uint8_t * src, int stride,
608
                           int keyframe)
609
{
610
    int sl, rsl, col, pos, possl;
611
    Block *b;
612
45100
    for (sl = s->image_height - 1; sl >= 0; sl--) {
613
305800
        for (col = 0; col < s->cols; col++) {
614
260900
            rsl = s->image_height - sl - 1;
615
260900
            b = s->frame_blocks + col + rsl / s->block_height * s->cols;
616
260900
            possl = stride * sl + col * s->block_width * 3;
617
260900
            pos = s->image_width * rsl * 3 + col * s->block_width * 3;
618
260900
            compare_sl(s, b, src + possl, s->current_frame + pos,
619
260900
                       s->key_frame + pos, rsl % s->block_height, keyframe);
620
        }
621
    }
622
#ifndef FLASHSV2_DUMB
623
    s->tot_lines += s->image_height * s->cols;
624
#endif
625
200
    return 0;
626
}
627
628
200
static int encode_all_blocks(FlashSV2Context * s, int keyframe)
629
{
630
    int row, col, res;
631
    uint8_t *data;
632
    Block *b, *prev;
633
1000
    for (row = 0; row < s->rows; row++) {
634
5350
        for (col = 0; col < s->cols; col++) {
635
4550
            b = s->frame_blocks + (row * s->cols + col);
636
4550
            prev = s->key_blocks + (row * s->cols + col);
637
4550
            b->flags = s->use15_7 ? COLORSPACE_15_7 : 0;
638
4550
            if (keyframe) {
639
455
                b->start = 0;
640
455
                b->len = b->height;
641
4095
            } else if (!b->dirty) {
642
                b->start = 0;
643
                b->len = 0;
644
                b->data_size = 0;
645
                continue;
646

4095
            } else if (b->start != 0 || b->len != b->height) {
647
                b->flags |= HAS_DIFF_BLOCKS;
648
            }
649
4550
            data = s->current_frame + s->image_width * 3 * s->block_height * row + s->block_width * col * 3;
650
4550
            res = encode_block(s, &s->palette, b, prev, data, s->image_width * 3, s->comp, s->dist, keyframe);
651
#ifndef FLASHSV2_DUMB
652
            if (b->dirty)
653
                s->diff_blocks++;
654
            s->comp_size += b->data_size;
655
            s->uncomp_size += b->enc_size;
656
#endif
657
4550
            if (res)
658
                return res;
659
        }
660
    }
661
#ifndef FLASHSV2_DUMB
662
    s->raw_size += s->image_width * s->image_height * 3;
663
    s->tot_blocks += s->rows * s->cols;
664
#endif
665
200
    return 0;
666
}
667
668
200
static int write_all_blocks(FlashSV2Context * s, uint8_t * buf,
669
                            int buf_size)
670
{
671
200
    int row, col, buf_pos = 0, len;
672
    Block *b;
673
1000
    for (row = 0; row < s->rows; row++) {
674
5350
        for (col = 0; col < s->cols; col++) {
675
4550
            b = s->frame_blocks + row * s->cols + col;
676
4550
            len = write_block(b, buf + buf_pos, buf_size - buf_pos);
677
4550
            b->start = b->len = b->dirty = 0;
678
4550
            if (len < 0)
679
                return len;
680
4550
            buf_pos += len;
681
        }
682
    }
683
200
    return buf_pos;
684
}
685
686
200
static int write_bitstream(FlashSV2Context * s, const uint8_t * src, int stride,
687
                           uint8_t * buf, int buf_size, int keyframe)
688
{
689
    int buf_pos, res;
690
691
200
    res = mark_all_blocks(s, src, stride, keyframe);
692
200
    if (res)
693
        return res;
694
200
    res = encode_all_blocks(s, keyframe);
695
200
    if (res)
696
        return res;
697
698
200
    res = write_header(s, buf, buf_size);
699
200
    if (res < 0) {
700
        return res;
701
    } else {
702
200
        buf_pos = res;
703
    }
704
200
    res = write_all_blocks(s, buf + buf_pos, buf_size - buf_pos);
705
200
    if (res < 0)
706
        return res;
707
200
    buf_pos += res;
708
#ifndef FLASHSV2_DUMB
709
    s->total_bits += ((double) buf_pos) * 8.0;
710
#endif
711
712
200
    return buf_pos;
713
}
714
715
static void recommend_keyframe(FlashSV2Context * s, int *keyframe)
716
{
717
#ifndef FLASHSV2_DUMB
718
    double block_ratio, line_ratio, enc_ratio, comp_ratio, data_ratio;
719
    if (s->avctx->gop_size > 0) {
720
        block_ratio = s->diff_blocks / s->tot_blocks;
721
        line_ratio = s->diff_lines / s->tot_lines;
722
        enc_ratio = s->uncomp_size / s->raw_size;
723
        comp_ratio = s->comp_size / s->uncomp_size;
724
        data_ratio = s->comp_size / s->raw_size;
725
726
        if ((block_ratio >= 0.5 && line_ratio / block_ratio <= 0.5) || line_ratio >= 0.95) {
727
            *keyframe = 1;
728
            return;
729
        }
730
    }
731
#else
732
    return;
733
#endif
734
}
735
736
#ifndef FLASHSV2_DUMB
737
static const double block_size_fraction = 1.0 / 300;
738
static const double use15_7_threshold = 8192;
739
static const double color15_7_factor = 100;
740
#endif
741
20
static int optimum_block_width(FlashSV2Context * s)
742
{
743
#ifndef FLASHSV2_DUMB
744
    double save = (1-pow(s->diff_lines/s->diff_blocks/s->block_height, 0.5)) * s->comp_size/s->tot_blocks;
745
    double width = block_size_fraction * sqrt(0.5 * save * s->rows * s->cols) * s->image_width;
746
    int pwidth = ((int) width);
747
    return FFCLIP(pwidth & ~15, 256, 16);
748
#else
749
20
    return 64;
750
#endif
751
}
752
753
20
static int optimum_block_height(FlashSV2Context * s)
754
{
755
#ifndef FLASHSV2_DUMB
756
    double save = (1-pow(s->diff_lines/s->diff_blocks/s->block_height, 0.5)) * s->comp_size/s->tot_blocks;
757
    double height = block_size_fraction * sqrt(0.5 * save * s->rows * s->cols) * s->image_height;
758
    int pheight = ((int) height);
759
    return FFCLIP(pheight & ~15, 256, 16);
760
#else
761
20
    return 64;
762
#endif
763
}
764
765
20
static int optimum_use15_7(FlashSV2Context * s)
766
{
767
#ifndef FLASHSV2_DUMB
768
    double ideal = ((double)(s->avctx->bit_rate * s->avctx->time_base.den * s->avctx->ticks_per_frame)) /
769
        ((double) s->avctx->time_base.num) * s->avctx->frame_number;
770
    if (ideal + use15_7_threshold < s->total_bits) {
771
        return 1;
772
    } else {
773
        return 0;
774
    }
775
#else
776
20
    return s->avctx->global_quality == 0;
777
#endif
778
}
779
780
200
static int optimum_dist(FlashSV2Context * s)
781
{
782
#ifndef FLASHSV2_DUMB
783
    double ideal =
784
        s->avctx->bit_rate * s->avctx->time_base.den *
785
        s->avctx->ticks_per_frame;
786
    int dist = pow((s->total_bits / ideal) * color15_7_factor, 3);
787
    av_log(s->avctx, AV_LOG_DEBUG, "dist: %d\n", dist);
788
    return dist;
789
#else
790
200
    return 15;
791
#endif
792
}
793
794
795
20
static int reconfigure_at_keyframe(FlashSV2Context * s, const uint8_t * image,
796
                                   int stride)
797
{
798
20
    int update_palette = 0;
799
    int res;
800
20
    int block_width  = optimum_block_width (s);
801
20
    int block_height = optimum_block_height(s);
802
803
20
    s->rows = (s->image_height + block_height - 1) / block_height;
804
20
    s->cols = (s->image_width  + block_width  - 1) / block_width;
805
806

20
    if (block_width != s->block_width || block_height != s->block_height) {
807
4
        s->block_width  = block_width;
808
4
        s->block_height = block_height;
809
4
        if (s->rows * s->cols > s->blocks_size / sizeof(Block)) {
810
            s->frame_blocks = av_realloc_array(s->frame_blocks, s->rows, s->cols * sizeof(Block));
811
            s->key_blocks = av_realloc_array(s->key_blocks, s->cols, s->rows * sizeof(Block));
812
            if (!s->frame_blocks || !s->key_blocks) {
813
                av_log(s->avctx, AV_LOG_ERROR, "Memory allocation failed.\n");
814
                return -1;
815
            }
816
            s->blocks_size = s->rows * s->cols * sizeof(Block);
817
        }
818
4
        init_blocks(s, s->frame_blocks, s->encbuffer, s->databuffer);
819
4
        init_blocks(s, s->key_blocks, s->keybuffer, 0);
820
821
4
        av_fast_malloc(&s->blockbuffer, &s->blockbuffer_size, block_width * block_height * 6);
822
4
        if (!s->blockbuffer) {
823
            av_log(s->avctx, AV_LOG_ERROR, "Could not allocate block buffer.\n");
824
            return AVERROR(ENOMEM);
825
        }
826
    }
827
828
20
    s->use15_7 = optimum_use15_7(s);
829
20
    if (s->use15_7) {
830

20
        if ((s->use_custom_palette && s->palette_type != 1) || update_palette) {
831
            res = generate_optimum_palette(&s->palette, image, s->image_width, s->image_height, stride);
832
            if (res)
833
                return res;
834
            s->palette_type = 1;
835
            av_log(s->avctx, AV_LOG_DEBUG, "Generated optimum palette\n");
836

20
        } else if (!s->use_custom_palette && s->palette_type != 0) {
837
4
            res = generate_default_palette(&s->palette);
838
4
            if (res)
839
                return res;
840
4
            s->palette_type = 0;
841
4
            av_log(s->avctx, AV_LOG_DEBUG, "Generated default palette\n");
842
        }
843
    }
844
845
846
20
    reset_stats(s);
847
848
20
    return 0;
849
}
850
851
200
static int flashsv2_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
852
                                 const AVFrame *p, int *got_packet)
853
{
854
200
    FlashSV2Context *const s = avctx->priv_data;
855
    int res;
856
200
    int keyframe = 0;
857
858
200
    if ((res = ff_alloc_packet2(avctx, pkt, s->frame_size + AV_INPUT_BUFFER_MIN_SIZE, 0)) < 0)
859
        return res;
860
861
    /* First frame needs to be a keyframe */
862
200
    if (avctx->frame_number == 0)
863
4
        keyframe = 1;
864
865
    /* Check the placement of keyframes */
866
200
    if (avctx->gop_size > 0) {
867
200
        if (avctx->frame_number >= s->last_key_frame + avctx->gop_size)
868
16
            keyframe = 1;
869
    }
870
871
200
    if (!keyframe
872
180
        && avctx->frame_number > s->last_key_frame + avctx->keyint_min) {
873
        recommend_keyframe(s, &keyframe);
874
        if (keyframe)
875
            av_log(avctx, AV_LOG_DEBUG, "Recommending key frame at frame %d\n", avctx->frame_number);
876
    }
877
878
200
    if (keyframe) {
879
20
        res = reconfigure_at_keyframe(s, p->data[0], p->linesize[0]);
880
20
        if (res)
881
            return res;
882
    }
883
884
200
    if (s->use15_7)
885
200
        s->dist = optimum_dist(s);
886
887
200
    res = write_bitstream(s, p->data[0], p->linesize[0], pkt->data, pkt->size, keyframe);
888
889
200
    if (keyframe) {
890
20
        new_key_frame(s);
891
20
        s->last_key_frame = avctx->frame_number;
892
20
        pkt->flags |= AV_PKT_FLAG_KEY;
893
20
        av_log(avctx, AV_LOG_DEBUG, "Inserting key frame at frame %d\n", avctx->frame_number);
894
    }
895
896
200
    pkt->size = res;
897
200
    *got_packet = 1;
898
899
200
    return 0;
900
}
901
902
4
static av_cold int flashsv2_encode_end(AVCodecContext * avctx)
903
{
904
4
    FlashSV2Context *s = avctx->priv_data;
905
906
4
    cleanup(s);
907
908
4
    return 0;
909
}
910
911
AVCodec ff_flashsv2_encoder = {
912
    .name           = "flashsv2",
913
    .long_name      = NULL_IF_CONFIG_SMALL("Flash Screen Video Version 2"),
914
    .type           = AVMEDIA_TYPE_VIDEO,
915
    .id             = AV_CODEC_ID_FLASHSV2,
916
    .priv_data_size = sizeof(FlashSV2Context),
917
    .init           = flashsv2_encode_init,
918
    .encode2        = flashsv2_encode_frame,
919
    .close          = flashsv2_encode_end,
920
    .pix_fmts       = (const enum AVPixelFormat[]){ AV_PIX_FMT_BGR24, AV_PIX_FMT_NONE },
921
    .caps_internal  = FF_CODEC_CAP_INIT_CLEANUP,
922
};