00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045 #include <stdio.h>
00046 #include <stdlib.h>
00047 #include <zlib.h>
00048
00049 #include "libavutil/imgutils.h"
00050 #include "avcodec.h"
00051 #include "put_bits.h"
00052 #include "bytestream.h"
00053
00054 #define HAS_IFRAME_IMAGE 0x02
00055 #define HAS_PALLET_INFO 0x01
00056
00057 #define COLORSPACE_BGR 0x00
00058 #define COLORSPACE_15_7 0x10
00059 #define HAS_DIFF_BLOCKS 0x04
00060 #define ZLIB_PRIME_COMPRESS_CURRENT 0x02
00061 #define ZLIB_PRIME_COMPRESS_PREVIOUS 0x01
00062
00063
00064
00065 #define FLASHSV2_DUMB
00066
00067 typedef struct Block {
00068 uint8_t *enc;
00069 uint8_t *sl_begin, *sl_end;
00070 int enc_size;
00071 uint8_t *data;
00072 unsigned long data_size;
00073
00074 uint8_t start, len;
00075 uint8_t dirty;
00076 uint8_t col, row, width, height;
00077 uint8_t flags;
00078 } Block;
00079
00080 typedef struct Palette {
00081 unsigned colors[128];
00082 uint8_t index[1 << 15];
00083 } Palette;
00084
00085 typedef struct FlashSV2Context {
00086 AVCodecContext *avctx;
00087 uint8_t *current_frame;
00088 uint8_t *key_frame;
00089 AVFrame frame;
00090 uint8_t *encbuffer;
00091 uint8_t *keybuffer;
00092 uint8_t *databuffer;
00093
00094 Block *frame_blocks;
00095 Block *key_blocks;
00096 int frame_size;
00097 int blocks_size;
00098
00099 int use15_7, dist, comp;
00100
00101 int rows, cols;
00102
00103 int last_key_frame;
00104
00105 int image_width, image_height;
00106 int block_width, block_height;
00107 uint8_t flags;
00108 uint8_t use_custom_palette;
00109 uint8_t palette_type;
00110 Palette palette;
00111 #ifndef FLASHSV2_DUMB
00112 double tot_blocks;
00113 double diff_blocks;
00114 double tot_lines;
00115 double diff_lines;
00116 double raw_size;
00117 double comp_size;
00118 double uncomp_size;
00119
00120 double total_bits;
00121 #endif
00122 } FlashSV2Context;
00123
00124 static av_cold void cleanup(FlashSV2Context * s)
00125 {
00126 av_freep(&s->encbuffer);
00127 av_freep(&s->keybuffer);
00128 av_freep(&s->databuffer);
00129 av_freep(&s->current_frame);
00130 av_freep(&s->key_frame);
00131
00132 av_freep(&s->frame_blocks);
00133 av_freep(&s->key_blocks);
00134 }
00135
00136 static void init_blocks(FlashSV2Context * s, Block * blocks,
00137 uint8_t * encbuf, uint8_t * databuf)
00138 {
00139 int row, col;
00140 Block *b;
00141 for (col = 0; col < s->cols; col++) {
00142 for (row = 0; row < s->rows; row++) {
00143 b = blocks + (col + row * s->cols);
00144 b->width = (col < s->cols - 1) ?
00145 s->block_width :
00146 s->image_width - col * s->block_width;
00147
00148 b->height = (row < s->rows - 1) ?
00149 s->block_height :
00150 s->image_height - row * s->block_height;
00151
00152 b->row = row;
00153 b->col = col;
00154 b->enc = encbuf;
00155 b->data = databuf;
00156 encbuf += b->width * b->height * 3;
00157 databuf += !databuf ? 0 : b->width * b->height * 6;
00158 }
00159 }
00160 }
00161
00162 static void reset_stats(FlashSV2Context * s)
00163 {
00164 #ifndef FLASHSV2_DUMB
00165 s->diff_blocks = 0.1;
00166 s->tot_blocks = 1;
00167 s->diff_lines = 0.1;
00168 s->tot_lines = 1;
00169 s->raw_size = s->comp_size = s->uncomp_size = 10;
00170 #endif
00171 }
00172
00173 static av_cold int flashsv2_encode_init(AVCodecContext * avctx)
00174 {
00175 FlashSV2Context *s = avctx->priv_data;
00176
00177 s->avctx = avctx;
00178
00179 s->comp = avctx->compression_level;
00180 if (s->comp == -1)
00181 s->comp = 9;
00182 if (s->comp < 0 || s->comp > 9) {
00183 av_log(avctx, AV_LOG_ERROR,
00184 "Compression level should be 0-9, not %d\n", s->comp);
00185 return -1;
00186 }
00187
00188
00189 if ((avctx->width > 4095) || (avctx->height > 4095)) {
00190 av_log(avctx, AV_LOG_ERROR,
00191 "Input dimensions too large, input must be max 4096x4096 !\n");
00192 return -1;
00193 }
00194
00195 if (av_image_check_size(avctx->width, avctx->height, 0, avctx) < 0)
00196 return -1;
00197
00198
00199 s->last_key_frame = 0;
00200
00201 s->image_width = avctx->width;
00202 s->image_height = avctx->height;
00203
00204 s->block_width = (s->image_width / 12) & ~15;
00205 s->block_height = (s->image_height / 12) & ~15;
00206
00207 s->rows = (s->image_height + s->block_height - 1) / s->block_height;
00208 s->cols = (s->image_width + s->block_width - 1) / s->block_width;
00209
00210 s->frame_size = s->image_width * s->image_height * 3;
00211 s->blocks_size = s->rows * s->cols * sizeof(Block);
00212
00213 s->encbuffer = av_mallocz(s->frame_size);
00214 s->keybuffer = av_mallocz(s->frame_size);
00215 s->databuffer = av_mallocz(s->frame_size * 6);
00216 s->current_frame = av_mallocz(s->frame_size);
00217 s->key_frame = av_mallocz(s->frame_size);
00218 s->frame_blocks = av_mallocz(s->blocks_size);
00219 s->key_blocks = av_mallocz(s->blocks_size);
00220
00221 init_blocks(s, s->frame_blocks, s->encbuffer, s->databuffer);
00222 init_blocks(s, s->key_blocks, s->keybuffer, 0);
00223 reset_stats(s);
00224 #ifndef FLASHSV2_DUMB
00225 s->total_bits = 1;
00226 #endif
00227
00228 s->use_custom_palette = 0;
00229 s->palette_type = -1;
00230
00231 if (!s->encbuffer || !s->keybuffer || !s->databuffer
00232 || !s->current_frame || !s->key_frame || !s->key_blocks
00233 || !s->frame_blocks) {
00234 av_log(avctx, AV_LOG_ERROR, "Memory allocation failed.\n");
00235 cleanup(s);
00236 return -1;
00237 }
00238
00239 return 0;
00240 }
00241
00242 static int new_key_frame(FlashSV2Context * s)
00243 {
00244 int i;
00245 memcpy(s->key_blocks, s->frame_blocks, s->blocks_size);
00246 memcpy(s->key_frame, s->current_frame, s->frame_size);
00247
00248 for (i = 0; i < s->rows * s->cols; i++) {
00249 s->key_blocks[i].enc += (s->keybuffer - s->encbuffer);
00250 s->key_blocks[i].sl_begin = 0;
00251 s->key_blocks[i].sl_end = 0;
00252 s->key_blocks[i].data = 0;
00253 }
00254 FFSWAP(uint8_t * , s->keybuffer, s->encbuffer);
00255
00256 return 0;
00257 }
00258
00259 static int write_palette(FlashSV2Context * s, uint8_t * buf, int buf_size)
00260 {
00261
00262 return -1;
00263 }
00264
00265 static int write_header(FlashSV2Context * s, uint8_t * buf, int buf_size)
00266 {
00267 PutBitContext pb;
00268 int buf_pos, len;
00269
00270 if (buf_size < 5)
00271 return -1;
00272
00273 init_put_bits(&pb, buf, buf_size * 8);
00274
00275 put_bits(&pb, 4, (s->block_width >> 4) - 1);
00276 put_bits(&pb, 12, s->image_width);
00277 put_bits(&pb, 4, (s->block_height >> 4) - 1);
00278 put_bits(&pb, 12, s->image_height);
00279
00280 flush_put_bits(&pb);
00281 buf_pos = 4;
00282
00283 buf[buf_pos++] = s->flags;
00284
00285 if (s->flags & HAS_PALLET_INFO) {
00286 len = write_palette(s, buf + buf_pos, buf_size - buf_pos);
00287 if (len < 0)
00288 return -1;
00289 buf_pos += len;
00290 }
00291
00292 return buf_pos;
00293 }
00294
00295 static int write_block(Block * b, uint8_t * buf, int buf_size)
00296 {
00297 int buf_pos = 0;
00298 unsigned block_size = b->data_size;
00299
00300 if (b->flags & HAS_DIFF_BLOCKS)
00301 block_size += 2;
00302 if (b->flags & ZLIB_PRIME_COMPRESS_CURRENT)
00303 block_size += 2;
00304 if (block_size > 0)
00305 block_size += 1;
00306 if (buf_size < block_size + 2)
00307 return -1;
00308
00309 buf[buf_pos++] = block_size >> 8;
00310 buf[buf_pos++] = block_size;
00311
00312 if (block_size == 0)
00313 return buf_pos;
00314
00315 buf[buf_pos++] = b->flags;
00316
00317 if (b->flags & HAS_DIFF_BLOCKS) {
00318 buf[buf_pos++] = (b->start);
00319 buf[buf_pos++] = (b->len);
00320 }
00321
00322 if (b->flags & ZLIB_PRIME_COMPRESS_CURRENT) {
00323
00324 buf[buf_pos++] = (b->col);
00325 buf[buf_pos++] = (b->row);
00326 }
00327
00328 memcpy(buf + buf_pos, b->data, b->data_size);
00329
00330 buf_pos += b->data_size;
00331
00332 return buf_pos;
00333 }
00334
00335 static int encode_zlib(Block * b, uint8_t * buf, unsigned long *buf_size, int comp)
00336 {
00337 int res = compress2(buf, buf_size, b->sl_begin, b->sl_end - b->sl_begin, comp);
00338 return res == Z_OK ? 0 : -1;
00339 }
00340
00341 static int encode_zlibprime(Block * b, Block * prime, uint8_t * buf,
00342 int *buf_size, int comp)
00343 {
00344 z_stream s;
00345 int res;
00346 s.zalloc = NULL;
00347 s.zfree = NULL;
00348 s.opaque = NULL;
00349 res = deflateInit(&s, comp);
00350 if (res < 0)
00351 return -1;
00352
00353 s.next_in = prime->enc;
00354 s.avail_in = prime->enc_size;
00355 while (s.avail_in > 0) {
00356 s.next_out = buf;
00357 s.avail_out = *buf_size;
00358 res = deflate(&s, Z_SYNC_FLUSH);
00359 if (res < 0)
00360 return -1;
00361 }
00362
00363 s.next_in = b->sl_begin;
00364 s.avail_in = b->sl_end - b->sl_begin;
00365 s.next_out = buf;
00366 s.avail_out = *buf_size;
00367 res = deflate(&s, Z_FINISH);
00368 deflateEnd(&s);
00369 *buf_size -= s.avail_out;
00370 if (res != Z_STREAM_END)
00371 return -1;
00372 return 0;
00373 }
00374
00375 static int encode_bgr(Block * b, const uint8_t * src, int stride)
00376 {
00377 int i;
00378 uint8_t *ptr = b->enc;
00379 for (i = 0; i < b->start; i++)
00380 memcpy(ptr + i * b->width * 3, src + i * stride, b->width * 3);
00381 b->sl_begin = ptr + i * b->width * 3;
00382 for (; i < b->start + b->len; i++)
00383 memcpy(ptr + i * b->width * 3, src + i * stride, b->width * 3);
00384 b->sl_end = ptr + i * b->width * 3;
00385 for (; i < b->height; i++)
00386 memcpy(ptr + i * b->width * 3, src + i * stride, b->width * 3);
00387 b->enc_size = ptr + i * b->width * 3 - b->enc;
00388 return b->enc_size;
00389 }
00390
00391 static inline unsigned pixel_color15(const uint8_t * src)
00392 {
00393 return (src[0] >> 3) | ((src[1] & 0xf8) << 2) | ((src[2] & 0xf8) << 7);
00394 }
00395
00396 static inline unsigned int chroma_diff(unsigned int c1, unsigned int c2)
00397 {
00398 unsigned int t1 = (c1 & 0x000000ff) + ((c1 & 0x0000ff00) >> 8) + ((c1 & 0x00ff0000) >> 16);
00399 unsigned int t2 = (c2 & 0x000000ff) + ((c2 & 0x0000ff00) >> 8) + ((c2 & 0x00ff0000) >> 16);
00400
00401 return abs(t1 - t2) + abs((c1 & 0x000000ff) - (c2 & 0x000000ff)) +
00402 abs(((c1 & 0x0000ff00) >> 8) - ((c2 & 0x0000ff00) >> 8)) +
00403 abs(((c1 & 0x00ff0000) >> 16) - ((c2 & 0x00ff0000) >> 16));
00404 }
00405
00406 static inline int pixel_color7_fast(Palette * palette, unsigned c15)
00407 {
00408 return palette->index[c15];
00409 }
00410
00411 static int pixel_color7_slow(Palette * palette, unsigned color)
00412 {
00413 int i, min = 0x7fffffff;
00414 int minc = -1;
00415 for (i = 0; i < 128; i++) {
00416 int c1 = palette->colors[i];
00417 int diff = chroma_diff(c1, color);
00418 if (diff < min) {
00419 min = diff;
00420 minc = i;
00421 }
00422 }
00423 return minc;
00424 }
00425
00426 static inline unsigned pixel_bgr(const uint8_t * src)
00427 {
00428 return (src[0]) | (src[1] << 8) | (src[2] << 16);
00429 }
00430
00431 static int write_pixel_15_7(Palette * palette, uint8_t * dest, const uint8_t * src,
00432 int dist)
00433 {
00434 unsigned c15 = pixel_color15(src);
00435 unsigned color = pixel_bgr(src);
00436 int d15 = chroma_diff(color, color & 0x00f8f8f8);
00437 int c7 = pixel_color7_fast(palette, c15);
00438 int d7 = chroma_diff(color, palette->colors[c7]);
00439 if (dist + d15 >= d7) {
00440 dest[0] = c7;
00441 return 1;
00442 } else {
00443 dest[0] = 0x80 | (c15 >> 8);
00444 dest[1] = c15 & 0xff;
00445 return 2;
00446 }
00447 }
00448
00449 static int update_palette_index(Palette * palette)
00450 {
00451 int r, g, b;
00452 unsigned int bgr, c15, index;
00453 for (r = 4; r < 256; r += 8) {
00454 for (g = 4; g < 256; g += 8) {
00455 for (b = 4; b < 256; b += 8) {
00456 bgr = b | (g << 8) | (r << 16);
00457 c15 = (b >> 3) | ((g & 0xf8) << 2) | ((r & 0xf8) << 7);
00458 index = pixel_color7_slow(palette, bgr);
00459
00460 palette->index[c15] = index;
00461 }
00462 }
00463 }
00464 return 0;
00465 }
00466
00467 static const unsigned int default_screen_video_v2_palette[128] = {
00468 0x00000000, 0x00333333, 0x00666666, 0x00999999, 0x00CCCCCC, 0x00FFFFFF,
00469 0x00330000, 0x00660000, 0x00990000, 0x00CC0000, 0x00FF0000, 0x00003300,
00470 0x00006600, 0x00009900, 0x0000CC00, 0x0000FF00, 0x00000033, 0x00000066,
00471 0x00000099, 0x000000CC, 0x000000FF, 0x00333300, 0x00666600, 0x00999900,
00472 0x00CCCC00, 0x00FFFF00, 0x00003333, 0x00006666, 0x00009999, 0x0000CCCC,
00473 0x0000FFFF, 0x00330033, 0x00660066, 0x00990099, 0x00CC00CC, 0x00FF00FF,
00474 0x00FFFF33, 0x00FFFF66, 0x00FFFF99, 0x00FFFFCC, 0x00FF33FF, 0x00FF66FF,
00475 0x00FF99FF, 0x00FFCCFF, 0x0033FFFF, 0x0066FFFF, 0x0099FFFF, 0x00CCFFFF,
00476 0x00CCCC33, 0x00CCCC66, 0x00CCCC99, 0x00CCCCFF, 0x00CC33CC, 0x00CC66CC,
00477 0x00CC99CC, 0x00CCFFCC, 0x0033CCCC, 0x0066CCCC, 0x0099CCCC, 0x00FFCCCC,
00478 0x00999933, 0x00999966, 0x009999CC, 0x009999FF, 0x00993399, 0x00996699,
00479 0x0099CC99, 0x0099FF99, 0x00339999, 0x00669999, 0x00CC9999, 0x00FF9999,
00480 0x00666633, 0x00666699, 0x006666CC, 0x006666FF, 0x00663366, 0x00669966,
00481 0x0066CC66, 0x0066FF66, 0x00336666, 0x00996666, 0x00CC6666, 0x00FF6666,
00482 0x00333366, 0x00333399, 0x003333CC, 0x003333FF, 0x00336633, 0x00339933,
00483 0x0033CC33, 0x0033FF33, 0x00663333, 0x00993333, 0x00CC3333, 0x00FF3333,
00484 0x00003366, 0x00336600, 0x00660033, 0x00006633, 0x00330066, 0x00663300,
00485 0x00336699, 0x00669933, 0x00993366, 0x00339966, 0x00663399, 0x00996633,
00486 0x006699CC, 0x0099CC66, 0x00CC6699, 0x0066CC99, 0x009966CC, 0x00CC9966,
00487 0x0099CCFF, 0x00CCFF99, 0x00FF99CC, 0x0099FFCC, 0x00CC99FF, 0x00FFCC99,
00488 0x00111111, 0x00222222, 0x00444444, 0x00555555, 0x00AAAAAA, 0x00BBBBBB,
00489 0x00DDDDDD, 0x00EEEEEE
00490 };
00491
00492 static int generate_default_palette(Palette * palette)
00493 {
00494 memcpy(palette->colors, default_screen_video_v2_palette,
00495 sizeof(default_screen_video_v2_palette));
00496
00497 return update_palette_index(palette);
00498 }
00499
00500 static int generate_optimum_palette(Palette * palette, const uint8_t * image,
00501 int width, int height, int stride)
00502 {
00503
00504 return -1;
00505 }
00506
00507 static inline int encode_15_7_sl(Palette * palette, uint8_t * dest,
00508 const uint8_t * src, int width, int dist)
00509 {
00510 int len = 0, x;
00511 for (x = 0; x < width; x++) {
00512 len += write_pixel_15_7(palette, dest + len, src + 3 * x, dist);
00513 }
00514 return len;
00515 }
00516
00517 static int encode_15_7(Palette * palette, Block * b, const uint8_t * src,
00518 int stride, int dist)
00519 {
00520 int i;
00521 uint8_t *ptr = b->enc;
00522 for (i = 0; i < b->start; i++)
00523 ptr += encode_15_7_sl(palette, ptr, src + i * stride, b->width, dist);
00524 b->sl_begin = ptr;
00525 for (; i < b->start + b->len; i++)
00526 ptr += encode_15_7_sl(palette, ptr, src + i * stride, b->width, dist);
00527 b->sl_end = ptr;
00528 for (; i < b->height; i++)
00529 ptr += encode_15_7_sl(palette, ptr, src + i * stride, b->width, dist);
00530 b->enc_size = ptr - b->enc;
00531 return b->enc_size;
00532 }
00533
00534 static int encode_block(Palette * palette, Block * b, Block * prev,
00535 const uint8_t * src, int stride, int comp, int dist,
00536 int keyframe)
00537 {
00538 unsigned buf_size = b->width * b->height * 6;
00539 uint8_t buf[buf_size];
00540 int res;
00541 if (b->flags & COLORSPACE_15_7) {
00542 encode_15_7(palette, b, src, stride, dist);
00543 } else {
00544 encode_bgr(b, src, stride);
00545 }
00546
00547 if (b->len > 0) {
00548 b->data_size = buf_size;
00549 res = encode_zlib(b, b->data, &b->data_size, comp);
00550 if (res)
00551 return res;
00552
00553 if (!keyframe) {
00554 res = encode_zlibprime(b, prev, buf, &buf_size, comp);
00555 if (res)
00556 return res;
00557
00558 if (buf_size < b->data_size) {
00559 b->data_size = buf_size;
00560 memcpy(b->data, buf, buf_size);
00561 b->flags |= ZLIB_PRIME_COMPRESS_PREVIOUS;
00562 }
00563 }
00564 } else {
00565 b->data_size = 0;
00566 }
00567 return 0;
00568 }
00569
00570 static int compare_sl(FlashSV2Context * s, Block * b, const uint8_t * src,
00571 uint8_t * frame, uint8_t * key, int y, int keyframe)
00572 {
00573 if (memcmp(src, frame, b->width * 3) != 0) {
00574 b->dirty = 1;
00575 memcpy(frame, src, b->width * 3);
00576 #ifndef FLASHSV2_DUMB
00577 s->diff_lines++;
00578 #endif
00579 }
00580 if (memcmp(src, key, b->width * 3) != 0) {
00581 if (b->len == 0)
00582 b->start = y;
00583 b->len = y + 1 - b->start;
00584 }
00585 return 0;
00586 }
00587
00588 static int mark_all_blocks(FlashSV2Context * s, const uint8_t * src, int stride,
00589 int keyframe)
00590 {
00591 int sl, rsl, col, pos, possl;
00592 Block *b;
00593 for (sl = s->image_height - 1; sl >= 0; sl--) {
00594 for (col = 0; col < s->cols; col++) {
00595 rsl = s->image_height - sl - 1;
00596 b = s->frame_blocks + col + rsl / s->block_height * s->cols;
00597 possl = stride * sl + col * s->block_width * 3;
00598 pos = s->image_width * rsl * 3 + col * s->block_width * 3;
00599 compare_sl(s, b, src + possl, s->current_frame + pos,
00600 s->key_frame + pos, rsl % s->block_height, keyframe);
00601 }
00602 }
00603 #ifndef FLASHSV2_DUMB
00604 s->tot_lines += s->image_height * s->cols;
00605 #endif
00606 return 0;
00607 }
00608
00609 static int encode_all_blocks(FlashSV2Context * s, int keyframe)
00610 {
00611 int row, col, res;
00612 uint8_t *data;
00613 Block *b, *prev;
00614 for (row = 0; row < s->rows; row++) {
00615 for (col = 0; col < s->cols; col++) {
00616 b = s->frame_blocks + (row * s->cols + col);
00617 prev = s->key_blocks + (row * s->cols + col);
00618 if (keyframe) {
00619 b->start = 0;
00620 b->len = b->height;
00621 b->flags = s->use15_7 ? COLORSPACE_15_7 : 0;
00622 } else if (!b->dirty) {
00623 b->start = 0;
00624 b->len = 0;
00625 b->data_size = 0;
00626 b->flags = s->use15_7 ? COLORSPACE_15_7 : 0;
00627 continue;
00628 } else {
00629 b->flags = s->use15_7 ? COLORSPACE_15_7 | HAS_DIFF_BLOCKS : HAS_DIFF_BLOCKS;
00630 }
00631 data = s->current_frame + s->image_width * 3 * s->block_height * row + s->block_width * col * 3;
00632 res = encode_block(&s->palette, b, prev, data, s->image_width * 3, s->comp, s->dist, keyframe);
00633 #ifndef FLASHSV2_DUMB
00634 if (b->dirty)
00635 s->diff_blocks++;
00636 s->comp_size += b->data_size;
00637 s->uncomp_size += b->enc_size;
00638 #endif
00639 if (res)
00640 return res;
00641 }
00642 }
00643 #ifndef FLASHSV2_DUMB
00644 s->raw_size += s->image_width * s->image_height * 3;
00645 s->tot_blocks += s->rows * s->cols;
00646 #endif
00647 return 0;
00648 }
00649
00650 static int write_all_blocks(FlashSV2Context * s, uint8_t * buf,
00651 int buf_size)
00652 {
00653 int row, col, buf_pos = 0, len;
00654 Block *b;
00655 for (row = 0; row < s->rows; row++) {
00656 for (col = 0; col < s->cols; col++) {
00657 b = s->frame_blocks + row * s->cols + col;
00658 len = write_block(b, buf + buf_pos, buf_size - buf_pos);
00659 b->start = b->len = b->dirty = 0;
00660 if (len < 0)
00661 return len;
00662 buf_pos += len;
00663 }
00664 }
00665 return buf_pos;
00666 }
00667
00668 static int write_bitstream(FlashSV2Context * s, const uint8_t * src, int stride,
00669 uint8_t * buf, int buf_size, int keyframe)
00670 {
00671 int buf_pos, res;
00672
00673 res = mark_all_blocks(s, src, stride, keyframe);
00674 if (res)
00675 return res;
00676 res = encode_all_blocks(s, keyframe);
00677 if (res)
00678 return res;
00679
00680 res = write_header(s, buf, buf_size);
00681 if (res < 0) {
00682 return res;
00683 } else {
00684 buf_pos = res;
00685 }
00686 res = write_all_blocks(s, buf + buf_pos, buf_size - buf_pos);
00687 if (res < 0)
00688 return res;
00689 buf_pos += res;
00690 #ifndef FLASHSV2_DUMB
00691 s->total_bits += ((double) buf_pos) * 8.0;
00692 #endif
00693
00694 return buf_pos;
00695 }
00696
00697 static void recommend_keyframe(FlashSV2Context * s, int *keyframe)
00698 {
00699 #ifndef FLASHSV2_DUMB
00700 double block_ratio, line_ratio, enc_ratio, comp_ratio, data_ratio;
00701 if (s->avctx->gop_size > 0) {
00702 block_ratio = s->diff_blocks / s->tot_blocks;
00703 line_ratio = s->diff_lines / s->tot_lines;
00704 enc_ratio = s->uncomp_size / s->raw_size;
00705 comp_ratio = s->comp_size / s->uncomp_size;
00706 data_ratio = s->comp_size / s->raw_size;
00707
00708 if ((block_ratio >= 0.5 && line_ratio / block_ratio <= 0.5) || line_ratio >= 0.95) {
00709 *keyframe = 1;
00710 return;
00711 }
00712 }
00713 #else
00714 return;
00715 #endif
00716 }
00717
00718 static const double block_size_fraction = 1.0 / 300;
00719 static int optimum_block_width(FlashSV2Context * s)
00720 {
00721 #ifndef FLASHSV2_DUMB
00722 double save = (1-pow(s->diff_lines/s->diff_blocks/s->block_height, 0.5)) * s->comp_size/s->tot_blocks;
00723 double width = block_size_fraction * sqrt(0.5 * save * s->rows * s->cols) * s->image_width;
00724 int pwidth = ((int) width);
00725 return FFCLIP(pwidth & ~15, 256, 16);
00726 #else
00727 return 64;
00728 #endif
00729 }
00730
00731 static int optimum_block_height(FlashSV2Context * s)
00732 {
00733 #ifndef FLASHSV2_DUMB
00734 double save = (1-pow(s->diff_lines/s->diff_blocks/s->block_height, 0.5)) * s->comp_size/s->tot_blocks;
00735 double height = block_size_fraction * sqrt(0.5 * save * s->rows * s->cols) * s->image_height;
00736 int pheight = ((int) height);
00737 return FFCLIP(pheight & ~15, 256, 16);
00738 #else
00739 return 64;
00740 #endif
00741 }
00742
00743 static const double use15_7_threshold = 8192;
00744
00745 static int optimum_use15_7(FlashSV2Context * s)
00746 {
00747 #ifndef FLASHSV2_DUMB
00748 double ideal = ((double)(s->avctx->bit_rate * s->avctx->time_base.den * s->avctx->ticks_per_frame)) /
00749 ((double) s->avctx->time_base.num) * s->avctx->frame_number;
00750 if (ideal + use15_7_threshold < s->total_bits) {
00751 return 1;
00752 } else {
00753 return 0;
00754 }
00755 #else
00756 return s->avctx->global_quality == 0;
00757 #endif
00758 }
00759
00760 static const double color15_7_factor = 100;
00761
00762 static int optimum_dist(FlashSV2Context * s)
00763 {
00764 #ifndef FLASHSV2_DUMB
00765 double ideal =
00766 s->avctx->bit_rate * s->avctx->time_base.den *
00767 s->avctx->ticks_per_frame;
00768 int dist = pow((s->total_bits / ideal) * color15_7_factor, 3);
00769 av_log(s->avctx, AV_LOG_DEBUG, "dist: %d\n", dist);
00770 return dist;
00771 #else
00772 return 15;
00773 #endif
00774 }
00775
00776
00777 static int reconfigure_at_keyframe(FlashSV2Context * s, const uint8_t * image,
00778 int stride)
00779 {
00780 int update_palette = 0;
00781 int res;
00782 s->block_width = optimum_block_width(s);
00783 s->block_height = optimum_block_height(s);
00784
00785 s->rows = (s->image_height + s->block_height - 1) / s->block_height;
00786 s->cols = (s->image_width + s->block_width - 1) / s->block_width;
00787
00788 if (s->rows * s->cols != s->blocks_size / sizeof(Block)) {
00789 if (s->rows * s->cols > s->blocks_size / sizeof(Block)) {
00790 s->frame_blocks = av_realloc(s->frame_blocks, s->rows * s->cols * sizeof(Block));
00791 s->key_blocks = av_realloc(s->key_blocks, s->cols * s->rows * sizeof(Block));
00792 if (!s->frame_blocks || !s->key_blocks) {
00793 av_log(s->avctx, AV_LOG_ERROR, "Memory allocation failed.\n");
00794 return -1;
00795 }
00796 s->blocks_size = s->rows * s->cols * sizeof(Block);
00797 }
00798 init_blocks(s, s->frame_blocks, s->encbuffer, s->databuffer);
00799 init_blocks(s, s->key_blocks, s->keybuffer, 0);
00800
00801 }
00802
00803 s->use15_7 = optimum_use15_7(s);
00804 if (s->use15_7) {
00805 if ((s->use_custom_palette && s->palette_type != 1) || update_palette) {
00806 res = generate_optimum_palette(&s->palette, image, s->image_width, s->image_height, stride);
00807 if (res)
00808 return res;
00809 s->palette_type = 1;
00810 av_log(s->avctx, AV_LOG_DEBUG, "Generated optimum palette\n");
00811 } else if (!s->use_custom_palette && s->palette_type != 0) {
00812 res = generate_default_palette(&s->palette);
00813 if (res)
00814 return res;
00815 s->palette_type = 0;
00816 av_log(s->avctx, AV_LOG_DEBUG, "Generated default palette\n");
00817 }
00818 }
00819
00820
00821 reset_stats(s);
00822
00823 return 0;
00824 }
00825
00826 static int flashsv2_encode_frame(AVCodecContext * avctx, uint8_t * buf,
00827 int buf_size, void *data)
00828 {
00829 FlashSV2Context *const s = avctx->priv_data;
00830 AVFrame *pict = data;
00831 AVFrame *const p = &s->frame;
00832 int res;
00833 int keyframe = 0;
00834
00835 *p = *pict;
00836
00837
00838 if (avctx->frame_number == 0)
00839 keyframe = 1;
00840
00841
00842 if (avctx->gop_size > 0) {
00843 if (avctx->frame_number >= s->last_key_frame + avctx->gop_size)
00844 keyframe = 1;
00845 }
00846
00847 if (buf_size < s->frame_size) {
00848
00849 av_log(avctx, AV_LOG_ERROR, "buf_size %d < %d\n", buf_size, s->frame_size);
00850 return -1;
00851 }
00852
00853 if (!keyframe
00854 && avctx->frame_number > s->last_key_frame + avctx->keyint_min) {
00855 recommend_keyframe(s, &keyframe);
00856 if (keyframe)
00857 av_log(avctx, AV_LOG_DEBUG, "Recommending key frame at frame %d\n", avctx->frame_number);
00858 }
00859
00860 if (keyframe) {
00861 res = reconfigure_at_keyframe(s, p->data[0], p->linesize[0]);
00862 if (res)
00863 return res;
00864 }
00865
00866 if (s->use15_7)
00867 s->dist = optimum_dist(s);
00868
00869 res = write_bitstream(s, p->data[0], p->linesize[0], buf, buf_size, keyframe);
00870
00871 if (keyframe) {
00872 new_key_frame(s);
00873 p->pict_type = AV_PICTURE_TYPE_I;
00874 p->key_frame = 1;
00875 s->last_key_frame = avctx->frame_number;
00876 av_log(avctx, AV_LOG_DEBUG, "Inserting key frame at frame %d\n", avctx->frame_number);
00877 } else {
00878 p->pict_type = AV_PICTURE_TYPE_P;
00879 p->key_frame = 0;
00880 }
00881
00882 avctx->coded_frame = p;
00883
00884 return res;
00885 }
00886
00887 static av_cold int flashsv2_encode_end(AVCodecContext * avctx)
00888 {
00889 FlashSV2Context *s = avctx->priv_data;
00890
00891 cleanup(s);
00892
00893 return 0;
00894 }
00895
00896 AVCodec ff_flashsv2_encoder = {
00897 .name = "flashsv2",
00898 .type = AVMEDIA_TYPE_VIDEO,
00899 .id = CODEC_ID_FLASHSV2,
00900 .priv_data_size = sizeof(FlashSV2Context),
00901 .init = flashsv2_encode_init,
00902 .encode = flashsv2_encode_frame,
00903 .close = flashsv2_encode_end,
00904 .pix_fmts = (enum PixelFormat[]) {PIX_FMT_BGR24, PIX_FMT_NONE},
00905 .long_name = NULL_IF_CONFIG_SMALL("Flash Screen Video Version 2"),
00906 .capabilities = CODEC_CAP_EXPERIMENTAL,
00907 };