summaryrefslogtreecommitdiff
path: root/vp9
diff options
context:
space:
mode:
Diffstat (limited to 'vp9')
-rw-r--r--vp9/common/vp9_onyxc_int.h12
-rw-r--r--vp9/encoder/vp9_encoder.c189
-rw-r--r--vp9/encoder/vp9_encoder.h46
-rw-r--r--vp9/encoder/vp9_ext_ratectrl.c151
-rw-r--r--vp9/encoder/vp9_ext_ratectrl.h48
-rw-r--r--vp9/encoder/vp9_firstpass.c4
-rw-r--r--vp9/encoder/vp9_ratectrl.c9
-rw-r--r--vp9/encoder/vp9_ratectrl.h3
-rw-r--r--vp9/encoder/vp9_speed_features.c4
-rw-r--r--vp9/encoder/vp9_svc_layercontext.c1
-rw-r--r--vp9/encoder/vp9_svc_layercontext.h1
-rw-r--r--vp9/simple_encode.cc150
-rw-r--r--vp9/simple_encode.h86
-rw-r--r--vp9/vp9_cx_iface.c179
-rw-r--r--vp9/vp9_cx_iface.h2
-rw-r--r--vp9/vp9cx.mk2
16 files changed, 733 insertions, 154 deletions
diff --git a/vp9/common/vp9_onyxc_int.h b/vp9/common/vp9_onyxc_int.h
index 6f9c6985f..1cfc12f6f 100644
--- a/vp9/common/vp9_onyxc_int.h
+++ b/vp9/common/vp9_onyxc_int.h
@@ -75,12 +75,10 @@ typedef struct {
// TODO(angiebird): Set frame_index/frame_coding_index on the decoder side
// properly.
- int frame_index; // Display order in the video, it's equivalent to the
- // show_idx defined in EncodeFrameInfo.
-#if CONFIG_RATE_CTRL
+ int frame_index; // Display order in the video, it's equivalent to the
+ // show_idx defined in EncodeFrameInfo.
int frame_coding_index; // The coding order (starting from zero) of this
// frame.
-#endif // CONFIG_RATE_CTRL
vpx_codec_frame_buffer_t raw_frame_buffer;
YV12_BUFFER_CONFIG buf;
} RefCntBuffer;
@@ -240,13 +238,11 @@ typedef struct VP9Common {
// TODO(angiebird): current_video_frame/current_frame_coding_index into a
// structure
unsigned int current_video_frame;
-#if CONFIG_RATE_CTRL
// Each show or no show frame is assigned with a coding index based on its
// coding order (starting from zero).
// Current frame's coding index.
int current_frame_coding_index;
-#endif
BITSTREAM_PROFILE profile;
// VPX_BITS_8 in profile 0 or 1, VPX_BITS_10 or VPX_BITS_12 in profile 2 or 3.
@@ -276,9 +272,7 @@ typedef struct VP9Common {
static INLINE void init_frame_indexes(VP9_COMMON *cm) {
cm->current_video_frame = 0;
-#if CONFIG_RATE_CTRL
cm->current_frame_coding_index = 0;
-#endif // CONFIG_RATE_CTRL
}
static INLINE void update_frame_indexes(VP9_COMMON *cm, int show_frame) {
@@ -287,9 +281,7 @@ static INLINE void update_frame_indexes(VP9_COMMON *cm, int show_frame) {
// update not a real frame
++cm->current_video_frame;
}
-#if CONFIG_RATE_CTRL
++cm->current_frame_coding_index;
-#endif // CONFIG_RATE_CTRL
}
typedef struct {
diff --git a/vp9/encoder/vp9_encoder.c b/vp9/encoder/vp9_encoder.c
index 048559061..37f644501 100644
--- a/vp9/encoder/vp9_encoder.c
+++ b/vp9/encoder/vp9_encoder.c
@@ -1025,6 +1025,7 @@ static void dealloc_compressor_data(VP9_COMP *cpi) {
free_partition_info(cpi);
free_motion_vector_info(cpi);
free_fp_motion_vector_info(cpi);
+ free_tpl_stats_info(cpi);
#endif
vp9_free_ref_frame_buffers(cm->buffer_pool);
@@ -2463,6 +2464,8 @@ VP9_COMP *vp9_create_compressor(const VP9EncoderConfig *oxcf,
cpi->allow_encode_breakout = ENCODE_BREAKOUT_ENABLED;
+ vp9_extrc_init(&cpi->ext_ratectrl);
+
#if !CONFIG_REALTIME_ONLY
if (oxcf->pass == 1) {
vp9_init_first_pass(cpi);
@@ -2663,6 +2666,7 @@ VP9_COMP *vp9_create_compressor(const VP9EncoderConfig *oxcf,
partition_info_init(cpi);
motion_vector_info_init(cpi);
fp_motion_vector_info_init(cpi);
+ tpl_stats_info_init(cpi);
#endif
return cpi;
@@ -2834,6 +2838,8 @@ void vp9_remove_compressor(VP9_COMP *cpi) {
}
#endif
+ vp9_extrc_delete(&cpi->ext_ratectrl);
+
vp9_remove_common(cm);
vp9_free_ref_frame_buffers(cm->buffer_pool);
#if CONFIG_VP9_POSTPROC
@@ -3316,6 +3322,13 @@ static void loopfilter_frame(VP9_COMP *cpi, VP9_COMMON *cm) {
return;
}
+ if (cpi->loopfilter_ctrl == NO_LOOPFILTER ||
+ (!is_reference_frame && cpi->loopfilter_ctrl == LOOPFILTER_REFERENCE)) {
+ lf->filter_level = 0;
+ vpx_extend_frame_inner_borders(cm->frame_to_show);
+ return;
+ }
+
if (xd->lossless) {
lf->filter_level = 0;
lf->last_filt_level = 0;
@@ -4195,6 +4208,27 @@ static int encode_without_recode_loop(VP9_COMP *cpi, size_t *size,
return 1;
}
+static int get_ref_frame_flags(const VP9_COMP *cpi) {
+ const int *const map = cpi->common.ref_frame_map;
+ const int gold_is_last = map[cpi->gld_fb_idx] == map[cpi->lst_fb_idx];
+ const int alt_is_last = map[cpi->alt_fb_idx] == map[cpi->lst_fb_idx];
+ const int gold_is_alt = map[cpi->gld_fb_idx] == map[cpi->alt_fb_idx];
+ int flags = VP9_ALT_FLAG | VP9_GOLD_FLAG | VP9_LAST_FLAG;
+
+ if (gold_is_last) flags &= ~VP9_GOLD_FLAG;
+
+ if (cpi->rc.frames_till_gf_update_due == INT_MAX &&
+ (cpi->svc.number_temporal_layers == 1 &&
+ cpi->svc.number_spatial_layers == 1))
+ flags &= ~VP9_GOLD_FLAG;
+
+ if (alt_is_last) flags &= ~VP9_ALT_FLAG;
+
+ if (gold_is_alt) flags &= ~VP9_ALT_FLAG;
+
+ return flags;
+}
+
#if !CONFIG_REALTIME_ONLY
#define MAX_QSTEP_ADJ 4
static int get_qstep_adj(int rate_excess, int rate_limit) {
@@ -4468,6 +4502,19 @@ static void encode_with_recode_loop(VP9_COMP *cpi, size_t *size, uint8_t *dest
q = cpi->encode_command.external_quantize_index;
}
#endif
+ if (cpi->ext_ratectrl.ready) {
+ const GF_GROUP *gf_group = &cpi->twopass.gf_group;
+ vpx_rc_encodeframe_decision_t encode_frame_decision;
+ FRAME_UPDATE_TYPE update_type = gf_group->update_type[gf_group->index];
+ const int ref_frame_flags = get_ref_frame_flags(cpi);
+ RefCntBuffer *ref_frame_bufs[MAX_INTER_REF_FRAMES];
+ get_ref_frame_bufs(cpi, ref_frame_bufs);
+ vp9_extrc_get_encodeframe_decision(
+ &cpi->ext_ratectrl, cm->current_video_frame,
+ cm->current_frame_coding_index, gf_group->index, update_type,
+ ref_frame_bufs, ref_frame_flags, &encode_frame_decision);
+ q = encode_frame_decision.q_index;
+ }
vp9_set_quantizer(cpi, q);
@@ -4507,6 +4554,9 @@ static void encode_with_recode_loop(VP9_COMP *cpi, size_t *size, uint8_t *dest
if (frame_over_shoot_limit == 0) frame_over_shoot_limit = 1;
}
+ if (cpi->ext_ratectrl.ready) {
+ break;
+ }
#if CONFIG_RATE_CTRL
// This part needs to be after save_coding_context() because
// restore_coding_context will be called in the end of this function.
@@ -4751,27 +4801,6 @@ static void encode_with_recode_loop(VP9_COMP *cpi, size_t *size, uint8_t *dest
}
#endif // !CONFIG_REALTIME_ONLY
-static int get_ref_frame_flags(const VP9_COMP *cpi) {
- const int *const map = cpi->common.ref_frame_map;
- const int gold_is_last = map[cpi->gld_fb_idx] == map[cpi->lst_fb_idx];
- const int alt_is_last = map[cpi->alt_fb_idx] == map[cpi->lst_fb_idx];
- const int gold_is_alt = map[cpi->gld_fb_idx] == map[cpi->alt_fb_idx];
- int flags = VP9_ALT_FLAG | VP9_GOLD_FLAG | VP9_LAST_FLAG;
-
- if (gold_is_last) flags &= ~VP9_GOLD_FLAG;
-
- if (cpi->rc.frames_till_gf_update_due == INT_MAX &&
- (cpi->svc.number_temporal_layers == 1 &&
- cpi->svc.number_spatial_layers == 1))
- flags &= ~VP9_GOLD_FLAG;
-
- if (alt_is_last) flags &= ~VP9_ALT_FLAG;
-
- if (gold_is_alt) flags &= ~VP9_ALT_FLAG;
-
- return flags;
-}
-
static void set_ext_overrides(VP9_COMP *cpi) {
// Overrides the defaults with the externally supplied values with
// vp9_update_reference() and vp9_update_entropy() calls
@@ -5076,9 +5105,7 @@ static void set_frame_index(VP9_COMP *cpi, VP9_COMMON *cm) {
const GF_GROUP *const gf_group = &cpi->twopass.gf_group;
ref_buffer->frame_index =
cm->current_video_frame + gf_group->arf_src_offset[gf_group->index];
-#if CONFIG_RATE_CTRL
ref_buffer->frame_coding_index = cm->current_frame_coding_index;
-#endif // CONFIG_RATE_CTRL
}
}
@@ -5281,6 +5308,7 @@ static void update_encode_frame_result(
#if CONFIG_RATE_CTRL
const PARTITION_INFO *partition_info,
const MOTION_VECTOR_INFO *motion_vector_info,
+ const TplDepStats *tpl_stats_info,
#endif // CONFIG_RATE_CTRL
ENCODE_FRAME_RESULT *encode_frame_result);
#endif // !CONFIG_REALTIME_ONLY
@@ -5456,6 +5484,13 @@ static void encode_frame_to_data_rate(
// build the bitstream
vp9_pack_bitstream(cpi, dest, size);
+ {
+ const RefCntBuffer *coded_frame_buf =
+ get_ref_cnt_buffer(cm, cm->new_fb_idx);
+ vp9_extrc_update_encodeframe_result(
+ &cpi->ext_ratectrl, (*size) << 3, cpi->Source, &coded_frame_buf->buf,
+ cm->bit_depth, cpi->oxcf.input_bit_depth);
+ }
#if CONFIG_REALTIME_ONLY
(void)encode_frame_result;
assert(encode_frame_result == NULL);
@@ -5486,9 +5521,9 @@ static void encode_frame_to_data_rate(
ref_frame_flags,
cpi->twopass.gf_group.update_type[cpi->twopass.gf_group.index],
cpi->Source, coded_frame_buf, ref_frame_bufs, vp9_get_quantizer(cpi),
- cpi->oxcf.input_bit_depth, cm->bit_depth, cpi->td.counts,
+ cm->bit_depth, cpi->oxcf.input_bit_depth, cpi->td.counts,
#if CONFIG_RATE_CTRL
- cpi->partition_info, cpi->motion_vector_info,
+ cpi->partition_info, cpi->motion_vector_info, cpi->tpl_stats_info,
#endif // CONFIG_RATE_CTRL
encode_frame_result);
}
@@ -5643,6 +5678,11 @@ static void Pass2Encode(VP9_COMP *cpi, size_t *size, uint8_t *dest,
unsigned int *frame_flags,
ENCODE_FRAME_RESULT *encode_frame_result) {
cpi->allow_encode_breakout = ENCODE_BREAKOUT_ENABLED;
+
+ if (cpi->common.current_frame_coding_index == 0) {
+ vp9_extrc_send_firstpass_stats(&cpi->ext_ratectrl,
+ &cpi->twopass.first_pass_info);
+ }
#if CONFIG_MISMATCH_DEBUG
mismatch_move_frame_idx_w();
#endif
@@ -7334,6 +7374,48 @@ static void free_tpl_buffer(VP9_COMP *cpi) {
}
}
+#if CONFIG_RATE_CTRL
+static void accumulate_frame_tpl_stats(VP9_COMP *cpi) {
+ VP9_COMMON *const cm = &cpi->common;
+ const GF_GROUP *gf_group = &cpi->twopass.gf_group;
+ int show_frame_count = 0;
+ int frame_idx;
+ // Accumulate tpl stats for each frame in the current group of picture.
+ for (frame_idx = 1; frame_idx < gf_group->gf_group_size; ++frame_idx) {
+ TplDepFrame *tpl_frame = &cpi->tpl_stats[frame_idx];
+ TplDepStats *tpl_stats = tpl_frame->tpl_stats_ptr;
+ const int tpl_stride = tpl_frame->stride;
+ int64_t intra_cost_base = 0;
+ int64_t inter_cost_base = 0;
+ int64_t mc_dep_cost_base = 0;
+ int64_t mc_ref_cost_base = 0;
+ int64_t mc_flow_base = 0;
+ int row, col;
+
+ if (!tpl_frame->is_valid) continue;
+
+ for (row = 0; row < cm->mi_rows && tpl_frame->is_valid; ++row) {
+ for (col = 0; col < cm->mi_cols; ++col) {
+ TplDepStats *this_stats = &tpl_stats[row * tpl_stride + col];
+ intra_cost_base += this_stats->intra_cost;
+ inter_cost_base += this_stats->inter_cost;
+ mc_dep_cost_base += this_stats->mc_dep_cost;
+ mc_ref_cost_base += this_stats->mc_ref_cost;
+ mc_flow_base += this_stats->mc_flow;
+ }
+ }
+
+ cpi->tpl_stats_info[show_frame_count].intra_cost = intra_cost_base;
+ cpi->tpl_stats_info[show_frame_count].inter_cost = inter_cost_base;
+ cpi->tpl_stats_info[show_frame_count].mc_dep_cost = mc_dep_cost_base;
+ cpi->tpl_stats_info[show_frame_count].mc_ref_cost = mc_ref_cost_base;
+ cpi->tpl_stats_info[show_frame_count].mc_flow = mc_flow_base;
+
+ ++show_frame_count;
+ }
+}
+#endif // CONFIG_RATE_CTRL
+
static void setup_tpl_stats(VP9_COMP *cpi) {
GF_PICTURE gf_picture[MAX_ARF_GOP_SIZE];
const GF_GROUP *gf_group = &cpi->twopass.gf_group;
@@ -7356,6 +7438,34 @@ static void setup_tpl_stats(VP9_COMP *cpi) {
dump_tpl_stats(cpi, tpl_group_frames, gf_group, gf_picture, cpi->tpl_bsize);
#endif // DUMP_TPL_STATS
#endif // CONFIG_NON_GREEDY_MV
+
+#if CONFIG_RATE_CTRL
+ accumulate_frame_tpl_stats(cpi);
+#endif // CONFIG_RATE_CTRL
+}
+
+void vp9_get_ref_frame_info(FRAME_UPDATE_TYPE update_type, int ref_frame_flags,
+ RefCntBuffer *ref_frame_bufs[MAX_INTER_REF_FRAMES],
+ int *ref_frame_coding_indexes,
+ int *ref_frame_valid_list) {
+ if (update_type != KF_UPDATE) {
+ const VP9_REFFRAME inter_ref_flags[MAX_INTER_REF_FRAMES] = { VP9_LAST_FLAG,
+ VP9_GOLD_FLAG,
+ VP9_ALT_FLAG };
+ int i;
+ for (i = 0; i < MAX_INTER_REF_FRAMES; ++i) {
+ assert(ref_frame_bufs[i] != NULL);
+ ref_frame_coding_indexes[i] = ref_frame_bufs[i]->frame_coding_index;
+ ref_frame_valid_list[i] = (ref_frame_flags & inter_ref_flags[i]) != 0;
+ }
+ } else {
+ // No reference frame is available when this is a key frame.
+ int i;
+ for (i = 0; i < MAX_INTER_REF_FRAMES; ++i) {
+ ref_frame_coding_indexes[i] = -1;
+ ref_frame_valid_list[i] = 0;
+ }
+ }
}
#if !CONFIG_REALTIME_ONLY
@@ -7505,6 +7615,7 @@ static void yv12_buffer_to_image_buffer(const YV12_BUFFER_CONFIG *yv12_buffer,
}
}
#endif // CONFIG_RATE_CTRL
+
static void update_encode_frame_result(
int ref_frame_flags, FRAME_UPDATE_TYPE update_type,
const YV12_BUFFER_CONFIG *source_frame, const RefCntBuffer *coded_frame_buf,
@@ -7513,12 +7624,13 @@ static void update_encode_frame_result(
#if CONFIG_RATE_CTRL
const PARTITION_INFO *partition_info,
const MOTION_VECTOR_INFO *motion_vector_info,
+ const TplDepStats *tpl_stats_info,
#endif // CONFIG_RATE_CTRL
ENCODE_FRAME_RESULT *encode_frame_result) {
#if CONFIG_RATE_CTRL
PSNR_STATS psnr;
#if CONFIG_VP9_HIGHBITDEPTH
- vpx_calc_highbd_psnr(source_frame, coded_frame_buf->buf, &psnr, bit_depth,
+ vpx_calc_highbd_psnr(source_frame, &coded_frame_buf->buf, &psnr, bit_depth,
input_bit_depth);
#else // CONFIG_VP9_HIGHBITDEPTH
(void)bit_depth;
@@ -7527,31 +7639,16 @@ static void update_encode_frame_result(
#endif // CONFIG_VP9_HIGHBITDEPTH
encode_frame_result->frame_coding_index = coded_frame_buf->frame_coding_index;
- if (update_type != KF_UPDATE) {
- const VP9_REFFRAME inter_ref_flags[MAX_INTER_REF_FRAMES] = { VP9_LAST_FLAG,
- VP9_GOLD_FLAG,
- VP9_ALT_FLAG };
- int i;
- for (i = 0; i < MAX_INTER_REF_FRAMES; ++i) {
- assert(ref_frame_bufs[i] != NULL);
- encode_frame_result->ref_frame_coding_indexes[i] =
- ref_frame_bufs[i]->frame_coding_index;
- encode_frame_result->ref_frame_valid_list[i] =
- (ref_frame_flags & inter_ref_flags[i]) != 0;
- }
- } else {
- // No reference frame is available when this is a key frame.
- int i;
- for (i = 0; i < MAX_INTER_REF_FRAMES; ++i) {
- encode_frame_result->ref_frame_coding_indexes[i] = -1;
- encode_frame_result->ref_frame_valid_list[i] = 0;
- }
- }
+ vp9_get_ref_frame_info(update_type, ref_frame_flags, ref_frame_bufs,
+ encode_frame_result->ref_frame_coding_indexes,
+ encode_frame_result->ref_frame_valid_list);
+
encode_frame_result->psnr = psnr.psnr[0];
encode_frame_result->sse = psnr.sse[0];
copy_frame_counts(counts, &encode_frame_result->frame_counts);
encode_frame_result->partition_info = partition_info;
encode_frame_result->motion_vector_info = motion_vector_info;
+ encode_frame_result->tpl_stats_info = tpl_stats_info;
if (encode_frame_result->coded_frame.allocated) {
yv12_buffer_to_image_buffer(&coded_frame_buf->buf,
&encode_frame_result->coded_frame);
diff --git a/vp9/encoder/vp9_encoder.h b/vp9/encoder/vp9_encoder.h
index 26d35cccf..8763a5e78 100644
--- a/vp9/encoder/vp9_encoder.h
+++ b/vp9/encoder/vp9_encoder.h
@@ -15,6 +15,7 @@
#include "./vpx_config.h"
#include "vpx/internal/vpx_codec_internal.h"
+#include "vpx/vpx_ext_ratectrl.h"
#include "vpx/vp8cx.h"
#if CONFIG_INTERNAL_STATS
#include "vpx_dsp/ssim.h"
@@ -38,6 +39,7 @@
#include "vp9/encoder/vp9_context_tree.h"
#include "vp9/encoder/vp9_encodemb.h"
#include "vp9/encoder/vp9_ethread.h"
+#include "vp9/encoder/vp9_ext_ratectrl.h"
#include "vp9/encoder/vp9_firstpass.h"
#include "vp9/encoder/vp9_job_queue.h"
#include "vp9/encoder/vp9_lookahead.h"
@@ -147,6 +149,12 @@ typedef enum {
kVeryHighSad = 6,
} CONTENT_STATE_SB;
+typedef enum {
+ LOOPFILTER_ALL = 0,
+ LOOPFILTER_REFERENCE = 1, // Disable loopfilter on non reference frames.
+ NO_LOOPFILTER = 2, // Disable loopfilter on all frames.
+} LOOPFILTER_CONTROL;
+
typedef struct VP9EncoderConfig {
BITSTREAM_PROFILE profile;
vpx_bit_depth_t bit_depth; // Codec bit-depth.
@@ -958,14 +966,18 @@ typedef struct VP9_COMP {
int multi_layer_arf;
vpx_roi_map_t roi;
+
+ LOOPFILTER_CONTROL loopfilter_ctrl;
#if CONFIG_RATE_CTRL
ENCODE_COMMAND encode_command;
PARTITION_INFO *partition_info;
MOTION_VECTOR_INFO *motion_vector_info;
MOTION_VECTOR_INFO *fp_motion_vector_info;
+ TplDepStats *tpl_stats_info;
RATE_QSTEP_MODEL rq_model[ENCODE_FRAME_TYPES];
#endif
+ EXT_RATECTRL ext_ratectrl;
} VP9_COMP;
#if CONFIG_RATE_CTRL
@@ -1018,6 +1030,23 @@ static INLINE void free_motion_vector_info(struct VP9_COMP *cpi) {
cpi->motion_vector_info = NULL;
}
+// Allocates memory for the tpl stats information.
+// Only called once in vp9_create_compressor().
+static INLINE void tpl_stats_info_init(struct VP9_COMP *cpi) {
+ VP9_COMMON *const cm = &cpi->common;
+ CHECK_MEM_ERROR(
+ cm, cpi->tpl_stats_info,
+ (TplDepStats *)vpx_calloc(MAX_LAG_BUFFERS, sizeof(TplDepStats)));
+ memset(cpi->tpl_stats_info, 0, MAX_LAG_BUFFERS * sizeof(TplDepStats));
+}
+
+// Frees memory of the tpl stats information.
+// Only called once in dealloc_compressor_data().
+static INLINE void free_tpl_stats_info(struct VP9_COMP *cpi) {
+ vpx_free(cpi->tpl_stats_info);
+ cpi->tpl_stats_info = NULL;
+}
+
// Allocates memory for the first pass motion vector information.
// The unit size is each 16x16 block.
// Only called once in vp9_create_compressor().
@@ -1025,12 +1054,19 @@ static INLINE void fp_motion_vector_info_init(struct VP9_COMP *cpi) {
VP9_COMMON *const cm = &cpi->common;
const int unit_width = get_num_unit_16x16(cpi->frame_info.frame_width);
const int unit_height = get_num_unit_16x16(cpi->frame_info.frame_height);
- int i;
CHECK_MEM_ERROR(cm, cpi->fp_motion_vector_info,
(MOTION_VECTOR_INFO *)vpx_calloc(unit_width * unit_height,
sizeof(MOTION_VECTOR_INFO)));
+}
+
+static INLINE void fp_motion_vector_info_reset(
+ int frame_width, int frame_height,
+ MOTION_VECTOR_INFO *fp_motion_vector_info) {
+ const int unit_width = get_num_unit_16x16(frame_width);
+ const int unit_height = get_num_unit_16x16(frame_height);
+ int i;
for (i = 0; i < unit_width * unit_height; ++i) {
- reset_mv_info(cpi->fp_motion_vector_info + i);
+ reset_mv_info(fp_motion_vector_info + i);
}
}
@@ -1073,6 +1109,7 @@ typedef struct ENCODE_FRAME_RESULT {
FRAME_COUNTS frame_counts;
const PARTITION_INFO *partition_info;
const MOTION_VECTOR_INFO *motion_vector_info;
+ const TplDepStats *tpl_stats_info;
IMAGE_BUFFER coded_frame;
RATE_QINDEX_HISTORY rq_history;
#endif // CONFIG_RATE_CTRL
@@ -1250,6 +1287,11 @@ void vp9_scale_references(VP9_COMP *cpi);
void vp9_update_reference_frames(VP9_COMP *cpi);
+void vp9_get_ref_frame_info(FRAME_UPDATE_TYPE update_type, int ref_frame_flags,
+ RefCntBuffer *ref_frame_bufs[MAX_INTER_REF_FRAMES],
+ int *ref_frame_coding_indexes,
+ int *ref_frame_valid_list);
+
void vp9_set_high_precision_mv(VP9_COMP *cpi, int allow_high_precision_mv);
YV12_BUFFER_CONFIG *vp9_svc_twostage_scale(
diff --git a/vp9/encoder/vp9_ext_ratectrl.c b/vp9/encoder/vp9_ext_ratectrl.c
new file mode 100644
index 000000000..a6a3e21d3
--- /dev/null
+++ b/vp9/encoder/vp9_ext_ratectrl.c
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2020 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 "vp9/encoder/vp9_ext_ratectrl.h"
+#include "vp9/encoder/vp9_encoder.h"
+#include "vp9/common/vp9_common.h"
+#include "vpx_dsp/psnr.h"
+
+void vp9_extrc_init(EXT_RATECTRL *ext_ratectrl) { vp9_zero(*ext_ratectrl); }
+
+void vp9_extrc_create(vpx_rc_funcs_t funcs, vpx_rc_config_t ratectrl_config,
+ EXT_RATECTRL *ext_ratectrl) {
+ vpx_rc_firstpass_stats_t *rc_firstpass_stats;
+ vp9_extrc_delete(ext_ratectrl);
+ ext_ratectrl->funcs = funcs;
+ ext_ratectrl->ratectrl_config = ratectrl_config;
+ ext_ratectrl->funcs.create_model(ext_ratectrl->funcs.priv,
+ &ext_ratectrl->ratectrl_config,
+ &ext_ratectrl->model);
+ rc_firstpass_stats = &ext_ratectrl->rc_firstpass_stats;
+ rc_firstpass_stats->num_frames = ratectrl_config.show_frame_count;
+ rc_firstpass_stats->frame_stats =
+ vpx_malloc(sizeof(*rc_firstpass_stats->frame_stats) *
+ rc_firstpass_stats->num_frames);
+ ext_ratectrl->ready = 1;
+}
+
+void vp9_extrc_delete(EXT_RATECTRL *ext_ratectrl) {
+ if (ext_ratectrl->ready) {
+ ext_ratectrl->funcs.delete_model(ext_ratectrl->model);
+ vpx_free(ext_ratectrl->rc_firstpass_stats.frame_stats);
+ }
+ vp9_extrc_init(ext_ratectrl);
+}
+
+static void gen_rc_firstpass_stats(const FIRSTPASS_STATS *stats,
+ vpx_rc_frame_stats_t *rc_frame_stats) {
+ rc_frame_stats->frame = stats->frame;
+ rc_frame_stats->weight = stats->weight;
+ rc_frame_stats->intra_error = stats->intra_error;
+ rc_frame_stats->coded_error = stats->coded_error;
+ rc_frame_stats->sr_coded_error = stats->sr_coded_error;
+ rc_frame_stats->frame_noise_energy = stats->frame_noise_energy;
+ rc_frame_stats->pcnt_inter = stats->pcnt_inter;
+ rc_frame_stats->pcnt_motion = stats->pcnt_motion;
+ rc_frame_stats->pcnt_second_ref = stats->pcnt_second_ref;
+ rc_frame_stats->pcnt_neutral = stats->pcnt_neutral;
+ rc_frame_stats->pcnt_intra_low = stats->pcnt_intra_low;
+ rc_frame_stats->pcnt_intra_high = stats->pcnt_intra_high;
+ rc_frame_stats->intra_skip_pct = stats->intra_skip_pct;
+ rc_frame_stats->intra_smooth_pct = stats->intra_smooth_pct;
+ rc_frame_stats->inactive_zone_rows = stats->inactive_zone_rows;
+ rc_frame_stats->inactive_zone_cols = stats->inactive_zone_cols;
+ rc_frame_stats->MVr = stats->MVr;
+ rc_frame_stats->mvr_abs = stats->mvr_abs;
+ rc_frame_stats->MVc = stats->MVc;
+ rc_frame_stats->mvc_abs = stats->mvc_abs;
+ rc_frame_stats->MVrv = stats->MVrv;
+ rc_frame_stats->MVcv = stats->MVcv;
+ rc_frame_stats->mv_in_out_count = stats->mv_in_out_count;
+ rc_frame_stats->duration = stats->duration;
+ rc_frame_stats->count = stats->count;
+}
+
+void vp9_extrc_send_firstpass_stats(EXT_RATECTRL *ext_ratectrl,
+ const FIRST_PASS_INFO *first_pass_info) {
+ if (ext_ratectrl->ready) {
+ vpx_rc_firstpass_stats_t *rc_firstpass_stats =
+ &ext_ratectrl->rc_firstpass_stats;
+ int i;
+ assert(rc_firstpass_stats->num_frames == first_pass_info->num_frames);
+ for (i = 0; i < rc_firstpass_stats->num_frames; ++i) {
+ gen_rc_firstpass_stats(&first_pass_info->stats[i],
+ &rc_firstpass_stats->frame_stats[i]);
+ }
+ ext_ratectrl->funcs.send_firstpass_stats(ext_ratectrl->model,
+ rc_firstpass_stats);
+ }
+}
+
+static int extrc_get_frame_type(FRAME_UPDATE_TYPE update_type) {
+ // TODO(angiebird): Add unit test to make sure this function behaves like
+ // get_frame_type_from_update_type()
+ // TODO(angiebird): Merge this function with get_frame_type_from_update_type()
+ switch (update_type) {
+ case KF_UPDATE: return 0; // kFrameTypeKey;
+ case ARF_UPDATE: return 2; // kFrameTypeAltRef;
+ case GF_UPDATE: return 4; // kFrameTypeGolden;
+ case OVERLAY_UPDATE: return 3; // kFrameTypeOverlay;
+ case LF_UPDATE: return 1; // kFrameTypeInter;
+ default:
+ fprintf(stderr, "Unsupported update_type %d\n", update_type);
+ abort();
+ return 1;
+ }
+}
+
+void vp9_extrc_get_encodeframe_decision(
+ EXT_RATECTRL *ext_ratectrl, int show_index, int coding_index, int gop_index,
+ FRAME_UPDATE_TYPE update_type,
+ RefCntBuffer *ref_frame_bufs[MAX_INTER_REF_FRAMES], int ref_frame_flags,
+ vpx_rc_encodeframe_decision_t *encode_frame_decision) {
+ if (ext_ratectrl->ready) {
+ vpx_rc_encodeframe_info_t encode_frame_info;
+ encode_frame_info.show_index = show_index;
+ encode_frame_info.coding_index = coding_index;
+ encode_frame_info.gop_index = gop_index;
+ encode_frame_info.frame_type = extrc_get_frame_type(update_type);
+
+ vp9_get_ref_frame_info(update_type, ref_frame_flags, ref_frame_bufs,
+ encode_frame_info.ref_frame_coding_indexes,
+ encode_frame_info.ref_frame_valid_list);
+
+ ext_ratectrl->funcs.get_encodeframe_decision(
+ ext_ratectrl->model, &encode_frame_info, encode_frame_decision);
+ }
+}
+
+void vp9_extrc_update_encodeframe_result(EXT_RATECTRL *ext_ratectrl,
+ int64_t bit_count,
+ const YV12_BUFFER_CONFIG *source_frame,
+ const YV12_BUFFER_CONFIG *coded_frame,
+ uint32_t bit_depth,
+ uint32_t input_bit_depth) {
+ if (ext_ratectrl->ready) {
+ PSNR_STATS psnr;
+ vpx_rc_encodeframe_result_t encode_frame_result;
+ encode_frame_result.bit_count = bit_count;
+ encode_frame_result.pixel_count =
+ source_frame->y_width * source_frame->y_height +
+ 2 * source_frame->uv_width * source_frame->uv_height;
+#if CONFIG_VP9_HIGHBITDEPTH
+ vpx_calc_highbd_psnr(source_frame, coded_frame, &psnr, bit_depth,
+ input_bit_depth);
+#else
+ (void)bit_depth;
+ (void)input_bit_depth;
+ vpx_calc_psnr(source_frame, coded_frame, &psnr);
+#endif
+ encode_frame_result.sse = psnr.sse[0];
+ ext_ratectrl->funcs.update_encodeframe_result(ext_ratectrl->model,
+ &encode_frame_result);
+ }
+}
diff --git a/vp9/encoder/vp9_ext_ratectrl.h b/vp9/encoder/vp9_ext_ratectrl.h
new file mode 100644
index 000000000..6a86218da
--- /dev/null
+++ b/vp9/encoder/vp9_ext_ratectrl.h
@@ -0,0 +1,48 @@
+/*
+ * Copyright (c) 2020 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 VPX_VP9_ENCODER_VP9_EXT_RATECTRL_H_
+#define VPX_VP9_ENCODER_VP9_EXT_RATECTRL_H_
+
+#include "vpx/vpx_ext_ratectrl.h"
+#include "vp9/encoder/vp9_firstpass.h"
+
+typedef struct EXT_RATECTRL {
+ int ready;
+ vpx_rc_model_t model;
+ vpx_rc_funcs_t funcs;
+ vpx_rc_config_t ratectrl_config;
+ vpx_rc_firstpass_stats_t rc_firstpass_stats;
+} EXT_RATECTRL;
+
+void vp9_extrc_init(EXT_RATECTRL *ext_ratectrl);
+
+void vp9_extrc_create(vpx_rc_funcs_t funcs, vpx_rc_config_t ratectrl_config,
+ EXT_RATECTRL *ext_ratectrl);
+
+void vp9_extrc_delete(EXT_RATECTRL *ext_ratectrl);
+
+void vp9_extrc_send_firstpass_stats(EXT_RATECTRL *ext_ratectrl,
+ const FIRST_PASS_INFO *first_pass_info);
+
+void vp9_extrc_get_encodeframe_decision(
+ EXT_RATECTRL *ext_ratectrl, int show_index, int coding_index, int gop_index,
+ FRAME_UPDATE_TYPE update_type,
+ RefCntBuffer *ref_frame_bufs[MAX_INTER_REF_FRAMES], int ref_frame_flags,
+ vpx_rc_encodeframe_decision_t *encode_frame_decision);
+
+void vp9_extrc_update_encodeframe_result(EXT_RATECTRL *ext_ratectrl,
+ int64_t bit_count,
+ const YV12_BUFFER_CONFIG *source_frame,
+ const YV12_BUFFER_CONFIG *coded_frame,
+ uint32_t bit_depth,
+ uint32_t input_bit_depth);
+
+#endif // VPX_VP9_ENCODER_VP9_EXT_RATECTRL_H_
diff --git a/vp9/encoder/vp9_firstpass.c b/vp9/encoder/vp9_firstpass.c
index 384775507..de954f757 100644
--- a/vp9/encoder/vp9_firstpass.c
+++ b/vp9/encoder/vp9_firstpass.c
@@ -1388,7 +1388,9 @@ static void first_pass_encode(VP9_COMP *cpi, FIRSTPASS_DATA *fp_acc_data) {
vp9_tile_init(tile, cm, 0, 0);
#if CONFIG_RATE_CTRL
- fp_motion_vector_info_init(cpi);
+ fp_motion_vector_info_reset(cpi->frame_info.frame_width,
+ cpi->frame_info.frame_height,
+ cpi->fp_motion_vector_info);
#endif
for (mb_row = 0; mb_row < cm->mb_rows; ++mb_row) {
diff --git a/vp9/encoder/vp9_ratectrl.c b/vp9/encoder/vp9_ratectrl.c
index 9bb8d45d2..4b87ff2f0 100644
--- a/vp9/encoder/vp9_ratectrl.c
+++ b/vp9/encoder/vp9_ratectrl.c
@@ -441,6 +441,7 @@ void vp9_rc_init(const VP9EncoderConfig *oxcf, int pass, RATE_CONTROL *rc) {
rc->last_post_encode_dropped_scene_change = 0;
rc->use_post_encode_drop = 0;
rc->ext_use_post_encode_drop = 0;
+ rc->disable_overshoot_maxq_cbr = 0;
rc->arf_active_best_quality_adjustment_factor = 1.0;
rc->arf_increase_active_best_quality = 0;
rc->preserve_arf_as_gld = 0;
@@ -2704,18 +2705,18 @@ int vp9_resize_one_pass_cbr(VP9_COMP *cpi) {
// Force downsize based on per-frame-bandwidth, for extreme case,
// for HD input.
if (cpi->resize_state == ORIG && cm->width * cm->height >= 1280 * 720) {
- if (rc->avg_frame_bandwidth < (int)(300000 / 30)) {
+ if (rc->avg_frame_bandwidth < 300000 / 30) {
resize_action = DOWN_ONEHALF;
cpi->resize_state = ONE_HALF;
force_downsize_rate = 1;
- } else if (rc->avg_frame_bandwidth < (int)(400000 / 30)) {
+ } else if (rc->avg_frame_bandwidth < 400000 / 30) {
resize_action = ONEHALFONLY_RESIZE ? DOWN_ONEHALF : DOWN_THREEFOUR;
cpi->resize_state = ONEHALFONLY_RESIZE ? ONE_HALF : THREE_QUARTER;
force_downsize_rate = 1;
}
} else if (cpi->resize_state == THREE_QUARTER &&
cm->width * cm->height >= 960 * 540) {
- if (rc->avg_frame_bandwidth < (int)(300000 / 30)) {
+ if (rc->avg_frame_bandwidth < 300000 / 30) {
resize_action = DOWN_ONEHALF;
cpi->resize_state = ONE_HALF;
force_downsize_rate = 1;
@@ -3262,7 +3263,7 @@ int vp9_encodedframe_overshoot(VP9_COMP *cpi, int frame_size, int *q) {
int tl = 0;
int sl = 0;
SVC *svc = &cpi->svc;
- for (sl = 0; sl < svc->first_spatial_layer_to_encode; ++sl) {
+ for (sl = 0; sl < VPXMAX(1, svc->first_spatial_layer_to_encode); ++sl) {
for (tl = 0; tl < svc->number_temporal_layers; ++tl) {
const int layer =
LAYER_IDS_TO_IDX(sl, tl, svc->number_temporal_layers);
diff --git a/vp9/encoder/vp9_ratectrl.h b/vp9/encoder/vp9_ratectrl.h
index c5ffb153c..0120f90a0 100644
--- a/vp9/encoder/vp9_ratectrl.h
+++ b/vp9/encoder/vp9_ratectrl.h
@@ -195,7 +195,8 @@ typedef struct {
int use_post_encode_drop;
// External flag to enable post encode frame dropping, controlled by user.
int ext_use_post_encode_drop;
-
+ // Flag to disable CBR feature to increase Q on overshoot detection.
+ int disable_overshoot_maxq_cbr;
int damped_adjustment[RATE_FACTOR_LEVELS];
double arf_active_best_quality_adjustment_factor;
int arf_increase_active_best_quality;
diff --git a/vp9/encoder/vp9_speed_features.c b/vp9/encoder/vp9_speed_features.c
index 5bbe54923..585c9604c 100644
--- a/vp9/encoder/vp9_speed_features.c
+++ b/vp9/encoder/vp9_speed_features.c
@@ -621,7 +621,7 @@ static void set_rt_speed_feature_framesize_independent(
// increase in encoding time.
if (cpi->use_svc && svc->spatial_layer_id > 0) sf->nonrd_keyframe = 1;
if (cm->frame_type != KEY_FRAME && cpi->resize_state == ORIG &&
- cpi->oxcf.rc_mode == VPX_CBR) {
+ cpi->oxcf.rc_mode == VPX_CBR && !cpi->rc.disable_overshoot_maxq_cbr) {
if (cm->width * cm->height <= 352 * 288 && !cpi->use_svc &&
cpi->oxcf.content != VP9E_CONTENT_SCREEN)
sf->overshoot_detection_cbr_rt = RE_ENCODE_MAXQ;
@@ -668,7 +668,7 @@ static void set_rt_speed_feature_framesize_independent(
sf->base_mv_aggressive = 1;
}
if (cm->frame_type != KEY_FRAME && cpi->resize_state == ORIG &&
- cpi->oxcf.rc_mode == VPX_CBR)
+ cpi->oxcf.rc_mode == VPX_CBR && !cpi->rc.disable_overshoot_maxq_cbr)
sf->overshoot_detection_cbr_rt = FAST_DETECTION_MAXQ;
}
diff --git a/vp9/encoder/vp9_svc_layercontext.c b/vp9/encoder/vp9_svc_layercontext.c
index d85b3632c..b6c7c74e1 100644
--- a/vp9/encoder/vp9_svc_layercontext.c
+++ b/vp9/encoder/vp9_svc_layercontext.c
@@ -357,6 +357,7 @@ void vp9_restore_layer_context(VP9_COMP *const cpi) {
if (is_one_pass_cbr_svc(cpi) && lc->speed > 0) {
cpi->oxcf.speed = lc->speed;
}
+ cpi->loopfilter_ctrl = lc->loopfilter_ctrl;
// Reset the frames_since_key and frames_to_key counters to their values
// before the layer restore. Keep these defined for the stream (not layer).
if (cpi->svc.number_temporal_layers > 1 ||
diff --git a/vp9/encoder/vp9_svc_layercontext.h b/vp9/encoder/vp9_svc_layercontext.h
index e7d9712aa..b12e7e01a 100644
--- a/vp9/encoder/vp9_svc_layercontext.h
+++ b/vp9/encoder/vp9_svc_layercontext.h
@@ -71,6 +71,7 @@ typedef struct {
int actual_num_seg2_blocks;
int counter_encode_maxq_scene_change;
uint8_t speed;
+ int loopfilter_ctrl;
} LAYER_CONTEXT;
typedef struct SVC {
diff --git a/vp9/simple_encode.cc b/vp9/simple_encode.cc
index 46b25d1fd..d4eb0c669 100644
--- a/vp9/simple_encode.cc
+++ b/vp9/simple_encode.cc
@@ -90,12 +90,20 @@ static int img_read(vpx_image_t *img, FILE *file) {
return 1;
}
+// Assume every config in VP9EncoderConfig is less than 100 characters.
+#define ENCODE_CONFIG_BUF_SIZE 100
+struct EncodeConfig {
+ char name[ENCODE_CONFIG_BUF_SIZE];
+ char value[ENCODE_CONFIG_BUF_SIZE];
+};
+
class SimpleEncode::EncodeImpl {
public:
VP9_COMP *cpi;
vpx_img_fmt_t img_fmt;
vpx_image_t tmp_img;
std::vector<FIRSTPASS_STATS> first_pass_stats;
+ std::vector<EncodeConfig> encode_config_list;
};
static VP9_COMP *init_encoder(const VP9EncoderConfig *oxcf,
@@ -199,6 +207,24 @@ static void update_motion_vector_info(
}
}
+static void update_tpl_stats_info(const TplDepStats *input_tpl_stats_info,
+ const int show_frame_count,
+ TplStatsInfo *output_tpl_stats_info) {
+ int frame_idx;
+ for (frame_idx = 0; frame_idx < show_frame_count; ++frame_idx) {
+ output_tpl_stats_info[frame_idx].intra_cost =
+ input_tpl_stats_info[frame_idx].intra_cost;
+ output_tpl_stats_info[frame_idx].inter_cost =
+ input_tpl_stats_info[frame_idx].inter_cost;
+ output_tpl_stats_info[frame_idx].mc_flow =
+ input_tpl_stats_info[frame_idx].mc_flow;
+ output_tpl_stats_info[frame_idx].mc_dep_cost =
+ input_tpl_stats_info[frame_idx].mc_dep_cost;
+ output_tpl_stats_info[frame_idx].mc_ref_cost =
+ input_tpl_stats_info[frame_idx].mc_ref_cost;
+ }
+}
+
static void update_frame_counts(const FRAME_COUNTS *input_counts,
FrameCounts *output_counts) {
// Init array sizes.
@@ -478,6 +504,7 @@ static bool init_encode_frame_result(EncodeFrameResult *encode_frame_result,
encode_frame_result->num_cols_4x4);
encode_frame_result->motion_vector_info.resize(
encode_frame_result->num_rows_4x4 * encode_frame_result->num_cols_4x4);
+ encode_frame_result->tpl_stats_info.resize(MAX_LAG_BUFFERS);
if (encode_frame_result->coding_data.get() == nullptr) {
return false;
@@ -499,7 +526,7 @@ static void encode_frame_result_update_rq_history(
}
static void update_encode_frame_result(
- EncodeFrameResult *encode_frame_result,
+ EncodeFrameResult *encode_frame_result, const int show_frame_count,
const ENCODE_FRAME_RESULT *encode_frame_info) {
encode_frame_result->coding_data_bit_size =
encode_frame_result->coding_data_byte_size * 8;
@@ -528,6 +555,10 @@ static void update_encode_frame_result(
kMotionVectorSubPixelPrecision);
update_frame_counts(&encode_frame_info->frame_counts,
&encode_frame_result->frame_counts);
+ if (encode_frame_result->frame_type == kFrameTypeAltRef) {
+ update_tpl_stats_info(encode_frame_info->tpl_stats_info, show_frame_count,
+ &encode_frame_result->tpl_stats_info[0]);
+ }
encode_frame_result_update_rq_history(&encode_frame_info->rq_history,
encode_frame_result);
}
@@ -711,6 +742,60 @@ static void UpdateGroupOfPicture(const VP9_COMP *cpi, int start_coding_index,
start_ref_frame_info, group_of_picture);
}
+#define SET_STRUCT_VALUE(config, structure, ret, field) \
+ if (strcmp(config.name, #field) == 0) { \
+ structure->field = atoi(config.value); \
+ ret = 1; \
+ }
+
+static void UpdateEncodeConfig(const EncodeConfig &config,
+ VP9EncoderConfig *oxcf) {
+ int ret = 0;
+ SET_STRUCT_VALUE(config, oxcf, ret, key_freq);
+ SET_STRUCT_VALUE(config, oxcf, ret, two_pass_vbrmin_section);
+ SET_STRUCT_VALUE(config, oxcf, ret, two_pass_vbrmax_section);
+ SET_STRUCT_VALUE(config, oxcf, ret, under_shoot_pct);
+ SET_STRUCT_VALUE(config, oxcf, ret, over_shoot_pct);
+ SET_STRUCT_VALUE(config, oxcf, ret, max_threads);
+ SET_STRUCT_VALUE(config, oxcf, ret, frame_parallel_decoding_mode);
+ SET_STRUCT_VALUE(config, oxcf, ret, tile_columns);
+ SET_STRUCT_VALUE(config, oxcf, ret, arnr_max_frames);
+ SET_STRUCT_VALUE(config, oxcf, ret, arnr_strength);
+ SET_STRUCT_VALUE(config, oxcf, ret, lag_in_frames);
+ SET_STRUCT_VALUE(config, oxcf, ret, encode_breakout);
+ SET_STRUCT_VALUE(config, oxcf, ret, enable_tpl_model);
+ SET_STRUCT_VALUE(config, oxcf, ret, enable_auto_arf);
+ if (strcmp(config.name, "rc_mode") == 0) {
+ int rc_mode = atoi(config.value);
+ if (rc_mode >= VPX_VBR && rc_mode <= VPX_Q) {
+ oxcf->rc_mode = (enum vpx_rc_mode)rc_mode;
+ ret = 1;
+ } else {
+ fprintf(stderr, "Invalid rc_mode value: %d\n", rc_mode);
+ }
+ }
+ SET_STRUCT_VALUE(config, oxcf, ret, cq_level);
+ if (ret == 0) {
+ fprintf(stderr, "Ignored unsupported encode_config %s\n", config.name);
+ }
+}
+
+static VP9EncoderConfig GetEncodeConfig(
+ int frame_width, int frame_height, vpx_rational_t frame_rate,
+ int target_bitrate, int encode_speed, vpx_enc_pass enc_pass,
+ const std::vector<EncodeConfig> &encode_config_list) {
+ VP9EncoderConfig oxcf =
+ vp9_get_encoder_config(frame_width, frame_height, frame_rate,
+ target_bitrate, encode_speed, enc_pass);
+ for (const auto &config : encode_config_list) {
+ UpdateEncodeConfig(config, &oxcf);
+ }
+ if (enc_pass == VPX_RC_FIRST_PASS) {
+ oxcf.lag_in_frames = 0;
+ }
+ return oxcf;
+}
+
SimpleEncode::SimpleEncode(int frame_width, int frame_height,
int frame_rate_num, int frame_rate_den,
int target_bitrate, int num_frames,
@@ -748,12 +833,45 @@ void SimpleEncode::SetEncodeSpeed(int encode_speed) {
encode_speed_ = encode_speed;
}
+StatusCode SimpleEncode::SetEncodeConfig(const char *name, const char *value) {
+ if (name == nullptr || value == nullptr) {
+ fprintf(stderr, "SetEncodeConfig: null pointer, name %p value %p\n", name,
+ value);
+ return StatusError;
+ }
+ EncodeConfig config;
+ snprintf(config.name, ENCODE_CONFIG_BUF_SIZE, "%s", name);
+ snprintf(config.value, ENCODE_CONFIG_BUF_SIZE, "%s", value);
+ impl_ptr_->encode_config_list.push_back(config);
+ return StatusOk;
+}
+
+StatusCode SimpleEncode::DumpEncodeConfigs(int pass, FILE *fp) {
+ if (fp == nullptr) {
+ fprintf(stderr, "DumpEncodeConfigs: null pointer, fp %p\n", fp);
+ return StatusError;
+ }
+ vpx_enc_pass enc_pass;
+ if (pass == 1) {
+ enc_pass = VPX_RC_FIRST_PASS;
+ } else {
+ enc_pass = VPX_RC_LAST_PASS;
+ }
+ const vpx_rational_t frame_rate =
+ make_vpx_rational(frame_rate_num_, frame_rate_den_);
+ const VP9EncoderConfig oxcf =
+ GetEncodeConfig(frame_width_, frame_height_, frame_rate, target_bitrate_,
+ encode_speed_, enc_pass, impl_ptr_->encode_config_list);
+ vp9_dump_encoder_config(&oxcf, fp);
+ return StatusOk;
+}
+
void SimpleEncode::ComputeFirstPassStats() {
vpx_rational_t frame_rate =
make_vpx_rational(frame_rate_num_, frame_rate_den_);
- const VP9EncoderConfig oxcf =
- vp9_get_encoder_config(frame_width_, frame_height_, frame_rate,
- target_bitrate_, encode_speed_, VPX_RC_FIRST_PASS);
+ const VP9EncoderConfig oxcf = GetEncodeConfig(
+ frame_width_, frame_height_, frame_rate, target_bitrate_, encode_speed_,
+ VPX_RC_FIRST_PASS, impl_ptr_->encode_config_list);
VP9_COMP *cpi = init_encoder(&oxcf, impl_ptr_->img_fmt);
struct lookahead_ctx *lookahead = cpi->lookahead;
int i;
@@ -913,9 +1031,10 @@ void SimpleEncode::StartEncode() {
assert(impl_ptr_->first_pass_stats.size() > 0);
vpx_rational_t frame_rate =
make_vpx_rational(frame_rate_num_, frame_rate_den_);
- VP9EncoderConfig oxcf =
- vp9_get_encoder_config(frame_width_, frame_height_, frame_rate,
- target_bitrate_, encode_speed_, VPX_RC_LAST_PASS);
+ VP9EncoderConfig oxcf = GetEncodeConfig(
+ frame_width_, frame_height_, frame_rate, target_bitrate_, encode_speed_,
+ VPX_RC_LAST_PASS, impl_ptr_->encode_config_list);
+
vpx_fixed_buf_t stats;
stats.buf = GetVectorData(impl_ptr_->first_pass_stats);
stats.sz = sizeof(impl_ptr_->first_pass_stats[0]) *
@@ -1083,7 +1202,10 @@ void SimpleEncode::EncodeFrame(EncodeFrameResult *encode_frame_result) {
abort();
}
- update_encode_frame_result(encode_frame_result, &encode_frame_info);
+ const GroupOfPicture group_of_picture = this->ObserveGroupOfPicture();
+ const int show_frame_count = group_of_picture.show_frame_count;
+ update_encode_frame_result(encode_frame_result, show_frame_count,
+ &encode_frame_info);
PostUpdateState(*encode_frame_result);
} else {
// TODO(angiebird): Clean up encode_frame_result.
@@ -1132,9 +1254,9 @@ int SimpleEncode::GetCodingFrameNum() const {
const int allow_alt_ref = 1;
vpx_rational_t frame_rate =
make_vpx_rational(frame_rate_num_, frame_rate_den_);
- const VP9EncoderConfig oxcf =
- vp9_get_encoder_config(frame_width_, frame_height_, frame_rate,
- target_bitrate_, encode_speed_, VPX_RC_LAST_PASS);
+ const VP9EncoderConfig oxcf = GetEncodeConfig(
+ frame_width_, frame_height_, frame_rate, target_bitrate_, encode_speed_,
+ VPX_RC_LAST_PASS, impl_ptr_->encode_config_list);
FRAME_INFO frame_info = vp9_get_frame_info(&oxcf);
FIRST_PASS_INFO first_pass_info;
fps_init_first_pass_info(&first_pass_info,
@@ -1149,9 +1271,9 @@ std::vector<int> SimpleEncode::ComputeKeyFrameMap() const {
assert(impl_ptr_->first_pass_stats.size() == num_frames_ + 1);
vpx_rational_t frame_rate =
make_vpx_rational(frame_rate_num_, frame_rate_den_);
- const VP9EncoderConfig oxcf =
- vp9_get_encoder_config(frame_width_, frame_height_, frame_rate,
- target_bitrate_, encode_speed_, VPX_RC_LAST_PASS);
+ const VP9EncoderConfig oxcf = GetEncodeConfig(
+ frame_width_, frame_height_, frame_rate, target_bitrate_, encode_speed_,
+ VPX_RC_LAST_PASS, impl_ptr_->encode_config_list);
FRAME_INFO frame_info = vp9_get_frame_info(&oxcf);
FIRST_PASS_INFO first_pass_info;
fps_init_first_pass_info(&first_pass_info,
diff --git a/vp9/simple_encode.h b/vp9/simple_encode.h
index 8f0d37439..e3ef3cea9 100644
--- a/vp9/simple_encode.h
+++ b/vp9/simple_encode.h
@@ -19,13 +19,18 @@
namespace vp9 {
+enum StatusCode {
+ StatusOk = 0,
+ StatusError,
+};
+
// TODO(angiebird): Add description for each frame type.
enum FrameType {
kFrameTypeKey = 0,
- kFrameTypeInter,
- kFrameTypeAltRef,
- kFrameTypeOverlay,
- kFrameTypeGolden,
+ kFrameTypeInter = 1,
+ kFrameTypeAltRef = 2,
+ kFrameTypeOverlay = 3,
+ kFrameTypeGolden = 4,
};
// TODO(angiebird): Add description for each reference frame type.
@@ -82,6 +87,24 @@ struct MotionVectorInfo {
double mv_column[2];
};
+// Accumulated tpl stats of all blocks in one frame.
+// For each frame, the tpl stats are computed per 32x32 block.
+struct TplStatsInfo {
+ // Intra complexity: the sum of absolute transform difference (SATD) of
+ // intra predicted residuals.
+ int64_t intra_cost;
+ // Inter complexity: the SATD of inter predicted residuals.
+ int64_t inter_cost;
+ // Motion compensated information flow. It measures how much information
+ // is propagated from the current frame to other frames.
+ int64_t mc_flow;
+ // Motion compensated dependency cost. It equals to its own intra_cost
+ // plus the mc_flow.
+ int64_t mc_dep_cost;
+ // Motion compensated reference cost.
+ int64_t mc_ref_cost;
+};
+
struct RefFrameInfo {
int coding_indexes[kRefFrameTypeMax];
@@ -256,6 +279,18 @@ struct EncodeFrameResult {
// Similar to partition info, all 4x4 blocks inside the same partition block
// share the same motion vector information.
std::vector<MotionVectorInfo> motion_vector_info;
+ // A vector of the tpl stats information.
+ // The tpl stats measure the complexity of a frame, as well as the
+ // informatioin propagated along the motion trajactory between frames, in
+ // the reference frame structure.
+ // The tpl stats could be used as a more accurate spatial and temporal
+ // complexity measure in addition to the first pass stats.
+ // The vector contains tpl stats for all show frames in a GOP.
+ // The tpl stats stored in the vector is according to the encoding order.
+ // For example, suppose there are N show frames for the current GOP.
+ // Then tpl_stats_info[0] stores the information of the first frame to be
+ // encoded for this GOP, i.e, the AltRef frame.
+ std::vector<TplStatsInfo> tpl_stats_info;
ImageBuffer coded_frame;
// recode_count, q_index_history and rate_history are only available when
@@ -322,6 +357,43 @@ class SimpleEncode {
// at the cost of lower compression efficiency.
void SetEncodeSpeed(int encode_speed);
+ // Set encoder config
+ // The following configs in VP9EncoderConfig are allowed to change in this
+ // function. See https://ffmpeg.org/ffmpeg-codecs.html#libvpx for each
+ // config's meaning.
+ // Configs in VP9EncoderConfig: Equivalent configs in ffmpeg:
+ // 1 key_freq -g
+ // 2 two_pass_vbrmin_section -minrate * 100LL / bit_rate
+ // 3 two_pass_vbrmax_section -maxrate * 100LL / bit_rate
+ // 4 under_shoot_pct -undershoot-pct
+ // 5 over_shoot_pct -overshoot-pct
+ // 6 max_threads -threads
+ // 7 frame_parallel_decoding_mode -frame-parallel
+ // 8 tile_column -tile-columns
+ // 9 arnr_max_frames -arnr-maxframes
+ // 10 arnr_strength -arnr-strength
+ // 11 lag_in_frames -rc_lookahead
+ // 12 encode_breakout -static-thresh
+ // 13 enable_tpl_model -enable-tpl
+ // 14 enable_auto_arf -auto-alt-ref
+ // 15 rc_mode
+ // Possible Settings:
+ // 0 - Variable Bit Rate (VPX_VBR) -b:v <bit_rate>
+ // 1 - Constant Bit Rate (VPX_CBR) -b:v <bit_rate> -minrate <bit_rate>
+ // -maxrate <bit_rate>
+ // two_pass_vbrmin_section == 100 i.e. bit_rate == minrate == maxrate
+ // two_pass_vbrmax_section == 100
+ // 2 - Constrained Quality (VPX_CQ) -crf <cq_level> -b:v bit_rate
+ // 3 - Constant Quality (VPX_Q) -crf <cq_level> -b:v 0
+ // See https://trac.ffmpeg.org/wiki/Encode/VP9 for more details.
+ // 16 cq_level see rc_mode for details.
+ StatusCode SetEncodeConfig(const char *name, const char *value);
+
+ // A debug function that dumps configs from VP9EncoderConfig
+ // pass = 1: first pass, pass = 2: second pass
+ // fp: file pointer for dumping config
+ StatusCode DumpEncodeConfigs(int pass, FILE *fp);
+
// Makes encoder compute the first pass stats and store it at
// impl_ptr_->first_pass_stats. key_frame_map_ is also computed based on the
// first pass stats.
@@ -400,9 +472,9 @@ class SimpleEncode {
// Encode a frame with target frame bits usage.
// The encoder will find a quantize index to make the actual frame bits usage
// match the target. EncodeFrameWithTargetFrameBits() will recode the frame
- // update to 7 times to find a q_index to make the actual_frame_bits to
- // satisfy following inequality.
- // |actual_frame_bits - target_frame_bits| * 100 / target_frame_bits
+ // up to 7 times to find a q_index to make the actual_frame_bits satisfy the
+ // following inequality. |actual_frame_bits - target_frame_bits| * 100 /
+ // target_frame_bits
// <= percent_diff.
void EncodeFrameWithTargetFrameBits(EncodeFrameResult *encode_frame_result,
int target_frame_bits,
diff --git a/vp9/vp9_cx_iface.c b/vp9/vp9_cx_iface.c
index 6caa4f739..a73683dfe 100644
--- a/vp9/vp9_cx_iface.c
+++ b/vp9/vp9_cx_iface.c
@@ -13,6 +13,7 @@
#include "./vpx_config.h"
#include "vpx/vpx_encoder.h"
+#include "vpx/vpx_ext_ratectrl.h"
#include "vpx_dsp/psnr.h"
#include "vpx_ports/vpx_once.h"
#include "vpx_ports/static_assert.h"
@@ -633,7 +634,7 @@ static vpx_codec_err_t set_encoder_config(
}
if (get_level_index(oxcf->target_level) >= 0) config_target_level(oxcf);
- // vp9_dump_encoder_config(oxcf);
+ // vp9_dump_encoder_config(oxcf, stderr);
return VPX_CODEC_OK;
}
@@ -1572,6 +1573,7 @@ static vpx_codec_err_t ctrl_set_svc_parameters(vpx_codec_alg_priv_t *ctx,
lc->scaling_factor_num = params->scaling_factor_num[sl];
lc->scaling_factor_den = params->scaling_factor_den[sl];
lc->speed = params->speed_per_layer[sl];
+ lc->loopfilter_ctrl = params->loopfilter_ctrl[sl];
}
}
@@ -1716,6 +1718,48 @@ static vpx_codec_err_t ctrl_set_postencode_drop(vpx_codec_alg_priv_t *ctx,
return VPX_CODEC_OK;
}
+static vpx_codec_err_t ctrl_set_disable_overshoot_maxq_cbr(
+ vpx_codec_alg_priv_t *ctx, va_list args) {
+ VP9_COMP *const cpi = ctx->cpi;
+ const unsigned int data = va_arg(args, unsigned int);
+ cpi->rc.disable_overshoot_maxq_cbr = data;
+ return VPX_CODEC_OK;
+}
+
+static vpx_codec_err_t ctrl_set_disable_loopfilter(vpx_codec_alg_priv_t *ctx,
+ va_list args) {
+ VP9_COMP *const cpi = ctx->cpi;
+ const unsigned int data = va_arg(args, unsigned int);
+ cpi->loopfilter_ctrl = data;
+ return VPX_CODEC_OK;
+}
+
+static vpx_codec_err_t ctrl_set_external_rate_control(vpx_codec_alg_priv_t *ctx,
+ va_list args) {
+ vpx_rc_funcs_t funcs = *CAST(VP9E_SET_EXTERNAL_RATE_CONTROL, args);
+ VP9_COMP *cpi = ctx->cpi;
+ EXT_RATECTRL *ext_ratectrl = &cpi->ext_ratectrl;
+ const VP9EncoderConfig *oxcf = &cpi->oxcf;
+ // TODO(angiebird): Check the possibility of this flag being set at pass == 1
+ if (oxcf->pass == 2) {
+ const FRAME_INFO *frame_info = &cpi->frame_info;
+ vpx_rc_config_t ratectrl_config;
+
+ ratectrl_config.frame_width = frame_info->frame_width;
+ ratectrl_config.frame_height = frame_info->frame_height;
+ ratectrl_config.show_frame_count = cpi->twopass.first_pass_info.num_frames;
+
+ // TODO(angiebird): Double check whether this is the proper way to set up
+ // target_bitrate and frame_rate.
+ ratectrl_config.target_bitrate_kbps = (int)(oxcf->target_bandwidth / 1000);
+ ratectrl_config.frame_rate_num = oxcf->g_timebase.den;
+ ratectrl_config.frame_rate_den = oxcf->g_timebase.num;
+
+ vp9_extrc_create(funcs, ratectrl_config, ext_ratectrl);
+ }
+ return VPX_CODEC_OK;
+}
+
static vpx_codec_ctrl_fn_map_t encoder_ctrl_maps[] = {
{ VP8_COPY_REFERENCE, ctrl_copy_reference },
@@ -1760,12 +1804,15 @@ static vpx_codec_ctrl_fn_map_t encoder_ctrl_maps[] = {
{ VP9E_SET_TARGET_LEVEL, ctrl_set_target_level },
{ VP9E_SET_ROW_MT, ctrl_set_row_mt },
{ VP9E_SET_POSTENCODE_DROP, ctrl_set_postencode_drop },
+ { VP9E_SET_DISABLE_OVERSHOOT_MAXQ_CBR, ctrl_set_disable_overshoot_maxq_cbr },
{ VP9E_ENABLE_MOTION_VECTOR_UNIT_TEST, ctrl_enable_motion_vector_unit_test },
{ VP9E_SET_SVC_INTER_LAYER_PRED, ctrl_set_svc_inter_layer_pred },
{ VP9E_SET_SVC_FRAME_DROP_LAYER, ctrl_set_svc_frame_drop_layer },
{ VP9E_SET_SVC_GF_TEMPORAL_REF, ctrl_set_svc_gf_temporal_ref },
{ VP9E_SET_SVC_SPATIAL_LAYER_SYNC, ctrl_set_svc_spatial_layer_sync },
{ VP9E_SET_DELTA_Q_UV, ctrl_set_delta_q_uv },
+ { VP9E_SET_DISABLE_LOOPFILTER, ctrl_set_disable_loopfilter },
+ { VP9E_SET_EXTERNAL_RATE_CONTROL, ctrl_set_external_rate_control },
// Getters
{ VP8E_GET_LAST_QUANTIZER, ctrl_get_quantizer },
@@ -1952,46 +1999,46 @@ VP9EncoderConfig vp9_get_encoder_config(int frame_width, int frame_height,
return oxcf;
}
-#define DUMP_STRUCT_VALUE(struct, value) \
- printf(#value " %" PRId64 "\n", (int64_t)(struct)->value)
+#define DUMP_STRUCT_VALUE(fp, structure, value) \
+ fprintf(fp, #value " %" PRId64 "\n", (int64_t)(structure)->value)
-void vp9_dump_encoder_config(const VP9EncoderConfig *oxcf) {
- DUMP_STRUCT_VALUE(oxcf, profile);
- DUMP_STRUCT_VALUE(oxcf, bit_depth);
- DUMP_STRUCT_VALUE(oxcf, width);
- DUMP_STRUCT_VALUE(oxcf, height);
- DUMP_STRUCT_VALUE(oxcf, input_bit_depth);
- DUMP_STRUCT_VALUE(oxcf, init_framerate);
+void vp9_dump_encoder_config(const VP9EncoderConfig *oxcf, FILE *fp) {
+ DUMP_STRUCT_VALUE(fp, oxcf, profile);
+ DUMP_STRUCT_VALUE(fp, oxcf, bit_depth);
+ DUMP_STRUCT_VALUE(fp, oxcf, width);
+ DUMP_STRUCT_VALUE(fp, oxcf, height);
+ DUMP_STRUCT_VALUE(fp, oxcf, input_bit_depth);
+ DUMP_STRUCT_VALUE(fp, oxcf, init_framerate);
// TODO(angiebird): dump g_timebase
// TODO(angiebird): dump g_timebase_in_ts
- DUMP_STRUCT_VALUE(oxcf, target_bandwidth);
+ DUMP_STRUCT_VALUE(fp, oxcf, target_bandwidth);
- DUMP_STRUCT_VALUE(oxcf, noise_sensitivity);
- DUMP_STRUCT_VALUE(oxcf, sharpness);
- DUMP_STRUCT_VALUE(oxcf, speed);
- DUMP_STRUCT_VALUE(oxcf, rc_max_intra_bitrate_pct);
- DUMP_STRUCT_VALUE(oxcf, rc_max_inter_bitrate_pct);
- DUMP_STRUCT_VALUE(oxcf, gf_cbr_boost_pct);
+ DUMP_STRUCT_VALUE(fp, oxcf, noise_sensitivity);
+ DUMP_STRUCT_VALUE(fp, oxcf, sharpness);
+ DUMP_STRUCT_VALUE(fp, oxcf, speed);
+ DUMP_STRUCT_VALUE(fp, oxcf, rc_max_intra_bitrate_pct);
+ DUMP_STRUCT_VALUE(fp, oxcf, rc_max_inter_bitrate_pct);
+ DUMP_STRUCT_VALUE(fp, oxcf, gf_cbr_boost_pct);
- DUMP_STRUCT_VALUE(oxcf, mode);
- DUMP_STRUCT_VALUE(oxcf, pass);
+ DUMP_STRUCT_VALUE(fp, oxcf, mode);
+ DUMP_STRUCT_VALUE(fp, oxcf, pass);
// Key Framing Operations
- DUMP_STRUCT_VALUE(oxcf, auto_key);
- DUMP_STRUCT_VALUE(oxcf, key_freq);
+ DUMP_STRUCT_VALUE(fp, oxcf, auto_key);
+ DUMP_STRUCT_VALUE(fp, oxcf, key_freq);
- DUMP_STRUCT_VALUE(oxcf, lag_in_frames);
+ DUMP_STRUCT_VALUE(fp, oxcf, lag_in_frames);
// ----------------------------------------------------------------
// DATARATE CONTROL OPTIONS
// vbr, cbr, constrained quality or constant quality
- DUMP_STRUCT_VALUE(oxcf, rc_mode);
+ DUMP_STRUCT_VALUE(fp, oxcf, rc_mode);
// buffer targeting aggressiveness
- DUMP_STRUCT_VALUE(oxcf, under_shoot_pct);
- DUMP_STRUCT_VALUE(oxcf, over_shoot_pct);
+ DUMP_STRUCT_VALUE(fp, oxcf, under_shoot_pct);
+ DUMP_STRUCT_VALUE(fp, oxcf, over_shoot_pct);
// buffering parameters
// TODO(angiebird): dump tarting_buffer_level_ms
@@ -1999,37 +2046,37 @@ void vp9_dump_encoder_config(const VP9EncoderConfig *oxcf) {
// TODO(angiebird): dump maximum_buffer_size_ms
// Frame drop threshold.
- DUMP_STRUCT_VALUE(oxcf, drop_frames_water_mark);
+ DUMP_STRUCT_VALUE(fp, oxcf, drop_frames_water_mark);
// controlling quality
- DUMP_STRUCT_VALUE(oxcf, fixed_q);
- DUMP_STRUCT_VALUE(oxcf, worst_allowed_q);
- DUMP_STRUCT_VALUE(oxcf, best_allowed_q);
- DUMP_STRUCT_VALUE(oxcf, cq_level);
- DUMP_STRUCT_VALUE(oxcf, aq_mode);
+ DUMP_STRUCT_VALUE(fp, oxcf, fixed_q);
+ DUMP_STRUCT_VALUE(fp, oxcf, worst_allowed_q);
+ DUMP_STRUCT_VALUE(fp, oxcf, best_allowed_q);
+ DUMP_STRUCT_VALUE(fp, oxcf, cq_level);
+ DUMP_STRUCT_VALUE(fp, oxcf, aq_mode);
// Special handling of Adaptive Quantization for AltRef frames
- DUMP_STRUCT_VALUE(oxcf, alt_ref_aq);
+ DUMP_STRUCT_VALUE(fp, oxcf, alt_ref_aq);
// Internal frame size scaling.
- DUMP_STRUCT_VALUE(oxcf, resize_mode);
- DUMP_STRUCT_VALUE(oxcf, scaled_frame_width);
- DUMP_STRUCT_VALUE(oxcf, scaled_frame_height);
+ DUMP_STRUCT_VALUE(fp, oxcf, resize_mode);
+ DUMP_STRUCT_VALUE(fp, oxcf, scaled_frame_width);
+ DUMP_STRUCT_VALUE(fp, oxcf, scaled_frame_height);
// Enable feature to reduce the frame quantization every x frames.
- DUMP_STRUCT_VALUE(oxcf, frame_periodic_boost);
+ DUMP_STRUCT_VALUE(fp, oxcf, frame_periodic_boost);
// two pass datarate control
- DUMP_STRUCT_VALUE(oxcf, two_pass_vbrbias);
- DUMP_STRUCT_VALUE(oxcf, two_pass_vbrmin_section);
- DUMP_STRUCT_VALUE(oxcf, two_pass_vbrmax_section);
- DUMP_STRUCT_VALUE(oxcf, vbr_corpus_complexity);
+ DUMP_STRUCT_VALUE(fp, oxcf, two_pass_vbrbias);
+ DUMP_STRUCT_VALUE(fp, oxcf, two_pass_vbrmin_section);
+ DUMP_STRUCT_VALUE(fp, oxcf, two_pass_vbrmax_section);
+ DUMP_STRUCT_VALUE(fp, oxcf, vbr_corpus_complexity);
// END DATARATE CONTROL OPTIONS
// ----------------------------------------------------------------
// Spatial and temporal scalability.
- DUMP_STRUCT_VALUE(oxcf, ss_number_layers);
- DUMP_STRUCT_VALUE(oxcf, ts_number_layers);
+ DUMP_STRUCT_VALUE(fp, oxcf, ss_number_layers);
+ DUMP_STRUCT_VALUE(fp, oxcf, ts_number_layers);
// Bitrate allocation for spatial layers.
// TODO(angiebird): dump layer_target_bitrate[VPX_MAX_LAYERS]
@@ -2037,25 +2084,25 @@ void vp9_dump_encoder_config(const VP9EncoderConfig *oxcf) {
// TODO(angiebird): dump ss_enable_auto_arf[VPX_SS_MAX_LAYERS]
// TODO(angiebird): dump ts_rate_decimator[VPX_TS_MAX_LAYERS]
- DUMP_STRUCT_VALUE(oxcf, enable_auto_arf);
- DUMP_STRUCT_VALUE(oxcf, encode_breakout);
- DUMP_STRUCT_VALUE(oxcf, error_resilient_mode);
- DUMP_STRUCT_VALUE(oxcf, frame_parallel_decoding_mode);
+ DUMP_STRUCT_VALUE(fp, oxcf, enable_auto_arf);
+ DUMP_STRUCT_VALUE(fp, oxcf, encode_breakout);
+ DUMP_STRUCT_VALUE(fp, oxcf, error_resilient_mode);
+ DUMP_STRUCT_VALUE(fp, oxcf, frame_parallel_decoding_mode);
- DUMP_STRUCT_VALUE(oxcf, arnr_max_frames);
- DUMP_STRUCT_VALUE(oxcf, arnr_strength);
+ DUMP_STRUCT_VALUE(fp, oxcf, arnr_max_frames);
+ DUMP_STRUCT_VALUE(fp, oxcf, arnr_strength);
- DUMP_STRUCT_VALUE(oxcf, min_gf_interval);
- DUMP_STRUCT_VALUE(oxcf, max_gf_interval);
+ DUMP_STRUCT_VALUE(fp, oxcf, min_gf_interval);
+ DUMP_STRUCT_VALUE(fp, oxcf, max_gf_interval);
- DUMP_STRUCT_VALUE(oxcf, tile_columns);
- DUMP_STRUCT_VALUE(oxcf, tile_rows);
+ DUMP_STRUCT_VALUE(fp, oxcf, tile_columns);
+ DUMP_STRUCT_VALUE(fp, oxcf, tile_rows);
- DUMP_STRUCT_VALUE(oxcf, enable_tpl_model);
+ DUMP_STRUCT_VALUE(fp, oxcf, enable_tpl_model);
- DUMP_STRUCT_VALUE(oxcf, max_threads);
+ DUMP_STRUCT_VALUE(fp, oxcf, max_threads);
- DUMP_STRUCT_VALUE(oxcf, target_level);
+ DUMP_STRUCT_VALUE(fp, oxcf, target_level);
// TODO(angiebird): dump two_pass_stats_in
@@ -2063,19 +2110,19 @@ void vp9_dump_encoder_config(const VP9EncoderConfig *oxcf) {
// TODO(angiebird): dump firstpass_mb_stats_in
#endif
- DUMP_STRUCT_VALUE(oxcf, tuning);
- DUMP_STRUCT_VALUE(oxcf, content);
+ DUMP_STRUCT_VALUE(fp, oxcf, tuning);
+ DUMP_STRUCT_VALUE(fp, oxcf, content);
#if CONFIG_VP9_HIGHBITDEPTH
- DUMP_STRUCT_VALUE(oxcf, use_highbitdepth);
+ DUMP_STRUCT_VALUE(fp, oxcf, use_highbitdepth);
#endif
- DUMP_STRUCT_VALUE(oxcf, color_space);
- DUMP_STRUCT_VALUE(oxcf, color_range);
- DUMP_STRUCT_VALUE(oxcf, render_width);
- DUMP_STRUCT_VALUE(oxcf, render_height);
- DUMP_STRUCT_VALUE(oxcf, temporal_layering_mode);
-
- DUMP_STRUCT_VALUE(oxcf, row_mt);
- DUMP_STRUCT_VALUE(oxcf, motion_vector_unit_test);
+ DUMP_STRUCT_VALUE(fp, oxcf, color_space);
+ DUMP_STRUCT_VALUE(fp, oxcf, color_range);
+ DUMP_STRUCT_VALUE(fp, oxcf, render_width);
+ DUMP_STRUCT_VALUE(fp, oxcf, render_height);
+ DUMP_STRUCT_VALUE(fp, oxcf, temporal_layering_mode);
+
+ DUMP_STRUCT_VALUE(fp, oxcf, row_mt);
+ DUMP_STRUCT_VALUE(fp, oxcf, motion_vector_unit_test);
}
FRAME_INFO vp9_get_frame_info(const VP9EncoderConfig *oxcf) {
diff --git a/vp9/vp9_cx_iface.h b/vp9/vp9_cx_iface.h
index 3188575dd..01338adb4 100644
--- a/vp9/vp9_cx_iface.h
+++ b/vp9/vp9_cx_iface.h
@@ -22,7 +22,7 @@ VP9EncoderConfig vp9_get_encoder_config(int frame_width, int frame_height,
int target_bitrate, int encode_speed,
vpx_enc_pass enc_pass);
-void vp9_dump_encoder_config(const VP9EncoderConfig *oxcf);
+void vp9_dump_encoder_config(const VP9EncoderConfig *oxcf, FILE *fp);
FRAME_INFO vp9_get_frame_info(const VP9EncoderConfig *oxcf);
diff --git a/vp9/vp9cx.mk b/vp9/vp9cx.mk
index 666f22882..38e99165a 100644
--- a/vp9/vp9cx.mk
+++ b/vp9/vp9cx.mk
@@ -96,6 +96,8 @@ VP9_CX_SRCS-yes += encoder/vp9_skin_detection.c
VP9_CX_SRCS-yes += encoder/vp9_skin_detection.h
VP9_CX_SRCS-yes += encoder/vp9_noise_estimate.c
VP9_CX_SRCS-yes += encoder/vp9_noise_estimate.h
+VP9_CX_SRCS-yes += encoder/vp9_ext_ratectrl.c
+VP9_CX_SRCS-yes += encoder/vp9_ext_ratectrl.h
ifeq ($(CONFIG_VP9_POSTPROC),yes)
VP9_CX_SRCS-$(CONFIG_INTERNAL_STATS) += common/vp9_postproc.h
VP9_CX_SRCS-$(CONFIG_INTERNAL_STATS) += common/vp9_postproc.c