Merge "Using struct twopass_rc* instead of VP9_COMP*."
diff --git a/build/make/Makefile b/build/make/Makefile
index 030c1b5..6894d6d 100644
--- a/build/make/Makefile
+++ b/build/make/Makefile
@@ -390,7 +390,7 @@
DIST-SRCS-$(CONFIG_MSVS) += build/make/gen_msvs_def.sh
DIST-SRCS-$(CONFIG_MSVS) += build/make/gen_msvs_proj.sh
DIST-SRCS-$(CONFIG_MSVS) += build/make/gen_msvs_sln.sh
- DIST-SRCS-$(CONFIG_MSVS) += build/x86-msvs/yasm.rules
+ DIST-SRCS-$(CONFIG_MSVS) += build/make/gen_msvs_vcxproj.sh
DIST-SRCS-$(CONFIG_MSVS) += build/x86-msvs/obj_int_extract.bat
DIST-SRCS-$(CONFIG_MSVS) += build/arm-msvs/obj_int_extract.bat
DIST-SRCS-$(CONFIG_RVCT) += build/make/armlink_adapter.sh
diff --git a/ivfdec.c b/ivfdec.c
index 4a0816f..a37a44c 100644
--- a/ivfdec.c
+++ b/ivfdec.c
@@ -17,11 +17,6 @@
char raw_hdr[32];
int is_ivf = 0;
- // TODO(tomfinegan): This can eventually go away, but for now it's required
- // because the means by which file types are detected differ in vpxdec and
- // vpxenc.
- rewind(input_ctx->file);
-
if (fread(raw_hdr, 1, 32, input_ctx->file) == 32) {
if (raw_hdr[0] == 'D' && raw_hdr[1] == 'K' &&
raw_hdr[2] == 'I' && raw_hdr[3] == 'F') {
diff --git a/vp9/common/vp9_alloccommon.c b/vp9/common/vp9_alloccommon.c
index 6d48542..ff20553 100644
--- a/vp9/common/vp9_alloccommon.c
+++ b/vp9/common/vp9_alloccommon.c
@@ -161,9 +161,6 @@
cm->new_fb_idx = cm->fb_count - 1;
cm->fb_idx_ref_cnt[cm->new_fb_idx] = 1;
- for (i = 0; i < REFS_PER_FRAME; i++)
- cm->active_ref_idx[i] = i;
-
for (i = 0; i < REF_FRAMES; i++) {
cm->ref_frame_map[i] = i;
cm->fb_idx_ref_cnt[i] = 1;
diff --git a/vp9/common/vp9_blockd.h b/vp9/common/vp9_blockd.h
index 38acf1e..c6af7f6 100644
--- a/vp9/common/vp9_blockd.h
+++ b/vp9/common/vp9_blockd.h
@@ -212,11 +212,17 @@
#define BLOCK_OFFSET(x, i) ((x) + (i) * 16)
+typedef struct RefBuffer {
+ // TODO(dkovalev): idx is not really required and should be removed, now it
+ // is used in vp9_onyxd_if.c
+ int idx;
+ YV12_BUFFER_CONFIG *buf;
+ struct scale_factors sf;
+} RefBuffer;
+
typedef struct macroblockd {
struct macroblockd_plane plane[MAX_MB_PLANE];
- const struct scale_factors *scale_factors[2];
-
MODE_INFO *last_mi;
int mode_info_stride;
@@ -235,7 +241,7 @@
int mb_to_bottom_edge;
/* pointers to reference frames */
- const YV12_BUFFER_CONFIG *ref_buf[2];
+ RefBuffer *block_refs[2];
/* pointer to current frame */
const YV12_BUFFER_CONFIG *cur_buf;
diff --git a/vp9/common/vp9_onyxc_int.h b/vp9/common/vp9_onyxc_int.h
index ed4c044..b5ed959 100644
--- a/vp9/common/vp9_onyxc_int.h
+++ b/vp9/common/vp9_onyxc_int.h
@@ -121,8 +121,8 @@
// roll new_fb_idx into it.
// Each frame can reference REFS_PER_FRAME buffers
- int active_ref_idx[REFS_PER_FRAME];
- struct scale_factors active_ref_scale[REFS_PER_FRAME];
+ RefBuffer frame_refs[REFS_PER_FRAME];
+
int new_fb_idx;
YV12_BUFFER_CONFIG post_proc_buffer;
@@ -224,13 +224,6 @@
uint32_t fb_idx_ref_lru_count;
} VP9_COMMON;
-// ref == 0 => LAST_FRAME
-// ref == 1 => GOLDEN_FRAME
-// ref == 2 => ALTREF_FRAME
-static YV12_BUFFER_CONFIG *get_frame_ref_buffer(VP9_COMMON *cm, int ref) {
- return &cm->yv12_fb[cm->active_ref_idx[ref]];
-}
-
static YV12_BUFFER_CONFIG *get_frame_new_buffer(VP9_COMMON *cm) {
return &cm->yv12_fb[cm->new_fb_idx];
}
diff --git a/vp9/common/vp9_reconinter.c b/vp9/common/vp9_reconinter.c
index c84007e..397f446 100644
--- a/vp9/common/vp9_reconinter.c
+++ b/vp9/common/vp9_reconinter.c
@@ -153,7 +153,7 @@
int ref;
for (ref = 0; ref < 1 + is_compound; ++ref) {
- const struct scale_factors *const sf = xd->scale_factors[ref];
+ const struct scale_factors *const sf = &xd->block_refs[ref]->sf;
struct buf_2d *const pre_buf = &pd->pre[ref];
struct buf_2d *const dst_buf = &pd->dst;
uint8_t *const dst = dst_buf->buf + dst_buf->stride * y + x;
@@ -256,7 +256,7 @@
int ref;
for (ref = 0; ref < 1 + is_compound; ++ref) {
- const struct scale_factors *const sf = xd->scale_factors[ref];
+ const struct scale_factors *const sf = &xd->block_refs[ref]->sf;
struct buf_2d *const pre_buf = &pd->pre[ref];
struct buf_2d *const dst_buf = &pd->dst;
uint8_t *const dst = dst_buf->buf + dst_buf->stride * y + x;
@@ -283,7 +283,7 @@
int xs, ys, x0, y0, x0_16, y0_16, x1, y1, frame_width,
frame_height, subpel_x, subpel_y;
uint8_t *ref_frame, *buf_ptr;
- const YV12_BUFFER_CONFIG *ref_buf = xd->ref_buf[ref];
+ const YV12_BUFFER_CONFIG *ref_buf = xd->block_refs[ref]->buf;
// Get reference frame pointer, width and height.
if (plane == 0) {
@@ -390,14 +390,3 @@
}
}
}
-
-// TODO(dkovalev: find better place for this function)
-void vp9_setup_scale_factors(VP9_COMMON *cm, int i) {
- const int ref = cm->active_ref_idx[i];
- struct scale_factors *const sf = &cm->active_ref_scale[i];
- YV12_BUFFER_CONFIG *const fb = &cm->yv12_fb[ref];
- vp9_setup_scale_factors_for_frame(sf,
- fb->y_crop_width, fb->y_crop_height,
- cm->width, cm->height);
-}
-
diff --git a/vp9/common/vp9_reconinter.h b/vp9/common/vp9_reconinter.h
index a4e968c..9f37939 100644
--- a/vp9/common/vp9_reconinter.h
+++ b/vp9/common/vp9_reconinter.h
@@ -92,10 +92,8 @@
static void set_scale_factors(VP9_COMMON *cm, MACROBLOCKD *xd,
int ref0, int ref1) {
- xd->scale_factors[0] = &cm->active_ref_scale[ref0 >= 0 ? ref0 : 0];
- xd->scale_factors[1] = &cm->active_ref_scale[ref1 >= 0 ? ref1 : 0];
+ xd->block_refs[0] = &cm->frame_refs[ref0 >= 0 ? ref0 : 0];
+ xd->block_refs[1] = &cm->frame_refs[ref1 >= 0 ? ref1 : 0];
}
-void vp9_setup_scale_factors(VP9_COMMON *cm, int i);
-
#endif // VP9_COMMON_VP9_RECONINTER_H_
diff --git a/vp9/common/vp9_rtcd_defs.sh b/vp9/common/vp9_rtcd_defs.sh
index 3025ed4..26fd7fb 100644
--- a/vp9/common/vp9_rtcd_defs.sh
+++ b/vp9/common/vp9_rtcd_defs.sh
@@ -343,25 +343,25 @@
# variance
prototype unsigned int vp9_variance32x16 "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse"
-specialize vp9_variance32x16 $sse2_x86inc
+specialize vp9_variance32x16 $sse2_x86inc $avx2_x86inc
prototype unsigned int vp9_variance16x32 "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse"
specialize vp9_variance16x32 $sse2_x86inc
prototype unsigned int vp9_variance64x32 "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse"
-specialize vp9_variance64x32 $sse2_x86inc
+specialize vp9_variance64x32 $sse2_x86inc $avx2_x86inc
prototype unsigned int vp9_variance32x64 "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse"
specialize vp9_variance32x64 $sse2_x86inc
prototype unsigned int vp9_variance32x32 "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse"
-specialize vp9_variance32x32 $sse2_x86inc
+specialize vp9_variance32x32 $sse2_x86inc $avx2_x86inc
prototype unsigned int vp9_variance64x64 "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse"
-specialize vp9_variance64x64 $sse2_x86inc
+specialize vp9_variance64x64 $sse2_x86inc $avx2_x86inc
prototype unsigned int vp9_variance16x16 "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse"
-specialize vp9_variance16x16 mmx $sse2_x86inc
+specialize vp9_variance16x16 mmx $sse2_x86inc $avx2_x86inc
prototype unsigned int vp9_variance16x8 "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int ref_stride, unsigned int *sse"
specialize vp9_variance16x8 mmx $sse2_x86inc
@@ -662,7 +662,7 @@
#specialize vp9_sub_pixel_mse16x16 sse2 mmx
prototype unsigned int vp9_mse16x16 "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int recon_stride, unsigned int *sse"
-specialize vp9_mse16x16 mmx $sse2_x86inc
+specialize vp9_mse16x16 mmx $sse2_x86inc $avx2_x86inc
prototype unsigned int vp9_mse8x16 "const uint8_t *src_ptr, int source_stride, const uint8_t *ref_ptr, int recon_stride, unsigned int *sse"
specialize vp9_mse8x16
diff --git a/vp9/common/vp9_systemdependent.h b/vp9/common/vp9_systemdependent.h
index 254a431..7c277c3 100644
--- a/vp9/common/vp9_systemdependent.h
+++ b/vp9/common/vp9_systemdependent.h
@@ -12,6 +12,7 @@
#define VP9_COMMON_VP9_SYSTEMDEPENDENT_H_
#ifdef _MSC_VER
+#include <intrin.h>
#include <math.h>
#define snprintf _snprintf
#endif
@@ -34,6 +35,16 @@
}
#endif
+static const inline int get_msb(int x) {
+#ifdef _MSC_VER
+int r = 0;
+_BitScanReverse(&r, x);
+return r;
+#else
+return 31 ^ __builtin_clz(x);
+#endif
+}
+
struct VP9Common;
void vp9_machine_specific_config(struct VP9Common *cm);
diff --git a/vp9/decoder/vp9_decodeframe.c b/vp9/decoder/vp9_decodeframe.c
index de6dbdc..59faccd 100644
--- a/vp9/decoder/vp9_decodeframe.c
+++ b/vp9/decoder/vp9_decodeframe.c
@@ -378,18 +378,13 @@
static void set_ref(VP9_COMMON *const cm, MACROBLOCKD *const xd,
int idx, int mi_row, int mi_col) {
MB_MODE_INFO *const mbmi = &xd->mi_8x8[0]->mbmi;
- const int ref = mbmi->ref_frame[idx] - LAST_FRAME;
- const YV12_BUFFER_CONFIG *cfg = get_frame_ref_buffer(cm, ref);
- const struct scale_factors *sf = &cm->active_ref_scale[ref];
-
- xd->ref_buf[idx] = cfg;
- if (!vp9_is_valid_scale(sf))
+ RefBuffer *ref_buffer = &cm->frame_refs[mbmi->ref_frame[idx] - LAST_FRAME];
+ xd->block_refs[idx] = ref_buffer;
+ if (!vp9_is_valid_scale(&ref_buffer->sf))
vpx_internal_error(&cm->error, VPX_CODEC_UNSUP_BITSTREAM,
"Invalid scale factors");
-
- xd->scale_factors[idx] = sf;
- setup_pre_planes(xd, idx, cfg, mi_row, mi_col, xd->scale_factors[idx]);
- xd->corrupted |= cfg->corrupted;
+ setup_pre_planes(xd, idx, ref_buffer->buf, mi_row, mi_col, &ref_buffer->sf);
+ xd->corrupted |= ref_buffer->buf->corrupted;
}
static void decode_modes_b(VP9_COMMON *const cm, MACROBLOCKD *const xd,
@@ -737,9 +732,9 @@
int found = 0, i;
for (i = 0; i < REFS_PER_FRAME; ++i) {
if (vp9_rb_read_bit(rb)) {
- YV12_BUFFER_CONFIG *const cfg = get_frame_ref_buffer(cm, i);
- width = cfg->y_crop_width;
- height = cfg->y_crop_height;
+ YV12_BUFFER_CONFIG *const buf = cm->frame_refs[i].buf;
+ width = buf->y_crop_width;
+ height = buf->y_crop_height;
found = 1;
break;
}
@@ -1171,8 +1166,10 @@
pbi->refresh_frame_flags = (1 << REF_FRAMES) - 1;
- for (i = 0; i < REFS_PER_FRAME; ++i)
- cm->active_ref_idx[i] = cm->new_fb_idx;
+ for (i = 0; i < REFS_PER_FRAME; ++i) {
+ cm->frame_refs[i].idx = cm->new_fb_idx;
+ cm->frame_refs[i].buf = get_frame_new_buffer(cm);
+ }
setup_frame_size(pbi, rb);
} else {
@@ -1191,7 +1188,9 @@
for (i = 0; i < REFS_PER_FRAME; ++i) {
const int ref = vp9_rb_read_literal(rb, REF_FRAMES_LOG2);
- cm->active_ref_idx[i] = cm->ref_frame_map[ref];
+ const int idx = cm->ref_frame_map[ref];
+ cm->frame_refs[i].idx = idx;
+ cm->frame_refs[i].buf = &cm->yv12_fb[idx];
cm->ref_frame_sign_bias[LAST_FRAME + i] = vp9_rb_read_bit(rb);
}
@@ -1201,9 +1200,13 @@
cm->mcomp_filter_type = read_interp_filter_type(rb);
for (i = 0; i < REFS_PER_FRAME; ++i) {
- vp9_setup_scale_factors(cm, i);
- if (vp9_is_scaled(&cm->active_ref_scale[i]))
- vp9_extend_frame_borders(&cm->yv12_fb[cm->active_ref_idx[i]],
+ RefBuffer *const ref_buf = &cm->frame_refs[i];
+ vp9_setup_scale_factors_for_frame(&ref_buf->sf,
+ ref_buf->buf->y_crop_width,
+ ref_buf->buf->y_crop_height,
+ cm->width, cm->height);
+ if (vp9_is_scaled(&ref_buf->sf))
+ vp9_extend_frame_borders(ref_buf->buf,
cm->subsampling_x, cm->subsampling_y);
}
}
diff --git a/vp9/decoder/vp9_onyxd_if.c b/vp9/decoder/vp9_onyxd_if.c
index d585b91..75d52c2 100644
--- a/vp9/decoder/vp9_onyxd_if.c
+++ b/vp9/decoder/vp9_onyxd_if.c
@@ -219,7 +219,7 @@
YV12_BUFFER_CONFIG *sd) {
VP9D_COMP *pbi = (VP9D_COMP *) ptr;
VP9_COMMON *cm = &pbi->common;
- int *ref_fb_ptr = NULL;
+ RefBuffer *ref_buf = NULL;
/* TODO(jkoleszar): The decoder doesn't have any real knowledge of what the
* encoder is using the frame buffers for. This is just a stub to keep the
@@ -227,21 +227,23 @@
* later commit that adds VP9-specific controls for this functionality.
*/
if (ref_frame_flag == VP9_LAST_FLAG) {
- ref_fb_ptr = &pbi->common.active_ref_idx[0];
+ ref_buf = &cm->frame_refs[0];
} else if (ref_frame_flag == VP9_GOLD_FLAG) {
- ref_fb_ptr = &pbi->common.active_ref_idx[1];
+ ref_buf = &cm->frame_refs[1];
} else if (ref_frame_flag == VP9_ALT_FLAG) {
- ref_fb_ptr = &pbi->common.active_ref_idx[2];
+ ref_buf = &cm->frame_refs[2];
} else {
vpx_internal_error(&pbi->common.error, VPX_CODEC_ERROR,
"Invalid reference frame");
return pbi->common.error.error_code;
}
- if (!equal_dimensions(&cm->yv12_fb[*ref_fb_ptr], sd)) {
+ if (!equal_dimensions(ref_buf->buf, sd)) {
vpx_internal_error(&pbi->common.error, VPX_CODEC_ERROR,
"Incorrect buffer dimensions");
} else {
+ int *ref_fb_ptr = &ref_buf->idx;
+
// Find an empty frame buffer.
const int free_fb = get_free_fb(cm);
// Decrease fb_idx_ref_cnt since it will be increased again in
@@ -250,7 +252,8 @@
// Manage the reference counters and copy image.
ref_cnt_fb(cm->fb_idx_ref_cnt, ref_fb_ptr, free_fb);
- vp8_yv12_copy_frame(sd, &cm->yv12_fb[*ref_fb_ptr]);
+ ref_buf->buf = &cm->yv12_fb[*ref_fb_ptr];
+ vp8_yv12_copy_frame(sd, ref_buf->buf);
}
return pbi->common.error.error_code;
@@ -285,7 +288,7 @@
// Invalidate these references until the next frame starts.
for (ref_index = 0; ref_index < 3; ref_index++)
- cm->active_ref_idx[ref_index] = INT_MAX;
+ cm->frame_refs[ref_index].idx = INT_MAX;
}
int vp9_receive_compressed_data(VP9D_PTR ptr,
@@ -317,8 +320,8 @@
* at this point, but if it becomes so, [0] may not always be the correct
* thing to do here.
*/
- if (cm->active_ref_idx[0] != INT_MAX)
- get_frame_ref_buffer(cm, 0)->corrupted = 1;
+ if (cm->frame_refs[0].idx != INT_MAX)
+ cm->frame_refs[0].buf->corrupted = 1;
}
cm->new_fb_idx = get_free_fb(cm);
@@ -334,8 +337,8 @@
* at this point, but if it becomes so, [0] may not always be the correct
* thing to do here.
*/
- if (cm->active_ref_idx[0] != INT_MAX)
- get_frame_ref_buffer(cm, 0)->corrupted = 1;
+ if (cm->frame_refs[0].idx != INT_MAX)
+ cm->frame_refs[0].buf->corrupted = 1;
if (cm->fb_idx_ref_cnt[cm->new_fb_idx] > 0)
cm->fb_idx_ref_cnt[cm->new_fb_idx]--;
diff --git a/vp9/encoder/vp9_bitstream.c b/vp9/encoder/vp9_bitstream.c
index b4d4ef5..bab6a97 100644
--- a/vp9/encoder/vp9_bitstream.c
+++ b/vp9/encoder/vp9_bitstream.c
@@ -1090,12 +1090,11 @@
static void write_frame_size_with_refs(VP9_COMP *cpi,
struct vp9_write_bit_buffer *wb) {
VP9_COMMON *const cm = &cpi->common;
- int refs[REFS_PER_FRAME] = {cpi->lst_fb_idx, cpi->gld_fb_idx,
- cpi->alt_fb_idx};
- int i, found = 0;
+ int found = 0;
- for (i = 0; i < REFS_PER_FRAME; ++i) {
- YV12_BUFFER_CONFIG *cfg = &cm->yv12_fb[cm->ref_frame_map[refs[i]]];
+ MV_REFERENCE_FRAME ref_frame;
+ for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
+ YV12_BUFFER_CONFIG *cfg = get_ref_frame_buffer(cpi, ref_frame);
found = cm->width == cfg->y_crop_width &&
cm->height == cfg->y_crop_height;
@@ -1159,8 +1158,6 @@
write_frame_size(cpi, wb);
} else {
- const int refs[REFS_PER_FRAME] = {cpi->lst_fb_idx, cpi->gld_fb_idx,
- cpi->alt_fb_idx};
if (!cm->show_frame)
vp9_wb_write_bit(wb, cm->intra_only);
@@ -1173,11 +1170,12 @@
vp9_wb_write_literal(wb, get_refresh_mask(cpi), REF_FRAMES);
write_frame_size(cpi, wb);
} else {
- int i;
+ MV_REFERENCE_FRAME ref_frame;
vp9_wb_write_literal(wb, get_refresh_mask(cpi), REF_FRAMES);
- for (i = 0; i < REFS_PER_FRAME; ++i) {
- vp9_wb_write_literal(wb, refs[i], REF_FRAMES_LOG2);
- vp9_wb_write_bit(wb, cm->ref_frame_sign_bias[LAST_FRAME + i]);
+ for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ++ref_frame) {
+ vp9_wb_write_literal(wb, get_ref_frame_idx(cpi, ref_frame),
+ REF_FRAMES_LOG2);
+ vp9_wb_write_bit(wb, cm->ref_frame_sign_bias[ref_frame]);
}
write_frame_size_with_refs(cpi, wb);
diff --git a/vp9/encoder/vp9_block.h b/vp9/encoder/vp9_block.h
index 374f429..c011948 100644
--- a/vp9/encoder/vp9_block.h
+++ b/vp9/encoder/vp9_block.h
@@ -62,9 +62,6 @@
// Bit flag for each mode whether it has high error in comparison to others.
unsigned int modes_with_high_error;
-
- // Bit flag for each ref frame whether it has high error compared to others.
- unsigned int frames_with_high_error;
} PICK_MODE_CONTEXT;
struct macroblock_plane {
diff --git a/vp9/encoder/vp9_encodeframe.c b/vp9/encoder/vp9_encodeframe.c
index 800dc49..a4d5fbe 100644
--- a/vp9/encoder/vp9_encodeframe.c
+++ b/vp9/encoder/vp9_encodeframe.c
@@ -107,11 +107,9 @@
static unsigned int get_sby_perpixel_variance(VP9_COMP *cpi, MACROBLOCK *x,
BLOCK_SIZE bs) {
unsigned int var, sse;
- var = cpi->fn_ptr[bs].vf(x->plane[0].src.buf,
- x->plane[0].src.stride,
+ var = cpi->fn_ptr[bs].vf(x->plane[0].src.buf, x->plane[0].src.stride,
VP9_VAR_OFFS, 0, &sse);
- return (var + (1 << (num_pels_log2_lookup[bs] - 1))) >>
- num_pels_log2_lookup[bs];
+ return ROUND_POWER_OF_TWO(var, num_pels_log2_lookup[bs]);
}
// Original activity measure from Tim T's code.
@@ -1996,8 +1994,7 @@
vp9_setup_src_planes(x, cpi->Source, 0, 0);
// TODO(jkoleszar): are these initializations required?
- setup_pre_planes(xd, 0, &cm->yv12_fb[cm->ref_frame_map[cpi->lst_fb_idx]],
- 0, 0, NULL);
+ setup_pre_planes(xd, 0, get_ref_frame_buffer(cpi, LAST_FRAME), 0, 0, NULL);
setup_dst_planes(xd, get_frame_new_buffer(cm), 0, 0);
setup_block_dptrs(&x->e_mbd, cm->subsampling_x, cm->subsampling_y);
@@ -2586,11 +2583,10 @@
int ref;
const int is_compound = has_second_ref(mbmi);
for (ref = 0; ref < 1 + is_compound; ++ref) {
- YV12_BUFFER_CONFIG *cfg = &cm->yv12_fb[cm->ref_frame_map[
- get_ref_frame_idx(cpi, mbmi->ref_frame[ref])]];
- setup_pre_planes(xd, ref, cfg, mi_row, mi_col, xd->scale_factors[ref]);
+ YV12_BUFFER_CONFIG *cfg = get_ref_frame_buffer(cpi,
+ mbmi->ref_frame[ref]);
+ setup_pre_planes(xd, ref, cfg, mi_row, mi_col, &xd->block_refs[ref]->sf);
}
-
vp9_build_inter_predictors_sb(xd, mi_row, mi_col, MAX(bsize, BLOCK_8X8));
}
diff --git a/vp9/encoder/vp9_encodemb.h b/vp9/encoder/vp9_encodemb.h
index 7be6621..cb872a7 100644
--- a/vp9/encoder/vp9_encodemb.h
+++ b/vp9/encoder/vp9_encodemb.h
@@ -16,17 +16,6 @@
#include "vp9/encoder/vp9_onyx_int.h"
#include "vp9/common/vp9_onyxc_int.h"
-typedef struct {
- MB_PREDICTION_MODE mode;
- MV_REFERENCE_FRAME ref_frame;
- MV_REFERENCE_FRAME second_ref_frame;
-} MODE_DEFINITION;
-
-typedef struct {
- MV_REFERENCE_FRAME ref_frame;
- MV_REFERENCE_FRAME second_ref_frame;
-} REF_DEFINITION;
-
struct optimize_ctx {
ENTROPY_CONTEXT ta[MAX_MB_PLANE][16];
ENTROPY_CONTEXT tl[MAX_MB_PLANE][16];
diff --git a/vp9/encoder/vp9_firstpass.c b/vp9/encoder/vp9_firstpass.c
index bcee413..3e0b617 100644
--- a/vp9/encoder/vp9_firstpass.c
+++ b/vp9/encoder/vp9_firstpass.c
@@ -492,10 +492,8 @@
int i;
int recon_yoffset, recon_uvoffset;
- const int lst_yv12_idx = cm->ref_frame_map[cpi->lst_fb_idx];
- const int gld_yv12_idx = cm->ref_frame_map[cpi->gld_fb_idx];
- YV12_BUFFER_CONFIG *const lst_yv12 = &cm->yv12_fb[lst_yv12_idx];
- YV12_BUFFER_CONFIG *const gld_yv12 = &cm->yv12_fb[gld_yv12_idx];
+ YV12_BUFFER_CONFIG *const lst_yv12 = get_ref_frame_buffer(cpi, LAST_FRAME);
+ YV12_BUFFER_CONFIG *const gld_yv12 = get_ref_frame_buffer(cpi, GOLDEN_FRAME);
YV12_BUFFER_CONFIG *const new_yv12 = get_frame_new_buffer(cm);
const int recon_y_stride = lst_yv12->y_stride;
const int recon_uv_stride = lst_yv12->uv_stride;
@@ -961,31 +959,6 @@
return fclamp(pow(error_term, power_term), 0.05, 5.0);
}
-// Given a current maxQ value sets a range for future values.
-// PGW TODO..
-// This code removes direct dependency on QIndex to determine the range
-// (now uses the actual quantizer) but has not been tuned.
-static void adjust_maxq_qrange(VP9_COMP *cpi) {
- int i;
- // Set the max corresponding to cpi->rc.avg_q * 2.0
- double q = cpi->rc.avg_q * 2.0;
- cpi->twopass.maxq_max_limit = cpi->rc.worst_quality;
- for (i = cpi->rc.best_quality; i <= cpi->rc.worst_quality; i++) {
- cpi->twopass.maxq_max_limit = i;
- if (vp9_convert_qindex_to_q(i) >= q)
- break;
- }
-
- // Set the min corresponding to cpi->rc.avg_q * 0.5
- q = cpi->rc.avg_q * 0.5;
- cpi->twopass.maxq_min_limit = cpi->rc.best_quality;
- for (i = cpi->rc.worst_quality; i >= cpi->rc.best_quality; i--) {
- cpi->twopass.maxq_min_limit = i;
- if (vp9_convert_qindex_to_q(i) <= q)
- break;
- }
-}
-
static int estimate_max_q(VP9_COMP *cpi,
FIRSTPASS_STATS *fpstats,
int section_target_bandwitdh) {
@@ -998,16 +971,15 @@
double err_correction_factor;
if (section_target_bandwitdh <= 0)
- return cpi->twopass.maxq_max_limit; // Highest value allowed
+ return cpi->rc.worst_quality; // Highest value allowed
target_norm_bits_per_mb = section_target_bandwitdh < (1 << 20)
? (512 * section_target_bandwitdh) / num_mbs
: 512 * (section_target_bandwitdh / num_mbs);
-
// Try and pick a max Q that will be high enough to encode the
// content at the given rate.
- for (q = cpi->twopass.maxq_min_limit; q < cpi->twopass.maxq_max_limit; q++) {
+ for (q = cpi->rc.best_quality; q < cpi->rc.worst_quality; q++) {
int bits_per_mb_at_this_q;
err_correction_factor = calc_correction_factor(err_per_mb,
@@ -2015,6 +1987,11 @@
cpi->rc.per_frame_bandwidth = target_frame_size;
}
+static int test_for_kf_one_pass(VP9_COMP *cpi) {
+ // Placeholder function for auto key frame
+ return 0;
+}
+
void vp9_get_svc_params(VP9_COMP *cpi) {
VP9_COMMON *const cm = &cpi->common;
if ((cm->current_video_frame == 0) ||
@@ -2034,9 +2011,10 @@
if (!cpi->refresh_alt_ref_frame &&
(cm->current_video_frame == 0 ||
cm->frame_flags & FRAMEFLAGS_KEY ||
- (cpi->oxcf.auto_key && (cpi->rc.frames_since_key %
- cpi->key_frame_frequency == 0)))) {
+ cpi->rc.frames_to_key == 0 ||
+ (cpi->oxcf.auto_key && test_for_kf_one_pass(cpi)))) {
cm->frame_type = KEY_FRAME;
+ cpi->rc.frames_to_key = cpi->key_frame_frequency;
} else {
cm->frame_type = INTER_FRAME;
}
@@ -2055,6 +2033,8 @@
} else {
cm->frame_type = INTER_FRAME;
}
+ cpi->rc.frames_to_key = INT_MAX;
+ // Do not use periodic key frames
}
void vp9_get_second_pass_params(VP9_COMP *cpi) {
@@ -2084,10 +2064,6 @@
int section_target_bandwidth =
(int)(cpi->twopass.bits_left / frames_left);
- // guess at maxq needed in 2nd pass
- cpi->twopass.maxq_max_limit = cpi->rc.worst_quality;
- cpi->twopass.maxq_min_limit = cpi->rc.best_quality;
-
tmp_q = estimate_max_q(cpi, &cpi->twopass.total_left_stats,
section_target_bandwidth);
@@ -2183,8 +2159,6 @@
if (cpi->target_bandwidth < 0)
cpi->target_bandwidth = 0;
- cpi->rc.frames_to_key--;
-
// Update the total stats remaining structure
subtract_stats(&cpi->twopass.total_left_stats, &this_frame);
}
diff --git a/vp9/encoder/vp9_mbgraph.c b/vp9/encoder/vp9_mbgraph.c
index a9e0dfd..f3ddd39 100644
--- a/vp9/encoder/vp9_mbgraph.c
+++ b/vp9/encoder/vp9_mbgraph.c
@@ -392,8 +392,7 @@
void vp9_update_mbgraph_stats(VP9_COMP *cpi) {
VP9_COMMON *const cm = &cpi->common;
int i, n_frames = vp9_lookahead_depth(cpi->lookahead);
- YV12_BUFFER_CONFIG *golden_ref =
- &cm->yv12_fb[cm->ref_frame_map[cpi->gld_fb_idx]];
+ YV12_BUFFER_CONFIG *golden_ref = get_ref_frame_buffer(cpi, GOLDEN_FRAME);
// we need to look ahead beyond where the ARF transitions into
// being a GF - so exit if we don't look ahead beyond that
diff --git a/vp9/encoder/vp9_onyx_if.c b/vp9/encoder/vp9_onyx_if.c
index 9561047..2cdf45d 100644
--- a/vp9/encoder/vp9_onyx_if.c
+++ b/vp9/encoder/vp9_onyx_if.c
@@ -170,17 +170,6 @@
}
}
-static void reset_segment_features(VP9_COMMON *cm) {
- struct segmentation *const seg = &cm->seg;
-
- // Set up default state for MB feature flags
- seg->enabled = 0;
- seg->update_map = 0;
- seg->update_data = 0;
- vpx_memset(seg->tree_probs, 255, sizeof(seg->tree_probs));
- vp9_clearall_segfeatures(seg);
-}
-
static void dealloc_compressor_data(VP9_COMP *cpi) {
// Delete sementation map
vpx_free(cpi->segmentation_map);
@@ -592,6 +581,180 @@
sf->thresh_mult_sub8x8[THR_COMP_GA] = INT_MAX;
}
+static void set_rt_speed_feature(VP9_COMMON *cm,
+ SPEED_FEATURES *sf,
+ int speed) {
+ sf->static_segmentation = 0;
+ sf->adaptive_rd_thresh = 1;
+ sf->recode_loop = (speed < 1);
+ if (speed >= 1) {
+ sf->use_square_partition_only = !frame_is_intra_only(cm);
+ sf->less_rectangular_check = 1;
+ sf->tx_size_search_method =
+ frame_is_intra_only(cm) ? USE_FULL_RD : USE_LARGESTALL;
+
+ if (MIN(cm->width, cm->height) >= 720)
+ sf->disable_split_mask = cm->show_frame ?
+ DISABLE_ALL_SPLIT :
+ DISABLE_ALL_INTER_SPLIT;
+ else
+ sf->disable_split_mask = DISABLE_COMPOUND_SPLIT;
+
+ sf->use_rd_breakout = 1;
+ sf->adaptive_motion_search = 1;
+ sf->adaptive_pred_filter_type = 1;
+ sf->auto_mv_step_size = 1;
+ sf->adaptive_rd_thresh = 2;
+ sf->recode_loop = 2;
+ sf->intra_y_mode_mask[TX_32X32] = INTRA_DC_H_V;
+ sf->intra_uv_mode_mask[TX_32X32] = INTRA_DC_H_V;
+ sf->intra_uv_mode_mask[TX_16X16] = INTRA_DC_H_V;
+ }
+ if (speed >= 2) {
+ sf->use_square_partition_only = !frame_is_intra_only(cm);
+ sf->less_rectangular_check = 1;
+ sf->tx_size_search_method =
+ frame_is_intra_only(cm) ? USE_FULL_RD : USE_LARGESTALL;
+
+ if (MIN(cm->width, cm->height) >= 720)
+ sf->disable_split_mask = cm->show_frame ?
+ DISABLE_ALL_SPLIT :
+ DISABLE_ALL_INTER_SPLIT;
+ else
+ sf->disable_split_mask = LAST_AND_INTRA_SPLIT_ONLY;
+
+ sf->mode_search_skip_flags = FLAG_SKIP_INTRA_DIRMISMATCH
+ | FLAG_SKIP_INTRA_BESTINTER | FLAG_SKIP_COMP_BESTINTRA
+ | FLAG_SKIP_INTRA_LOWVAR;
+
+ sf->use_rd_breakout = 1;
+ sf->adaptive_motion_search = 1;
+ sf->adaptive_pred_filter_type = 2;
+ sf->auto_mv_step_size = 1;
+
+ sf->disable_filter_search_var_thresh = 50;
+ sf->comp_inter_joint_search_thresh = BLOCK_SIZES;
+
+ sf->auto_min_max_partition_size = 1;
+ sf->use_lastframe_partitioning = LAST_FRAME_PARTITION_LOW_MOTION;
+ sf->adjust_partitioning_from_last_frame = 1;
+ sf->last_partitioning_redo_frequency = 3;
+
+ sf->adaptive_rd_thresh = 2;
+ sf->recode_loop = 2;
+ sf->use_lp32x32fdct = 1;
+ sf->mode_skip_start = 11;
+ sf->intra_y_mode_mask[TX_32X32] = INTRA_DC_H_V;
+ sf->intra_y_mode_mask[TX_16X16] = INTRA_DC_H_V;
+ sf->intra_uv_mode_mask[TX_32X32] = INTRA_DC_H_V;
+ sf->intra_uv_mode_mask[TX_16X16] = INTRA_DC_H_V;
+ }
+ if (speed >= 3) {
+ sf->use_square_partition_only = 1;
+ sf->tx_size_search_method = USE_LARGESTALL;
+
+ if (MIN(cm->width, cm->height) >= 720)
+ sf->disable_split_mask = DISABLE_ALL_SPLIT;
+ else
+ sf->disable_split_mask = DISABLE_ALL_INTER_SPLIT;
+
+ sf->mode_search_skip_flags = FLAG_SKIP_INTRA_DIRMISMATCH
+ | FLAG_SKIP_INTRA_BESTINTER | FLAG_SKIP_COMP_BESTINTRA
+ | FLAG_SKIP_INTRA_LOWVAR;
+
+ sf->use_rd_breakout = 1;
+ sf->adaptive_motion_search = 1;
+ sf->adaptive_pred_filter_type = 2;
+ sf->auto_mv_step_size = 1;
+
+ sf->disable_filter_search_var_thresh = 100;
+ sf->comp_inter_joint_search_thresh = BLOCK_SIZES;
+
+ sf->auto_min_max_partition_size = 1;
+ sf->use_lastframe_partitioning = LAST_FRAME_PARTITION_ALL;
+ sf->adjust_partitioning_from_last_frame = 1;
+ sf->last_partitioning_redo_frequency = 3;
+
+ sf->use_uv_intra_rd_estimate = 1;
+ sf->skip_encode_sb = 1;
+ sf->use_lp32x32fdct = 1;
+ sf->subpel_iters_per_step = 1;
+ sf->use_fast_coef_updates = 2;
+
+ sf->adaptive_rd_thresh = 4;
+ sf->mode_skip_start = 6;
+ }
+ if (speed >= 4) {
+ sf->use_square_partition_only = 1;
+ sf->tx_size_search_method = USE_LARGESTALL;
+ sf->disable_split_mask = DISABLE_ALL_SPLIT;
+
+ sf->mode_search_skip_flags = FLAG_SKIP_INTRA_DIRMISMATCH
+ | FLAG_SKIP_INTRA_BESTINTER | FLAG_SKIP_COMP_BESTINTRA
+ | FLAG_SKIP_COMP_REFMISMATCH | FLAG_SKIP_INTRA_LOWVAR
+ | FLAG_EARLY_TERMINATE;
+
+ sf->use_rd_breakout = 1;
+ sf->adaptive_motion_search = 1;
+ sf->adaptive_pred_filter_type = 2;
+ sf->auto_mv_step_size = 1;
+
+ sf->disable_filter_search_var_thresh = 200;
+ sf->comp_inter_joint_search_thresh = BLOCK_SIZES;
+
+ sf->auto_min_max_partition_size = 1;
+ sf->use_lastframe_partitioning = LAST_FRAME_PARTITION_ALL;
+ sf->adjust_partitioning_from_last_frame = 1;
+ sf->last_partitioning_redo_frequency = 3;
+
+ sf->use_uv_intra_rd_estimate = 1;
+ sf->skip_encode_sb = 1;
+ sf->use_lp32x32fdct = 1;
+ sf->subpel_iters_per_step = 1;
+ sf->use_fast_coef_updates = 2;
+
+ sf->adaptive_rd_thresh = 4;
+ sf->mode_skip_start = 6;
+
+ /* sf->intra_y_mode_mask = INTRA_DC_ONLY;
+ sf->intra_uv_mode_mask = INTRA_DC_ONLY;
+ sf->search_method = BIGDIA;
+ sf->disable_split_var_thresh = 64;
+ sf->disable_filter_search_var_thresh = 64; */
+ }
+ if (speed >= 5) {
+ int i;
+ sf->comp_inter_joint_search_thresh = BLOCK_SIZES;
+ sf->use_one_partition_size_always = 1;
+ sf->always_this_block_size = BLOCK_16X16;
+ sf->tx_size_search_method =
+ frame_is_intra_only(cm) ? USE_FULL_RD : USE_LARGESTALL;
+ sf->mode_search_skip_flags = FLAG_SKIP_INTRA_DIRMISMATCH
+ | FLAG_SKIP_INTRA_BESTINTER | FLAG_SKIP_COMP_BESTINTRA
+ | FLAG_SKIP_COMP_REFMISMATCH | FLAG_SKIP_INTRA_LOWVAR
+ | FLAG_EARLY_TERMINATE;
+ sf->use_rd_breakout = 1;
+ sf->use_lp32x32fdct = 1;
+ sf->optimize_coefficients = 0;
+ sf->auto_mv_step_size = 1;
+ // sf->reduce_first_step_size = 1;
+ // sf->reference_masking = 1;
+
+ sf->disable_split_mask = DISABLE_ALL_SPLIT;
+ sf->search_method = HEX;
+ sf->subpel_iters_per_step = 1;
+ sf->disable_split_var_thresh = 64;
+ sf->disable_filter_search_var_thresh = 500;
+ for (i = 0; i < TX_SIZES; i++) {
+ sf->intra_y_mode_mask[i] = INTRA_DC_ONLY;
+ sf->intra_uv_mode_mask[i] = INTRA_DC_ONLY;
+ }
+ sf->use_fast_coef_updates = 2;
+ sf->adaptive_rd_thresh = 4;
+ sf->mode_skip_start = 6;
+ }
+}
+
void vp9_set_speed_features(VP9_COMP *cpi) {
SPEED_FEATURES *sf = &cpi->sf;
VP9_COMMON *cm = &cpi->common;
@@ -599,9 +762,9 @@
int speed = cpi->speed;
int i;
- // Only modes 0 and 1 supported for now in experimental code basae
- if (mode > 1)
- mode = 1;
+ // Convert negative speed to positive
+ if (speed < 0)
+ speed = -speed;
for (i = 0; i < MAX_MODES; ++i)
cpi->mode_chosen_counts[i] = 0;
@@ -624,7 +787,6 @@
sf->use_lp32x32fdct = 0;
sf->adaptive_motion_search = 0;
sf->adaptive_pred_filter_type = 0;
- sf->use_avoid_tested_higherror = 0;
sf->reference_masking = 0;
sf->use_one_partition_size_always = 0;
sf->less_rectangular_check = 0;
@@ -663,13 +825,13 @@
break;
case 1:
+
#if CONFIG_MULTIPLE_ARF
// Switch segmentation off.
sf->static_segmentation = 0;
#else
sf->static_segmentation = 0;
#endif
- sf->use_avoid_tested_higherror = 1;
sf->adaptive_rd_thresh = 1;
sf->recode_loop = (speed < 1);
@@ -844,6 +1006,9 @@
sf->mode_skip_start = 6;
}
break;
+ case 2:
+ set_rt_speed_feature(cm, sf, speed);
+ break;
}; /* switch */
// Set rd thresholds based on mode and speed setting
@@ -1192,7 +1357,7 @@
cm->refresh_frame_context = 1;
cm->reset_frame_context = 0;
- reset_segment_features(cm);
+ vp9_reset_segment_features(&cm->seg);
set_high_precision_mv(cpi, 0);
{
@@ -1202,9 +1367,6 @@
cpi->segment_encode_breakout[i] = cpi->oxcf.encode_breakout;
}
- // At the moment the first order values may not be > MAXQ
- cpi->oxcf.fixed_q = MIN(cpi->oxcf.fixed_q, MAXQ);
-
// local file playback mode == really big buffer
if (cpi->oxcf.end_usage == USAGE_LOCAL_FILE_PLAYBACK) {
cpi->oxcf.starting_buffer_level = 60000;
@@ -1266,13 +1428,6 @@
}
update_frame_size(cpi);
- if (cpi->oxcf.fixed_q >= 0) {
- cpi->rc.last_q[0] = cpi->oxcf.fixed_q;
- cpi->rc.last_q[1] = cpi->oxcf.fixed_q;
- cpi->rc.last_q[2] = cpi->oxcf.fixed_q;
- cpi->rc.last_boosted_qindex = cpi->oxcf.fixed_q;
- }
-
cpi->speed = cpi->oxcf.cpu_used;
if (cpi->oxcf.lag_in_frames == 0) {
@@ -1498,7 +1653,6 @@
init_pick_mode_context(cpi);
cm->current_video_frame = 0;
- cpi->rc.frames_till_gf_update_due = 0;
// Set reference frame sign bias for ALTREF frame to 1 (for now)
cm->ref_frame_sign_bias[ALTREF_FRAME] = 1;
@@ -2280,53 +2434,6 @@
vp8_yv12_extend_frame_borders(dst_fb);
}
-
-static void update_alt_ref_frame_stats(VP9_COMP *cpi) {
- // this frame refreshes means next frames don't unless specified by user
- cpi->rc.frames_since_golden = 0;
-
-#if CONFIG_MULTIPLE_ARF
- if (!cpi->multi_arf_enabled)
-#endif
- // Clear the alternate reference update pending flag.
- cpi->rc.source_alt_ref_pending = 0;
-
- // Set the alternate reference frame active flag
- cpi->rc.source_alt_ref_active = 1;
-}
-
-static void update_golden_frame_stats(VP9_COMP *cpi) {
- // Update the Golden frame usage counts.
- if (cpi->refresh_golden_frame) {
- // this frame refreshes means next frames don't unless specified by user
- cpi->refresh_golden_frame = 0;
- cpi->rc.frames_since_golden = 0;
-
- // ******** Fixed Q test code only ************
- // If we are going to use the ALT reference for the next group of frames
- // set a flag to say so.
- if (cpi->oxcf.fixed_q >= 0 &&
- cpi->oxcf.play_alternate && !cpi->refresh_alt_ref_frame) {
- cpi->rc.source_alt_ref_pending = 1;
- cpi->rc.frames_till_gf_update_due = cpi->rc.baseline_gf_interval;
- }
-
- if (!cpi->rc.source_alt_ref_pending)
- cpi->rc.source_alt_ref_active = 0;
-
- // Decrement count down till next gf
- if (cpi->rc.frames_till_gf_update_due > 0)
- cpi->rc.frames_till_gf_update_due--;
-
- } else if (!cpi->refresh_alt_ref_frame) {
- // Decrement count down till next gf
- if (cpi->rc.frames_till_gf_update_due > 0)
- cpi->rc.frames_till_gf_update_due--;
-
- cpi->rc.frames_since_golden++;
- }
-}
-
static int find_fp_qindex() {
int i;
@@ -2939,7 +3046,7 @@
if (frame_is_intra_only(cm)) {
vp9_setup_key_frame(cpi);
// Reset the loop filter deltas and segmentation map.
- reset_segment_features(cm);
+ vp9_reset_segment_features(&cm->seg);
// If segmentation is enabled force a map update for key frames.
if (seg->enabled) {
@@ -2979,8 +3086,9 @@
if (vp9_drop_frame(cpi)) {
// Update buffer level with zero size, update frame counters, and return.
vp9_update_buffer_level(cpi, 0);
+ cm->last_frame_type = cm->frame_type;
+ vp9_rc_postencode_update_drop_frame(cpi);
cm->current_video_frame++;
- cpi->rc.frames_since_key++;
return;
}
}
@@ -3049,7 +3157,7 @@
// Special case code to reduce pulsing when key frames are forced at a
// fixed interval. Note the reconstruction error if it is the frame before
// the force key frame
- if (cpi->rc.next_key_frame_forced && (cpi->rc.frames_to_key == 0)) {
+ if (cpi->rc.next_key_frame_forced && cpi->rc.frames_to_key == 1) {
cpi->ambient_err = vp9_calc_ss_err(cpi->Source, get_frame_new_buffer(cm));
}
@@ -3113,8 +3221,6 @@
* needed in motion search besides loopfilter */
cm->last_frame_type = cm->frame_type;
- vp9_rc_postencode_update(cpi, *size);
-
#if 0
output_frame_level_debug_stats(cpi);
#endif
@@ -3130,13 +3236,7 @@
get_ref_frame_flags(cpi);
- if (cpi->oxcf.play_alternate && cpi->refresh_alt_ref_frame
- && (cm->frame_type != KEY_FRAME))
- // Update the alternate reference frame stats as appropriate.
- update_alt_ref_frame_stats(cpi);
- else
- // Update the Golden frame stats as appropriate.
- update_golden_frame_stats(cpi);
+ vp9_rc_postencode_update(cpi, *size);
if (cm->frame_type == KEY_FRAME) {
// Tell the caller that the frame was coded as a key frame
@@ -3150,10 +3250,6 @@
cpi->new_frame_coding_order_period = -1;
}
#endif
-
- // As this frame is a key frame the next defaults to an inter frame.
- vp9_clear_system_state();
- cpi->rc.frames_since_key = 0;
} else {
*frame_flags = cm->frame_flags&~FRAMEFLAGS_KEY;
@@ -3203,7 +3299,6 @@
// Don't increment frame counters if this was an altref buffer
// update not a real frame
++cm->current_video_frame;
- ++cpi->rc.frames_since_key;
}
// restore prev_mi
cm->prev_mi = cm->prev_mip + cm->mode_info_stride + 1;
@@ -3303,6 +3398,7 @@
VP9_COMMON *cm = &cpi->common;
struct vpx_usec_timer cmptimer;
YV12_BUFFER_CONFIG *force_src_buffer = NULL;
+ const int refs[] = { cpi->lst_fb_idx, cpi->gld_fb_idx, cpi->alt_fb_idx };
int i;
// FILE *fp_out = fopen("enc_frame_type.txt", "a");
@@ -3504,16 +3600,13 @@
}
#endif
- /* Get the mapping of L/G/A to the reference buffer pool */
- cm->active_ref_idx[0] = cm->ref_frame_map[cpi->lst_fb_idx];
- cm->active_ref_idx[1] = cm->ref_frame_map[cpi->gld_fb_idx];
- cm->active_ref_idx[2] = cm->ref_frame_map[cpi->alt_fb_idx];
-
#if 0 // CONFIG_MULTIPLE_ARF
if (cpi->multi_arf_enabled) {
fprintf(fp_out, " idx(%d, %d, %d, %d) active(%d, %d, %d)",
cpi->lst_fb_idx, cpi->gld_fb_idx, cpi->alt_fb_idx, cm->new_fb_idx,
- cm->active_ref_idx[0], cm->active_ref_idx[1], cm->active_ref_idx[2]);
+ cm->ref_frame_map[cpi->lst_fb_idx],
+ cm->ref_frame_map[cpi->gld_fb_idx],
+ cm->ref_frame_map[cpi->alt_fb_idx]);
if (cpi->refresh_alt_ref_frame)
fprintf(fp_out, " type:ARF");
if (cpi->rc.is_src_frame_alt_ref)
@@ -3530,12 +3623,20 @@
cm->subsampling_x, cm->subsampling_y,
VP9BORDERINPIXELS, NULL, NULL, NULL);
- // Calculate scaling factors for each of the 3 available references
+
for (i = 0; i < REFS_PER_FRAME; ++i) {
- vp9_setup_scale_factors(cm, i);
- if (vp9_is_scaled(&cm->active_ref_scale[i]))
- vp9_extend_frame_borders(&cm->yv12_fb[cm->active_ref_idx[i]],
- cm->subsampling_x, cm->subsampling_y);
+ const int idx = cm->ref_frame_map[refs[i]];
+ YV12_BUFFER_CONFIG *const buf = &cm->yv12_fb[idx];
+
+ RefBuffer *const ref_buf = &cm->frame_refs[i];
+ ref_buf->buf = buf;
+ ref_buf->idx = idx;
+ vp9_setup_scale_factors_for_frame(&ref_buf->sf,
+ buf->y_crop_width, buf->y_crop_height,
+ cm->width, cm->height);
+
+ if (vp9_is_scaled(&ref_buf->sf))
+ vp9_extend_frame_borders(buf, cm->subsampling_x, cm->subsampling_y);
}
vp9_setup_interp_filters(&cpi->mb.e_mbd, DEFAULT_INTERP_FILTER, cm);
diff --git a/vp9/encoder/vp9_onyx_int.h b/vp9/encoder/vp9_onyx_int.h
index d32711c..abc2dda 100644
--- a/vp9/encoder/vp9_onyx_int.h
+++ b/vp9/encoder/vp9_onyx_int.h
@@ -252,7 +252,6 @@
LAST_FRAME_PARTITION_METHOD use_lastframe_partitioning;
TX_SIZE_SEARCH_METHOD tx_size_search_method;
int use_lp32x32fdct;
- int use_avoid_tested_higherror;
int use_one_partition_size_always;
int less_rectangular_check;
int use_square_partition_only;
@@ -531,8 +530,6 @@
double modified_error_left;
double kf_intra_err_min;
double gf_intra_err_min;
- int maxq_max_limit;
- int maxq_min_limit;
int static_scene_max_gf_interval;
int kf_bits;
// Remaining error from uncoded frames in a gf group. Two pass use only
@@ -666,6 +663,12 @@
}
}
+static YV12_BUFFER_CONFIG *get_ref_frame_buffer(VP9_COMP *cpi,
+ MV_REFERENCE_FRAME ref_frame) {
+ VP9_COMMON *const cm = &cpi->common;
+ return &cm->yv12_fb[cm->ref_frame_map[get_ref_frame_idx(cpi, ref_frame)]];
+}
+
void vp9_encode_frame(VP9_COMP *cpi);
void vp9_pack_bitstream(VP9_COMP *cpi, uint8_t *dest, size_t *size);
diff --git a/vp9/encoder/vp9_ratectrl.c b/vp9/encoder/vp9_ratectrl.c
index bae87b7..31b0116 100644
--- a/vp9/encoder/vp9_ratectrl.c
+++ b/vp9/encoder/vp9_ratectrl.c
@@ -257,16 +257,6 @@
cpi->rc.this_frame_target = target;
}
-// Do the best we can to define the parameters for the next GF based
-// on what information we have available.
-//
-// In this experimental code only two pass is supported
-// so we just use the interval determined in the two pass code.
-static void calc_gf_params(VP9_COMP *cpi) {
- // Set the gf interval
- cpi->rc.frames_till_gf_update_due = cpi->rc.baseline_gf_interval;
-}
-
// Update the buffer level: leaky bucket model.
void vp9_update_buffer_level(VP9_COMP *const cpi, int encoded_frame_size) {
VP9_COMMON *const cm = &cpi->common;
@@ -374,8 +364,6 @@
/ one_percent_bits);
if (percent_low > cpi->oxcf.under_shoot_pct) {
percent_low = cpi->oxcf.under_shoot_pct;
- } else if (percent_low < 0) {
- percent_low = 0;
}
// Lower the target bandwidth for this frame.
this_frame_target -= (this_frame_target * percent_low) / 200;
@@ -384,8 +372,6 @@
/ one_percent_bits);
if (percent_high > cpi->oxcf.over_shoot_pct) {
percent_high = cpi->oxcf.over_shoot_pct;
- } else if (percent_high < 0) {
- percent_high = 0;
}
// Increase the target bandwidth for this frame.
this_frame_target += (this_frame_target * percent_high) / 200;
@@ -851,6 +837,43 @@
return 1;
}
+static void update_alt_ref_frame_stats(VP9_COMP *cpi) {
+ // this frame refreshes means next frames don't unless specified by user
+ cpi->rc.frames_since_golden = 0;
+
+#if CONFIG_MULTIPLE_ARF
+ if (!cpi->multi_arf_enabled)
+#endif
+ // Clear the alternate reference update pending flag.
+ cpi->rc.source_alt_ref_pending = 0;
+
+ // Set the alternate reference frame active flag
+ cpi->rc.source_alt_ref_active = 1;
+}
+
+static void update_golden_frame_stats(VP9_COMP *cpi) {
+ // Update the Golden frame usage counts.
+ if (cpi->refresh_golden_frame) {
+ // this frame refreshes means next frames don't unless specified by user
+ cpi->refresh_golden_frame = 0;
+ cpi->rc.frames_since_golden = 0;
+
+ if (!cpi->rc.source_alt_ref_pending)
+ cpi->rc.source_alt_ref_active = 0;
+
+ // Decrement count down till next gf
+ if (cpi->rc.frames_till_gf_update_due > 0)
+ cpi->rc.frames_till_gf_update_due--;
+
+ } else if (!cpi->refresh_alt_ref_frame) {
+ // Decrement count down till next gf
+ if (cpi->rc.frames_till_gf_update_due > 0)
+ cpi->rc.frames_till_gf_update_due--;
+
+ cpi->rc.frames_since_golden++;
+ }
+}
+
void vp9_rc_postencode_update(VP9_COMP *cpi, uint64_t bytes_used) {
VP9_COMMON *const cm = &cpi->common;
// Update rate control heuristics
@@ -938,4 +961,24 @@
cpi->twopass.gf_group_bits = MAX(cpi->twopass.gf_group_bits, 0);
}
#endif
+
+ if (cpi->oxcf.play_alternate && cpi->refresh_alt_ref_frame
+ && (cm->frame_type != KEY_FRAME))
+ // Update the alternate reference frame stats as appropriate.
+ update_alt_ref_frame_stats(cpi);
+ else
+ // Update the Golden frame stats as appropriate.
+ update_golden_frame_stats(cpi);
+
+ if (cm->frame_type == KEY_FRAME)
+ cpi->rc.frames_since_key = 0;
+ if (cm->show_frame) {
+ cpi->rc.frames_since_key++;
+ cpi->rc.frames_to_key--;
+ }
+}
+
+void vp9_rc_postencode_update_drop_frame(VP9_COMP *cpi) {
+ cpi->rc.frames_since_key++;
+ // cpi->rc.frames_to_key--;
}
diff --git a/vp9/encoder/vp9_ratectrl.h b/vp9/encoder/vp9_ratectrl.h
index 8293557..086755a 100644
--- a/vp9/encoder/vp9_ratectrl.h
+++ b/vp9/encoder/vp9_ratectrl.h
@@ -52,6 +52,8 @@
// on bytes used
void vp9_rc_postencode_update(VP9_COMP *cpi,
uint64_t bytes_used);
+// for dropped frames
+void vp9_rc_postencode_update_drop_frame(VP9_COMP *cpi);
// estimates bits per mb for a given qindex and correction factor
int vp9_rc_bits_per_mb(FRAME_TYPE frame_type, int qindex,
diff --git a/vp9/encoder/vp9_rdopt.c b/vp9/encoder/vp9_rdopt.c
index 46fe163..97dc1e0 100644
--- a/vp9/encoder/vp9_rdopt.c
+++ b/vp9/encoder/vp9_rdopt.c
@@ -48,53 +48,62 @@
#define MIN_EARLY_TERM_INDEX 3
+typedef struct {
+ MB_PREDICTION_MODE mode;
+ MV_REFERENCE_FRAME ref_frame[2];
+} MODE_DEFINITION;
+
+typedef struct {
+ MV_REFERENCE_FRAME ref_frame[2];
+} REF_DEFINITION;
+
const MODE_DEFINITION vp9_mode_order[MAX_MODES] = {
- {NEARESTMV, LAST_FRAME, NONE},
- {NEARESTMV, ALTREF_FRAME, NONE},
- {NEARESTMV, GOLDEN_FRAME, NONE},
+ {NEARESTMV, {LAST_FRAME, NONE}},
+ {NEARESTMV, {ALTREF_FRAME, NONE}},
+ {NEARESTMV, {GOLDEN_FRAME, NONE}},
- {DC_PRED, INTRA_FRAME, NONE},
+ {DC_PRED, {INTRA_FRAME, NONE}},
- {NEWMV, LAST_FRAME, NONE},
- {NEWMV, ALTREF_FRAME, NONE},
- {NEWMV, GOLDEN_FRAME, NONE},
+ {NEWMV, {LAST_FRAME, NONE}},
+ {NEWMV, {ALTREF_FRAME, NONE}},
+ {NEWMV, {GOLDEN_FRAME, NONE}},
- {NEARMV, LAST_FRAME, NONE},
- {NEARMV, ALTREF_FRAME, NONE},
- {NEARESTMV, LAST_FRAME, ALTREF_FRAME},
- {NEARESTMV, GOLDEN_FRAME, ALTREF_FRAME},
+ {NEARMV, {LAST_FRAME, NONE}},
+ {NEARMV, {ALTREF_FRAME, NONE}},
+ {NEARESTMV, {LAST_FRAME, ALTREF_FRAME}},
+ {NEARESTMV, {GOLDEN_FRAME, ALTREF_FRAME}},
- {TM_PRED, INTRA_FRAME, NONE},
+ {TM_PRED, {INTRA_FRAME, NONE}},
- {NEARMV, LAST_FRAME, ALTREF_FRAME},
- {NEWMV, LAST_FRAME, ALTREF_FRAME},
- {NEARMV, GOLDEN_FRAME, NONE},
- {NEARMV, GOLDEN_FRAME, ALTREF_FRAME},
- {NEWMV, GOLDEN_FRAME, ALTREF_FRAME},
+ {NEARMV, {LAST_FRAME, ALTREF_FRAME}},
+ {NEWMV, {LAST_FRAME, ALTREF_FRAME}},
+ {NEARMV, {GOLDEN_FRAME, NONE}},
+ {NEARMV, {GOLDEN_FRAME, ALTREF_FRAME}},
+ {NEWMV, {GOLDEN_FRAME, ALTREF_FRAME}},
- {ZEROMV, LAST_FRAME, NONE},
- {ZEROMV, GOLDEN_FRAME, NONE},
- {ZEROMV, ALTREF_FRAME, NONE},
- {ZEROMV, LAST_FRAME, ALTREF_FRAME},
- {ZEROMV, GOLDEN_FRAME, ALTREF_FRAME},
+ {ZEROMV, {LAST_FRAME, NONE}},
+ {ZEROMV, {GOLDEN_FRAME, NONE}},
+ {ZEROMV, {ALTREF_FRAME, NONE}},
+ {ZEROMV, {LAST_FRAME, ALTREF_FRAME}},
+ {ZEROMV, {GOLDEN_FRAME, ALTREF_FRAME}},
- {H_PRED, INTRA_FRAME, NONE},
- {V_PRED, INTRA_FRAME, NONE},
- {D135_PRED, INTRA_FRAME, NONE},
- {D207_PRED, INTRA_FRAME, NONE},
- {D153_PRED, INTRA_FRAME, NONE},
- {D63_PRED, INTRA_FRAME, NONE},
- {D117_PRED, INTRA_FRAME, NONE},
- {D45_PRED, INTRA_FRAME, NONE},
+ {H_PRED, {INTRA_FRAME, NONE}},
+ {V_PRED, {INTRA_FRAME, NONE}},
+ {D135_PRED, {INTRA_FRAME, NONE}},
+ {D207_PRED, {INTRA_FRAME, NONE}},
+ {D153_PRED, {INTRA_FRAME, NONE}},
+ {D63_PRED, {INTRA_FRAME, NONE}},
+ {D117_PRED, {INTRA_FRAME, NONE}},
+ {D45_PRED, {INTRA_FRAME, NONE}},
};
const REF_DEFINITION vp9_ref_order[MAX_REFS] = {
- {LAST_FRAME, NONE},
- {GOLDEN_FRAME, NONE},
- {ALTREF_FRAME, NONE},
- {LAST_FRAME, ALTREF_FRAME},
- {GOLDEN_FRAME, ALTREF_FRAME},
- {INTRA_FRAME, NONE},
+ {{LAST_FRAME, NONE}},
+ {{GOLDEN_FRAME, NONE}},
+ {{ALTREF_FRAME, NONE}},
+ {{LAST_FRAME, ALTREF_FRAME}},
+ {{GOLDEN_FRAME, ALTREF_FRAME}},
+ {{INTRA_FRAME, NONE}},
};
// The baseline rd thresholds for breaking out of the rd loop for
@@ -308,26 +317,14 @@
}
}
-static INLINE void linear_interpolate2(double x, int ntab, int inv_step,
- const double *tab1, const double *tab2,
- double *v1, double *v2) {
- double y = x * inv_step;
- int d = (int) y;
- if (d >= ntab - 1) {
- *v1 = tab1[ntab - 1];
- *v2 = tab2[ntab - 1];
- } else {
- double a = y - d;
- *v1 = tab1[d] * (1 - a) + tab1[d + 1] * a;
- *v2 = tab2[d] * (1 - a) + tab2[d + 1] * a;
- }
-}
+static const int MAX_XSQ_Q10 = 245727;
-static void model_rd_norm(double x, double *R, double *D) {
- static const int inv_tab_step = 8;
- static const int tab_size = 120;
+static void model_rd_norm(int xsq_q10, int *r_q10, int *d_q10) {
// NOTE: The tables below must be of the same size
- //
+
+ // The functions described below are sampled at the four most significant
+ // bits of x^2 + 8 / 256
+
// Normalized rate
// This table models the rate for a Laplacian source
// source with given variance when quantized with a uniform quantizer
@@ -335,22 +332,20 @@
// Rn(x) = H(sqrt(r)) + sqrt(r)*[1 + H(r)/(1 - r)],
// where r = exp(-sqrt(2) * x) and x = qpstep / sqrt(variance),
// and H(x) is the binary entropy function.
- static const double rate_tab[] = {
- 64.00, 4.944, 3.949, 3.372, 2.966, 2.655, 2.403, 2.194,
- 2.014, 1.858, 1.720, 1.596, 1.485, 1.384, 1.291, 1.206,
- 1.127, 1.054, 0.986, 0.923, 0.863, 0.808, 0.756, 0.708,
- 0.662, 0.619, 0.579, 0.541, 0.506, 0.473, 0.442, 0.412,
- 0.385, 0.359, 0.335, 0.313, 0.291, 0.272, 0.253, 0.236,
- 0.220, 0.204, 0.190, 0.177, 0.165, 0.153, 0.142, 0.132,
- 0.123, 0.114, 0.106, 0.099, 0.091, 0.085, 0.079, 0.073,
- 0.068, 0.063, 0.058, 0.054, 0.050, 0.047, 0.043, 0.040,
- 0.037, 0.034, 0.032, 0.029, 0.027, 0.025, 0.023, 0.022,
- 0.020, 0.019, 0.017, 0.016, 0.015, 0.014, 0.013, 0.012,
- 0.011, 0.010, 0.009, 0.008, 0.008, 0.007, 0.007, 0.006,
- 0.006, 0.005, 0.005, 0.005, 0.004, 0.004, 0.004, 0.003,
- 0.003, 0.003, 0.003, 0.002, 0.002, 0.002, 0.002, 0.002,
- 0.002, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001,
- 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.001, 0.000,
+ static const int rate_tab_q10[] = {
+ 65536, 6086, 5574, 5275, 5063, 4899, 4764, 4651,
+ 4553, 4389, 4255, 4142, 4044, 3958, 3881, 3811,
+ 3748, 3635, 3538, 3453, 3376, 3307, 3244, 3186,
+ 3133, 3037, 2952, 2877, 2809, 2747, 2690, 2638,
+ 2589, 2501, 2423, 2353, 2290, 2232, 2179, 2130,
+ 2084, 2001, 1928, 1862, 1802, 1748, 1698, 1651,
+ 1608, 1530, 1460, 1398, 1342, 1290, 1243, 1199,
+ 1159, 1086, 1021, 963, 911, 864, 821, 781,
+ 745, 680, 623, 574, 530, 490, 455, 424,
+ 395, 345, 304, 269, 239, 213, 190, 171,
+ 154, 126, 104, 87, 73, 61, 52, 44,
+ 38, 28, 21, 16, 12, 10, 8, 6,
+ 5, 3, 2, 1, 1, 1, 0, 0,
};
// Normalized distortion
// This table models the normalized distortion for a Laplacian source
@@ -359,54 +354,73 @@
// Dn(x) = 1 - 1/sqrt(2) * x / sinh(x/sqrt(2))
// where x = qpstep / sqrt(variance)
// Note the actual distortion is Dn * variance.
- static const double dist_tab[] = {
- 0.000, 0.001, 0.005, 0.012, 0.021, 0.032, 0.045, 0.061,
- 0.079, 0.098, 0.119, 0.142, 0.166, 0.190, 0.216, 0.242,
- 0.269, 0.296, 0.324, 0.351, 0.378, 0.405, 0.432, 0.458,
- 0.484, 0.509, 0.534, 0.557, 0.580, 0.603, 0.624, 0.645,
- 0.664, 0.683, 0.702, 0.719, 0.735, 0.751, 0.766, 0.780,
- 0.794, 0.807, 0.819, 0.830, 0.841, 0.851, 0.861, 0.870,
- 0.878, 0.886, 0.894, 0.901, 0.907, 0.913, 0.919, 0.925,
- 0.930, 0.935, 0.939, 0.943, 0.947, 0.951, 0.954, 0.957,
- 0.960, 0.963, 0.966, 0.968, 0.971, 0.973, 0.975, 0.976,
- 0.978, 0.980, 0.981, 0.982, 0.984, 0.985, 0.986, 0.987,
- 0.988, 0.989, 0.990, 0.990, 0.991, 0.992, 0.992, 0.993,
- 0.993, 0.994, 0.994, 0.995, 0.995, 0.996, 0.996, 0.996,
- 0.996, 0.997, 0.997, 0.997, 0.997, 0.998, 0.998, 0.998,
- 0.998, 0.998, 0.998, 0.999, 0.999, 0.999, 0.999, 0.999,
- 0.999, 0.999, 0.999, 0.999, 0.999, 0.999, 0.999, 1.000,
+ static const int dist_tab_q10[] = {
+ 0, 0, 1, 1, 1, 2, 2, 2,
+ 3, 3, 4, 5, 5, 6, 7, 7,
+ 8, 9, 11, 12, 13, 15, 16, 17,
+ 18, 21, 24, 26, 29, 31, 34, 36,
+ 39, 44, 49, 54, 59, 64, 69, 73,
+ 78, 88, 97, 106, 115, 124, 133, 142,
+ 151, 167, 184, 200, 215, 231, 245, 260,
+ 274, 301, 327, 351, 375, 397, 418, 439,
+ 458, 495, 528, 559, 587, 613, 637, 659,
+ 680, 717, 749, 777, 801, 823, 842, 859,
+ 874, 899, 919, 936, 949, 960, 969, 977,
+ 983, 994, 1001, 1006, 1010, 1013, 1015, 1017,
+ 1018, 1020, 1022, 1022, 1023, 1023, 1023, 1024,
+ };
+ static const int xsq_iq_q10[] = {
+ 0, 4, 8, 12, 16, 20, 24, 28,
+ 32, 40, 48, 56, 64, 72, 80, 88,
+ 96, 112, 128, 144, 160, 176, 192, 208,
+ 224, 256, 288, 320, 352, 384, 416, 448,
+ 480, 544, 608, 672, 736, 800, 864, 928,
+ 992, 1120, 1248, 1376, 1504, 1632, 1760, 1888,
+ 2016, 2272, 2528, 2784, 3040, 3296, 3552, 3808,
+ 4064, 4576, 5088, 5600, 6112, 6624, 7136, 7648,
+ 8160, 9184, 10208, 11232, 12256, 13280, 14304, 15328,
+ 16352, 18400, 20448, 22496, 24544, 26592, 28640, 30688,
+ 32736, 36832, 40928, 45024, 49120, 53216, 57312, 61408,
+ 65504, 73696, 81888, 90080, 98272, 106464, 114656, 122848,
+ 131040, 147424, 163808, 180192, 196576, 212960, 229344, 245728,
};
/*
- assert(sizeof(rate_tab) == tab_size * sizeof(rate_tab[0]);
- assert(sizeof(dist_tab) == tab_size * sizeof(dist_tab[0]);
- assert(sizeof(rate_tab) == sizeof(dist_tab));
+ static const int tab_size = sizeof(rate_tab_q10) / sizeof(rate_tab_q10[0]);
+ assert(sizeof(dist_tab_q10) / sizeof(dist_tab_q10[0]) == tab_size);
+ assert(sizeof(xsq_iq_q10) / sizeof(xsq_iq_q10[0]) == tab_size);
+ assert(MAX_XSQ_Q10 + 1 == xsq_iq_q10[tab_size - 1]);
*/
- assert(x >= 0.0);
- linear_interpolate2(x, tab_size, inv_tab_step,
- rate_tab, dist_tab, R, D);
+ int tmp = (xsq_q10 >> 2) + 8;
+ int k = get_msb(tmp) - 3;
+ int xq = (k << 3) + ((tmp >> k) & 0x7);
+ const int one_q10 = 1 << 10;
+ const int a_q10 = ((xsq_q10 - xsq_iq_q10[xq]) << 10) >> (2 + k);
+ const int b_q10 = one_q10 - a_q10;
+ *r_q10 = (rate_tab_q10[xq] * b_q10 + rate_tab_q10[xq + 1] * a_q10) >> 10;
+ *d_q10 = (dist_tab_q10[xq] * b_q10 + dist_tab_q10[xq + 1] * a_q10) >> 10;
}
-static void model_rd_from_var_lapndz(int var, int n, int qstep,
- int *rate, int64_t *dist) {
+static void model_rd_from_var_lapndz(unsigned int var, unsigned int n,
+ unsigned int qstep, int *rate,
+ int64_t *dist) {
// This function models the rate and distortion for a Laplacian
// source with given variance when quantized with a uniform quantizer
// with given stepsize. The closed form expressions are in:
// Hang and Chen, "Source Model for transform video coder and its
// application - Part I: Fundamental Theory", IEEE Trans. Circ.
// Sys. for Video Tech., April 1997.
- vp9_clear_system_state();
- if (var == 0 || n == 0) {
+ if (var == 0) {
*rate = 0;
*dist = 0;
} else {
- double D, R;
- double s2 = (double) var / n;
- double x = qstep / sqrt(s2);
- model_rd_norm(x, &R, &D);
- *rate = (int)((n << 8) * R + 0.5);
- *dist = (int)(var * D + 0.5);
+ int d_q10, r_q10;
+ uint64_t xsq_q10_64 =
+ ((((uint64_t)qstep * qstep * n) << 10) + (var >> 1)) / var;
+ int xsq_q10 = xsq_q10_64 > MAX_XSQ_Q10 ? MAX_XSQ_Q10 : xsq_q10_64;
+ model_rd_norm(xsq_q10, &r_q10, &d_q10);
+ *rate = (n * r_q10 + 2) >> 2;
+ *dist = (var * (int64_t)d_q10 + 512) >> 10;
}
- vp9_clear_system_state();
}
static void model_rd_for_sb(VP9_COMP *cpi, BLOCK_SIZE bsize,
@@ -1524,7 +1538,7 @@
vp9_build_inter_predictor(pre, pd->pre[ref].stride,
dst, pd->dst.stride,
&mi->bmi[i].as_mv[ref].as_mv,
- xd->scale_factors[ref],
+ &xd->block_refs[ref]->sf,
width, height, ref, &xd->subpix, MV_PRECISION_Q3,
mi_col * MI_SIZE + 4 * (i % 2),
mi_row * MI_SIZE + 4 * (i / 2));
@@ -1632,6 +1646,7 @@
int i, br = 0, idx, idy;
int64_t bd = 0, block_sse = 0;
MB_PREDICTION_MODE this_mode;
+ VP9_COMMON *cm = &cpi->common;
MODE_INFO *mi = x->e_mbd.mi_8x8[0];
MB_MODE_INFO *const mbmi = &mi->mbmi;
struct macroblock_plane *const p = &x->plane[0];
@@ -1673,13 +1688,13 @@
i = idy * 2 + idx;
frame_mv[ZEROMV][mbmi->ref_frame[0]].as_int = 0;
- vp9_append_sub8x8_mvs_for_idx(&cpi->common, &x->e_mbd, tile,
+ vp9_append_sub8x8_mvs_for_idx(cm, &x->e_mbd, tile,
i, 0, mi_row, mi_col,
&frame_mv[NEARESTMV][mbmi->ref_frame[0]],
&frame_mv[NEARMV][mbmi->ref_frame[0]]);
if (has_second_rf) {
frame_mv[ZEROMV][mbmi->ref_frame[1]].as_int = 0;
- vp9_append_sub8x8_mvs_for_idx(&cpi->common, &x->e_mbd, tile,
+ vp9_append_sub8x8_mvs_for_idx(cm, &x->e_mbd, tile,
i, 1, mi_row, mi_col,
&frame_mv[NEARESTMV][mbmi->ref_frame[1]],
&frame_mv[NEARMV][mbmi->ref_frame[1]]);
@@ -1738,6 +1753,7 @@
// motion search for newmv (single predictor case only)
if (!has_second_rf && this_mode == NEWMV &&
seg_mvs[i][mbmi->ref_frame[0]].as_int == INVALID_MV) {
+ int_mv *const new_mv = &mode_mv[NEWMV];
int step_param = 0;
int further_steps;
int thissme, bestsme = INT_MAX;
@@ -1763,7 +1779,7 @@
else
max_mv = MAX(abs(bsi->mvp.as_mv.row), abs(bsi->mvp.as_mv.col)) >> 3;
- if (cpi->sf.auto_mv_step_size && cpi->common.show_frame) {
+ if (cpi->sf.auto_mv_step_size && cm->show_frame) {
// Take wtd average of the step_params based on the last frame's
// max mv magnitude and the best ref mvs of the current block for
// the given reference.
@@ -1776,7 +1792,7 @@
mvp_full.row = bsi->mvp.as_mv.row >> 3;
mvp_full.col = bsi->mvp.as_mv.col >> 3;
- if (cpi->sf.adaptive_motion_search && cpi->common.show_frame) {
+ if (cpi->sf.adaptive_motion_search && cm->show_frame) {
mvp_full.row = x->pred_mv[mbmi->ref_frame[0]].as_mv.row >> 3;
mvp_full.col = x->pred_mv[mbmi->ref_frame[0]].as_mv.col >> 3;
step_param = MAX(step_param, 8);
@@ -1793,24 +1809,24 @@
step_param,
sadpb, 1, v_fn_ptr, 1,
&bsi->ref_mv->as_mv,
- &mode_mv[NEWMV].as_mv);
+ &new_mv->as_mv);
} else if (cpi->sf.search_method == SQUARE) {
bestsme = vp9_square_search(x, &mvp_full,
step_param,
sadpb, 1, v_fn_ptr, 1,
&bsi->ref_mv->as_mv,
- &mode_mv[NEWMV].as_mv);
+ &new_mv->as_mv);
} else if (cpi->sf.search_method == BIGDIA) {
bestsme = vp9_bigdia_search(x, &mvp_full,
step_param,
sadpb, 1, v_fn_ptr, 1,
&bsi->ref_mv->as_mv,
- &mode_mv[NEWMV].as_mv);
+ &new_mv->as_mv);
} else {
bestsme = vp9_full_pixel_diamond(cpi, x, &mvp_full, step_param,
sadpb, further_steps, 0, v_fn_ptr,
&bsi->ref_mv->as_mv,
- &mode_mv[NEWMV]);
+ new_mv);
}
// Should we do a full search (best quality only)
@@ -1826,20 +1842,20 @@
if (thissme < bestsme) {
bestsme = thissme;
- mode_mv[NEWMV].as_int = mi->bmi[i].as_mv[0].as_int;
+ new_mv->as_int = mi->bmi[i].as_mv[0].as_int;
} else {
/* The full search result is actually worse so re-instate the
* previous best vector */
- mi->bmi[i].as_mv[0].as_int = mode_mv[NEWMV].as_int;
+ mi->bmi[i].as_mv[0].as_int = new_mv->as_int;
}
}
if (bestsme < INT_MAX) {
int distortion;
cpi->find_fractional_mv_step(x,
- &mode_mv[NEWMV].as_mv,
+ &new_mv->as_mv,
&bsi->ref_mv->as_mv,
- cpi->common.allow_high_precision_mv,
+ cm->allow_high_precision_mv,
x->errorperbit, v_fn_ptr,
0, cpi->sf.subpel_iters_per_step,
x->nmvjointcost, x->mvcost,
@@ -1847,11 +1863,11 @@
&x->pred_sse[mbmi->ref_frame[0]]);
// save motion search result for use in compound prediction
- seg_mvs[i][mbmi->ref_frame[0]].as_int = mode_mv[NEWMV].as_int;
+ seg_mvs[i][mbmi->ref_frame[0]].as_int = new_mv->as_int;
}
if (cpi->sf.adaptive_motion_search)
- x->pred_mv[mbmi->ref_frame[0]].as_int = mode_mv[NEWMV].as_int;
+ x->pred_mv[mbmi->ref_frame[0]].as_int = new_mv->as_int;
// restore src pointers
mi_buf_restore(x, orig_src, orig_pre);
@@ -2108,16 +2124,20 @@
cpi->common.show_frame &&
block_size < cpi->sf.max_partition_size);
+ int_mv pred_mv[3] = {
+ mbmi->ref_mvs[ref_frame][0], mbmi->ref_mvs[ref_frame][1],
+ x->pred_mv[ref_frame]
+ };
+
// Get the sad for each candidate reference mv
for (i = 0; i < num_mv_refs; i++) {
- this_mv.as_int = (i < MAX_MV_REF_CANDIDATES) ?
- mbmi->ref_mvs[ref_frame][i].as_int : x->pred_mv[ref_frame].as_int;
+ this_mv.as_int = pred_mv[i].as_int;
max_mv = MAX(max_mv,
MAX(abs(this_mv.as_mv.row), abs(this_mv.as_mv.col)) >> 3);
- // The list is at an end if we see 0 for a second time.
+ // only need to check zero mv once
if (!this_mv.as_int && zero_seen)
- break;
+ continue;
zero_seen = zero_seen || !this_mv.as_int;
row_offset = this_mv.as_mv.row >> 3;
@@ -2268,8 +2288,7 @@
YV12_BUFFER_CONFIG *yv12 = &cm->yv12_fb[cpi->common.ref_frame_map[idx]];
MACROBLOCKD *const xd = &x->e_mbd;
MB_MODE_INFO *const mbmi = &xd->mi_8x8[0]->mbmi;
- const struct scale_factors *const sf =
- &cpi->common.active_ref_scale[frame_type - 1];
+ const struct scale_factors *const sf = &cm->frame_refs[frame_type - 1].sf;
// TODO(jkoleszar): Is the UV buffer ever used here? If so, need to make this
@@ -2325,7 +2344,7 @@
int bestsme = INT_MAX;
int further_steps, step_param;
int sadpb = x->sadperbit16;
- int_mv mvp_full;
+ MV mvp_full;
int ref = mbmi->ref_frame[0];
int_mv ref_mv = mbmi->ref_mvs[ref][0];
@@ -2336,6 +2355,10 @@
YV12_BUFFER_CONFIG *scaled_ref_frame = get_scaled_ref_frame(cpi, ref);
+ int_mv pred_mv[3] = {
+ mbmi->ref_mvs[ref][0], mbmi->ref_mvs[ref][1], x->pred_mv[ref]
+ };
+
if (scaled_ref_frame) {
int i;
// Swap out the reference frame for a version that's been scaled to
@@ -2351,21 +2374,10 @@
// Adjust search parameters based on small partitions' result.
if (x->fast_ms) {
- // && abs(mvp_full.as_mv.row - x->pred_mv.as_mv.row) < 24 &&
- // abs(mvp_full.as_mv.col - x->pred_mv.as_mv.col) < 24) {
// adjust search range
step_param = 6;
if (x->fast_ms > 1)
step_param = 8;
-
- // Get prediction MV.
- mvp_full.as_int = x->pred_mv[ref].as_int;
-
- // Adjust MV sign if needed.
- if (cm->ref_frame_sign_bias[ref]) {
- mvp_full.as_mv.col *= -1;
- mvp_full.as_mv.row *= -1;
- }
} else {
// Work out the size of the first step in the mv step search.
// 0 here is maximum length first step. 1 is MAX >> 1 etc.
@@ -2411,36 +2423,28 @@
}
}
- mvp_full.as_int = x->mv_best_ref_index[ref] < MAX_MV_REF_CANDIDATES ?
- mbmi->ref_mvs[ref][x->mv_best_ref_index[ref]].as_int :
- x->pred_mv[ref].as_int;
+ mvp_full = pred_mv[x->mv_best_ref_index[ref]].as_mv;
- mvp_full.as_mv.col >>= 3;
- mvp_full.as_mv.row >>= 3;
+ mvp_full.col >>= 3;
+ mvp_full.row >>= 3;
// Further step/diamond searches as necessary
further_steps = (cpi->sf.max_step_search_steps - 1) - step_param;
if (cpi->sf.search_method == HEX) {
- bestsme = vp9_hex_search(x, &mvp_full.as_mv,
- step_param,
- sadpb, 1,
+ bestsme = vp9_hex_search(x, &mvp_full, step_param, sadpb, 1,
&cpi->fn_ptr[bsize], 1,
&ref_mv.as_mv, &tmp_mv->as_mv);
} else if (cpi->sf.search_method == SQUARE) {
- bestsme = vp9_square_search(x, &mvp_full.as_mv,
- step_param,
- sadpb, 1,
+ bestsme = vp9_square_search(x, &mvp_full, step_param, sadpb, 1,
&cpi->fn_ptr[bsize], 1,
&ref_mv.as_mv, &tmp_mv->as_mv);
} else if (cpi->sf.search_method == BIGDIA) {
- bestsme = vp9_bigdia_search(x, &mvp_full.as_mv,
- step_param,
- sadpb, 1,
+ bestsme = vp9_bigdia_search(x, &mvp_full, step_param, sadpb, 1,
&cpi->fn_ptr[bsize], 1,
&ref_mv.as_mv, &tmp_mv->as_mv);
} else {
- bestsme = vp9_full_pixel_diamond(cpi, x, &mvp_full.as_mv, step_param,
+ bestsme = vp9_full_pixel_diamond(cpi, x, &mvp_full, step_param,
sadpb, further_steps, 1,
&cpi->fn_ptr[bsize],
&ref_mv.as_mv, tmp_mv);
@@ -2540,7 +2544,7 @@
ref_yv12[!id].stride,
second_pred, pw,
&frame_mv[refs[!id]].as_mv,
- xd->scale_factors[!id],
+ &xd->block_refs[!id]->sf,
pw, ph, 0,
&xd->subpix, MV_PRECISION_Q3,
mi_col * MI_SIZE, mi_row * MI_SIZE);
@@ -2760,9 +2764,8 @@
mbmi->mode_context[mbmi->ref_frame[0]]);
if (!(*mode_excluded))
- *mode_excluded = is_comp_pred
- ? cpi->common.reference_mode == SINGLE_REFERENCE
- : cpi->common.reference_mode == COMPOUND_REFERENCE;
+ *mode_excluded = is_comp_pred ? cm->reference_mode == SINGLE_REFERENCE
+ : cm->reference_mode == COMPOUND_REFERENCE;
pred_exists = 0;
// Are all MVs integer pel for Y and UV
@@ -2894,7 +2897,7 @@
}
}
- if (cpi->common.mcomp_filter_type == SWITCHABLE)
+ if (cm->mcomp_filter_type == SWITCHABLE)
*rate2 += get_switchable_rate(x);
if (!is_comp_pred && cpi->enable_encode_breakout) {
@@ -3124,10 +3127,6 @@
int_mv single_newmv[MAX_REF_FRAMES] = { { 0 } };
static const int flag_list[4] = { 0, VP9_LAST_FLAG, VP9_GOLD_FLAG,
VP9_ALT_FLAG };
- int idx_list[4] = {0,
- cpi->lst_fb_idx,
- cpi->gld_fb_idx,
- cpi->alt_fb_idx};
int64_t best_rd = best_rd_so_far;
int64_t best_tx_rd[TX_MODES];
int64_t best_tx_diff[TX_MODES];
@@ -3136,7 +3135,6 @@
int64_t best_filter_rd[SWITCHABLE_FILTER_CONTEXTS];
int64_t best_filter_diff[SWITCHABLE_FILTER_CONTEXTS];
MB_MODE_INFO best_mbmode = { 0 };
- int j;
int mode_index, best_mode_index = 0;
unsigned int ref_costs_single[MAX_REF_FRAMES], ref_costs_comp[MAX_REF_FRAMES];
vp9_prob comp_mode_p;
@@ -3149,10 +3147,7 @@
int64_t dist_uv[TX_SIZES];
int skip_uv[TX_SIZES];
MB_PREDICTION_MODE mode_uv[TX_SIZES];
- unsigned int ref_frame_mask = 0;
- unsigned int mode_mask = 0;
int64_t mode_distortions[MB_MODE_COUNT] = {-1};
- int64_t frame_distortions[MAX_REF_FRAMES] = {-1};
int intra_cost_penalty = 20 * vp9_dc_quant(cm->base_qindex, cm->y_dc_delta_q);
const int bws = num_8x8_blocks_wide_lookup[bsize] / 2;
const int bhs = num_8x8_blocks_high_lookup[bsize] / 2;
@@ -3161,7 +3156,6 @@
x->skip_encode = cpi->sf.skip_encode_frame && x->q_index < QIDX_SKIP_THRESH;
// Everywhere the flag is set the error is much higher than its neighbors.
- ctx->frames_with_high_error = 0;
ctx->modes_with_high_error = 0;
estimate_ref_frame_costs(cpi, segment_id, ref_costs_single, ref_costs_comp,
@@ -3180,44 +3174,11 @@
*returnrate = INT_MAX;
- // Create a mask set to 1 for each reference frame used by a smaller
- // resolution.
- if (cpi->sf.use_avoid_tested_higherror) {
- switch (block_size) {
- case BLOCK_64X64:
- for (i = 0; i < 4; i++) {
- for (j = 0; j < 4; j++) {
- ref_frame_mask |= x->mb_context[i][j].frames_with_high_error;
- mode_mask |= x->mb_context[i][j].modes_with_high_error;
- }
- }
- for (i = 0; i < 4; i++) {
- ref_frame_mask |= x->sb32_context[i].frames_with_high_error;
- mode_mask |= x->sb32_context[i].modes_with_high_error;
- }
- break;
- case BLOCK_32X32:
- for (i = 0; i < 4; i++) {
- ref_frame_mask |=
- x->mb_context[x->sb_index][i].frames_with_high_error;
- mode_mask |= x->mb_context[x->sb_index][i].modes_with_high_error;
- }
- break;
- default:
- // Until we handle all block sizes set it to present;
- ref_frame_mask = 0;
- mode_mask = 0;
- break;
- }
- ref_frame_mask = ~ref_frame_mask;
- mode_mask = ~mode_mask;
- }
-
for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ref_frame++) {
x->pred_mv_sad[ref_frame] = INT_MAX;
if (cpi->ref_frame_flags & flag_list[ref_frame]) {
- setup_buffer_inter(cpi, x, tile, idx_list[ref_frame], ref_frame,
- block_size, mi_row, mi_col,
+ setup_buffer_inter(cpi, x, tile, get_ref_frame_idx(cpi, ref_frame),
+ ref_frame, block_size, mi_row, mi_col,
frame_mv[NEARESTMV], frame_mv[NEARMV], yv12_mb);
}
frame_mv[NEWMV][ref_frame].as_int = INVALID_MV;
@@ -3243,14 +3204,14 @@
x->skip = 0;
this_mode = vp9_mode_order[mode_index].mode;
- ref_frame = vp9_mode_order[mode_index].ref_frame;
- second_ref_frame = vp9_mode_order[mode_index].second_ref_frame;
+ ref_frame = vp9_mode_order[mode_index].ref_frame[0];
+ second_ref_frame = vp9_mode_order[mode_index].ref_frame[1];
// Look at the reference frame of the best mode so far and set the
// skip mask to look at a subset of the remaining modes.
if (mode_index > cpi->sf.mode_skip_start) {
if (mode_index == (cpi->sf.mode_skip_start + 1)) {
- switch (vp9_mode_order[best_mode_index].ref_frame) {
+ switch (vp9_mode_order[best_mode_index].ref_frame[0]) {
case INTRA_FRAME:
cpi->mode_skip_mask = 0;
break;
@@ -3295,19 +3256,6 @@
if (x->fast_ms > 2 && ref_frame != x->subblock_ref)
continue;
- if (cpi->sf.use_avoid_tested_higherror && bsize >= BLOCK_8X8) {
- if (!(ref_frame_mask & (1 << ref_frame))) {
- continue;
- }
- if (!(mode_mask & (1 << this_mode))) {
- continue;
- }
- if (second_ref_frame != NONE
- && !(ref_frame_mask & (1 << second_ref_frame))) {
- continue;
- }
- }
-
mbmi->ref_frame[0] = ref_frame;
mbmi->ref_frame[1] = second_ref_frame;
@@ -3323,7 +3271,7 @@
comp_pred = second_ref_frame > INTRA_FRAME;
if (comp_pred) {
if (cpi->sf.mode_search_skip_flags & FLAG_SKIP_COMP_BESTINTRA)
- if (vp9_mode_order[best_mode_index].ref_frame == INTRA_FRAME)
+ if (vp9_mode_order[best_mode_index].ref_frame[0] == INTRA_FRAME)
continue;
if (cpi->sf.mode_search_skip_flags & FLAG_SKIP_COMP_REFMISMATCH)
if (ref_frame != best_inter_ref_frame &&
@@ -3422,7 +3370,7 @@
// one of the neighboring directional modes
if ((cpi->sf.mode_search_skip_flags & FLAG_SKIP_INTRA_BESTINTER) &&
(this_mode >= D45_PRED && this_mode <= TM_PRED)) {
- if (vp9_mode_order[best_mode_index].ref_frame > INTRA_FRAME)
+ if (vp9_mode_order[best_mode_index].ref_frame[0] > INTRA_FRAME)
continue;
}
mbmi->mode = this_mode;
@@ -3556,10 +3504,6 @@
|| distortion2 < mode_distortions[this_mode]) {
mode_distortions[this_mode] = distortion2;
}
- if (frame_distortions[ref_frame] == -1
- || distortion2 < frame_distortions[ref_frame]) {
- frame_distortions[ref_frame] = distortion2;
- }
// Did this mode help.. i.e. is it the new best mode
if (this_rd < best_rd || x->skip) {
@@ -3683,7 +3627,7 @@
// If we used an estimate for the uv intra rd in the loop above...
if (cpi->sf.use_uv_intra_rd_estimate) {
// Do Intra UV best rd mode selection if best mode choice above was intra.
- if (vp9_mode_order[best_mode_index].ref_frame == INTRA_FRAME) {
+ if (vp9_mode_order[best_mode_index].ref_frame[0] == INTRA_FRAME) {
TX_SIZE uv_tx_size;
*mbmi = best_mbmode;
uv_tx_size = get_uv_tx_size(mbmi);
@@ -3699,7 +3643,7 @@
// If we are using reference masking and the set mask flag is set then
// create the reference frame mask.
if (cpi->sf.reference_masking && cpi->set_ref_frame_mask)
- cpi->ref_frame_mask = ~(1 << vp9_mode_order[best_mode_index].ref_frame);
+ cpi->ref_frame_mask = ~(1 << vp9_mode_order[best_mode_index].ref_frame[0]);
// Flag all modes that have a distortion thats > 2x the best we found at
// this level.
@@ -3712,14 +3656,6 @@
}
}
- // Flag all ref frames that have a distortion thats > 2x the best we found at
- // this level.
- for (ref_frame = INTRA_FRAME; ref_frame <= ALTREF_FRAME; ref_frame++) {
- if (frame_distortions[ref_frame] > 2 * *returndistortion) {
- ctx->frames_with_high_error |= (1 << ref_frame);
- }
- }
-
assert((cm->mcomp_filter_type == SWITCHABLE) ||
(cm->mcomp_filter_type == best_mbmode.interp_filter) ||
!is_inter_block(&best_mbmode));
@@ -3811,10 +3747,6 @@
struct buf_2d yv12_mb[4][MAX_MB_PLANE];
static const int flag_list[4] = { 0, VP9_LAST_FLAG, VP9_GOLD_FLAG,
VP9_ALT_FLAG };
- int idx_list[4] = {0,
- cpi->lst_fb_idx,
- cpi->gld_fb_idx,
- cpi->alt_fb_idx};
int64_t best_rd = best_rd_so_far;
int64_t best_yrd = best_rd_so_far; // FIXME(rbultje) more precise
int64_t best_tx_rd[TX_MODES];
@@ -3834,8 +3766,7 @@
int64_t dist_uv[TX_SIZES];
int skip_uv[TX_SIZES];
MB_PREDICTION_MODE mode_uv[TX_SIZES] = { 0 };
- int intra_cost_penalty = 20 * vp9_dc_quant(cpi->common.base_qindex,
- cpi->common.y_dc_delta_q);
+ int intra_cost_penalty = 20 * vp9_dc_quant(cm->base_qindex, cm->y_dc_delta_q);
int_mv seg_mvs[4][MAX_REF_FRAMES];
b_mode_info best_bmodes[4];
int best_skip2 = 0;
@@ -3865,8 +3796,8 @@
for (ref_frame = LAST_FRAME; ref_frame <= ALTREF_FRAME; ref_frame++) {
if (cpi->ref_frame_flags & flag_list[ref_frame]) {
- setup_buffer_inter(cpi, x, tile, idx_list[ref_frame], ref_frame,
- block_size, mi_row, mi_col,
+ setup_buffer_inter(cpi, x, tile, get_ref_frame_idx(cpi, ref_frame),
+ ref_frame, block_size, mi_row, mi_col,
frame_mv[NEARESTMV], frame_mv[NEARMV],
yv12_mb);
}
@@ -3892,14 +3823,14 @@
tx_cache[i] = INT64_MAX;
x->skip = 0;
- ref_frame = vp9_ref_order[mode_index].ref_frame;
- second_ref_frame = vp9_ref_order[mode_index].second_ref_frame;
+ ref_frame = vp9_ref_order[mode_index].ref_frame[0];
+ second_ref_frame = vp9_ref_order[mode_index].ref_frame[1];
// Look at the reference frame of the best mode so far and set the
// skip mask to look at a subset of the remaining modes.
if (mode_index > 2 && cpi->sf.mode_skip_start < MAX_MODES) {
if (mode_index == 3) {
- switch (vp9_ref_order[best_mode_index].ref_frame) {
+ switch (vp9_ref_order[best_mode_index].ref_frame[0]) {
case INTRA_FRAME:
cpi->mode_skip_mask = 0;
break;
@@ -3954,7 +3885,7 @@
comp_pred = second_ref_frame > INTRA_FRAME;
if (comp_pred) {
if (cpi->sf.mode_search_skip_flags & FLAG_SKIP_COMP_BESTINTRA)
- if (vp9_ref_order[best_mode_index].ref_frame == INTRA_FRAME)
+ if (vp9_ref_order[best_mode_index].ref_frame[0] == INTRA_FRAME)
continue;
if (cpi->sf.mode_search_skip_flags & FLAG_SKIP_COMP_REFMISMATCH)
if (ref_frame != best_inter_ref_frame &&
@@ -3964,12 +3895,11 @@
// TODO(jingning, jkoleszar): scaling reference frame not supported for
// sub8x8 blocks.
- if (ref_frame > 0 &&
- vp9_is_scaled(&cpi->common.active_ref_scale[ref_frame - 1]))
+ if (ref_frame > 0 && vp9_is_scaled(&cm->frame_refs[ref_frame - 1].sf))
continue;
if (second_ref_frame > 0 &&
- vp9_is_scaled(&cpi->common.active_ref_scale[second_ref_frame - 1]))
+ vp9_is_scaled(&cm->frame_refs[second_ref_frame - 1].sf))
continue;
set_scale_factors(cm, xd, ref_frame - 1, second_ref_frame - 1);
@@ -3978,7 +3908,7 @@
// Evaluate all sub-pel filters irrespective of whether we can use
// them for this frame.
mbmi->interp_filter = cm->mcomp_filter_type;
- vp9_setup_interp_filters(xd, mbmi->interp_filter, &cpi->common);
+ vp9_setup_interp_filters(xd, mbmi->interp_filter, cm);
if (comp_pred) {
if (!(cpi->ref_frame_flags & flag_list[second_ref_frame]))
@@ -4101,7 +4031,7 @@
int newbest, rs;
int64_t rs_rd;
mbmi->interp_filter = switchable_filter_index;
- vp9_setup_interp_filters(xd, mbmi->interp_filter, &cpi->common);
+ vp9_setup_interp_filters(xd, mbmi->interp_filter, cm);
tmp_rd = rd_pick_best_mbsegmentation(cpi, x, tile,
&mbmi->ref_mvs[ref_frame][0],
@@ -4167,7 +4097,7 @@
mbmi->interp_filter = (cm->mcomp_filter_type == SWITCHABLE ?
tmp_best_filter : cm->mcomp_filter_type);
- vp9_setup_interp_filters(xd, mbmi->interp_filter, &cpi->common);
+ vp9_setup_interp_filters(xd, mbmi->interp_filter, cm);
if (!pred_exists) {
// Handles the special case when a filter that is not in the
// switchable list (bilinear, 6-tap) is indicated at the frame level
@@ -4183,7 +4113,7 @@
if (tmp_rd == INT64_MAX)
continue;
} else {
- if (cpi->common.mcomp_filter_type == SWITCHABLE) {
+ if (cm->mcomp_filter_type == SWITCHABLE) {
int rs = get_switchable_rate(x);
tmp_best_rdu -= RDCOST(x->rdmult, x->rddiv, rs, 0);
}
@@ -4201,13 +4131,12 @@
rate2 += rate;
distortion2 += distortion;
- if (cpi->common.mcomp_filter_type == SWITCHABLE)
+ if (cm->mcomp_filter_type == SWITCHABLE)
rate2 += get_switchable_rate(x);
if (!mode_excluded)
- mode_excluded = comp_pred
- ? cpi->common.reference_mode == SINGLE_REFERENCE
- : cpi->common.reference_mode == COMPOUND_REFERENCE;
+ mode_excluded = comp_pred ? cm->reference_mode == SINGLE_REFERENCE
+ : cm->reference_mode == COMPOUND_REFERENCE;
compmode_cost = vp9_cost_bit(comp_mode_p, comp_pred);
@@ -4235,7 +4164,7 @@
}
}
- if (cpi->common.reference_mode == REFERENCE_MODE_SELECT)
+ if (cm->reference_mode == REFERENCE_MODE_SELECT)
rate2 += compmode_cost;
// Estimate the reference frame signaling cost and add it
@@ -4346,7 +4275,7 @@
if (!disable_skip && ref_frame != INTRA_FRAME) {
int64_t single_rd, hybrid_rd, single_rate, hybrid_rate;
- if (cpi->common.reference_mode == REFERENCE_MODE_SELECT) {
+ if (cm->reference_mode == REFERENCE_MODE_SELECT) {
single_rate = rate2 - compmode_cost;
hybrid_rate = rate2;
} else {
@@ -4425,7 +4354,7 @@
// If we used an estimate for the uv intra rd in the loop above...
if (cpi->sf.use_uv_intra_rd_estimate) {
// Do Intra UV best rd mode selection if best mode choice above was intra.
- if (vp9_ref_order[best_mode_index].ref_frame == INTRA_FRAME) {
+ if (vp9_ref_order[best_mode_index].ref_frame[0] == INTRA_FRAME) {
TX_SIZE uv_tx_size;
*mbmi = best_mbmode;
uv_tx_size = get_uv_tx_size(mbmi);
@@ -4440,7 +4369,7 @@
// If we are using reference masking and the set mask flag is set then
// create the reference frame mask.
if (cpi->sf.reference_masking && cpi->set_ref_frame_mask)
- cpi->ref_frame_mask = ~(1 << vp9_ref_order[best_mode_index].ref_frame);
+ cpi->ref_frame_mask = ~(1 << vp9_ref_order[best_mode_index].ref_frame[0]);
if (best_rd == INT64_MAX && bsize < BLOCK_8X8) {
*returnrate = INT_MAX;
diff --git a/vp9/encoder/vp9_segmentation.c b/vp9/encoder/vp9_segmentation.c
index 4568e7a..509717e 100644
--- a/vp9/encoder/vp9_segmentation.c
+++ b/vp9/encoder/vp9_segmentation.c
@@ -296,3 +296,12 @@
vpx_memcpy(seg->tree_probs, no_pred_tree, sizeof(no_pred_tree));
}
}
+
+void vp9_reset_segment_features(struct segmentation *seg) {
+ // Set up default state for MB feature flags
+ seg->enabled = 0;
+ seg->update_map = 0;
+ seg->update_data = 0;
+ vpx_memset(seg->tree_probs, 255, sizeof(seg->tree_probs));
+ vp9_clearall_segfeatures(seg);
+}
diff --git a/vp9/encoder/vp9_segmentation.h b/vp9/encoder/vp9_segmentation.h
index 03f14ea..3c6eb70 100644
--- a/vp9/encoder/vp9_segmentation.h
+++ b/vp9/encoder/vp9_segmentation.h
@@ -43,4 +43,6 @@
void vp9_choose_segmap_coding_method(VP9_COMP *cpi);
+void vp9_reset_segment_features(struct segmentation *seg);
+
#endif // VP9_ENCODER_VP9_SEGMENTATION_H_
diff --git a/vp9/encoder/x86/vp9_variance_avx2.c b/vp9/encoder/x86/vp9_variance_avx2.c
new file mode 100644
index 0000000..c9b90d5
--- /dev/null
+++ b/vp9/encoder/x86/vp9_variance_avx2.c
@@ -0,0 +1,157 @@
+/*
+ * Copyright (c) 2012 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 "./vpx_config.h"
+
+#include "vp9/encoder/vp9_variance.h"
+#include "vp9/common/vp9_pragmas.h"
+#include "vpx_ports/mem.h"
+
+typedef void (*get_var_avx2) (
+ const unsigned char *src_ptr,
+ int source_stride,
+ const unsigned char *ref_ptr,
+ int recon_stride,
+ unsigned int *SSE,
+ int *Sum
+);
+
+void vp9_get16x16var_avx2
+(
+ const unsigned char *src_ptr,
+ int source_stride,
+ const unsigned char *ref_ptr,
+ int recon_stride,
+ unsigned int *SSE,
+ int *Sum
+);
+
+void vp9_get32x32var_avx2
+(
+ const unsigned char *src_ptr,
+ int source_stride,
+ const unsigned char *ref_ptr,
+ int recon_stride,
+ unsigned int *SSE,
+ int *Sum
+);
+
+static void variance_avx2(const unsigned char *src_ptr, int source_stride,
+ const unsigned char *ref_ptr, int recon_stride,
+ int w, int h, unsigned int *sse, int *sum,
+ get_var_avx2 var_fn, int block_size) {
+ unsigned int sse0;
+ int sum0;
+ int i, j;
+
+ *sse = 0;
+ *sum = 0;
+
+ for (i = 0; i < h; i += 16) {
+ for (j = 0; j < w; j += block_size) {
+ // processing 16 rows horizontally each call
+ var_fn(src_ptr + source_stride * i + j, source_stride,
+ ref_ptr + recon_stride * i + j, recon_stride, &sse0, &sum0);
+ *sse += sse0;
+ *sum += sum0;
+ }
+ }
+}
+
+unsigned int vp9_variance16x16_avx2
+(
+ const unsigned char *src_ptr,
+ int source_stride,
+ const unsigned char *ref_ptr,
+ int recon_stride,
+ unsigned int *sse) {
+ unsigned int var;
+ int avg;
+
+ variance_avx2(src_ptr, source_stride, ref_ptr, recon_stride, 16, 16,
+ &var, &avg, vp9_get16x16var_avx2, 16);
+ *sse = var;
+ return (var - (((unsigned int)avg * avg) >> 8));
+}
+
+unsigned int vp9_mse16x16_avx2(
+ const unsigned char *src_ptr,
+ int source_stride,
+ const unsigned char *ref_ptr,
+ int recon_stride,
+ unsigned int *sse) {
+ unsigned int sse0;
+ int sum0;
+ vp9_get16x16var_avx2(src_ptr, source_stride, ref_ptr, recon_stride, &sse0,
+ &sum0);
+ *sse = sse0;
+ return sse0;
+}
+
+unsigned int vp9_variance32x32_avx2(const uint8_t *src_ptr,
+ int source_stride,
+ const uint8_t *ref_ptr,
+ int recon_stride,
+ unsigned int *sse) {
+ unsigned int var;
+ int avg;
+
+ // processing 32 elements vertically in parallel
+ variance_avx2(src_ptr, source_stride, ref_ptr, recon_stride, 32, 32,
+ &var, &avg, vp9_get32x32var_avx2, 32);
+ *sse = var;
+ return (var - (((int64_t)avg * avg) >> 10));
+}
+
+unsigned int vp9_variance32x16_avx2(const uint8_t *src_ptr,
+ int source_stride,
+ const uint8_t *ref_ptr,
+ int recon_stride,
+ unsigned int *sse) {
+ unsigned int var;
+ int avg;
+
+ // processing 32 elements vertically in parallel
+ variance_avx2(src_ptr, source_stride, ref_ptr, recon_stride, 32, 16,
+ &var, &avg, vp9_get32x32var_avx2, 32);
+ *sse = var;
+ return (var - (((int64_t)avg * avg) >> 9));
+}
+
+
+unsigned int vp9_variance64x64_avx2(const uint8_t *src_ptr,
+ int source_stride,
+ const uint8_t *ref_ptr,
+ int recon_stride,
+ unsigned int *sse) {
+ unsigned int var;
+ int avg;
+
+ // processing 32 elements vertically in parallel
+ variance_avx2(src_ptr, source_stride, ref_ptr, recon_stride, 64, 64,
+ &var, &avg, vp9_get32x32var_avx2, 32);
+ *sse = var;
+ return (var - (((int64_t)avg * avg) >> 12));
+}
+
+unsigned int vp9_variance64x32_avx2(const uint8_t *src_ptr,
+ int source_stride,
+ const uint8_t *ref_ptr,
+ int recon_stride,
+ unsigned int *sse) {
+ unsigned int var;
+ int avg;
+
+ // processing 32 elements vertically in parallel
+ variance_avx2(src_ptr, source_stride, ref_ptr, recon_stride, 64, 32,
+ &var, &avg, vp9_get32x32var_avx2, 32);
+
+ *sse = var;
+ return (var - (((int64_t)avg * avg) >> 11));
+}
diff --git a/vp9/encoder/x86/vp9_variance_impl_intrin_avx2.c b/vp9/encoder/x86/vp9_variance_impl_intrin_avx2.c
new file mode 100644
index 0000000..f992328
--- /dev/null
+++ b/vp9/encoder/x86/vp9_variance_impl_intrin_avx2.c
@@ -0,0 +1,213 @@
+/*
+ * Copyright (c) 2012 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 <immintrin.h> // AVX2
+
+void vp9_get16x16var_avx2(const unsigned char *src_ptr,
+ int source_stride,
+ const unsigned char *ref_ptr,
+ int recon_stride,
+ unsigned int *SSE,
+ int *Sum) {
+ __m256i src, src_expand_low, src_expand_high, ref, ref_expand_low;
+ __m256i ref_expand_high, madd_low, madd_high;
+ unsigned int i, src_2strides, ref_2strides;
+ __m256i zero_reg = _mm256_set1_epi16(0);
+ __m256i sum_ref_src = _mm256_set1_epi16(0);
+ __m256i madd_ref_src = _mm256_set1_epi16(0);
+
+ // processing two strides in a 256 bit register reducing the number
+ // of loop stride by half (comparing to the sse2 code)
+ src_2strides = source_stride << 1;
+ ref_2strides = recon_stride << 1;
+ for (i = 0; i < 8; i++) {
+ src = _mm256_castsi128_si256(
+ _mm_loadu_si128((__m128i const *) (src_ptr)));
+ src = _mm256_inserti128_si256(src,
+ _mm_loadu_si128((__m128i const *)(src_ptr+source_stride)), 1);
+
+ ref =_mm256_castsi128_si256(
+ _mm_loadu_si128((__m128i const *) (ref_ptr)));
+ ref = _mm256_inserti128_si256(ref,
+ _mm_loadu_si128((__m128i const *)(ref_ptr+recon_stride)), 1);
+
+ // expanding to 16 bit each lane
+ src_expand_low = _mm256_unpacklo_epi8(src, zero_reg);
+ src_expand_high = _mm256_unpackhi_epi8(src, zero_reg);
+
+ ref_expand_low = _mm256_unpacklo_epi8(ref, zero_reg);
+ ref_expand_high = _mm256_unpackhi_epi8(ref, zero_reg);
+
+ // src-ref
+ src_expand_low = _mm256_sub_epi16(src_expand_low, ref_expand_low);
+ src_expand_high = _mm256_sub_epi16(src_expand_high, ref_expand_high);
+
+ // madd low (src - ref)
+ madd_low = _mm256_madd_epi16(src_expand_low, src_expand_low);
+
+ // add high to low
+ src_expand_low = _mm256_add_epi16(src_expand_low, src_expand_high);
+
+ // madd high (src - ref)
+ madd_high = _mm256_madd_epi16(src_expand_high, src_expand_high);
+
+ sum_ref_src = _mm256_add_epi16(sum_ref_src, src_expand_low);
+
+ // add high to low
+ madd_ref_src = _mm256_add_epi32(madd_ref_src,
+ _mm256_add_epi32(madd_low, madd_high));
+
+ src_ptr+= src_2strides;
+ ref_ptr+= ref_2strides;
+ }
+
+ {
+ __m128i sum_res, madd_res;
+ __m128i expand_sum_low, expand_sum_high, expand_sum;
+ __m128i expand_madd_low, expand_madd_high, expand_madd;
+ __m128i ex_expand_sum_low, ex_expand_sum_high, ex_expand_sum;
+
+ // extract the low lane and add it to the high lane
+ sum_res = _mm_add_epi16(_mm256_castsi256_si128(sum_ref_src),
+ _mm256_extractf128_si256(sum_ref_src, 1));
+
+ madd_res = _mm_add_epi32(_mm256_castsi256_si128(madd_ref_src),
+ _mm256_extractf128_si256(madd_ref_src, 1));
+
+ // padding each 2 bytes with another 2 zeroed bytes
+ expand_sum_low = _mm_unpacklo_epi16(_mm256_castsi256_si128(zero_reg),
+ sum_res);
+ expand_sum_high = _mm_unpackhi_epi16(_mm256_castsi256_si128(zero_reg),
+ sum_res);
+
+ // shifting the sign 16 bits right
+ expand_sum_low = _mm_srai_epi32(expand_sum_low, 16);
+ expand_sum_high = _mm_srai_epi32(expand_sum_high, 16);
+
+ expand_sum = _mm_add_epi32(expand_sum_low, expand_sum_high);
+
+ // expand each 32 bits of the madd result to 64 bits
+ expand_madd_low = _mm_unpacklo_epi32(madd_res,
+ _mm256_castsi256_si128(zero_reg));
+ expand_madd_high = _mm_unpackhi_epi32(madd_res,
+ _mm256_castsi256_si128(zero_reg));
+
+ expand_madd = _mm_add_epi32(expand_madd_low, expand_madd_high);
+
+ ex_expand_sum_low = _mm_unpacklo_epi32(expand_sum,
+ _mm256_castsi256_si128(zero_reg));
+ ex_expand_sum_high = _mm_unpackhi_epi32(expand_sum,
+ _mm256_castsi256_si128(zero_reg));
+
+ ex_expand_sum = _mm_add_epi32(ex_expand_sum_low, ex_expand_sum_high);
+
+ // shift 8 bytes eight
+ madd_res = _mm_srli_si128(expand_madd, 8);
+ sum_res = _mm_srli_si128(ex_expand_sum, 8);
+
+ madd_res = _mm_add_epi32(madd_res, expand_madd);
+ sum_res = _mm_add_epi32(sum_res, ex_expand_sum);
+
+ *((int*)SSE)= _mm_cvtsi128_si32(madd_res);
+
+ *((int*)Sum)= _mm_cvtsi128_si32(sum_res);
+ }
+}
+
+void vp9_get32x32var_avx2(const unsigned char *src_ptr,
+ int source_stride,
+ const unsigned char *ref_ptr,
+ int recon_stride,
+ unsigned int *SSE,
+ int *Sum) {
+ __m256i src, src_expand_low, src_expand_high, ref, ref_expand_low;
+ __m256i ref_expand_high, madd_low, madd_high;
+ unsigned int i;
+ __m256i zero_reg = _mm256_set1_epi16(0);
+ __m256i sum_ref_src = _mm256_set1_epi16(0);
+ __m256i madd_ref_src = _mm256_set1_epi16(0);
+
+ // processing 32 elements in parallel
+ for (i = 0; i < 16; i++) {
+ src = _mm256_loadu_si256((__m256i const *) (src_ptr));
+
+ ref = _mm256_loadu_si256((__m256i const *) (ref_ptr));
+
+ // expanding to 16 bit each lane
+ src_expand_low = _mm256_unpacklo_epi8(src, zero_reg);
+ src_expand_high = _mm256_unpackhi_epi8(src, zero_reg);
+
+ ref_expand_low = _mm256_unpacklo_epi8(ref, zero_reg);
+ ref_expand_high = _mm256_unpackhi_epi8(ref, zero_reg);
+
+ // src-ref
+ src_expand_low = _mm256_sub_epi16(src_expand_low, ref_expand_low);
+ src_expand_high = _mm256_sub_epi16(src_expand_high, ref_expand_high);
+
+ // madd low (src - ref)
+ madd_low = _mm256_madd_epi16(src_expand_low, src_expand_low);
+
+ // add high to low
+ src_expand_low = _mm256_add_epi16(src_expand_low, src_expand_high);
+
+ // madd high (src - ref)
+ madd_high = _mm256_madd_epi16(src_expand_high, src_expand_high);
+
+ sum_ref_src = _mm256_add_epi16(sum_ref_src, src_expand_low);
+
+ // add high to low
+ madd_ref_src = _mm256_add_epi32(madd_ref_src,
+ _mm256_add_epi32(madd_low, madd_high));
+
+ src_ptr+= source_stride;
+ ref_ptr+= recon_stride;
+ }
+
+ {
+ __m256i expand_sum_low, expand_sum_high, expand_sum;
+ __m256i expand_madd_low, expand_madd_high, expand_madd;
+ __m256i ex_expand_sum_low, ex_expand_sum_high, ex_expand_sum;
+
+ // padding each 2 bytes with another 2 zeroed bytes
+ expand_sum_low = _mm256_unpacklo_epi16(zero_reg, sum_ref_src);
+ expand_sum_high = _mm256_unpackhi_epi16(zero_reg, sum_ref_src);
+
+ // shifting the sign 16 bits right
+ expand_sum_low = _mm256_srai_epi32(expand_sum_low, 16);
+ expand_sum_high = _mm256_srai_epi32(expand_sum_high, 16);
+
+ expand_sum = _mm256_add_epi32(expand_sum_low, expand_sum_high);
+
+ // expand each 32 bits of the madd result to 64 bits
+ expand_madd_low = _mm256_unpacklo_epi32(madd_ref_src, zero_reg);
+ expand_madd_high = _mm256_unpackhi_epi32(madd_ref_src, zero_reg);
+
+ expand_madd = _mm256_add_epi32(expand_madd_low, expand_madd_high);
+
+ ex_expand_sum_low = _mm256_unpacklo_epi32(expand_sum, zero_reg);
+ ex_expand_sum_high = _mm256_unpackhi_epi32(expand_sum, zero_reg);
+
+ ex_expand_sum = _mm256_add_epi32(ex_expand_sum_low, ex_expand_sum_high);
+
+ // shift 8 bytes eight
+ madd_ref_src = _mm256_srli_si256(expand_madd, 8);
+ sum_ref_src = _mm256_srli_si256(ex_expand_sum, 8);
+
+ madd_ref_src = _mm256_add_epi32(madd_ref_src, expand_madd);
+ sum_ref_src = _mm256_add_epi32(sum_ref_src, ex_expand_sum);
+
+ // extract the low lane and the high lane and add the results
+ *((int*)SSE)= _mm_cvtsi128_si32(_mm256_castsi256_si128(madd_ref_src)) +
+ _mm_cvtsi128_si32(_mm256_extractf128_si256(madd_ref_src, 1));
+
+ *((int*)Sum)= _mm_cvtsi128_si32(_mm256_castsi256_si128(sum_ref_src)) +
+ _mm_cvtsi128_si32(_mm256_extractf128_si256(sum_ref_src, 1));
+ }
+}
diff --git a/vp9/vp9cx.mk b/vp9/vp9cx.mk
index 9114a30..0d79346 100644
--- a/vp9/vp9cx.mk
+++ b/vp9/vp9cx.mk
@@ -81,6 +81,7 @@
VP9_CX_SRCS-$(HAVE_MMX) += encoder/x86/vp9_variance_impl_mmx.asm
VP9_CX_SRCS-$(HAVE_MMX) += encoder/x86/vp9_sad_mmx.asm
VP9_CX_SRCS-$(HAVE_SSE2) += encoder/x86/vp9_variance_impl_sse2.asm
+VP9_CX_SRCS-$(HAVE_AVX2) += encoder/x86/vp9_variance_impl_intrin_avx2.c
VP9_CX_SRCS-$(HAVE_SSE2) += encoder/x86/vp9_sad4d_sse2.asm
VP9_CX_SRCS-$(HAVE_SSE2) += encoder/x86/vp9_subpel_variance_impl_sse2.asm
VP9_CX_SRCS-$(HAVE_SSE2) += encoder/x86/vp9_temporal_filter_apply_sse2.asm
@@ -91,6 +92,7 @@
VP9_CX_SRCS-$(HAVE_SSE2) += encoder/x86/vp9_sad_sse2.asm
VP9_CX_SRCS-$(HAVE_SSE2) += encoder/x86/vp9_subtract_sse2.asm
VP9_CX_SRCS-$(HAVE_SSE2) += encoder/x86/vp9_variance_sse2.c
+VP9_CX_SRCS-$(HAVE_AVX2) += encoder/x86/vp9_variance_avx2.c
VP9_CX_SRCS-$(HAVE_SSE2) += encoder/x86/vp9_subpel_variance.asm
endif
diff --git a/vp9_spatial_scalable_encoder.c b/vp9_spatial_scalable_encoder.c
index a727f50..b637331 100644
--- a/vp9_spatial_scalable_encoder.c
+++ b/vp9_spatial_scalable_encoder.c
@@ -79,7 +79,9 @@
struct VpxInputContext input_ctx;
} AppInput;
-void usage_exit(const char *exec_name) {
+static const char *exec_name;
+
+void usage_exit() {
fprintf(stderr, "Usage: %s <options> input_filename output_filename\n",
exec_name);
fprintf(stderr, "Options:\n");
@@ -95,12 +97,6 @@
exit(EXIT_FAILURE);
}
-static int create_dummy_frame(vpx_image_t *img) {
- const size_t buf_size = img->w * img->h * 3 / 2;
- memset(img->planes[0], 129, buf_size);
- return 1;
-}
-
static void parse_command_line(int argc, const char **argv_,
AppInput *app_input, SvcContext *svc_ctx,
vpx_codec_enc_cfg_t *enc_cfg) {
@@ -170,7 +166,7 @@
die("Error: Unrecognized option %s\n", *argi);
if (argv[0] == NULL || argv[1] == 0) {
- usage_exit(argv_[0]);
+ usage_exit();
}
app_input->input_ctx.filename = argv[0];
app_input->output_filename = argv[1];
@@ -210,6 +206,7 @@
memset(&svc_ctx, 0, sizeof(svc_ctx));
svc_ctx.log_print = 1;
+ exec_name = argv[0];
parse_command_line(argc, argv, &app_input, &svc_ctx, &enc_cfg);
// Allocate image buffer
@@ -260,8 +257,16 @@
fclose(app_input.input_ctx.file);
if (vpx_codec_destroy(&codec)) die_codec(&codec, "Failed to destroy codec");
- // rewrite the output file headers with the actual frame count
+ // rewrite the output file headers with the actual frame count, and
+ // resolution of the highest layer
if (!fseek(outfile, 0, SEEK_SET)) {
+ // get resolution of highest layer
+ if (VPX_CODEC_OK != vpx_svc_get_layer_resolution(&svc_ctx,
+ svc_ctx.spatial_layers - 1,
+ &enc_cfg.g_w,
+ &enc_cfg.g_h)) {
+ die("Failed to get output resolution");
+ }
ivf_write_file_header(outfile, &enc_cfg, VP9_FOURCC, frame_cnt);
}
fclose(outfile);
diff --git a/vpx/exports_enc b/vpx/exports_enc
index 1d9340c..99b1bfa 100644
--- a/vpx/exports_enc
+++ b/vpx/exports_enc
@@ -20,3 +20,4 @@
text vpx_svc_set_options
text vpx_svc_set_quantizers
text vpx_svc_set_scale_factors
+text vpx_svc_get_layer_resolution
diff --git a/vpxenc.c b/vpxenc.c
index d0ed9b5..4c933ce 100644
--- a/vpxenc.c
+++ b/vpxenc.c
@@ -26,7 +26,6 @@
#include "third_party/libyuv/include/libyuv/scale.h"
#include "./args.h"
-#include "./ivfdec.h"
#include "./ivfenc.h"
#if CONFIG_VP8_ENCODER || CONFIG_VP9_ENCODER
@@ -126,13 +125,19 @@
return !shortread;
}
-int file_is_y4m(FILE *infile, y4m_input *y4m, const char detect[4]) {
+int file_is_y4m(const char detect[4]) {
if (memcmp(detect, "YUV4", 4) == 0) {
return 1;
}
return 0;
}
+int fourcc_is_ivf(const char detect[4]) {
+ if (memcmp(detect, "DKIF", 4) == 0) {
+ return 1;
+ }
+ return 0;
+}
/* Murmur hash derived from public domain reference implementation at
* http:// sites.google.com/site/murmurhash/
@@ -1044,7 +1049,7 @@
input->detect.position = 0;
if (input->detect.buf_read == 4
- && file_is_y4m(input->file, &input->y4m, input->detect.buf)) {
+ && file_is_y4m(input->detect.buf)) {
if (y4m_input_open(&input->y4m, input->file, input->detect.buf, 4,
input->only_i420) >= 0) {
input->file_type = FILE_TYPE_Y4M;
@@ -1055,7 +1060,7 @@
input->use_i420 = 0;
} else
fatal("Unsupported Y4M stream.");
- } else if (input->detect.buf_read == 4 && file_is_ivf(input)) {
+ } else if (input->detect.buf_read == 4 && fourcc_is_ivf(input->detect.buf)) {
fatal("IVF is not supported as input.");
} else {
input->file_type = FILE_TYPE_RAW;
diff --git a/warnings.c b/warnings.c
index f76d706..a9c7d04 100644
--- a/warnings.c
+++ b/warnings.c
@@ -71,14 +71,6 @@
return c == 'y';
}
-static void check_lag_in_frames_realtime_deadline(
- int lag_in_frames,
- int deadline,
- struct WarningList *warning_list) {
- if (deadline == VPX_DL_REALTIME && lag_in_frames != 0)
- add_warning(lag_in_frames_with_realtime, warning_list);
-}
-
static void check_quantizer(int min_q, int max_q,
struct WarningList *warning_list) {
const int lossless = min_q == 0 && max_q == 0;
@@ -88,7 +80,7 @@
void check_encoder_config(int disable_prompt,
const struct VpxEncoderConfig *global_config,
- const struct vpx_codec_enc_cfg *stream_config) {
+ struct vpx_codec_enc_cfg *stream_config) {
int num_warnings = 0;
struct WarningListNode *warning = NULL;
struct WarningList warning_list = {0};
@@ -96,9 +88,9 @@
check_quantizer(stream_config->rc_min_quantizer,
stream_config->rc_max_quantizer,
&warning_list);
- check_lag_in_frames_realtime_deadline(stream_config->g_lag_in_frames,
- global_config->deadline,
- &warning_list);
+
+ if (global_config->deadline == VPX_DL_REALTIME)
+ stream_config->g_lag_in_frames = 0;
/* Count and print warnings. */
for (warning = warning_list.warning_node;
diff --git a/warnings.h b/warnings.h
index ac3a4b6..90b34c8 100644
--- a/warnings.h
+++ b/warnings.h
@@ -20,6 +20,6 @@
*/
void check_encoder_config(int disable_prompt,
const struct VpxEncoderConfig *global_config,
- const struct vpx_codec_enc_cfg *stream_config);
+ struct vpx_codec_enc_cfg *stream_config);
#endif // WARNINGS_H_