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