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 PixelFormat[]){ PIX_FMT_BGR24, PIX_FMT_NONE },
00930     .long_name      = NULL_IF_CONFIG_SMALL("Flash Screen Video Version 2"),
00931 };