Commit c2876cf0 authored by Adrian Grange's avatar Adrian Grange

Initial addition of multiple ARF frames

This is work-in-progress, it implements multiple ARF
encoding behind an experimental flag.

It adds the ability to insert multiple ARF frames into a
single ARF group. This patch implements the reordering
of the coded frames, and implements a fixed-length coding
pattern. It applies a fixed quantizer strategy based on
where the frame is in the coding sequence.

Further work to modify the rate control strategy is
ongoing and will be submitted via a set of future patches.

In this first step, each ARF group is recursively
bisected and an ARF frame added at that position in the
sequence. The recursion continues until ARF frames are
within MIN_GF_INTERVAL frames.

The code sits behind the "multiple-arf" experimental
flag ("CONFIG_MULTIPLE_ARF"). The experimental flag
"oneshotq" ("CONFIG_ONESHOTQ") also needs to be enabled
for this patch to work correctly.

Change-Id: Ie473b05ebb43ac473c0cfb659b2b8042823085e2
parent 626d0650
......@@ -253,6 +253,7 @@ EXPERIMENT_LIST="
scatterscan
oneshotq
sbsegment
multiple_arf
"
CONFIG_LIST="
external_build
......
......@@ -2685,7 +2685,7 @@ static void update_alt_ref_frame_stats(VP8_COMP *cpi)
/* Clear the alternate reference update pending flag. */
cpi->source_alt_ref_pending = 0;
/* Set the alternate refernce frame active flag */
/* Set the alternate reference frame active flag */
cpi->source_alt_ref_active = 1;
......@@ -3332,7 +3332,7 @@ static void encode_frame_to_data_rate
else
cpi->common.ref_frame_sign_bias[ALTREF_FRAME] = 0;
/* Check to see if a key frame is signalled
/* Check to see if a key frame is signaled
* For two pass with auto key frame enabled cm->frame_type may already
* be set, but not for one pass.
*/
......
......@@ -18,6 +18,7 @@
#include "vp9/common/vp9_entropymv.h"
#include "vp9/common/vp9_entropy.h"
#include "vp9/common/vp9_entropymode.h"
#if CONFIG_POSTPROC
#include "vp9/common/vp9_postproc.h"
#endif
......@@ -37,8 +38,13 @@ void vp9_initialize_common(void);
#define QINDEX_RANGE (MAXQ + 1)
#if CONFIG_MULTIPLE_ARF
#define NUM_REF_FRAMES 8
#define NUM_REF_FRAMES_LG2 3
#else
#define NUM_REF_FRAMES 3
#define NUM_REF_FRAMES_LG2 2
#endif
#define ALLOWED_REFS_PER_FRAME 3
......@@ -52,6 +58,8 @@ void vp9_initialize_common(void);
#define COMP_PRED_CONTEXTS 2
#define MAX_LAG_BUFFERS 25
typedef struct frame_contexts {
vp9_prob bmode_prob[VP9_NKF_BINTRAMODES - 1];
vp9_prob ymode_prob[VP9_YMODES - 1]; /* interframe intra mode probs */
......
......@@ -249,7 +249,7 @@ int vp9_get_reference_dec(VP9D_PTR ptr, int index, YV12_BUFFER_CONFIG **fb) {
return 0;
}
/* If any buffer updating is signalled it should be done here. */
/* If any buffer updating is signaled it should be done here. */
static void swap_frame_buffers(VP9D_COMP *pbi) {
int ref_index = 0, mask;
......
......@@ -2617,7 +2617,12 @@ void vp9_pack_bitstream(VP9_COMP *cpi, unsigned char *dest,
int refresh_mask;
// Should the GF or ARF be updated using the transmitted frame or buffer
if (cpi->refresh_golden_frame && !cpi->refresh_alt_ref_frame) {
#if CONFIG_MULTIPLE_ARF
if (!cpi->multi_arf_enabled && cpi->refresh_golden_frame &&
!cpi->refresh_alt_ref_frame) {
#else
if (cpi->refresh_golden_frame && !cpi->refresh_alt_ref_frame) {
#endif
/* Preserve the previously existing golden frame and update the frame in
* the alt ref slot instead. This is highly specific to the use of
* alt-ref as a forward reference, and this needs to be generalized as
......@@ -2630,10 +2635,21 @@ void vp9_pack_bitstream(VP9_COMP *cpi, unsigned char *dest,
refresh_mask = (cpi->refresh_last_frame << cpi->lst_fb_idx) |
(cpi->refresh_golden_frame << cpi->alt_fb_idx);
} else {
int arf_idx = cpi->alt_fb_idx;
#if CONFIG_MULTIPLE_ARF
// Determine which ARF buffer to use to encode this ARF frame.
if (cpi->multi_arf_enabled) {
int sn = cpi->sequence_number;
arf_idx = (cpi->frame_coding_order[sn] < 0) ?
cpi->arf_buffer_idx[sn + 1] :
cpi->arf_buffer_idx[sn];
}
#endif
refresh_mask = (cpi->refresh_last_frame << cpi->lst_fb_idx) |
(cpi->refresh_golden_frame << cpi->gld_fb_idx) |
(cpi->refresh_alt_ref_frame << cpi->alt_fb_idx);
(cpi->refresh_alt_ref_frame << arf_idx);
}
vp9_write_literal(&header_bc, refresh_mask, NUM_REF_FRAMES);
vp9_write_literal(&header_bc, cpi->lst_fb_idx, NUM_REF_FRAMES_LG2);
vp9_write_literal(&header_bc, cpi->gld_fb_idx, NUM_REF_FRAMES_LG2);
......
This diff is collapsed.
This diff is collapsed.
......@@ -31,18 +31,22 @@
// Experimental rate control switches
#if CONFIG_ONESHOTQ
#define ONE_SHOT_Q_ESTIMATE 1
#define STRICT_ONE_SHOT_Q 1
#define DISABLE_RC_LONG_TERM_MEM 1
#define ONE_SHOT_Q_ESTIMATE 0
#define STRICT_ONE_SHOT_Q 0
#define DISABLE_RC_LONG_TERM_MEM 0
#endif
// #define SPEEDSTATS 1
#if CONFIG_MULTIPLE_ARF
// Set MIN_GF_INTERVAL to 1 for the full decomposition.
#define MIN_GF_INTERVAL 2
#else
#define MIN_GF_INTERVAL 4
#endif
#define DEFAULT_GF_INTERVAL 7
#define KEY_FRAME_CONTEXT 5
#define MAX_LAG_BUFFERS 25
#if CONFIG_COMP_INTERINTRA_PRED
#define MAX_MODES 54
#else
......@@ -326,7 +330,11 @@ typedef struct VP9_COMP {
struct lookahead_ctx *lookahead;
struct lookahead_entry *source;
#if CONFIG_MULTIPLE_ARF
struct lookahead_entry *alt_ref_source[NUM_REF_FRAMES];
#else
struct lookahead_entry *alt_ref_source;
#endif
YV12_BUFFER_CONFIG *Source;
YV12_BUFFER_CONFIG *un_scaled_source;
......@@ -345,6 +353,9 @@ typedef struct VP9_COMP {
int lst_fb_idx;
int gld_fb_idx;
int alt_fb_idx;
#if CONFIG_MULTIPLE_ARF
int alt_ref_fb_idx[NUM_REF_FRAMES - 3];
#endif
int refresh_last_frame;
int refresh_golden_frame;
int refresh_alt_ref_frame;
......@@ -358,6 +369,12 @@ typedef struct VP9_COMP {
unsigned int key_frame_frequency;
unsigned int this_key_frame_forced;
unsigned int next_key_frame_forced;
#if CONFIG_MULTIPLE_ARF
// Position within a frame coding order (including any additional ARF frames).
unsigned int sequence_number;
// Next frame in naturally occurring order that has not yet been coded.
int next_frame_in_order;
#endif
// Ambient reconstruction err target for force key frames
int ambient_err;
......@@ -396,7 +413,6 @@ typedef struct VP9_COMP {
double gf_rate_correction_factor;
int frames_till_gf_update_due; // Count down till next GF
int current_gf_interval; // GF interval chosen when we coded the last GF
int gf_overspend_bits; // Total bits overspent becasue of GF boost (cumulative)
......@@ -686,6 +702,19 @@ typedef struct VP9_COMP {
int initial_width;
int initial_height;
#if CONFIG_MULTIPLE_ARF
// ARF tracking variables.
int multi_arf_enabled;
unsigned int frame_coding_order_period;
unsigned int new_frame_coding_order_period;
int frame_coding_order[MAX_LAG_BUFFERS * 2];
int arf_buffer_idx[MAX_LAG_BUFFERS * 3 / 2];
int arf_weight[MAX_LAG_BUFFERS];
int arf_buffered;
int this_frame_weight;
int max_arf_level;
#endif
} VP9_COMP;
void vp9_encode_frame(VP9_COMP *cpi);
......
......@@ -112,7 +112,7 @@ int vp9_bits_per_mb(FRAME_TYPE frame_type, int qindex,
const double q = vp9_convert_qindex_to_q(qindex);
int enumerator = frame_type == KEY_FRAME ? 4000000 : 2500000;
// q based adjustment to baseline enumberator
// q based adjustment to baseline enumerator
enumerator += (int)(enumerator * q) >> 12;
return (int)(0.5 + (enumerator * correction_factor / q));
}
......@@ -300,7 +300,7 @@ static void calc_iframe_target_size(VP9_COMP *cpi) {
}
// Do the best we can to define the parameteres for the next GF based
// 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
......@@ -358,16 +358,13 @@ static void calc_pframe_target_size(VP9_COMP *cpi) {
(estimate_bits_at_q(1, q, cpi->common.MBs, 1.0)
* cpi->last_boost) / 100;
}
} else {
// If there is an active ARF at this location use the minimum
// bits on this frame even if it is a contructed arf.
// bits on this frame even if it is a constructed arf.
// The active maximum quantizer insures that an appropriate
// number of bits will be spent if needed for contstructed ARFs.
// number of bits will be spent if needed for constructed ARFs.
cpi->this_frame_target = 0;
}
cpi->current_gf_interval = cpi->frames_till_gf_update_due;
}
}
......
......@@ -486,7 +486,10 @@ static vpx_codec_err_t vp8e_common_init(vpx_codec_ctx_t *ctx,
priv->vp8_cfg.pkt_list = &priv->pkt_list.head;
priv->vp8_cfg.experimental = experimental;
priv->cx_data_sz = priv->cfg.g_w * priv->cfg.g_h * 3 / 2 * 2;
// TODO(agrange) Check the limits set on this buffer, or the check that is
// applied in vp8e_encode.
priv->cx_data_sz = priv->cfg.g_w * priv->cfg.g_h * 3 / 2 * 8;
// priv->cx_data_sz = priv->cfg.g_w * priv->cfg.g_h * 3 / 2 * 2;
if (priv->cx_data_sz < 4096) priv->cx_data_sz = 4096;
......@@ -754,7 +757,7 @@ static vpx_codec_err_t vp8e_encode(vpx_codec_alg_priv_t *ctx,
vpx_codec_cx_pkt_t pkt;
VP9_COMP *cpi = (VP9_COMP *)ctx->cpi;
/* Pack invisible frames with the next visisble frame */
/* Pack invisible frames with the next visible frame */
if (!cpi->common.show_frame) {
if (!ctx->pending_cx_data)
ctx->pending_cx_data = cx_data;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment