Copy less when active map is in use
authorAlpha Lam <hclam@chromium.org>
Tue, 9 Aug 2011 19:59:45 +0000 (20:59 +0100)
committerJohn Koleszar <jkoleszar@google.com>
Fri, 19 Aug 2011 14:29:41 +0000 (10:29 -0400)
When active map is specified and the current frame is not a key frame,
golden frame nor a altref frame then copy only those active regions.

This significantly reduces encoding time by as much as 19% on the test
system where realtime encoding is used. This is particularly useful
when the frame size is large (e.g. 2560x1600) and there's only a few
action macroblocks.

Change-Id: If394a813ec2df5a0201745d1348dbde4278f7ad4

vp8/common/extend.c
vp8/common/extend.h
vp8/encoder/lookahead.c
vp8/encoder/lookahead.h
vp8/encoder/onyx_if.c

index a2d3253..9089e16 100644 (file)
@@ -102,6 +102,60 @@ void vp8_copy_and_extend_frame(YV12_BUFFER_CONFIG *src,
 }
 
 
+void vp8_copy_and_extend_frame_with_rect(YV12_BUFFER_CONFIG *src,
+                                         YV12_BUFFER_CONFIG *dst,
+                                         int srcy, int srcx,
+                                         int srch, int srcw)
+{
+    int et = dst->border;
+    int el = dst->border;
+    int eb = dst->border + dst->y_height - src->y_height;
+    int er = dst->border + dst->y_width - src->y_width;
+    int src_y_offset = srcy * src->y_stride + srcx;
+    int dst_y_offset = srcy * dst->y_stride + srcx;
+    int src_uv_offset = ((srcy * src->uv_stride) >> 1) + (srcx >> 1);
+    int dst_uv_offset = ((srcy * dst->uv_stride) >> 1) + (srcx >> 1);
+
+    // If the side is not touching the bounder then don't extend.
+    if (srcy)
+      et = 0;
+    if (srcx)
+      el = 0;
+    if (srcy + srch != src->y_height)
+      eb = 0;
+    if (srcx + srcw != src->y_width)
+      er = 0;
+
+    copy_and_extend_plane(src->y_buffer + src_y_offset,
+                          src->y_stride,
+                          dst->y_buffer + dst_y_offset,
+                          dst->y_stride,
+                          srch, srcw,
+                          et, el, eb, er);
+
+    et = (et + 1) >> 1;
+    el = (el + 1) >> 1;
+    eb = (eb + 1) >> 1;
+    er = (er + 1) >> 1;
+    srch = (srch + 1) >> 1;
+    srcw = (srcw + 1) >> 1;
+
+    copy_and_extend_plane(src->u_buffer + src_uv_offset,
+                          src->uv_stride,
+                          dst->u_buffer + dst_uv_offset,
+                          dst->uv_stride,
+                          srch, srcw,
+                          et, el, eb, er);
+
+    copy_and_extend_plane(src->v_buffer + src_uv_offset,
+                          src->uv_stride,
+                          dst->v_buffer + dst_uv_offset,
+                          dst->uv_stride,
+                          srch, srcw,
+                          et, el, eb, er);
+}
+
+
 /* note the extension is only for the last row, for intra prediction purpose */
 void vp8_extend_mb_row(YV12_BUFFER_CONFIG *ybf, unsigned char *YPtr, unsigned char *UPtr, unsigned char *VPtr)
 {
index 9e0be4e..74a0b17 100644 (file)
@@ -17,5 +17,9 @@
 void vp8_extend_mb_row(YV12_BUFFER_CONFIG *ybf, unsigned char *YPtr, unsigned char *UPtr, unsigned char *VPtr);
 void vp8_copy_and_extend_frame(YV12_BUFFER_CONFIG *src,
                                YV12_BUFFER_CONFIG *dst);
+void vp8_copy_and_extend_frame_with_rect(YV12_BUFFER_CONFIG *src,
+                                         YV12_BUFFER_CONFIG *dst,
+                                         int srcy, int srcx,
+                                         int srch, int srcw);
 
 #endif
index d7f85cb..b92e82b 100644 (file)
@@ -102,15 +102,68 @@ vp8_lookahead_push(struct lookahead_ctx *ctx,
                    YV12_BUFFER_CONFIG   *src,
                    int64_t               ts_start,
                    int64_t               ts_end,
-                   unsigned int          flags)
+                   unsigned int          flags,
+                   unsigned char        *active_map)
 {
     struct lookahead_entry* buf;
+    int row, col, active_end;
+    int mb_rows = (src->y_height + 15) >> 4;
+    int mb_cols = (src->y_width + 15) >> 4;
 
     if(ctx->sz + 1 > ctx->max_sz)
         return 1;
     ctx->sz++;
     buf = pop(ctx, &ctx->write_idx);
-    vp8_copy_and_extend_frame(src, &buf->img);
+
+    // Only do this partial copy if the following conditions are all met:
+    // 1. Lookahead queue has has size of 1.
+    // 2. Active map is provided.
+    // 3. This is not a key frame, golden nor altref frame.
+    if (ctx->max_sz == 1 && active_map && !flags)
+    {
+        for (row = 0; row < mb_rows; ++row)
+        {
+            col = 0;
+
+            while (1)
+            {
+                // Find the first active macroblock in this row.
+                for (; col < mb_cols; ++col)
+                {
+                    if (active_map[col])
+                        break;
+                }
+
+                // No more active macroblock in this row.
+                if (col == mb_cols)
+                    break;
+
+                // Find the end of active region in this row.
+                active_end = col;
+
+                for (; active_end < mb_cols; ++active_end)
+                {
+                    if (!active_map[active_end])
+                        break;
+                }
+
+                // Only copy this active region.
+                vp8_copy_and_extend_frame_with_rect(src, &buf->img,
+                                                    row << 4,
+                                                    col << 4, 16,
+                                                    (active_end - col) << 4);
+
+                // Start again from the end of this active region.
+                col = active_end;
+            }
+
+            active_map += mb_cols;
+        }
+    }
+    else
+    {
+        vp8_copy_and_extend_frame(src, &buf->img);
+    }
     buf->ts_start = ts_start;
     buf->ts_end = ts_end;
     buf->flags = flags;
index a483d7e..afb3fd4 100644 (file)
@@ -47,18 +47,23 @@ void vp8_lookahead_destroy(struct lookahead_ctx *ctx);
  * This function will copy the source image into a new framebuffer with
  * the expected stride/border.
  *
- * \param[in] ctx       Pointer to the lookahead context
- * \param[in] src       Pointer to the image to enqueue
- * \param[in] ts_start  Timestamp for the start of this frame
- * \param[in] ts_end    Timestamp for the end of this frame
- * \param[in] flags     Flags set on this frame
+ * If active_map is non-NULL and there is only one frame in the queue, then copy
+ * only active macroblocks.
+ *
+ * \param[in] ctx         Pointer to the lookahead context
+ * \param[in] src         Pointer to the image to enqueue
+ * \param[in] ts_start    Timestamp for the start of this frame
+ * \param[in] ts_end      Timestamp for the end of this frame
+ * \param[in] flags       Flags set on this frame
+ * \param[in] active_map  Map that specifies which macroblock is active
  */
 int
 vp8_lookahead_push(struct lookahead_ctx *ctx,
                    YV12_BUFFER_CONFIG   *src,
                    int64_t               ts_start,
                    int64_t               ts_end,
-                   unsigned int          flags);
+                   unsigned int          flags,
+                   unsigned char        *active_map);
 
 
 /**\brief Get the next source buffer to encode
index 36a1865..3f7b868 100644 (file)
@@ -4676,7 +4676,7 @@ int vp8_receive_raw_frame(VP8_PTR ptr, unsigned int frame_flags, YV12_BUFFER_CON
 
     vpx_usec_timer_start(&timer);
     if(vp8_lookahead_push(cpi->lookahead, sd, time_stamp, end_time,
-                          frame_flags))
+                          frame_flags, cpi->active_map_enabled ? cpi->active_map : NULL))
         res = -1;
     cm->clr_type = sd->clrtype;
     vpx_usec_timer_mark(&timer);