FFmpeg  4.0
flashsv2enc.c
Go to the documentation of this file.
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 {
71  int enc_size;
73  unsigned long data_size;
74 
79 } Block;
80 
81 typedef struct Palette {
82  unsigned colors[128];
83  uint8_t index[1 << 15];
84 } Palette;
85 
86 typedef struct FlashSV2Context {
93 
96 
101 
102  int use15_7, dist, comp;
103 
104  int rows, cols;
105 
107 
108  int image_width, image_height;
109  int block_width, block_height;
112  uint8_t palette_type; ///< 0=>default, 1=>custom - changed when palette regenerated.
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
126 
128 {
129  av_freep(&s->encbuffer);
130  av_freep(&s->keybuffer);
131  av_freep(&s->databuffer);
132  av_freep(&s->blockbuffer);
133  av_freep(&s->current_frame);
134  av_freep(&s->key_frame);
135 
136  av_freep(&s->frame_blocks);
137  av_freep(&s->key_blocks);
138 }
139 
140 static void init_blocks(FlashSV2Context * s, Block * blocks,
141  uint8_t * encbuf, uint8_t * databuf)
142 {
143  int row, col;
144  Block *b;
145  for (col = 0; col < s->cols; col++) {
146  for (row = 0; row < s->rows; row++) {
147  b = blocks + (col + row * s->cols);
148  b->width = (col < s->cols - 1) ?
149  s->block_width :
150  s->image_width - col * s->block_width;
151 
152  b->height = (row < s->rows - 1) ?
153  s->block_height :
154  s->image_height - row * s->block_height;
155 
156  b->row = row;
157  b->col = col;
158  b->enc = encbuf;
159  b->data = databuf;
160  encbuf += b->width * b->height * 3;
161  databuf += !databuf ? 0 : b->width * b->height * 6;
162  }
163  }
164 }
165 
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 }
176 
178 {
179  FlashSV2Context *s = avctx->priv_data;
180 
181  s->avctx = avctx;
182 
183  s->comp = avctx->compression_level;
184  if (s->comp == -1)
185  s->comp = 9;
186  if (s->comp < 0 || s->comp > 9) {
187  av_log(avctx, AV_LOG_ERROR,
188  "Compression level should be 0-9, not %d\n", s->comp);
189  return -1;
190  }
191 
192 
193  if ((avctx->width > 4095) || (avctx->height > 4095)) {
194  av_log(avctx, AV_LOG_ERROR,
195  "Input dimensions too large, input must be max 4095x4095 !\n");
196  return -1;
197  }
198  if ((avctx->width < 16) || (avctx->height < 16)) {
199  av_log(avctx, AV_LOG_ERROR,
200  "Input dimensions too small, input must be at least 16x16 !\n");
201  return -1;
202  }
203 
204  if (av_image_check_size(avctx->width, avctx->height, 0, avctx) < 0)
205  return -1;
206 
207 
208  s->last_key_frame = 0;
209 
210  s->image_width = avctx->width;
211  s->image_height = avctx->height;
212 
213  s->block_width = (s->image_width / 12) & ~15;
214  s->block_height = (s->image_height / 12) & ~15;
215 
216  if(!s->block_width)
217  s->block_width = 1;
218  if(!s->block_height)
219  s->block_height = 1;
220 
221  s->rows = (s->image_height + s->block_height - 1) / s->block_height;
222  s->cols = (s->image_width + s->block_width - 1) / s->block_width;
223 
224  s->frame_size = s->image_width * s->image_height * 3;
225  s->blocks_size = s->rows * s->cols * sizeof(Block);
226 
229  s->databuffer = av_mallocz(s->frame_size * 6);
234 
235  s->blockbuffer = NULL;
236  s->blockbuffer_size = 0;
237 
239  init_blocks(s, s->key_blocks, s->keybuffer, 0);
240  reset_stats(s);
241 #ifndef FLASHSV2_DUMB
242  s->total_bits = 1;
243 #endif
244 
245  s->use_custom_palette = 0;
246  s->palette_type = -1; // so that the palette will be generated in reconfigure_at_keyframe
247 
248  if (!s->encbuffer || !s->keybuffer || !s->databuffer
249  || !s->current_frame || !s->key_frame || !s->key_blocks
250  || !s->frame_blocks) {
251  av_log(avctx, AV_LOG_ERROR, "Memory allocation failed.\n");
252  cleanup(s);
253  return -1;
254  }
255 
256  return 0;
257 }
258 
260 {
261  int i;
262  memcpy(s->key_blocks, s->frame_blocks, s->blocks_size);
263  memcpy(s->key_frame, s->current_frame, s->frame_size);
264 
265  for (i = 0; i < s->rows * s->cols; i++) {
266  s->key_blocks[i].enc += (s->keybuffer - s->encbuffer);
267  s->key_blocks[i].sl_begin = 0;
268  s->key_blocks[i].sl_end = 0;
269  s->key_blocks[i].data = 0;
270  }
271  memcpy(s->keybuffer, s->encbuffer, s->frame_size);
272 
273  return 0;
274 }
275 
276 static int write_palette(FlashSV2Context * s, uint8_t * buf, int buf_size)
277 {
278  //this isn't implemented yet! Default palette only!
279  return -1;
280 }
281 
282 static int write_header(FlashSV2Context * s, uint8_t * buf, int buf_size)
283 {
284  PutBitContext pb;
285  int buf_pos, len;
286 
287  if (buf_size < 5)
288  return -1;
289 
290  init_put_bits(&pb, buf, buf_size);
291 
292  put_bits(&pb, 4, (s->block_width >> 4) - 1);
293  put_bits(&pb, 12, s->image_width);
294  put_bits(&pb, 4, (s->block_height >> 4) - 1);
295  put_bits(&pb, 12, s->image_height);
296 
297  flush_put_bits(&pb);
298  buf_pos = 4;
299 
300  buf[buf_pos++] = s->flags;
301 
302  if (s->flags & HAS_PALLET_INFO) {
303  len = write_palette(s, buf + buf_pos, buf_size - buf_pos);
304  if (len < 0)
305  return -1;
306  buf_pos += len;
307  }
308 
309  return buf_pos;
310 }
311 
312 static int write_block(Block * b, uint8_t * buf, int buf_size)
313 {
314  int buf_pos = 0;
315  unsigned block_size = b->data_size;
316 
317  if (b->flags & HAS_DIFF_BLOCKS)
318  block_size += 2;
320  block_size += 2;
321  if (block_size > 0)
322  block_size += 1;
323  if (buf_size < block_size + 2)
324  return -1;
325 
326  buf[buf_pos++] = block_size >> 8;
327  buf[buf_pos++] = block_size;
328 
329  if (block_size == 0)
330  return buf_pos;
331 
332  buf[buf_pos++] = b->flags;
333 
334  if (b->flags & HAS_DIFF_BLOCKS) {
335  buf[buf_pos++] = (b->start);
336  buf[buf_pos++] = (b->len);
337  }
338 
340  //This feature of the format is poorly understood, and as of now, unused.
341  buf[buf_pos++] = (b->col);
342  buf[buf_pos++] = (b->row);
343  }
344 
345  memcpy(buf + buf_pos, b->data, b->data_size);
346 
347  buf_pos += b->data_size;
348 
349  return buf_pos;
350 }
351 
352 static int encode_zlib(Block * b, uint8_t * buf, unsigned long *buf_size, int comp)
353 {
354  int res = compress2(buf, buf_size, b->sl_begin, b->sl_end - b->sl_begin, comp);
355  return res == Z_OK ? 0 : -1;
356 }
357 
358 static int encode_zlibprime(Block * b, Block * prime, uint8_t * buf,
359  int *buf_size, int comp)
360 {
361  z_stream s;
362  int res;
363  s.zalloc = NULL;
364  s.zfree = NULL;
365  s.opaque = NULL;
366  res = deflateInit(&s, comp);
367  if (res < 0)
368  return -1;
369 
370  s.next_in = prime->enc;
371  s.avail_in = prime->enc_size;
372  while (s.avail_in > 0) {
373  s.next_out = buf;
374  s.avail_out = *buf_size;
375  res = deflate(&s, Z_SYNC_FLUSH);
376  if (res < 0)
377  return -1;
378  }
379 
380  s.next_in = b->sl_begin;
381  s.avail_in = b->sl_end - b->sl_begin;
382  s.next_out = buf;
383  s.avail_out = *buf_size;
384  res = deflate(&s, Z_FINISH);
385  deflateEnd(&s);
386  *buf_size -= s.avail_out;
387  if (res != Z_STREAM_END)
388  return -1;
389  return 0;
390 }
391 
392 static int encode_bgr(Block * b, const uint8_t * src, int stride)
393 {
394  int i;
395  uint8_t *ptr = b->enc;
396  for (i = 0; i < b->start; i++)
397  memcpy(ptr + i * b->width * 3, src + i * stride, b->width * 3);
398  b->sl_begin = ptr + i * b->width * 3;
399  for (; i < b->start + b->len; i++)
400  memcpy(ptr + i * b->width * 3, src + i * stride, b->width * 3);
401  b->sl_end = ptr + i * b->width * 3;
402  for (; i < b->height; i++)
403  memcpy(ptr + i * b->width * 3, src + i * stride, b->width * 3);
404  b->enc_size = ptr + i * b->width * 3 - b->enc;
405  return b->enc_size;
406 }
407 
408 static inline unsigned pixel_color15(const uint8_t * src)
409 {
410  return (src[0] >> 3) | ((src[1] & 0xf8) << 2) | ((src[2] & 0xf8) << 7);
411 }
412 
413 static inline unsigned int chroma_diff(unsigned int c1, unsigned int c2)
414 {
415 #define ABSDIFF(a,b) (abs((int)(a)-(int)(b)))
416 
417  unsigned int t1 = (c1 & 0x000000ff) + ((c1 & 0x0000ff00) >> 8) + ((c1 & 0x00ff0000) >> 16);
418  unsigned int t2 = (c2 & 0x000000ff) + ((c2 & 0x0000ff00) >> 8) + ((c2 & 0x00ff0000) >> 16);
419 
420  return ABSDIFF(t1, t2) + ABSDIFF(c1 & 0x000000ff, c2 & 0x000000ff) +
421  ABSDIFF((c1 & 0x0000ff00) >> 8 , (c2 & 0x0000ff00) >> 8) +
422  ABSDIFF((c1 & 0x00ff0000) >> 16, (c2 & 0x00ff0000) >> 16);
423 }
424 
425 static inline int pixel_color7_fast(Palette * palette, unsigned c15)
426 {
427  return palette->index[c15];
428 }
429 
430 static int pixel_color7_slow(Palette * palette, unsigned color)
431 {
432  int i, min = 0x7fffffff;
433  int minc = -1;
434  for (i = 0; i < 128; i++) {
435  int c1 = palette->colors[i];
436  int diff = chroma_diff(c1, color);
437  if (diff < min) {
438  min = diff;
439  minc = i;
440  }
441  }
442  return minc;
443 }
444 
445 static inline unsigned pixel_bgr(const uint8_t * src)
446 {
447  return (src[0]) | (src[1] << 8) | (src[2] << 16);
448 }
449 
450 static int write_pixel_15_7(Palette * palette, uint8_t * dest, const uint8_t * src,
451  int dist)
452 {
453  unsigned c15 = pixel_color15(src);
454  unsigned color = pixel_bgr(src);
455  int d15 = chroma_diff(color, color & 0x00f8f8f8);
456  int c7 = pixel_color7_fast(palette, c15);
457  int d7 = chroma_diff(color, palette->colors[c7]);
458  if (dist + d15 >= d7) {
459  dest[0] = c7;
460  return 1;
461  } else {
462  dest[0] = 0x80 | (c15 >> 8);
463  dest[1] = c15 & 0xff;
464  return 2;
465  }
466 }
467 
468 static int update_palette_index(Palette * palette)
469 {
470  int r, g, b;
471  unsigned int bgr, c15, index;
472  for (r = 4; r < 256; r += 8) {
473  for (g = 4; g < 256; g += 8) {
474  for (b = 4; b < 256; b += 8) {
475  bgr = b | (g << 8) | (r << 16);
476  c15 = (b >> 3) | ((g & 0xf8) << 2) | ((r & 0xf8) << 7);
477  index = pixel_color7_slow(palette, bgr);
478 
479  palette->index[c15] = index;
480  }
481  }
482  }
483  return 0;
484 }
485 
486 static const unsigned int default_screen_video_v2_palette[128] = {
487  0x00000000, 0x00333333, 0x00666666, 0x00999999, 0x00CCCCCC, 0x00FFFFFF,
488  0x00330000, 0x00660000, 0x00990000, 0x00CC0000, 0x00FF0000, 0x00003300,
489  0x00006600, 0x00009900, 0x0000CC00, 0x0000FF00, 0x00000033, 0x00000066,
490  0x00000099, 0x000000CC, 0x000000FF, 0x00333300, 0x00666600, 0x00999900,
491  0x00CCCC00, 0x00FFFF00, 0x00003333, 0x00006666, 0x00009999, 0x0000CCCC,
492  0x0000FFFF, 0x00330033, 0x00660066, 0x00990099, 0x00CC00CC, 0x00FF00FF,
493  0x00FFFF33, 0x00FFFF66, 0x00FFFF99, 0x00FFFFCC, 0x00FF33FF, 0x00FF66FF,
494  0x00FF99FF, 0x00FFCCFF, 0x0033FFFF, 0x0066FFFF, 0x0099FFFF, 0x00CCFFFF,
495  0x00CCCC33, 0x00CCCC66, 0x00CCCC99, 0x00CCCCFF, 0x00CC33CC, 0x00CC66CC,
496  0x00CC99CC, 0x00CCFFCC, 0x0033CCCC, 0x0066CCCC, 0x0099CCCC, 0x00FFCCCC,
497  0x00999933, 0x00999966, 0x009999CC, 0x009999FF, 0x00993399, 0x00996699,
498  0x0099CC99, 0x0099FF99, 0x00339999, 0x00669999, 0x00CC9999, 0x00FF9999,
499  0x00666633, 0x00666699, 0x006666CC, 0x006666FF, 0x00663366, 0x00669966,
500  0x0066CC66, 0x0066FF66, 0x00336666, 0x00996666, 0x00CC6666, 0x00FF6666,
501  0x00333366, 0x00333399, 0x003333CC, 0x003333FF, 0x00336633, 0x00339933,
502  0x0033CC33, 0x0033FF33, 0x00663333, 0x00993333, 0x00CC3333, 0x00FF3333,
503  0x00003366, 0x00336600, 0x00660033, 0x00006633, 0x00330066, 0x00663300,
504  0x00336699, 0x00669933, 0x00993366, 0x00339966, 0x00663399, 0x00996633,
505  0x006699CC, 0x0099CC66, 0x00CC6699, 0x0066CC99, 0x009966CC, 0x00CC9966,
506  0x0099CCFF, 0x00CCFF99, 0x00FF99CC, 0x0099FFCC, 0x00CC99FF, 0x00FFCC99,
507  0x00111111, 0x00222222, 0x00444444, 0x00555555, 0x00AAAAAA, 0x00BBBBBB,
508  0x00DDDDDD, 0x00EEEEEE
509 };
510 
511 static int generate_default_palette(Palette * palette)
512 {
513  memcpy(palette->colors, default_screen_video_v2_palette,
515 
516  return update_palette_index(palette);
517 }
518 
519 static int generate_optimum_palette(Palette * palette, const uint8_t * image,
520  int width, int height, int stride)
521 {
522  //this isn't implemented yet! Default palette only!
523  return -1;
524 }
525 
526 static inline int encode_15_7_sl(Palette * palette, uint8_t * dest,
527  const uint8_t * src, int width, int dist)
528 {
529  int len = 0, x;
530  for (x = 0; x < width; x++) {
531  len += write_pixel_15_7(palette, dest + len, src + 3 * x, dist);
532  }
533  return len;
534 }
535 
536 static int encode_15_7(Palette * palette, Block * b, const uint8_t * src,
537  int stride, int dist)
538 {
539  int i;
540  uint8_t *ptr = b->enc;
541  for (i = 0; i < b->start; i++)
542  ptr += encode_15_7_sl(palette, ptr, src + i * stride, b->width, dist);
543  b->sl_begin = ptr;
544  for (; i < b->start + b->len; i++)
545  ptr += encode_15_7_sl(palette, ptr, src + i * stride, b->width, dist);
546  b->sl_end = ptr;
547  for (; i < b->height; i++)
548  ptr += encode_15_7_sl(palette, ptr, src + i * stride, b->width, dist);
549  b->enc_size = ptr - b->enc;
550  return b->enc_size;
551 }
552 
553 static int encode_block(FlashSV2Context *s, Palette * palette, Block * b,
554  Block * prev, const uint8_t * src, int stride, int comp,
555  int dist, int keyframe)
556 {
557  unsigned buf_size = b->width * b->height * 6;
558  uint8_t *buf = s->blockbuffer;
559  int res;
560 
561  if (b->flags & COLORSPACE_15_7) {
562  encode_15_7(palette, b, src, stride, dist);
563  } else {
564  encode_bgr(b, src, stride);
565  }
566 
567  if (b->len > 0) {
568  b->data_size = buf_size;
569  res = encode_zlib(b, b->data, &b->data_size, comp);
570  if (res)
571  return res;
572 
573  if (!keyframe) {
574  res = encode_zlibprime(b, prev, buf, &buf_size, comp);
575  if (res)
576  return res;
577 
578  if (buf_size < b->data_size) {
579  b->data_size = buf_size;
580  memcpy(b->data, buf, buf_size);
582  }
583  }
584  } else {
585  b->data_size = 0;
586  }
587  return 0;
588 }
589 
590 static int compare_sl(FlashSV2Context * s, Block * b, const uint8_t * src,
591  uint8_t * frame, uint8_t * key, int y, int keyframe)
592 {
593  if (memcmp(src, frame, b->width * 3) != 0) {
594  b->dirty = 1;
595  memcpy(frame, src, b->width * 3);
596 #ifndef FLASHSV2_DUMB
597  s->diff_lines++;
598 #endif
599  }
600  if (memcmp(src, key, b->width * 3) != 0) {
601  if (b->len == 0)
602  b->start = y;
603  b->len = y + 1 - b->start;
604  }
605  return 0;
606 }
607 
608 static int mark_all_blocks(FlashSV2Context * s, const uint8_t * src, int stride,
609  int keyframe)
610 {
611  int sl, rsl, col, pos, possl;
612  Block *b;
613  for (sl = s->image_height - 1; sl >= 0; sl--) {
614  for (col = 0; col < s->cols; col++) {
615  rsl = s->image_height - sl - 1;
616  b = s->frame_blocks + col + rsl / s->block_height * s->cols;
617  possl = stride * sl + col * s->block_width * 3;
618  pos = s->image_width * rsl * 3 + col * s->block_width * 3;
619  compare_sl(s, b, src + possl, s->current_frame + pos,
620  s->key_frame + pos, rsl % s->block_height, keyframe);
621  }
622  }
623 #ifndef FLASHSV2_DUMB
624  s->tot_lines += s->image_height * s->cols;
625 #endif
626  return 0;
627 }
628 
629 static int encode_all_blocks(FlashSV2Context * s, int keyframe)
630 {
631  int row, col, res;
632  uint8_t *data;
633  Block *b, *prev;
634  for (row = 0; row < s->rows; row++) {
635  for (col = 0; col < s->cols; col++) {
636  b = s->frame_blocks + (row * s->cols + col);
637  prev = s->key_blocks + (row * s->cols + col);
638  b->flags = s->use15_7 ? COLORSPACE_15_7 : 0;
639  if (keyframe) {
640  b->start = 0;
641  b->len = b->height;
642  } else if (!b->dirty) {
643  b->start = 0;
644  b->len = 0;
645  b->data_size = 0;
646  continue;
647  } else if (b->start != 0 || b->len != b->height) {
648  b->flags |= HAS_DIFF_BLOCKS;
649  }
650  data = s->current_frame + s->image_width * 3 * s->block_height * row + s->block_width * col * 3;
651  res = encode_block(s, &s->palette, b, prev, data, s->image_width * 3, s->comp, s->dist, keyframe);
652 #ifndef FLASHSV2_DUMB
653  if (b->dirty)
654  s->diff_blocks++;
655  s->comp_size += b->data_size;
656  s->uncomp_size += b->enc_size;
657 #endif
658  if (res)
659  return res;
660  }
661  }
662 #ifndef FLASHSV2_DUMB
663  s->raw_size += s->image_width * s->image_height * 3;
664  s->tot_blocks += s->rows * s->cols;
665 #endif
666  return 0;
667 }
668 
670  int buf_size)
671 {
672  int row, col, buf_pos = 0, len;
673  Block *b;
674  for (row = 0; row < s->rows; row++) {
675  for (col = 0; col < s->cols; col++) {
676  b = s->frame_blocks + row * s->cols + col;
677  len = write_block(b, buf + buf_pos, buf_size - buf_pos);
678  b->start = b->len = b->dirty = 0;
679  if (len < 0)
680  return len;
681  buf_pos += len;
682  }
683  }
684  return buf_pos;
685 }
686 
687 static int write_bitstream(FlashSV2Context * s, const uint8_t * src, int stride,
688  uint8_t * buf, int buf_size, int keyframe)
689 {
690  int buf_pos, res;
691 
692  res = mark_all_blocks(s, src, stride, keyframe);
693  if (res)
694  return res;
695  res = encode_all_blocks(s, keyframe);
696  if (res)
697  return res;
698 
699  res = write_header(s, buf, buf_size);
700  if (res < 0) {
701  return res;
702  } else {
703  buf_pos = res;
704  }
705  res = write_all_blocks(s, buf + buf_pos, buf_size - buf_pos);
706  if (res < 0)
707  return res;
708  buf_pos += res;
709 #ifndef FLASHSV2_DUMB
710  s->total_bits += ((double) buf_pos) * 8.0;
711 #endif
712 
713  return buf_pos;
714 }
715 
716 static void recommend_keyframe(FlashSV2Context * s, int *keyframe)
717 {
718 #ifndef FLASHSV2_DUMB
719  double block_ratio, line_ratio, enc_ratio, comp_ratio, data_ratio;
720  if (s->avctx->gop_size > 0) {
721  block_ratio = s->diff_blocks / s->tot_blocks;
722  line_ratio = s->diff_lines / s->tot_lines;
723  enc_ratio = s->uncomp_size / s->raw_size;
724  comp_ratio = s->comp_size / s->uncomp_size;
725  data_ratio = s->comp_size / s->raw_size;
726 
727  if ((block_ratio >= 0.5 && line_ratio / block_ratio <= 0.5) || line_ratio >= 0.95) {
728  *keyframe = 1;
729  return;
730  }
731  }
732 #else
733  return;
734 #endif
735 }
736 
737 #ifndef FLASHSV2_DUMB
738 static const double block_size_fraction = 1.0 / 300;
739 static const double use15_7_threshold = 8192;
740 static const double color15_7_factor = 100;
741 #endif
743 {
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 width = block_size_fraction * sqrt(0.5 * save * s->rows * s->cols) * s->image_width;
747  int pwidth = ((int) width);
748  return FFCLIP(pwidth & ~15, 256, 16);
749 #else
750  return 64;
751 #endif
752 }
753 
755 {
756 #ifndef FLASHSV2_DUMB
757  double save = (1-pow(s->diff_lines/s->diff_blocks/s->block_height, 0.5)) * s->comp_size/s->tot_blocks;
758  double height = block_size_fraction * sqrt(0.5 * save * s->rows * s->cols) * s->image_height;
759  int pheight = ((int) height);
760  return FFCLIP(pheight & ~15, 256, 16);
761 #else
762  return 64;
763 #endif
764 }
765 
767 {
768 #ifndef FLASHSV2_DUMB
769  double ideal = ((double)(s->avctx->bit_rate * s->avctx->time_base.den * s->avctx->ticks_per_frame)) /
770  ((double) s->avctx->time_base.num) * s->avctx->frame_number;
771  if (ideal + use15_7_threshold < s->total_bits) {
772  return 1;
773  } else {
774  return 0;
775  }
776 #else
777  return s->avctx->global_quality == 0;
778 #endif
779 }
780 
782 {
783 #ifndef FLASHSV2_DUMB
784  double ideal =
785  s->avctx->bit_rate * s->avctx->time_base.den *
787  int dist = pow((s->total_bits / ideal) * color15_7_factor, 3);
788  av_log(s->avctx, AV_LOG_DEBUG, "dist: %d\n", dist);
789  return dist;
790 #else
791  return 15;
792 #endif
793 }
794 
795 
796 static int reconfigure_at_keyframe(FlashSV2Context * s, const uint8_t * image,
797  int stride)
798 {
799  int update_palette = 0;
800  int res;
801  int block_width = optimum_block_width (s);
802  int block_height = optimum_block_height(s);
803 
804  s->rows = (s->image_height + block_height - 1) / block_height;
805  s->cols = (s->image_width + block_width - 1) / block_width;
806 
807  if (block_width != s->block_width || block_height != s->block_height) {
808  s->block_width = block_width;
809  s->block_height = block_height;
810  if (s->rows * s->cols > s->blocks_size / sizeof(Block)) {
811  s->frame_blocks = av_realloc_array(s->frame_blocks, s->rows, s->cols * sizeof(Block));
812  s->key_blocks = av_realloc_array(s->key_blocks, s->cols, s->rows * sizeof(Block));
813  if (!s->frame_blocks || !s->key_blocks) {
814  av_log(s->avctx, AV_LOG_ERROR, "Memory allocation failed.\n");
815  return -1;
816  }
817  s->blocks_size = s->rows * s->cols * sizeof(Block);
818  }
820  init_blocks(s, s->key_blocks, s->keybuffer, 0);
821 
822  av_fast_malloc(&s->blockbuffer, &s->blockbuffer_size, block_width * block_height * 6);
823  if (!s->blockbuffer) {
824  av_log(s->avctx, AV_LOG_ERROR, "Could not allocate block buffer.\n");
825  return AVERROR(ENOMEM);
826  }
827  }
828 
829  s->use15_7 = optimum_use15_7(s);
830  if (s->use15_7) {
831  if ((s->use_custom_palette && s->palette_type != 1) || update_palette) {
832  res = generate_optimum_palette(&s->palette, image, s->image_width, s->image_height, stride);
833  if (res)
834  return res;
835  s->palette_type = 1;
836  av_log(s->avctx, AV_LOG_DEBUG, "Generated optimum palette\n");
837  } else if (!s->use_custom_palette && s->palette_type != 0) {
839  if (res)
840  return res;
841  s->palette_type = 0;
842  av_log(s->avctx, AV_LOG_DEBUG, "Generated default palette\n");
843  }
844  }
845 
846 
847  reset_stats(s);
848 
849  return 0;
850 }
851 
853  const AVFrame *p, int *got_packet)
854 {
855  FlashSV2Context *const s = avctx->priv_data;
856  int res;
857  int keyframe = 0;
858 
859  if ((res = ff_alloc_packet2(avctx, pkt, s->frame_size + AV_INPUT_BUFFER_MIN_SIZE, 0)) < 0)
860  return res;
861 
862  /* First frame needs to be a keyframe */
863  if (avctx->frame_number == 0)
864  keyframe = 1;
865 
866  /* Check the placement of keyframes */
867  if (avctx->gop_size > 0) {
868  if (avctx->frame_number >= s->last_key_frame + avctx->gop_size)
869  keyframe = 1;
870  }
871 
872  if (!keyframe
873  && avctx->frame_number > s->last_key_frame + avctx->keyint_min) {
874  recommend_keyframe(s, &keyframe);
875  if (keyframe)
876  av_log(avctx, AV_LOG_DEBUG, "Recommending key frame at frame %d\n", avctx->frame_number);
877  }
878 
879  if (keyframe) {
880  res = reconfigure_at_keyframe(s, p->data[0], p->linesize[0]);
881  if (res)
882  return res;
883  }
884 
885  if (s->use15_7)
886  s->dist = optimum_dist(s);
887 
888  res = write_bitstream(s, p->data[0], p->linesize[0], pkt->data, pkt->size, keyframe);
889 
890  if (keyframe) {
891  new_key_frame(s);
892  s->last_key_frame = avctx->frame_number;
893  pkt->flags |= AV_PKT_FLAG_KEY;
894  av_log(avctx, AV_LOG_DEBUG, "Inserting key frame at frame %d\n", avctx->frame_number);
895  }
896 
897  pkt->size = res;
898  *got_packet = 1;
899 
900  return 0;
901 }
902 
904 {
905  FlashSV2Context *s = avctx->priv_data;
906 
907  cleanup(s);
908 
909  return 0;
910 }
911 
913  .name = "flashsv2",
914  .long_name = NULL_IF_CONFIG_SMALL("Flash Screen Video Version 2"),
915  .type = AVMEDIA_TYPE_VIDEO,
916  .id = AV_CODEC_ID_FLASHSV2,
917  .priv_data_size = sizeof(FlashSV2Context),
919  .encode2 = flashsv2_encode_frame,
920  .close = flashsv2_encode_end,
922 };
uint8_t use_custom_palette
Definition: flashsv2enc.c:111
uint8_t index[1<< 15]
Definition: flashsv2enc.c:83
#define NULL
Definition: coverity.c:32
static int compare_sl(FlashSV2Context *s, Block *b, const uint8_t *src, uint8_t *frame, uint8_t *key, int y, int keyframe)
Definition: flashsv2enc.c:590
const char * s
Definition: avisynth_c.h:768
static int optimum_block_width(FlashSV2Context *s)
Definition: flashsv2enc.c:742
static void recommend_keyframe(FlashSV2Context *s, int *keyframe)
Definition: flashsv2enc.c:716
This structure describes decoded (raw) audio or video data.
Definition: frame.h:218
static int new_key_frame(FlashSV2Context *s)
Definition: flashsv2enc.c:259
uint8_t len
Definition: flashsv2enc.c:75
static unsigned pixel_color15(const uint8_t *src)
Definition: flashsv2enc.c:408
Block * frame_blocks
Definition: flashsv2enc.c:97
static int optimum_use15_7(FlashSV2Context *s)
Definition: flashsv2enc.c:766
misc image utilities
static void put_bits(Jpeg2000EncoderContext *s, int val, int n)
put n times val bit
Definition: j2kenc.c:207
int64_t bit_rate
the average bitrate
Definition: avcodec.h:1568
static int encode_zlibprime(Block *b, Block *prime, uint8_t *buf, int *buf_size, int comp)
Definition: flashsv2enc.c:358
const char * g
Definition: vf_curves.c:112
static av_cold int init(AVCodecContext *avctx)
Definition: avrndec.c:35
int num
Numerator.
Definition: rational.h:59
static const unsigned int default_screen_video_v2_palette[128]
Definition: flashsv2enc.c:486
int size
Definition: avcodec.h:1431
const char * b
Definition: vf_curves.c:113
uint8_t * sl_begin
Definition: flashsv2enc.c:70
static int generate_optimum_palette(Palette *palette, const uint8_t *image, int width, int height, int stride)
Definition: flashsv2enc.c:519
uint8_t width
Definition: flashsv2enc.c:77
int enc_size
Definition: flashsv2enc.c:71
static int optimum_dist(FlashSV2Context *s)
Definition: flashsv2enc.c:781
const char * key
static AVPacket pkt
#define src
Definition: vp8dsp.c:254
int stride
Definition: mace.c:144
AVCodec.
Definition: avcodec.h:3408
AVCodecContext * avctx
Definition: flashsv2enc.c:87
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented...
Definition: avcodec.h:1640
static av_cold int flashsv2_encode_end(AVCodecContext *avctx)
Definition: flashsv2enc.c:903
int ff_alloc_packet2(AVCodecContext *avctx, AVPacket *avpkt, int64_t size, int64_t min_size)
Check AVPacket size and/or allocate data.
Definition: encode.c:32
#define HAS_PALLET_INFO
Definition: flashsv2enc.c:56
uint8_t
#define av_cold
Definition: attributes.h:82
static int generate_default_palette(Palette *palette)
Definition: flashsv2enc.c:511
static int flashsv2_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *p, int *got_packet)
Definition: flashsv2enc.c:852
uint8_t * data
Definition: flashsv2enc.c:72
static void deflate(uint8_t *dst, const uint8_t *p1, int width, int threshold, const uint8_t *coordinates[], int coord)
Definition: vf_neighbor.c:114
static AVFrame * frame
static int encode_block(FlashSV2Context *s, Palette *palette, Block *b, Block *prev, const uint8_t *src, int stride, int comp, int dist, int keyframe)
Definition: flashsv2enc.c:553
#define ZLIB_PRIME_COMPRESS_CURRENT
Definition: flashsv2enc.c:61
uint8_t * data
Definition: avcodec.h:1430
static const uint64_t c1
Definition: murmur3.c:49
uint8_t flags
Definition: flashsv2enc.c:78
#define COLORSPACE_15_7
Definition: flashsv2enc.c:59
static unsigned int chroma_diff(unsigned int c1, unsigned int c2)
Definition: flashsv2enc.c:413
Block * key_blocks
Definition: flashsv2enc.c:98
void * av_realloc_array(void *ptr, size_t nmemb, size_t size)
Allocate, reallocate, or free an array.
Definition: mem.c:198
#define AV_INPUT_BUFFER_MIN_SIZE
minimum encoding buffer size Used to avoid some checks during header writing.
Definition: avcodec.h:780
#define av_log(a,...)
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition: avcodec.h:1462
static av_cold int flashsv2_encode_init(AVCodecContext *avctx)
Definition: flashsv2enc.c:177
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
#define ZLIB_PRIME_COMPRESS_PREVIOUS
Definition: flashsv2enc.c:62
static int encode_zlib(Block *b, uint8_t *buf, unsigned long *buf_size, int comp)
Definition: flashsv2enc.c:352
static int encode_15_7(Palette *palette, Block *b, const uint8_t *src, int stride, int dist)
Definition: flashsv2enc.c:536
#define AVERROR(e)
Definition: error.h:43
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:186
uint8_t * blockbuffer
Definition: flashsv2enc.c:94
const char * r
Definition: vf_curves.c:111
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:197
#define t1
Definition: regdef.h:29
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:236
const char * name
Name of the codec implementation.
Definition: avcodec.h:3415
int flags
A combination of AV_PKT_FLAG values.
Definition: avcodec.h:1436
AVCodec ff_flashsv2_encoder
Definition: flashsv2enc.c:912
void av_fast_malloc(void *ptr, unsigned int *size, size_t min_size)
Allocate a buffer, reusing the given one if large enough.
Definition: mem.c:488
int av_image_check_size(unsigned int w, unsigned int h, int log_offset, void *log_ctx)
Check if the given dimension of an image is valid, meaning that all bytes of the image can be address...
Definition: imgutils.c:282
uint8_t * databuffer
Definition: flashsv2enc.c:92
uint8_t dirty
Definition: flashsv2enc.c:76
int width
picture width / height.
Definition: avcodec.h:1690
static int pixel_color7_slow(Palette *palette, unsigned color)
Definition: flashsv2enc.c:430
uint8_t * keybuffer
Definition: flashsv2enc.c:91
uint8_t * key_frame
Definition: flashsv2enc.c:89
static int write_block(Block *b, uint8_t *buf, int buf_size)
Definition: flashsv2enc.c:312
packed RGB 8:8:8, 24bpp, BGRBGR...
Definition: pixfmt.h:65
int ticks_per_frame
For some codecs, the time base is closer to the field rate than the frame rate.
Definition: avcodec.h:1649
static int encode_bgr(Block *b, const uint8_t *src, int stride)
Definition: flashsv2enc.c:392
static int reconfigure_at_keyframe(FlashSV2Context *s, const uint8_t *image, int stride)
Definition: flashsv2enc.c:796
if(ret< 0)
Definition: vf_mcdeint.c:279
static void comp(unsigned char *dst, ptrdiff_t dst_stride, unsigned char *src, ptrdiff_t src_stride, int add)
Definition: eamad.c:83
#define HAS_DIFF_BLOCKS
Definition: flashsv2enc.c:60
static int write_palette(FlashSV2Context *s, uint8_t *buf, int buf_size)
Definition: flashsv2enc.c:276
static int update_palette_index(Palette *palette)
Definition: flashsv2enc.c:468
Libavcodec external API header.
int compression_level
Definition: avcodec.h:1590
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:249
main external API structure.
Definition: avcodec.h:1518
static int write_header(FlashSV2Context *s, uint8_t *buf, int buf_size)
Definition: flashsv2enc.c:282
unsigned long data_size
Definition: flashsv2enc.c:73
static int encode_15_7_sl(Palette *palette, uint8_t *dest, const uint8_t *src, int width, int dist)
Definition: flashsv2enc.c:526
void * buf
Definition: avisynth_c.h:690
uint8_t row
Definition: flashsv2enc.c:77
uint8_t start
Definition: flashsv2enc.c:75
static int mark_all_blocks(FlashSV2Context *s, const uint8_t *src, int stride, int keyframe)
Definition: flashsv2enc.c:608
int index
Definition: gxfenc.c:89
static int pixel_color7_fast(Palette *palette, unsigned c15)
Definition: flashsv2enc.c:425
static void init_blocks(FlashSV2Context *s, Block *blocks, uint8_t *encbuf, uint8_t *databuf)
Definition: flashsv2enc.c:140
static enum AVPixelFormat pix_fmts[]
Definition: libkvazaar.c:266
int global_quality
Global quality for codecs which cannot change it per frame.
Definition: avcodec.h:1584
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:232
uint8_t * enc
Definition: flashsv2enc.c:69
int gop_size
the number of pictures in a group of pictures, or 0 for intra_only
Definition: avcodec.h:1712
uint8_t height
Definition: flashsv2enc.c:77
int
static unsigned pixel_bgr(const uint8_t *src)
Definition: flashsv2enc.c:445
uint8_t palette_type
0=>default, 1=>custom - changed when palette regenerated.
Definition: flashsv2enc.c:112
common internal api header.
static void flush_put_bits(PutBitContext *s)
Pad the end of the output stream with zeros.
Definition: put_bits.h:101
static int write_all_blocks(FlashSV2Context *s, uint8_t *buf, int buf_size)
Definition: flashsv2enc.c:669
static const uint64_t c2
Definition: murmur3.c:50
static void init_put_bits(PutBitContext *s, uint8_t *buffer, int buffer_size)
Initialize the PutBitContext s.
Definition: put_bits.h:48
int den
Denominator.
Definition: rational.h:60
unsigned colors[128]
Definition: flashsv2enc.c:82
void * priv_data
Definition: avcodec.h:1545
static av_always_inline int diff(const uint32_t a, const uint32_t b)
uint8_t * current_frame
Definition: flashsv2enc.c:88
static int encode_all_blocks(FlashSV2Context *s, int keyframe)
Definition: flashsv2enc.c:629
int frame_number
Frame counter, set by libavcodec.
Definition: avcodec.h:2204
#define av_freep(p)
static int optimum_block_height(FlashSV2Context *s)
Definition: flashsv2enc.c:754
float min
#define ABSDIFF(a, b)
AVPixelFormat
Pixel format.
Definition: pixfmt.h:60
This structure stores compressed data.
Definition: avcodec.h:1407
static int write_bitstream(FlashSV2Context *s, const uint8_t *src, int stride, uint8_t *buf, int buf_size, int keyframe)
Definition: flashsv2enc.c:687
static int write_pixel_15_7(Palette *palette, uint8_t *dest, const uint8_t *src, int dist)
Definition: flashsv2enc.c:450
#define t2
Definition: regdef.h:30
static void reset_stats(FlashSV2Context *s)
Definition: flashsv2enc.c:166
static av_cold void cleanup(FlashSV2Context *s)
Definition: flashsv2enc.c:127
uint8_t col
Definition: flashsv2enc.c:77
uint8_t * encbuffer
Definition: flashsv2enc.c:90
int keyint_min
minimum GOP size
Definition: avcodec.h:2094
uint8_t * sl_end
Definition: flashsv2enc.c:70
bitstream writer API