avcodec/me_cmp: add median SAD compare function
authorStanislav Dolganov <dolganov@qst.hk>
Thu, 18 Aug 2016 11:40:09 +0000 (14:40 +0300)
committerMichael Niedermayer <michael@niedermayer.cc>
Mon, 22 Aug 2016 14:41:33 +0000 (16:41 +0200)
Signed-off-by: Michael Niedermayer <michael@niedermayer.cc>
libavcodec/avcodec.h
libavcodec/me_cmp.c
libavcodec/me_cmp.h
libavcodec/motion_est.c
libavcodec/mpegvideo.h
libavcodec/options_table.h

index 6ac6646..e2dad5d 100644 (file)
@@ -2093,22 +2093,23 @@ typedef struct AVCodecContext {
      * - decoding: unused
      */
     int ildct_cmp;
-#define FF_CMP_SAD    0
-#define FF_CMP_SSE    1
-#define FF_CMP_SATD   2
-#define FF_CMP_DCT    3
-#define FF_CMP_PSNR   4
-#define FF_CMP_BIT    5
-#define FF_CMP_RD     6
-#define FF_CMP_ZERO   7
-#define FF_CMP_VSAD   8
-#define FF_CMP_VSSE   9
-#define FF_CMP_NSSE   10
-#define FF_CMP_W53    11
-#define FF_CMP_W97    12
-#define FF_CMP_DCTMAX 13
-#define FF_CMP_DCT264 14
-#define FF_CMP_CHROMA 256
+#define FF_CMP_SAD          0
+#define FF_CMP_SSE          1
+#define FF_CMP_SATD         2
+#define FF_CMP_DCT          3
+#define FF_CMP_PSNR         4
+#define FF_CMP_BIT          5
+#define FF_CMP_RD           6
+#define FF_CMP_ZERO         7
+#define FF_CMP_VSAD         8
+#define FF_CMP_VSSE         9
+#define FF_CMP_NSSE         10
+#define FF_CMP_W53          11
+#define FF_CMP_W97          12
+#define FF_CMP_DCTMAX       13
+#define FF_CMP_DCT264       14
+#define FF_CMP_MEDIAN_SAD   15
+#define FF_CMP_CHROMA       256
 
     /**
      * ME diamond size & shape
index dc76b07..6639b91 100644 (file)
@@ -139,6 +139,45 @@ static inline int pix_abs16_c(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
     return s;
 }
 
+static inline int pix_median_abs16_c(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
+                             ptrdiff_t stride, int h)
+{
+    int s = 0, i, j;
+
+#define V(x) (pix1[x] - pix2[x])
+
+    s    += abs(V(0));
+    s    += abs(V(1) - V(0));
+    s    += abs(V(2) - V(1));
+    s    += abs(V(3) - V(2));
+    s    += abs(V(4) - V(3));
+    s    += abs(V(5) - V(4));
+    s    += abs(V(6) - V(5));
+    s    += abs(V(7) - V(6));
+    s    += abs(V(8) - V(7));
+    s    += abs(V(9) - V(8));
+    s    += abs(V(10) - V(9));
+    s    += abs(V(11) - V(10));
+    s    += abs(V(12) - V(11));
+    s    += abs(V(13) - V(12));
+    s    += abs(V(14) - V(13));
+    s    += abs(V(15) - V(14));
+
+    pix1 += stride;
+    pix2 += stride;
+
+    for (i = 1; i < h; i++) {
+        s    += abs(V(0) - V(-stride));
+        for (j = 1; j < 16; j++)
+            s    += abs(V(j) - mid_pred(V(j-stride), V(j-1), V(j-stride) + V(j-1) - V(j-stride-1)));
+        pix1 += stride;
+        pix2 += stride;
+
+    }
+#undef V
+    return s;
+}
+
 static int pix_abs16_x2_c(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
                           ptrdiff_t stride, int h)
 {
@@ -247,6 +286,37 @@ static inline int pix_abs8_c(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
     return s;
 }
 
+static inline int pix_median_abs8_c(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
+                             ptrdiff_t stride, int h)
+{
+    int s = 0, i, j;
+
+#define V(x) (pix1[x] - pix2[x])
+
+    s    += abs(V(0));
+    s    += abs(V(1) - V(0));
+    s    += abs(V(2) - V(1));
+    s    += abs(V(3) - V(2));
+    s    += abs(V(4) - V(3));
+    s    += abs(V(5) - V(4));
+    s    += abs(V(6) - V(5));
+    s    += abs(V(7) - V(6));
+
+    pix1 += stride;
+    pix2 += stride;
+
+    for (i = 1; i < h; i++) {
+        s    += abs(V(0) - V(-stride));
+        for (j = 1; j < 8; j++)
+            s    += abs(V(j) - mid_pred(V(j-stride), V(j-1), V(j-stride) + V(j-1) - V(j-stride-1)));
+        pix1 += stride;
+        pix2 += stride;
+
+    }
+#undef V
+    return s;
+}
+
 static int pix_abs8_x2_c(MpegEncContext *v, uint8_t *pix1, uint8_t *pix2,
                          ptrdiff_t stride, int h)
 {
@@ -378,6 +448,9 @@ void ff_set_cmp(MECmpContext *c, me_cmp_func *cmp, int type)
         case FF_CMP_SAD:
             cmp[i] = c->sad[i];
             break;
+        case FF_CMP_MEDIAN_SAD:
+            cmp[i] = c->median_sad[i];
+            break;
         case FF_CMP_SATD:
             cmp[i] = c->hadamard8_diff[i];
             break;
@@ -993,4 +1066,7 @@ av_cold void ff_me_cmp_init(MECmpContext *c, AVCodecContext *avctx)
         ff_me_cmp_init_x86(c, avctx);
     if (ARCH_MIPS)
         ff_me_cmp_init_mips(c, avctx);
+
+    c->median_sad[0] = pix_median_abs16_c;
+    c->median_sad[1] = pix_median_abs8_c;
 }
index a3603ec..5666f59 100644 (file)
@@ -76,6 +76,7 @@ typedef struct MECmpContext {
     me_cmp_func frame_skip_cmp[6]; // only width 8 used
 
     me_cmp_func pix_abs[2][4];
+    me_cmp_func median_sad[2];
 } MECmpContext;
 
 void ff_me_cmp_init_static(void);
index 257d00b..25b606f 100644 (file)
@@ -897,6 +897,7 @@ static inline int get_penalty_factor(int lambda, int lambda2, int type){
     case FF_CMP_NSSE:
         return lambda2>>FF_LAMBDA_SHIFT;
     case FF_CMP_BIT:
+    case FF_CMP_MEDIAN_SAD:
         return 1;
     }
 }
index a1f3d4b..c82fa3e 100644 (file)
@@ -594,7 +594,8 @@ enum rc_strategy {
 { "nsse",   "Noise preserving sum of squared differences", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_NSSE }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS, "cmp_func" }, \
 { "dct264", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_DCT264 }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS, "cmp_func" }, \
 { "dctmax", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_DCTMAX }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS, "cmp_func" }, \
-{ "chroma", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_CHROMA }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS, "cmp_func" }
+{ "chroma", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_CHROMA }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS, "cmp_func" }, \
+{ "msad",   "Sum of absolute differences, median predicted", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_MEDIAN_SAD }, INT_MIN, INT_MAX, FF_MPV_OPT_FLAGS, "cmp_func" }
 
 #ifndef FF_MPV_OFFSET
 #define FF_MPV_OFFSET(x) offsetof(MpegEncContext, x)
index adfbe72..fe35454 100644 (file)
@@ -312,6 +312,7 @@ static const AVOption avcodec_options[] = {
 #endif
 {"dctmax", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_DCTMAX }, INT_MIN, INT_MAX, V|E, "cmp_func"},
 {"chroma", NULL, 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_CHROMA }, INT_MIN, INT_MAX, V|E, "cmp_func"},
+{"msad", "sum of absolute differences, median predicted", 0, AV_OPT_TYPE_CONST, {.i64 = FF_CMP_MEDIAN_SAD }, INT_MIN, INT_MAX, V|E, "cmp_func"},
 {"pre_dia_size", "diamond type & size for motion estimation pre-pass", OFFSET(pre_dia_size), AV_OPT_TYPE_INT, {.i64 = DEFAULT }, INT_MIN, INT_MAX, V|E},
 {"subq", "sub-pel motion estimation quality", OFFSET(me_subpel_quality), AV_OPT_TYPE_INT, {.i64 = 8 }, INT_MIN, INT_MAX, V|E},
 #if FF_API_AFD