svq3: rip out the svq3-relevant parts of pred_motion() out of h264
authorAnton Khirnov <anton@khirnov.net>
Wed, 23 Mar 2016 08:59:57 +0000 (09:59 +0100)
committerAnton Khirnov <anton@khirnov.net>
Mon, 28 Mar 2016 07:55:24 +0000 (09:55 +0200)
libavcodec/svq3.c

index 5564d29..a248cd6 100644 (file)
@@ -311,6 +311,79 @@ static inline int svq3_decode_block(GetBitContext *gb, int16_t *block,
     return 0;
 }
 
+static av_always_inline int
+svq3_fetch_diagonal_mv(const H264Context *h, H264SliceContext *sl,
+                       const int16_t **C,
+                       int i, int list, int part_width)
+{
+    const int topright_ref = sl->ref_cache[list][i - 8 + part_width];
+
+    if (topright_ref != PART_NOT_AVAILABLE) {
+        *C = sl->mv_cache[list][i - 8 + part_width];
+        return topright_ref;
+    } else {
+        *C = sl->mv_cache[list][i - 8 - 1];
+        return sl->ref_cache[list][i - 8 - 1];
+    }
+}
+
+/**
+ * Get the predicted MV.
+ * @param n the block index
+ * @param part_width the width of the partition (4, 8,16) -> (1, 2, 4)
+ * @param mx the x component of the predicted motion vector
+ * @param my the y component of the predicted motion vector
+ */
+static av_always_inline void svq3_pred_motion(const H264Context *const h,
+                                              H264SliceContext *sl, int n,
+                                              int part_width, int list,
+                                              int ref, int *const mx, int *const my)
+{
+    const int index8       = scan8[n];
+    const int top_ref      = sl->ref_cache[list][index8 - 8];
+    const int left_ref     = sl->ref_cache[list][index8 - 1];
+    const int16_t *const A = sl->mv_cache[list][index8 - 1];
+    const int16_t *const B = sl->mv_cache[list][index8 - 8];
+    const int16_t *C;
+    int diagonal_ref, match_count;
+
+/* mv_cache
+ * B . . A T T T T
+ * U . . L . . , .
+ * U . . L . . . .
+ * U . . L . . , .
+ * . . . L . . . .
+ */
+
+    diagonal_ref = svq3_fetch_diagonal_mv(h, sl, &C, index8, list, part_width);
+    match_count  = (diagonal_ref == ref) + (top_ref == ref) + (left_ref == ref);
+    if (match_count > 1) { //most common
+        *mx = mid_pred(A[0], B[0], C[0]);
+        *my = mid_pred(A[1], B[1], C[1]);
+    } else if (match_count == 1) {
+        if (left_ref == ref) {
+            *mx = A[0];
+            *my = A[1];
+        } else if (top_ref == ref) {
+            *mx = B[0];
+            *my = B[1];
+        } else {
+            *mx = C[0];
+            *my = C[1];
+        }
+    } else {
+        if (top_ref      == PART_NOT_AVAILABLE &&
+            diagonal_ref == PART_NOT_AVAILABLE &&
+            left_ref     != PART_NOT_AVAILABLE) {
+            *mx = A[0];
+            *my = A[1];
+        } else {
+            *mx = mid_pred(A[0], B[0], C[0]);
+            *my = mid_pred(A[1], B[1], C[1]);
+        }
+    }
+}
+
 static inline void svq3_mc_dir_part(SVQ3Context *s,
                                     int x, int y, int width, int height,
                                     int mx, int my, int dxy,
@@ -409,7 +482,7 @@ static inline int svq3_mc_dir(SVQ3Context *s, int size, int mode,
                 (j >> 1 & 4) + (i      & 8);
 
             if (mode != PREDICT_MODE) {
-                pred_motion(h, sl, k, part_width >> 2, dir, 1, &mx, &my);
+                svq3_pred_motion(h, sl, k, part_width >> 2, dir, 1, &mx, &my);
             } else {
                 mx = s->next_pic->motion_val[0][b_xy][0] << 1;
                 my = s->next_pic->motion_val[0][b_xy][1] << 1;