mirror of
https://github.com/FFmpeg/FFmpeg.git
synced 2024-12-23 12:43:46 +02:00
ffv1.4: use 2 coefficients for calculating the Y plane in the RCT
0-0.7% improved compression Signed-off-by: Michael Niedermayer <michaelni@gmx.at>
This commit is contained in:
parent
2bdda9a15c
commit
0e575c24d6
@ -130,7 +130,8 @@ typedef struct FFV1Context {
|
||||
int slice_y;
|
||||
int slice_reset_contexts;
|
||||
int slice_coding_mode;
|
||||
int slice_rct_y_coef;
|
||||
int slice_rct_by_coef;
|
||||
int slice_rct_ry_coef;
|
||||
} FFV1Context;
|
||||
|
||||
int ffv1_common_init(AVCodecContext *avctx);
|
||||
|
@ -260,7 +260,7 @@ static void decode_rgb_frame(FFV1Context *s, uint8_t *src[3], int w, int h, int
|
||||
if (s->slice_coding_mode != 1) {
|
||||
b -= offset;
|
||||
r -= offset;
|
||||
g -= ((b + r) * s->slice_rct_y_coef) >> 2;
|
||||
g -= (b * s->slice_rct_by_coef + r * s->slice_rct_ry_coef) >> 2;
|
||||
b += g;
|
||||
r += g;
|
||||
}
|
||||
@ -334,8 +334,9 @@ static int decode_slice_header(FFV1Context *f, FFV1Context *fs)
|
||||
fs->slice_reset_contexts = get_rac(c, state);
|
||||
fs->slice_coding_mode = get_symbol(c, state, 0);
|
||||
if (fs->slice_coding_mode != 1) {
|
||||
fs->slice_rct_y_coef = get_symbol(c, state, 0);
|
||||
if (fs->slice_rct_y_coef > 2U) {
|
||||
fs->slice_rct_by_coef = get_symbol(c, state, 0);
|
||||
fs->slice_rct_ry_coef = get_symbol(c, state, 0);
|
||||
if ((uint64_t)fs->slice_rct_by_coef + (uint64_t)fs->slice_rct_ry_coef > 4) {
|
||||
av_log(f->avctx, AV_LOG_ERROR, "slice_rct_y_coef out of range\n");
|
||||
return AVERROR_INVALIDDATA;
|
||||
}
|
||||
@ -388,7 +389,8 @@ static int decode_slice(AVCodecContext *c, void *arg)
|
||||
}
|
||||
}
|
||||
|
||||
fs->slice_rct_y_coef = 1;
|
||||
fs->slice_rct_by_coef = 1;
|
||||
fs->slice_rct_ry_coef = 1;
|
||||
|
||||
if (f->version > 2) {
|
||||
if (ffv1_init_slice_state(f, fs) < 0)
|
||||
|
@ -441,7 +441,7 @@ static int encode_rgb_frame(FFV1Context *s, uint8_t *src[3], int w, int h, int s
|
||||
if (s->slice_coding_mode != 1) {
|
||||
b -= g;
|
||||
r -= g;
|
||||
g += ((b + r) * s->slice_rct_y_coef) >> 2;
|
||||
g += (b * s->slice_rct_by_coef + r * s->slice_rct_ry_coef) >> 2;
|
||||
b += offset;
|
||||
r += offset;
|
||||
}
|
||||
@ -560,7 +560,7 @@ static int write_extradata(FFV1Context *f)
|
||||
if (f->version == 3) {
|
||||
f->micro_version = 4;
|
||||
} else if (f->version == 4)
|
||||
f->micro_version = 1;
|
||||
f->micro_version = 2;
|
||||
put_symbol(c, state, f->micro_version, 0);
|
||||
}
|
||||
|
||||
@ -999,14 +999,36 @@ static void encode_slice_header(FFV1Context *f, FFV1Context *fs)
|
||||
if (fs->slice_coding_mode == 1)
|
||||
ffv1_clear_slice_state(f, fs);
|
||||
put_symbol(c, state, fs->slice_coding_mode, 0);
|
||||
if (fs->slice_coding_mode != 1)
|
||||
put_symbol(c, state, fs->slice_rct_y_coef, 0);
|
||||
if (fs->slice_coding_mode != 1) {
|
||||
put_symbol(c, state, fs->slice_rct_by_coef, 0);
|
||||
put_symbol(c, state, fs->slice_rct_ry_coef, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void choose_rct_params(FFV1Context *fs, uint8_t *src[3], const int stride[3], int w, int h)
|
||||
{
|
||||
int stat[3] = {0};
|
||||
#define NB_Y_COEFF 15
|
||||
static const int rct_y_coeff[15][2] = {
|
||||
{0, 0}, // 4G
|
||||
{1, 1}, // R + 2G + B
|
||||
{2, 2}, // 2R + 2B
|
||||
{0, 2}, // 2G + 2B
|
||||
{2, 0}, // 2R + 2G
|
||||
{4, 0}, // 4R
|
||||
{0, 4}, // 4B
|
||||
|
||||
{0, 3}, // 1G + 3B
|
||||
{3, 0}, // 3R + 1G
|
||||
{3, 1}, // 3R + B
|
||||
{1, 3}, // R + 3B
|
||||
{1, 2}, // R + G + 2B
|
||||
{2, 1}, // 2R + G + B
|
||||
{0, 1}, // 3G + B
|
||||
{1, 0}, // R + 3G
|
||||
};
|
||||
|
||||
int stat[NB_Y_COEFF] = {0};
|
||||
int x, y, i, p, best;
|
||||
int16_t *sample[3];
|
||||
int lbd = fs->bits_per_raw_sample <= 8;
|
||||
@ -1041,9 +1063,9 @@ static void choose_rct_params(FFV1Context *fs, uint8_t *src[3], const int stride
|
||||
br -= bg;
|
||||
bb -= bg;
|
||||
|
||||
stat[0] += FFABS(bg);
|
||||
stat[1] += FFABS(bg + ((br+bb)>>2));
|
||||
stat[2] += FFABS(bg + ((br+bb)>>1));
|
||||
for (i = 0; i<NB_Y_COEFF; i++) {
|
||||
stat[i] += FFABS(bg + ((br*rct_y_coeff[i][0] + bb*rct_y_coeff[i][1])>>2));
|
||||
}
|
||||
|
||||
}
|
||||
sample[0][x] = ag;
|
||||
@ -1057,12 +1079,13 @@ static void choose_rct_params(FFV1Context *fs, uint8_t *src[3], const int stride
|
||||
}
|
||||
|
||||
best = 0;
|
||||
for (i=1; i<=2; i++) {
|
||||
for (i=1; i<NB_Y_COEFF; i++) {
|
||||
if (stat[i] < stat[best])
|
||||
best = i;
|
||||
}
|
||||
|
||||
fs->slice_rct_y_coef = best;
|
||||
fs->slice_rct_by_coef = rct_y_coeff[best][1];
|
||||
fs->slice_rct_ry_coef = rct_y_coeff[best][0];
|
||||
}
|
||||
|
||||
static int encode_slice(AVCodecContext *c, void *arg)
|
||||
@ -1085,7 +1108,8 @@ static int encode_slice(AVCodecContext *c, void *arg)
|
||||
if (f->version > 3) {
|
||||
choose_rct_params(fs, planes, p->linesize, width, height);
|
||||
} else {
|
||||
fs->slice_rct_y_coef = 1;
|
||||
fs->slice_rct_by_coef = 1;
|
||||
fs->slice_rct_ry_coef = 1;
|
||||
}
|
||||
|
||||
retry:
|
||||
|
Loading…
Reference in New Issue
Block a user