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