diff --git a/vp8/common/extend.c b/vp8/common/extend.c index a2d325332..9089e1629 100644 --- a/vp8/common/extend.c +++ b/vp8/common/extend.c @@ -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) { diff --git a/vp8/common/extend.h b/vp8/common/extend.h index 9e0be4e06..74a0b177d 100644 --- a/vp8/common/extend.h +++ b/vp8/common/extend.h @@ -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 diff --git a/vp8/encoder/lookahead.c b/vp8/encoder/lookahead.c index d7f85cba1..b92e82bdf 100644 --- a/vp8/encoder/lookahead.c +++ b/vp8/encoder/lookahead.c @@ -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; diff --git a/vp8/encoder/lookahead.h b/vp8/encoder/lookahead.h index a483d7e0b..afb3fd4a9 100644 --- a/vp8/encoder/lookahead.h +++ b/vp8/encoder/lookahead.h @@ -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 diff --git a/vp8/encoder/onyx_if.c b/vp8/encoder/onyx_if.c index b1b3abde6..ff9a64172 100644 --- a/vp8/encoder/onyx_if.c +++ b/vp8/encoder/onyx_if.c @@ -4559,7 +4559,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);