64 #define SQR(x) ((x) * (x)) 67 #define GET_CHAN(color, chan) (((color) >> ((chan) * 5) & 0x1F) * 8) 68 #define R(color) GET_CHAN(color, RED) 69 #define G(color) GET_CHAN(color, GREEN) 70 #define B(color) GET_CHAN(color, BLUE) 90 color4[0][0] = min[0];
91 color4[0][1] = min[1];
92 color4[0][2] = min[2];
94 color4[3][0] = max[0];
95 color4[3][1] = max[1];
96 color4[3][2] = max[2];
99 step = (color4[3][0] - color4[0][0] + 1) / 3;
100 color4[1][0] = color4[0][0] +
step;
101 color4[2][0] = color4[3][0] -
step;
104 step = (color4[3][1] - color4[0][1] + 1) / 3;
105 color4[1][1] = color4[0][1] +
step;
106 color4[2][1] = color4[3][1] -
step;
109 step = (color4[3][2] - color4[0][2] + 1) / 3;
110 color4[1][2] = color4[0][2] +
step;
111 color4[2][2] = color4[3][2] -
step;
160 tot =
SQR(colorA[0] - colorB[0]);
161 tot +=
SQR(colorA[1] - colorB[1]);
162 tot +=
SQR(colorA[2] - colorB[2]);
174 diff =
FFABS(
R(colorA[0]) -
R(colorB[0]));
178 diff =
FFABS(
G(colorA[0]) -
G(colorB[0]));
182 diff =
FFABS(
B(colorA[0]) -
B(colorB[0]));
198 uint8_t min_r, max_r, min_g, max_g, min_b, max_b;
202 min_r = min_g = min_b = UINT8_MAX;
203 max_r = max_g = max_b = 0;
209 min_r =
FFMIN(
R(block_ptr[x]), min_r);
210 min_g =
FFMIN(
G(block_ptr[x]), min_g);
211 min_b =
FFMIN(
B(block_ptr[x]), min_b);
213 max_r =
FFMAX(
R(block_ptr[x]), max_r);
214 max_g =
FFMAX(
G(block_ptr[x]), max_g);
215 max_b =
FFMAX(
B(block_ptr[x]), max_b);
224 if (r > g && r > b) {
228 }
else if (g > b && g >= r) {
250 if (diff >= thresh) {
266 double *slope,
double *y_intercept,
double *correlation_coef)
268 double sumx = 0, sumy = 0, sumx2 = 0, sumy2 = 0, sumxy = 0,
269 sumx_sq = 0, sumy_sq = 0,
tmp, tmp2;
280 x =
GET_CHAN(block_ptr[j], xchannel);
281 y =
GET_CHAN(block_ptr[j], ychannel);
291 sumx_sq = sumx * sumx;
292 tmp = (count * sumx2 - sumx_sq);
298 sumy_sq = sumy * sumy;
300 *slope = (sumx * sumy - sumxy) /
tmp;
301 *y_intercept = (sumy - (*slope) * sumx) / count;
303 tmp2 = count * sumy2 - sumy_sq;
305 *correlation_coef = 0.0;
307 *correlation_coef = (count * sumxy - sumx * sumy) /
318 int min,
int max,
int tmp_min,
int tmp_max,
327 int x_inc, lin_y, lin_x;
328 x =
GET_CHAN(block_ptr[j], xchannel);
329 y =
GET_CHAN(block_ptr[j], ychannel);
332 x_inc =
floor( (x - min) * 3.0 / (max - min) + 0.5);
336 lin_y = (
int)(tmp_min + (tmp_max - tmp_min) * x_inc / 3.0 + 0.5);
338 err =
FFABS(lin_y - y);
343 lin_x = (
int)(min + (max - min) * x_inc / 3.0 + 0.5);
345 err =
FFABS(lin_x - x);
361 int smallest_variance = INT_MAX;
368 for (
int palette_entry = 0; palette_entry < 4; palette_entry++) {
369 int variance =
diff_colors(dithered_color, colors[palette_entry]);
371 if (variance < smallest_variance) {
372 smallest_variance = variance;
390 uint16_t rounded_max, rounded_min;
398 put_bits(pb, 16, rounded_max & ~0x8000);
400 put_bits(pb, 16, rounded_min | 0x8000);
404 for (y = 0; y < 4; y++) {
405 for (x = 0; x < 4; x++) {
418 uint16_t *dest_pixels,
421 for (
int y = 0; y < 4; y++) {
422 memcpy(dest_pixels, src_pixels, 8);
445 int *total_rgb,
int *total_pixels,
446 uint8_t avg_color[3],
int first_block)
450 int total_pixels_blk;
453 uint8_t min_color_blk[3], max_color_blk[3];
454 int total_rgb_blk[3];
458 min_color[0] = UINT8_MAX;
459 min_color[1] = UINT8_MAX;
460 min_color[2] = UINT8_MAX;
477 min_color_blk[0] = min_color[0];
478 min_color_blk[1] = min_color[1];
479 min_color_blk[2] = min_color[2];
480 max_color_blk[0] = max_color[0];
481 max_color_blk[1] = max_color[1];
482 max_color_blk[2] = max_color[2];
483 total_rgb_blk[0] = total_rgb[0];
484 total_rgb_blk[1] = total_rgb[1];
485 total_rgb_blk[2] = total_rgb[2];
493 total_rgb_blk[0] +=
R(block[x]);
494 total_rgb_blk[1] +=
G(block[x]);
495 total_rgb_blk[2] +=
B(block[x]);
497 min_color_blk[0] =
FFMIN(
R(block[x]), min_color_blk[0]);
498 min_color_blk[1] =
FFMIN(
G(block[x]), min_color_blk[1]);
499 min_color_blk[2] =
FFMIN(
B(block[x]), min_color_blk[2]);
501 max_color_blk[0] =
FFMAX(
R(block[x]), max_color_blk[0]);
502 max_color_blk[1] =
FFMAX(
G(block[x]), max_color_blk[1]);
503 max_color_blk[2] =
FFMAX(
B(block[x]), max_color_blk[2]);
511 avg_color_blk[0] = total_rgb_blk[0] / total_pixels_blk;
512 avg_color_blk[1] = total_rgb_blk[1] / total_pixels_blk;
513 avg_color_blk[2] = total_rgb_blk[2] / total_pixels_blk;
518 is_in_range = (max_color_blk[0] - avg_color_blk[0] <= threshold &&
519 max_color_blk[1] - avg_color_blk[1] <= threshold &&
520 max_color_blk[2] - avg_color_blk[2] <= threshold &&
521 avg_color_blk[0] - min_color_blk[0] <= threshold &&
522 avg_color_blk[1] - min_color_blk[1] <= threshold &&
523 avg_color_blk[2] - min_color_blk[2] <= threshold);
529 min_color[0] = min_color_blk[0];
530 min_color[1] = min_color_blk[1];
531 min_color[2] = min_color_blk[2];
532 max_color[0] = max_color_blk[0];
533 max_color[1] = max_color_blk[1];
534 max_color[2] = max_color_blk[2];
535 total_rgb[0] = total_rgb_blk[0];
536 total_rgb[1] = total_rgb_blk[1];
537 total_rgb[2] = total_rgb_blk[2];
538 *total_pixels = total_pixels_blk;
539 avg_color[0] = avg_color_blk[0];
540 avg_color[1] = avg_color_blk[1];
541 avg_color[2] = avg_color_blk[2];
550 int block_counter = 0;
553 int prev_block_offset;
554 int block_offset = 0;
558 int tmp_min, tmp_max;
562 uint8_t min_color[3], max_color[3];
563 double slope, y_intercept, correlation_coef;
564 uint16_t *src_pixels = (uint16_t *)pict->
data[0];
576 while (block_counter < total_blocks) {
582 prev_block_offset = 0;
584 while (n_blocks < 32 && block_counter + n_blocks < total_blocks) {
595 if (prev_block_offset && block_offset - prev_block_offset > 12) {
599 prev_block_offset = block_offset;
608 block_counter += n_blocks;
632 block_counter += n_blocks;
644 min_color, max_color,
645 total_rgb, &pixel_count, avg_color, 1)) {
646 prev_block_offset = block_offset;
652 &prev_pixels[block_offset], &bi, block_counter + n_blocks);
655 while (n_blocks < 32 && block_counter + n_blocks < total_blocks) {
660 if (block_offset - prev_block_offset > 12) {
665 min_color, max_color,
666 total_rgb, &pixel_count, avg_color, 0)) {
670 prev_block_offset = block_offset;
674 &prev_pixels[block_offset], &bi, block_counter + n_blocks);
684 block_counter += n_blocks;
699 for (i = 0; i < 3; i++) {
706 slope = y_intercept = correlation_coef = 0;
708 if (
leastsquares(&src_pixels[block_offset], &bi, chan, i,
709 &slope, &y_intercept, &correlation_coef)) {
710 min_color[
i] =
GET_CHAN(src_pixels[block_offset], i);
711 max_color[
i] =
GET_CHAN(src_pixels[block_offset], i);
713 tmp_min = (
int)(0.5 + min * slope + y_intercept);
714 tmp_max = (
int)(0.5 +
max * slope + y_intercept);
718 tmp_min = av_clip_uint8(tmp_min);
719 tmp_max = av_clip_uint8(tmp_max);
722 min,
max, tmp_min, tmp_max, chan, i), err);
724 min_color[
i] = tmp_min;
725 max_color[
i] = tmp_max;
735 row_ptr = &src_pixels[block_offset];
737 for (
int y = 0; y < 4; y++) {
738 for (
int x = 0; x < 4; x++){
739 rgb555 = row_ptr[x] & ~0x8000;
749 &s->
pb, &src_pixels[block_offset], &bi);
754 &prev_pixels[block_offset], &bi, block_counter);
828 #define OFFSET(x) offsetof(RpzaContext, x) 829 #define VE AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM 851 .priv_class = &rpza_class,
static void av_unused put_bits32(PutBitContext *s, uint32_t value)
Write exactly 32 bits into a bitstream.
static int diff_colors(uint8_t *colorA, uint8_t *colorB)
static int max_component_diff(uint16_t *colorA, uint16_t *colorB)
#define GET_CHAN(color, chan)
This structure describes decoded (raw) audio or video data.
static void put_bits(Jpeg2000EncoderContext *s, int val, int n)
put n times val bit
#define LIBAVUTIL_VERSION_INT
void av_shrink_packet(AVPacket *pkt, int size)
Reduce packet size, correctly zeroing padding.
static av_cold int init(AVCodecContext *avctx)
const char * av_default_item_name(void *ptr)
Return the context name.
static __device__ float floor(float a)
static void get_colors(uint8_t *min, uint8_t *max, uint8_t color4[4][3])
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
#define av_assert0(cond)
assert() equivalent, that is always enabled.
int ff_alloc_packet2(AVCodecContext *avctx, AVPacket *avpkt, int64_t size, int64_t min_size)
Check AVPacket size and/or allocate data.
#define FF_CODEC_CAP_INIT_THREADSAFE
The codec does not modify any global variables in the init function, allowing to call the init functi...
The exact code depends on how similar the blocks are and how related they are to the block
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
static void update_block_in_prev_frame(const uint16_t *src_pixels, uint16_t *dest_pixels, const BlockInfo *bi, int block_counter)
static int compare_blocks(uint16_t *block1, uint16_t *block2, BlockInfo *bi, int thresh)
static int rpza_encode_init(AVCodecContext *avctx)
static int encode_four_color_block(uint8_t *min_color, uint8_t *max_color, PutBitContext *pb, uint16_t *block_ptr, BlockInfo *bi)
static int get_block_info(BlockInfo *bi, int block)
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
simple assert() macros that are a bit more flexible than ISO C assert().
const char * name
Name of the codec implementation.
int start_one_color_thresh
static int rpza_encode_end(AVCodecContext *avctx)
static int put_bits_count(PutBitContext *s)
int continue_one_color_thresh
static int leastsquares(uint16_t *block_ptr, BlockInfo *bi, channel_offset xchannel, channel_offset ychannel, double *slope, double *y_intercept, double *correlation_coef)
int width
picture width / height.
static const AVClass rpza_class
#define FFABS(a)
Absolute value, Note, INT_MIN / INT64_MIN result in undefined behavior as they are not representable ...
static int calc_lsq_max_fit_error(uint16_t *block_ptr, BlockInfo *bi, int min, int max, int tmp_min, int tmp_max, channel_offset xchannel, channel_offset ychannel)
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames...
Libavcodec external API header.
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
main external API structure.
static uint16_t rgb24_to_rgb555(uint8_t *rgb24)
Describe the class of an AVClass context structure.
static const SheerTable rgb[2]
static enum AVPixelFormat pix_fmts[]
int av_frame_get_buffer(AVFrame *frame, int align)
Allocate new buffer(s) for audio or video data.
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
static void get_max_component_diff(BlockInfo *bi, uint16_t *block_ptr, uint8_t *min, uint8_t *max, channel_offset *chan)
common internal api header.
static void flush_put_bits(PutBitContext *s)
Pad the end of the output stream with zeros.
common internal and external API header
channel
Use these values when setting the channel map with ebur128_set_channel().
#define AV_PIX_FMT_RGB555
static int match_color(uint16_t *color, uint8_t colors[4][3])
static void init_put_bits(PutBitContext *s, uint8_t *buffer, int buffer_size)
Initialize the PutBitContext s.
static int update_block_stats(RpzaContext *s, BlockInfo *bi, uint16_t *block, uint8_t min_color[3], uint8_t max_color[3], int *total_rgb, int *total_pixels, uint8_t avg_color[3], int first_block)
static av_always_inline int diff(const uint32_t a, const uint32_t b)
static void rpza_encode_stream(RpzaContext *s, const AVFrame *pict)
static const AVOption options[]
static int16_t block1[64]
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later.That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another.Frame references ownership and permissions
AVPixelFormat
Pixel format.
This structure stores compressed data.
trying all byte sequences megabyte in length and selecting the best looking sequence will yield cases to try But a word about which is also called distortion Distortion can be quantified by almost any quality measurement one chooses the sum of squared differences is used but more complex methods that consider psychovisual effects can be used as well It makes no difference in this discussion First step
static int rpza_encode_frame(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *frame, int *got_packet)