55 #define HAS_IFRAME_IMAGE 0x02
56 #define HAS_PALLET_INFO 0x01
58 #define COLORSPACE_BGR 0x00
59 #define COLORSPACE_15_7 0x10
60 #define HAS_DIFF_BLOCKS 0x04
61 #define ZLIB_PRIME_COMPRESS_CURRENT 0x02
62 #define ZLIB_PRIME_COMPRESS_PREVIOUS 0x01
114 #ifndef FLASHSV2_DUMB
145 memset(blocks, 0,
s->cols *
s->rows *
sizeof(*blocks));
146 for (col = 0; col <
s->cols; col++) {
147 for (row = 0; row <
s->rows; row++) {
148 b = blocks + (col + row *
s->cols);
149 b->width = (col <
s->cols - 1) ?
151 s->image_width - col *
s->block_width;
153 b->height = (row < s->rows - 1) ?
155 s->image_height - row *
s->block_height;
161 encbuf +=
b->width *
b->height * 3;
162 databuf = databuf ? databuf +
b->width *
b->height * 6 :
NULL;
169 #ifndef FLASHSV2_DUMB
170 s->diff_blocks = 0.1;
174 s->raw_size =
s->comp_size =
s->uncomp_size = 10;
180 s->block_width = block_width;
181 s->block_height = block_height;
182 s->rows = (
s->image_height +
s->block_height - 1) /
s->block_height;
183 s->cols = (
s->image_width +
s->block_width - 1) /
s->block_width;
184 if (
s->rows *
s->cols >
s->blocks_size /
sizeof(
Block)) {
187 if (!
s->frame_blocks || !
s->key_blocks) {
191 s->blocks_size =
s->rows *
s->cols *
sizeof(
Block);
196 av_fast_malloc(&
s->blockbuffer, &
s->blockbuffer_size, block_width * block_height * 6);
197 if (!
s->blockbuffer) {
215 if (
s->comp < 0 ||
s->comp > 9) {
217 "Compression level should be 0-9, not %d\n",
s->comp);
222 if ((avctx->
width > 4095) || (avctx->
height > 4095)) {
224 "Input dimensions too large, input must be max 4095x4095 !\n");
229 "Input dimensions too small, input must be at least 16x16 !\n");
237 s->last_key_frame = 0;
239 s->image_width = avctx->
width;
240 s->image_height = avctx->
height;
242 s->frame_size =
s->image_width *
s->image_height * 3;
249 if (!
s->encbuffer || !
s->keybuffer || !
s->databuffer
250 || !
s->current_frame || !
s->key_frame) {
256 #ifndef FLASHSV2_DUMB
260 s->use_custom_palette = 0;
261 s->palette_type = -1;
269 memcpy(
s->key_blocks,
s->frame_blocks,
s->blocks_size);
270 memcpy(
s->key_frame,
s->current_frame,
s->frame_size);
272 for (
i = 0;
i <
s->rows *
s->cols;
i++) {
273 s->key_blocks[
i].enc += (
s->keybuffer -
s->encbuffer);
274 s->key_blocks[
i].sl_begin = 0;
275 s->key_blocks[
i].sl_end = 0;
276 s->key_blocks[
i].data = 0;
278 memcpy(
s->keybuffer,
s->encbuffer,
s->frame_size);
299 put_bits(&pb, 4, (
s->block_width >> 4) - 1);
301 put_bits(&pb, 4, (
s->block_height >> 4) - 1);
307 buf[buf_pos++] =
s->flags;
322 unsigned block_size =
b->data_size;
330 if (buf_size < block_size + 2)
333 buf[buf_pos++] = block_size >> 8;
334 buf[buf_pos++] = block_size;
339 buf[buf_pos++] =
b->flags;
342 buf[buf_pos++] = (
b->start);
343 buf[buf_pos++] = (
b->len);
348 buf[buf_pos++] = (
b->col);
349 buf[buf_pos++] = (
b->row);
352 memcpy(buf + buf_pos,
b->data,
b->data_size);
354 buf_pos +=
b->data_size;
361 int res = compress2(buf, buf_size,
b->sl_begin,
b->sl_end -
b->sl_begin,
comp);
362 return res == Z_OK ? 0 : -1;
366 int *buf_size,
int comp)
373 res = deflateInit(&
s,
comp);
377 s.next_in = prime->
enc;
379 while (
s.avail_in > 0) {
381 s.avail_out = *buf_size;
387 s.next_in =
b->sl_begin;
388 s.avail_in =
b->sl_end -
b->sl_begin;
390 s.avail_out = *buf_size;
393 *buf_size -=
s.avail_out;
394 if (res != Z_STREAM_END)
403 for (
i = 0;
i <
b->start;
i++)
404 memcpy(ptr +
i *
b->width * 3,
src +
i *
stride,
b->width * 3);
405 b->sl_begin = ptr +
i *
b->width * 3;
406 for (;
i <
b->start +
b->len;
i++)
407 memcpy(ptr +
i *
b->width * 3,
src +
i *
stride,
b->width * 3);
408 b->sl_end = ptr +
i *
b->width * 3;
409 for (;
i <
b->height;
i++)
410 memcpy(ptr +
i *
b->width * 3,
src +
i *
stride,
b->width * 3);
411 b->enc_size = ptr +
i *
b->width * 3 -
b->enc;
417 return (
src[0] >> 3) | ((
src[1] & 0xf8) << 2) | ((
src[2] & 0xf8) << 7);
422 #define ABSDIFF(a,b) (abs((int)(a)-(int)(b)))
424 unsigned int t1 = (
c1 & 0x000000ff) + ((
c1 & 0x0000ff00) >> 8) + ((
c1 & 0x00ff0000) >> 16);
425 unsigned int t2 = (
c2 & 0x000000ff) + ((
c2 & 0x0000ff00) >> 8) + ((
c2 & 0x00ff0000) >> 16);
428 ABSDIFF((
c1 & 0x0000ff00) >> 8 , (
c2 & 0x0000ff00) >> 8) +
429 ABSDIFF((
c1 & 0x00ff0000) >> 16, (
c2 & 0x00ff0000) >> 16);
434 return palette->
index[c15];
439 int i,
min = 0x7fffffff;
441 for (
i = 0;
i < 128;
i++) {
454 return (
src[0]) | (
src[1] << 8) | (
src[2] << 16);
465 if (dist + d15 >= d7) {
469 dest[0] = 0x80 | (c15 >> 8);
470 dest[1] = c15 & 0xff;
478 unsigned int bgr, c15,
index;
479 for (
r = 4;
r < 256;
r += 8) {
480 for (
g = 4;
g < 256;
g += 8) {
481 for (
b = 4;
b < 256;
b += 8) {
482 bgr =
b | (
g << 8) | (
r << 16);
483 c15 = (
b >> 3) | ((
g & 0xf8) << 2) | ((
r & 0xf8) << 7);
494 0x00000000, 0x00333333, 0x00666666, 0x00999999, 0x00CCCCCC, 0x00FFFFFF,
495 0x00330000, 0x00660000, 0x00990000, 0x00CC0000, 0x00FF0000, 0x00003300,
496 0x00006600, 0x00009900, 0x0000CC00, 0x0000FF00, 0x00000033, 0x00000066,
497 0x00000099, 0x000000CC, 0x000000FF, 0x00333300, 0x00666600, 0x00999900,
498 0x00CCCC00, 0x00FFFF00, 0x00003333, 0x00006666, 0x00009999, 0x0000CCCC,
499 0x0000FFFF, 0x00330033, 0x00660066, 0x00990099, 0x00CC00CC, 0x00FF00FF,
500 0x00FFFF33, 0x00FFFF66, 0x00FFFF99, 0x00FFFFCC, 0x00FF33FF, 0x00FF66FF,
501 0x00FF99FF, 0x00FFCCFF, 0x0033FFFF, 0x0066FFFF, 0x0099FFFF, 0x00CCFFFF,
502 0x00CCCC33, 0x00CCCC66, 0x00CCCC99, 0x00CCCCFF, 0x00CC33CC, 0x00CC66CC,
503 0x00CC99CC, 0x00CCFFCC, 0x0033CCCC, 0x0066CCCC, 0x0099CCCC, 0x00FFCCCC,
504 0x00999933, 0x00999966, 0x009999CC, 0x009999FF, 0x00993399, 0x00996699,
505 0x0099CC99, 0x0099FF99, 0x00339999, 0x00669999, 0x00CC9999, 0x00FF9999,
506 0x00666633, 0x00666699, 0x006666CC, 0x006666FF, 0x00663366, 0x00669966,
507 0x0066CC66, 0x0066FF66, 0x00336666, 0x00996666, 0x00CC6666, 0x00FF6666,
508 0x00333366, 0x00333399, 0x003333CC, 0x003333FF, 0x00336633, 0x00339933,
509 0x0033CC33, 0x0033FF33, 0x00663333, 0x00993333, 0x00CC3333, 0x00FF3333,
510 0x00003366, 0x00336600, 0x00660033, 0x00006633, 0x00330066, 0x00663300,
511 0x00336699, 0x00669933, 0x00993366, 0x00339966, 0x00663399, 0x00996633,
512 0x006699CC, 0x0099CC66, 0x00CC6699, 0x0066CC99, 0x009966CC, 0x00CC9966,
513 0x0099CCFF, 0x00CCFF99, 0x00FF99CC, 0x0099FFCC, 0x00CC99FF, 0x00FFCC99,
514 0x00111111, 0x00222222, 0x00444444, 0x00555555, 0x00AAAAAA, 0x00BBBBBB,
515 0x00DDDDDD, 0x00EEEEEE
537 for (x = 0; x <
width; x++) {
548 for (
i = 0;
i <
b->start;
i++)
551 for (;
i <
b->start +
b->len;
i++)
554 for (;
i <
b->height;
i++)
556 b->enc_size = ptr -
b->enc;
562 int dist,
int keyframe)
564 unsigned buf_size =
b->width *
b->height * 6;
575 b->data_size = buf_size;
585 if (buf_size < b->data_size) {
586 b->data_size = buf_size;
587 memcpy(
b->data, buf, buf_size);
600 if (memcmp(
src,
frame,
b->width * 3) != 0) {
603 #ifndef FLASHSV2_DUMB
607 if (memcmp(
src,
key,
b->width * 3) != 0) {
610 b->len = y + 1 -
b->start;
618 int sl, rsl, col,
pos, possl;
620 for (sl =
s->image_height - 1; sl >= 0; sl--) {
621 for (col = 0; col <
s->cols; col++) {
622 rsl =
s->image_height - sl - 1;
623 b =
s->frame_blocks + col + rsl /
s->block_height *
s->cols;
624 possl =
stride * sl + col *
s->block_width * 3;
625 pos =
s->image_width * rsl * 3 + col *
s->block_width * 3;
627 s->key_frame +
pos, rsl %
s->block_height, keyframe);
630 #ifndef FLASHSV2_DUMB
631 s->tot_lines +=
s->image_height *
s->cols;
641 for (row = 0; row <
s->rows; row++) {
642 for (col = 0; col <
s->cols; col++) {
643 b =
s->frame_blocks + (row *
s->cols + col);
644 prev =
s->key_blocks + (row *
s->cols + col);
649 }
else if (!
b->dirty) {
654 }
else if (
b->start != 0 ||
b->len !=
b->height) {
657 data =
s->current_frame +
s->image_width * 3 *
s->block_height * row +
s->block_width * col * 3;
659 #ifndef FLASHSV2_DUMB
662 s->comp_size +=
b->data_size;
663 s->uncomp_size +=
b->enc_size;
669 #ifndef FLASHSV2_DUMB
670 s->raw_size +=
s->image_width *
s->image_height * 3;
671 s->tot_blocks +=
s->rows *
s->cols;
679 int row, col, buf_pos = 0,
len;
681 for (row = 0; row <
s->rows; row++) {
682 for (col = 0; col <
s->cols; col++) {
683 b =
s->frame_blocks + row *
s->cols + col;
685 b->start =
b->len =
b->dirty = 0;
695 uint8_t * buf,
int buf_size,
int keyframe)
716 #ifndef FLASHSV2_DUMB
717 s->total_bits += ((double) buf_pos) * 8.0;
725 #ifndef FLASHSV2_DUMB
726 double block_ratio, line_ratio, enc_ratio, comp_ratio, data_ratio;
727 if (
s->avctx->gop_size > 0) {
728 block_ratio =
s->diff_blocks /
s->tot_blocks;
729 line_ratio =
s->diff_lines /
s->tot_lines;
730 enc_ratio =
s->uncomp_size /
s->raw_size;
731 comp_ratio =
s->comp_size /
s->uncomp_size;
732 data_ratio =
s->comp_size /
s->raw_size;
734 if ((block_ratio >= 0.5 && line_ratio / block_ratio <= 0.5) || line_ratio >= 0.95) {
744 #ifndef FLASHSV2_DUMB
745 static const double block_size_fraction = 1.0 / 300;
746 static const double use15_7_threshold = 8192;
747 static const double color15_7_factor = 100;
751 #ifndef FLASHSV2_DUMB
752 double save = (1-pow(
s->diff_lines/
s->diff_blocks/
s->block_height, 0.5)) *
s->comp_size/
s->tot_blocks;
753 double width = block_size_fraction * sqrt(0.5 * save *
s->rows *
s->cols) *
s->image_width;
755 return FFCLIP(pwidth & ~15, 256, 16);
763 #ifndef FLASHSV2_DUMB
764 double save = (1-pow(
s->diff_lines/
s->diff_blocks/
s->block_height, 0.5)) *
s->comp_size/
s->tot_blocks;
765 double height = block_size_fraction * sqrt(0.5 * save *
s->rows *
s->cols) *
s->image_height;
767 return FFCLIP(pheight & ~15, 256, 16);
775 #ifndef FLASHSV2_DUMB
776 double ideal = ((double)(
s->avctx->bit_rate *
s->avctx->time_base.den *
s->avctx->ticks_per_frame)) /
777 ((
double)
s->avctx->time_base.num) *
s->avctx->frame_number;
778 if (ideal + use15_7_threshold < s->total_bits) {
784 return s->avctx->global_quality == 0;
790 #ifndef FLASHSV2_DUMB
792 s->avctx->bit_rate *
s->avctx->time_base.den *
793 s->avctx->ticks_per_frame;
794 int dist = pow((
s->total_bits / ideal) * color15_7_factor, 3);
806 int update_palette = 0;
811 if (block_width !=
s->block_width || block_height !=
s->block_height) {
819 if ((
s->use_custom_palette &&
s->palette_type != 1) || update_palette) {
825 }
else if (!
s->use_custom_palette &&
s->palette_type != 0) {
841 const AVFrame *p,
int *got_packet)
Libavcodec external API header.
static av_cold int init(AVCodecContext *avctx)
static void comp(unsigned char *dst, ptrdiff_t dst_stride, unsigned char *src, ptrdiff_t src_stride, int add)
int ff_alloc_packet2(AVCodecContext *avctx, AVPacket *avpkt, int64_t size, int64_t min_size)
Check AVPacket size and/or allocate data.
static int optimum_dist(FlashSV2Context *s)
#define ZLIB_PRIME_COMPRESS_PREVIOUS
static int write_palette(FlashSV2Context *s, uint8_t *buf, int buf_size)
static int flashsv2_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *p, int *got_packet)
static int encode_15_7_sl(Palette *palette, uint8_t *dest, const uint8_t *src, int width, int dist)
AVCodec ff_flashsv2_encoder
static int encode_bgr(Block *b, const uint8_t *src, int stride)
static int write_block(Block *b, uint8_t *buf, int buf_size)
static unsigned int chroma_diff(unsigned int c1, unsigned int c2)
static int write_header(FlashSV2Context *s, uint8_t *buf, int buf_size)
static av_cold int flashsv2_encode_init(AVCodecContext *avctx)
static int generate_default_palette(Palette *palette)
static int encode_zlibprime(Block *b, Block *prime, uint8_t *buf, int *buf_size, int comp)
static av_cold int flashsv2_encode_end(AVCodecContext *avctx)
static int optimum_use15_7(FlashSV2Context *s)
static int write_all_blocks(FlashSV2Context *s, uint8_t *buf, int buf_size)
static int encode_zlib(Block *b, uint8_t *buf, unsigned long *buf_size, int comp)
static av_cold void cleanup(FlashSV2Context *s)
#define ZLIB_PRIME_COMPRESS_CURRENT
static int update_palette_index(Palette *palette)
static int encode_block(FlashSV2Context *s, Palette *palette, Block *b, Block *prev, const uint8_t *src, int stride, int comp, int dist, int keyframe)
static void init_blocks(FlashSV2Context *s, Block *blocks, uint8_t *encbuf, uint8_t *databuf)
static int reconfigure_at_keyframe(FlashSV2Context *s, const uint8_t *image, int stride)
static unsigned pixel_bgr(const uint8_t *src)
static int write_pixel_15_7(Palette *palette, uint8_t *dest, const uint8_t *src, int dist)
static void recommend_keyframe(FlashSV2Context *s, int *keyframe)
static int new_key_frame(FlashSV2Context *s)
static unsigned pixel_color15(const uint8_t *src)
static const unsigned int default_screen_video_v2_palette[128]
static int update_block_dimensions(FlashSV2Context *s, int block_width, int block_height)
static int optimum_block_width(FlashSV2Context *s)
static int mark_all_blocks(FlashSV2Context *s, const uint8_t *src, int stride, int keyframe)
static int compare_sl(FlashSV2Context *s, Block *b, const uint8_t *src, uint8_t *frame, uint8_t *key, int y, int keyframe)
static int optimum_block_height(FlashSV2Context *s)
static void reset_stats(FlashSV2Context *s)
static int generate_optimum_palette(Palette *palette, const uint8_t *image, int width, int height, int stride)
static int pixel_color7_fast(Palette *palette, unsigned c15)
static int write_bitstream(FlashSV2Context *s, const uint8_t *src, int stride, uint8_t *buf, int buf_size, int keyframe)
static int encode_15_7(Palette *palette, Block *b, const uint8_t *src, int stride, int dist)
static int encode_all_blocks(FlashSV2Context *s, int keyframe)
static int pixel_color7_slow(Palette *palette, unsigned color)
#define AV_INPUT_BUFFER_MIN_SIZE
minimum encoding buffer size Used to avoid some checks during header writing.
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
void av_fast_malloc(void *ptr, unsigned int *size, size_t min_size)
Allocate a buffer, reusing the given one if large enough.
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
void * av_realloc_array(void *ptr, size_t nmemb, size_t size)
Allocate, reallocate, or free an array.
int av_image_check_size(unsigned int w, unsigned int h, int log_offset, void *log_ctx)
Check if the given dimension of an image is valid, meaning that all bytes of the image can be address...
static void put_bits(Jpeg2000EncoderContext *s, int val, int n)
put n times val bit
#define FF_CODEC_CAP_INIT_CLEANUP
The codec allows calling the close function for deallocation even if the init function returned a fai...
common internal API header
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
static enum AVPixelFormat pix_fmts[]
AVPixelFormat
Pixel format.
@ AV_PIX_FMT_BGR24
packed RGB 8:8:8, 24bpp, BGRBGR...
static void init_put_bits(PutBitContext *s, uint8_t *buffer, int buffer_size)
Initialize the PutBitContext s.
static void flush_put_bits(PutBitContext *s)
Pad the end of the output stream with zeros.
main external API structure.
int width
picture width / height.
int keyint_min
minimum GOP size
int gop_size
the number of pictures in a group of pictures, or 0 for intra_only
int frame_number
Frame counter, set by libavcodec.
const char * name
Name of the codec implementation.
This structure describes decoded (raw) audio or video data.
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
This structure stores compressed data.
int flags
A combination of AV_PKT_FLAG values.
uint8_t use_custom_palette
uint8_t palette_type
0=>default, 1=>custom - changed when palette regenerated.
static void deflate(uint8_t *dst, const uint8_t *p1, int width, int threshold, const uint8_t *coordinates[], int coord, int maxc)
static av_always_inline int diff(const uint32_t a, const uint32_t b)