summaryrefslogtreecommitdiff
path: root/vp9
diff options
context:
space:
mode:
Diffstat (limited to 'vp9')
-rw-r--r--vp9/encoder/vp9_lookahead.c51
-rw-r--r--vp9/encoder/vp9_lookahead.h3
-rw-r--r--vp9/encoder/vp9_onyx_if.c43
-rw-r--r--vp9/encoder/vp9_onyx_int.h4
4 files changed, 83 insertions, 18 deletions
diff --git a/vp9/encoder/vp9_lookahead.c b/vp9/encoder/vp9_lookahead.c
index a88d5ecf8..cf03e0142 100644
--- a/vp9/encoder/vp9_lookahead.c
+++ b/vp9/encoder/vp9_lookahead.c
@@ -28,8 +28,8 @@ struct lookahead_ctx {
/* Return the buffer at the given absolute index and increment the index */
-static struct lookahead_entry * pop(struct lookahead_ctx *ctx,
- unsigned int *idx) {
+static struct lookahead_entry *pop(struct lookahead_ctx *ctx,
+ unsigned int *idx) {
unsigned int index = *idx;
struct lookahead_entry *buf = ctx->buf + index;
@@ -55,16 +55,19 @@ void vp9_lookahead_destroy(struct lookahead_ctx *ctx) {
}
-struct lookahead_ctx * vp9_lookahead_init(unsigned int width,
- unsigned int height,
- unsigned int subsampling_x,
- unsigned int subsampling_y,
- unsigned int depth) {
+struct lookahead_ctx *vp9_lookahead_init(unsigned int width,
+ unsigned int height,
+ unsigned int subsampling_x,
+ unsigned int subsampling_y,
+ unsigned int depth) {
struct lookahead_ctx *ctx = NULL;
// Clamp the lookahead queue depth
depth = clamp(depth, 1, MAX_LAG_BUFFERS);
+ // Allocate memory to keep previous source frames available.
+ depth += MAX_PRE_FRAMES;
+
// Allocate the lookahead structures
ctx = calloc(1, sizeof(*ctx));
if (ctx) {
@@ -96,7 +99,7 @@ int vp9_lookahead_push(struct lookahead_ctx *ctx, YV12_BUFFER_CONFIG *src,
int mb_cols = (src->y_width + 15) >> 4;
#endif
- if (ctx->sz + 1 > ctx->max_sz)
+ if (ctx->sz + 1 + MAX_PRE_FRAMES > ctx->max_sz)
return 1;
ctx->sz++;
buf = pop(ctx, &ctx->write_idx);
@@ -159,11 +162,11 @@ int vp9_lookahead_push(struct lookahead_ctx *ctx, YV12_BUFFER_CONFIG *src,
}
-struct lookahead_entry * vp9_lookahead_pop(struct lookahead_ctx *ctx,
- int drain) {
+struct lookahead_entry *vp9_lookahead_pop(struct lookahead_ctx *ctx,
+ int drain) {
struct lookahead_entry *buf = NULL;
- if (ctx->sz && (drain || ctx->sz == ctx->max_sz)) {
+ if (ctx->sz && (drain || ctx->sz == ctx->max_sz - MAX_PRE_FRAMES)) {
buf = pop(ctx, &ctx->read_idx);
ctx->sz--;
}
@@ -171,16 +174,28 @@ struct lookahead_entry * vp9_lookahead_pop(struct lookahead_ctx *ctx,
}
-struct lookahead_entry * vp9_lookahead_peek(struct lookahead_ctx *ctx,
- int index) {
+struct lookahead_entry *vp9_lookahead_peek(struct lookahead_ctx *ctx,
+ int index) {
struct lookahead_entry *buf = NULL;
- if (index < (int)ctx->sz) {
- index += ctx->read_idx;
- if (index >= (int)ctx->max_sz)
- index -= ctx->max_sz;
- buf = ctx->buf + index;
+ if (index >= 0) {
+ // Forward peek
+ if (index < (int)ctx->sz) {
+ index += ctx->read_idx;
+ if (index >= (int)ctx->max_sz)
+ index -= ctx->max_sz;
+ buf = ctx->buf + index;
+ }
+ } else if (index < 0) {
+ // Backward peek
+ if (-index <= MAX_PRE_FRAMES) {
+ index += ctx->read_idx;
+ if (index < 0)
+ index += ctx->max_sz;
+ buf = ctx->buf + index;
+ }
}
+
return buf;
}
diff --git a/vp9/encoder/vp9_lookahead.h b/vp9/encoder/vp9_lookahead.h
index ff63c0d0d..046c533cc 100644
--- a/vp9/encoder/vp9_lookahead.h
+++ b/vp9/encoder/vp9_lookahead.h
@@ -20,6 +20,9 @@ extern "C" {
#define MAX_LAG_BUFFERS 25
+// The max of past frames we want to keep in the queue.
+#define MAX_PRE_FRAMES 1
+
struct lookahead_entry {
YV12_BUFFER_CONFIG img;
int64_t ts_start;
diff --git a/vp9/encoder/vp9_onyx_if.c b/vp9/encoder/vp9_onyx_if.c
index 122477906..65f92d087 100644
--- a/vp9/encoder/vp9_onyx_if.c
+++ b/vp9/encoder/vp9_onyx_if.c
@@ -200,6 +200,7 @@ static void dealloc_compressor_data(VP9_COMP *cpi) {
vp9_free_frame_buffer(&cpi->last_frame_uf);
vp9_free_frame_buffer(&cpi->scaled_source);
+ vp9_free_frame_buffer(&cpi->scaled_last_source);
vp9_free_frame_buffer(&cpi->alt_ref_buffer);
vp9_lookahead_destroy(cpi->lookahead);
@@ -960,6 +961,13 @@ void vp9_alloc_compressor_data(VP9_COMP *cpi) {
vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
"Failed to allocate scaled source buffer");
+ if (vp9_alloc_frame_buffer(&cpi->scaled_last_source,
+ cm->width, cm->height,
+ cm->subsampling_x, cm->subsampling_y,
+ VP9_ENC_BORDER_IN_PIXELS))
+ vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
+ "Failed to allocate scaled last source buffer");
+
vpx_free(cpi->tok);
{
@@ -1001,6 +1009,13 @@ static void update_frame_size(VP9_COMP *cpi) {
vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
"Failed to reallocate scaled source buffer");
+ if (vp9_realloc_frame_buffer(&cpi->scaled_last_source,
+ cm->width, cm->height,
+ cm->subsampling_x, cm->subsampling_y,
+ VP9_ENC_BORDER_IN_PIXELS, NULL, NULL, NULL))
+ vpx_internal_error(&cm->error, VPX_CODEC_MEM_ERROR,
+ "Failed to reallocate scaled last source buffer");
+
{
int y_stride = cpi->scaled_source.y_stride;
@@ -2914,6 +2929,19 @@ static void encode_frame_to_data_rate(VP9_COMP *cpi,
} else {
cpi->Source = cpi->un_scaled_source;
}
+
+ // Scale the last source buffer, if required.
+ if (cpi->unscaled_last_source != NULL) {
+ if (cm->mi_cols * MI_SIZE != cpi->unscaled_last_source->y_width ||
+ cm->mi_rows * MI_SIZE != cpi->unscaled_last_source->y_height) {
+ scale_and_extend_frame_nonnormative(cpi->unscaled_last_source,
+ &cpi->scaled_last_source);
+ cpi->Last_Source = &cpi->scaled_last_source;
+ } else {
+ cpi->Last_Source = cpi->unscaled_last_source;
+ }
+ }
+
vp9_scale_references(cpi);
vp9_clear_system_state();
@@ -3332,6 +3360,7 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags,
vpx_usec_timer_start(&cmptimer);
cpi->source = NULL;
+ cpi->last_source = NULL;
set_high_precision_mv(cpi, ALTREF_HIGH_PRECISION_MV);
@@ -3394,6 +3423,13 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags,
#if CONFIG_MULTIPLE_ARF
int i;
#endif
+
+ // Get last frame source.
+ if (cm->current_video_frame > 0) {
+ if ((cpi->last_source = vp9_lookahead_peek(cpi->lookahead, -1)) == NULL)
+ return -1;
+ }
+
if ((cpi->source = vp9_lookahead_pop(cpi->lookahead, flush))) {
cm->show_frame = 1;
cm->intra_only = 0;
@@ -3432,6 +3468,13 @@ int vp9_get_compressed_data(VP9_COMP *cpi, unsigned int *frame_flags,
if (cpi->source) {
cpi->un_scaled_source = cpi->Source = force_src_buffer ? force_src_buffer
: &cpi->source->img;
+
+ if (cpi->last_source != NULL) {
+ cpi->unscaled_last_source = &cpi->last_source->img;
+ } else {
+ cpi->unscaled_last_source = NULL;
+ }
+
*time_stamp = cpi->source->ts_start;
*time_end = cpi->source->ts_end;
*frame_flags = cpi->source->flags;
diff --git a/vp9/encoder/vp9_onyx_int.h b/vp9/encoder/vp9_onyx_int.h
index 582fa0ea3..8255073c9 100644
--- a/vp9/encoder/vp9_onyx_int.h
+++ b/vp9/encoder/vp9_onyx_int.h
@@ -596,10 +596,14 @@ typedef struct VP9_COMP {
#else
struct lookahead_entry *alt_ref_source;
#endif
+ struct lookahead_entry *last_source;
YV12_BUFFER_CONFIG *Source;
+ YV12_BUFFER_CONFIG *Last_Source; // NULL for first frame and alt_ref frames
YV12_BUFFER_CONFIG *un_scaled_source;
YV12_BUFFER_CONFIG scaled_source;
+ YV12_BUFFER_CONFIG *unscaled_last_source;
+ YV12_BUFFER_CONFIG scaled_last_source;
int key_frame_frequency;