annotate ffmpeg/libavcodec/flashsv2enc.c @ 13:844d341cf643 tip

Back up before ISMIR
author Yading Song <yading.song@eecs.qmul.ac.uk>
date Thu, 31 Oct 2013 13:17:06 +0000
parents 6840f77b83aa
children
rev   line source
yading@10 1 /*
yading@10 2 * Flash Screen Video Version 2 encoder
yading@10 3 * Copyright (C) 2009 Joshua Warner
yading@10 4 *
yading@10 5 * This file is part of FFmpeg.
yading@10 6 *
yading@10 7 * FFmpeg is free software; you can redistribute it and/or
yading@10 8 * modify it under the terms of the GNU Lesser General Public
yading@10 9 * License as published by the Free Software Foundation; either
yading@10 10 * version 2.1 of the License, or (at your option) any later version.
yading@10 11 *
yading@10 12 * FFmpeg is distributed in the hope that it will be useful,
yading@10 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
yading@10 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
yading@10 15 * Lesser General Public License for more details.
yading@10 16 *
yading@10 17 * You should have received a copy of the GNU Lesser General Public
yading@10 18 * License along with FFmpeg; if not, write to the Free Software
yading@10 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
yading@10 20 */
yading@10 21
yading@10 22 /**
yading@10 23 * @file
yading@10 24 * Flash Screen Video Version 2 encoder
yading@10 25 * @author Joshua Warner
yading@10 26 */
yading@10 27
yading@10 28 /* Differences from version 1 stream:
yading@10 29 * NOTE: Currently, the only player that supports version 2 streams is Adobe Flash Player itself.
yading@10 30 * * Supports sending only a range of scanlines in a block,
yading@10 31 * indicating a difference from the corresponding block in the last keyframe.
yading@10 32 * * Supports initializing the zlib dictionary with data from the corresponding
yading@10 33 * block in the last keyframe, to improve compression.
yading@10 34 * * Supports a hybrid 15-bit rgb / 7-bit palette color space.
yading@10 35 */
yading@10 36
yading@10 37 /* TODO:
yading@10 38 * Don't keep Block structures for both current frame and keyframe.
yading@10 39 * Make better heuristics for deciding stream parameters (optimum_* functions). Currently these return constants.
yading@10 40 * Figure out how to encode palette information in the stream, choose an optimum palette at each keyframe.
yading@10 41 * Figure out how the zlibPrimeCompressCurrent flag works, implement support.
yading@10 42 * Find other sample files (that weren't generated here), develop a decoder.
yading@10 43 */
yading@10 44
yading@10 45 #include <stdio.h>
yading@10 46 #include <stdlib.h>
yading@10 47 #include <zlib.h>
yading@10 48
yading@10 49 #include "libavutil/imgutils.h"
yading@10 50 #include "avcodec.h"
yading@10 51 #include "internal.h"
yading@10 52 #include "put_bits.h"
yading@10 53 #include "bytestream.h"
yading@10 54
yading@10 55 #define HAS_IFRAME_IMAGE 0x02
yading@10 56 #define HAS_PALLET_INFO 0x01
yading@10 57
yading@10 58 #define COLORSPACE_BGR 0x00
yading@10 59 #define COLORSPACE_15_7 0x10
yading@10 60 #define HAS_DIFF_BLOCKS 0x04
yading@10 61 #define ZLIB_PRIME_COMPRESS_CURRENT 0x02
yading@10 62 #define ZLIB_PRIME_COMPRESS_PREVIOUS 0x01
yading@10 63
yading@10 64 // Disables experimental "smart" parameter-choosing code, as well as the statistics that it depends on.
yading@10 65 // At the moment, the "smart" code is a great example of how the parameters *shouldn't* be chosen.
yading@10 66 #define FLASHSV2_DUMB
yading@10 67
yading@10 68 typedef struct Block {
yading@10 69 uint8_t *enc;
yading@10 70 uint8_t *sl_begin, *sl_end;
yading@10 71 int enc_size;
yading@10 72 uint8_t *data;
yading@10 73 unsigned long data_size;
yading@10 74
yading@10 75 uint8_t start, len;
yading@10 76 uint8_t dirty;
yading@10 77 uint8_t col, row, width, height;
yading@10 78 uint8_t flags;
yading@10 79 } Block;
yading@10 80
yading@10 81 typedef struct Palette {
yading@10 82 unsigned colors[128];
yading@10 83 uint8_t index[1 << 15];
yading@10 84 } Palette;
yading@10 85
yading@10 86 typedef struct FlashSV2Context {
yading@10 87 AVCodecContext *avctx;
yading@10 88 uint8_t *current_frame;
yading@10 89 uint8_t *key_frame;
yading@10 90 AVFrame frame;
yading@10 91 uint8_t *encbuffer;
yading@10 92 uint8_t *keybuffer;
yading@10 93 uint8_t *databuffer;
yading@10 94
yading@10 95 uint8_t *blockbuffer;
yading@10 96 int blockbuffer_size;
yading@10 97
yading@10 98 Block *frame_blocks;
yading@10 99 Block *key_blocks;
yading@10 100 int frame_size;
yading@10 101 int blocks_size;
yading@10 102
yading@10 103 int use15_7, dist, comp;
yading@10 104
yading@10 105 int rows, cols;
yading@10 106
yading@10 107 int last_key_frame;
yading@10 108
yading@10 109 int image_width, image_height;
yading@10 110 int block_width, block_height;
yading@10 111 uint8_t flags;
yading@10 112 uint8_t use_custom_palette;
yading@10 113 uint8_t palette_type; ///< 0=>default, 1=>custom - changed when palette regenerated.
yading@10 114 Palette palette;
yading@10 115 #ifndef FLASHSV2_DUMB
yading@10 116 double tot_blocks; ///< blocks encoded since last keyframe
yading@10 117 double diff_blocks; ///< blocks that were different since last keyframe
yading@10 118 double tot_lines; ///< total scanlines in image since last keyframe
yading@10 119 double diff_lines; ///< scanlines that were different since last keyframe
yading@10 120 double raw_size; ///< size of raw frames since last keyframe
yading@10 121 double comp_size; ///< size of compressed data since last keyframe
yading@10 122 double uncomp_size; ///< size of uncompressed data since last keyframe
yading@10 123
yading@10 124 double total_bits; ///< total bits written to stream so far
yading@10 125 #endif
yading@10 126 } FlashSV2Context;
yading@10 127
yading@10 128 static av_cold void cleanup(FlashSV2Context * s)
yading@10 129 {
yading@10 130 av_freep(&s->encbuffer);
yading@10 131 av_freep(&s->keybuffer);
yading@10 132 av_freep(&s->databuffer);
yading@10 133 av_freep(&s->blockbuffer);
yading@10 134 av_freep(&s->current_frame);
yading@10 135 av_freep(&s->key_frame);
yading@10 136
yading@10 137 av_freep(&s->frame_blocks);
yading@10 138 av_freep(&s->key_blocks);
yading@10 139 }
yading@10 140
yading@10 141 static void init_blocks(FlashSV2Context * s, Block * blocks,
yading@10 142 uint8_t * encbuf, uint8_t * databuf)
yading@10 143 {
yading@10 144 int row, col;
yading@10 145 Block *b;
yading@10 146 for (col = 0; col < s->cols; col++) {
yading@10 147 for (row = 0; row < s->rows; row++) {
yading@10 148 b = blocks + (col + row * s->cols);
yading@10 149 b->width = (col < s->cols - 1) ?
yading@10 150 s->block_width :
yading@10 151 s->image_width - col * s->block_width;
yading@10 152
yading@10 153 b->height = (row < s->rows - 1) ?
yading@10 154 s->block_height :
yading@10 155 s->image_height - row * s->block_height;
yading@10 156
yading@10 157 b->row = row;
yading@10 158 b->col = col;
yading@10 159 b->enc = encbuf;
yading@10 160 b->data = databuf;
yading@10 161 encbuf += b->width * b->height * 3;
yading@10 162 databuf += !databuf ? 0 : b->width * b->height * 6;
yading@10 163 }
yading@10 164 }
yading@10 165 }
yading@10 166
yading@10 167 static void reset_stats(FlashSV2Context * s)
yading@10 168 {
yading@10 169 #ifndef FLASHSV2_DUMB
yading@10 170 s->diff_blocks = 0.1;
yading@10 171 s->tot_blocks = 1;
yading@10 172 s->diff_lines = 0.1;
yading@10 173 s->tot_lines = 1;
yading@10 174 s->raw_size = s->comp_size = s->uncomp_size = 10;
yading@10 175 #endif
yading@10 176 }
yading@10 177
yading@10 178 static av_cold int flashsv2_encode_init(AVCodecContext * avctx)
yading@10 179 {
yading@10 180 FlashSV2Context *s = avctx->priv_data;
yading@10 181
yading@10 182 s->avctx = avctx;
yading@10 183
yading@10 184 s->comp = avctx->compression_level;
yading@10 185 if (s->comp == -1)
yading@10 186 s->comp = 9;
yading@10 187 if (s->comp < 0 || s->comp > 9) {
yading@10 188 av_log(avctx, AV_LOG_ERROR,
yading@10 189 "Compression level should be 0-9, not %d\n", s->comp);
yading@10 190 return -1;
yading@10 191 }
yading@10 192
yading@10 193
yading@10 194 if ((avctx->width > 4095) || (avctx->height > 4095)) {
yading@10 195 av_log(avctx, AV_LOG_ERROR,
yading@10 196 "Input dimensions too large, input must be max 4096x4096 !\n");
yading@10 197 return -1;
yading@10 198 }
yading@10 199 if ((avctx->width < 16) || (avctx->height < 16)) {
yading@10 200 av_log(avctx, AV_LOG_ERROR,
yading@10 201 "Input dimensions too small, input must be at least 16x16 !\n");
yading@10 202 return -1;
yading@10 203 }
yading@10 204
yading@10 205 if (av_image_check_size(avctx->width, avctx->height, 0, avctx) < 0)
yading@10 206 return -1;
yading@10 207
yading@10 208
yading@10 209 s->last_key_frame = 0;
yading@10 210
yading@10 211 s->image_width = avctx->width;
yading@10 212 s->image_height = avctx->height;
yading@10 213
yading@10 214 s->block_width = (s->image_width / 12) & ~15;
yading@10 215 s->block_height = (s->image_height / 12) & ~15;
yading@10 216
yading@10 217 if(!s->block_width)
yading@10 218 s->block_width = 1;
yading@10 219 if(!s->block_height)
yading@10 220 s->block_height = 1;
yading@10 221
yading@10 222 s->rows = (s->image_height + s->block_height - 1) / s->block_height;
yading@10 223 s->cols = (s->image_width + s->block_width - 1) / s->block_width;
yading@10 224
yading@10 225 s->frame_size = s->image_width * s->image_height * 3;
yading@10 226 s->blocks_size = s->rows * s->cols * sizeof(Block);
yading@10 227
yading@10 228 s->encbuffer = av_mallocz(s->frame_size);
yading@10 229 s->keybuffer = av_mallocz(s->frame_size);
yading@10 230 s->databuffer = av_mallocz(s->frame_size * 6);
yading@10 231 s->current_frame = av_mallocz(s->frame_size);
yading@10 232 s->key_frame = av_mallocz(s->frame_size);
yading@10 233 s->frame_blocks = av_mallocz(s->blocks_size);
yading@10 234 s->key_blocks = av_mallocz(s->blocks_size);
yading@10 235
yading@10 236 s->blockbuffer = NULL;
yading@10 237 s->blockbuffer_size = 0;
yading@10 238
yading@10 239 init_blocks(s, s->frame_blocks, s->encbuffer, s->databuffer);
yading@10 240 init_blocks(s, s->key_blocks, s->keybuffer, 0);
yading@10 241 reset_stats(s);
yading@10 242 #ifndef FLASHSV2_DUMB
yading@10 243 s->total_bits = 1;
yading@10 244 #endif
yading@10 245
yading@10 246 s->use_custom_palette = 0;
yading@10 247 s->palette_type = -1; // so that the palette will be generated in reconfigure_at_keyframe
yading@10 248
yading@10 249 if (!s->encbuffer || !s->keybuffer || !s->databuffer
yading@10 250 || !s->current_frame || !s->key_frame || !s->key_blocks
yading@10 251 || !s->frame_blocks) {
yading@10 252 av_log(avctx, AV_LOG_ERROR, "Memory allocation failed.\n");
yading@10 253 cleanup(s);
yading@10 254 return -1;
yading@10 255 }
yading@10 256
yading@10 257 return 0;
yading@10 258 }
yading@10 259
yading@10 260 static int new_key_frame(FlashSV2Context * s)
yading@10 261 {
yading@10 262 int i;
yading@10 263 memcpy(s->key_blocks, s->frame_blocks, s->blocks_size);
yading@10 264 memcpy(s->key_frame, s->current_frame, s->frame_size);
yading@10 265
yading@10 266 for (i = 0; i < s->rows * s->cols; i++) {
yading@10 267 s->key_blocks[i].enc += (s->keybuffer - s->encbuffer);
yading@10 268 s->key_blocks[i].sl_begin = 0;
yading@10 269 s->key_blocks[i].sl_end = 0;
yading@10 270 s->key_blocks[i].data = 0;
yading@10 271 }
yading@10 272 memcpy(s->keybuffer, s->encbuffer, s->frame_size);
yading@10 273
yading@10 274 return 0;
yading@10 275 }
yading@10 276
yading@10 277 static int write_palette(FlashSV2Context * s, uint8_t * buf, int buf_size)
yading@10 278 {
yading@10 279 //this isn't implemented yet! Default palette only!
yading@10 280 return -1;
yading@10 281 }
yading@10 282
yading@10 283 static int write_header(FlashSV2Context * s, uint8_t * buf, int buf_size)
yading@10 284 {
yading@10 285 PutBitContext pb;
yading@10 286 int buf_pos, len;
yading@10 287
yading@10 288 if (buf_size < 5)
yading@10 289 return -1;
yading@10 290
yading@10 291 init_put_bits(&pb, buf, buf_size * 8);
yading@10 292
yading@10 293 put_bits(&pb, 4, (s->block_width >> 4) - 1);
yading@10 294 put_bits(&pb, 12, s->image_width);
yading@10 295 put_bits(&pb, 4, (s->block_height >> 4) - 1);
yading@10 296 put_bits(&pb, 12, s->image_height);
yading@10 297
yading@10 298 flush_put_bits(&pb);
yading@10 299 buf_pos = 4;
yading@10 300
yading@10 301 buf[buf_pos++] = s->flags;
yading@10 302
yading@10 303 if (s->flags & HAS_PALLET_INFO) {
yading@10 304 len = write_palette(s, buf + buf_pos, buf_size - buf_pos);
yading@10 305 if (len < 0)
yading@10 306 return -1;
yading@10 307 buf_pos += len;
yading@10 308 }
yading@10 309
yading@10 310 return buf_pos;
yading@10 311 }
yading@10 312
yading@10 313 static int write_block(Block * b, uint8_t * buf, int buf_size)
yading@10 314 {
yading@10 315 int buf_pos = 0;
yading@10 316 unsigned block_size = b->data_size;
yading@10 317
yading@10 318 if (b->flags & HAS_DIFF_BLOCKS)
yading@10 319 block_size += 2;
yading@10 320 if (b->flags & ZLIB_PRIME_COMPRESS_CURRENT)
yading@10 321 block_size += 2;
yading@10 322 if (block_size > 0)
yading@10 323 block_size += 1;
yading@10 324 if (buf_size < block_size + 2)
yading@10 325 return -1;
yading@10 326
yading@10 327 buf[buf_pos++] = block_size >> 8;
yading@10 328 buf[buf_pos++] = block_size;
yading@10 329
yading@10 330 if (block_size == 0)
yading@10 331 return buf_pos;
yading@10 332
yading@10 333 buf[buf_pos++] = b->flags;
yading@10 334
yading@10 335 if (b->flags & HAS_DIFF_BLOCKS) {
yading@10 336 buf[buf_pos++] = (b->start);
yading@10 337 buf[buf_pos++] = (b->len);
yading@10 338 }
yading@10 339
yading@10 340 if (b->flags & ZLIB_PRIME_COMPRESS_CURRENT) {
yading@10 341 //This feature of the format is poorly understood, and as of now, unused.
yading@10 342 buf[buf_pos++] = (b->col);
yading@10 343 buf[buf_pos++] = (b->row);
yading@10 344 }
yading@10 345
yading@10 346 memcpy(buf + buf_pos, b->data, b->data_size);
yading@10 347
yading@10 348 buf_pos += b->data_size;
yading@10 349
yading@10 350 return buf_pos;
yading@10 351 }
yading@10 352
yading@10 353 static int encode_zlib(Block * b, uint8_t * buf, unsigned long *buf_size, int comp)
yading@10 354 {
yading@10 355 int res = compress2(buf, buf_size, b->sl_begin, b->sl_end - b->sl_begin, comp);
yading@10 356 return res == Z_OK ? 0 : -1;
yading@10 357 }
yading@10 358
yading@10 359 static int encode_zlibprime(Block * b, Block * prime, uint8_t * buf,
yading@10 360 int *buf_size, int comp)
yading@10 361 {
yading@10 362 z_stream s;
yading@10 363 int res;
yading@10 364 s.zalloc = NULL;
yading@10 365 s.zfree = NULL;
yading@10 366 s.opaque = NULL;
yading@10 367 res = deflateInit(&s, comp);
yading@10 368 if (res < 0)
yading@10 369 return -1;
yading@10 370
yading@10 371 s.next_in = prime->enc;
yading@10 372 s.avail_in = prime->enc_size;
yading@10 373 while (s.avail_in > 0) {
yading@10 374 s.next_out = buf;
yading@10 375 s.avail_out = *buf_size;
yading@10 376 res = deflate(&s, Z_SYNC_FLUSH);
yading@10 377 if (res < 0)
yading@10 378 return -1;
yading@10 379 }
yading@10 380
yading@10 381 s.next_in = b->sl_begin;
yading@10 382 s.avail_in = b->sl_end - b->sl_begin;
yading@10 383 s.next_out = buf;
yading@10 384 s.avail_out = *buf_size;
yading@10 385 res = deflate(&s, Z_FINISH);
yading@10 386 deflateEnd(&s);
yading@10 387 *buf_size -= s.avail_out;
yading@10 388 if (res != Z_STREAM_END)
yading@10 389 return -1;
yading@10 390 return 0;
yading@10 391 }
yading@10 392
yading@10 393 static int encode_bgr(Block * b, const uint8_t * src, int stride)
yading@10 394 {
yading@10 395 int i;
yading@10 396 uint8_t *ptr = b->enc;
yading@10 397 for (i = 0; i < b->start; i++)
yading@10 398 memcpy(ptr + i * b->width * 3, src + i * stride, b->width * 3);
yading@10 399 b->sl_begin = ptr + i * b->width * 3;
yading@10 400 for (; i < b->start + b->len; i++)
yading@10 401 memcpy(ptr + i * b->width * 3, src + i * stride, b->width * 3);
yading@10 402 b->sl_end = ptr + i * b->width * 3;
yading@10 403 for (; i < b->height; i++)
yading@10 404 memcpy(ptr + i * b->width * 3, src + i * stride, b->width * 3);
yading@10 405 b->enc_size = ptr + i * b->width * 3 - b->enc;
yading@10 406 return b->enc_size;
yading@10 407 }
yading@10 408
yading@10 409 static inline unsigned pixel_color15(const uint8_t * src)
yading@10 410 {
yading@10 411 return (src[0] >> 3) | ((src[1] & 0xf8) << 2) | ((src[2] & 0xf8) << 7);
yading@10 412 }
yading@10 413
yading@10 414 static inline unsigned int chroma_diff(unsigned int c1, unsigned int c2)
yading@10 415 {
yading@10 416 unsigned int t1 = (c1 & 0x000000ff) + ((c1 & 0x0000ff00) >> 8) + ((c1 & 0x00ff0000) >> 16);
yading@10 417 unsigned int t2 = (c2 & 0x000000ff) + ((c2 & 0x0000ff00) >> 8) + ((c2 & 0x00ff0000) >> 16);
yading@10 418
yading@10 419 return abs(t1 - t2) + abs((c1 & 0x000000ff) - (c2 & 0x000000ff)) +
yading@10 420 abs(((c1 & 0x0000ff00) >> 8) - ((c2 & 0x0000ff00) >> 8)) +
yading@10 421 abs(((c1 & 0x00ff0000) >> 16) - ((c2 & 0x00ff0000) >> 16));
yading@10 422 }
yading@10 423
yading@10 424 static inline int pixel_color7_fast(Palette * palette, unsigned c15)
yading@10 425 {
yading@10 426 return palette->index[c15];
yading@10 427 }
yading@10 428
yading@10 429 static int pixel_color7_slow(Palette * palette, unsigned color)
yading@10 430 {
yading@10 431 int i, min = 0x7fffffff;
yading@10 432 int minc = -1;
yading@10 433 for (i = 0; i < 128; i++) {
yading@10 434 int c1 = palette->colors[i];
yading@10 435 int diff = chroma_diff(c1, color);
yading@10 436 if (diff < min) {
yading@10 437 min = diff;
yading@10 438 minc = i;
yading@10 439 }
yading@10 440 }
yading@10 441 return minc;
yading@10 442 }
yading@10 443
yading@10 444 static inline unsigned pixel_bgr(const uint8_t * src)
yading@10 445 {
yading@10 446 return (src[0]) | (src[1] << 8) | (src[2] << 16);
yading@10 447 }
yading@10 448
yading@10 449 static int write_pixel_15_7(Palette * palette, uint8_t * dest, const uint8_t * src,
yading@10 450 int dist)
yading@10 451 {
yading@10 452 unsigned c15 = pixel_color15(src);
yading@10 453 unsigned color = pixel_bgr(src);
yading@10 454 int d15 = chroma_diff(color, color & 0x00f8f8f8);
yading@10 455 int c7 = pixel_color7_fast(palette, c15);
yading@10 456 int d7 = chroma_diff(color, palette->colors[c7]);
yading@10 457 if (dist + d15 >= d7) {
yading@10 458 dest[0] = c7;
yading@10 459 return 1;
yading@10 460 } else {
yading@10 461 dest[0] = 0x80 | (c15 >> 8);
yading@10 462 dest[1] = c15 & 0xff;
yading@10 463 return 2;
yading@10 464 }
yading@10 465 }
yading@10 466
yading@10 467 static int update_palette_index(Palette * palette)
yading@10 468 {
yading@10 469 int r, g, b;
yading@10 470 unsigned int bgr, c15, index;
yading@10 471 for (r = 4; r < 256; r += 8) {
yading@10 472 for (g = 4; g < 256; g += 8) {
yading@10 473 for (b = 4; b < 256; b += 8) {
yading@10 474 bgr = b | (g << 8) | (r << 16);
yading@10 475 c15 = (b >> 3) | ((g & 0xf8) << 2) | ((r & 0xf8) << 7);
yading@10 476 index = pixel_color7_slow(palette, bgr);
yading@10 477
yading@10 478 palette->index[c15] = index;
yading@10 479 }
yading@10 480 }
yading@10 481 }
yading@10 482 return 0;
yading@10 483 }
yading@10 484
yading@10 485 static const unsigned int default_screen_video_v2_palette[128] = {
yading@10 486 0x00000000, 0x00333333, 0x00666666, 0x00999999, 0x00CCCCCC, 0x00FFFFFF,
yading@10 487 0x00330000, 0x00660000, 0x00990000, 0x00CC0000, 0x00FF0000, 0x00003300,
yading@10 488 0x00006600, 0x00009900, 0x0000CC00, 0x0000FF00, 0x00000033, 0x00000066,
yading@10 489 0x00000099, 0x000000CC, 0x000000FF, 0x00333300, 0x00666600, 0x00999900,
yading@10 490 0x00CCCC00, 0x00FFFF00, 0x00003333, 0x00006666, 0x00009999, 0x0000CCCC,
yading@10 491 0x0000FFFF, 0x00330033, 0x00660066, 0x00990099, 0x00CC00CC, 0x00FF00FF,
yading@10 492 0x00FFFF33, 0x00FFFF66, 0x00FFFF99, 0x00FFFFCC, 0x00FF33FF, 0x00FF66FF,
yading@10 493 0x00FF99FF, 0x00FFCCFF, 0x0033FFFF, 0x0066FFFF, 0x0099FFFF, 0x00CCFFFF,
yading@10 494 0x00CCCC33, 0x00CCCC66, 0x00CCCC99, 0x00CCCCFF, 0x00CC33CC, 0x00CC66CC,
yading@10 495 0x00CC99CC, 0x00CCFFCC, 0x0033CCCC, 0x0066CCCC, 0x0099CCCC, 0x00FFCCCC,
yading@10 496 0x00999933, 0x00999966, 0x009999CC, 0x009999FF, 0x00993399, 0x00996699,
yading@10 497 0x0099CC99, 0x0099FF99, 0x00339999, 0x00669999, 0x00CC9999, 0x00FF9999,
yading@10 498 0x00666633, 0x00666699, 0x006666CC, 0x006666FF, 0x00663366, 0x00669966,
yading@10 499 0x0066CC66, 0x0066FF66, 0x00336666, 0x00996666, 0x00CC6666, 0x00FF6666,
yading@10 500 0x00333366, 0x00333399, 0x003333CC, 0x003333FF, 0x00336633, 0x00339933,
yading@10 501 0x0033CC33, 0x0033FF33, 0x00663333, 0x00993333, 0x00CC3333, 0x00FF3333,
yading@10 502 0x00003366, 0x00336600, 0x00660033, 0x00006633, 0x00330066, 0x00663300,
yading@10 503 0x00336699, 0x00669933, 0x00993366, 0x00339966, 0x00663399, 0x00996633,
yading@10 504 0x006699CC, 0x0099CC66, 0x00CC6699, 0x0066CC99, 0x009966CC, 0x00CC9966,
yading@10 505 0x0099CCFF, 0x00CCFF99, 0x00FF99CC, 0x0099FFCC, 0x00CC99FF, 0x00FFCC99,
yading@10 506 0x00111111, 0x00222222, 0x00444444, 0x00555555, 0x00AAAAAA, 0x00BBBBBB,
yading@10 507 0x00DDDDDD, 0x00EEEEEE
yading@10 508 };
yading@10 509
yading@10 510 static int generate_default_palette(Palette * palette)
yading@10 511 {
yading@10 512 memcpy(palette->colors, default_screen_video_v2_palette,
yading@10 513 sizeof(default_screen_video_v2_palette));
yading@10 514
yading@10 515 return update_palette_index(palette);
yading@10 516 }
yading@10 517
yading@10 518 static int generate_optimum_palette(Palette * palette, const uint8_t * image,
yading@10 519 int width, int height, int stride)
yading@10 520 {
yading@10 521 //this isn't implemented yet! Default palette only!
yading@10 522 return -1;
yading@10 523 }
yading@10 524
yading@10 525 static inline int encode_15_7_sl(Palette * palette, uint8_t * dest,
yading@10 526 const uint8_t * src, int width, int dist)
yading@10 527 {
yading@10 528 int len = 0, x;
yading@10 529 for (x = 0; x < width; x++) {
yading@10 530 len += write_pixel_15_7(palette, dest + len, src + 3 * x, dist);
yading@10 531 }
yading@10 532 return len;
yading@10 533 }
yading@10 534
yading@10 535 static int encode_15_7(Palette * palette, Block * b, const uint8_t * src,
yading@10 536 int stride, int dist)
yading@10 537 {
yading@10 538 int i;
yading@10 539 uint8_t *ptr = b->enc;
yading@10 540 for (i = 0; i < b->start; i++)
yading@10 541 ptr += encode_15_7_sl(palette, ptr, src + i * stride, b->width, dist);
yading@10 542 b->sl_begin = ptr;
yading@10 543 for (; i < b->start + b->len; i++)
yading@10 544 ptr += encode_15_7_sl(palette, ptr, src + i * stride, b->width, dist);
yading@10 545 b->sl_end = ptr;
yading@10 546 for (; i < b->height; i++)
yading@10 547 ptr += encode_15_7_sl(palette, ptr, src + i * stride, b->width, dist);
yading@10 548 b->enc_size = ptr - b->enc;
yading@10 549 return b->enc_size;
yading@10 550 }
yading@10 551
yading@10 552 static int encode_block(FlashSV2Context *s, Palette * palette, Block * b,
yading@10 553 Block * prev, const uint8_t * src, int stride, int comp,
yading@10 554 int dist, int keyframe)
yading@10 555 {
yading@10 556 unsigned buf_size = b->width * b->height * 6;
yading@10 557 uint8_t *buf = s->blockbuffer;
yading@10 558 int res;
yading@10 559
yading@10 560 if (b->flags & COLORSPACE_15_7) {
yading@10 561 encode_15_7(palette, b, src, stride, dist);
yading@10 562 } else {
yading@10 563 encode_bgr(b, src, stride);
yading@10 564 }
yading@10 565
yading@10 566 if (b->len > 0) {
yading@10 567 b->data_size = buf_size;
yading@10 568 res = encode_zlib(b, b->data, &b->data_size, comp);
yading@10 569 if (res)
yading@10 570 return res;
yading@10 571
yading@10 572 if (!keyframe) {
yading@10 573 res = encode_zlibprime(b, prev, buf, &buf_size, comp);
yading@10 574 if (res)
yading@10 575 return res;
yading@10 576
yading@10 577 if (buf_size < b->data_size) {
yading@10 578 b->data_size = buf_size;
yading@10 579 memcpy(b->data, buf, buf_size);
yading@10 580 b->flags |= ZLIB_PRIME_COMPRESS_PREVIOUS;
yading@10 581 }
yading@10 582 }
yading@10 583 } else {
yading@10 584 b->data_size = 0;
yading@10 585 }
yading@10 586 return 0;
yading@10 587 }
yading@10 588
yading@10 589 static int compare_sl(FlashSV2Context * s, Block * b, const uint8_t * src,
yading@10 590 uint8_t * frame, uint8_t * key, int y, int keyframe)
yading@10 591 {
yading@10 592 if (memcmp(src, frame, b->width * 3) != 0) {
yading@10 593 b->dirty = 1;
yading@10 594 memcpy(frame, src, b->width * 3);
yading@10 595 #ifndef FLASHSV2_DUMB
yading@10 596 s->diff_lines++;
yading@10 597 #endif
yading@10 598 }
yading@10 599 if (memcmp(src, key, b->width * 3) != 0) {
yading@10 600 if (b->len == 0)
yading@10 601 b->start = y;
yading@10 602 b->len = y + 1 - b->start;
yading@10 603 }
yading@10 604 return 0;
yading@10 605 }
yading@10 606
yading@10 607 static int mark_all_blocks(FlashSV2Context * s, const uint8_t * src, int stride,
yading@10 608 int keyframe)
yading@10 609 {
yading@10 610 int sl, rsl, col, pos, possl;
yading@10 611 Block *b;
yading@10 612 for (sl = s->image_height - 1; sl >= 0; sl--) {
yading@10 613 for (col = 0; col < s->cols; col++) {
yading@10 614 rsl = s->image_height - sl - 1;
yading@10 615 b = s->frame_blocks + col + rsl / s->block_height * s->cols;
yading@10 616 possl = stride * sl + col * s->block_width * 3;
yading@10 617 pos = s->image_width * rsl * 3 + col * s->block_width * 3;
yading@10 618 compare_sl(s, b, src + possl, s->current_frame + pos,
yading@10 619 s->key_frame + pos, rsl % s->block_height, keyframe);
yading@10 620 }
yading@10 621 }
yading@10 622 #ifndef FLASHSV2_DUMB
yading@10 623 s->tot_lines += s->image_height * s->cols;
yading@10 624 #endif
yading@10 625 return 0;
yading@10 626 }
yading@10 627
yading@10 628 static int encode_all_blocks(FlashSV2Context * s, int keyframe)
yading@10 629 {
yading@10 630 int row, col, res;
yading@10 631 uint8_t *data;
yading@10 632 Block *b, *prev;
yading@10 633 for (row = 0; row < s->rows; row++) {
yading@10 634 for (col = 0; col < s->cols; col++) {
yading@10 635 b = s->frame_blocks + (row * s->cols + col);
yading@10 636 prev = s->key_blocks + (row * s->cols + col);
yading@10 637 b->flags = s->use15_7 ? COLORSPACE_15_7 : 0;
yading@10 638 if (keyframe) {
yading@10 639 b->start = 0;
yading@10 640 b->len = b->height;
yading@10 641 } else if (!b->dirty) {
yading@10 642 b->start = 0;
yading@10 643 b->len = 0;
yading@10 644 b->data_size = 0;
yading@10 645 continue;
yading@10 646 } else if (b->start != 0 || b->len != b->height) {
yading@10 647 b->flags |= HAS_DIFF_BLOCKS;
yading@10 648 }
yading@10 649 data = s->current_frame + s->image_width * 3 * s->block_height * row + s->block_width * col * 3;
yading@10 650 res = encode_block(s, &s->palette, b, prev, data, s->image_width * 3, s->comp, s->dist, keyframe);
yading@10 651 #ifndef FLASHSV2_DUMB
yading@10 652 if (b->dirty)
yading@10 653 s->diff_blocks++;
yading@10 654 s->comp_size += b->data_size;
yading@10 655 s->uncomp_size += b->enc_size;
yading@10 656 #endif
yading@10 657 if (res)
yading@10 658 return res;
yading@10 659 }
yading@10 660 }
yading@10 661 #ifndef FLASHSV2_DUMB
yading@10 662 s->raw_size += s->image_width * s->image_height * 3;
yading@10 663 s->tot_blocks += s->rows * s->cols;
yading@10 664 #endif
yading@10 665 return 0;
yading@10 666 }
yading@10 667
yading@10 668 static int write_all_blocks(FlashSV2Context * s, uint8_t * buf,
yading@10 669 int buf_size)
yading@10 670 {
yading@10 671 int row, col, buf_pos = 0, len;
yading@10 672 Block *b;
yading@10 673 for (row = 0; row < s->rows; row++) {
yading@10 674 for (col = 0; col < s->cols; col++) {
yading@10 675 b = s->frame_blocks + row * s->cols + col;
yading@10 676 len = write_block(b, buf + buf_pos, buf_size - buf_pos);
yading@10 677 b->start = b->len = b->dirty = 0;
yading@10 678 if (len < 0)
yading@10 679 return len;
yading@10 680 buf_pos += len;
yading@10 681 }
yading@10 682 }
yading@10 683 return buf_pos;
yading@10 684 }
yading@10 685
yading@10 686 static int write_bitstream(FlashSV2Context * s, const uint8_t * src, int stride,
yading@10 687 uint8_t * buf, int buf_size, int keyframe)
yading@10 688 {
yading@10 689 int buf_pos, res;
yading@10 690
yading@10 691 res = mark_all_blocks(s, src, stride, keyframe);
yading@10 692 if (res)
yading@10 693 return res;
yading@10 694 res = encode_all_blocks(s, keyframe);
yading@10 695 if (res)
yading@10 696 return res;
yading@10 697
yading@10 698 res = write_header(s, buf, buf_size);
yading@10 699 if (res < 0) {
yading@10 700 return res;
yading@10 701 } else {
yading@10 702 buf_pos = res;
yading@10 703 }
yading@10 704 res = write_all_blocks(s, buf + buf_pos, buf_size - buf_pos);
yading@10 705 if (res < 0)
yading@10 706 return res;
yading@10 707 buf_pos += res;
yading@10 708 #ifndef FLASHSV2_DUMB
yading@10 709 s->total_bits += ((double) buf_pos) * 8.0;
yading@10 710 #endif
yading@10 711
yading@10 712 return buf_pos;
yading@10 713 }
yading@10 714
yading@10 715 static void recommend_keyframe(FlashSV2Context * s, int *keyframe)
yading@10 716 {
yading@10 717 #ifndef FLASHSV2_DUMB
yading@10 718 double block_ratio, line_ratio, enc_ratio, comp_ratio, data_ratio;
yading@10 719 if (s->avctx->gop_size > 0) {
yading@10 720 block_ratio = s->diff_blocks / s->tot_blocks;
yading@10 721 line_ratio = s->diff_lines / s->tot_lines;
yading@10 722 enc_ratio = s->uncomp_size / s->raw_size;
yading@10 723 comp_ratio = s->comp_size / s->uncomp_size;
yading@10 724 data_ratio = s->comp_size / s->raw_size;
yading@10 725
yading@10 726 if ((block_ratio >= 0.5 && line_ratio / block_ratio <= 0.5) || line_ratio >= 0.95) {
yading@10 727 *keyframe = 1;
yading@10 728 return;
yading@10 729 }
yading@10 730 }
yading@10 731 #else
yading@10 732 return;
yading@10 733 #endif
yading@10 734 }
yading@10 735
yading@10 736 static const double block_size_fraction = 1.0 / 300;
yading@10 737 static int optimum_block_width(FlashSV2Context * s)
yading@10 738 {
yading@10 739 #ifndef FLASHSV2_DUMB
yading@10 740 double save = (1-pow(s->diff_lines/s->diff_blocks/s->block_height, 0.5)) * s->comp_size/s->tot_blocks;
yading@10 741 double width = block_size_fraction * sqrt(0.5 * save * s->rows * s->cols) * s->image_width;
yading@10 742 int pwidth = ((int) width);
yading@10 743 return FFCLIP(pwidth & ~15, 256, 16);
yading@10 744 #else
yading@10 745 return 64;
yading@10 746 #endif
yading@10 747 }
yading@10 748
yading@10 749 static int optimum_block_height(FlashSV2Context * s)
yading@10 750 {
yading@10 751 #ifndef FLASHSV2_DUMB
yading@10 752 double save = (1-pow(s->diff_lines/s->diff_blocks/s->block_height, 0.5)) * s->comp_size/s->tot_blocks;
yading@10 753 double height = block_size_fraction * sqrt(0.5 * save * s->rows * s->cols) * s->image_height;
yading@10 754 int pheight = ((int) height);
yading@10 755 return FFCLIP(pheight & ~15, 256, 16);
yading@10 756 #else
yading@10 757 return 64;
yading@10 758 #endif
yading@10 759 }
yading@10 760
yading@10 761 static const double use15_7_threshold = 8192;
yading@10 762
yading@10 763 static int optimum_use15_7(FlashSV2Context * s)
yading@10 764 {
yading@10 765 #ifndef FLASHSV2_DUMB
yading@10 766 double ideal = ((double)(s->avctx->bit_rate * s->avctx->time_base.den * s->avctx->ticks_per_frame)) /
yading@10 767 ((double) s->avctx->time_base.num) * s->avctx->frame_number;
yading@10 768 if (ideal + use15_7_threshold < s->total_bits) {
yading@10 769 return 1;
yading@10 770 } else {
yading@10 771 return 0;
yading@10 772 }
yading@10 773 #else
yading@10 774 return s->avctx->global_quality == 0;
yading@10 775 #endif
yading@10 776 }
yading@10 777
yading@10 778 static const double color15_7_factor = 100;
yading@10 779
yading@10 780 static int optimum_dist(FlashSV2Context * s)
yading@10 781 {
yading@10 782 #ifndef FLASHSV2_DUMB
yading@10 783 double ideal =
yading@10 784 s->avctx->bit_rate * s->avctx->time_base.den *
yading@10 785 s->avctx->ticks_per_frame;
yading@10 786 int dist = pow((s->total_bits / ideal) * color15_7_factor, 3);
yading@10 787 av_log(s->avctx, AV_LOG_DEBUG, "dist: %d\n", dist);
yading@10 788 return dist;
yading@10 789 #else
yading@10 790 return 15;
yading@10 791 #endif
yading@10 792 }
yading@10 793
yading@10 794
yading@10 795 static int reconfigure_at_keyframe(FlashSV2Context * s, const uint8_t * image,
yading@10 796 int stride)
yading@10 797 {
yading@10 798 int update_palette = 0;
yading@10 799 int res;
yading@10 800 int block_width = optimum_block_width (s);
yading@10 801 int block_height = optimum_block_height(s);
yading@10 802
yading@10 803 s->rows = (s->image_height + block_height - 1) / block_height;
yading@10 804 s->cols = (s->image_width + block_width - 1) / block_width;
yading@10 805
yading@10 806 if (block_width != s->block_width || block_height != s->block_height) {
yading@10 807 s->block_width = block_width;
yading@10 808 s->block_height = block_height;
yading@10 809 if (s->rows * s->cols > s->blocks_size / sizeof(Block)) {
yading@10 810 s->frame_blocks = av_realloc(s->frame_blocks, s->rows * s->cols * sizeof(Block));
yading@10 811 s->key_blocks = av_realloc(s->key_blocks, s->cols * s->rows * sizeof(Block));
yading@10 812 if (!s->frame_blocks || !s->key_blocks) {
yading@10 813 av_log(s->avctx, AV_LOG_ERROR, "Memory allocation failed.\n");
yading@10 814 return -1;
yading@10 815 }
yading@10 816 s->blocks_size = s->rows * s->cols * sizeof(Block);
yading@10 817 }
yading@10 818 init_blocks(s, s->frame_blocks, s->encbuffer, s->databuffer);
yading@10 819 init_blocks(s, s->key_blocks, s->keybuffer, 0);
yading@10 820
yading@10 821 av_fast_malloc(&s->blockbuffer, &s->blockbuffer_size, block_width * block_height * 6);
yading@10 822 if (!s->blockbuffer) {
yading@10 823 av_log(s->avctx, AV_LOG_ERROR, "Could not allocate block buffer.\n");
yading@10 824 return AVERROR(ENOMEM);
yading@10 825 }
yading@10 826 }
yading@10 827
yading@10 828 s->use15_7 = optimum_use15_7(s);
yading@10 829 if (s->use15_7) {
yading@10 830 if ((s->use_custom_palette && s->palette_type != 1) || update_palette) {
yading@10 831 res = generate_optimum_palette(&s->palette, image, s->image_width, s->image_height, stride);
yading@10 832 if (res)
yading@10 833 return res;
yading@10 834 s->palette_type = 1;
yading@10 835 av_log(s->avctx, AV_LOG_DEBUG, "Generated optimum palette\n");
yading@10 836 } else if (!s->use_custom_palette && s->palette_type != 0) {
yading@10 837 res = generate_default_palette(&s->palette);
yading@10 838 if (res)
yading@10 839 return res;
yading@10 840 s->palette_type = 0;
yading@10 841 av_log(s->avctx, AV_LOG_DEBUG, "Generated default palette\n");
yading@10 842 }
yading@10 843 }
yading@10 844
yading@10 845
yading@10 846 reset_stats(s);
yading@10 847
yading@10 848 return 0;
yading@10 849 }
yading@10 850
yading@10 851 static int flashsv2_encode_frame(AVCodecContext *avctx, AVPacket *pkt,
yading@10 852 const AVFrame *pict, int *got_packet)
yading@10 853 {
yading@10 854 FlashSV2Context *const s = avctx->priv_data;
yading@10 855 AVFrame *const p = &s->frame;
yading@10 856 int res;
yading@10 857 int keyframe = 0;
yading@10 858
yading@10 859 *p = *pict;
yading@10 860
yading@10 861 if ((res = ff_alloc_packet2(avctx, pkt, s->frame_size + FF_MIN_BUFFER_SIZE)) < 0)
yading@10 862 return res;
yading@10 863
yading@10 864 /* First frame needs to be a keyframe */
yading@10 865 if (avctx->frame_number == 0)
yading@10 866 keyframe = 1;
yading@10 867
yading@10 868 /* Check the placement of keyframes */
yading@10 869 if (avctx->gop_size > 0) {
yading@10 870 if (avctx->frame_number >= s->last_key_frame + avctx->gop_size)
yading@10 871 keyframe = 1;
yading@10 872 }
yading@10 873
yading@10 874 if (!keyframe
yading@10 875 && avctx->frame_number > s->last_key_frame + avctx->keyint_min) {
yading@10 876 recommend_keyframe(s, &keyframe);
yading@10 877 if (keyframe)
yading@10 878 av_log(avctx, AV_LOG_DEBUG, "Recommending key frame at frame %d\n", avctx->frame_number);
yading@10 879 }
yading@10 880
yading@10 881 if (keyframe) {
yading@10 882 res = reconfigure_at_keyframe(s, p->data[0], p->linesize[0]);
yading@10 883 if (res)
yading@10 884 return res;
yading@10 885 }
yading@10 886
yading@10 887 if (s->use15_7)
yading@10 888 s->dist = optimum_dist(s);
yading@10 889
yading@10 890 res = write_bitstream(s, p->data[0], p->linesize[0], pkt->data, pkt->size, keyframe);
yading@10 891
yading@10 892 if (keyframe) {
yading@10 893 new_key_frame(s);
yading@10 894 p->pict_type = AV_PICTURE_TYPE_I;
yading@10 895 p->key_frame = 1;
yading@10 896 s->last_key_frame = avctx->frame_number;
yading@10 897 pkt->flags |= AV_PKT_FLAG_KEY;
yading@10 898 av_log(avctx, AV_LOG_DEBUG, "Inserting key frame at frame %d\n", avctx->frame_number);
yading@10 899 } else {
yading@10 900 p->pict_type = AV_PICTURE_TYPE_P;
yading@10 901 p->key_frame = 0;
yading@10 902 }
yading@10 903
yading@10 904 avctx->coded_frame = p;
yading@10 905
yading@10 906 pkt->size = res;
yading@10 907 *got_packet = 1;
yading@10 908
yading@10 909 return 0;
yading@10 910 }
yading@10 911
yading@10 912 static av_cold int flashsv2_encode_end(AVCodecContext * avctx)
yading@10 913 {
yading@10 914 FlashSV2Context *s = avctx->priv_data;
yading@10 915
yading@10 916 cleanup(s);
yading@10 917
yading@10 918 return 0;
yading@10 919 }
yading@10 920
yading@10 921 AVCodec ff_flashsv2_encoder = {
yading@10 922 .name = "flashsv2",
yading@10 923 .type = AVMEDIA_TYPE_VIDEO,
yading@10 924 .id = AV_CODEC_ID_FLASHSV2,
yading@10 925 .priv_data_size = sizeof(FlashSV2Context),
yading@10 926 .init = flashsv2_encode_init,
yading@10 927 .encode2 = flashsv2_encode_frame,
yading@10 928 .close = flashsv2_encode_end,
yading@10 929 .pix_fmts = (const enum AVPixelFormat[]){ AV_PIX_FMT_BGR24, AV_PIX_FMT_NONE },
yading@10 930 .long_name = NULL_IF_CONFIG_SMALL("Flash Screen Video Version 2"),
yading@10 931 };