[FFmpeg-cvslog] ffv1.4: use 2 coefficients for calculating the Y plane in the RCT

Michael Niedermayer git at videolan.org
Tue Dec 10 03:24:44 CET 2013


ffmpeg | branch: master | Michael Niedermayer <michaelni at gmx.at> | Tue Dec 10 03:14:41 2013 +0100| [0e575c24d62a3d9f51bca04d22c234e3857b86a9] | committer: Michael Niedermayer

ffv1.4: use 2 coefficients for calculating the Y plane in the RCT

0-0.7% improved compression

Signed-off-by: Michael Niedermayer <michaelni at gmx.at>

> http://git.videolan.org/gitweb.cgi/ffmpeg.git/?a=commit;h=0e575c24d62a3d9f51bca04d22c234e3857b86a9
---

 libavcodec/ffv1.h    |    3 ++-
 libavcodec/ffv1dec.c |   10 ++++++----
 libavcodec/ffv1enc.c |   46 +++++++++++++++++++++++++++++++++++-----------
 3 files changed, 43 insertions(+), 16 deletions(-)

diff --git a/libavcodec/ffv1.h b/libavcodec/ffv1.h
index 2c3e6e4..9d8329f 100644
--- a/libavcodec/ffv1.h
+++ b/libavcodec/ffv1.h
@@ -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);
diff --git a/libavcodec/ffv1dec.c b/libavcodec/ffv1dec.c
index 6c01ebf..d7dd110 100644
--- a/libavcodec/ffv1dec.c
+++ b/libavcodec/ffv1dec.c
@@ -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)
diff --git a/libavcodec/ffv1enc.c b/libavcodec/ffv1enc.c
index a518146..7f9f203 100644
--- a/libavcodec/ffv1enc.c
+++ b/libavcodec/ffv1enc.c
@@ -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:



More information about the ffmpeg-cvslog mailing list