diff --git a/vp8/common/extend.c b/vp8/common/extend.c index 47207fa790032656b397bdef3ac1ba2542f5e6c1..5b8b4e4755e9f25bef146b287020bad75e3b4eba 100644 --- a/vp8/common/extend.c +++ b/vp8/common/extend.c @@ -13,10 +13,12 @@ #include "vpx_mem/vpx_mem.h" -static void extend_plane_borders +static void copy_and_extend_plane ( unsigned char *s, /* source */ - int sp, /* pitch */ + int sp, /* source pitch */ + unsigned char *d, /* destination */ + int dp, /* destination pitch */ int h, /* height */ int w, /* width */ int et, /* extend top border */ @@ -25,7 +27,6 @@ static void extend_plane_borders int er /* extend right border */ ) { - int i; unsigned char *src_ptr1, *src_ptr2; unsigned char *dest_ptr1, *dest_ptr2; @@ -34,68 +35,73 @@ static void extend_plane_borders /* copy the left and right most columns out */ src_ptr1 = s; src_ptr2 = s + w - 1; - dest_ptr1 = s - el; - dest_ptr2 = s + w; + dest_ptr1 = d - el; + dest_ptr2 = d + w; for (i = 0; i < h - 0 + 1; i++) { - /* Some linkers will complain if we call vpx_memset with el set to a - * constant 0. - */ - if (el) - vpx_memset(dest_ptr1, src_ptr1[0], el); + vpx_memset(dest_ptr1, src_ptr1[0], el); + vpx_memcpy(dest_ptr1 + el, src_ptr1, w); vpx_memset(dest_ptr2, src_ptr2[0], er); src_ptr1 += sp; src_ptr2 += sp; - dest_ptr1 += sp; - dest_ptr2 += sp; + dest_ptr1 += dp; + dest_ptr2 += dp; } - /* Now copy the top and bottom source lines into each line of the respective borders */ - src_ptr1 = s - el; - src_ptr2 = s + sp * (h - 1) - el; - dest_ptr1 = s + sp * (-et) - el; - dest_ptr2 = s + sp * (h) - el; - linesize = el + er + w + 1; + /* Now copy the top and bottom lines into each line of the respective + * borders + */ + src_ptr1 = d - el; + src_ptr2 = d + dp * (h - 1) - el; + dest_ptr1 = d + dp * (-et) - el; + dest_ptr2 = d + dp * (h) - el; + linesize = el + er + w; - for (i = 0; i < (int)et; i++) + for (i = 0; i < et; i++) { vpx_memcpy(dest_ptr1, src_ptr1, linesize); - dest_ptr1 += sp; + dest_ptr1 += dp; } - for (i = 0; i < (int)eb; i++) + for (i = 0; i < eb; i++) { vpx_memcpy(dest_ptr2, src_ptr2, linesize); - dest_ptr2 += sp; + dest_ptr2 += dp; } } -void vp8_extend_to_multiple_of16(YV12_BUFFER_CONFIG *ybf, int width, int height) +void vp8_copy_and_extend_frame(YV12_BUFFER_CONFIG *src, + YV12_BUFFER_CONFIG *dst) { - int er = 0xf & (16 - (width & 0xf)); - int eb = 0xf & (16 - (height & 0xf)); - - /* check for non multiples of 16 */ - if (er != 0 || eb != 0) - { - extend_plane_borders(ybf->y_buffer, ybf->y_stride, height, width, 0, 0, eb, er); - - /* adjust for uv */ - height = (height + 1) >> 1; - width = (width + 1) >> 1; - er = 0x7 & (8 - (width & 0x7)); - eb = 0x7 & (8 - (height & 0x7)); - - if (er || eb) - { - extend_plane_borders(ybf->u_buffer, ybf->uv_stride, height, width, 0, 0, eb, er); - extend_plane_borders(ybf->v_buffer, ybf->uv_stride, height, width, 0, 0, eb, er); - } - } + 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; + + copy_and_extend_plane(src->y_buffer, src->y_stride, + dst->y_buffer, dst->y_stride, + src->y_height, src->y_width, + et, el, eb, er); + + et = (et + 1) >> 1; + el = (el + 1) >> 1; + eb = (eb + 1) >> 1; + er = (er + 1) >> 1; + + copy_and_extend_plane(src->u_buffer, src->uv_stride, + dst->u_buffer, dst->uv_stride, + src->uv_height, src->uv_width, + et, el, eb, er); + + copy_and_extend_plane(src->v_buffer, src->uv_stride, + dst->v_buffer, dst->uv_stride, + src->uv_height, src->uv_width, + 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 fd0a608e53c4d00da9908fd2210e0ce534559f92..9e0be4e0661530e5024492de53cc2fd1450a81f4 100644 --- a/vp8/common/extend.h +++ b/vp8/common/extend.h @@ -14,8 +14,8 @@ #include "vpx_scale/yv12config.h" -void Extend(YV12_BUFFER_CONFIG *ybf); void vp8_extend_mb_row(YV12_BUFFER_CONFIG *ybf, unsigned char *YPtr, unsigned char *UPtr, unsigned char *VPtr); -void vp8_extend_to_multiple_of16(YV12_BUFFER_CONFIG *ybf, int width, int height); +void vp8_copy_and_extend_frame(YV12_BUFFER_CONFIG *src, + YV12_BUFFER_CONFIG *dst); #endif diff --git a/vp8/encoder/firstpass.c b/vp8/encoder/firstpass.c index 8f24a11a02799f303b6812a91f8a8ebf7df6a433..6f330991bd989fd76da1749c8bc1afd6f57ccdec 100644 --- a/vp8/encoder/firstpass.c +++ b/vp8/encoder/firstpass.c @@ -786,7 +786,8 @@ void vp8_first_pass(VP8_COMP *cpi) // TODO: handle the case when duration is set to 0, or something less // than the full time between subsequent cpi->source_time_stamp s . - fps.duration = cpi->source_end_time_stamp - cpi->source_time_stamp; + fps.duration = cpi->source->ts_end + - cpi->source->ts_start; // don't want to do output stats with a stack variable! memcpy(cpi->this_frame_stats, diff --git a/vp8/encoder/lookahead.c b/vp8/encoder/lookahead.c new file mode 100644 index 0000000000000000000000000000000000000000..3b86d40942d56c1c780f383b6cc365a41d99a0c0 --- /dev/null +++ b/vp8/encoder/lookahead.c @@ -0,0 +1,157 @@ +/* + * Copyright (c) 2011 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ +#include <assert.h> +#include <stdlib.h> +#include "vpx_config.h" +#include "lookahead.h" +#include "vp8/common/extend.h" + +#define MAX_LAG_BUFFERS (CONFIG_REALTIME_ONLY? 1 : 25) + +struct lookahead_ctx +{ + unsigned int max_sz; /* Absolute size of the queue */ + unsigned int sz; /* Number of buffers currently in the queue */ + unsigned int read_idx; /* Read index */ + unsigned int write_idx; /* Write index */ + struct lookahead_entry *buf; /* Buffer list */ +}; + + +/* Return the buffer at the given absolute index and increment the index */ +static struct lookahead_entry * +pop(struct lookahead_ctx *ctx, + unsigned int *idx) +{ + unsigned int index = *idx; + struct lookahead_entry *buf = ctx->buf + index; + + assert(index < ctx->max_sz); + if(++index >= ctx->max_sz) + index -= ctx->max_sz; + *idx = index; + return buf; +} + + +void +vp8_lookahead_destroy(struct lookahead_ctx *ctx) +{ + if(ctx) + { + if(ctx->buf) + { + int i; + + for(i = 0; i < ctx->max_sz; i++) + vp8_yv12_de_alloc_frame_buffer(&ctx->buf[i].img); + free(ctx->buf); + } + free(ctx); + } +} + + +struct lookahead_ctx* +vp8_lookahead_init(unsigned int width, + unsigned int height, + unsigned int depth) +{ + struct lookahead_ctx *ctx = NULL; + int i; + + /* Clamp the lookahead queue depth */ + if(depth < 1) + depth = 1; + else if(depth > MAX_LAG_BUFFERS) + depth = MAX_LAG_BUFFERS; + + /* Align the buffer dimensions */ + width = (width + 15) & ~15; + height = (height + 15) & ~15; + + /* Allocate the lookahead structures */ + ctx = calloc(1, sizeof(*ctx)); + if(ctx) + { + ctx->max_sz = depth; + ctx->buf = calloc(depth, sizeof(*ctx->buf)); + if(!ctx->buf) + goto bail; + for(i=0; i<depth; i++) + if (vp8_yv12_alloc_frame_buffer(&ctx->buf[i].img, width, height, 16)) + goto bail; + } + return ctx; +bail: + vp8_lookahead_destroy(ctx); + return NULL; +} + + +int +vp8_lookahead_push(struct lookahead_ctx *ctx, + YV12_BUFFER_CONFIG *src, + int64_t ts_start, + int64_t ts_end, + unsigned int flags) +{ + struct lookahead_entry* buf; + + 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); + buf->ts_start = ts_start; + buf->ts_end = ts_end; + buf->flags = flags; + return 0; +} + + +struct lookahead_entry* +vp8_lookahead_pop(struct lookahead_ctx *ctx, + int drain) +{ + struct lookahead_entry* buf = NULL; + + if(ctx->sz && (drain || ctx->sz == ctx->max_sz)) + { + buf = pop(ctx, &ctx->read_idx); + ctx->sz--; + } + return buf; +} + + +struct lookahead_entry* +vp8_lookahead_peek(struct lookahead_ctx *ctx, + int index) +{ + struct lookahead_entry* buf = NULL; + + assert(index < ctx->max_sz); + if(index < ctx->sz) + { + index += ctx->read_idx; + if(index >= ctx->max_sz) + index -= ctx->max_sz; + buf = ctx->buf + index; + } + return buf; +} + + +unsigned int +vp8_lookahead_depth(struct lookahead_ctx *ctx) +{ + return ctx->sz; +} diff --git a/vp8/encoder/lookahead.h b/vp8/encoder/lookahead.h new file mode 100644 index 0000000000000000000000000000000000000000..a483d7e0b9b61083e69dea8242732425343b5dc9 --- /dev/null +++ b/vp8/encoder/lookahead.h @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2011 The WebM project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ +#ifndef LOOKAHEAD_H +#define LOOKAHEAD_H +#include "vpx_scale/yv12config.h" +#include "vpx/vpx_integer.h" + +struct lookahead_entry +{ + YV12_BUFFER_CONFIG img; + int64_t ts_start; + int64_t ts_end; + unsigned int flags; +}; + + +struct lookahead_ctx; + +/**\brief Initializes the lookahead stage + * + * The lookahead stage is a queue of frame buffers on which some analysis + * may be done when buffers are enqueued. + * + * + */ +struct lookahead_ctx* vp8_lookahead_init(unsigned int width, + unsigned int height, + unsigned int depth + ); + + +/**\brief Destroys the lookahead stage + * + */ +void vp8_lookahead_destroy(struct lookahead_ctx *ctx); + + +/**\brief Enqueue a source buffer + * + * 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 + */ +int +vp8_lookahead_push(struct lookahead_ctx *ctx, + YV12_BUFFER_CONFIG *src, + int64_t ts_start, + int64_t ts_end, + unsigned int flags); + + +/**\brief Get the next source buffer to encode + * + * + * \param[in] ctx Pointer to the lookahead context + * \param[in] drain Flag indicating the buffer should be drained + * (return a buffer regardless of the current queue depth) + * + * \retval NULL, if drain set and queue is empty + * \retval NULL, if drain not set and queue not of the configured depth + * + */ +struct lookahead_entry* +vp8_lookahead_pop(struct lookahead_ctx *ctx, + int drain); + + +/**\brief Get a future source buffer to encode + * + * \param[in] ctx Pointer to the lookahead context + * \param[in] index Index of the frame to be returned, 0 == next frame + * + * \retval NULL, if no buffer exists at the specified index + * + */ +struct lookahead_entry* +vp8_lookahead_peek(struct lookahead_ctx *ctx, + int index); + + +/**\brief Get the number of frames currently in the lookahead queue + * + * \param[in] ctx Pointer to the lookahead context + */ +unsigned int +vp8_lookahead_depth(struct lookahead_ctx *ctx); + + +#endif diff --git a/vp8/encoder/onyx_if.c b/vp8/encoder/onyx_if.c index 476bf30f8681738fd70079270d0c1b061e8aed8c..92e0cbb193017e696ddbb72cf6911b9676eef43b 100644 --- a/vp8/encoder/onyx_if.c +++ b/vp8/encoder/onyx_if.c @@ -71,7 +71,7 @@ extern void vp8_yv12_copy_src_frame_func_neon(YV12_BUFFER_CONFIG *src_ybc, YV12_ int vp8_estimate_entropy_savings(VP8_COMP *cpi); int vp8_calc_ss_err(YV12_BUFFER_CONFIG *source, YV12_BUFFER_CONFIG *dest, const vp8_variance_rtcd_vtable_t *rtcd); -extern void vp8_temporal_filter_prepare_c(VP8_COMP *cpi); +extern void vp8_temporal_filter_prepare_c(VP8_COMP *cpi, int distance); static void set_default_lf_deltas(VP8_COMP *cpi); @@ -287,16 +287,9 @@ static void dealloc_compressor_data(VP8_COMP *cpi) vp8_yv12_de_alloc_frame_buffer(&cpi->last_frame_uf); vp8_yv12_de_alloc_frame_buffer(&cpi->scaled_source); #if VP8_TEMPORAL_ALT_REF - vp8_yv12_de_alloc_frame_buffer(&cpi->alt_ref_buffer.source_buffer); + vp8_yv12_de_alloc_frame_buffer(&cpi->alt_ref_buffer); #endif - { - int i; - - for (i = 0; i < MAX_LAG_BUFFERS; i++) - vp8_yv12_de_alloc_frame_buffer(&cpi->src_buffer[i].source_buffer); - - cpi->source_buffer_count = 0; - } + vp8_lookahead_destroy(cpi->lookahead); vpx_free(cpi->tok); cpi->tok = 0; @@ -1252,35 +1245,23 @@ void vp8_set_speed_features(VP8_COMP *cpi) } static void alloc_raw_frame_buffers(VP8_COMP *cpi) { - int i, buffers; - /* allocate source_buffer to be multiples of 16 */ int width = (cpi->oxcf.Width + 15) & ~15; + int height = (cpi->oxcf.Height + 15) & ~15; - buffers = cpi->oxcf.lag_in_frames; - - if (buffers > MAX_LAG_BUFFERS) - buffers = MAX_LAG_BUFFERS; - - if (buffers < 1) - buffers = 1; - - for (i = 0; i < buffers; i++) - if (vp8_yv12_alloc_frame_buffer(&cpi->src_buffer[i].source_buffer, - width, cpi->oxcf.Height, - 16)) - vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR, - "Failed to allocate lag buffer"); + cpi->lookahead = vp8_lookahead_init(cpi->oxcf.Width, cpi->oxcf.Height, + cpi->oxcf.lag_in_frames); + if(!cpi->lookahead) + vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR, + "Failed to allocate lag buffers"); #if VP8_TEMPORAL_ALT_REF - if (vp8_yv12_alloc_frame_buffer(&cpi->alt_ref_buffer.source_buffer, - width, cpi->oxcf.Height, 16)) + if (vp8_yv12_alloc_frame_buffer(&cpi->alt_ref_buffer, + width, height, 16)) vpx_internal_error(&cpi->common.error, VPX_CODEC_MEM_ERROR, "Failed to allocate altref buffer"); #endif - - cpi->source_buffer_count = 0; } static int vp8_alloc_partition_data(VP8_COMP *cpi) @@ -1772,7 +1753,7 @@ void vp8_change_config(VP8_PTR ptr, VP8_CONFIG *oxcf) cpi->oxcf.lag_in_frames = MAX_LAG_BUFFERS; // YX Temp - cpi->last_alt_ref_sei = -1; + cpi->alt_ref_source = NULL; cpi->is_src_frame_alt_ref = 0; cpi->is_next_src_alt_ref = 0; @@ -2120,8 +2101,6 @@ VP8_PTR vp8_create_compressor(VP8_CONFIG *oxcf) cpi->ready_for_new_frame = 1; - cpi->source_encode_index = 0; - // make sure frame 1 is okay cpi->error_bins[0] = cpi->common.MBs; @@ -2169,7 +2148,8 @@ void vp8_remove_compressor(VP8_PTR *ptr) if (cpi->pass != 1) { FILE *f = fopen("opsnr.stt", "a"); - double time_encoded = (cpi->source_end_time_stamp - cpi->first_time_stamp_ever) / 10000000.000; + double time_encoded = (cpi->last_end_time_stamp_seen + - cpi->first_time_stamp_ever) / 10000000.000; double total_encode_time = (cpi->time_receive_data + cpi->time_compress_data) / 1000.000; double dr = (double)cpi->bytes * (double) 8 / (double)1000 / time_encoded; @@ -2624,37 +2604,13 @@ static void scale_and_extend_source(YV12_BUFFER_CONFIG *sd, VP8_COMP *cpi) vp8_scale_frame(sd, &cpi->scaled_source, cm->temp_scale_frame.y_buffer, tmp_height, hs, hr, vs, vr, 0); + vp8_yv12_extend_frame_borders(&cpi->scaled_source); cpi->Source = &cpi->scaled_source; #endif } - // we may need to copy to a buffer so we can extend the image... - else if (cm->Width != cm->yv12_fb[cm->lst_fb_idx].y_width || - cm->Height != cm->yv12_fb[cm->lst_fb_idx].y_height) - { - //vp8_yv12_copy_frame_ptr(sd, &cpi->scaled_source); -#if HAVE_ARMV7 -#if CONFIG_RUNTIME_CPU_DETECT - if (cm->rtcd.flags & HAS_NEON) -#endif - { - vp8_yv12_copy_src_frame_func_neon(sd, &cpi->scaled_source); - } -#if CONFIG_RUNTIME_CPU_DETECT - else -#endif -#endif -#if !HAVE_ARMV7 || CONFIG_RUNTIME_CPU_DETECT - { - vp8_yv12_copy_frame_ptr(sd, &cpi->scaled_source); - } -#endif - - cpi->Source = &cpi->scaled_source; - } +} - vp8_extend_to_multiple_of16(cpi->Source, cm->Width, cm->Height); -} static void resize_key_frame(VP8_COMP *cpi) { #if CONFIG_SPATIAL_RESAMPLING @@ -3567,7 +3523,6 @@ static void encode_frame_to_data_rate if (Adjustment) { int buff_lvl_step; - int tmp_lvl = cpi->buffer_level; if (cpi->buffer_level < cpi->oxcf.maximum_buffer_size) { @@ -4668,17 +4623,17 @@ static void Pass2Encode(VP8_COMP *cpi, unsigned long *size, unsigned char *dest, extern void vp8_push_neon(INT64 *store); extern void vp8_pop_neon(INT64 *store); #endif + + int vp8_receive_raw_frame(VP8_PTR ptr, unsigned int frame_flags, YV12_BUFFER_CONFIG *sd, INT64 time_stamp, INT64 end_time) { #if HAVE_ARMV7 INT64 store_reg[8]; #endif - VP8_COMP *cpi = (VP8_COMP *) ptr; - VP8_COMMON *cm = &cpi->common; + VP8_COMP *cpi = (VP8_COMP *) ptr; + VP8_COMMON *cm = &cpi->common; struct vpx_usec_timer timer; - - if (!cpi) - return -1; + int res = 0; #if HAVE_ARMV7 #if CONFIG_RUNTIME_CPU_DETECT @@ -4690,75 +4645,10 @@ int vp8_receive_raw_frame(VP8_PTR ptr, unsigned int frame_flags, YV12_BUFFER_CON #endif vpx_usec_timer_start(&timer); - - // no more room for frames; - if (cpi->source_buffer_count != 0 && cpi->source_buffer_count >= cpi->oxcf.lag_in_frames) - { -#if HAVE_ARMV7 -#if CONFIG_RUNTIME_CPU_DETECT - if (cm->rtcd.flags & HAS_NEON) -#endif - { - vp8_pop_neon(store_reg); - } -#endif - return -1; - } - - //printf("in-cpi->source_buffer_count: %d\n", cpi->source_buffer_count); - + if(vp8_lookahead_push(cpi->lookahead, sd, time_stamp, end_time, + frame_flags)) + res = -1; cm->clr_type = sd->clrtype; - - // make a copy of the frame for use later... -#if !(CONFIG_REALTIME_ONLY) - - if (cpi->oxcf.allow_lag) - { - int which_buffer = cpi->source_encode_index - 1; - SOURCE_SAMPLE *s; - - if (which_buffer == -1) - which_buffer = cpi->oxcf.lag_in_frames - 1; - - if (cpi->source_buffer_count < cpi->oxcf.lag_in_frames - 1) - which_buffer = cpi->source_buffer_count; - - s = &cpi->src_buffer[which_buffer]; - - s->source_time_stamp = time_stamp; - s->source_end_time_stamp = end_time; - s->source_frame_flags = frame_flags; - vp8_yv12_copy_frame_ptr(sd, &s->source_buffer); - - cpi->source_buffer_count ++; - } - else -#endif - { - SOURCE_SAMPLE *s; - s = &cpi->src_buffer[0]; - s->source_end_time_stamp = end_time; - s->source_time_stamp = time_stamp; - s->source_frame_flags = frame_flags; -#if HAVE_ARMV7 -#if CONFIG_RUNTIME_CPU_DETECT - if (cm->rtcd.flags & HAS_NEON) -#endif - { - vp8_yv12_copy_src_frame_func_neon(sd, &s->source_buffer); - } -#if CONFIG_RUNTIME_CPU_DETECT - else -#endif -#endif -#if !HAVE_ARMV7 || CONFIG_RUNTIME_CPU_DETECT - { - vp8_yv12_copy_frame_ptr(sd, &s->source_buffer); - } -#endif - cpi->source_buffer_count = 1; - } - vpx_usec_timer_mark(&timer); cpi->time_receive_data += vpx_usec_timer_elapsed(&timer); @@ -4771,8 +4661,10 @@ int vp8_receive_raw_frame(VP8_PTR ptr, unsigned int frame_flags, YV12_BUFFER_CON } #endif - return 0; + return res; } + + int vp8_get_compressed_data(VP8_PTR ptr, unsigned int *frame_flags, unsigned long *size, unsigned char *dest, INT64 *time_stamp, INT64 *time_end, int flush) { #if HAVE_ARMV7 @@ -4783,6 +4675,7 @@ int vp8_get_compressed_data(VP8_PTR ptr, unsigned int *frame_flags, unsigned lon struct vpx_usec_timer tsctimer; struct vpx_usec_timer ticktimer; struct vpx_usec_timer cmptimer; + YV12_BUFFER_CONFIG *force_src_buffer = NULL; if (!cpi) return -1; @@ -4798,95 +4691,24 @@ int vp8_get_compressed_data(VP8_PTR ptr, unsigned int *frame_flags, unsigned lon vpx_usec_timer_start(&cmptimer); - - // flush variable tells us that even though we have less than 10 frames - // in our buffer we need to start producing compressed frames. - // Probably because we are at the end of a file.... - if ((cpi->source_buffer_count == cpi->oxcf.lag_in_frames && cpi->oxcf.lag_in_frames > 0) - || (!cpi->oxcf.allow_lag && cpi->source_buffer_count > 0) - || (flush && cpi->source_buffer_count > 0)) - { - - SOURCE_SAMPLE *s; - - s = &cpi->src_buffer[cpi->source_encode_index]; - cpi->source_time_stamp = s->source_time_stamp; - cpi->source_end_time_stamp = s->source_end_time_stamp; + cpi->source = NULL; #if !(CONFIG_REALTIME_ONLY) - - // Should we code an alternate reference frame - if (cpi->oxcf.error_resilient_mode == 0 && - cpi->oxcf.play_alternate && - cpi->source_alt_ref_pending && - (cpi->frames_till_gf_update_due < cpi->source_buffer_count) && - cpi->oxcf.lag_in_frames != 0) + // Should we code an alternate reference frame + if (cpi->oxcf.error_resilient_mode == 0 && + cpi->oxcf.play_alternate && + cpi->source_alt_ref_pending) + { + if ((cpi->source = vp8_lookahead_peek(cpi->lookahead, + cpi->frames_till_gf_update_due))) { - cpi->last_alt_ref_sei = (cpi->source_encode_index + cpi->frames_till_gf_update_due) % cpi->oxcf.lag_in_frames; - -#if VP8_TEMPORAL_ALT_REF - + cpi->alt_ref_source = cpi->source; if (cpi->oxcf.arnr_max_frames > 0) { -#if 0 - // my attempt at a loop that tests the results of strength filter. - int start_frame = cpi->last_alt_ref_sei - 3; - - int i, besti = -1, pastin = cpi->oxcf.arnr_strength; - - int besterr; - - if (start_frame < 0) - start_frame += cpi->oxcf.lag_in_frames; - - besterr = calc_low_ss_err(&cpi->src_buffer[cpi->last_alt_ref_sei].source_buffer, - &cpi->src_buffer[start_frame].source_buffer, IF_RTCD(&cpi->rtcd.variance)); - - for (i = 0; i < 7; i++) - { - int thiserr; - cpi->oxcf.arnr_strength = i; - vp8_temporal_filter_prepare_c(cpi); - - thiserr = calc_low_ss_err(&cpi->alt_ref_buffer.source_buffer, - &cpi->src_buffer[start_frame].source_buffer, IF_RTCD(&cpi->rtcd.variance)); - - if (10 * thiserr < besterr * 8) - { - besterr = thiserr; - besti = i; - } - } - - if (besti != -1) - { - cpi->oxcf.arnr_strength = besti; - vp8_temporal_filter_prepare_c(cpi); - s = &cpi->alt_ref_buffer; - - // FWG not sure if I need to copy this data for the Alt Ref frame - s->source_time_stamp = cpi->src_buffer[cpi->last_alt_ref_sei].source_time_stamp; - s->source_end_time_stamp = cpi->src_buffer[cpi->last_alt_ref_sei].source_end_time_stamp; - s->source_frame_flags = cpi->src_buffer[cpi->last_alt_ref_sei].source_frame_flags; - } - else - s = &cpi->src_buffer[cpi->last_alt_ref_sei]; - -#else - vp8_temporal_filter_prepare_c(cpi); - s = &cpi->alt_ref_buffer; - - // FWG not sure if I need to copy this data for the Alt Ref frame - s->source_time_stamp = cpi->src_buffer[cpi->last_alt_ref_sei].source_time_stamp; - s->source_end_time_stamp = cpi->src_buffer[cpi->last_alt_ref_sei].source_end_time_stamp; - s->source_frame_flags = cpi->src_buffer[cpi->last_alt_ref_sei].source_frame_flags; - -#endif + vp8_temporal_filter_prepare_c(cpi, + cpi->frames_till_gf_update_due); + force_src_buffer = &cpi->alt_ref_buffer; } - else -#endif - s = &cpi->src_buffer[cpi->last_alt_ref_sei]; - cm->frames_till_alt_ref_frame = cpi->frames_till_gf_update_due; cm->refresh_alt_ref_frame = 1; cm->refresh_golden_frame = 0; @@ -4896,40 +4718,33 @@ int vp8_get_compressed_data(VP8_PTR ptr, unsigned int *frame_flags, unsigned lon cpi->is_src_frame_alt_ref = 0; cpi->is_next_src_alt_ref = 0; } - else + } #endif + + if (!cpi->source) + { + if ((cpi->source = vp8_lookahead_pop(cpi->lookahead, flush))) { cm->show_frame = 1; -#if !(CONFIG_REALTIME_ONLY) - - if (cpi->oxcf.allow_lag) - { - if (cpi->source_encode_index == cpi->last_alt_ref_sei) - { - cpi->is_src_frame_alt_ref = 1; - cpi->last_alt_ref_sei = -1; - } - else - cpi->is_src_frame_alt_ref = 0; - cpi->source_encode_index = (cpi->source_encode_index + 1) % cpi->oxcf.lag_in_frames; + cpi->is_src_frame_alt_ref = cpi->alt_ref_source + && (cpi->source == cpi->alt_ref_source); - if(cpi->source_encode_index == cpi->last_alt_ref_sei) - cpi->is_next_src_alt_ref = 1; - else - cpi->is_next_src_alt_ref = 0; - } - -#endif - cpi->source_buffer_count--; + cpi->is_next_src_alt_ref = cpi->alt_ref_source + && (vp8_lookahead_peek(cpi->lookahead, 0) + == cpi->alt_ref_source); + if(cpi->is_src_frame_alt_ref) + cpi->alt_ref_source = NULL; } + } - cpi->un_scaled_source = &s->source_buffer; - cpi->Source = &s->source_buffer; - cpi->source_frame_flags = s->source_frame_flags; - - *time_stamp = cpi->source_time_stamp; - *time_end = cpi->source_end_time_stamp; + if (cpi->source) + { + cpi->un_scaled_source = + cpi->Source = force_src_buffer ? force_src_buffer : &cpi->source->img; + *time_stamp = cpi->source->ts_start; + *time_end = cpi->source->ts_end; + *frame_flags = cpi->source->flags; } else { @@ -4955,26 +4770,24 @@ int vp8_get_compressed_data(VP8_PTR ptr, unsigned int *frame_flags, unsigned lon return -1; } - *frame_flags = cpi->source_frame_flags; - - if (cpi->source_time_stamp < cpi->first_time_stamp_ever) + if (cpi->source->ts_start < cpi->first_time_stamp_ever) { - cpi->first_time_stamp_ever = cpi->source_time_stamp; - cpi->last_end_time_stamp_seen = cpi->source_time_stamp; + cpi->first_time_stamp_ever = cpi->source->ts_start; + cpi->last_end_time_stamp_seen = cpi->source->ts_start; } // adjust frame rates based on timestamps given if (!cm->refresh_alt_ref_frame) { - if (cpi->source_time_stamp == cpi->first_time_stamp_ever) + if (cpi->source->ts_start == cpi->first_time_stamp_ever) { - double this_fps = 10000000.000 / (cpi->source_end_time_stamp - cpi->source_time_stamp); + double this_fps = 10000000.000 / (cpi->source->ts_end - cpi->source->ts_start); vp8_new_frame_rate(cpi, this_fps); } else { - long long nanosecs = cpi->source_end_time_stamp + long long nanosecs = cpi->source->ts_end - cpi->last_end_time_stamp_seen; if (nanosecs > 0) @@ -4985,8 +4798,8 @@ int vp8_get_compressed_data(VP8_PTR ptr, unsigned int *frame_flags, unsigned lon } - cpi->last_time_stamp_seen = cpi->source_time_stamp; - cpi->last_end_time_stamp_seen = cpi->source_end_time_stamp; + cpi->last_time_stamp_seen = cpi->source->ts_start; + cpi->last_end_time_stamp_seen = cpi->source->ts_end; } if (cpi->compressor_speed == 2) @@ -5107,7 +4920,6 @@ int vp8_get_compressed_data(VP8_PTR ptr, unsigned int *frame_flags, unsigned lon if (cpi->b_calculate_psnr) { - double y, u, v; double ye,ue,ve; double frame_psnr; YV12_BUFFER_CONFIG *orig = cpi->Source; @@ -5140,7 +4952,7 @@ int vp8_get_compressed_data(VP8_PTR ptr, unsigned int *frame_flags, unsigned lon cpi->total_sq_error += sq_error; cpi->total += frame_psnr; { - double y2, u2, v2, frame_psnr2, frame_ssim2 = 0; + double frame_psnr2, frame_ssim2 = 0; double weight = 0; vp8_deblock(cm->frame_to_show, &cm->post_proc_buffer, cm->filter_level * 10 / 6, 1, 0, IF_RTCD(&cm->rtcd.postproc)); diff --git a/vp8/encoder/onyx_int.h b/vp8/encoder/onyx_int.h index 0e53f6803a939555fc6cb0b189ebe8edb4867b0a..0ab528e27504d6e77124e4315af14e4de457f8e1 100644 --- a/vp8/encoder/onyx_int.h +++ b/vp8/encoder/onyx_int.h @@ -29,6 +29,7 @@ #include "mcomp.h" #include "temporal_filter.h" #include "vp8/common/findnearmv.h" +#include "lookahead.h" //#define SPEEDSTATS 1 #define MIN_GF_INTERVAL 4 @@ -217,14 +218,6 @@ typedef struct void *ptr1; } LPFTHREAD_DATA; -typedef struct -{ - INT64 source_time_stamp; - INT64 source_end_time_stamp; - - DECLARE_ALIGNED(16, YV12_BUFFER_CONFIG, source_buffer); - unsigned int source_frame_flags; -} SOURCE_SAMPLE; typedef struct VP8_ENCODER_RTCD { @@ -280,19 +273,17 @@ typedef struct VP8_CONFIG oxcf; + struct lookahead_ctx *lookahead; + struct lookahead_entry *source; + struct lookahead_entry *alt_ref_source; + YV12_BUFFER_CONFIG *Source; YV12_BUFFER_CONFIG *un_scaled_source; - INT64 source_time_stamp; - INT64 source_end_time_stamp; - unsigned int source_frame_flags; YV12_BUFFER_CONFIG scaled_source; - int source_buffer_count; // number of src_buffers in use for lagged encoding - int source_encode_index; // index of buffer in src_buffer to encode int source_alt_ref_pending; // frame in src_buffers has been identified to be encoded as an alt ref int source_alt_ref_active; // an alt ref frame has been encoded and is usable - int last_alt_ref_sei; // index into src_buffers of frame used as alt reference int is_src_frame_alt_ref; // source of frame to encode is an exact copy of an alt ref frame int is_next_src_alt_ref; // source of next frame to encode is an exact copy of an alt ref frame @@ -301,8 +292,6 @@ typedef struct int gold_is_alt; // don't do both alt and gold search ( just do gold). //int refresh_alt_ref_frame; - SOURCE_SAMPLE src_buffer[MAX_LAG_BUFFERS]; - YV12_BUFFER_CONFIG last_frame_uf; TOKENEXTRA *tok; @@ -638,7 +627,7 @@ typedef struct VP8_ENCODER_RTCD rtcd; #endif #if VP8_TEMPORAL_ALT_REF - SOURCE_SAMPLE alt_ref_buffer; + YV12_BUFFER_CONFIG alt_ref_buffer; YV12_BUFFER_CONFIG *frames[MAX_LAG_BUFFERS]; int fixed_divide[512]; #endif diff --git a/vp8/encoder/temporal_filter.c b/vp8/encoder/temporal_filter.c index cec9518975d2710e8c131c3b0701184114d2f8aa..8cd9f4711e2fcbfc099511a68f1ba1b0c84d2c4f 100644 --- a/vp8/encoder/temporal_filter.c +++ b/vp8/encoder/temporal_filter.c @@ -357,8 +357,8 @@ static void vp8_temporal_filter_iterate_c } // Normalize filter output to produce AltRef frame - dst1 = cpi->alt_ref_buffer.source_buffer.y_buffer; - stride = cpi->alt_ref_buffer.source_buffer.y_stride; + dst1 = cpi->alt_ref_buffer.y_buffer; + stride = cpi->alt_ref_buffer.y_stride; byte = mb_y_offset; for (i = 0,k = 0; i < 16; i++) { @@ -377,9 +377,9 @@ static void vp8_temporal_filter_iterate_c byte += stride - 16; } - dst1 = cpi->alt_ref_buffer.source_buffer.u_buffer; - dst2 = cpi->alt_ref_buffer.source_buffer.v_buffer; - stride = cpi->alt_ref_buffer.source_buffer.uv_stride; + dst1 = cpi->alt_ref_buffer.u_buffer; + dst2 = cpi->alt_ref_buffer.v_buffer; + stride = cpi->alt_ref_buffer.uv_stride; byte = mb_uv_offset; for (i = 0,k = 256; i < 8; i++) { @@ -422,7 +422,8 @@ static void vp8_temporal_filter_iterate_c void vp8_temporal_filter_prepare_c ( - VP8_COMP *cpi + VP8_COMP *cpi, + int distance ) { int frame = 0; @@ -441,12 +442,9 @@ void vp8_temporal_filter_prepare_c int max_frames = cpi->active_arnr_frames; - num_frames_backward = cpi->last_alt_ref_sei - cpi->source_encode_index; - - if (num_frames_backward < 0) - num_frames_backward += cpi->oxcf.lag_in_frames; - - num_frames_forward = cpi->oxcf.lag_in_frames - (num_frames_backward + 1); + num_frames_backward = distance; + num_frames_forward = vp8_lookahead_depth(cpi->lookahead) + - (num_frames_backward + 1); switch (blur_type) { @@ -498,8 +496,7 @@ void vp8_temporal_filter_prepare_c break; } - start_frame = (cpi->last_alt_ref_sei - + frames_to_blur_forward) % cpi->oxcf.lag_in_frames; + start_frame = distance + frames_to_blur_forward; #ifdef DEBUGFWG // DEBUG FWG @@ -520,12 +517,9 @@ void vp8_temporal_filter_prepare_c for (frame = 0; frame < frames_to_blur; frame++) { int which_buffer = start_frame - frame; - - if (which_buffer < 0) - which_buffer += cpi->oxcf.lag_in_frames; - - cpi->frames[frames_to_blur-1-frame] - = &cpi->src_buffer[which_buffer].source_buffer; + struct lookahead_entry* buf = vp8_lookahead_peek(cpi->lookahead, + which_buffer); + cpi->frames[frames_to_blur-1-frame] = &buf->img; } vp8_temporal_filter_iterate_c ( diff --git a/vp8/vp8cx.mk b/vp8/vp8cx.mk index 8037f9adbbe8f11779839fc7fd517ba574af91d0..a7b68dba7578d5d941b3b52f322f5e455a3308d9 100644 --- a/vp8/vp8cx.mk +++ b/vp8/vp8cx.mk @@ -52,6 +52,8 @@ VP8_CX_SRCS-yes += encoder/encodeintra.h VP8_CX_SRCS-yes += encoder/encodemb.h VP8_CX_SRCS-yes += encoder/encodemv.h VP8_CX_SRCS-yes += encoder/firstpass.h +VP8_CX_SRCS-yes += encoder/lookahead.c +VP8_CX_SRCS-yes += encoder/lookahead.h VP8_CX_SRCS-yes += encoder/mcomp.h VP8_CX_SRCS-yes += encoder/modecosts.h VP8_CX_SRCS-yes += encoder/onyx_int.h