#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 */
int er /* extend right border */
)
{
-
int i;
unsigned char *src_ptr1, *src_ptr2;
unsigned char *dest_ptr1, *dest_ptr2;
/* 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)
{
#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
// 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,
--- /dev/null
+/*
+ * 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;
+}
--- /dev/null
+/*
+ * 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
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);
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;
}
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)
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;
cpi->ready_for_new_frame = 1;
- cpi->source_encode_index = 0;
-
// make sure frame 1 is okay
cpi->error_bins[0] = cpi->common.MBs;
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;
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
if (Adjustment)
{
int buff_lvl_step;
- int tmp_lvl = cpi->buffer_level;
if (cpi->buffer_level < cpi->oxcf.maximum_buffer_size)
{
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
#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);
}
#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
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;
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;
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
{
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)
}
- 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)
if (cpi->b_calculate_psnr)
{
- double y, u, v;
double ye,ue,ve;
double frame_psnr;
YV12_BUFFER_CONFIG *orig = cpi->Source;
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));
#include "mcomp.h"
#include "temporal_filter.h"
#include "vp8/common/findnearmv.h"
+#include "lookahead.h"
//#define SPEEDSTATS 1
#define MIN_GF_INTERVAL 4
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
{
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
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;
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
}
// 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++)
{
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++)
{
void vp8_temporal_filter_prepare_c
(
- VP8_COMP *cpi
+ VP8_COMP *cpi,
+ int distance
)
{
int frame = 0;
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)
{
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
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 (
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