2 * Flash Screen Video Version 2 encoder
3 * Copyright (C) 2009 Joshua Warner
5 * This file is part of FFmpeg.
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.
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.
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
24 * Flash Screen Video Version 2 encoder
25 * @author Joshua Warner
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.
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.
49 #include "libavutil/imgutils.h"
53 #include "bytestream.h"
55 #define HAS_IFRAME_IMAGE 0x02
56 #define HAS_PALLET_INFO 0x01
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
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.
68 typedef struct Block {
70 uint8_t *sl_begin, *sl_end;
73 unsigned long data_size;
77 uint8_t col, row, width, height;
81 typedef struct Palette {
83 uint8_t index[1 << 15];
86 typedef struct FlashSV2Context {
87 AVCodecContext *avctx;
88 uint8_t *current_frame;
100 int use15_7, dist, comp;
106 int image_width, image_height;
107 int block_width, block_height;
109 uint8_t use_custom_palette;
110 uint8_t palette_type; ///< 0=>default, 1=>custom - changed when palette regenerated.
112 #ifndef FLASHSV2_DUMB
113 double tot_blocks; ///< blocks encoded since last keyframe
114 double diff_blocks; ///< blocks that were different since last keyframe
115 double tot_lines; ///< total scanlines in image since last keyframe
116 double diff_lines; ///< scanlines that were different since last keyframe
117 double raw_size; ///< size of raw frames since last keyframe
118 double comp_size; ///< size of compressed data since last keyframe
119 double uncomp_size; ///< size of uncompressed data since last keyframe
121 double total_bits; ///< total bits written to stream so far
125 static av_cold void cleanup(FlashSV2Context * s)
127 av_freep(&s->encbuffer);
128 av_freep(&s->keybuffer);
129 av_freep(&s->databuffer);
130 av_freep(&s->current_frame);
131 av_freep(&s->key_frame);
133 av_freep(&s->frame_blocks);
134 av_freep(&s->key_blocks);
137 static void init_blocks(FlashSV2Context * s, Block * blocks,
138 uint8_t * encbuf, uint8_t * databuf)
142 for (col = 0; col < s->cols; col++) {
143 for (row = 0; row < s->rows; row++) {
144 b = blocks + (col + row * s->cols);
145 b->width = (col < s->cols - 1) ?
147 s->image_width - col * s->block_width;
149 b->height = (row < s->rows - 1) ?
151 s->image_height - row * s->block_height;
157 encbuf += b->width * b->height * 3;
158 databuf += !databuf ? 0 : b->width * b->height * 6;
163 static void reset_stats(FlashSV2Context * s)
165 #ifndef FLASHSV2_DUMB
166 s->diff_blocks = 0.1;
170 s->raw_size = s->comp_size = s->uncomp_size = 10;
174 static av_cold int flashsv2_encode_init(AVCodecContext * avctx)
176 FlashSV2Context *s = avctx->priv_data;
180 s->comp = avctx->compression_level;
183 if (s->comp < 0 || s->comp > 9) {
184 av_log(avctx, AV_LOG_ERROR,
185 "Compression level should be 0-9, not %d\n", s->comp);
190 if ((avctx->width > 4095) || (avctx->height > 4095)) {
191 av_log(avctx, AV_LOG_ERROR,
192 "Input dimensions too large, input must be max 4096x4096 !\n");
195 if ((avctx->width < 16) || (avctx->height < 16)) {
196 av_log(avctx, AV_LOG_ERROR,
197 "Input dimensions too small, input must be at least 16x16 !\n");
201 if (av_image_check_size(avctx->width, avctx->height, 0, avctx) < 0)
205 s->last_key_frame = 0;
207 s->image_width = avctx->width;
208 s->image_height = avctx->height;
210 s->block_width = (s->image_width / 12) & ~15;
211 s->block_height = (s->image_height / 12) & ~15;
218 s->rows = (s->image_height + s->block_height - 1) / s->block_height;
219 s->cols = (s->image_width + s->block_width - 1) / s->block_width;
221 s->frame_size = s->image_width * s->image_height * 3;
222 s->blocks_size = s->rows * s->cols * sizeof(Block);
224 s->encbuffer = av_mallocz(s->frame_size);
225 s->keybuffer = av_mallocz(s->frame_size);
226 s->databuffer = av_mallocz(s->frame_size * 6);
227 s->current_frame = av_mallocz(s->frame_size);
228 s->key_frame = av_mallocz(s->frame_size);
229 s->frame_blocks = av_mallocz(s->blocks_size);
230 s->key_blocks = av_mallocz(s->blocks_size);
232 init_blocks(s, s->frame_blocks, s->encbuffer, s->databuffer);
233 init_blocks(s, s->key_blocks, s->keybuffer, 0);
235 #ifndef FLASHSV2_DUMB
239 s->use_custom_palette = 0;
240 s->palette_type = -1; // so that the palette will be generated in reconfigure_at_keyframe
242 if (!s->encbuffer || !s->keybuffer || !s->databuffer
243 || !s->current_frame || !s->key_frame || !s->key_blocks
244 || !s->frame_blocks) {
245 av_log(avctx, AV_LOG_ERROR, "Memory allocation failed.\n");
253 static int new_key_frame(FlashSV2Context * s)
256 memcpy(s->key_blocks, s->frame_blocks, s->blocks_size);
257 memcpy(s->key_frame, s->current_frame, s->frame_size);
259 for (i = 0; i < s->rows * s->cols; i++) {
260 s->key_blocks[i].enc += (s->keybuffer - s->encbuffer);
261 s->key_blocks[i].sl_begin = 0;
262 s->key_blocks[i].sl_end = 0;
263 s->key_blocks[i].data = 0;
265 FFSWAP(uint8_t * , s->keybuffer, s->encbuffer);
270 static int write_palette(FlashSV2Context * s, uint8_t * buf, int buf_size)
272 //this isn't implemented yet! Default palette only!
276 static int write_header(FlashSV2Context * s, uint8_t * buf, int buf_size)
284 init_put_bits(&pb, buf, buf_size * 8);
286 put_bits(&pb, 4, (s->block_width >> 4) - 1);
287 put_bits(&pb, 12, s->image_width);
288 put_bits(&pb, 4, (s->block_height >> 4) - 1);
289 put_bits(&pb, 12, s->image_height);
294 buf[buf_pos++] = s->flags;
296 if (s->flags & HAS_PALLET_INFO) {
297 len = write_palette(s, buf + buf_pos, buf_size - buf_pos);
306 static int write_block(Block * b, uint8_t * buf, int buf_size)
309 unsigned block_size = b->data_size;
311 if (b->flags & HAS_DIFF_BLOCKS)
313 if (b->flags & ZLIB_PRIME_COMPRESS_CURRENT)
317 if (buf_size < block_size + 2)
320 buf[buf_pos++] = block_size >> 8;
321 buf[buf_pos++] = block_size;
326 buf[buf_pos++] = b->flags;
328 if (b->flags & HAS_DIFF_BLOCKS) {
329 buf[buf_pos++] = (b->start);
330 buf[buf_pos++] = (b->len);
333 if (b->flags & ZLIB_PRIME_COMPRESS_CURRENT) {
334 //This feature of the format is poorly understood, and as of now, unused.
335 buf[buf_pos++] = (b->col);
336 buf[buf_pos++] = (b->row);
339 memcpy(buf + buf_pos, b->data, b->data_size);
341 buf_pos += b->data_size;
346 static int encode_zlib(Block * b, uint8_t * buf, unsigned long *buf_size, int comp)
348 int res = compress2(buf, buf_size, b->sl_begin, b->sl_end - b->sl_begin, comp);
349 return res == Z_OK ? 0 : -1;
352 static int encode_zlibprime(Block * b, Block * prime, uint8_t * buf,
353 int *buf_size, int comp)
360 res = deflateInit(&s, comp);
364 s.next_in = prime->enc;
365 s.avail_in = prime->enc_size;
366 while (s.avail_in > 0) {
368 s.avail_out = *buf_size;
369 res = deflate(&s, Z_SYNC_FLUSH);
374 s.next_in = b->sl_begin;
375 s.avail_in = b->sl_end - b->sl_begin;
377 s.avail_out = *buf_size;
378 res = deflate(&s, Z_FINISH);
380 *buf_size -= s.avail_out;
381 if (res != Z_STREAM_END)
386 static int encode_bgr(Block * b, const uint8_t * src, int stride)
389 uint8_t *ptr = b->enc;
390 for (i = 0; i < b->start; i++)
391 memcpy(ptr + i * b->width * 3, src + i * stride, b->width * 3);
392 b->sl_begin = ptr + i * b->width * 3;
393 for (; i < b->start + b->len; i++)
394 memcpy(ptr + i * b->width * 3, src + i * stride, b->width * 3);
395 b->sl_end = ptr + i * b->width * 3;
396 for (; i < b->height; i++)
397 memcpy(ptr + i * b->width * 3, src + i * stride, b->width * 3);
398 b->enc_size = ptr + i * b->width * 3 - b->enc;
402 static inline unsigned pixel_color15(const uint8_t * src)
404 return (src[0] >> 3) | ((src[1] & 0xf8) << 2) | ((src[2] & 0xf8) << 7);
407 static inline unsigned int chroma_diff(unsigned int c1, unsigned int c2)
409 unsigned int t1 = (c1 & 0x000000ff) + ((c1 & 0x0000ff00) >> 8) + ((c1 & 0x00ff0000) >> 16);
410 unsigned int t2 = (c2 & 0x000000ff) + ((c2 & 0x0000ff00) >> 8) + ((c2 & 0x00ff0000) >> 16);
412 return abs(t1 - t2) + abs((c1 & 0x000000ff) - (c2 & 0x000000ff)) +
413 abs(((c1 & 0x0000ff00) >> 8) - ((c2 & 0x0000ff00) >> 8)) +
414 abs(((c1 & 0x00ff0000) >> 16) - ((c2 & 0x00ff0000) >> 16));
417 static inline int pixel_color7_fast(Palette * palette, unsigned c15)
419 return palette->index[c15];
422 static int pixel_color7_slow(Palette * palette, unsigned color)
424 int i, min = 0x7fffffff;
426 for (i = 0; i < 128; i++) {
427 int c1 = palette->colors[i];
428 int diff = chroma_diff(c1, color);
437 static inline unsigned pixel_bgr(const uint8_t * src)
439 return (src[0]) | (src[1] << 8) | (src[2] << 16);
442 static int write_pixel_15_7(Palette * palette, uint8_t * dest, const uint8_t * src,
445 unsigned c15 = pixel_color15(src);
446 unsigned color = pixel_bgr(src);
447 int d15 = chroma_diff(color, color & 0x00f8f8f8);
448 int c7 = pixel_color7_fast(palette, c15);
449 int d7 = chroma_diff(color, palette->colors[c7]);
450 if (dist + d15 >= d7) {
454 dest[0] = 0x80 | (c15 >> 8);
455 dest[1] = c15 & 0xff;
460 static int update_palette_index(Palette * palette)
463 unsigned int bgr, c15, index;
464 for (r = 4; r < 256; r += 8) {
465 for (g = 4; g < 256; g += 8) {
466 for (b = 4; b < 256; b += 8) {
467 bgr = b | (g << 8) | (r << 16);
468 c15 = (b >> 3) | ((g & 0xf8) << 2) | ((r & 0xf8) << 7);
469 index = pixel_color7_slow(palette, bgr);
471 palette->index[c15] = index;
478 static const unsigned int default_screen_video_v2_palette[128] = {
479 0x00000000, 0x00333333, 0x00666666, 0x00999999, 0x00CCCCCC, 0x00FFFFFF,
480 0x00330000, 0x00660000, 0x00990000, 0x00CC0000, 0x00FF0000, 0x00003300,
481 0x00006600, 0x00009900, 0x0000CC00, 0x0000FF00, 0x00000033, 0x00000066,
482 0x00000099, 0x000000CC, 0x000000FF, 0x00333300, 0x00666600, 0x00999900,
483 0x00CCCC00, 0x00FFFF00, 0x00003333, 0x00006666, 0x00009999, 0x0000CCCC,
484 0x0000FFFF, 0x00330033, 0x00660066, 0x00990099, 0x00CC00CC, 0x00FF00FF,
485 0x00FFFF33, 0x00FFFF66, 0x00FFFF99, 0x00FFFFCC, 0x00FF33FF, 0x00FF66FF,
486 0x00FF99FF, 0x00FFCCFF, 0x0033FFFF, 0x0066FFFF, 0x0099FFFF, 0x00CCFFFF,
487 0x00CCCC33, 0x00CCCC66, 0x00CCCC99, 0x00CCCCFF, 0x00CC33CC, 0x00CC66CC,
488 0x00CC99CC, 0x00CCFFCC, 0x0033CCCC, 0x0066CCCC, 0x0099CCCC, 0x00FFCCCC,
489 0x00999933, 0x00999966, 0x009999CC, 0x009999FF, 0x00993399, 0x00996699,
490 0x0099CC99, 0x0099FF99, 0x00339999, 0x00669999, 0x00CC9999, 0x00FF9999,
491 0x00666633, 0x00666699, 0x006666CC, 0x006666FF, 0x00663366, 0x00669966,
492 0x0066CC66, 0x0066FF66, 0x00336666, 0x00996666, 0x00CC6666, 0x00FF6666,
493 0x00333366, 0x00333399, 0x003333CC, 0x003333FF, 0x00336633, 0x00339933,
494 0x0033CC33, 0x0033FF33, 0x00663333, 0x00993333, 0x00CC3333, 0x00FF3333,
495 0x00003366, 0x00336600, 0x00660033, 0x00006633, 0x00330066, 0x00663300,
496 0x00336699, 0x00669933, 0x00993366, 0x00339966, 0x00663399, 0x00996633,
497 0x006699CC, 0x0099CC66, 0x00CC6699, 0x0066CC99, 0x009966CC, 0x00CC9966,
498 0x0099CCFF, 0x00CCFF99, 0x00FF99CC, 0x0099FFCC, 0x00CC99FF, 0x00FFCC99,
499 0x00111111, 0x00222222, 0x00444444, 0x00555555, 0x00AAAAAA, 0x00BBBBBB,
500 0x00DDDDDD, 0x00EEEEEE
503 static int generate_default_palette(Palette * palette)
505 memcpy(palette->colors, default_screen_video_v2_palette,
506 sizeof(default_screen_video_v2_palette));
508 return update_palette_index(palette);
511 static int generate_optimum_palette(Palette * palette, const uint8_t * image,
512 int width, int height, int stride)
514 //this isn't implemented yet! Default palette only!
518 static inline int encode_15_7_sl(Palette * palette, uint8_t * dest,
519 const uint8_t * src, int width, int dist)
522 for (x = 0; x < width; x++) {
523 len += write_pixel_15_7(palette, dest + len, src + 3 * x, dist);
528 static int encode_15_7(Palette * palette, Block * b, const uint8_t * src,
529 int stride, int dist)
532 uint8_t *ptr = b->enc;
533 for (i = 0; i < b->start; i++)
534 ptr += encode_15_7_sl(palette, ptr, src + i * stride, b->width, dist);
536 for (; i < b->start + b->len; i++)
537 ptr += encode_15_7_sl(palette, ptr, src + i * stride, b->width, dist);
539 for (; i < b->height; i++)
540 ptr += encode_15_7_sl(palette, ptr, src + i * stride, b->width, dist);
541 b->enc_size = ptr - b->enc;
545 static int encode_block(Palette * palette, Block * b, Block * prev,
546 const uint8_t * src, int stride, int comp, int dist,
549 unsigned buf_size = b->width * b->height * 6;
550 uint8_t buf[buf_size];
552 if (b->flags & COLORSPACE_15_7) {
553 encode_15_7(palette, b, src, stride, dist);
555 encode_bgr(b, src, stride);
559 b->data_size = buf_size;
560 res = encode_zlib(b, b->data, &b->data_size, comp);
565 res = encode_zlibprime(b, prev, buf, &buf_size, comp);
569 if (buf_size < b->data_size) {
570 b->data_size = buf_size;
571 memcpy(b->data, buf, buf_size);
572 b->flags |= ZLIB_PRIME_COMPRESS_PREVIOUS;
581 static int compare_sl(FlashSV2Context * s, Block * b, const uint8_t * src,
582 uint8_t * frame, uint8_t * key, int y, int keyframe)
584 if (memcmp(src, frame, b->width * 3) != 0) {
586 memcpy(frame, src, b->width * 3);
587 #ifndef FLASHSV2_DUMB
591 if (memcmp(src, key, b->width * 3) != 0) {
594 b->len = y + 1 - b->start;
599 static int mark_all_blocks(FlashSV2Context * s, const uint8_t * src, int stride,
602 int sl, rsl, col, pos, possl;
604 for (sl = s->image_height - 1; sl >= 0; sl--) {
605 for (col = 0; col < s->cols; col++) {
606 rsl = s->image_height - sl - 1;
607 b = s->frame_blocks + col + rsl / s->block_height * s->cols;
608 possl = stride * sl + col * s->block_width * 3;
609 pos = s->image_width * rsl * 3 + col * s->block_width * 3;
610 compare_sl(s, b, src + possl, s->current_frame + pos,
611 s->key_frame + pos, rsl % s->block_height, keyframe);
614 #ifndef FLASHSV2_DUMB
615 s->tot_lines += s->image_height * s->cols;
620 static int encode_all_blocks(FlashSV2Context * s, int keyframe)
625 for (row = 0; row < s->rows; row++) {
626 for (col = 0; col < s->cols; col++) {
627 b = s->frame_blocks + (row * s->cols + col);
628 prev = s->key_blocks + (row * s->cols + col);
632 b->flags = s->use15_7 ? COLORSPACE_15_7 : 0;
633 } else if (!b->dirty) {
637 b->flags = s->use15_7 ? COLORSPACE_15_7 : 0;
640 b->flags = s->use15_7 ? COLORSPACE_15_7 | HAS_DIFF_BLOCKS : HAS_DIFF_BLOCKS;
642 data = s->current_frame + s->image_width * 3 * s->block_height * row + s->block_width * col * 3;
643 res = encode_block(&s->palette, b, prev, data, s->image_width * 3, s->comp, s->dist, keyframe);
644 #ifndef FLASHSV2_DUMB
647 s->comp_size += b->data_size;
648 s->uncomp_size += b->enc_size;
654 #ifndef FLASHSV2_DUMB
655 s->raw_size += s->image_width * s->image_height * 3;
656 s->tot_blocks += s->rows * s->cols;
661 static int write_all_blocks(FlashSV2Context * s, uint8_t * buf,
664 int row, col, buf_pos = 0, len;
666 for (row = 0; row < s->rows; row++) {
667 for (col = 0; col < s->cols; col++) {
668 b = s->frame_blocks + row * s->cols + col;
669 len = write_block(b, buf + buf_pos, buf_size - buf_pos);
670 b->start = b->len = b->dirty = 0;
679 static int write_bitstream(FlashSV2Context * s, const uint8_t * src, int stride,
680 uint8_t * buf, int buf_size, int keyframe)
684 res = mark_all_blocks(s, src, stride, keyframe);
687 res = encode_all_blocks(s, keyframe);
691 res = write_header(s, buf, buf_size);
697 res = write_all_blocks(s, buf + buf_pos, buf_size - buf_pos);
701 #ifndef FLASHSV2_DUMB
702 s->total_bits += ((double) buf_pos) * 8.0;
708 static void recommend_keyframe(FlashSV2Context * s, int *keyframe)
710 #ifndef FLASHSV2_DUMB
711 double block_ratio, line_ratio, enc_ratio, comp_ratio, data_ratio;
712 if (s->avctx->gop_size > 0) {
713 block_ratio = s->diff_blocks / s->tot_blocks;
714 line_ratio = s->diff_lines / s->tot_lines;
715 enc_ratio = s->uncomp_size / s->raw_size;
716 comp_ratio = s->comp_size / s->uncomp_size;
717 data_ratio = s->comp_size / s->raw_size;
719 if ((block_ratio >= 0.5 && line_ratio / block_ratio <= 0.5) || line_ratio >= 0.95) {
729 static const double block_size_fraction = 1.0 / 300;
730 static int optimum_block_width(FlashSV2Context * s)
732 #ifndef FLASHSV2_DUMB
733 double save = (1-pow(s->diff_lines/s->diff_blocks/s->block_height, 0.5)) * s->comp_size/s->tot_blocks;
734 double width = block_size_fraction * sqrt(0.5 * save * s->rows * s->cols) * s->image_width;
735 int pwidth = ((int) width);
736 return FFCLIP(pwidth & ~15, 256, 16);
742 static int optimum_block_height(FlashSV2Context * s)
744 #ifndef FLASHSV2_DUMB
745 double save = (1-pow(s->diff_lines/s->diff_blocks/s->block_height, 0.5)) * s->comp_size/s->tot_blocks;
746 double height = block_size_fraction * sqrt(0.5 * save * s->rows * s->cols) * s->image_height;
747 int pheight = ((int) height);
748 return FFCLIP(pheight & ~15, 256, 16);
754 static const double use15_7_threshold = 8192;
756 static int optimum_use15_7(FlashSV2Context * s)
758 #ifndef FLASHSV2_DUMB
759 double ideal = ((double)(s->avctx->bit_rate * s->avctx->time_base.den * s->avctx->ticks_per_frame)) /
760 ((double) s->avctx->time_base.num) * s->avctx->frame_number;
761 if (ideal + use15_7_threshold < s->total_bits) {
767 return s->avctx->global_quality == 0;
771 static const double color15_7_factor = 100;
773 static int optimum_dist(FlashSV2Context * s)
775 #ifndef FLASHSV2_DUMB
777 s->avctx->bit_rate * s->avctx->time_base.den *
778 s->avctx->ticks_per_frame;
779 int dist = pow((s->total_bits / ideal) * color15_7_factor, 3);
780 av_log(s->avctx, AV_LOG_DEBUG, "dist: %d\n", dist);
788 static int reconfigure_at_keyframe(FlashSV2Context * s, const uint8_t * image,
791 int update_palette = 0;
793 s->block_width = optimum_block_width(s);
794 s->block_height = optimum_block_height(s);
796 s->rows = (s->image_height + s->block_height - 1) / s->block_height;
797 s->cols = (s->image_width + s->block_width - 1) / s->block_width;
799 if (s->rows * s->cols != s->blocks_size / sizeof(Block)) {
800 if (s->rows * s->cols > s->blocks_size / sizeof(Block)) {
801 s->frame_blocks = av_realloc(s->frame_blocks, s->rows * s->cols * sizeof(Block));
802 s->key_blocks = av_realloc(s->key_blocks, s->cols * s->rows * sizeof(Block));
803 if (!s->frame_blocks || !s->key_blocks) {
804 av_log(s->avctx, AV_LOG_ERROR, "Memory allocation failed.\n");
807 s->blocks_size = s->rows * s->cols * sizeof(Block);
809 init_blocks(s, s->frame_blocks, s->encbuffer, s->databuffer);
810 init_blocks(s, s->key_blocks, s->keybuffer, 0);
814 s->use15_7 = optimum_use15_7(s);
816 if ((s->use_custom_palette && s->palette_type != 1) || update_palette) {
817 res = generate_optimum_palette(&s->palette, image, s->image_width, s->image_height, stride);
821 av_log(s->avctx, AV_LOG_DEBUG, "Generated optimum palette\n");
822 } else if (!s->use_custom_palette && s->palette_type != 0) {
823 res = generate_default_palette(&s->palette);
827 av_log(s->avctx, AV_LOG_DEBUG, "Generated default palette\n");
837 static int flashsv2_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
838 const AVFrame *pict, int *got_packet)
840 FlashSV2Context *const s = avctx->priv_data;
841 AVFrame *const p = &s->frame;
847 if ((res = ff_alloc_packet2(avctx, pkt, s->frame_size + FF_MIN_BUFFER_SIZE)) < 0)
850 /* First frame needs to be a keyframe */
851 if (avctx->frame_number == 0)
854 /* Check the placement of keyframes */
855 if (avctx->gop_size > 0) {
856 if (avctx->frame_number >= s->last_key_frame + avctx->gop_size)
861 && avctx->frame_number > s->last_key_frame + avctx->keyint_min) {
862 recommend_keyframe(s, &keyframe);
864 av_log(avctx, AV_LOG_DEBUG, "Recommending key frame at frame %d\n", avctx->frame_number);
868 res = reconfigure_at_keyframe(s, p->data[0], p->linesize[0]);
874 s->dist = optimum_dist(s);
876 res = write_bitstream(s, p->data[0], p->linesize[0], pkt->data, pkt->size, keyframe);
880 p->pict_type = AV_PICTURE_TYPE_I;
882 s->last_key_frame = avctx->frame_number;
883 pkt->flags |= AV_PKT_FLAG_KEY;
884 av_log(avctx, AV_LOG_DEBUG, "Inserting key frame at frame %d\n", avctx->frame_number);
886 p->pict_type = AV_PICTURE_TYPE_P;
890 avctx->coded_frame = p;
898 static av_cold int flashsv2_encode_end(AVCodecContext * avctx)
900 FlashSV2Context *s = avctx->priv_data;
907 AVCodec ff_flashsv2_encoder = {
909 .type = AVMEDIA_TYPE_VIDEO,
910 .id = CODEC_ID_FLASHSV2,
911 .priv_data_size = sizeof(FlashSV2Context),
912 .init = flashsv2_encode_init,
913 .encode2 = flashsv2_encode_frame,
914 .close = flashsv2_encode_end,
915 .pix_fmts = (const enum PixelFormat[]){ PIX_FMT_BGR24, PIX_FMT_NONE },
916 .long_name = NULL_IF_CONFIG_SMALL("Flash Screen Video Version 2"),
917 .capabilities = CODEC_CAP_EXPERIMENTAL,